guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Shorter lambda expressions


From: Panicz Maciej Godek
Subject: Re: Shorter lambda expressions
Date: Thu, 23 Jan 2014 09:17:02 +0100

Hi!

2014/1/23 Mark H Weaver <address@hidden>:
> Hello all,
>
> For a short time I liked 'cut' from SRFI-26, but I soon became
> frustrated by its limitations, most notably not being able to reference
> the arguments out of order or within nested expressions.  I don't like
> the inconsistent style that results when I use 'cut' wherever possible
> and 'lambda' everywhere else.  So I just stopped using it altogether.
[...]

Before getting acquainted with SRFI-26, I came up with something
similar. It uses define-macro, because I didn't know syntax-case back
then, but I eventually stopped using it, since it was a little bit
confusing. It solved the problem by allowing numbered placeholders, so
e.g.
(\ + _1 _10) created a function of ten arguments which added its first
argument to its tenth argument, skipping all the others. There was
also a general placeholder, _, which behaved like SRFI-26's <>, so for
instance
(\ + _ _)
was an equivalent of
(\ + _1 _2)
but I eventually started to find it a little confusing, because the
same symbol refered to another entity.
Also the choice of symbol "\" was unfortunate, as it made the syntax
unportable among schemes (certain implementations would require to
write "\\" to get a backslash).

As far as I remember (I'd have to analyze the code to make sure), it
did support nested expressions. Also, after some time, I added another
placeholder ... for variadic arguments, which behaved more or less
like <...> form SRFI-26.

I think it would be best to extend SRFI-26 with the option of using
<1>, <2>, ... placeholders, where the resulting lambda would get the
arity indicated by the highest placeholder. Also, it should support
nested expressions.
Personally, I'd prefer it over the Gauche-style extension.

(define-macro (\ f . args)
  (let* ((prefix "_")
         (placeholder '_)
         (ellipsis '...)
         (rest (if (equal? (last args) ellipsis) ellipsis '()))
         (args (if (symbol? rest) (drop-right args 1) args))
         (max-arg 0)
         (next-arg
          (lambda ()
            (set! max-arg (+ max-arg 1))
            (string->symbol (string-append
                             prefix (number->string max-arg))))))
    (letrec ((process-arg
              (lambda(arg)
                (cond ((eq? arg placeholder)
                       (next-arg))
                      ((and-let*
                           (((symbol? arg))
                            (arg-string (symbol->string arg))
                            (match-struct (string-match
                                           (string-append
                                            "^"
                                            (regexp-quote prefix)
                                            "([0-9]+)$")
                                             arg-string))
                            (number (string->number
                                     (match:substring
                                      match-struct 1))))
                         (if (> number max-arg)
                             (set! max-arg number))
                         #t)
                       arg)
                      ((and (list? arg)
                            (not (null? arg))
                            (not (memq (first arg) '(\ quote))))
                       (map process-arg arg))
                      (else arg)))))
      (let ((args (map process-arg args)))
        `(lambda ,(append
                   (map (lambda (n)
                          (string->symbol
                           (string-append prefix (number->string n))))
                        (iota max-arg 1))
                   rest)
           ,(if (symbol? rest)
                `(apply ,f ,@args ,rest)
                `(,f ,@args)))))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]