From: Mateusz Berezecki on
Hi,

I have a following package/symbol question.
I'm using SBCL on ubuntu lucid lynx.

Here's the source code reproducing the problem.

(make-package 'test)
(in-package :test)
(cl:use-package :cl)

(defmacro test-macro (op)
`,(case op
(hi t)
(t nil)))

(test-macro hi) ==> t
(test-macro hello) ==> nil


All is good so far, but problems emerge as soon as I switch to a
different package.

(in-package :cl-user)

(test:test-macro hello) ==> nil
(test:test-macro hi) ==> nil
(test:test-macro test::hi) ==> t

I understand that 'hi symbol is interned into a test package so the
real comparison inside of case statement is against op and test::hi
but this is not what I want. Is there a way to correct this behavior
and not requiring prefixing with packages, etc. ?

I am building a DSL macro but I want it to be exported from one
package and used by other packages.

Any ideas?
From: joswig on
On 8 Aug., 22:35, Mateusz Berezecki <mateu...(a)gmail.com> wrote:
> Hi,
>
> I have a following package/symbol question.
> I'm using SBCL on ubuntu lucid lynx.
>
> Here's the source code reproducing the problem.
>
> (make-package 'test)
> (in-package :test)
> (cl:use-package :cl)
>
> (defmacro test-macro (op)
>  `,(case op
>       (hi t)
>       (t nil)))

`, is not needed.

>
> (test-macro hi) ==> t
> (test-macro hello) ==> nil
>
> All is good so far, but problems emerge as soon as I switch to a
> different package.
>
> (in-package :cl-user)
>
> (test:test-macro hello) ==> nil
> (test:test-macro hi) ==> nil
> (test:test-macro test::hi) ==> t
>
> I understand that 'hi symbol is interned into a test package so the
> real comparison inside of case statement is against op and test::hi
> but this is not what I want. Is there a way to correct this behavior
> and not requiring prefixing with packages, etc. ?

You can compare the symbol names. Then you might want to use COND
instead of CASE,
since CASE compares with EQL. You might want to compare the symbol
names with EQUAL.

>
> I am building a DSL macro but I want it to be exported from one
> package and used by other packages.
>
> Any ideas?

From: Scott L. Burson on
Mateusz Berezecki wrote:
>
> I understand that 'hi symbol is interned into a test package so the
> real comparison inside of case statement is against op and test::hi
> but this is not what I want. Is there a way to correct this behavior
> and not requiring prefixing with packages, etc. ?

The usual way to deal with this problem is to use keywords (symbols in
the keyword package). Thus:

(defmacro test-macro (op)
(case op
(:hi t)
(t nil)))

(in-package :cl-user)
(test:test-macro :hi) ==> t

This maybe isn't quite what you want since the colon is still required,
but it is the standard approach in CL.

An alternative would be to export both TEST-MACRO and HI from the TEST
package, and use the TEST package in the package where you write your
code. Then you won't have to include the package prefix on TEST-MACRO
either:

(in-package :test)
(export '(test-macro hi) :test)
(in-package :cl-user)
(use-package :test)

;;; Assuming your original definition of TEST-MACRO
(test-macro hi) ==> t

This might seem like the obviously preferable solution -- and indeed you
certainly will want to use it for the symbol TEST-MACRO -- but in
general I think it's better for symbols that are part of the syntax of
macros (like HI in this example) to be in the keyword package.

-- Scott
From: Pascal J. Bourguignon on
Mateusz Berezecki <mateuszb(a)gmail.com> writes:
> I have a following package/symbol question.
> I'm using SBCL on ubuntu lucid lynx.
>
> Here's the source code reproducing the problem.
>
> (make-package 'test)

The behavior of the package thusly created will be implementation
dependent. Better create it as:

(make-package 'test :use '(:cl))


> (in-package :test)
> (cl:use-package :cl)
>
> (defmacro test-macro (op)
> `,(case op
> (hi t)
> (t nil)))
>
> (test-macro hi) ==> t
> (test-macro hello) ==> nil
>
>
> All is good so far, but problems emerge as soon as I switch to a
> different package.
>
> (in-package :cl-user)
>
> (test:test-macro hello) ==> nil
> (test:test-macro hi) ==> nil
> (test:test-macro test::hi) ==> t
>
> I understand that 'hi symbol is interned into a test package so the
> real comparison inside of case statement is against op and test::hi
> but this is not what I want. Is there a way to correct this behavior
> and not requiring prefixing with packages, etc. ?
>
> I am building a DSL macro but I want it to be exported from one
> package and used by other packages.
>
> Any ideas?

Use defpackage and export HI:

(defpackage "TEST"
(:use "CL")
(:export "TEST-MACRO" "HI"))
(in-package "TEST")

(defmacro test-macro (op)
(case op
((hi) t)
(otherwise nil)))


(in-package "CL-USER")
(use-package "TEST")

(test-macro hi)
;; -> T
(test-macro lo)
;; -> NIL


--
__Pascal Bourguignon__ http://www.informatimago.com/