On Sat, 2 Sep 2006, John Resig wrote:

>> Lately I've been experimenting with Parenscript, which is a 
>> Lisp-to-JavaScript translator that allows you to write macros; if 
>> anyone's interested I can post some sequencing macro code I've been 
>> working on...
>
> Go ahead! I'm interested :-)

Right on.

So, for a simple example, here's a snippet of Parenscript code that 
creates a DIV, puts some text in it, and fades it in, out, and back in 
again:

   (.append #$"body" (html ((:div :id "mydiv"
                                  :style (css-inline :background "white"))
                            "Hello, world!")))
   (seq
    (.fade-in #$"div #mydiv" "slow")
    (.fade-out #$"div #mydiv" "slow")
    (.fade-in #$"div #mydiv" "fast")))

A few notes about the syntax: The "#$" is a reader-macro I wrote for for 
convenience; #$"body" gets transformed into ($ "body"). I haven't yet 
decided if this is a good thing or not. ;) In Parenscript, functions that 
start with a "." such as ".append" and ".fade-in", above, are treated as 
method calls. Capitalization is translated by Parenscript from Lisp-style 
to JavaScript-style, which is why the jQuery methods end up looking like 
".fade-in". The "html" and "css-inline" macros are part of Parenscript, 
and allow you to generate JavaScript that builds HTML and CSS from 
s-expressions.

The sequencing macro is "seq". The above "seq" call gets transformed into 
the following:

   (.fade-in #$"div #mydiv" "slow"
      (lambda ()
         (.fade-out #$"div #mydiv" "slow"
            (lambda ()
               (.fade-in #$"div #mydiv" "fast")))))

The resulting JavaScript is this:

   function main() {
     $('body').append('<div id="mydiv" style="' + ('background:white')
                      + '">Hello, world!</div>');
     $('div #mydiv').fadeIn('slow',
                            function () {
                              $('div #mydiv').fadeOut('slow',
                                                      function () {
                                                        $('div 
#mydiv').fadeIn('fast');
                                                      });
                            });
   }

So, this has similar effects to what I think you're trying to achieve with 
method chaining, but is more general because you are not limited to a 
single jQuery object for the dispatch of each chained operation.

Here's my working definition of "seq":

   (defjsmacro seq (&rest forms)
     (labels
         ((aux (lst)
               (cond
                ((null lst) nil)
                ((and (consp lst) (not (cdr lst))) (car lst))
                (t (append (car lst) (list `(lambda () ,(aux (cdr lst)))))))))
       (aux forms)))

I'd like to extend it to allow inserting ordinary code in the middle of 
the sequence with a "par" construct - I'm lifting this terminology out of 
an interesting but obscure concurrent language called Occam:

   http://en.wikipedia.org/wiki/Occam_programming_language

Ironically, in an event-driven model, "par" is really the default 
behavior. When working with background functions, everything is parallel; 
you have to really work at making things sequential.

Dave

_______________________________________________
jQuery mailing list
discuss@jquery.com
http://jquery.com/discuss/

Reply via email to