[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