all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Meta-code confusion
@ 2012-08-10 19:12 Doug Lewan
  2012-08-10 21:38 ` Doug Lewan
       [not found] ` <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>
  0 siblings, 2 replies; 5+ messages in thread
From: Doug Lewan @ 2012-08-10 19:12 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

I have development environment that has a handful of files with isomorphic (but not identical) structures.
I'd like to use the same code to define modes for all of them, but clearly there are things I don't understand about writing meta-code in emacs lisp.

As a starting point I'm failing with the following:

(defvar *pp-symbol-re* "\\(?:\\s_\\|\\sw\\)")
(defun ppm-define-vars (name abbreviation)
  "Build a list of vars for the new mode."
  (let* ((start-var-name (format "*pp-%s-start-re*" abbreviation))
	 (start-var (make-symbol start-var-name))
	 (start-re (list 'concat (format "^%s\\s-+" name) '*pp-symbol-re*)))
    (list (list 'defvar start-var start-re))))

I want all such functions to return a list of definitions of the type of interest.
This one happens to return a list of one element, [I would like] a variable definition.
It certainly looks like it's returning the right kind of thing:

(car (ppm-define-vars "douglas" "dug"))
=> (defvar *pp-dug-start-re* (concat "^douglas\\s-+" *pp-symbol-re*))

And (eval) looks like it does the right thing:
(eval (car (ppm-define-vars "douglas" "dug")))
=> *pp-dug-start-re*

(defvar) returns a symbol and (symbolp) confirms that that is a symbol.

However, using *pp-dug-start-re* gets a void-variable error.
On the other hand 
(boundp (eval (car (ppm-define-vars "douglas" "dug"))))
=> t
which would seem to be a contradiction.

I'm using 
GNU Emacs 24.1.1 (i686-pc-cygwin, GTK+ Version 2.24.10) of 2012-07-17 on fiona    and
GNU Emacs 24.1.1 (powerpc-ibm-aix6.1.0.0, X toolkit, Xaw scroll bars) of 2012-07-25 on devlpar1.

I would gladly pay with a beer¹ to understand this better.

,Douglas
Douglas Lewan
Shubert Ticketing
(201) 489-8600 ext 224

There is no national science just as there is no national multiplication table; what is national is no longer science. - Anton Checov
_____________
¹ "beer" is a variable, replace it with an appropriate value should beer be distasteful to you or otherwise inappropriate.




^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: Meta-code confusion
  2012-08-10 19:12 Meta-code confusion Doug Lewan
@ 2012-08-10 21:38 ` Doug Lewan
       [not found] ` <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>
  1 sibling, 0 replies; 5+ messages in thread
From: Doug Lewan @ 2012-08-10 21:38 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org

Well, after a few more hours I have a work-around. I think the original problem was because (defvar) is a special form, but I'm still not sure.

The current work-around is to build a string that looks right and then (eval (read THAT-STRING)) and let the results of that be the return value. I can't see the interesting difference, but it does what I want.

,Doug

> -----Original Message-----
> From: help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org
> [mailto:help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org] On
> Behalf Of Doug Lewan
> Sent: Friday, 2012 August 10 15:12
> To: help-gnu-emacs@gnu.org
> Subject: Meta-code confusion
> 
> I have development environment that has a handful of files with
> isomorphic (but not identical) structures.
> I'd like to use the same code to define modes for all of them, but
> clearly there are things I don't understand about writing meta-code in
> emacs lisp.
> 
> As a starting point I'm failing with the following:
> 
> (defvar *pp-symbol-re* "\\(?:\\s_\\|\\sw\\)")
> (defun ppm-define-vars (name abbreviation)
>   "Build a list of vars for the new mode."
>   (let* ((start-var-name (format "*pp-%s-start-re*" abbreviation))
> 	 (start-var (make-symbol start-var-name))
> 	 (start-re (list 'concat (format "^%s\\s-+" name) '*pp-symbol-
> re*)))
>     (list (list 'defvar start-var start-re))))
> 
> I want all such functions to return a list of definitions of the type
> of interest.
> This one happens to return a list of one element, [I would like] a
> variable definition.
> It certainly looks like it's returning the right kind of thing:
> 
> (car (ppm-define-vars "douglas" "dug"))
> => (defvar *pp-dug-start-re* (concat "^douglas\\s-+" *pp-symbol-re*))
> 
> And (eval) looks like it does the right thing:
> (eval (car (ppm-define-vars "douglas" "dug")))
> => *pp-dug-start-re*
> 
> (defvar) returns a symbol and (symbolp) confirms that that is a symbol.
> 
> However, using *pp-dug-start-re* gets a void-variable error.
> On the other hand
> (boundp (eval (car (ppm-define-vars "douglas" "dug"))))
> => t
> which would seem to be a contradiction.
> 
> I'm using
> GNU Emacs 24.1.1 (i686-pc-cygwin, GTK+ Version 2.24.10) of 2012-07-17
> on fiona    and
> GNU Emacs 24.1.1 (powerpc-ibm-aix6.1.0.0, X toolkit, Xaw scroll bars)
> of 2012-07-25 on devlpar1.
> 
> I would gladly pay with a beer¹ to understand this better.
> 
> ,Douglas
> Douglas Lewan
> Shubert Ticketing
> (201) 489-8600 ext 224
> 
> There is no national science just as there is no national
> multiplication table; what is national is no longer science. - Anton
> Checov
> _____________
> ¹ "beer" is a variable, replace it with an appropriate value should
> beer be distasteful to you or otherwise inappropriate.
> 




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Meta-code confusion
       [not found] ` <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>
@ 2012-08-10 22:02   ` Barry Margolin
  2012-08-13 14:04     ` Doug Lewan
  0 siblings, 1 reply; 5+ messages in thread
From: Barry Margolin @ 2012-08-10 22:02 UTC (permalink / raw)
  To: help-gnu-emacs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 3383 bytes --]

In article <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>,
 Doug Lewan <dougl@shubertticketing.com> wrote:

> Well, after a few more hours I have a work-around. I think the original 
> problem was because (defvar) is a special form, but I'm still not sure.
> 
> The current work-around is to build a string that looks right and then (eval 
> (read THAT-STRING)) and let the results of that be the return value. I can't 
> see the interesting difference, but it does what I want.

That's almost always the wrong thing.  Rather than that, you should 
build a list (probably using backquote to fill in a template) and then 
(eval THAT-LIST).

But more likely, you probably need to define your own macro rather than 
a function.

> 
> ,Doug
> 
> > -----Original Message-----
> > From: help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org
> > [mailto:help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org] On
> > Behalf Of Doug Lewan
> > Sent: Friday, 2012 August 10 15:12
> > To: help-gnu-emacs@gnu.org
> > Subject: Meta-code confusion
> > 
> > I have development environment that has a handful of files with
> > isomorphic (but not identical) structures.
> > I'd like to use the same code to define modes for all of them, but
> > clearly there are things I don't understand about writing meta-code in
> > emacs lisp.
> > 
> > As a starting point I'm failing with the following:
> > 
> > (defvar *pp-symbol-re* "\\(?:\\s_\\|\\sw\\)")
> > (defun ppm-define-vars (name abbreviation)
> >   "Build a list of vars for the new mode."
> >   (let* ((start-var-name (format "*pp-%s-start-re*" abbreviation))
> > 	 (start-var (make-symbol start-var-name))
> > 	 (start-re (list 'concat (format "^%s\\s-+" name) '*pp-symbol-
> > re*)))
> >     (list (list 'defvar start-var start-re))))
> > 
> > I want all such functions to return a list of definitions of the type
> > of interest.
> > This one happens to return a list of one element, [I would like] a
> > variable definition.
> > It certainly looks like it's returning the right kind of thing:
> > 
> > (car (ppm-define-vars "douglas" "dug"))
> > => (defvar *pp-dug-start-re* (concat "^douglas\\s-+" *pp-symbol-re*))
> > 
> > And (eval) looks like it does the right thing:
> > (eval (car (ppm-define-vars "douglas" "dug")))
> > => *pp-dug-start-re*
> > 
> > (defvar) returns a symbol and (symbolp) confirms that that is a symbol.
> > 
> > However, using *pp-dug-start-re* gets a void-variable error.
> > On the other hand
> > (boundp (eval (car (ppm-define-vars "douglas" "dug"))))
> > => t
> > which would seem to be a contradiction.
> > 
> > I'm using
> > GNU Emacs 24.1.1 (i686-pc-cygwin, GTK+ Version 2.24.10) of 2012-07-17
> > on fiona    and
> > GNU Emacs 24.1.1 (powerpc-ibm-aix6.1.0.0, X toolkit, Xaw scroll bars)
> > of 2012-07-25 on devlpar1.
> > 
> > I would gladly pay with a beer¹ to understand this better.
> > 
> > ,Douglas
> > Douglas Lewan
> > Shubert Ticketing
> > (201) 489-8600 ext 224
> > 
> > There is no national science just as there is no national
> > multiplication table; what is national is no longer science. - Anton
> > Checov
> > _____________
> > ¹ "beer" is a variable, replace it with an appropriate value should
> > beer be distasteful to you or otherwise inappropriate.
> >

-- 
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***


^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: Meta-code confusion
  2012-08-10 22:02   ` Barry Margolin
@ 2012-08-13 14:04     ` Doug Lewan
  2012-08-13 16:44       ` Aurélien Aptel
  0 siblings, 1 reply; 5+ messages in thread
From: Doug Lewan @ 2012-08-13 14:04 UTC (permalink / raw)
  To: help-gnu-emacs@gnu.org



> -----Original Message-----
> From: help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org
> [mailto:help-gnu-emacs-bounces+dougl=shubertticketing.com@gnu.org] On
> Behalf Of Barry Margolin
> Sent: Friday, 2012 August 10 18:03
> To: help-gnu-emacs@gnu.org
> Subject: Re: Meta-code confusion
> 
> In article <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>,
>  Doug Lewan <dougl@shubertticketing.com> wrote:
> 
> > The current work-around is to build a string that looks right and
> then (eval
> > (read THAT-STRING)) and let the results of that be the return value.
> 
> That's almost always the wrong thing.  Rather than that, you should
> build a list (probably using backquote to fill in a template) and then
> (eval THAT-LIST).

I suspected that. It's certainly not a satisfying solution

> 
> But more likely, you probably need to define your own macro rather than
> a function.

And I do suppose that this would be more correct (and satisfying). I'm not fluent in macros and try to avoid them, but maybe the time has come....

Thanks for the advice.

,Doug




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Meta-code confusion
  2012-08-13 14:04     ` Doug Lewan
@ 2012-08-13 16:44       ` Aurélien Aptel
  0 siblings, 0 replies; 5+ messages in thread
From: Aurélien Aptel @ 2012-08-13 16:44 UTC (permalink / raw)
  To: Doug Lewan; +Cc: help-gnu-emacs@gnu.org

On Mon, Aug 13, 2012 at 4:04 PM, Doug Lewan <dougl@shubertticketing.com> wrote:
>> But more likely, you probably need to define your own macro rather than
>> a function.
>
> And I do suppose that this would be more correct (and satisfying). I'm not fluent in macros and try to avoid them, but maybe the time has come....

It's really simpler using a macro. Are you familiar with the backquote?

This is a backquote form:
`(a b c)
=> (a b c)

It's almost the same behaviour as the regular quote *but* if you
prefix an element with a comma, it is evaluated.

'(1 (+ 1 1) 3)    ;; regular quote
=> (1 (+ 1 1) 3)

`(1 (+ 1 1) 3)    ;; backquote
=> (1 (+ 1 1) 3)

`(1 ,(+ 1 1) 3)    ;; backquote with a comma
=> (1 2 3)

Notice how the expression after the comma is evaluated.

Here's a simple macro that does what you want:

(defmacro ppm-define-vars (name abbrev)
  (let ((var (intern (format "*pp-%s-start-re*" abbrev)))
        (fmt (format "^%s\\s-+" (regexp-quote name))))
    `(defvar ,var (concat ,fmt *pp-symbol-re*))))

No nested list call and way more readable, right?

When the macro is evaluated, it is first "expanded" and the resulting
form is then evaluated. You can see the result (expansion) of the
macro *before* it gets evaluated with the macroexpand function.

(macroexpand '(ppm-define-vars "douglas" "dug"))
=> (defvar *pp-dug-start-re* (concat "^douglas\\s-+" *pp-symbol-re*))

There's more in the manual if you're interested. Look at (info
"(elisp) Macros") or [1].
Good luck!

1: http://www.gnu.org/software/emacs/manual/html_node/elisp/Macros.html#Macros



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-08-13 16:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-08-10 19:12 Meta-code confusion Doug Lewan
2012-08-10 21:38 ` Doug Lewan
     [not found] ` <mailman.6744.1344634688.855.help-gnu-emacs@gnu.org>
2012-08-10 22:02   ` Barry Margolin
2012-08-13 14:04     ` Doug Lewan
2012-08-13 16:44       ` Aurélien Aptel

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.