Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I've been considering adding lexical lookup to s-format #27

Closed
nicferrier opened this issue Apr 28, 2013 · 9 comments
Closed

I've been considering adding lexical lookup to s-format #27

nicferrier opened this issue Apr 28, 2013 · 9 comments

Comments

@nicferrier
Copy link
Contributor

So you can do this:

(let ((x 1))
  (s-format "x is ${x}" 'lex-value))

Good idea? Bad idea?

@magnars
Copy link
Owner

magnars commented Apr 28, 2013

I think that looks brilliant. But maybe as a separate function, so you can ditch the 'lex-value all together?

(let ((x 1))
  (s-lex-format "x is ${x}"))

@nicferrier
Copy link
Contributor Author

The only trouble with that is that I think there are two things that
would be useful, lexical access and lexical access with Lisp output:

I'm using this code right now:

(defvar lexical-value-when-dynamic :error
  "How `lexical-value' should act in dynamic scope.

Valid values are `:error', which is the default and causes
`lexical-value' to error when called in dynamic scope, or
`:symbol-value' which causes the `symbol-value' function to be
called for the symbol or `nil' which causes nil to be returned.")

(defmacro lexical-value (lexical-symbol)
  "What is the value of the LEXICAL-SYMBOL specified?"
  (let ((pv (make-symbol "pv"))
        (sv (make-symbol "snv")))
    `(let ((,pv (lambda ())))
       (if (eq 'closure (car ,pv))
           (let ((value 
                  (assoc ,lexical-symbol (cadr ,pv))))
             (when value (cdr value)))
           (case lexical-value-when-dynamic
             (:error (error "not in a lexical environment"))
             (:symbol-value (symbol-value ,lexical-symbol))
             (t nil))))))

(defmacro with-sformat-lex (&rest body)
  (declare (debug (&rest form))
           (indent 0))
  `(flet ((lex-val (var)
            (let ((lexical-value-when-dynamic :symbol-value)
                  (variable (intern var)))
              (lexical-value variable)))
          (lisp-val (var) (format "%S" (lex-val var))))
     ,@body))

So I can go:

(let ((x 1)
      (y '(a b c)))
 (with-sformat-lex
   (format "x is: ${x} and y is: ${y}" 'lisp-val)))

or I could use lex-val.

I guess I could start adding more dynamic options to format to control
how things are output?

@magnars
Copy link
Owner

magnars commented Apr 29, 2013

What I want are fewer dynamic options and instead a cleaner API. Functions
that do one thing.

On Mon, Apr 29, 2013 at 3:32 PM, Nic Ferrier notifications@github.comwrote:

The only trouble with that is that I think there are two things that
would be useful, lexical access and lexical access with Lisp output:

I'm using this code right now:

(defvar lexical-value-when-dynamic :error
"How `lexical-value' should act in dynamic scope.

Valid values are `:error', which is the default and causes
`lexical-value' to error when called in dynamic scope, or
`:symbol-value' which causes the `symbol-value' function to be
called for the symbol or `nil' which causes nil to be returned.")

(defmacro lexical-value (lexical-symbol)
"What is the value of the LEXICAL-SYMBOL specified?"
(let ((pv (make-symbol "pv"))
(sv (make-symbol "snv")))
`(let ((,pv (lambda ())))
(if (eq 'closure (car ,pv))
(let ((value
(assoc ,lexical-symbol (cadr ,pv))))
(when value (cdr value)))
(case lexical-value-when-dynamic
(:error (error "not in a lexical environment"))
(:symbol-value (symbol-value ,lexical-symbol))
(t nil))))))

(defmacro with-sformat-lex (&rest body)
(declare (debug (&rest form))
(indent 0))
`(flet ((lex-val (var)
(let ((lexical-value-when-dynamic :symbol-value)
(variable (intern var)))
(lexical-value variable)))
(lisp-val (var) (format "%S" (lex-val var))))
,@body))

So I can go:

(let ((x 1)
(y '(a b c)))
(with-sformat-lex
(format "x is: ${x} and y is: ${y}" 'lisp-val)))

or I could use lex-val.

I guess I could start adding more dynamic options to format to control
how things are output?


Reply to this email directly or view it on GitHubhttps://github.com//issues/27#issuecomment-17166575
.

@nicferrier
Copy link
Contributor Author

Do you? I like all that being able to change the behaviour of things by let binding and such. It's fun.

@nicferrier
Copy link
Contributor Author

How about this:

(defmacro s-lex-format (format-str)
  (let ((pv (make-symbol "pv")))
    `(s-format
      ,format-str
      (let ((,pv (lambda ())))
        (if (eq 'closure (car ,pv))
            (lambda (var-name)
              (let ((value 
                     (assoc (intern var-name) (cadr ,pv))))
                (when value (cdr value))))
            (lambda (var-name)
              (case lexical-value-when-dynamic
                (:error (error "not in a lexical environment"))
                (:symbol-value (symbol-value
                                (intern var-name)))
                (t nil))))))))

(let ((lexical-value-when-dynamic :symbol-value)
      (x "1"))
  (s-lex-format "${x}"))

My only concern with this is that often you want the lex value to be lisp printed ("%S" instead of "%s") and that's not possible here. It could be done with a switch or a dyn var.

@magnars
Copy link
Owner

magnars commented Apr 29, 2013

It's too convoluted for me. I would be a happy man if I could just have a formatting function that grabs content off the current scope. But come to think of it, maybe that's just concat, with " " separating the keys instead of ${}. How is ${} any better?

@nicferrier
Copy link
Contributor Author

For all the reasons that s-format is better. My use case is this:

;;; ${name}.el --- ${desc}

${copy}

${decl}

;;; Commentary:

${commentary}

;;; Code:

${defn-code}

${prvide-code}
;;; ${name}.el ends here

Code that with concat and see how happy you are :-)

@magnars
Copy link
Owner

magnars commented Apr 29, 2013

Haha, you're right. That would be terrible. :-)

On Mon, Apr 29, 2013 at 11:18 PM, Nic Ferrier notifications@github.comwrote:

For all the reasons that s-format is better. My use case is this:

;;; ${name}.el --- ${desc}

${copy}

${decl}

;;; Commentary:

${commentary}

;;; Code:

${defn-code}

${prvide-code}
;;; ${name}.el ends here

Code that with concat and see how happy you are :-)


Reply to this email directly or view it on GitHubhttps://github.com//issues/27#issuecomment-17195146
.

@nicferrier
Copy link
Contributor Author

It seems like a standard templating problem to me. And I've never really got how we can fix that with simple Lisp. Maybe there is a better solution but I'm not aware of it.

nicferrier added a commit to nicferrier/s.el that referenced this issue May 9, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants