docs/learn-definitions.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
----- content-type: "page" title: "Learn: Definitions" ----- {@ _defs_.md || 0 @} Being a concatenative language, {{m}} does not really need named parameters or variables: symbols just pop elements off the main stack in order, and that's normally enough. There is however one small problem with the traditional concatenative paradigm; consider the following program for example: dup () cons "Compiling on $#..." swap interpolate puts pop () cons "nim --os:$# c test.nim" swap interpolate run This program takes an operating system indetifier (windows, linux, osx) and attempts to build the file **test.nim** for it. Sure, it is remarkable that no variables are needed for such a program, but it is not very readable: because no variables are used, it is often necessary to make copies of elements and push them to the end of the stack -- that's what the {#link-symbol||dup#} and {#link-symbol||swap#} are used for. The good news is that you can use the {#link-symbol||let#} symbol to define new symbols, and symbols can also be set to literals of course. Consider the following program: (os) let "Compiling on $#..." (os) interpolate puts pop "nim --os:$# c test.nim" (os) interpolate run In this case, the first element on the stack is saved to a symbol called **os**, which is then used whenever needed in the rest of the program. ## Lexical scoping and binding mn, like many other programming languages, uses [lexical scoping](https://en.wikipedia.org/wiki/Scope_\(computer_science\)#Lexical_scope_vs._dynamic_scope) to resolve symbols. Consider the following program: 4 (a) let ( a 3 + (a) let ( a 1 + (a) let (a dup * (a) let) dequote ) dequote ) dequote ...What is the value of the symbol `a` after executing it? Simple: `4`. Every quotation defines its own scope, and in each scope, a new variable called `a` is defined. In the innermost scope containing the quotation `(a dup * (a) let)` the value of `a` is set to `64`, but this value is not propagated to the outer scopes. Note also that the value of `a` in the innermost scope is first retrieved from the outer scope (8). If we want to change the value of the original `a` symbol defined in the outermost scope, we have to use the {#link-symbol||bind#}, so that the program becomes the following: 4 (a) let ;First definition of the symbol a ( a 3 + (a) bind ;The value of a is updated to 7. ( a 1 + (a) bind ;The value of a is updated to 8 (a dup * (a) bind) dequote ;The value of a is now 64 ) dequote ) dequote |