emacs-devel
[Top][All Lists]
Advanced

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

Re: macros and the lexical environment


From: Nic Ferrier
Subject: Re: macros and the lexical environment
Date: Wed, 05 Jun 2013 09:23:21 +0100

Nic Ferrier said:

>> However. It's implementation is a pain. 

"Pascal J. Bourguignon" <address@hidden> replied:

> ???
>
> (defmacro s-lex-format (string)
>   (s-lex-format* string))
>
> Is that painful???
>
> The most painful in your s-lex-format, it's the $ before the brace!
>
> (defmacro s-lex-format (string)
>   (s-lex-format* string))
>
> (defun s-lex-format* (string)
>   (loop
>      with last = 0
>      with arguments = '()
>      with result = ""
>      for start = (search "${" string) then (search "${" string :start2 last)
>      while start
>      do (let ((end (search "}" string :start2 start)))
>           (unless end (error "Missing } after ${"))
>           (push (intern (subseq string (+ 2 start) end)) arguments)
>           (setf result (format "%s%s%%s" result (subseq string last start))
>                 last (1+ end)))
>      finally (let ((end (length string)))
>                (return `(format ,(concat result (subseq string last end))
>                                 ,@(nreverse arguments))))))
>
>
> (s-lex-format*  "${a} - the answer is ${v}")
> --> (format "%s - the answer is %s" a v)
>
>
> (byte-compile '(lambda ()
>                 (let ((v 42)
>                       (a "hello world"))
>                   (s-lex-format "${a} - the answer is ${v}"))))
> --> #[nil "\302\303^X^Y\304\305^H #*\207" 
>           [a v 42 "hello world" format "%s - the answer is %s"]
>           4]

Fantastic. If only you had read all my mail because I went on to say:


>> I decided that it would be better to expand the format string into a
>> list of variable references. But that doesn't work well unless the
>> string is static, using a reference for the format string doesn't
>> work because it's not available at compile time:
>>
>>  (let ((v 42)
>>        (a "hello world")
>>        (template "${a} - the answer is ${v}"))
>>     (s-lex-format template))
>>
>> will fail to expand.

and yours suffers from the same problem of course.


> Otherwise, the principle of lisp is to use fully parenthesized prefix
> notation.  Therefore don't try to subvert it by accessing
> subreptitiously the lexical environment.  Instead, just define your own
> macros.   For example, to pass the "lexical environment" to the
> run-time:
>
>
> (defmacro with-variable-memo-let (memo bindings &rest body)
>   (let ((vars (mapcar (lambda (binding)
>                         (if (atom binding) binding (first binding)))
>                       bindings)))
>     `(let ((,memo ',vars)
>            ,@bindings)
>        ,@body)))
>
> (with-variable-memo-let memo
>   ((v 42)
>    (a "hello world"))
>   memo)
> --> (v a)

/me feels lectured at.

The point of the macro was clear, to let the user avoid repeating
themselves.

I agree that a Lisp syntax is nearly always best, however, this is a
good exception. A string syntax is useful to mix in data in other
formats than s-expressions (HTML for example, although another way of
doing this would be to switch everything to s-expressions like esxml
does). String stuff is also easy to adapt to buffers so s-lex-format
was easy to adapt to buffers.

In summary, you haven't resolved the problem, it's fundamental in
elisp. You can't get at the names of the variables in scope at compile
time and have:

* variables references for the template
* or a compiled version


Nic



reply via email to

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