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 <[email protected]> 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 <[email protected]> > 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 <[email protected]> > > 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 > > [email protected] > > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel > > > > _______________________________________________ > parenscript-devel mailing list > [email protected] > http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel >
_______________________________________________ parenscript-devel mailing list [email protected] http://lists.common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel
