diff options
| author | s-ol <s-ol@users.noreply.github.com> | 2020-05-17 15:41:56 +0000 |
|---|---|---|
| committer | s-ol <s+removethis@s-ol.nu> | 2025-03-02 14:24:49 +0000 |
| commit | 406da94f13f47a9c7aef6b9c11cfe057772630cf (patch) | |
| tree | dd98e12eddd421e2883c90239cb10225bb75b07e /docs/guide/scopes.md | |
| parent | builtin/trae: print literals literally (diff) | |
| download | alive-406da94f13f47a9c7aef6b9c11cfe057772630cf.tar.gz alive-406da94f13f47a9c7aef6b9c11cfe057772630cf.zip | |
split guide into multiple pages
Diffstat (limited to 'docs/guide/scopes.md')
| -rw-r--r-- | docs/guide/scopes.md | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/docs/guide/scopes.md b/docs/guide/scopes.md new file mode 100644 index 0000000..87568ef --- /dev/null +++ b/docs/guide/scopes.md @@ -0,0 +1,82 @@ +Both [import][] and [import*][] are actually shorthands and what they +accomplish can be done using the lower-level builtins [def][], [use][] and +[require][]. Here is how you could replace [import][]: + + #(with import:) + (import math) + (trace (math/+ 1 2)) + + #(with def and require:) + (def math (require "math")) + (trace (math/+ 1 2)) + +[require][] returns a *scope*, which is defined as the symbol `math`. +Then `math/+` is resolved by looking for `+` in this nested scope. Note that +the symbol that the scope is defined as and the name of the module that is +loaded do not have to be the same, you could call the alias whatever you want: + + #(this not possible with import!) + (def fancy-math (require "math")) + (trace (fancy-math/+ 1 2)) + +Most of the time the name of the module makes a handy prefix already, so +[import][] can be used to save a bit of typing and make the code look a bit +cleaner. [import*][], on the other hand, defines every symbol from the imported +module individually. It could be implemented with [use][] like this: + + (use (require "math")) + (trace (+ 1 2)) + +[use][] copies all symbol definitions from the scope it is passed to the +current scope. + +Note that [import][], [import*][], [def][], and [use][] all can take multiple +arguments: + + #(using the shorthands:) + (import* math logic) + (import midi osc) + + #(using require, use and def:) + (use (require "math") (require "logic")) + (def midi (require "midi") + osc (require "osc")) + +It is common to have an [import][] and [import*][] expression at the top of an +`alv` program to load all of the modules that will be used later, but the +modules don't necessarily have to be loaded at the very beginning, as long as +all symbols are defined before they are being used. + +## nested scopes +Once a symbol is defined, it cannot be changed or removed: + + (def a 3) + (def a 4) #(error!) + +It is, however, possible to 'shadow' a symbol by re-defining it in a nested +scope: So far, all symbols we have defined - using `def`, [import][] and +[import*][] - have been defined in the *global scope*, the scope that is active +in the whole `alv` program. The [do][] builtin can be used to create a new +scope and evaluate some expressions in it: + + (import string) + + (def a 1 + b 2) + + (trace (.. "first: " a " " b)) + (do + (def a 3) + (trace (.. "second: " a " " b)) + (trace (.. "third: " a " " b)) + +This example prints the following: + + trace (.. "first: " a " " b): <Value str: first: 1 2> + trace (.. "second: " a " " b): <Value str: second: 3 2> + trace (.. "third: " a " " b): <Value str: third: 1 2> + +As you can see, within a nested scope it is possible to overwrite a definition +from the parent scope. Symbols that are not explicitly redefined in a nested +scope keep their values, and changes in the nested scope do not impact the +parent scope. |
