The Select Button game jam is happening this month, and I want to use Gazelle to develop my entry. That means I needed the following features.
Multi-body Functions
define and lambda now support a multi-body syntax so that
different patterns can be used to produce different effects.
Consider:
(gazelle:essentials)
(define (vocalize [
(([: :cat name])
(+ name " says: meow"))
(([: :dog name])
(+ name " says: woof"))
]))
Then,
(vocalize [: :cat "Garfield"])
evaluates to:
"Garfield says: meow"
While
(vocalize [: :dog "Bowzer"])
to
"Bowzer says: woof"
The syntax is:
(define [(<argument-pattern1> body10 body1 ...)
(<argument-pattern2> body20 body2 ...)
...])
Where each <argument-pattern> is a shadchen-style, array pattern
with the array head removed.
Simple function definitions are still supported. I don't want to show the generated code because the pattern matcher generates large nested structures. I'm working on it, although some optimizations are in place for simple situations, like vectors of symbols with a symbol tail, etc. It should be possible to write a flat pattern matcher, but that is some work.
Macros support a similar interface. eg:
(define-macro let*
[((nil (tail body))
(progn ,@body))
(((list (list symbol value) (tail binders)) (tail body))
(let ((,symbol ,value))
(let* ,binders ,@body)))])
Is an implementation of a let* like macro.
Self Recursion in Functions
Functions can recur to themselves using recur in tail positions. It
is, at the moment, an unchecked error if recur occurs somewhere
else. Given the underlying language implementation, it might be hard
to check this statically. One can write filter like this, then:
(define (filter [
((fun [:] acc)
acc)
((fun [: hd (tail tl)] acc)
(if (fun hd)
(recur fun tl (acc.concat [: hd]))
(recur fun tl acc)))
]))
This sort of mock recursion doesn't grow the stack. Cute.
Changes to the define syntax apply to define+ as well.
I really need to use git more responsibly, all these changes, including lots of regressions, have been happening on the master branch, frequently updated on github. Sorry!
3 comments:
Why not change "recur" to "goto"? It would be both correct and traditional.
I believe that is a completely unfair dig, for at least one reason: recur can only `goto` one place, and is more like `re-enter`. That is it.
And, actually, now that you mention crazy control flow operations, what about this silly idea of `return`ing from a function? I rather like the functional approach where return value of a function must be one of its tails, but in Javascript you must literally mark the return value and you can return from any location whatever in the body. Recur is tame in comparison.
Post a Comment