Has anyone ever come across/experimented with a Lisp/Scheme that has “where” clauses? Something like: (define (foo x)
(if (> x 2)
(inc y)
(dec y))
(where ([y (* x x)]
[inc (λ(x)(+ x 1)]
[dec (λ(x)(- x 1)]))
=>
(define (foo x)
(let ([y (* x x)]
[inc (λ(x)(+ x 1)]
[dec (λ(x)(- x 1)])
(if (> x 2)
(inc y)
(dec y))))
I’m curious what pitfalls this has (at the very least I feel like you’d limit it to certain locations as in Haskell’s where), and how it could possibly be implemented. Cheers :slightly_smiling_face:
it’s pretty easy to implement, here’s an untested version: (define-syntax (where stx) (raise-syntax-error #f stx "used outside of `define/where`"))
(define-syntax (define/where stx)
(syntax-parse stx #:literals (where)
[(_ (f args ...) e0 e ... (where (clauses ...))) #'(define (f args) (let (clauses ...) e0 e ...))]))
Thanks! It makes sense to me reading it, but gives "_ wildcard not allowed as expression" when trying to use it. Really, I should feel ashamed if I can’t work it out myself, now I know it really can just be transformed into a let using a special define/where form.
If you’re using #lang racket
you’ll need to (require (for-syntax syntax/parse))
. syntax-parse
is not required by default. Also it needs to be required for-syntax
. I think approximately 100% of people using syntax/parse
get puzzled by this error message.
After you fix that, you’ll get another error, which is hopefully clearer: ; /tmp/foo.rkt:8:64: syntax: missing ellipsis with pattern variable in template
; at: args
; in: (syntax (define (f args) (let (clauses ...) e0 e ...)))
I added a … after args; hopefully that’s it.
Bingo.
At least, that makes the definition of the macro OK. I haven’t tried to use it.
Seems to work great! Thank you both for your help. If I wasn’t already convinced of Lisp/Scheme/Racket’s ease-of-transformation (I was) I sure am now! :wink:
I remember someone mentioning this was removed from OCaml for some reason, but what exactly was said escapes me, sadly.
FWIW, recent Rackets also include this information in the error message: _: wildcard not allowed as an expression
after encountering unbound identifiers (which is possibly the real problem):
where
syntax-parse