[Grace-core] SETL question
James Noble
kjx at ecs.vuw.ac.nz
Mon Apr 1 03:38:01 PDT 2013
Hi all
earlier Philippe Kruchten posted this:
> Set of primes numbers between 1 and 100 in SETL:
> print ( { x : x in 2..100 | not exists y in [ 2 .. x-1] | x mod y = 0 } )
>
> How do you do this in Grace?
So after thinking a bit, I came up with this:
(2..100).select { x-> (2..(x-1)).none { y-> (x%y) == 0 }}
which doesn't work because we don't have a good collection protocol yet.
It was heavily inspired by the Ruby extensions to Smalltalk collections.
This runs on irb on my mac:
(2..100).select {|x| (2..x-1).none? {|y| x%y==0 }}
Grace needs more parentheses because we don't have much operator precedence,
and our blocks are "v->" rather than "|v|". Otherwise, in lots of ways we are similar to Ruby.
In Alloy, it would be something like
all e : 2..100 | no x : 2..x-1 |
(assuming Alloy had ranges and numbers that work)
which lead me towards:
all (2..100) suchThat {x-> no (2..(x-1)) suchThat {y-> (x%y)==0 }}
or, shorter: all (2..100) st {x-> no (2..(x-1)) st {y-> (x%y)==0 }}
which runs here, if you first cut and paste the definitions below.
http://homepages.ecs.vuw.ac.nz/~mwh/minigrace/js/
although I'm not at all sure "all()suchThat()" and "no()suchThat()" are consistent with regards to return type - "all" probably should be renamed back to "collect" or something.
this is another case where Grace using only blocks, not macros, means we write
all (2..10) collect {x -> x * x}
rather than the more lisp-ish (or Wirth-ish, or "natural")
all x : (2..10) collect {x *x}
But I always liked the arguments in favour of this:
- I doubt the differences matter to novices who aren't strong in maths
- it introduces lambdas really early.
cheers
James
PS http://smalltalkzen.wordpress.com/2011/02/02/arlo-guthrie-and-the-origins-of-the-collection-protocol/
method all (collection) suchThat (block) {
def result = []
for (collection) do { each ->
if (block.apply(each)) then {result.push(each)}
}
return result
}
method no (collection) suchThat (block) {
for (collection) do { each ->
if (block.apply(each)) then {return false}
}
return true
}
method all (collection) st (block) {all (collection) suchThat (block)}
method no (collection) st (block) {no (collection) suchThat (block)}
print (all (2..100) st {x-> no (2..(x-1)) st {y-> (x%y)==0 }})
More information about the Grace-core
mailing list