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: Pascal J. Bourguignon
Subject: Re: macros and the lexical environment
Date: Wed, 05 Jun 2013 01:07:09 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3 (gnu/linux)

Nic Ferrier <address@hidden> writes:

> A while ago I wrote to the list about s-lex-format, a contribution I
> made to magnars excellent s library for string handling.
>
> s-lex-format is designed to let you interpolate values from the current
> lexical environment into a string, like this:
>
>   (let ((v 42)
>         (a "hello world"))
>      (s-lex-format "${a} - the answer is ${v}"))
>
> this is terrifically useful.
>
> However. It's implementation is a pain. 


???

(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]






> But what I'm really asking is, isn't this quite a useful thing to want
> to do? get at the current environment state? the interpreter must know
> the environment state. 

By definition, the lexical state is lexical, therefore you know it, even
before writing the s-lex-format expression!


> Could it be exposed to macros at compile time?

It could, but it's not necessary.


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)


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
A bad day in () is better than a good day in {}.
You can take the lisper out of the lisp job, but you can't take the lisp out
of the lisper (; -- antifuchs




reply via email to

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