<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="">Thank you Robert for your examples.<div class=""><br class=""><div class="">I take Ron’s point that closures are consistent in all usage, including funcall vs process-run-function.</div><div class=""><div class="">I now understand is that “thread-local binding” means that process-run-function is executed in the top-level environment.</div></div><div class="">— “Dynamic extent” refers to time within a single thread, and does have meaning across multiple threads.</div><div class=""><div class="">— Funcall is a function; process-run-function is a special form.</div></div><div class=""><br class=""></div><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;"><div class=""><dt class=""><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><div class="" style="margin: 0px; font-stretch: normal; line-height: normal;"><span class="" style="font-variant-ligatures: no-common-ligatures;"><div class=""><br class=""></div></span></div></div></dt></div></div></div><div class=""><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">(let ((foo 4))</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> (declare (special foo))</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> (flet ((bar () (print foo) :return-me-from-bar))</span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span>(funcall #'bar)))</div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255); min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class="">4 </div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">:RETURN-ME-FROM-BAR</span></div></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; font-stretch: normal; font-size: 11px; line-height: normal; font-family: Menlo; background-color: rgb(255, 255, 255);" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">(let ((foo 4))</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> (declare (special foo))</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> (flet ((bar () (print foo) :return-me-from-bar))</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""> </span>(process-run-function :process2 #'bar)))</div><div style="margin: 0px; font-stretch: normal; line-height: normal; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class="">> Error: Unbound variable: FOO</div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">> While executing: BAR, in process PROCESS2(2).</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; font-stretch: normal; line-height: normal;" class=""><br class=""></div></span></div><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Jun 15, 2019, at 1:28 AM, Robert Munyer <<a href="mailto:2420506348@munyer.com" class="">2420506348@munyer.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">None of your results really involve thread semantics.<br class="">You can get all of those results with a single thread.<br class="">I will paste a transcript below.<br class=""><br class="">martin wrote: <br class=""><br class=""><blockquote type="cite" class="">Actually, I am amazed that the closed-over case works.<br class="">In the following form, process1 terminates before process2 calls bar;<br class="">nevertheless the call to bar has access to the lexical environment of<br class="">process1 - or maybe that isn't a correct description.<br class=""><br class="">(process-run-function :process1<br class=""> #'(lambda ()<br class=""> (let ((foo 4))<br class=""> (flet ((bar () (print foo) :return-me-from-bar))<br class=""> (bar)<br class=""> (process-run-function :process2 #'(lambda ()<br class=""> (sleep 10)<br class=""> (bar)<br class=""> :return-me-from-lambda))))))<br class=""></blockquote><br class="">It would be better to say that BAR has access to its _own_ lexical<br class="">environment, because it is a closure. You can see the same thing<br class="">happening in several of my single-threaded replications below.<br class=""><br class="">They would have failed in some early versions of Lisp, which<br class="">suffered from the "upward funarg problem", but Common Lisp<br class="">implementations are not allowed to have that problem.<br class=""><br class="">See AI Memo #199, "The Function of FUNCTION in LISP, or Why the<br class="">FUNARG Problem Should be Called the Environment Problem".<br class=""><br class="">Transcript replicating your results in standard CL, no threads:<br class=""><br class="">? (defun bar () (print 27))<br class="">BAR<br class="">? (funcall (let ((foo 2))<br class=""> (flet ((bar () (format t "~&~s" foo)))<br class=""> (bar)<br class=""> #'bar)))<br class="">2<br class="">2<br class="">NIL<br class="">? (defvar *foo* 3)<br class="">*FOO*<br class="">? (funcall (let ((*foo* 2))<br class=""> (flet ((bar () (format t "~&~s" *foo*)))<br class=""> (bar)<br class=""> #'bar)))<br class="">2<br class="">3<br class="">NIL<br class="">? (funcall (funcall (let ((foo 4))<br class=""> (lambda ()<br class=""> (flet ((bar () (format t "~&~s" foo)))<br class=""> (bar)<br class=""> #'bar)))))<br class="">4<br class="">4<br class="">NIL<br class="">? (defparameter *foo* 5)<br class="">*FOO*<br class="">? (funcall (funcall (let ((*foo* 4))<br class=""> (lambda ()<br class=""> (flet ((bar () (format t "~&~s" *foo*)))<br class=""> (bar)<br class=""> #'bar)))))<br class="">5<br class="">5<br class="">NIL<br class="">? (funcall (let ((foo 4))<br class=""> (declare (special foo))<br class=""> (flet ((bar () (format t "~&~s" foo)))<br class=""> (bar)<br class=""> #'bar)))<br class="">4<br class=""><blockquote type="cite" class="">Error: Unbound variable: FOO<br class="">While executing: BAR, in process listener(1).<br class="">Type :POP to abort, :R for a list of available restarts.<br class="">Type :? for other options.<br class=""></blockquote>1 > :pop<br class=""><br class="">? (funcall (let ((foo 4))<br class=""> (flet ((bar () (format t "~&~s" foo)))<br class=""> (bar)<br class=""> (lambda ()<br class=""> (sleep 10)<br class=""> (bar)))))<br class="">4<br class="">4<br class="">NIL<br class="">_______________________________________________<br class="">Openmcl-devel mailing list<br class=""><a href="mailto:Openmcl-devel@clozure.com" class="">Openmcl-devel@clozure.com</a><br class="">https://lists.clozure.com/mailman/listinfo/openmcl-devel<br class=""></div></div></blockquote></div><br class=""></div></div></body></html>