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?
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."
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/
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]
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.
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/