<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Hello everyone,<div class=""><br class=""></div><div class="">How’s it going?</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">What is a good path forward for adding (tagbody …) to ParenScript?</div><div class="">Package “parenscript-tagbody-go” [1] currently provides a beta-version implementation using (defpsmacro …).</div><div class="">It seems like originally, even classes and objects were user-land macro packages outside of lisp implementations.</div><div class="">Nevertheless, integration into package “parenscript” seems to help with usability and discoverability.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">The implementation seems to be mostly working.  Jason’s bug report seem to be fixed.</div><div class="">Two more bugs concerning duplicate labels and empty (tagbody) forms were fixed as well.</div><div class=""><br class=""></div><div class="">There is now also a preliminary package “parenscript-series” [2] that already offers</div><div class="">a custom js array scanner and two js array collectors.  One collector pushes the other unshifts.</div><div class="">The push collector was surprisingly difficult to implement, because SERIES macroexpands (push …) in (parenscript:chain arr (parenscript:push elem)) to whatever the current lisp implementation does. On SBCL 2.3.1, for example, it ends up with some SBCL internal form.</div><div class="">The solution is (parenscript:funcall (parenscript:getprop arr (quote push)) elem).</div><div class=""><br class=""></div><div class="">The biggest problems with collectors and scanners were unimplemented CL forms in ParenScript, e.g. (the …) and (make-list …).</div><div class="">It seems to be less work to reimplement the few SERIES operations that use too many of those CL features compared to porting all the missing CL features that the CL SERIES expanders rely on.</div><div class=""><br class=""></div><div class="">With this array scanner and these two array collectors, (series:map-fn …) gets translated to JavaScript correctly, without further intervention.</div><div class="">So the following works, now that (tagbody …) can be pipelined and compiled:</div><div class=""><br class=""></div><div class=""><pre class=""><code class="">(ps*
</code>  (series-expand:series-expand
    '(collect-js-array-push
       (map-fn T (lambda (x) (* x 2))
          (map-fn T #’1+
             (scan-js-array '(1 2 3))))))</pre><pre class="">;; => #<JavaScript code></pre><pre class="">;; => [4, 6, 8] // when evaluated in JavaScript</pre><pre class=""><br class=""></pre><pre class=""><br class=""></pre><pre class="">Does it seem useful to integrate “parenscript-tagbody-go” into ParenScript itself or is a standalone package better maintenance-wise?</pre><pre class="">Something like "parenscript-series” seems like it may be better off as a separate package.</pre><pre class="">Nevertheless, SERIES is a pipelining compiler for pre-order traversal and with ParenScript being its own full compiler, integrating SERIES could be valuable.</pre><pre class="">Especially when implementing and composing operations from relational algebra having pipelining is a huge help.</pre><pre class="">Most of the usability mess with SERIES and CL seems to stem from the fact that it was *not* included in the standard and integrated into CL implementations properly [3 (page 55), 4 (page 6)].</pre><pre class="">SERIES got two honorable mentions in CLtL2 [5,6], but that seems to have been it from a usability standpoint.</pre><pre class=""><br class=""></pre><pre class=""><br class=""></pre><pre class="">What does experience suggest on these two matters?</pre><pre class=""><br class=""></pre><pre class=""><br class=""></pre><pre class=""><br class=""></pre><pre class="">Cheers,</pre><pre class="">Andrew</pre><div class=""><br class=""></div></div><div class=""><br class=""></div><div class="">[1] <a href="https://dapperdrake.neocities.org/faster-loops-javascript" class="">https://dapperdrake.neocities.org/faster-loops-javascript</a></div><div class="">[2] <a href="https://dapperdrake.neocities.org/faster-loops-javascript" class="">https://dapperdrake.neocities.org/faster-loops-javascript</a></div><div class="">[3] <a href="https://dspace.mit.edu/handle/1721.1/6035" class="">https://dspace.mit.edu/handle/1721.1/6035</a></div><div class="">[4] <a href="https://dspace.mit.edu/handle/1721.1/6031" class="">https://dspace.mit.edu/handle/1721.1/6031</a></div><div class="">[5] <a href="http://cltl2.lisp.se/cltl/clm/node347.html#SECTION003400000000000000000" class="">http://cltl2.lisp.se/cltl/clm/node347.html#SECTION003400000000000000000</a></div><div class="">[6] <a href="http://cltl2.lisp.se/cltl/clm/node362.html#SECTION003500000000000000000" class="">http://cltl2.lisp.se/cltl/clm/node362.html#SECTION003500000000000000000</a></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jan 27, 2023, at 09:00, Andrew Easton <<a href="mailto:Andrew@easton24.com" class="">Andrew@easton24.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Hello everyone, </div><div class=""><br class=""></div><div class="">How’s it going?</div><div class=""><br class=""></div><div class="">There is now a working version of (parenscript:defpsmacro tagbody (&body body) …)),</div><div class="">See my blog post here: "<a href="https://dapperdrake.neocities.org/faster-loops-javascript" class="">https://dapperdrake.neocities.org/faster-loops-javascript</a>” .</div><div class=""><br class=""></div><div class="">This adds nestable (tagbody … (tagbody …) …)) forms as a user-land library to parenscript.</div><div class=""><br class=""></div><div class="">Apologies for missing documentation.  It will be added gradually.  Also, hosting a tarball on</div><div class=""><a href="http://neocities.org/" class="">Neocities.org</a> is planned in future as well as somehow getting the library into quicklisp. A name</div><div class="">like parenscript-tagbody-go seems useful.</div><div class=""><br class=""></div><div class="">This code is still missing the check of *DEFINED-OPERATORS*.  How is that supposed to look?</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Cheers,</div><div class="">Andrew </div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On May 29, 2022, at 20:24, Andrew Easton <<a href="mailto:andrew@easton24.de" class="">andrew@easton24.de</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi Philipp,<br class=""><br class="">That sounds like a good plan.<br class=""><br class="">From my current vantage point, this seems like step<br class="">three.  I just got done with at step one.  Step two<br class="">is for me to get acquainted with the parenscript<br class="">codebase.<br class=""><br class="">I will get a feel the existing code base and then we<br class="">can take the next steps from there.<br class=""><br class="">I already cloned the git repository to my local<br class="">development machine.  The current commit for branch<br class="">master seems to be:<br class=""><br class="">commit 1fd720bc4e2bc5ed92064391b730b9d4db35462a (HEAD -> master)<br class="">| Author: Vladimir Sedach <<a href="mailto:vas@oneofus.la" class="">vas@oneofus.la</a>><br class="">| Date:   Wed Jun 17 20:29:19 2020 -0700<br class=""><br class=""><br class="">Regarding tail-call optimization in JavaScript:<br class="">Jason Miller also recommended that.  Unfortunately, I<br class="">dug up information indicating that it is unsupported<br class="">in Google's V8 JavaScript implementation, see<br class="">[<a href="http://stackoverflow.com/" class="">stackoverflow.com</a> (2017)].<br class=""><br class="">Quoting part of my reply to Jason for the benefit of<br class="">future readers of this specific email:<br class=""><br class=""><blockquote type="cite" class="">[...] This seems to necessitate a (loop (case ...))<br class="">based approach, because SERIES may be used for loops<br class="">with iteration counts greater than the stack size.<br class="">Nevertheless, not all is lost.<br class=""><br class="">PARENSCRIPT already compiles<br class="">(block nil ((lambda () (return 3)))) as catch/throw<br class="">correctly.  Note, the call in the body of the BLOCK.<br class="">So at least some dynamic ((lambda () (go ...))) calls<br class="">should be compilable; hopefully all of them.  Even if<br class="">it only captures 70% of all use cases, that is way<br class="">more than zero.<br class=""></blockquote><br class=""><br class=""><br class="">Cheers,<br class="">Andrew<br class=""><br class=""><br class=""><br class="">[<a href="http://stackoverflow.com/" class="">stackoverflow.com</a> (2017)], Answer by T.J. Crowder:<br class="">TITLE:<br class="">ES6 Tail Recursion Optimisation Stack Overflow,<br class="">URL:<br class=""><a href="https://stackoverflow.com/questions/42788139/es6-tail-recursion-optimisation-stack-overflow" class="">https://stackoverflow.com/questions/42788139/es6-tail-recursion-optimisation-stack-overflow</a><br class=""><br class=""><br class=""><br class="">On Sat, May 21, 2022 at 10:58:57AM +0200, Philipp Marek wrote:<br class=""><blockquote type="cite" class="">Hi Andrew,<br class=""><br class="">first of all -- how about registering on <a href="http://gitlab.common-lisp.net" class="">gitlab.common-lisp.net</a>,<br class="">so that you can become a developer for [1] and work with a branch<br class="">using a Merge Request?<br class="">It would be much easier to track your progress (and individual changes)<br class="">that way.<br class=""><br class=""><blockquote type="cite" class="">I have started to implement TAGBODY for PARENSCRIPT<br class="">[A,B,C].  The general idea is to imitate a jump table<br class="">by looping over a switch-case.  A GO (C-terminology:<br class="">jump) then sets the switch-variable to the next jump<br class="">destination.  The loop subsequently causes the switch<br class="">to branch to the jump target in the switch-variable.<br class="">Leaving the tagbody means leaving the loop.<br class=""></blockquote><br class="">Hmmm, okay.<br class="">My first thought would've been to use a function for each<br class="">part and just do tail recursion... but it seems that<br class="">this isn't really supported in Javascript?!<br class=""><br class=""><br class=""><br class=""><blockquote type="cite" class="">There are complications.  Common Lisp allows nested<br class="">tagbody-forms.  Common Lisp allows go-tags to be<br class="">referenced within the lexical scope *and* the dynamic<br class="">extent of a tagbody form.  This means that a LAMBDA<br class="">can close over a go-tag and jump there, see an<br class="">example in [B], of how inconvenient this can become<br class="">for compilation to JavaScript.<br class=""></blockquote><br class="">Yeah... that would be a good reason for simple function<br class="">calls and tail recursion.<br class=""><br class=""><br class=""><blockquote type="cite" class="">1. I need a code review of the algorithm.<br class="">   The implementation in [B] seems to be<br class="">   satisfactory.  There are some test cases and<br class="">   examples.  Most there is the most hairy example I<br class="">   could find up to now.  I may have missed crucial<br class="">   details.<br class=""></blockquote><br class="">I'll take a look - but please let's try to get it into<br class="">the git repo first, so that any discussions have some<br class="">common state to refer to.<br class=""><br class=""><br class=""><blockquote type="cite" class="">2. My understanding of the CL:TAGBODY definition in<br class="">   the CLHS [4] may be wrong.  Which alternate<br class="">   interpretations does anybody here know of?<br class=""></blockquote><br class="">What are your questions, or points of confusion?<br class=""><br class=""><br class=""><br class="">Ad 1: <a href="https://gitlab.common-lisp.net/parenscript/parenscript" class="">https://gitlab.common-lisp.net/parenscript/parenscript</a><br class=""></blockquote><br class=""></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></body></html>