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