The current DESTRUCTURING-BIND could be much more useful if you could pull apart objects and arrays. CoffeeScript has a great mechanism for this (http://coffeescript.org/#destructuring). Below is an example of what this macro might look like in parenscript. Let me know your thoughts.
David
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
Hi David,
Parenscript does have such an operator, called BIND. Since it hasn't been documented yet, here are some examples. The idea is that you use keywords to bind to object properties and ordinary symbols to bind to array elements. Let's look at arrays first. A simple example:
(bind (a b c) '(10 20 30) (list c b a)) => (30 20 10)
Bind elements to NIL to ignore them:
(bind (a nil c) '(10 20 30) (list c a)) => (30 10)
To ignore the tail of an array, just omit it:
(bind (a b) '(10 20 30 40) (list b a)) => (20 10)
You can use &rest (or .) in the destructuring list:
(bind (a &rest others) '(10 20 30) (list others a)) => ((20 30) 10)
(bind (a . others) '(10 20 30) (list others a)) => same
You can nest array bindings:
(bind (a (b (c d))) '(10 (20 (30 40))) (list d c b a)) => (40 30 20 10)
Now for objects. A simple example:
(bind (:a :b :c) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
Since the properties are named, order doesn't matter:
(bind (:a :c :b) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
If you want to bind to a property using a different name, you can use a binding pair instead of a keyword:
(bind ((my-name :original)) (create :original 10) (list my-name)) => (10)
I use that sparingly because the extra parens can impede readability, but it's handy to avoid naming collisions:
(let ((original 99)) (bind ((mine :original)) (create :original 10) (list original mine))) => (99 10)
You can bind to an object inside an array:
(bind (a (:b)) (list 10 (create :b 20)) (list b a)) => (20 10)
However, you can't bind to an array inside an object, or an object inside an object, in a single BIND form — you have to use two:
(bind (:a) (make :a '(10 20 30)) (bind (nil b c) a (list c b))) => (30 20)
(bind (:a) (make :a (make :b 20 :c 30)) (bind (:b :c) a (list c b))) => (30 20)
That's because the notation doesn't seem to allow for any unambiguous way to do such nesting. (If you can think of one, please show us some examples.) This is the chief difference from the notation in your example, which adds additional syntax to support more complex destructuring lists. The tradeoff here is that BIND, lacking syntax, handles the simplest and most common cases more elegantly.
There is a form BIND* which allows multiple binds in a row to avoid unwanted indentation:
(bind* ((a b) '(10 20) (:c) (make :c 30)) (list a b c)) => (10 20 30)
It simply takes a list of binding pairs and turns them into a nested series of BIND forms.
Finally, note that if you mix keyword and non-keyword symbols in a binding list, it's considered an array binding and not an object binding:
(bind (:a b) '(10 20) (list b a)) => (20 10)
(bind (:a b) (make :a 10 :b 20) (list b a)) => (undefined undefined)
But it's bad practice to mix keywords and non-keywords in the same binding list. Perhaps BIND should throw an error when given such input.
So now let's look at your example:
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
As I mentioned, the main difference is that PS's BIND doesn't use special syntax like :obj and :arr to convey what's being destructured. No doubt tastes will differ on this. In any case, to translate your example, we'll have to use nested BINDs:
(bind (:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (bind (:firstname) name (bind (first-like) likes (+ "Your name is " firstname " and you like " first-like)))) => "Your name is Joe and you like programming"
We can do the same thing with BIND* like this:
(bind* ((:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (:firstname) name (first-like) likes) (+ "Your name is " firstname " and you like " first-like)) => "Your name is Joe and you like programming"
It would be a straightforward exercise to write your D-BIND as a macro that interprets the :obj and :arr directives, uses gensyms to create intermediate bindings, and emits the above nested BIND form.
If you find anything else in CoffeeScript that you think would be a natural fit for PS, please post it here.
Daniel
Vladimir -- writing the below made me think of whether we should incorporate it into the PS docs somehow, with whatever changes are needed to fit the docs' conventions. Do you agree? What would be the best way to do this?
We really should document LOOP as well, especially since it has the :MAP and :OF extensions for working with JS objects.
On Tue, Jan 15, 2013 at 1:20 PM, Daniel Gackle danielgackle@gmail.comwrote:
Hi David,
Parenscript does have such an operator, called BIND. Since it hasn't been documented yet, here are some examples. The idea is that you use keywords to bind to object properties and ordinary symbols to bind to array elements. Let's look at arrays first. A simple example:
(bind (a b c) '(10 20 30) (list c b a)) => (30 20 10)
Bind elements to NIL to ignore them:
(bind (a nil c) '(10 20 30) (list c a)) => (30 10)
To ignore the tail of an array, just omit it:
(bind (a b) '(10 20 30 40) (list b a)) => (20 10)
You can use &rest (or .) in the destructuring list:
(bind (a &rest others) '(10 20 30) (list others a)) => ((20 30) 10)
(bind (a . others) '(10 20 30) (list others a)) => same
You can nest array bindings:
(bind (a (b (c d))) '(10 (20 (30 40))) (list d c b a)) => (40 30 20 10)
Now for objects. A simple example:
(bind (:a :b :c) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
Since the properties are named, order doesn't matter:
(bind (:a :c :b) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
If you want to bind to a property using a different name, you can use a binding pair instead of a keyword:
(bind ((my-name :original)) (create :original 10) (list my-name)) => (10)
I use that sparingly because the extra parens can impede readability, but it's handy to avoid naming collisions:
(let ((original 99)) (bind ((mine :original)) (create :original 10) (list original mine))) => (99 10)
You can bind to an object inside an array:
(bind (a (:b)) (list 10 (create :b 20)) (list b a)) => (20 10)
However, you can't bind to an array inside an object, or an object inside an object, in a single BIND form — you have to use two:
(bind (:a) (make :a '(10 20 30)) (bind (nil b c) a (list c b))) => (30 20)
(bind (:a) (make :a (make :b 20 :c 30)) (bind (:b :c) a (list c b))) => (30 20)
That's because the notation doesn't seem to allow for any unambiguous way to do such nesting. (If you can think of one, please show us some examples.) This is the chief difference from the notation in your example, which adds additional syntax to support more complex destructuring lists. The tradeoff here is that BIND, lacking syntax, handles the simplest and most common cases more elegantly.
There is a form BIND* which allows multiple binds in a row to avoid unwanted indentation:
(bind* ((a b) '(10 20) (:c) (make :c 30)) (list a b c)) => (10 20 30)
It simply takes a list of binding pairs and turns them into a nested series of BIND forms.
Finally, note that if you mix keyword and non-keyword symbols in a binding list, it's considered an array binding and not an object binding:
(bind (:a b) '(10 20) (list b a)) => (20 10)
(bind (:a b) (make :a 10 :b 20) (list b a)) => (undefined undefined)
But it's bad practice to mix keywords and non-keywords in the same binding list. Perhaps BIND should throw an error when given such input.
So now let's look at your example:
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
As I mentioned, the main difference is that PS's BIND doesn't use special syntax like :obj and :arr to convey what's being destructured. No doubt tastes will differ on this. In any case, to translate your example, we'll have to use nested BINDs:
(bind (:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (bind (:firstname) name (bind (first-like) likes (+ "Your name is " firstname " and you like " first-like)))) => "Your name is Joe and you like programming"
We can do the same thing with BIND* like this:
(bind* ((:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (:firstname) name (first-like) likes) (+ "Your name is " firstname " and you like " first-like)) => "Your name is Joe and you like programming"
It would be a straightforward exercise to write your D-BIND as a macro that interprets the :obj and :arr directives, uses gensyms to create intermediate bindings, and emits the above nested BIND form.
If you find anything else in CoffeeScript that you think would be a natural fit for PS, please post it here.
Daniel
I'm all for documenting LOOP extensions. I was actually thinking of deprecating BIND and BIND* since they're non-cl. I propose this: split off CL and non-CL stuff into two different packages, that are both imported and re-exported from the PARENSCRIPT package. The non-CL stuff should also, whenever possible, define macros/functions with equivalent functionality in Common Lisp, to provide an easy way to run PS code in CL.
Thoughts?
Vladimir
On Tue, Jan 15, 2013 at 12:30 PM, Daniel Gackle danielgackle@gmail.com wrote:
Vladimir -- writing the below made me think of whether we should incorporate it into the PS docs somehow, with whatever changes are needed to fit the docs' conventions. Do you agree? What would be the best way to do this?
We really should document LOOP as well, especially since it has the :MAP and :OF extensions for working with JS objects.
On Tue, Jan 15, 2013 at 1:20 PM, Daniel Gackle danielgackle@gmail.com wrote:
Hi David,
Parenscript does have such an operator, called BIND. Since it hasn't been documented yet, here are some examples. The idea is that you use keywords to bind to object properties and ordinary symbols to bind to array elements. Let's look at arrays first. A simple example:
(bind (a b c) '(10 20 30) (list c b a)) => (30 20 10)
Bind elements to NIL to ignore them:
(bind (a nil c) '(10 20 30) (list c a)) => (30 10)
To ignore the tail of an array, just omit it:
(bind (a b) '(10 20 30 40) (list b a)) => (20 10)
You can use &rest (or .) in the destructuring list:
(bind (a &rest others) '(10 20 30) (list others a)) => ((20 30) 10)
(bind (a . others) '(10 20 30) (list others a)) => same
You can nest array bindings:
(bind (a (b (c d))) '(10 (20 (30 40))) (list d c b a)) => (40 30 20 10)
Now for objects. A simple example:
(bind (:a :b :c) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
Since the properties are named, order doesn't matter:
(bind (:a :c :b) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
If you want to bind to a property using a different name, you can use a binding pair instead of a keyword:
(bind ((my-name :original)) (create :original 10) (list my-name)) => (10)
I use that sparingly because the extra parens can impede readability, but it's handy to avoid naming collisions:
(let ((original 99)) (bind ((mine :original)) (create :original 10) (list original mine))) => (99 10)
You can bind to an object inside an array:
(bind (a (:b)) (list 10 (create :b 20)) (list b a)) => (20 10)
However, you can't bind to an array inside an object, or an object inside an object, in a single BIND form — you have to use two:
(bind (:a) (make :a '(10 20 30)) (bind (nil b c) a (list c b))) => (30 20)
(bind (:a) (make :a (make :b 20 :c 30)) (bind (:b :c) a (list c b))) => (30 20)
That's because the notation doesn't seem to allow for any unambiguous way to do such nesting. (If you can think of one, please show us some examples.) This is the chief difference from the notation in your example, which adds additional syntax to support more complex destructuring lists. The tradeoff here is that BIND, lacking syntax, handles the simplest and most common cases more elegantly.
There is a form BIND* which allows multiple binds in a row to avoid unwanted indentation:
(bind* ((a b) '(10 20) (:c) (make :c 30)) (list a b c)) => (10 20 30)
It simply takes a list of binding pairs and turns them into a nested series of BIND forms.
Finally, note that if you mix keyword and non-keyword symbols in a binding list, it's considered an array binding and not an object binding:
(bind (:a b) '(10 20) (list b a)) => (20 10)
(bind (:a b) (make :a 10 :b 20) (list b a)) => (undefined undefined)
But it's bad practice to mix keywords and non-keywords in the same binding list. Perhaps BIND should throw an error when given such input.
So now let's look at your example:
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
As I mentioned, the main difference is that PS's BIND doesn't use special syntax like :obj and :arr to convey what's being destructured. No doubt tastes will differ on this. In any case, to translate your example, we'll have to use nested BINDs:
(bind (:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (bind (:firstname) name (bind (first-like) likes (+ "Your name is " firstname " and you like " first-like)))) => "Your name is Joe and you like programming"
We can do the same thing with BIND* like this:
(bind* ((:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (:firstname) name (first-like) likes) (+ "Your name is " firstname " and you like " first-like)) => "Your name is Joe and you like programming"
It would be a straightforward exercise to write your D-BIND as a macro that interprets the :obj and :arr directives, uses gensyms to create intermediate bindings, and emits the above nested BIND form.
If you find anything else in CoffeeScript that you think would be a natural fit for PS, please post it here.
Daniel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
I think it makes sense to put BIND in a more outer circle, so to speak. It's definitely more of a library macro, not any kind of standard.
I'm not sure I understand this, though:
The non-CL stuff should also, whenever possible, define macros/functions with equivalent functionality in Common Lisp, to provide an easy way to run PS code in CL.
Do you mean that there should be a CL implementation of (to use the same example) BIND?
Dan
On Thu, Jan 17, 2013 at 12:41 PM, Vladimir Sedach vsedach@gmail.com wrote:
I'm all for documenting LOOP extensions. I was actually thinking of deprecating BIND and BIND* since they're non-cl. I propose this: split off CL and non-CL stuff into two different packages, that are both imported and re-exported from the PARENSCRIPT package. The non-CL stuff should also, whenever possible, define macros/functions with equivalent functionality in Common Lisp, to provide an easy way to run PS code in CL.
Thoughts?
Vladimir
On Tue, Jan 15, 2013 at 12:30 PM, Daniel Gackle danielgackle@gmail.com wrote:
Vladimir -- writing the below made me think of whether we should incorporate it into the PS docs somehow, with whatever changes are needed to fit the docs' conventions. Do you agree? What would be the best way to do this?
We really should document LOOP as well, especially since it has the :MAP and :OF extensions for working with JS objects.
On Tue, Jan 15, 2013 at 1:20 PM, Daniel Gackle danielgackle@gmail.com wrote:
Hi David,
Parenscript does have such an operator, called BIND. Since it hasn't been documented yet, here are some examples. The idea is that you use keywords to bind to object properties and ordinary symbols to bind to array elements. Let's look at arrays first. A simple example:
(bind (a b c) '(10 20 30) (list c b a)) => (30 20 10)
Bind elements to NIL to ignore them:
(bind (a nil c) '(10 20 30) (list c a)) => (30 10)
To ignore the tail of an array, just omit it:
(bind (a b) '(10 20 30 40) (list b a)) => (20 10)
You can use &rest (or .) in the destructuring list:
(bind (a &rest others) '(10 20 30) (list others a)) => ((20 30) 10)
(bind (a . others) '(10 20 30) (list others a)) => same
You can nest array bindings:
(bind (a (b (c d))) '(10 (20 (30 40))) (list d c b a)) => (40 30 20 10)
Now for objects. A simple example:
(bind (:a :b :c) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
Since the properties are named, order doesn't matter:
(bind (:a :c :b) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
If you want to bind to a property using a different name, you can use a binding pair instead of a keyword:
(bind ((my-name :original)) (create :original 10) (list my-name)) => (10)
I use that sparingly because the extra parens can impede readability, but it's handy to avoid naming collisions:
(let ((original 99)) (bind ((mine :original)) (create :original 10) (list original mine))) => (99 10)
You can bind to an object inside an array:
(bind (a (:b)) (list 10 (create :b 20)) (list b a)) => (20 10)
However, you can't bind to an array inside an object, or an object inside an object, in a single BIND form — you have to use two:
(bind (:a) (make :a '(10 20 30)) (bind (nil b c) a (list c b))) => (30 20)
(bind (:a) (make :a (make :b 20 :c 30)) (bind (:b :c) a (list c b))) => (30 20)
That's because the notation doesn't seem to allow for any unambiguous way to do such nesting. (If you can think of one, please show us some examples.) This is the chief difference from the notation in your example, which adds additional syntax to support more complex destructuring lists. The tradeoff here is that BIND, lacking syntax, handles the simplest and most common cases more elegantly.
There is a form BIND* which allows multiple binds in a row to avoid unwanted indentation:
(bind* ((a b) '(10 20) (:c) (make :c 30)) (list a b c)) => (10 20 30)
It simply takes a list of binding pairs and turns them into a nested series of BIND forms.
Finally, note that if you mix keyword and non-keyword symbols in a binding list, it's considered an array binding and not an object binding:
(bind (:a b) '(10 20) (list b a)) => (20 10)
(bind (:a b) (make :a 10 :b 20) (list b a)) => (undefined undefined)
But it's bad practice to mix keywords and non-keywords in the same binding list. Perhaps BIND should throw an error when given such input.
So now let's look at your example:
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
As I mentioned, the main difference is that PS's BIND doesn't use special syntax like :obj and :arr to convey what's being destructured. No doubt tastes will differ on this. In any case, to translate your example, we'll have to use nested BINDs:
(bind (:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (bind (:firstname) name (bind (first-like) likes (+ "Your name is " firstname " and you like " first-like)))) => "Your name is Joe and you like programming"
We can do the same thing with BIND* like this:
(bind* ((:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (:firstname) name (first-like) likes) (+ "Your name is " firstname " and you like " first-like)) => "Your name is Joe and you like programming"
It would be a straightforward exercise to write your D-BIND as a macro that interprets the :obj and :arr directives, uses gensyms to create intermediate bindings, and emits the above nested BIND form.
If you find anything else in CoffeeScript that you think would be a natural fit for PS, please post it here.
Daniel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
Come to think of it, there's a problem. PS's LOOP uses BIND. It's super handy and I rely on it all the time to do things like (loop :for (a (:b)) :in c...). I suppose there are a few options for dealing with this but the easiest would be to keep (or move) LOOP into the same package as BIND.
On Thu, Jan 17, 2013 at 3:13 PM, Daniel Gackle danielgackle@gmail.comwrote:
I think it makes sense to put BIND in a more outer circle, so to speak. It's definitely more of a library macro, not any kind of standard.
I'm not sure I understand this, though:
The non-CL stuff should also, whenever possible, define macros/functions with equivalent functionality in Common Lisp, to provide an easy way to run PS code in CL.
Do you mean that there should be a CL implementation of (to use the same example) BIND?
Dan
On Thu, Jan 17, 2013 at 12:41 PM, Vladimir Sedach vsedach@gmail.comwrote:
I'm all for documenting LOOP extensions. I was actually thinking of deprecating BIND and BIND* since they're non-cl. I propose this: split off CL and non-CL stuff into two different packages, that are both imported and re-exported from the PARENSCRIPT package. The non-CL stuff should also, whenever possible, define macros/functions with equivalent functionality in Common Lisp, to provide an easy way to run PS code in CL.
Thoughts?
Vladimir
On Tue, Jan 15, 2013 at 12:30 PM, Daniel Gackle danielgackle@gmail.com wrote:
Vladimir -- writing the below made me think of whether we should incorporate it into the PS docs somehow, with whatever changes are needed to fit the docs' conventions. Do you agree? What would be the best way to do this?
We really should document LOOP as well, especially since it has the :MAP and :OF extensions for working with JS objects.
On Tue, Jan 15, 2013 at 1:20 PM, Daniel Gackle danielgackle@gmail.com wrote:
Hi David,
Parenscript does have such an operator, called BIND. Since it hasn't been documented yet, here are some examples. The idea is that you use keywords to bind to object properties and ordinary symbols to bind to array elements. Let's look at arrays first. A simple example:
(bind (a b c) '(10 20 30) (list c b a)) => (30 20 10)
Bind elements to NIL to ignore them:
(bind (a nil c) '(10 20 30) (list c a)) => (30 10)
To ignore the tail of an array, just omit it:
(bind (a b) '(10 20 30 40) (list b a)) => (20 10)
You can use &rest (or .) in the destructuring list:
(bind (a &rest others) '(10 20 30) (list others a)) => ((20 30) 10)
(bind (a . others) '(10 20 30) (list others a)) => same
You can nest array bindings:
(bind (a (b (c d))) '(10 (20 (30 40))) (list d c b a)) => (40 30 20 10)
Now for objects. A simple example:
(bind (:a :b :c) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
Since the properties are named, order doesn't matter:
(bind (:a :c :b) (create :a 10 :b 20 :c 30) (list c b a)) => (30 20 10)
If you want to bind to a property using a different name, you can use a binding pair instead of a keyword:
(bind ((my-name :original)) (create :original 10) (list my-name)) => (10)
I use that sparingly because the extra parens can impede readability, but it's handy to avoid naming collisions:
(let ((original 99)) (bind ((mine :original)) (create :original 10) (list original mine))) => (99 10)
You can bind to an object inside an array:
(bind (a (:b)) (list 10 (create :b 20)) (list b a)) => (20 10)
However, you can't bind to an array inside an object, or an object inside an object, in a single BIND form — you have to use two:
(bind (:a) (make :a '(10 20 30)) (bind (nil b c) a (list c b))) => (30 20)
(bind (:a) (make :a (make :b 20 :c 30)) (bind (:b :c) a (list c b))) => (30 20)
That's because the notation doesn't seem to allow for any unambiguous way to do such nesting. (If you can think of one, please show us some examples.) This is the chief difference from the notation in your example, which adds additional syntax to support more complex destructuring lists. The tradeoff here is that BIND, lacking syntax, handles the simplest and most common cases more elegantly.
There is a form BIND* which allows multiple binds in a row to avoid unwanted indentation:
(bind* ((a b) '(10 20) (:c) (make :c 30)) (list a b c)) => (10 20 30)
It simply takes a list of binding pairs and turns them into a nested series of BIND forms.
Finally, note that if you mix keyword and non-keyword symbols in a binding list, it's considered an array binding and not an object binding:
(bind (:a b) '(10 20) (list b a)) => (20 10)
(bind (:a b) (make :a 10 :b 20) (list b a)) => (undefined undefined)
But it's bad practice to mix keywords and non-keywords in the same binding list. Perhaps BIND should throw an error when given such input.
So now let's look at your example:
(d-bind (:obj name (:obj firstname lastname) likes (:arr first-like second-like)) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (alert (+ "Your name is " firstname " and you like " first-like)))
As I mentioned, the main difference is that PS's BIND doesn't use special syntax like :obj and :arr to convey what's being destructured. No doubt tastes will differ on this. In any case, to translate your example, we'll have to use nested BINDs:
(bind (:name :likes) (create :name (create :firstname "Joe" :lastname "Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (bind (:firstname) name (bind (first-like) likes (+ "Your name is " firstname " and you like " first-like)))) => "Your name is Joe and you like programming"
We can do the same thing with BIND* like this:
(bind* ((:name :likes) (create :name (create :firstname "Joe"
:lastname
"Blo") :occupation "Web Developer" :likes '("programming" "woodworking" "cycling")) (:firstname) name (first-like) likes) (+ "Your name is " firstname " and you like " first-like)) => "Your name is Joe and you like programming"
It would be a straightforward exercise to write your D-BIND as a macro that interprets the :obj and :arr directives, uses gensyms to create intermediate bindings, and emits the above nested BIND form.
If you find anything else in CoffeeScript that you think would be a natural fit for PS, please post it here.
Daniel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel mailing list parenscript-devel@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
parenscript-devel@common-lisp.net