Lisp HUG Maillist Archive

Question about macro expansion

Suppose that in package my-macros, I have:

(defmacro foo (bar p v)
  `(defun ,bar ()
     (if (func ,p)
       ,v)))

If I expand the macro in my-package-1, e.g.

(foo a 'b 'c)

it becomes

(defun a ()
  (if (my-macros:func 'b)
    'c)

But "func" doesn't exist in the my-macros package.  It does exist in my-package-1 (and my-package-2, ...)

Why is a macro assuming the package of a function?  More importantly, can I define a macro once such that when it is expanded in my-package-N it calls the func in my-packageN?  Right now, I'm defining the same macro in each package where it's used so that I can get the behavior I need, but surely there's a better way.


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

> On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:
> 
> Suppose that in package my-macros, I have:
> 
> (defmacro foo (bar p v)
>  `(defun ,bar ()
>     (if (func ,p)
>       ,v)))
> 
> If I expand the macro in my-package-1, e.g.
> 
> (foo a 'b 'c)
> 
> it becomes
> 
> (defun a ()
>  (if (my-macros:func 'b)
>    'c)
> 
> But "func" doesn't exist in the my-macros package.  It does exist in my-package-1 (and my-package-2, ...)
> 
> Why is a macro assuming the package of a function?  More importantly, can I define a macro once such that when it is expanded in my-package-N it calls the func in my-packageN?  Right now, I'm defining the same macro in each package where it's used so that I can get the behavior I need, but surely there's a better way.


When the reader encounters a hitherto unknown symbol without an explicit package qualifier, it assumes the symbol belongs to the current package. You can tell the reader that FUNC belongs to some other package by either explicitly qualifying the symbol—that is, by writing THE-OTHER-PACKAGE:FUNC— or by importing the symbol FUNC from the other package into package MY-MACROS.

Please note, the reader doesn’t “assume the package of a function”. Functions don’t have packages. Only symbols have packages. Packages contain symbols, and only symbols.



_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

Right.  But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded.  Not the package in which the macro is defined.

> On Apr 11, 2018, at 11:43 AM, mikel evins <mevins@me.com> wrote:
> 
> 
>> On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:
>> 
>> Suppose that in package my-macros, I have:
>> 
>> (defmacro foo (bar p v)
>> `(defun ,bar ()
>>    (if (func ,p)
>>      ,v)))
>> 
>> If I expand the macro in my-package-1, e.g.
>> 
>> (foo a 'b 'c)
>> 
>> it becomes
>> 
>> (defun a ()
>> (if (my-macros:func 'b)
>>   'c)
>> 
>> But "func" doesn't exist in the my-macros package.  It does exist in my-package-1 (and my-package-2, ...)
>> 
>> Why is a macro assuming the package of a function?  More importantly, can I define a macro once such that when it is expanded in my-package-N it calls the func in my-packageN?  Right now, I'm defining the same macro in each package where it's used so that I can get the behavior I need, but surely there's a better way.
> 
> 
> When the reader encounters a hitherto unknown symbol without an explicit package qualifier, it assumes the symbol belongs to the current package. You can tell the reader that FUNC belongs to some other package by either explicitly qualifying the symbol—that is, by writing THE-OTHER-PACKAGE:FUNC— or by importing the symbol FUNC from the other package into package MY-MACROS.
> 
> Please note, the reader doesn’t “assume the package of a function”. Functions don’t have packages. Only symbols have packages. Packages contain symbols, and only symbols.
> 
> 


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

> On Apr 11, 2018, at 10:51 AM, Bob Felts <wrf3@stablecross.com> wrote:
> 
> Right.  But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded.  Not the package in which the macro is defined.

It’s the reader, not the macroexpander, that decides which package you’re referring to. If your macroexpander refers to the symbol FUNC, then the reader looks for it in the package that is the value of CL:*PACKAGE* at the time the macro definition is processed. If you want FUNC to be found in some other package then you must explicitly arrange for it to be looked up in that other package. 

There are various ways to accomplish that. If your requirements can’t be met by explicitly qualifying the symbol, or by suitable choice of in-package or let-binding CL:*PACKAGE*, then you could do something like

(funcall (intern “FUNC” (choose-the-correct-package-for-the-context)
            ,p))




_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

Chris, cjv, and mikel:

Madhu provided a suggestion that is a synthesis of your solutions.  I didn't want to provide "func" as a parameter to the macros, because it's the same in every case, and I'd like to save typing.  And, yes, "func" is defined in each file that uses foo.

Madhu's suggestion was to define foo as follows:

  (defmacro foo (bar p v &optional (func (intern "FUNC" *package*)))
    ...
    (if (,func ...


Thanks, everyone.

And, yes, I'm not happy with a design that needs this, but I'm still trying to shape things.

> On Apr 11, 2018, at 12:35 PM, Christopher Riesbeck <c-riesbeck@northwestern.edu> wrote:
> 
> 
> On 4/11/2018 10:51 AM, Bob Felts wrote:
>> Right.  But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded.  Not the package in which the macro is defined.
>> 
>>>> On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:
>>>> 
>>>> Suppose that in package my-macros, I have:
>>>> 
>>>> (defmacro foo (bar p v)
>>>> `(defun ,bar ()
>>>>    (if (func ,p)
>>>>      ,v)))
> 
> The difficulty of doing this is a sign the design doesn't really make sense. Anyone using FOO has to know that they must define a function FUNC in their package. There's no sign of that in the call, and no way to use a different name, if they already have a FUNC (perhaps from a library) that does something else.
> 
> Had you made FUNC a parameter of the macro, e.g., (foo func ...), then the macro would be more flexible and you wouldn't have this problem.
> 
> 
> -- 
> ................................................
> Christopher Riesbeck
> Associate Professor, Electrical Engineering and Computer Science
> McCormick School of Engineering
> Northwestern University
> 
> 2145 Sheridan Rd., Evanston, IL 60208
> 
> Home page: http://www.cs.northwestern.edu/~riesbeck/
> Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html
> 


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

&aux is also an option for that hack.  &optional allows users to specify 
a name. &aux doesn't  change the API of the macro. I personally would go 
for &optional because I think func should be a parameter.

On 4/11/2018 11:57 AM, Bob Felts wrote:
> Chris, cjv, and mikel:
>
> Madhu provided a suggestion that is a synthesis of your solutions.  I didn't want to provide "func" as a parameter to the macros, because it's the same in every case, and I'd like to save typing.  And, yes, "func" is defined in each file that uses foo.
>
> Madhu's suggestion was to define foo as follows:
>
>    (defmacro foo (bar p v &optional (func (intern "FUNC" *package*)))
>      ...
>      (if (,func ...
>
>
> Thanks, everyone.
>
> And, yes, I'm not happy with a design that needs this, but I'm still trying to shape things.
>
>> On Apr 11, 2018, at 12:35 PM, Christopher Riesbeck <c-riesbeck@northwestern.edu> wrote:
>>
>>
>> On 4/11/2018 10:51 AM, Bob Felts wrote:
>>> Right.  But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded.  Not the package in which the macro is defined.
>>>
>>>>> On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:
>>>>>
>>>>> Suppose that in package my-macros, I have:
>>>>>
>>>>> (defmacro foo (bar p v)
>>>>> `(defun ,bar ()
>>>>>     (if (func ,p)
>>>>>       ,v)))
>> The difficulty of doing this is a sign the design doesn't really make sense. Anyone using FOO has to know that they must define a function FUNC in their package. There's no sign of that in the call, and no way to use a different name, if they already have a FUNC (perhaps from a library) that does something else.
>>
>> Had you made FUNC a parameter of the macro, e.g., (foo func ...), then the macro would be more flexible and you wouldn't have this problem.
>>
>>
>> -- 
>> ................................................
>> Christopher Riesbeck
>> Associate Professor, Electrical Engineering and Computer Science
>> McCormick School of Engineering
>> Northwestern University
>>
>> 2145 Sheridan Rd., Evanston, IL 60208
>>
>> Home page: http://www.cs.northwestern.edu/~riesbeck/
>> Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html
>>
>
> _______________________________________________
> Lisp Hug - the mailing list for LispWorks users
> lisp-hug@lispworks.com
> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.lispworks.com_support_lisp-2Dhug.html&d=DwIDAg&c=yHlS04HhBraes5BQ9ueu5zKhE7rtNXt_d012z2PA6ws&r=rYww9Ur1WoBi28j2XhN4rwFLo31INs66FdFiX_Ro7pI&m=tmzqa4ZqNiaMr39HHYTs3Eax-arnp6nD75rfAyHpJg8&s=bsJHPDIhDjO8tx2DUmLpvDsZ1hQBPTO3FzxbcHEOWZs&e=

-- 
.................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Question about macro expansion

Yes, it would help if you were to explain why you want the macro to get a different function in every package where it is used, instead of importing the func symbol into every package where you use your macro.

It seems odd that a function would fill the same role, but in a different way, in different packages.

Indeed, it seems likely to me that what you are doing here would better be done with method dispatch -- making func a generic function, instead of a name that just happens always to bound to The Right Thing.

Note that I'm being very intentional about saying "a name that just happens to be bound to the right thing." Symbols with the same name in different package don't really share an identity the same way that a generic function does, so this seems esthetically unappealing.

On 11 Apr 2018, at 11:57, Bob Felts wrote:

Chris, cjv, and mikel:

Madhu provided a suggestion that is a synthesis of your solutions. I didn't want to provide "func" as a parameter to the macros, because it's the same in every case, and I'd like to save typing. And, yes, "func" is defined in each file that uses foo.

Madhu's suggestion was to define foo as follows:

(defmacro foo (bar p v &optional (func (intern "FUNC" *package*)))
...
(if (,func ...


Thanks, everyone.

And, yes, I'm not happy with a design that needs this, but I'm still trying to shape things.

On Apr 11, 2018, at 12:35 PM, Christopher Riesbeck <c-riesbeck@northwestern.edu> wrote:


On 4/11/2018 10:51 AM, Bob Felts wrote:

Right. But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded. Not the package in which the macro is defined.

On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:

Suppose that in package my-macros, I have:

(defmacro foo (bar p v)
`(defun ,bar ()
(if (func ,p)
,v)))

The difficulty of doing this is a sign the design doesn't really make sense. Anyone using FOO has to know that they must define a function FUNC in their package. There's no sign of that in the call, and no way to use a different name, if they already have a FUNC (perhaps from a library) that does something else.

Had you made FUNC a parameter of the macro, e.g., (foo func ...), then the macro would be more flexible and you wouldn't have this problem.


--
................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Robert P. Goldman
Research Fellow
Smart Information Flow Technologies (d/b/a SIFT, LLC)

319 N. First Ave., Suite 400
Minneapolis, MN 55401

Voice: (612) 326-3934
Email: rpgoldman@SIFT.net

Re: Question about macro expansion

I'm using macros to both generate data structures at compile time and to generate functions that use those data structures.  There can be any number of independent "major" data structures -- one in each package -- and one "minor" data structure which is used in conjunction with one major data structure.  All of these data structures have the same name.  At the bottom, there is one function that takes a major data structure, the minor data structure, and some other input and does something with it.  The "function" was just a poor man's way to get to the major data structure in each package.

All of this worked when the macros were defined in the packages that use them.  But that lead to duplicate macros.  Put the macros in their own package and they start expanding differently.  They aren't like C's text based macros.  Now that I really grasp this, given Madhu's suggestion, I can use intern, find-package and &aux to cajole the macros to expand to the places where things are.

Thanks, everyone.

On Apr 11, 2018, at 1:56 PM, Robert Goldman <rpgoldman@sift.net> wrote:

Yes, it would help if you were to explain why you want the macro to get a different function in every package where it is used, instead of importing the func symbol into every package where you use your macro.

It seems odd that a function would fill the same role, but in a different way, in different packages.

Indeed, it seems likely to me that what you are doing here would better be done with method dispatch -- making func a generic function, instead of a name that just happens always to bound to The Right Thing.

Note that I'm being very intentional about saying "a name that just happens to be bound to the right thing." Symbols with the same name in different package don't really share an identity the same way that a generic function does, so this seems esthetically unappealing.

On 11 Apr 2018, at 11:57, Bob Felts wrote:

Chris, cjv, and mikel:

Madhu provided a suggestion that is a synthesis of your solutions. I didn't want to provide "func" as a parameter to the macros, because it's the same in every case, and I'd like to save typing. And, yes, "func" is defined in each file that uses foo.

Madhu's suggestion was to define foo as follows:

(defmacro foo (bar p v &optional (func (intern "FUNC" *package*)))
...
(if (,func ...


Thanks, everyone.

And, yes, I'm not happy with a design that needs this, but I'm still trying to shape things.

On Apr 11, 2018, at 12:35 PM, Christopher Riesbeck <c-riesbeck@northwestern.edu> wrote:


On 4/11/2018 10:51 AM, Bob Felts wrote:

Right. But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded. Not the package in which the macro is defined.

On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:

Suppose that in package my-macros, I have:

(defmacro foo (bar p v)
`(defun ,bar ()
(if (func ,p)
,v)))

The difficulty of doing this is a sign the design doesn't really make sense. Anyone using FOO has to know that they must define a function FUNC in their package. There's no sign of that in the call, and no way to use a different name, if they already have a FUNC (perhaps from a library) that does something else.

Had you made FUNC a parameter of the macro, e.g., (foo func ...), then the macro would be more flexible and you wouldn't have this problem.


--
.................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Robert P. Goldman
Research Fellow
Smart Information Flow Technologies (d/b/a SIFT, LLC)

319 N. First Ave., Suite 400
Minneapolis, MN 55401

Voice: (612) 326-3934
Email: rpgoldman@SIFT.net


Re: Question about macro expansion

That works, but as I said, I think you would be happier if you had a single generic function instead of making a different function for each one of these data structures.

cheers,
r


On 11 Apr 2018, at 14:11, Bob Felts wrote:

I'm using macros to both generate data structures at compile time and to generate functions that use those data structures.  There can be any number of independent "major" data structures -- one in each package -- and one "minor" data structure which is used in conjunction with one major data structure.  All of these data structures have the same name.  At the bottom, there is one function that takes a major data structure, the minor data structure, and some other input and does something with it.  The "function" was just a poor man's way to get to the major data structure in each package.

All of this worked when the macros were defined in the packages that use them.  But that lead to duplicate macros.  Put the macros in their own package and they start expanding differently.  They aren't like C's text based macros.  Now that I really grasp this, given Madhu's suggestion, I can use intern, find-package and &aux to cajole the macros to expand to the places where things are.

Thanks, everyone.

On Apr 11, 2018, at 1:56 PM, Robert Goldman <rpgoldman@sift.net> wrote:

Yes, it would help if you were to explain why you want the macro to get a different function in every package where it is used, instead of importing the func symbol into every package where you use your macro.

It seems odd that a function would fill the same role, but in a different way, in different packages.

Indeed, it seems likely to me that what you are doing here would better be done with method dispatch -- making func a generic function, instead of a name that just happens always to bound to The Right Thing.

Note that I'm being very intentional about saying "a name that just happens to be bound to the right thing." Symbols with the same name in different package don't really share an identity the same way that a generic function does, so this seems esthetically unappealing.

On 11 Apr 2018, at 11:57, Bob Felts wrote:

Chris, cjv, and mikel:

Madhu provided a suggestion that is a synthesis of your solutions. I didn't want to provide "func" as a parameter to the macros, because it's the same in every case, and I'd like to save typing. And, yes, "func" is defined in each file that uses foo.

Madhu's suggestion was to define foo as follows:

(defmacro foo (bar p v &optional (func (intern "FUNC" *package*)))
...
(if (,func ...


Thanks, everyone.

And, yes, I'm not happy with a design that needs this, but I'm still trying to shape things.

On Apr 11, 2018, at 12:35 PM, Christopher Riesbeck <c-riesbeck@northwestern.edu> wrote:


On 4/11/2018 10:51 AM, Bob Felts wrote:

Right. But in this case I'm emitting code to be compiled in multiple packages. At compile time, I want the "func" which is defined in the package in which the macro is expanded. Not the package in which the macro is defined.

On Apr 11, 2018, at 10:33 AM, Bob Felts <wrf3@stablecross.com> wrote:

Suppose that in package my-macros, I have:

(defmacro foo (bar p v)
`(defun ,bar ()
(if (func ,p)
,v)))

The difficulty of doing this is a sign the design doesn't really make sense. Anyone using FOO has to know that they must define a function FUNC in their package. There's no sign of that in the call, and no way to use a different name, if they already have a FUNC (perhaps from a library) that does something else.

Had you made FUNC a parameter of the macro, e.g., (foo func ...), then the macro would be more flexible and you wouldn't have this problem.


--
................................................
Christopher Riesbeck
Associate Professor, Electrical Engineering and Computer Science
McCormick School of Engineering
Northwestern University

2145 Sheridan Rd., Evanston, IL 60208

Home page: http://www.cs.northwestern.edu/~riesbeck/
Calendar: http://www.cs.northwestern.edu/~riesbeck/calendar.html

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Robert P. Goldman
Research Fellow
Smart Information Flow Technologies (d/b/a SIFT, LLC)

319 N. First Ave., Suite 400
Minneapolis, MN 55401

Voice: (612) 326-3934
Email: rpgoldman@SIFT.net




Robert P. Goldman
Research Fellow
Smart Information Flow Technologies (d/b/a SIFT, LLC)

319 N. First Ave., Suite 400
Minneapolis, MN 55401

Voice: (612) 326-3934
Email: rpgoldman@SIFT.net

Updated at: 2020-12-10 08:30 UTC