The Science of Programming/The Simplest Things
If you have studied Chapter 4 of CME, you will have learned the power rule for differentiating simple polynomial functions, known as terms. A term has the form:
with a being known as the coefficient of the term and n being known as the exponent of the term.
Here is the power rule for terms:
As example, consider the polynomial:
If the power rule is correct, then the derivative should be:
Let's test. We start out by defining a function to represent the polynomial:
function y(x) { 2 * (x ^ 3); }
As before, the dependent variable becomes the name of the function and the independent variable becomes the formal parameter.
Before we continue, now would be a good time to learn about using Sway with files, since typing into the interpreter can be rather painful for function definitions.
Thus for the rest of this book, even though interactions with the interpreter are shown, you should be storing Sway programs in files and running Sway programs from files.
The derivative, or can be written as this function:
function dy/dx(x) { 6 * (x ^ 2); }
Is there any way to test whether or not the power rule is correct? Recall our revised ratio function from the previous chapter:
function ratio(x,dx,y) { var dy = y(x + dx) - y(x); dy / dx; }
As you should remember, the ratio it computes is an approximation for the derivative at a given x. Note that we've changed the names of the formal parameters, w to x, dw to dx, and h to y, to reflect the fact that we are working with polynomials now.[1]
We believe that ratio (for small dx) produces a number that should be close to what the function dy/dx produces.
Let's define a testing function:
function test(x) { var dx = 0.000001; println("for x = ",x); inspect(ratio(x,dx,y)); inspect(dy/dx(x)); println(); }
Given a value for x, the test function will print out the two results. Time for some nomenclature. When we use our ratio function, we are finding the derivative numerically. That is to say, we use a small number for dx, find the resulting dy, and then compute the ratio . On the other hand, using the power rule (as embodied in the function dy/dx), we find the derivative symbolically since we never actually compute an actual ratio.
sway> test(10); for x = 10 ratio(x,dx,y) is 600.00005965 dy/dx(x) is 600 sway> test(20); for x = 20 ratio(x,dx,y) is 2400.0001231 dy/dx(x) is 2400 sway> test(30); for x = 30 ratio(x,dx,y) is 5400.0001837 dy/dx(x) is 5400
For this test at least, we see that there is good agreement between our numeric and symbolic solutions.
Clearly, though, the symbolic solution is preferred because:
- it is exact
- it is easier to compute
You may be asking yourself, can we write a program to find a derivative symbolically?
A Shortcoming to Our Approach
[edit | edit source]It certainly would be nice if we could use the symbolic approach to finding derivatives instead of our numeric approach using ratios. The problem is that our function representing a term:
function y(x) { 2 * (x ^ 3); }
has the coefficient 2 and the exponent 3 hard-wired. If we are given such a function but aren't privy to the internal details (such as the value of the hard-wired exponent), we cannot create the derivative function since we need to know the value of the exponent to do so and have no way to get at it. We need to contrive a way to retrieve the exponent from the function so we can use it to construct the derivative function.
The next section is to give you an exposure to one approach for extracting the components of a function. The approach uses objects.
If you don't know what an object is or how to create one in Sway, please read about using objects in The Sway Reference Manual now.
OK, now that you are familiar with objects, we can begin to use objects to write a program that finds a derivative symbolically.
Polynomial Objects and the Power Rule
[edit | edit source]Instead of using a function to represent the polynomial y, we are going to use an object instead. From studying the reference manual, you know that an object is simply an environment and an environment is simply a table of variables and their values. You also know that you use a function to create an object and that a function that creates an object is conventionally known as a constructor. Finally, you know that to define a constructor function, you have that function return the predefined variable this.
Here's a constructor for a simple polynomial object. We name the constructor term:
function term(a,n) { function value(x) { a * (x ^ n); } this; }
Note that the constructor includes an internal function for computing the value of y given an x, just as before. We call that function by using the dot operator.
sway> var y = term(2,3); OBJECT: <OBJECT 1671> sway> y . value(4); INTEGER: 128 sway> y . value(5); INTEGER: 250
Indeed, is truly 128 and is truly 250.
Now comes the good part! Storing a polynomial term as an object rather than a function allows us to extract the coefficient a and the exponent n:
sway> y . a; INTEGER: 2; sway> y . n; INTEGER: 3;
We can even pretty print the object y to see all its fields:
sway> pp(y); <OBJECT 2561>: context: <OBJECT 749> dynamicContext: <OBJECT 749> callDepth: 1 constructor: <function term(a,n)> this: <OBJECT 2561> value: <function value(x)> a: 2 n: 3 OBJECT: <OBJECT 2561>
We see, among other fields, the correct values for a and n. Later on, you will understand the meaning and purpose of the predefined fields: context, dynamicContext, and constructor. The this field you already know.
We want access to a and n because the power rule needs them to compute the derivative polynomial. Now we can write an expression that allows us to compute the derivative:
sway> var coeff = y . a; sway> var exp = y . n;
sway> var z = term(coeff * exp,exp - 1); OBJECT: <OBJECT 2783>
sway> z . a; INTEGER: 6
sway> z . n; INTEGER: 2
sway> z . value(4) INTEGER: 96
Of course, we could write a function to do this task for us:
function powerRule(t) { var coeff = t . a; var exp = t . n; term(coeff * exp,exp - 1); }
Note that the powerRule function takes a term object as an argument and returns a new term object that represents the derivative. This is because the new term has a coefficient of a * n and an exponent of n - 1, just like the power rule dictates. Let's check and make sure our power rule works as intended:
sway> var y = term(2,3); sway> var z = powerRule(y); sway> y . value(4); INTEGER: 128 sway> z . value(4); INTEGER: 96
Indeed it does!
Moreover, pretty printing z shows us the correct values for a and n:
sway> pp(dy/dx); <OBJECT 2922>: context: <OBJECT 749> dynamicContext: <OBJECT 2808> callDepth: 2 constructor: <function term(a,n)> this: <OBJECT 2922> value: <function value(x)> a: 6 n: 2 OBJECT: <OBJECT 2922>
You may not have noticed it, but we have a little lack of symmetry. While the term object has an internal function for computing its value, we use an external function, powerRule to compute its derivative. When we program using objects, we use internal functions when possible. So let's rewrite the term function so that it can compute its own derivative:
function term(a,n) { function value(x) { a * (x ^ n); } function diff() { term(a * n,n - 1); } this; }
We name this new internal function, diff, to indicate taking the differential of our object. Note how we have dispensed with the variables coeff and exp inside the diff function and just used a and n directly.
Finally, we add a third internal function to term. This one is used to visualize our object in a more concise way than using the pp function. By convention, we will call this function toString:
function term(a,n) { function value(x) { a * (x ^ n); } function diff() { term(a * n,n - 1); } function toString() { string(a) + "x^" + string(n); } this; }
The toString function converts both the coefficient and the exponent to strings and then concatenates those strings together to form a string representation of the term:
sway> y = term(2,3); sway> z = y . diff();
sway> y . toString() STRING: "2x^3"
sway> x . toString() STRING: "6x^2"
Notice how much easier it is to pick out the coefficient and the exponent of a term by using the toString function. Another way to formulate the toString function takes advantage of the fact that if you add a string and a number (with the string on the left hand side of the plus sign, the number is automatically converted to a string. That, with the fact that Sway combines mathematical operators from left-to-right, lets us remove the string conversion of n:
function toString() { string(a) + "x^" + n; }
If we use an empty string to start the expression, we can remove the first string conversion as well:
function toString() { "" + a + "x^" + n; }
A Whole System of Objects
[edit | edit source]From here on out, we are going to develop a system for finding the derivative (and eventually, the integral) of many kinds of mathematical objects (limited only by our imagination and attention span). Each object in our system will do (at least) three things. The first is to compute its value at a given spot. The second is to compute its derivative (and eventually, its integral). The third is to compute its visualization. So all our mathematical objects will have value, diff, and toString internal functions or methods. [2]
Even the simplest real-world mathematical objects such as numbers and variables will need to be re-created as Sway objects. That way, we can always take the derivative of an object without having to ask first if taking the derivative makes sense.
Questions
[edit | edit source]All formulas are written using Grammar School Precedence.
1. Why does the Sway implementation of have parentheses: 2 * (x ^ 3)?
2. Using the powerRule function, can you take the derivative of a derivative? Explain.
3. Write a function that uses the power rule function to answer the following questions on p. 58 of Thompson: 1, 2, 4, 6, 7. Name your function p58. Your function should calculate, then print the answers to the questions.
4. Using pencil and paper, work exercises 3, 8, 9, and 10 on p. 58 of Thompson.
Footnotes
[edit | edit source]- ↑ In general, it does not matter what names are used for the formal parameters, so we could have left the ratio function untouched and it would still work exactly the same.
- ↑ In the world of object-oriented programming (which is another way of saying programming with objects), these internal functions are called methods. We will use the term method from now one. Just remember, a method is simply an internal function.