Update Square_Spiral notebook to use Joy kernel
https://todo.sr.ht/~sforman/thun-der/19
This commit is contained in:
parent
dafdb9d620
commit
d420f572df
28660
docs/Square_Spiral.html
28660
docs/Square_Spiral.html
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -1,7 +1,3 @@
|
|||
```python
|
||||
from notebook_preamble import J, V, define
|
||||
```
|
||||
|
||||
# Square Spiral Example Joy Code
|
||||
|
||||
|
||||
|
|
@ -65,28 +61,177 @@ with `<=`:
|
|||
|
||||
[abs] ii <=
|
||||
|
||||
|
||||
```Joy
|
||||
[_p [abs] ii <=] inscribe
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
```Joy
|
||||
clear 23 -18
|
||||
```
|
||||
|
||||
23 -18
|
||||
|
||||
|
||||
```Joy
|
||||
[_p] trace
|
||||
```
|
||||
|
||||
23 -18 • _p
|
||||
23 -18 • [abs] ii <=
|
||||
23 -18 [abs] • ii <=
|
||||
23 • abs -18 abs <=
|
||||
23 • -18 abs <=
|
||||
23 -18 • abs <=
|
||||
23 18 • <=
|
||||
false •
|
||||
|
||||
false
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Short-Circuiting Boolean Combinators
|
||||
|
||||
I've defined two short-circuiting Boolean combinators `&&` and `||` that
|
||||
each accept two quoted predicate programs, run the first, and
|
||||
conditionally run the second only if required (to compute the final
|
||||
Boolean value). They run their predicate arguments `nullary`.
|
||||
|
||||
|
||||
```python
|
||||
define('&& [nullary] cons [nullary [0]] dip branch')
|
||||
define('|| [nullary] cons [nullary] dip [1] branch')
|
||||
```Joy
|
||||
[&& [nullary] cons [nullary [false]] dip branch] inscribe
|
||||
[|| [nullary] cons [nullary] dip [true] branch] inscribe
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
[true] [false] &&
|
||||
```
|
||||
|
||||
false
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
[false] [true] &&
|
||||
```
|
||||
|
||||
false
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
[true] [false] ||
|
||||
```
|
||||
|
||||
true
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
[false] [true] ||
|
||||
```
|
||||
|
||||
true
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Translating the Conditionals
|
||||
|
||||
Given those, we can define `x != y || x >= 0` as:
|
||||
|
||||
[<>] [pop 0 >=] ||
|
||||
_a == [!=] [pop 0 >=] ||
|
||||
|
||||
|
||||
```Joy
|
||||
[_a [!=] [pop 0 >=] ||] inscribe
|
||||
```
|
||||
|
||||
|
||||
|
||||
And `(abs(x) <= abs(y) && (x != y || x >= 0))` as:
|
||||
|
||||
[[abs] ii <=] [[<>] [pop 0 >=] ||] &&
|
||||
_b == [_p] [_a] &&
|
||||
|
||||
|
||||
```Joy
|
||||
[_b [_p] [_a] &&] inscribe
|
||||
```
|
||||
|
||||
|
||||
|
||||
It's a little rough, but, as I say, with a little familiarity it becomes
|
||||
legible.
|
||||
|
||||
|
||||
```Joy
|
||||
clear 23 -18
|
||||
```
|
||||
|
||||
23 -18
|
||||
|
||||
|
||||
```Joy
|
||||
[_b] trace
|
||||
```
|
||||
|
||||
23 -18 • _b
|
||||
23 -18 • [_p] [_a] &&
|
||||
23 -18 [_p] • [_a] &&
|
||||
23 -18 [_p] [_a] • &&
|
||||
23 -18 [_p] [_a] • [nullary] cons [nullary [false]] dip branch
|
||||
23 -18 [_p] [_a] [nullary] • cons [nullary [false]] dip branch
|
||||
23 -18 [_p] [[_a] nullary] • [nullary [false]] dip branch
|
||||
23 -18 [_p] [[_a] nullary] [nullary [false]] • dip branch
|
||||
23 -18 [_p] • nullary [false] [[_a] nullary] branch
|
||||
23 -18 [_p] • [stack] dinfrirst [false] [[_a] nullary] branch
|
||||
23 -18 [_p] [stack] • dinfrirst [false] [[_a] nullary] branch
|
||||
23 -18 [_p] [stack] • dip infrst [false] [[_a] nullary] branch
|
||||
23 -18 • stack [_p] infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] • [_p] infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] [_p] • infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] [_p] • infra first [false] [[_a] nullary] branch
|
||||
23 -18 • _p [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 • [abs] ii <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 [abs] • ii <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 • abs -18 abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 • -18 abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 • abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 18 • <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
false • [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
false [-18 23] • swaack first [false] [[_a] nullary] branch
|
||||
23 -18 [false] • first [false] [[_a] nullary] branch
|
||||
23 -18 false • [false] [[_a] nullary] branch
|
||||
23 -18 false [false] • [[_a] nullary] branch
|
||||
23 -18 false [false] [[_a] nullary] • branch
|
||||
23 -18 • false
|
||||
23 -18 false •
|
||||
|
||||
23 -18 false
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
### The Increment / Decrement Branches
|
||||
|
||||
Turning to the branches of the main `if` statement:
|
||||
|
|
@ -113,13 +258,6 @@ Similar logic applies to the other branch:
|
|||
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
|
||||
### "Not Negative"
|
||||
|
||||
|
||||
```python
|
||||
define('!- 0 >=')
|
||||
```
|
||||
|
||||
## Putting the Pieces Together
|
||||
|
||||
We can assemble the three functions we just defined in quotes and give
|
||||
|
|
@ -131,6 +269,20 @@ the symmetry of the two branches, we have:
|
|||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
|
||||
```Joy
|
||||
[spiral_next
|
||||
|
||||
[_b]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
] inscribe
|
||||
```
|
||||
|
||||
|
||||
|
||||
As I was writing this up I realized that, since the `&&` combinator
|
||||
doesn't consume the stack (below its quoted args), I can unquote the
|
||||
predicate, swap the branches, and use the `branch` combinator instead of
|
||||
|
|
@ -141,45 +293,120 @@ predicate, swap the branches, and use the `branch` combinator instead of
|
|||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
|
||||
|
||||
```python
|
||||
define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
|
||||
```
|
||||
|
||||
Let's try it out:
|
||||
|
||||
|
||||
```python
|
||||
J('0 0 spiral_next')
|
||||
```Joy
|
||||
clear 0 0
|
||||
```
|
||||
|
||||
0 0
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
1 0
|
||||
|
||||
|
||||
|
||||
```python
|
||||
J('1 0 spiral_next')
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
1 -1
|
||||
|
||||
|
||||
|
||||
```python
|
||||
J('1 -1 spiral_next')
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
0 -1
|
||||
|
||||
|
||||
|
||||
```python
|
||||
J('0 -1 spiral_next')
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
-1 -1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
-1 0
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
-1 1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
0 1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
1 1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
2 1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
2 0
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
2 -1
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
2 -2
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
1 -2
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
0 -2
|
||||
|
||||
|
||||
```Joy
|
||||
spiral_next
|
||||
```
|
||||
|
||||
-1 -2
|
||||
|
||||
## Turning it into a Generator with `x`
|
||||
|
||||
It can be used with the x combinator to make a kind of generator for
|
||||
|
|
@ -188,7 +415,7 @@ spiral square coordinates.
|
|||
|
||||
We can use `codireco` to make a generator
|
||||
|
||||
codireco ::= cons dip rest cons
|
||||
codireco == cons dip rest cons
|
||||
|
||||
It will look like this:
|
||||
|
||||
|
|
@ -196,19 +423,37 @@ It will look like this:
|
|||
|
||||
Here's a trace of how it works:
|
||||
|
||||
[0 [dup ++] codireco] . x
|
||||
[0 [dup ++] codireco] . 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 . [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
|
||||
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
|
||||
. 0 dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 . dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 0 . ++ [0 [dup ++] codireco] rest cons
|
||||
0 1 . [0 [dup ++] codireco] rest cons
|
||||
0 1 [0 [dup ++] codireco] . rest cons
|
||||
0 1 [[dup ++] codireco] . cons
|
||||
0 [1 [dup ++] codireco] .
|
||||
|
||||
```Joy
|
||||
clear
|
||||
|
||||
[0 [dup ++] codireco] [x] trace
|
||||
```
|
||||
|
||||
[0 [dup ++] codireco] • x
|
||||
[0 [dup ++] codireco] • 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 • [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • codi reco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • cons dip reco
|
||||
[0 [dup ++] codireco] [0 dup ++] • dip reco
|
||||
• 0 dup ++ [0 [dup ++] codireco] reco
|
||||
0 • dup ++ [0 [dup ++] codireco] reco
|
||||
0 0 • ++ [0 [dup ++] codireco] reco
|
||||
0 1 • [0 [dup ++] codireco] reco
|
||||
0 1 [0 [dup ++] codireco] • reco
|
||||
0 1 [0 [dup ++] codireco] • rest cons
|
||||
0 1 [[dup ++] codireco] • cons
|
||||
0 [1 [dup ++] codireco] •
|
||||
|
||||
0 [1 [dup ++] codireco]
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
But first we have to change the `spiral_next` function to work on a
|
||||
quoted pair of integers, and leave a copy of the pair on the stack.
|
||||
|
|
@ -225,13 +470,12 @@ to:
|
|||
[x' y']
|
||||
|
||||
|
||||
```python
|
||||
J('[0 0] [spiral_next] infra')
|
||||
```Joy
|
||||
[0 0] [spiral_next] infra
|
||||
```
|
||||
|
||||
[0 1]
|
||||
|
||||
|
||||
So our generator is:
|
||||
|
||||
[[x y] [dup [spiral_next] infra] codireco]
|
||||
|
|
@ -247,30 +491,49 @@ out of the value and stepper function:
|
|||
----------------------------------------------------
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
```
|
||||
|
||||
|
||||
|
||||
Here it is in action:
|
||||
|
||||
|
||||
```python
|
||||
J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
|
||||
```Joy
|
||||
[0 0] [dup [spiral_next] infra] make_generator x x x x pop
|
||||
```
|
||||
|
||||
[0 0] [0 1] [-1 1] [-1 0]
|
||||
|
||||
|
||||
Four `x` combinators, four pairs of coordinates.
|
||||
|
||||
Or you can leave out `dup` and let the value stay in the generator until you want it:
|
||||
|
||||
|
||||
```Joy
|
||||
clear
|
||||
|
||||
[0 0] [[spiral_next] infra] make_generator 50 [x] times first
|
||||
```
|
||||
|
||||
[2 4]
|
||||
|
||||
## Conclusion
|
||||
|
||||
So that's an example of Joy code. It's a straightforward translation of
|
||||
the original. It's a little long for a single definition, you might
|
||||
break it up like so:
|
||||
|
||||
_spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
_spn_Pa == [abs] ii <=
|
||||
_spn_Pb == [!=] [pop 0 >=] ||
|
||||
_spn_P == [_spn_Pa] [_spn_Pb] &&
|
||||
|
||||
_spn_T == [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E == [pop !-] [--] [++] ifte
|
||||
|
||||
_spn_T ::= [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E ::= [pop !-] [--] [++] ifte
|
||||
|
||||
spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
|
||||
spiral_next == _spn_P [_spn_E] [_spn_T] branch
|
||||
|
||||
This way it's easy to see that the function is a branch with two
|
||||
quasi-symmetrical paths.
|
||||
|
|
@ -280,84 +543,3 @@ pairs, where the next pair in the series can be generated at any time by
|
|||
using the `x` combinator on the generator (which is just a quoted
|
||||
expression containing a copy of the current pair and the "stepper
|
||||
function" to generate the next pair from that.)
|
||||
|
||||
|
||||
```python
|
||||
define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
|
||||
define('_spn_T [!-] [[++]] [[--]] ifte dip')
|
||||
define('_spn_E [pop !-] [--] [++] ifte')
|
||||
define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
|
||||
```
|
||||
|
||||
|
||||
```python
|
||||
V('23 18 spiral_next')
|
||||
```
|
||||
|
||||
. 23 18 spiral_next
|
||||
23 . 18 spiral_next
|
||||
23 18 . spiral_next
|
||||
23 18 . _spn_P [_spn_E] [_spn_T] branch
|
||||
23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
|
||||
23 18 . 0 [_spn_E] [_spn_T] branch
|
||||
23 18 0 . [_spn_E] [_spn_T] branch
|
||||
23 18 0 [_spn_E] . [_spn_T] branch
|
||||
23 18 0 [_spn_E] [_spn_T] . branch
|
||||
23 18 . _spn_E
|
||||
23 18 . [pop !-] [--] [++] ifte
|
||||
23 18 [pop !-] . [--] [++] ifte
|
||||
23 18 [pop !-] [--] . [++] ifte
|
||||
23 18 [pop !-] [--] [++] . ifte
|
||||
23 18 [pop !-] [--] [++] . [nullary not] dipd branch
|
||||
23 18 [pop !-] [--] [++] [nullary not] . dipd branch
|
||||
23 18 [pop !-] . nullary not [--] [++] branch
|
||||
23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
|
||||
23 18 . stack [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] . [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] [pop !-] . infra first not [--] [++] branch
|
||||
23 18 . pop !- [18 23] swaack first not [--] [++] branch
|
||||
23 . !- [18 23] swaack first not [--] [++] branch
|
||||
23 . 0 >= [18 23] swaack first not [--] [++] branch
|
||||
23 0 . >= [18 23] swaack first not [--] [++] branch
|
||||
True . [18 23] swaack first not [--] [++] branch
|
||||
True [18 23] . swaack first not [--] [++] branch
|
||||
23 18 [True] . first not [--] [++] branch
|
||||
23 18 True . not [--] [++] branch
|
||||
23 18 False . [--] [++] branch
|
||||
23 18 False [--] . [++] branch
|
||||
23 18 False [--] [++] . branch
|
||||
23 18 . --
|
||||
23 17 .
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
.. code:: ipython3
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
Square Spiral Example Joy Code
|
||||
==============================
|
||||
|
||||
|
|
@ -9,21 +5,21 @@ Here is the example of Joy code from the ``README`` file:
|
|||
|
||||
::
|
||||
|
||||
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
|
||||
It might seem unreadable but with a little familiarity it becomes just
|
||||
as legible as any other notation. Some layout helps:
|
||||
|
||||
::
|
||||
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
|
|
@ -33,34 +29,34 @@ Ulam Spiral).
|
|||
Original Form
|
||||
-------------
|
||||
|
||||
It's adapted from `the original code on
|
||||
It’s adapted from `the original code on
|
||||
StackOverflow <https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777>`__:
|
||||
|
||||
If all you're trying to do is generate the first N points in the
|
||||
spiral (without the original problem's constraint of masking to an N
|
||||
x M region), the code becomes very simple:
|
||||
If all you’re trying to do is generate the first N points in the
|
||||
spiral (without the original problem’s constraint of masking to an N
|
||||
x M region), the code becomes very simple:
|
||||
|
||||
::
|
||||
|
||||
void spiral(const int N)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(int i = 0; i < N; ++i)
|
||||
{
|
||||
cout << x << '\t' << y << '\n';
|
||||
if(abs(x) <= abs(y) && (x != y || x >= 0))
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
else
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
void spiral(const int N)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(int i = 0; i < N; ++i)
|
||||
{
|
||||
cout << x << '\t' << y << '\n';
|
||||
if(abs(x) <= abs(y) && (x != y || x >= 0))
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
else
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
Translation to Joy
|
||||
------------------
|
||||
|
||||
I'm going to make a function that take two ints (``x`` and ``y``) and
|
||||
generates the next pair, we'll turn it into a generator later using the
|
||||
I’m going to make a function that take two ints (``x`` and ``y``) and
|
||||
generates the next pair, we’ll turn it into a generator later using the
|
||||
``x`` combinator.
|
||||
|
||||
First Boolean Predicate
|
||||
|
|
@ -71,33 +67,215 @@ to apply ``abs`` to both values and then compare them with ``<=``:
|
|||
|
||||
::
|
||||
|
||||
[abs] ii <=
|
||||
[abs] ii <=
|
||||
|
||||
I've defined two short-circuiting Boolean combinators ``&&`` and ``||``
|
||||
.. code:: Joy
|
||||
|
||||
[_p [abs] ii <=] inscribe
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear 23 -18
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23 -18
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
[_p] trace
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23 -18 • _p
|
||||
23 -18 • [abs] ii <=
|
||||
23 -18 [abs] • ii <=
|
||||
23 • abs -18 abs <=
|
||||
23 • -18 abs <=
|
||||
23 -18 • abs <=
|
||||
23 18 • <=
|
||||
false •
|
||||
|
||||
false
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
Short-Circuiting Boolean Combinators
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
I’ve defined two short-circuiting Boolean combinators ``&&`` and ``||``
|
||||
that each accept two quoted predicate programs, run the first, and
|
||||
conditionally run the second only if required (to compute the final
|
||||
Boolean value). They run their predicate arguments ``nullary``.
|
||||
|
||||
.. code:: ipython3
|
||||
.. code:: Joy
|
||||
|
||||
define('&& [nullary] cons [nullary [0]] dip branch')
|
||||
define('|| [nullary] cons [nullary] dip [1] branch')
|
||||
[&& [nullary] cons [nullary [false]] dip branch] inscribe
|
||||
[|| [nullary] cons [nullary] dip [true] branch] inscribe
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
[true] [false] &&
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
false
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
[false] [true] &&
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
false
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
[true] [false] ||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
true
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
[false] [true] ||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
true
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
Translating the Conditionals
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Given those, we can define ``x != y || x >= 0`` as:
|
||||
|
||||
::
|
||||
|
||||
[<>] [pop 0 >=] ||
|
||||
_a == [!=] [pop 0 >=] ||
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
[_a [!=] [pop 0 >=] ||] inscribe
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
And ``(abs(x) <= abs(y) && (x != y || x >= 0))`` as:
|
||||
|
||||
::
|
||||
|
||||
[[abs] ii <=] [[<>] [pop 0 >=] ||] &&
|
||||
_b == [_p] [_a] &&
|
||||
|
||||
It's a little rough, but, as I say, with a little familiarity it becomes
|
||||
.. code:: Joy
|
||||
|
||||
[_b [_p] [_a] &&] inscribe
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
It’s a little rough, but, as I say, with a little familiarity it becomes
|
||||
legible.
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear 23 -18
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23 -18
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
[_b] trace
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23 -18 • _b
|
||||
23 -18 • [_p] [_a] &&
|
||||
23 -18 [_p] • [_a] &&
|
||||
23 -18 [_p] [_a] • &&
|
||||
23 -18 [_p] [_a] • [nullary] cons [nullary [false]] dip branch
|
||||
23 -18 [_p] [_a] [nullary] • cons [nullary [false]] dip branch
|
||||
23 -18 [_p] [[_a] nullary] • [nullary [false]] dip branch
|
||||
23 -18 [_p] [[_a] nullary] [nullary [false]] • dip branch
|
||||
23 -18 [_p] • nullary [false] [[_a] nullary] branch
|
||||
23 -18 [_p] • [stack] dinfrirst [false] [[_a] nullary] branch
|
||||
23 -18 [_p] [stack] • dinfrirst [false] [[_a] nullary] branch
|
||||
23 -18 [_p] [stack] • dip infrst [false] [[_a] nullary] branch
|
||||
23 -18 • stack [_p] infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] • [_p] infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] [_p] • infrst [false] [[_a] nullary] branch
|
||||
23 -18 [-18 23] [_p] • infra first [false] [[_a] nullary] branch
|
||||
23 -18 • _p [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 • [abs] ii <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 [abs] • ii <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 • abs -18 abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 • -18 abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 -18 • abs <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
23 18 • <= [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
false • [-18 23] swaack first [false] [[_a] nullary] branch
|
||||
false [-18 23] • swaack first [false] [[_a] nullary] branch
|
||||
23 -18 [false] • first [false] [[_a] nullary] branch
|
||||
23 -18 false • [false] [[_a] nullary] branch
|
||||
23 -18 false [false] • [[_a] nullary] branch
|
||||
23 -18 false [false] [[_a] nullary] • branch
|
||||
23 -18 • false
|
||||
23 -18 false •
|
||||
|
||||
23 -18 false
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
The Increment / Decrement Branches
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -105,42 +283,35 @@ Turning to the branches of the main ``if`` statement:
|
|||
|
||||
::
|
||||
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
|
||||
Rewrite as a hybrid (pseudo-code) ``ifte`` expression:
|
||||
|
||||
::
|
||||
|
||||
[y >= 0] [x += 1] [X -= 1] ifte
|
||||
[y >= 0] [x += 1] [X -= 1] ifte
|
||||
|
||||
Change each C phrase to Joy code:
|
||||
|
||||
::
|
||||
|
||||
[0 >=] [[++] dip] [[--] dip] ifte
|
||||
[0 >=] [[++] dip] [[--] dip] ifte
|
||||
|
||||
Factor out the dip from each branch:
|
||||
|
||||
::
|
||||
|
||||
[0 >=] [[++]] [[--]] ifte dip
|
||||
[0 >=] [[++]] [[--]] ifte dip
|
||||
|
||||
Similar logic applies to the other branch:
|
||||
|
||||
::
|
||||
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
|
||||
[x >= 0] [y -= 1] [y += 1] ifte
|
||||
[x >= 0] [y -= 1] [y += 1] ifte
|
||||
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
|
||||
"Not Negative"
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('!- 0 >=')
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
|
||||
Putting the Pieces Together
|
||||
---------------------------
|
||||
|
|
@ -151,68 +322,184 @@ the symmetry of the two branches, we have:
|
|||
|
||||
::
|
||||
|
||||
[[[abs] ii <=] [[<>] [pop !-] ||] &&]
|
||||
[[[abs] ii <=] [[<>] [pop !-] ||] &&]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
[spiral_next
|
||||
|
||||
[_b]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
] inscribe
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
As I was writing this up I realized that, since the ``&&`` combinator
|
||||
doesn't consume the stack (below its quoted args), I can unquote the
|
||||
doesn’t consume the stack (below its quoted args), I can unquote the
|
||||
predicate, swap the branches, and use the ``branch`` combinator instead
|
||||
of ``ifte``:
|
||||
|
||||
::
|
||||
|
||||
[[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
[[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
|
||||
.. code:: ipython3
|
||||
Let’s try it out:
|
||||
|
||||
define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
|
||||
.. code:: Joy
|
||||
|
||||
Let's try it out:
|
||||
clear 0 0
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('0 0 spiral_next')
|
||||
.. parsed-literal::
|
||||
|
||||
0 0
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 0
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('1 0 spiral_next')
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 -1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('1 -1 spiral_next')
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 -1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('0 -1 spiral_next')
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-1 -1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-1 0
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-1 1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 0
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 -1
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 -2
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 -2
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 -2
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
spiral_next
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-1 -2
|
||||
|
||||
Turning it into a Generator with ``x``
|
||||
--------------------------------------
|
||||
|
|
@ -224,31 +511,51 @@ We can use ``codireco`` to make a generator
|
|||
|
||||
::
|
||||
|
||||
codireco ::= cons dip rest cons
|
||||
codireco == cons dip rest cons
|
||||
|
||||
It will look like this:
|
||||
|
||||
::
|
||||
|
||||
[value [F] codireco]
|
||||
[value [F] codireco]
|
||||
|
||||
Here's a trace of how it works:
|
||||
Here’s a trace of how it works:
|
||||
|
||||
::
|
||||
.. code:: Joy
|
||||
|
||||
[0 [dup ++] codireco] . x
|
||||
[0 [dup ++] codireco] . 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 . [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
|
||||
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
|
||||
. 0 dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 . dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 0 . ++ [0 [dup ++] codireco] rest cons
|
||||
0 1 . [0 [dup ++] codireco] rest cons
|
||||
0 1 [0 [dup ++] codireco] . rest cons
|
||||
0 1 [[dup ++] codireco] . cons
|
||||
0 [1 [dup ++] codireco] .
|
||||
clear
|
||||
|
||||
[0 [dup ++] codireco] [x] trace
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 [dup ++] codireco] • x
|
||||
[0 [dup ++] codireco] • 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 • [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • codi reco
|
||||
[0 [dup ++] codireco] 0 [dup ++] • cons dip reco
|
||||
[0 [dup ++] codireco] [0 dup ++] • dip reco
|
||||
• 0 dup ++ [0 [dup ++] codireco] reco
|
||||
0 • dup ++ [0 [dup ++] codireco] reco
|
||||
0 0 • ++ [0 [dup ++] codireco] reco
|
||||
0 1 • [0 [dup ++] codireco] reco
|
||||
0 1 [0 [dup ++] codireco] • reco
|
||||
0 1 [0 [dup ++] codireco] • rest cons
|
||||
0 1 [[dup ++] codireco] • cons
|
||||
0 [1 [dup ++] codireco] •
|
||||
|
||||
0 [1 [dup ++] codireco]
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
But first we have to change the ``spiral_next`` function to work on a
|
||||
quoted pair of integers, and leave a copy of the pair on the stack.
|
||||
|
|
@ -256,166 +563,107 @@ From:
|
|||
|
||||
::
|
||||
|
||||
y x spiral_next
|
||||
---------------------
|
||||
y' x'
|
||||
y x spiral_next
|
||||
---------------------
|
||||
y' x'
|
||||
|
||||
to:
|
||||
|
||||
::
|
||||
|
||||
[x y] [spiral_next] infra
|
||||
-------------------------------
|
||||
[x' y']
|
||||
[x y] [spiral_next] infra
|
||||
-------------------------------
|
||||
[x' y']
|
||||
|
||||
.. code:: ipython3
|
||||
.. code:: Joy
|
||||
|
||||
J('[0 0] [spiral_next] infra')
|
||||
[0 0] [spiral_next] infra
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 1]
|
||||
|
||||
|
||||
So our generator is:
|
||||
|
||||
::
|
||||
|
||||
[[x y] [dup [spiral_next] infra] codireco]
|
||||
[[x y] [dup [spiral_next] infra] codireco]
|
||||
|
||||
Or rather:
|
||||
|
||||
::
|
||||
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
There is a function ``make_generator`` that will build the generator for
|
||||
us out of the value and stepper function:
|
||||
|
||||
::
|
||||
|
||||
[0 0] [dup [spiral_next] infra] make_generator
|
||||
----------------------------------------------------
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
[0 0] [dup [spiral_next] infra] make_generator
|
||||
----------------------------------------------------
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
|
||||
|
||||
Here it is in action:
|
||||
|
||||
.. code:: ipython3
|
||||
.. code:: Joy
|
||||
|
||||
J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
|
||||
[0 0] [dup [spiral_next] infra] make_generator x x x x pop
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 0] [0 1] [-1 1] [-1 0]
|
||||
|
||||
|
||||
Four ``x`` combinators, four pairs of coordinates.
|
||||
|
||||
Or you can leave out ``dup`` and let the value stay in the generator
|
||||
until you want it:
|
||||
|
||||
.. code:: Joy
|
||||
|
||||
clear
|
||||
|
||||
[0 0] [[spiral_next] infra] make_generator 50 [x] times first
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[2 4]
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
So that's an example of Joy code. It's a straightforward translation of
|
||||
the original. It's a little long for a single definition, you might
|
||||
So that’s an example of Joy code. It’s a straightforward translation of
|
||||
the original. It’s a little long for a single definition, you might
|
||||
break it up like so:
|
||||
|
||||
::
|
||||
|
||||
_spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
_spn_Pa == [abs] ii <=
|
||||
_spn_Pb == [!=] [pop 0 >=] ||
|
||||
_spn_P == [_spn_Pa] [_spn_Pb] &&
|
||||
|
||||
_spn_T ::= [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E ::= [pop !-] [--] [++] ifte
|
||||
_spn_T == [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E == [pop !-] [--] [++] ifte
|
||||
|
||||
spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
|
||||
spiral_next == _spn_P [_spn_E] [_spn_T] branch
|
||||
|
||||
This way it's easy to see that the function is a branch with two
|
||||
This way it’s easy to see that the function is a branch with two
|
||||
quasi-symmetrical paths.
|
||||
|
||||
We then used this function to make a simple generator of coordinate
|
||||
pairs, where the next pair in the series can be generated at any time by
|
||||
using the ``x`` combinator on the generator (which is just a quoted
|
||||
expression containing a copy of the current pair and the "stepper
|
||||
function" to generate the next pair from that.)
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
|
||||
define('_spn_T [!-] [[++]] [[--]] ifte dip')
|
||||
define('_spn_E [pop !-] [--] [++] ifte')
|
||||
define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
V('23 18 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 23 18 spiral_next
|
||||
23 . 18 spiral_next
|
||||
23 18 . spiral_next
|
||||
23 18 . _spn_P [_spn_E] [_spn_T] branch
|
||||
23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
|
||||
23 18 . 0 [_spn_E] [_spn_T] branch
|
||||
23 18 0 . [_spn_E] [_spn_T] branch
|
||||
23 18 0 [_spn_E] . [_spn_T] branch
|
||||
23 18 0 [_spn_E] [_spn_T] . branch
|
||||
23 18 . _spn_E
|
||||
23 18 . [pop !-] [--] [++] ifte
|
||||
23 18 [pop !-] . [--] [++] ifte
|
||||
23 18 [pop !-] [--] . [++] ifte
|
||||
23 18 [pop !-] [--] [++] . ifte
|
||||
23 18 [pop !-] [--] [++] . [nullary not] dipd branch
|
||||
23 18 [pop !-] [--] [++] [nullary not] . dipd branch
|
||||
23 18 [pop !-] . nullary not [--] [++] branch
|
||||
23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
|
||||
23 18 . stack [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] . [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] [pop !-] . infra first not [--] [++] branch
|
||||
23 18 . pop !- [18 23] swaack first not [--] [++] branch
|
||||
23 . !- [18 23] swaack first not [--] [++] branch
|
||||
23 . 0 >= [18 23] swaack first not [--] [++] branch
|
||||
23 0 . >= [18 23] swaack first not [--] [++] branch
|
||||
True . [18 23] swaack first not [--] [++] branch
|
||||
True [18 23] . swaack first not [--] [++] branch
|
||||
23 18 [True] . first not [--] [++] branch
|
||||
23 18 True . not [--] [++] branch
|
||||
23 18 False . [--] [++] branch
|
||||
23 18 False [--] . [++] branch
|
||||
23 18 False [--] [++] . branch
|
||||
23 18 . --
|
||||
23 17 .
|
||||
|
||||
expression containing a copy of the current pair and the “stepper
|
||||
function” to generate the next pair from that.)
|
||||
|
|
|
|||
Loading…
Reference in New Issue