From: Mirko on 5 Apr 2010 14:03 On Apr 5, 12:49 pm, "jos...(a)corporate-world.lisp.de" <jos...(a)lisp.de> wrote: > On 5 Apr., 18:24, Tamas K Papp <tkp...(a)gmail.com> wrote: > > > > > On Mon, 05 Apr 2010 08:27:52 -0700, Mirko wrote: > > > I have a utility that may need to do some unit conversions. I would > > > like to specify the conversion rules as an association list: > > > > ((a do-something) (b do-something-else) ... etc) > > > > Now, I could specify `do-something' as #'(lambda (arg) > > > (* arg 5)) > > > > and so on. All the lambda's have the same format #'(lambda (arg) > > > (...)), only the ellipsis changing from item to item > > > > Specifying the lambdas works, but makes the a-list hard to read. Instead > > > I would like it to contain the bodies of the lambda's. > > > > ((a (* arg 5)) (b (/ arg 12)) ... etc) > > > > So, the question is how to compile those bodies (I am not sure `compile' > > > is the right term - I just want to get an `executable' lambda out of > > > these). > > > > Right now, I am compiling via macros: > > > > (defmacro build (sym) > > > `(lambda (arg) > > > ,(second (assoc sym +table+))) > > > > and then > > > > (funcall (build a) arg) > > > > will execute my function. > > > > But I am wondering if I am misusing the macros here, and if there is > > > something more direct > > > I think that this is OK, but I would do it in a slightly different > > way. You want convenient syntax for two things: defining new > > conversions, and performing them by name. I would just use a macro > > for the first and a generic function for the second, eg: > > > (defgeneric do-conversion (name arg) > > (:documentation "Perform the named conversion on ARG.")) > > > (defmacro define-conversion (name &body body) > > `(defmethod do-conversion ((name (eql ',name)) arg) > > ,@body)) > > > (define-conversion m->km (/ arg 1000)) > > (define-conversion km->m (* arg 1000)) > > > ;; example: > > (do-conversion 'm->km 1000) > > > Best, > > > Tamas > > How about this one without generic functions. > Dispatch is done by symbol lookup if necessary. > > (defparameter *table* > '((m->km (/ arg 1000)) > (km->m (* arg 1000)))) > > (defmacro defconv (var conversions) > (when (symbolp conversions) > (setf conversions (symbol-value conversions))) > `(progn ,@(loop for (name calculation) in conversions > collect `(defun ,name (,var) > ,calculation)))) > > (defconv arg *table*) > > (m->km 4) > > (funcall 'm->km 4) > > (defun convert (how what) > (funcall how what)) > > (convert 'm->km 4) Well, thank you both, but that is not what I am looking for. (and my previous example breaks down now). Suppose I have this list: (* arg 4). how can I convert it into something that I can call with (mapcar #'foo some-list) on the fly? So, I do not want to define this function using defun. I want a lambda. Thanks, Mirko
From: Tamas K Papp on 5 Apr 2010 14:56 On Mon, 05 Apr 2010 11:03:45 -0700, Mirko wrote: > On Apr 5, 12:49 pm, "jos...(a)corporate-world.lisp.de" <jos...(a)lisp.de> > wrote: >> On 5 Apr., 18:24, Tamas K Papp <tkp...(a)gmail.com> wrote: >> >> >> >> > On Mon, 05 Apr 2010 08:27:52 -0700, Mirko wrote: >> > > I have a utility that may need to do some unit conversions. I >> > > would like to specify the conversion rules as an association list: >> >> > > ((a do-something) (b do-something-else) ... etc) >> >> > > Now, I could specify `do-something' as #'(lambda (arg) >> > > (* arg 5)) >> >> > > and so on. All the lambda's have the same format #'(lambda (arg) >> > > (...)), only the ellipsis changing from item to item >> >> > > Specifying the lambdas works, but makes the a-list hard to read. >> > > Instead I would like it to contain the bodies of the lambda's. >> >> > > ((a (* arg 5)) (b (/ arg 12)) ... etc) >> >> > > So, the question is how to compile those bodies (I am not sure >> > > `compile' is the right term - I just want to get an `executable' >> > > lambda out of these). >> >> > > Right now, I am compiling via macros: >> >> > > (defmacro build (sym) >> > > `(lambda (arg) >> > > ,(second (assoc sym +table+))) >> >> > > and then >> >> > > (funcall (build a) arg) >> >> > > will execute my function. >> >> > > But I am wondering if I am misusing the macros here, and if there >> > > is something more direct >> >> > I think that this is OK, but I would do it in a slightly different >> > way. You want convenient syntax for two things: defining new >> > conversions, and performing them by name. I would just use a macro >> > for the first and a generic function for the second, eg: >> >> > (defgeneric do-conversion (name arg) >> > (:documentation "Perform the named conversion on ARG.")) >> >> > (defmacro define-conversion (name &body body) >> > `(defmethod do-conversion ((name (eql ',name)) arg) >> > ,@body)) >> >> > (define-conversion m->km (/ arg 1000)) (define-conversion km->m (* >> > arg 1000)) >> >> > ;; example: >> > (do-conversion 'm->km 1000) >> >> > Best, >> >> > Tamas >> >> How about this one without generic functions. Dispatch is done by >> symbol lookup if necessary. >> >> (defparameter *table* >> '((m->km (/ arg 1000)) >> (km->m (* arg 1000)))) >> >> (defmacro defconv (var conversions) >> (when (symbolp conversions) >> (setf conversions (symbol-value conversions))) >> `(progn ,@(loop for (name calculation) in conversions >> collect `(defun ,name (,var) >> ,calculation)))) >> >> (defconv arg *table*) >> >> (m->km 4) >> >> (funcall 'm->km 4) >> >> (defun convert (how what) >> (funcall how what)) >> >> (convert 'm->km 4) > > Well, thank you both, but that is not what I am looking for. > > (and my previous example breaks down now). > > Suppose I have this list: (* arg 4). > > how can I convert it into something that I can call with (mapcar #'foo > some-list) on the fly? > > So, I do not want to define this function using defun. I want a > lambda. Maybe I am not getting the question, but if you just want a lambda, you could use a lambda. If you want to drop the arg to make it more compact, you could do something like (defmacro conv (&body body) `(lambda (arg) ,@body)) (funcall (conv (* arg 4)) 3) Tamas
From: Thomas A. Russ on 5 Apr 2010 14:28 Mirko <mirko.vukovic(a)gmail.com> writes: > On Apr 5, 12:49�pm, "jos...(a)corporate-world.lisp.de" <jos...(a)lisp.de> > > How about this one without generic functions. > > Dispatch is done by symbol lookup if necessary. > > > > (defparameter *table* > > � '((m->km (/ arg 1000)) > > � � (km->m (* arg 1000)))) > > > > (defmacro defconv (var conversions) > > � (when (symbolp conversions) > > � � (setf conversions (symbol-value conversions))) > > � `(progn ,@(loop for (name calculation) in conversions > > � � � � � � � � � collect `(defun ,name (,var) > > � � � � � � � � � � � � � � �,calculation)))) > > > > (defconv arg *table*) > > > > (m->km 4) > > > > (funcall 'm->km 4) > > > > (defun convert (how what) > > � (funcall how what)) > > > > (convert 'm->km 4) > > Well, thank you both, but that is not what I am looking for. > > (and my previous example breaks down now). > > Suppose I have this list: (* arg 4). > > how can I convert it into something that I can call with (mapcar #'foo > some-list) on the fly? Any of the solutions that produce the lambda function will work for this. So, as long as you had a way of looking up the function, it should work. Suppose you had a table of (key . function) forms, and this funciton: (defun get-conversion-function (key) (cdr (assoc key *table))) you could then simply call (mapcar (get-conversion-function 'foo) some-list) MAPCAR evaluates its arguments (like all functions), so you can compute the function to return. It will just work like you want it to. -- Thomas A. Russ, USC/Information Sciences Institute
From: Rainer Joswig on 5 Apr 2010 15:23 In article <f853a030-f395-481c-85a0-e3d7d2bd312d(a)y17g2000yqd.googlegroups.com>, Mirko <mirko.vukovic(a)gmail.com> wrote: > Well, thank you both, but that is not what I am looking for. > > (and my previous example breaks down now). > > Suppose I have this list: (* arg 4). > > how can I convert it into something that I can call with (mapcar #'foo > some-list) on the fly? > > So, I do not want to define this function using defun. I want a > lambda. > > Thanks, > > Mirko The typical question is: do you really want to do that and not have pre-compiled functions? If yes: CL-USER 49 > '(* arg 4) (* ARG 4) CL-USER 50 > (append '(lambda (arg)) (list '(* arg 4))) (LAMBDA (ARG) (* ARG 4)) CL-USER 51 > (eval (append '(lambda (arg)) (list '(* arg 4)))) #<anonymous interpreted function 4060000BB4> CL-USER 52 > (compile nil (append '(lambda (arg)) (list '(* arg 4)))) #<Function 11 4060000DFC> NIL NIL CL-USER 53 > (mapcar (compile nil (append '(lambda (arg)) (list '(* arg 4)))) '(1 2 3 4)) (4 8 12 16) -- http://lispm.dyndns.org/
From: Mirko on 5 Apr 2010 16:12 On Apr 5, 3:23 pm, Rainer Joswig <jos...(a)lisp.de> wrote: > In article > <f853a030-f395-481c-85a0-e3d7d2bd3...(a)y17g2000yqd.googlegroups.com>, > > > > Mirko <mirko.vuko...(a)gmail.com> wrote: > > Well, thank you both, but that is not what I am looking for. > > > (and my previous example breaks down now). > > > Suppose I have this list: (* arg 4). > > > how can I convert it into something that I can call with (mapcar #'foo > > some-list) on the fly? > > > So, I do not want to define this function using defun. I want a > > lambda. > > > Thanks, > > > Mirko > > The typical question is: do you really want to do that and not have pre-compiled functions? > > If yes: > > CL-USER 49 > '(* arg 4) > (* ARG 4) > > CL-USER 50 > (append '(lambda (arg)) (list '(* arg 4))) > (LAMBDA (ARG) (* ARG 4)) > > CL-USER 51 > (eval (append '(lambda (arg)) (list '(* arg 4)))) > #<anonymous interpreted function 4060000BB4> > > CL-USER 52 > (compile nil (append '(lambda (arg)) (list '(* arg 4)))) > #<Function 11 4060000DFC> > NIL > NIL > > CL-USER 53 > (mapcar (compile nil (append '(lambda (arg)) (list '(* arg 4)))) '(1 2 3 4)) > (4 8 12 16) > > --http://lispm.dyndns.org/ I evidently missed stating the crucial part. I wanted run-time compilation - the lambda will exist only briefly. This is really a matter of preference. I could have defined all the conversion functions a-priori form the stored conversion definitions, but I felt that would be an overkill. I have multiple variable types, and multiple possible units Pascal's post pointed me to `compile', and that has done the trick. Now I am off to carefully read the hyperspec section. Thanks.
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Self-producing programs in Common LISP Next: when to use #: |