Reputation: 719
I don't know of any practical uses for this, it just came to my mind whether there is any thing comparable to defmethod
to defun
for lambda
? Something like this
(defmacro tlambda (args &body body)
(let* ((gf-name (subseq (write-to-string (gensym)) 2))
(gf-sym (read-from-string gf-name)))
`(progn (defmethod ,gf-sym ,args ,@body)
(prog1 (symbol-function ',gf-sym) (unintern ',gf-sym)))))
(tlambda ((x fixnum))) ;#<STANDARD-GENERIC-FUNCTION #:G759 (1)>
(funcall (tlambda ((x fixnum)) (* x 2)) 4) ;8
(funcall (tlambda ((x list)) (second x)) '(a s d f)) ;S
(funcall (tlambda ((x string)) (string-upcase x)) "lambda") ;"LAMBDA"
Upvotes: 1
Views: 175
Reputation:
I agree with Svante that you probably don't want this. But if you did want it the way you are doing it is very confused: I simply don't understand what you are doing with gf-sym
and gf-name
but it represents some quite serious confusion about symbols I think (and is almost certainly unsafe). Instead you could do something like this:
(defmacro tlambda (&body cases)
(let* ((gf-name (gensym)))
`(progn
,@(mapcar (lambda (case)
`(defmethod ,gf-name ,@case))
cases)
(symbol-function ',gf-name))))
And now
> (let ((l (tlambda
((x y) (cons x y))
((x (y integer))
(declare (ignore x)) y))))
(values (funcall l 'a 'b)
(funcall l 'a 1)))
(a . b)
1
I'm not sure whether the objects created by tlambda
can be garbage-collected: it may be they can.
Upvotes: 0
Reputation: 51501
I do not think that this makes sense in the shape you show. What should happen if the type doesn't match? If you just want to check types, use check-type
.
Defmethod
and defun
are not really comparable, by the way. Defun
registers a function, while defmethod
adds a method to an existing (though maybe implicitly created) generic function. The types that you use in a method definition are used to dispatch (runtime polymorphism) to the right method upon invocation of the generic function. The mechanisms for this dispatch are a bit expensive when constructed, so you probably shouldn't try to do that on the fly (something like a generic-lambda
) or transiently (something like a method-let
).
Instead, use (e
/c
)typecase
and similar for ad hoc dispatch, and check-type
for checking types. There are also libraries for pattern-based polymorphism (e. g. optima, trivia), which you could use for more elaborate cases.
Upvotes: 3