diff options
Diffstat (limited to 'blog/stem.org')
-rw-r--r-- | blog/stem.org | 66 |
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. |