Mike Austin's Blog

Friday, April 07, 2006

Predicate syntax generalization

I always look at language design with a refactoring approach. Write a syntax for one particular problem, then write a new syntax for another problem. Now refactor those two languages into one. For example, take this problem:

From 1 to 10, give me the square of each even number.

The generalization of this problem could be something like:
list, predicate, function => list

Haskell and Python do a nice job with list comprehention:
[i * i | i <- [1..10], i `mod` 2 == 0]
But list comprehention is it's own syntax, completely different from the rest of Haskell or Python (actually it's set-builder notation).

Matz, the creator of Ruby learned that passing a closure to a function is so common, that it is built into the syntax:
(1..10).map { |i| i * i if i % 2 == 0 }.compact!
But how do we separate that predicate from the function? If we take Ruby's idea of passing closures as syntax, and also provide a syntax for passing predicates, we get Impulse, my language tinkerings:
1..10 map: (i [i % 2 == 0] -> i * i)
It's not about less typing, it's about generalization and eliminating sub-language syntaxes. Extending it to multi-predicate closures, the need for any conditionals goes away completely:
x = ([x >  10] ->  10
[x < -10] -> -10) value
Just thought I'd ramble a bit... it's my blog anyways :)

0 Comments:

Post a Comment

<< Home