[racket] One define to rule them all

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Sat Nov 13 15:29:31 EST 2010

If you like this sort of thing, you may also like super values:

https://github.com/jeapostrophe/exp/blob/master/values.ss

An excerpt:

(let-values+ ([(x . xs) (values 10 10.2 10.3)]
               [(y) 2])
              (list x xs y))
 =>
 (list 10 (list 10.2 10.3) 2)

 (let-values+ ([(x [z 3]) 11]
               [(y) 2])
              (list x y z))
 =>
 (list 11 2 3)

 (let-values+ ([(x #:foo z) (values+ 12 #:foo 3)]
               [(y) 2])
              (list x y z))
 =>
 (list 12 2 3)

 (let-values+ ([(x #:foo [z 3]) 13]
               [(y) 2])
              (list x y z))
 =>
 (list 13 2 3)

On Fri, Nov 12, 2010 at 4:40 PM, Neil Toronto <neil.toronto at gmail.com> wrote:
> In internal definition contexts, I've been using the following macro to
> define everything but functions:
>
> (define-syntax (def stx)
>  (syntax-case stx (values)
>    [(_ x e0 e ...)
>     (identifier? #'x)
>     (syntax/loc stx
>       (define x (let () e0 e ...)))]
>    [(_ (values x ...) e0 e ...)
>     (andmap identifier? (syntax->list #'(x ...)))
>     (syntax/loc stx
>       (define-values (x ...) (let () e0 e ...)))]
>    [(_ (values pat ...) e0 e ...)
>     (syntax/loc stx
>       (match-define (list pat ...)
>                     (call-with-values (lambda () e0 e ...) list)))]
>    [(_ pat e0 e ...)
>     (syntax/loc stx
>       (match-define pat (let () e0 e ...)))]))
>
>
> So these do the obvious things:
>
>    (def a 4)
>    (def (values) (values))
>    (def (values b c) (values 4 5))
>    (def (values (list d e) f)
>      (values (list 4 5) 6))
>
> Common cases like (def x:id e ...+) and (def (values x:id ...) e ...+)
> expand to the most direct define-like form. (It avoids `match-define'
> because `match-define' 1) always binds a failure thunk; and 2) forces
> multiple values to be converted to lists.)
>
> With `def', it's easier to recognize a sequence of definitions leading up to
> a computation buried inside a conditional branch. For example, instead of:
>
>    (cond ...
>          [(the-condition? z-sig)
>           (define x (compute-x z))
>           (match-define (foo y-bar y-baz) y)
>           (define-values (a b) (get-some-values x y-bar))
>           (the-computation x y-baz a b)] ...)
>
> I have:
>
>    (cond ...
>          [(the-condition? z-sig)
>           (def x (compute-x z))
>           (def (foo y-bar y-baz) y)
>           (def (values a b) (get-some-values x y-bar))
>           (the-computation x y-baz a b)] ...)
>
> It's hard to miss all the `def's lined up in the same column.
>
> Have I left anything out? Does anybody else think it's awesome/useful?
> Hideous?
>
> Neil T
>
> (It's a shame it can't do functions, but there's no way to tell whether (def
> (foo y-bar y-baz) ...) is intended to match a foo struct or define a foo
> function. Also, optional parameters and struct matching look the same. I
> wrote a `defun' macro that solves the latter problem - it even does currying
> and keywords - but I can't say that I like it yet.)
>
> _________________________________________________
>  For list-related administrative tasks:
>  http://lists.racket-lang.org/listinfo/users
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.