
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