lilypond-user
[Top][All Lists]
Advanced

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

Re: Scratching my head around define-macro and variable evaluation


From: Stefano Troncaro
Subject: Re: Scratching my head around define-macro and variable evaluation
Date: Wed, 28 Mar 2018 16:43:10 -0300

Hi David,

Thank you for your reply. Yes, I undestood that about macros. I'm trying to dynamically generate the variable definitions inside a let block from an alist, but the only way I manage to do that is if I type the alist manually. I want to achieve that with an alist stored in a variable. Simplified example:
\version "2.19.80"

#(define-macro (custom-let alist . body)
   `(let ,(map (lambda(pair) (list (car pair) (cdr pair))) alist)
      . ,body))

#(custom-let ((my-key . "my-val") (another-key . "another-val"))
   (pretty-print my-key)
   (pretty-print another-key))
%Outputs:
%"my-val"
%"another-val"

#(define my-alist '((my-key . "my-val") (another-key . "another-val")))

#(custom-let my-alist
   (pretty-print my-key)
   (pretty-print another-key))
%No applicable method for #<<extended-generic> map (0)> in call (map #<procedure #f (pair)> my-alist)

This is why I wanted to be able to evaluate the contents of the variable inside the body of the macro. I thought of manually evaluating the argument, but if I understand correctly it is not possible to do it in the correct scope (only globally and not locally)? If so, then do you have a suggestion to solve the problem showed above?

2018-03-28 16:23 GMT-03:00 David Kastrup <address@hidden>:
Stefano Troncaro <address@hidden> writes:

> Hi everyone!
>
> I have a question about the following example:
>
>> \version "2.19.80"
>> #(define-macro (why-the-difference obj)
>>    (display (format "~a , " obj))
>>    `(display (format "~a\n" ,obj)))
>>
>> #(why-the-difference (list 1 2 3))% => (list 1 2 3) , (1 2 3)
>> #(define var (list 1 2 3))
>>
>> #(why-the-difference var)% => var , (1 2 3)
>>
>> So, I assume that the difference is because the macro has access to what
> is typed, and uses that to produce an _expression_ that is later evaluated.
> So, in the first example, (list 1 2 3) was typed, so that's shown in the
> output before the comma. While in the second example, var was typed, so the
> symbol var is shown instead.
>
> Is there a way to evaluate the symbol inside the body of the macro?

Not reliably.  It's a rather loosely defined point of time.

> I tried the following to no avail:
>
>> \version "2.19.80"
>> #(use-modules (ice-9 r5rs))
>>
>> #(define-macro (my-attempt obj)
>>    (display (format "~a , " (eval 'obj (interaction-environment))))
>>    `(display (format "~a\n" ,obj)))

Well, that's completely wrong.  (interaction-environment) is a _global_
environment.  It does not have access to local variables/symbols like
obj.  So you'd want to write

(eval obj (interaction-environment)) if at all, and even then this will
only work for global variables.

>> #(define var (list 1 2 3))
>>
>> #(my-attempt var)
>>
>> This generates the error 'unbound variable: obj'. I don't understand why
> obj is not considered defined, when if I use obj I get the symbol var (as
> the first snippet showed). Anyways, I *can* evaluate var:
>
>> \version "2.19.80"
>> #(use-modules (ice-9 r5rs))
>>
>> #(define-macro (my-attempt obj)
>>    (display (format "~a , " (eval 'var (interaction-environment))))
>>    `(display (format "~a\n" ,obj)))
>>
>> #(define var (list 1 2 3))
>>
>> #(my-attempt var)% => (1 2 3) , (1 2 3)
>>
>> Which makes sense. This achieves what I want but it is not useful because
> I need to know the name of the variable before-hand, so it will not work
> dynamically.
>
> Does anyone know of a way around this?

Apparently you don't understand what a macro does.  A macro receives its
arguments _unevaluated_, and the result is later evaluated in the
closure where the macro is called.  (eval obj (interaction-environment))
is exactly equivalent to (eval 'var (interaction-environment)) here.

--
David Kastrup


reply via email to

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