aboutsummaryrefslogtreecommitdiff
path: root/blog/stem.org
diff options
context:
space:
mode:
Diffstat (limited to 'blog/stem.org')
-rw-r--r--blog/stem.org66
1 files changed, 54 insertions, 12 deletions
diff --git a/blog/stem.org b/blog/stem.org
index 451df04..adec880 100644
--- a/blog/stem.org
+++ b/blog/stem.org
@@ -68,6 +68,8 @@ doesn't matter. Just know that it runs stem code interactively.
A basic word that prints out the top thing on the stack and removes it is simply a period:
#+begin_src stem :exports both
+# this is a comment, used to explain code but doesn't affect the outcome at all.
+# comments start with a '#'.
"hello world\n" .
#+end_src
@@ -141,19 +143,25 @@ and logical operations:
3 4 > .
3 4 <= .
3 4 >= .
-1 0 and
-1 1 and
-0 0 or
-0 1 or
+1 1 and .
+1 0 and .
+0 1 or .
+0 0 or .
#+end_src
#+RESULTS:
-: 1
-: 0
-: 1
-: 0
-: 1
-: 0
+#+begin_example
+1
+0
+1
+0
+1
+0
+1
+0
+1
+0
+#+end_example
Which compare the first number to the second number with a certain operation like "greater than or equals to". The result is a zero or one, indicating
that the statement is either /true/ or /false/, with 1 being true. With these statements, you can make decisions:
@@ -258,14 +266,17 @@ how to define words in terms of other words, or so-called /compound words/.
** Compound Words
Compound words, or words made up of other words (and literals), are created with yet /another/ word, ~def~. ~def~ takes an undefined word
(all undefined words are just put on the stack) and a quote, and then from there on the word in question is defined as that quote, where whenever
-stem sees that word in the future, it immediately ~eval~'s that quote.
+stem sees that word in the future, it immediately ~eval~'s that quote. ~undef~ undefines a word, which is self explanatory.
#+begin_src stem :exports both
hello [ "hello world\n" . ] def
hello
+\hello undef
+hello .
#+end_src
#+RESULTS:
: hello world
+: W: hello
In order to put words on the stack instead of calling them, just escape them:
#+begin_src stem :exports both
@@ -317,4 +328,35 @@ dupt [ [ [ dup ] dip ] dip ] def
which duplicates the second and third value on the stack respectively. However, we might want to define ~dupn~ for any n, which takes in an integer
and computes ~dup~ ~n~ values down. We can do that with metaprogramming, or less abstractly, we can do it by repeatedly putting quotes inside quotes,
-and then we can ~eval~ the resultant quote.
+and then we can ~eval~ the resultant quote. Here is the code that programs ~dipn~ in its entirety, without any sugarcoating:
+#+begin_src stem
+# dsc simply discards the top object on the stack
+dsc2 [ dsc dsc ] def
+dupd [ [ dup ] dip ] def
+over [ dupd swap ] def
+dup2 [ over over ] def
+dip2 [ swap [ dip ] dip ] def
+loop [ dup2 [ swap [ ] if ] dip2 dup [ 1 - loop ] [ dsc2 ] if ] def
+dipn [ [ [ dip ] curry ] swap loop eval ] def
+dupn [ [ dup ] swap dipn ] def
+
+# this is the code that does stuff
+1 2 3 4 5 6 7 8 3 dupn ?
+#+end_src
+
+#+RESULTS:
+: 1
+: 2
+: 3
+: 4
+: 5
+: 5
+: 6
+: 7
+: 8
+
+As you can see, in the early days of programming in this language, you must use quite a lot of words in order to talk about even basic concepts. As
+the language evolves, however, it becomes ever more easy to "talk" about abstract subjects in it. What this piece of code does is it adds ~dip~ to the
+right of the previous quote, nesting quotes like russian dolls over and over again until it becomes suitable to call ~eval~. Thus, we have built up
+a piece of code in the language and then automatically executed it! Note that because ~def~ is also a word, you can automatically define words as well,
+which is a powerful concept.