help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How do I pass a variable defined in a wrapping let, to a lambda?


From: Jean Louis
Subject: Re: How do I pass a variable defined in a wrapping let, to a lambda?
Date: Sat, 12 Mar 2022 09:40:22 +0300
User-agent: Mutt/2.2.0 (2022-02-12)

* Emanuel Berg via Users list for the GNU Emacs text editor 
<help-gnu-emacs@gnu.org> [2022-03-12 05:41]:
> Michael Heerdegen wrote:
> 
> > you may want to find out what evaluating lexical-binding in
> > the buffer with lexical-binding -> nil gives you.
> >
> > Second: (AFAIK...) be sure to reeval `steinars-test' with
> > lexical-binding -> nil. `steinars-test' defined using the
> > lexical binding dialect will return a closure even when
> > called in the dynamcially binding dialect.
> 
> This is an example of why I think there should be three `let':
> 
> * "let" that is static/lexical except for already-defined
>   dynamic/special variables (i.e., what `let' is already under
>   static/lexical scope, so won't break any code to change.
>   well, there wouldn't be any change except static/lexical
>   would be default everywhere)
> 
> * "dlet" that is always dynamic/special

New `dlet' is this and it broke my programs because somebody removed
`let*'  inside. I don't think that person who changed it every used
`dlet' in their own programs. Reason is semantics, "dlet" uses "let*"
so they changed it, but did not provide "dlet*" (though is easy to
adapt it).

new `dlet':

(defmacro dlet (binders &rest body)
  "Like `let' but using dynamic scoping."
  (declare (indent 1) (debug let))
  ;; (defvar FOO) only affects the current scope, but in order for
  ;; this not to affect code after the main `let' we need to create a new scope,
  ;; which is what the surrounding `let' is for.
  ;; FIXME: (let () ...) currently doesn't actually create a new scope,
  ;; which is why we use (let (_) ...).
  `(let (_)
     ,@(mapcar (lambda (binder)
                 `(defvar ,(if (consp binder) (car binder) binder)))
               binders)
     (let ,binders ,@body)))

so I have just changed it back to what it was and use it with my own
prefix as `rcd-dlet' -- that way there is no need for quarrel.

(defmacro rcd-dlet (binders &rest body)
  "Like `let*' but using dynamic scoping."
  (declare (indent 1) (debug let))
  ;; (defvar FOO) only affects the current scope, but in order for
  ;; this not to affect code after the main `let' we need to create a new scope,
  ;; which is what the surrounding `let' is for.
  ;; FIXME: (let () ...) currently doesn't actually create a new scope,
  ;; which is why we use (let (_) ...).
  `(let (_)
     ,@(mapcar (lambda (binder)
                 `(defvar ,(if (consp binder) (car binder) binder)))
               binders)
     (let* ,binders ,@body)))


I find `dlet', rather `rcd-dlet' very useful in interpolation of
variables and templates that come from third sources, thus not coming
from the Emacs Lisp file itself.

Some insights:

      (rcd-dlet ((wrs::template (gethash "templates_content" wrs::template))
                 ;; now wrs::template is visible inside of
                 ;; wrs::template, sounds funny
             (open-graph-type "Article")
                 ;; now "open-graph-type" variable is accessible
                 ;; for use or interpolation within wrs::template scripts
             (wrs::html (rcd-template-eval wrs::template '("⟦" "⟧") 
wrs::variables))
                 ;; now wrs::template is interpolating various
                 ;; wrs::variables, expanding them inside of the
                 ;; template as otherwise they would not be visible
                 ;; rcd-dlet as only rcd-dlet breaks out of lexical binding
             (wrs::local-file (wrs-page-url page-id t))
             (wrs::local-dir (file-name-directory wrs::local-file)))
        (make-directory wrs::local-dir t)
        (string-to-file-force wrs::html wrs::local-file)))))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

In support of Richard M. Stallman
https://stallmansupport.org/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]