Skip to content

Instantly share code, notes, and snippets.

@crcx
Last active May 18, 2017 01:29
Show Gist options
  • Save crcx/e338a5132ab9a5ceb00c550e8f8809de to your computer and use it in GitHub Desktop.
Save crcx/e338a5132ab9a5ceb00c550e8f8809de to your computer and use it in GitHub Desktop.
Sets (simple arrays) in Retro

Sets

Sets are statically sized arrays. They are represented in memory as:

count
data #1 (first)
...
data #n (last)

TODO:

[x] set:from-results
[x] set:from-string
[x] set:contains?
[x] set:contains-string?
[x] set:filter
[x] set:map
[x] set:for-each
[x] set:dup
[x] set:reverse
[x] set:nth

The first couple of words are used to create sets. The first, set:from-results executes a quote and constructs a set from the returned values.

:set:from-results (q-a)
  depth [ call ] dip depth swap -
  here [ dup , [ , ] times ] dip ;

The second, set:from-string, creates a new string with the characters in given a string.

:set:from-string (s-a)
  s:reverse [ [ ] s:for-each ] curry
  set:from-results ;

A very crucial piece is set:for-each. This runs a quote once against each value in a set. This will be leveraged to implement additional combinators.

{{
  'Q var
---reveal---
  :set:for-each (aq-)
    @Q [ !Q fetch-next
         [ fetch-next swap [ @Q call ] dip ] times drop
       ] dip !Q ;
}}

With this I can easily define set:dup to make a copy of a set.

:set:dup (a-a)
  here [ dup fetch , [ , ] set:for-each ] dip ;

Next is set:filter, which is extracts matching values from a set. This is used like:

[ #1 #2 #3 #4 #5 #6 #7 #8 ] set
[ n:even? ] set:filter

It returns a new set with the values that the quote returned a TRUE flag for.

:set:filter (aq-)
  [ over [ call ] dip swap [ , ] [ drop ] choose ] curry
  here [ over fetch , set:for-each ] dip here over - n:dec over store ;

Next are set:contains? and set:contains-string? which compare a given value to each item in the array and returns a flag.

{{
  'F var
---reveal---
  :set:contains? (na-f)
    &F v:off
    [ over eq? @F or !F ] set:for-each
    drop @F ;

  :set:contains-string? (na-f)
    &F v:off
    [ over s:eq? @F or !F ] set:for-each
    drop @F ;
}}

I implemented set:map to apply a quotation to each item in a set and construct a new set from the returned values.

Example:

[ #1 #2 #3 ] set
[ #10 * ] set:map
:set:map (aq-)
  [ call , ] curry
  here [ over fetch , set:for-each ] dip ;

You can use set:reverse to make a copy of a set with the values reversed. This can be useful after a set:from-results.

:set:reverse (a-a)
  here [ fetch-next [ + n:dec ] sip dup ,
         [ dup fetch , n:dec ] times drop
       ] dip ;

set:nth provides a quick means of adjusting a set and offset into an address for use with fetch and store.

:set:nth (an-a)
  + n:inc ;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment