aboutsummaryrefslogtreecommitdiffstats
path: root/docs/guide/scopes.md
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-05-17 15:41:56 +0000
committers-ol <s+removethis@s-ol.nu>2025-03-02 14:24:49 +0000
commit406da94f13f47a9c7aef6b9c11cfe057772630cf (patch)
treedd98e12eddd421e2883c90239cb10225bb75b07e /docs/guide/scopes.md
parentbuiltin/trae: print literals literally (diff)
downloadalive-406da94f13f47a9c7aef6b9c11cfe057772630cf.tar.gz
alive-406da94f13f47a9c7aef6b9c11cfe057772630cf.zip
split guide into multiple pages
Diffstat (limited to 'docs/guide/scopes.md')
-rw-r--r--docs/guide/scopes.md82
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.