no longer use ```` for code blocks; this fence sequence will be used for embedded tests in a later update
FossilOrigin-Name: dfed0de00b8d63672a882b79c4951cce0076007ef208c063b2f4e54fe9bd08f8
This commit is contained in:
parent
e71709b303
commit
e549b4ced6
14 changed files with 604 additions and 642 deletions
|
@ -3,6 +3,10 @@ RETRO 12 - 2018.6 - WIP
|
|||
Major Changes:
|
||||
|
||||
- renamed `s:with-format` to `s:format`
|
||||
- ```` no longer used for code blocks (now reserved for 'tests'
|
||||
under rre)
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
Bug fixes:
|
||||
|
||||
|
@ -14,6 +18,8 @@ Core Language:
|
|||
|
||||
Interfaces:
|
||||
|
||||
- no longer use ```` for code blocks; use ~~~ instead
|
||||
|
||||
Other:
|
||||
|
||||
Documentation:
|
||||
|
|
|
@ -8,9 +8,9 @@ any time.
|
|||
|
||||
Example:
|
||||
|
||||
````
|
||||
~~~
|
||||
#12 [ dup * ] call
|
||||
````
|
||||
~~~
|
||||
|
||||
In this, the code stating with `[` and ending with `]` is the quote. Here
|
||||
it's just `call`ed immediately, but you can also pass it to other words.
|
||||
|
@ -23,60 +23,60 @@ execution. This begins with conditionals.
|
|||
Assuming that we have a flag on the stack, you can run a quote if the
|
||||
flag is `TRUE`:
|
||||
|
||||
````
|
||||
~~~
|
||||
#1 #2 eq?
|
||||
[ 'True! puts ] if
|
||||
````
|
||||
~~~
|
||||
|
||||
Or if it's `FALSE`:
|
||||
|
||||
````
|
||||
~~~
|
||||
#1 #2 eq?
|
||||
[ 'Not_true! puts ] -if
|
||||
````
|
||||
~~~
|
||||
|
||||
There's also a `choose` combinator:
|
||||
|
||||
````
|
||||
~~~
|
||||
#1 #2 eq?
|
||||
[ 'True! puts ]
|
||||
[ 'Not_true! puts ] choose
|
||||
````
|
||||
~~~
|
||||
|
||||
RETRO also uses combinators for loops:
|
||||
|
||||
A counted loop takes a count and a quote:
|
||||
|
||||
````
|
||||
~~~
|
||||
#0 #100 [ dup putn sp n:inc ] times
|
||||
````
|
||||
~~~
|
||||
|
||||
You can also loop while a quote returns a flag of `TRUE`:
|
||||
|
||||
````
|
||||
~~~
|
||||
#0 [ n:inc dup #100 lt? ] while
|
||||
````
|
||||
~~~
|
||||
|
||||
Or while it returns `FALSE`:
|
||||
|
||||
````
|
||||
~~~
|
||||
#100 [ n:dec dup n:zero? ] until
|
||||
````
|
||||
~~~
|
||||
|
||||
In RETRO you can also use combinators to iterate over data structures. For
|
||||
instance, many structures provide a `for-each` combinator which can be run
|
||||
once for each item in the structure. E.g., with a string:
|
||||
|
||||
````
|
||||
~~~
|
||||
'Hello [ putc ] s:for-each
|
||||
````
|
||||
~~~
|
||||
|
||||
Moving further, combinators are also used for filters and operations on
|
||||
data. Again with strings:
|
||||
|
||||
````
|
||||
~~~
|
||||
'Hello_World! [ c:-vowel? ] s:filter
|
||||
````
|
||||
~~~
|
||||
|
||||
This runs `s:filter` which takes a quote returning a flag. For each `TRUE`
|
||||
it appends the character into a new string, while `FALSE` results are
|
||||
|
@ -84,9 +84,9 @@ discarded.
|
|||
|
||||
You might also use a `map`ping combinator to update a data set:
|
||||
|
||||
````
|
||||
~~~
|
||||
'Hello_World [ c:to-upper ] s:map
|
||||
````
|
||||
~~~
|
||||
|
||||
This takes a quote that modifies a value which is then used to build a
|
||||
new string.
|
||||
|
|
|
@ -26,7 +26,7 @@ The major prefixes are:
|
|||
|
||||
Example:
|
||||
|
||||
````
|
||||
~~~
|
||||
(This_is_a_comment)
|
||||
|
||||
(Define_some_words)
|
||||
|
@ -49,4 +49,4 @@ $a (this_is_the_ASCII_'a')
|
|||
'Foo var
|
||||
#100 !Foo
|
||||
@Foo putn
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -17,50 +17,50 @@ If, in the following table, a live cell is represented by 1 and a dead cell by 0
|
|||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
~~~
|
||||
:example|RosettaCode|1D-Cellular-Automota ;
|
||||
````
|
||||
~~~
|
||||
|
||||
I had originally written an implementation of this in RETRO 11. For RETRO 12 I took advantage of new language features and some further considerations into the rules for this task.
|
||||
|
||||
The first word, `string,` inlines a string to `here`. I'll use this to setup the initial input.
|
||||
|
||||
````
|
||||
~~~
|
||||
:string, (s-) [ , ] s:for-each #0 , ;
|
||||
````
|
||||
~~~
|
||||
|
||||
The next two lines setup an initial generation and a buffer for the evolved generation. In this case, `This` is the current generation and `Next` reflects the next step in the evolution.
|
||||
|
||||
````
|
||||
~~~
|
||||
'This d:create
|
||||
'.###.##.#.#.#.#..#.. string,
|
||||
|
||||
'Next d:create
|
||||
'.................... string,
|
||||
````
|
||||
~~~
|
||||
|
||||
I use `display` to show the current generation.
|
||||
|
||||
````
|
||||
~~~
|
||||
:display (-)
|
||||
&This puts nl ;
|
||||
````
|
||||
~~~
|
||||
|
||||
As might be expected, `update` copies the `Next` generation to the `This` generation, setting things up for the next cycle.
|
||||
|
||||
````
|
||||
~~~
|
||||
:update (-)
|
||||
&Next &This dup s:length copy ;
|
||||
````
|
||||
~~~
|
||||
|
||||
The word `group` extracts a group of three cells. This data will be passed to `evolve` for processing.
|
||||
|
||||
````
|
||||
~~~
|
||||
:group (a-nnn)
|
||||
[ fetch ]
|
||||
[ n:inc fetch ]
|
||||
[ n:inc n:inc fetch ] tri ;
|
||||
````
|
||||
~~~
|
||||
|
||||
I use `evolve` to decide how a cell should change, based on its initial state with relation to its neighbors.
|
||||
|
||||
|
@ -72,25 +72,25 @@ In the prior implementation this part was much more complex as I tallied things
|
|||
- if the result is `#-2`, the cell should live
|
||||
- otherwise it'll be dead
|
||||
|
||||
````
|
||||
~~~
|
||||
:evolve (nnn-c)
|
||||
[ $# eq? ] tri@ + +
|
||||
#-2 eq? [ $# ] [ $. ] choose ;
|
||||
````
|
||||
~~~
|
||||
|
||||
For readability I separated out the next few things. `at` takes an index and returns the address in `This` starting with the index.
|
||||
|
||||
````
|
||||
~~~
|
||||
:at (n-na)
|
||||
&This over + ;
|
||||
````
|
||||
~~~
|
||||
|
||||
The `record` word adds the evolved value to a buffer. In this case my `generation` code will set the buffer to `Next`.
|
||||
|
||||
````
|
||||
~~~
|
||||
:record (c-)
|
||||
buffer:add n:inc ;
|
||||
````
|
||||
~~~
|
||||
|
||||
And now to tie it all together. Meet `generation`, the longest bit of code in this sample. It has several bits:
|
||||
|
||||
|
@ -107,21 +107,21 @@ And now to tie it all together. Meet `generation`, the longest bit of code in th
|
|||
|
||||
- copy `Next` to `This` using `update`.
|
||||
|
||||
````
|
||||
~~~
|
||||
:generation (-)
|
||||
[ &Next buffer:set
|
||||
#-1 &This s:length
|
||||
[ at group evolve record ] times drop
|
||||
update
|
||||
] buffer:preserve ;
|
||||
````
|
||||
~~~
|
||||
|
||||
The last bit is a helper. It takes a number of generations and displays the state, then runs a `generation`.
|
||||
|
||||
````
|
||||
~~~
|
||||
:generations (n-)
|
||||
[ display generation ] times ;
|
||||
````
|
||||
~~~
|
||||
|
||||
And a text. The output should be:
|
||||
|
||||
|
@ -136,6 +136,6 @@ And a text. The output should be:
|
|||
..##................
|
||||
..##................
|
||||
|
||||
````
|
||||
~~~
|
||||
#10 generations
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -2,13 +2,7 @@
|
|||
|
||||
Display the text for the *99 Bottles of Beer* song.
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|99Bottles ;
|
||||
````
|
||||
|
||||
````
|
||||
~~~
|
||||
[ dup putn sp 'bottles puts ]
|
||||
[ '1_bottle puts ]
|
||||
[ 'no_more_bottles puts ]
|
||||
|
@ -38,4 +32,4 @@ Declare module constant (prevents reloading when using `import`):
|
|||
[ nl display-verse dup n:-zero? ] while drop ;
|
||||
|
||||
#99 verses
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
This is an example adding two three element vectors.
|
||||
|
||||
````
|
||||
~~~
|
||||
:vadd (v1v2v3-)
|
||||
'abc 'cabcabcab reorder
|
||||
[ #2 + ] tri@ [ fetch ] bi@ + swap store
|
||||
[ n:inc ] tri@ [ fetch ] bi@ + swap store
|
||||
[ fetch ] bi@ + swap store ;
|
||||
````
|
||||
~~~
|
||||
|
||||
A test case:
|
||||
|
||||
````
|
||||
~~~
|
||||
'a d:create #1 , #2 , #3 ,
|
||||
'b d:create #2 , #3 , #4 ,
|
||||
'c d:create #3 allot
|
||||
|
@ -20,5 +20,5 @@ A test case:
|
|||
&c fetch-next putn nl
|
||||
fetch-next putn nl
|
||||
fetch putn nl
|
||||
````
|
||||
~~~
|
||||
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
# example|GreatestCommonDivisor
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|GreatestCommonDivisor ;
|
||||
````
|
||||
|
||||
````
|
||||
~~~
|
||||
:gcd (ab-n)
|
||||
[ tuck mod dup ] while drop ;
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
# example|IterativeFibonacci
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|IterativeFibonacci ;
|
||||
````
|
||||
|
||||
----
|
||||
|
||||
````
|
||||
~~~
|
||||
:fib (n-m)
|
||||
[ #0 #1 ] dip
|
||||
[ over + swap ] times drop ;
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -1,17 +1,9 @@
|
|||
# example|LeastCommonMultiple
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|LeastCommonMultiple ;
|
||||
````
|
||||
|
||||
----
|
||||
|
||||
````
|
||||
~~~
|
||||
:gcd (ab-n)
|
||||
[ tuck mod dup ] while drop ;
|
||||
|
||||
:lcm (ab-n)
|
||||
dup-pair gcd [ * ] dip / ;
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
This is a quick and dirty way to find prime numbers in a set.
|
||||
|
||||
````
|
||||
~~~
|
||||
{{
|
||||
#2 'NextPrime var<n>
|
||||
:extract (s-s)
|
||||
|
@ -12,13 +12,13 @@ This is a quick and dirty way to find prime numbers in a set.
|
|||
#2 !NextPrime
|
||||
dup fetch [ extract &NextPrime v:inc ] times ;
|
||||
}}
|
||||
````
|
||||
~~~
|
||||
|
||||
And a test:
|
||||
|
||||
````
|
||||
~~~
|
||||
:create-set (-a)
|
||||
here #7000 , #2 #7002 [ dup , n:inc ] times drop ;
|
||||
|
||||
create-set get-primes [ putn sp ] set:for-each
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
# example|RecursiveFactorial
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|RecursiveFactorial ;
|
||||
````
|
||||
|
||||
----
|
||||
|
||||
````
|
||||
~~~
|
||||
:<factorial>
|
||||
dup #1 -eq? 0; drop
|
||||
dup n:dec <factorial> * ;
|
||||
|
@ -17,5 +9,5 @@ Declare module constant (prevents reloading when using `import`):
|
|||
dup n:zero?
|
||||
[ n:inc ]
|
||||
[ <factorial> ] choose ;
|
||||
````
|
||||
~~~
|
||||
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
# example|RecursiveFibonacci
|
||||
|
||||
Declare module constant (prevents reloading when using `import`):
|
||||
|
||||
````
|
||||
:example|RecursiveFibonacci ;
|
||||
````
|
||||
|
||||
----
|
||||
|
||||
````
|
||||
~~~
|
||||
:fib (n-m)
|
||||
dup
|
||||
[ n:zero? ] [ #1 eq? ] bi or
|
||||
not 0; drop
|
||||
[ n:dec fib ] sip
|
||||
[ #2 - fib ] call + ;
|
||||
````
|
||||
~~~
|
||||
|
|
|
@ -10,9 +10,9 @@ In Retro this is fairly easy. We can use `s:hash` to identify a unique
|
|||
string. So make a copy, take he hash, reverse the copy, get its hash,
|
||||
and compare them.
|
||||
|
||||
````
|
||||
~~~
|
||||
:s:palindrome? (s-f)
|
||||
dup s:hash [ s:reverse s:hash ] dip eq? ;
|
||||
|
||||
'ingirumimusnocteetconsumimurigni s:palindrome?
|
||||
````
|
||||
~~~
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue