From: Sam S. <sd...@gn...> - 2017-12-24 00:34:10
|
Hi Bruno, > * Bruno Haible <oe...@py...t> [2017-12-23 22:31:05 +0100]: > > Your proposal introduces a new approach to scoping: Have the scope > depend on whether the access to a variable is a read or a write > access. Not really - it merely allows control over binding activation. > 1) The purpose of the scopes in the language definition is that by looking > a the (fully macroexpanded) source code of a function, the user can > tell to which binding a certain variable reference refers. > If the user furthermore has to _scan_ the source code for assignments, > this lookup is significantly more complicated. CL is already complicated enough. This is a small extra cherry on the side. ;-) Jörg already implemented LAZY-LET in pure CL. What I am suggesting is a mere optimization. > 2) What about conditional accesses? > (lazy-let (a) > (if (> (random) 0.5) > (setq a 10)) > (lambda (a) (print a))) What you probably meant was lambda without arguments (otherwise the question is trivial), and then we get random results: (let ((a 1)) (values (funcall (lazy-let1 (a) (when (zerop (random 2)) (setq a 10)) (lambda () (print a)))) a)) ==> 1 or 10 randomly as the 1st value; 1 always as the second value. > 3) There are forms which combine a read access and a write access, like > (INCF b). This activates the binding and assigns the inner binding to 1+outer. > Instead, maybe we should provide explicit control of the environment in > which a form will be evaluated/compiled. For example: > > (let ((a 1)) > (environment-let env-with-a > (let ((b 2)) > (in-enviroment env-with-a (list a b))))) (declare (name-environment env-with-a)) and (declare (use-environment env-with-a)) looks better to me. > Such a clisp specific set of special-operators ENVIRONMENT-LET and > IN-ENVIRONMENT could be emulated for other implementations through a > code walker. Since lazy-let can be implemented via a simple macro, code walkers will be happy. > Still, I don't know whether such a thing is really needed for the LOOP > macro, where we have a finite set of initforms and bindings. So (loop for var in var do ...) will expand to something like (macrolet ... (declare (name-environment outer)) (let ((var nil)) (tagbody ... (setq var (locally (declare (use-environment outer)) var)) ...))) this is easy, but I am afraid more complicated things will be harder. (loop for x in x for y in x for z = y then x ...) >> The problem with loop is that under certain circumstances we separate >> initializing and binding of a variable. > > This is not a problem by itself. It is explicitly allowed by CLHS > 6.1.1.4 "Implementations can interleave the setting of initial values > with the bindings." If I understand you correctly, this merely implies that the naive user expectations are not guaranteed. Sure. Why not give them what they want if we can though? > What I see as a problem is that users are not warned when they write > unportable code. That is, we should have a warning (in the spirit of > "gcc -fsanitize=undefined" for C) whenever the interpretation of an > initform actually depends on the environment. You are looking at the problem from the portability/compliance POV. I am trying to implement "naive user expectations" (as long as they are conforming, of course). Thanks. -- Sam Steingold (http://sds.podval.org/) on darwin Ns 10.3.1504 http://steingoldpsychology.com http://www.childpsy.net http://camera.org http://jij.org http://islamexposedonline.com http://think-israel.org How do you prove a cotheorem? Using rollaries. |