[pro] help with macro

karol skocik karol.skocik at gmail.com
Mon Sep 26 15:39:54 UTC 2011


Hi,
  thanks for help.

On Mon, Sep 26, 2011 at 3:02 PM, Scott McKay <swm at google.com> wrote:
> You're pretty much asking for type inference, but with you
> being the one doing the inference.

Yes, it's more or less a way to provide more type hints to SBCL.

On Mon, Sep 26, 2011 at 4:28 PM, Peter Stirling
<peter at pjstirling.plus.com> wrote:
> You are misunderstanding the way that symbols work:
>
> First your source code is read by the reader, and symbols are looked up
> by their package prefix, or interned in the current package if
> unqualified. After this point the raw text that from your lisp file is
> thrown away and macro-expansion and compilation is performed using only
> the symbols and constants identified/produced by the reader. Since your
> macro is trying to shadow symbols rather than generate new ones you only
> need to worry about package prefixes at the call site of your macro, and
> not in the macro itself
>

Thanks for explanation. I was confused thinking that reader
subsequently reads more of the form as it is expanded, which is
rubbish.

> :use in defpackage will import all external symbols into the defined
> package, and since "+" is external in :cl, and it's highly likely that
> you are ":use :cl" it wouldn't need a prefix.
>
>
> (defmacro with-typed-arguments ((name) type &body body)
>  (let ((func (gensym)))
>    `(let ((,func #',name))
>       (declare (sb-ext:disable-package-locks ,name))
>       (macrolet ((,name (&rest args)
>                         (list* 'funcall ',func
>                                (mapcar (lambda (arg)
>                                          (list 'the ',type arg))
>                                        args))))
>         (declare (sb-ext:enable-package-locks ,name))
>         , at body))))
>
>
> Should do the expansion you want, but it's not the "right" way in
> common-lisp.
>

Works nicely, thank you! Why do you consider it as not "right"?

Have a nice day.
  Karol

> On Mon, 2011-09-26 at 09:31 +0200, karol skocik wrote:
>> Hi Lispers,
>>   I need a help with a following macro I am trying to write:
>>
>> When the call site looks like this:
>>
>> (with-typed-arguments (distance) single-float
>>           (+ (distance a b c d)
>>              (distance x y z w)))
>>
>> I want it to expand into something like this:
>>
>> (+ (DISTANCE (THE SINGLE-FLOAT A) (THE SINGLE-FLOAT B) (THE
>> SINGLE-FLOAT C) (THE SINGLE-FLOAT D))
>>     (DISTANCE (THE SINGLE-FLOAT X) (THE SINGLE-FLOAT Y) (THE
>> SINGLE-FLOAT Z) (THE SINGLE-FLOAT W))))
>>
>> Now, what I have currently is:
>>
>> (defmacro with-typed-arguments ((&rest functions) argument-type &body body)
>>   (flet ((macrolet-body (fun)
>>            `(,fun (&rest args)
>>                   `(funcall #',',fun ,@(iter (for arg :in args)
>>                                              (collect `(the
>> ,',argument-type ,arg)))))))
>>     `(macrolet (,@(mapcar #'macrolet-body functions))
>>        , at body)))
>>
>> But it some things I don't understand:
>>
>> 1.) the function called with typed arguments is called using funcall -
>> not a show stopper, just a style issue. Without funcall the expansion
>> loops forever since the expansion does not emit the code, but expands
>> deeper into infinite recursion of macrolets. Can it be fixed somehow?
>>
>> 2.) in the flet macrolet-body, I have a trouble understanding ,',fun
>> construction next to the funcall - why the "fun" next to funcall can't
>> be replaced by macrolet-body argument fun with ,,fun ? It is buried in
>> `` but ,,fun there just got me (for call (macrolet-body +)) -> `(,+
>> ...). Let me show my trouble in the example:
>>
>> In this definition:
>> (defmacro with-typed-arguments ((&rest functions) argument-type &body body)
>>   (flet ((macrolet-body (fun)
>>            `(,fun (&rest args)
>>                   `(funcall #',,fun ,@(iter (for arg :in args)
>>                                              (collect `(the
>> ,',argument-type ,arg)))))))
>>     `(macrolet (,@(mapcar #'macrolet-body functions))
>>        , at body)))
>>
>> this expansion:
>> (with-typed-arguments (distance) single-float
>>           (+ (distance a b c d)
>>              (distance x y z w)))
>>
>> results in this:
>> (MACROLET ((DISTANCE (&REST ARGS)
>>              `(FUNCALL #',DISTANCE
>>           ;; <- why is there ,DISTANCE when there is `(... `(... ,,fun
>> ?
>>                        ,@(ITER
>>                            (FOR ARG :IN ARGS)
>>                            (COLLECT `(THE SINGLE-FLOAT ,ARG))))))
>>   (+ (DISTANCE A B C D) (DISTANCE X Y Z W)))
>>
>> 3.) package-locks - I want it to work with arithmetic functions
>> (especially!) defined in CL package. That doesn't work, since I can't
>> make a macrolet ((+ (&rest args) ...) because of package-locks. I am
>> happy with SBCL specific fix, using SBCL's
>> sb-ext:disable-package-locks, or sb-ext:without-package-locks, but I
>> can't make it work.
>> Especially, I have a trouble understanding, how do I create a symbol
>> with package prefix needed in declaration like this:
>> (declare (sb-ext:disable-package-locks cl::+))
>>
>> Is there a way to prepend the symbol-package and '::' to the given
>> symbol? How to construct such fully qualified symbol like cl::+?
>>
>> Thank you,
>>   Karol
>>
>> _______________________________________________
>> pro mailing list
>> pro at common-lisp.net
>> http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro
>
>
>




More information about the pro mailing list