3 ms·
You're right, it could, if you prefer. In the same labels form with an extra parameter cs, which the yield's all pass in; or in a labels/flet form inside constr
by martinflack 10y ago
You're right, it could, if you prefer. In the same labels form with an extra parameter cs, which the yield's all pass in; or in a labels/flet form inside constraint.
(defmacro defsolver (name default constraints result)
(flet ((normal-var (var) `(iter (for ,var ,@(rest default))))
(custom-var (var spec) `(iter (for ,var in ,spec)))
(guard (expr) `(when ,expr))
(solved () `(return-from ,name ,result)))
(labels ((constraint (cs &aux (c (first cs)))
(flet ((yield (form) (append form (list (constraint (rest cs))))))
(cond ((null cs) nil)
((eq c :solved) (solved))
((symbolp c) (yield (normal-var c)))
((eq (first c) 'for) (yield (custom-var (second c) (third c))))
(t (yield (guard c)))))))
`(defun ,name () ,(constraint `(,@constraints :solved))))))
- kazinator 10y agoAll your functions can be in a single labels block now. It's okay for a non-recursive function to be a labels. flet is really for those situations in which labels cannot be used, like defining an inner foo which shadows and calls (i.e wraps) an outer foo.