This project is read-only.

NeturalMath Quick Start Guide

Part 6: Symbolic Manipulation

This document is not complete, and my represent features which are not yet implemented in the current version of NeturalMath.

Introduction to Symbols

As we have shown in the previous tutorial, defining a variable is not the same as assigning it a value. The definition of a variable is actually an expression, which is defined as a series of symbols and operators. When variables are used in an expression, the expression will examine the definition of the variable when it is evaluated. If the variable is undefined, it will throw an error. When a variable is directly assigned to another variable, the reference to the variable makes up the entire expression, rather than the expression assigned to that variable. This means that if the first variable is assigned a new definition, the second variable will also change. This can result in problems if it is the expression of the first variable which is desired. To avoid this problem, NeturalMath allows for symbolic manipulation. Symbolic manipulation is a kind of meta-programming syntax which allows one to directly modify the definitions of symbols, rather than work through expressions.

Symbols are referenced using symbolic notation. Symbolic notation means that you are referencing the definition of that symbol, rather than a pointer to the symbol. The dollar sign $ is used to represent that you want to reference a variable in symbolic notation. That is $x references the definition of x, rather than x itself. It is by manipulating these symbols that you can tap into the true power of NeturalMath.
The example below helps to illustrate this concept:
x = 3
y = x + 8
z = y

def y // returns x + 8
def z // returns y

print x // returns 3
print y // returns 11
print z // returns 11

// now we change the definition of y
y = x - 5
def y  // returns x - 5
def z  // returns y

print x // returns 3
print y // returns -2
print z // returns -2

// Now we clone the definition of y, instead of referencing it by using symbolic notation
z = $y
y = x * 12

def y  // returns x * 12
def z  // returns x - 5

print x // returns 3
print y // returns 36
print z // returns -2

Cloning Expressions Using Symbols

The example above illustrates how it is possible to clone an expression using symbolic notation. Whenever we prefix a symbol with the dollar sign ($), we indicate that we want to make use of the expression assigned to that symbol rather than the symbol itself. This makes it possible to clone one variable into another, but it also makes it possible to merge complex expressions into a single, easier to understand expression. NeturalMath will attempt to reduce any expression into a simpler form. This means that it will look for cases where variables will cancel each other out or it is possible to otherwise reduce the complexity of the expression. Consider the examples below:
x = a
y = 2 * a
z = x + y

def z

This example will return that z is equal to x+y, not a+(2*a). If we use symbolic notation for x and y, we see a very different output:
x = a
y = 2 * a
z = $x + $y

def z

Here we see that the definition of z is now equal to 3*a. Why is this? First, what happened was that by using symbolic notation, we were able to tell NeturalMath that we wanted to use the expressions for x and y rather than the variables themselves. This meant that we truely were assigning z a value of a+(2*a). Second, as we learned in the previous lesson, NeturalMath will attempt to reduce the complexity of any expression into the simplest possible form. Because 3*a is simpler than a+(2*a), this is what the final value is assigned to. Using this technique, we can combine complex equations into simpler ones and return the reduced output. This is illustrated below:
top = 3 * (x + 2)
bottom = x

total = $top / $bottom
def total // returns 3 + (6 / x)

Referencing a Variable's Value

The examples above showed us how we can reference a variable's expression rather than the variable itself. This is useful when it is desireable to return the value computed from an expression rather than a pointer to the expression itself. In order to reference a variable by value rather than by reference we use the At Symbol (@) before the identifier. This indicates that we want to use the value of the symbol rather than the symbol itself. One simple mnemonic to remember the three ways to reference a variable (or other symbol) are that when we want to use the variable as a pointer, we don't use anything. If we want the expression that the symbol represents, then we call the variable using the Dollar Sign ($). We can think of the Dollar Sign as looking like a big letter "S". We can think, "S is for Symbol." If we want to use the value of a variable, we can use the At Symbol (@) to call it. Think, "At Symbol for the value At the variable". The example below shows a comparison of how each of these three methods work.
x = 3  // x is assigned a value of 3
y = x + 3

refValue = y  // value assigned standard reference
symValue = $y  // value assigned to symbol's expression
atValue = @y  // value assigned to the symbol's computed value

def refValue  // prints y
def symValue  // prints x + 3
def atValue  // prints 6 

Just as symbolic notation ($) indicates that we should use the expression for a variable rather than the variable, value notation (@) indicates that we should use the resulting value of the expression. This would be the same value that would be displayed on screen if the variable was used in a print command. This usage has the same limitations as the print command as well. If the value cannot be determined because it depends on variables which are not yet defined, there is another issue that prevents execution, using value notation will cause NeturalMath to throw an error.
y = x + 3
z = @y  // throws an error because x is not defined.

Last edited Nov 27, 2010 at 4:08 PM by zanethorn, version 3


No comments yet.