Hi, thanks for help.
On Mon, Sep 26, 2011 at 3:02 PM, Scott McKay swm@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@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)) ,@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)) ,@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)) ,@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@common-lisp.net http://lists.common-lisp.net/cgi-bin/mailman/listinfo/pro