Wednesday, May 30, 2012

Defining variables and variable scopes in Fuzuli



Fuzuli has a basic variable scoping strategy and it is easy to understand. Many Algol family languages support variable types, variable defining, initial value setting and updating values. Internally, everything in Fuzuli is a Token. A Token is a C++ object. It can hold an INTEGER, a FLOAT, a STRING, a LIST of all types and a COBJECT. Variables are basically type of an INTEGER, a FLOAT or a STRING. A Fuzuli LIST is a vector or array of those kind of objects. A LIST may be a member of an other LIST. So, objects in Fuzuli can be recursively deep. A COBJECT is a (void*) pointer and can be anything. This type of variable is used for external function calls, usually from C++ or C libraries such as Math, IO and MySQL. Integration of COBJECT types expands the universe that Fuzuli can access. However, a standard user does not need this kind of object because Nafile (nfl) packages wrap those external function calls.

We use (let) expression to set value of a variable in Fuzuli:


# Value of a is set to 10
(let a 10)

# a is now 20
(let a 20)

# a is now a string
(let a "Hello!")

# a is now a double precision number
(let a 3.141592)


(block) expression defines a block in which variables are locally scoped. If a variable defined in a higher scope, it is current in the child scope. In other terms, if a variable set in a deeper scope but it is first defined in the higher scope, the first defined variable is current. Have a look at the example below:


# Value of a is set to 10
# a is defined in higher level
(let a 10)

# this block defines a deeper (local) scope
(block
  (let a 20)
)

# out of the block, a is 20 because global a is accessed from the local scope
(print a)
# the answer is 20


However, one can want to define a local variable with same name of the higher scoped variable. For this, (def) expressions can be used. Look at the example below:

# Defined in an higher scope
(let a 10)

# deeper scope
(block
  (def a NULL)
  (let a 7)
)

# we are in higher scope again
(print a)
# the answer is 10.


So, in Fuzuli, a user does not need to define variables if they want to give a reference them. Look at the (for) expression given below:

(let i 5)

(for (let i 0) (< i 10) (inc i)
    (block
        (print "i is " i "\n")
    )
)

(print "Finally, i is " i  "\n")


The output is

i is 0
i is 1
i is 2
i is 3
i is 4
i is 5
i is 6
i is 7
i is 8
i is 9
Finally, i is 10


because, i is first defined in a higher level of scope. If i is not defined before the (for) expression, the code should be like this

(for (let i 0) (< i 10) (inc i)
    (block
        (print "i is " i "\n")
    )
)

(print "Finally, i is " i  "\n")


and the output is

i is 0
i is 1
i is 2
i is 3
i is 4
i is 5
i is 6
i is 7
i is 8
i is 9
Finally, i is NULL


because i is defined locally and it is invisible in the higher scope. Strategy of variable scoping in function calls is an other special issue in Fuzuli Suppose that we have an (sum) function defined as follows:

(function sum (params x)
    (block
        (def t FLOAT)(def i FLOAT)
        (let t 0.0)
        (foreach i in x
            (let t (+ t i))
        )
        (return t)
    )
)


In the example above, the (sum) function takes a list 'x' as parameter and returns the sum of elements of this list. The variable 't' is defined and set in the function body. This is unnecessary if we don't use a variable with name 't' in the higher level of scopes. For convenience and security, defining all local function variables before they were used is a good habit. For the rest of the example, the sum function can be called using

(let mylist (list 1 2 3 4 5))
(let result (sum mylist))
(print result "\n")
and gives the result of 15. Hope you have fun !

No comments:

Post a Comment

Thanks