From: Russell Wallace
Subject: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <9461cc05-6416-4953-9f26-57ab9da4aff2@s1g2000prg.googlegroups.com>
There is a job I need to do for which DESTRUCTURING-BIND would be
perfect, except I need to fail gracefully, that is, in the event of a
structural mismatch, ignore extra data and set extra variables to nil,
rather than raise an error. Is there a way to do this?

I suppose just catching the error won't be enough, because it will
leave extra variables in undefined state?

I could try writing my own, I suppose it can be written as a macro? Or
has someone else already written an error-free version that I could
use?

From: Pascal J. Bourguignon
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <873ahtmjwj.fsf@hubble.informatimago.com>
Russell Wallace <···············@gmail.com> writes:

> There is a job I need to do for which DESTRUCTURING-BIND would be
> perfect, except I need to fail gracefully, that is, in the event of a
> structural mismatch, ignore extra data and set extra variables to nil,
> rather than raise an error. Is there a way to do this?


C/USER[41]> (mapc (lambda (test)
                    (destructuring-bind (&optional a b c &rest too-much) test
                      (declare (ignore too-much))
                      (print (list a b c))))
                  '(() (1) (1 2) (1 2 3) (1 2 3 4)))

(NIL NIL NIL) 
(1 NIL NIL) 
(1 2 NIL) 
(1 2 3) 
(1 2 3) 
(NIL (1) (1 2) (1 2 3) (1 2 3 4))
C/USER[42]> 


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"I have challenged the entire quality assurance team to a Bat-Leth
contest.  They will not concern us again."
From: Russell Wallace
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <89ef260f-f987-489f-b8ef-0ad5f9d57500@s9g2000prg.googlegroups.com>
Perfect, thanks!
From: Pascal Costanza
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <6o7n82F28vqnU1@mid.individual.net>
Pascal J. Bourguignon wrote:
> Russell Wallace <···············@gmail.com> writes:
> 
>> There is a job I need to do for which DESTRUCTURING-BIND would be
>> perfect, except I need to fail gracefully, that is, in the event of a
>> structural mismatch, ignore extra data and set extra variables to nil,
>> rather than raise an error. Is there a way to do this?
> 
> 
> C/USER[41]> (mapc (lambda (test)
>                     (destructuring-bind (&optional a b c &rest too-much) test
>                       (declare (ignore too-much))
>                       (print (list a b c))))
>                   '(() (1) (1 2) (1 2 3) (1 2 3 4)))

Sidenote: More often than not, destructuring-bind is not necessary, but 
a plain old lambda will do just as fine. Consider:

(mapc (lambda (&optional a b c &rest too-much)
         ...)
       ...)

I have the impression that lambda expressions are typically more 
efficient, probably because they are usually compiled, while 
destructuring-bind usually seems to do its main job at runtime.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Russell Wallace
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <261ec57a-c5dc-4de4-ab5d-18c9898789dc@e38g2000prn.googlegroups.com>
I ended up using apply, in a style similar to the one posted for
destructuring-bind. I've written parsers before in C, but the code I
ended up with here (top level of a parser for the TPTP format) is a
very nice example of code that, not only had I not been able to write
without Lisp, but that it had not occurred to me to want to write
without Lisp.

(defun cnf-annotated (input &optional name role expr &rest extra)
  (declare (ignore extra))
  (when
    (or
      (eq (input-selection input) t)
      (find name (input-selection input)))
    (new-clause
      (or-literals expr)
      :from
        (make-source
          :file (input-file input)
          :name name
          :role role))))

(defun include (input &optional file (selection t) &rest extra)
  (declare (ignore extra))
  (parse-file
    (splice *include* file)
    (intersection-t (input-selection input) selection)))

(defun parse-formula (input)
  (let ((e (parse-expr input)))
    (case (car e)
      (|cnf|
        (apply #'cnf-annotated input (cdr e)))
      (|include|
        (apply #'include input (cdr e)))
      (otherwise
        (read-error input "cnf formula expected")))))
From: William James
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <gfn0dn$1bk$1@aioe.org>
Pascal J. Bourguignon wrote:

> Russell Wallace <···············@gmail.com> writes:
> 
> > There is a job I need to do for which DESTRUCTURING-BIND would be
> > perfect, except I need to fail gracefully, that is, in the event of
> > a structural mismatch, ignore extra data and set extra variables to
> > nil, rather than raise an error. Is there a way to do this?
> 
> 
> C/USER[41]> (mapc (lambda (test)
>                     (destructuring-bind (&optional a b c &rest
> too-much) test                       (declare (ignore too-much))
>                       (print (list a b c))))
>                   '(() (1) (1 2) (1 2 3) (1 2 3 4)))
> 
> (NIL NIL NIL) 
> (1 NIL NIL) 
> (1 2 NIL) 
> (1 2 3) 
> (1 2 3) 
> (NIL (1) (1 2) (1 2 3) (1 2 3 4))
> C/USER[42]> 

Ruby:

[[],[1],[1,2],[1,2,3]].map{|a,b| p [a,b]}
[nil, nil]
[1, nil]
[1, 2]
[1, 2]
From: Kaz Kylheku
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <20081118154813.701@gmail.com>
On 2008-11-15, William James <·········@yahoo.com> wrote:
> Pascal J. Bourguignon wrote:
>
>> Russell Wallace <···············@gmail.com> writes:
>> 
>> > There is a job I need to do for which DESTRUCTURING-BIND would be
>> > perfect, except I need to fail gracefully, that is, in the event of
>> > a structural mismatch, ignore extra data and set extra variables to
>> > nil, rather than raise an error. Is there a way to do this?
>> 
>> 
>> C/USER[41]> (mapc (lambda (test)
>>                     (destructuring-bind (&optional a b c &rest
>> too-much) test                       (declare (ignore too-much))
>>                       (print (list a b c))))
>>                   '(() (1) (1 2) (1 2 3) (1 2 3 4)))
>> 
>> (NIL NIL NIL) 
>> (1 NIL NIL) 
>> (1 2 NIL) 
>> (1 2 3) 
>> (1 2 3) 
>> (NIL (1) (1 2) (1 2 3) (1 2 3 4))
>> C/USER[42]> 
>
> Ruby:
>
> [[],[1],[1,2],[1,2,3]].map{|a,b| p [a,b]}

I.e. Ruby silently screws you if you accidentally miss a function argument,
or supply too many.

And don't forget that if you ever get a compiler one day, compiled functions
will have to preserve today's evaluated semantics. 

Or, wait, no. Matz doesn't care about backward compatibility.
From: =?UTF-8?B?QW5kcsOpIFRoaWVtZQ==?=
Subject: Re: Error-free DESTRUCTURING-BIND
Date: 
Message-ID: <ggmqrf$dg1$1@news.motzarella.org>
William James schrieb:
> Pascal J. Bourguignon wrote:
> 
>> Russell Wallace <···············@gmail.com> writes:
>>
>>> There is a job I need to do for which DESTRUCTURING-BIND would be
>>> perfect, except I need to fail gracefully, that is, in the event of
>>> a structural mismatch, ignore extra data and set extra variables to
>>> nil, rather than raise an error. Is there a way to do this?
>>
>> C/USER[41]> (mapc (lambda (test)
>>                     (destructuring-bind (&optional a b c &rest
>> too-much) test                       (declare (ignore too-much))
>>                       (print (list a b c))))
>>                   '(() (1) (1 2) (1 2 3) (1 2 3 4)))
>>
>> (NIL NIL NIL) 
>> (1 NIL NIL) 
>> (1 2 NIL) 
>> (1 2 3) 
>> (1 2 3) 
>> (NIL (1) (1 2) (1 2 3) (1 2 3 4))
>> C/USER[42]> 
> 
> Ruby:
> 
> [[], [1], [1, 2], [1, 2, 3]].map{|a, b| p [a, b]}
> [nil, nil]
> [1, nil]
> [1, 2]
> [1, 2]


Clojure (both examples):
user> (doseq [[a b c] '(() (1) (1 2) (1 2 3) (1 2 3 4))]
         (println [a b c]))
[nil nil nil]
[1 nil nil]
[1 2 nil]
[1 2 3]
[1 2 3]
nil
user> (doseq [[a b] [[] [1] [1 2] [1 2 3]]] (prn [a b]))
[nil nil]
[1 nil]
[1 2]
[1 2]
nil

As we see: in Lisp this is not much longer.

(doseq [[a b] [[] [1] [1 2] [1 2 3]]] (prn [a b]))
vs
[[], [1], [1, 2], [1, 2, 3]].map{|a, b| p [a, b]}

Is map used in Ruby also for doing side effects?
For a demonstration this is fine, but I think in production code
one tells the reader of the code something when calling map.


André
-- 
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/