# Runtime Any ginger data-structure can be put into a ginger file. The data itself has no executional meaning on its own, but if the data is properly formed it can be parsed by the ginger interpreter and a thread of execution can be started. For example, if I put the following in a file called `test.gng`: ``` (1 2 3) ``` It doesn't have any meaning, it's just a list. However, if you put the following: ``` (add 1 2 3) ``` and run `ginger test.gng` then a program can be interpreted from the given data. This file describes how given data can be formed into a valid program. ## Eval Ginger evaluation is done the same was as other lisp languages: the first item in a list is the function name, the rest of the items in the list are arguments to the function. In the example above, `add` is the function name, and `1`, `2`, and `3` are arguments to the function. Arguments to a function can be functions to be eval'd themselves. An equivalent to the example above would have been: ``` (add 1 2 (add 1 2)) ``` ## Doing multiple things It's not very useful to only be able to do one thing. A vector of lists is interpreted into sequentially eval'ing each item in the vector. For (a trivial) example: ``` [ (add 1 2) (sub 4 (add 1 2)) (mul 8 0) ] ``` ## Variables/Scope The above example does a few things, but it repeats itself in the second part (with the `sub`). If we could save the result of the addition to a variable that would be awesomesauce. The `=` function does this! It makes it so that the first argument is equivalent to the evaluation of the second argument. Variables' can not be re-defined to be another value, and their first letters must be upper-case, thisis how they're differentiated from raw string literals.The above could be re-written as: ``` [ (= AdditionResult (add 1 2)) (sub 4 AdditionResult) (mul 8 0) ] ``` In the above example `AdditionResult` is a valid variable inside of the vector that contains its declaration, and any vectors contained within that vector. For example: ``` [ (= AdditionResult (add 1 2)) [ (sub 4 AdditionResult) ;This works (mul 8 0) ] ] [ (add 4 AdditionResult) ] ;This does not work! ``` ## Literals We've determined that a list is interpreted as a function/arguments set, and an upper-case string is interpreted as a variable name which will be de-referenced. What if we want to actually use these structures without eval'ing them? For these cases we have the literal function `l`: ``` [ (concat (l (1 2 3)) (l (4 5 6))) ; => (1 2 3 4 5 6) (println (l "I start with a capital letter and I DONT CARE!!!")) ] ``` ## Functions ### Anonymous Anonymous functions are declared using the `fn` function. The first argument is a vector of argument names (remember, all upper-case!) and the second is a list/vector to be eval'd. Examples: ``` [ (= Add3 (fn [Num] (add Num 3))) (Add3 4) ; => 7 (= Add3Sub1 (fn [Num] [ (= Added (add Num 3)) (sub Added 1) ])) (Add3Sub1 4) ] ; => 6 ``` `fn` returns a function, which can be passed around and assigned like any other value. In the above examples the functions are assigned to the `Add3` and `Add3Sub1` variables. Functions can also be passed into other functions as arguments: ``` ;DoTwice takes a function Fun and a number Num. it will call Fun twice on Num and return the result. [ (= DoTwice (fn [Fun Num] (Fun (Fun Num)))) (DoTwice (fn [Num] (add Num 1)) 3) ] ; => 5 ``` ### Defined Defined functions attach the function definition to a string literal (lower-case) in the current scope. They are useful as they support more features then an anonymous function, such as inline documentation. These extra features will be documented elsewhere. To create a defined function use the `dfn` function: ``` [ (dfn add-four-sub-three [Num] [ (= A (add Num 4)) (sub A 3) ]) (add-four-sub-three 4) ] ; => 5 ``` ## Namespaces Namespaces give names to defined scopes which can be referenced from elsewhere. The best way to show this is with an example: ``` [ (ns circle [ (= Pi 3.14) (dfn area [R] (mul R R Pi)) ]) (circle/area 5) ; => 78.5 ] ``` ### Embedded namespaces Namespaces can be embedded into a tree-like structure: ``` [ (ns math [ (= Pi 3.14) (ns circle (dfn area [R] (mul R R Pi))) (ns square (dfn area [R] (mul R R))) ]) (math.circle/area 5) ; => 78.5 (math.square/area 5) ; => 25 ] ``` In the above example `circle` and `square` are both sub-namespaces of the `math` namespace. In `circle` the variable `Pi` is referenced. Ginger will look in the current scope for that variable, and when it's not found travel up the scope tree. `Pi` is defined in `math`'s scope, so that value is used. ### Namespace resolution Let's do a more complicated example to show how namespace resolution works: ``` [ (ns tlns [ (ns alpha (= A "The first letter in the alphabet")) (ns facts (= BestLetter alpha/A)) ]) (println tlns.facts/BestLetter) ] ``` In the above example `BestLetter` is defined inside `facts` to be the variable `A` which exists in the namespace `alpha`. To resolve this variable ginger first looks inside `facts`'s scope for a namespace called `alpha`, doesn't find it, then moves up to `tlns`'s scope, which does contain a namespace called `alpha`. Similaraly, to resolve `tlns.facts/BestLetter` ginger first looks in that statements current scope for a namespace called `tlns`, which it finds, and looks in there for `facts`, etc... ### Variable namespaces A namespace is nothing more than a string literal. If a variable is used instead ginger will resolve the variable before trying to resolve the namespace. ``` [ (ns tlns [ (ns alpha (= A "The first letter in the alphabet"))]) (= NS1 tlns) (= NS2 alpha) (= NS NS1.NS2) (println NS/A) ; This would print the message defined above ] ```