Assuming CURRY1 returns a function, then that is not portable. The predicate-name given to SATISFIES is expected to be a symbol with a global function definition and there is no way to pass extra arguments.
LispWorks TYPEP is not checking for this (but SUBTYPEP does). -- Martin Simmons LispWorks Ltd http://www.lispworks.com/ >>>>> On Thu, 22 Feb 2024 11:09:02 +0100, Marco Antoniotti said: > > Hi Pascal > > this works in LW > > CL-USER 21 > > (deftype msb (&optional (bits 8)) `(satisfies ,(curry1 > 'msb-test bits))) > MSB > > CL-USER 22 > (typep 42 '(msb 6)) ; Less than or equal to 6, fail. > NIL > > CL-USER 23 > (typep 42 '(msb 7)) ; Greater than or equal to 7, succeed. > > T > > The function CURRY1 just curries one argument and MSB-TEST does the > check, taking two arguments, the second being the object to typep > (details irrelevant; trust me: it works). > > I know: done too much Haskell recently. > > MA > > On Wed, Feb 21, 2024 at 11:45 PM Pascal Bourguignon <p...@informatimago.com> > wrote: > > > Le 21/02/2024 à 22:10, Marco Antoniotti a écrit : > > > Hi > > > > > > I just stumbled upon this and I need confirmation. > > > > > > You cannot do anything like this, can you? > > > > > > (defstruct foo x) > > > > > > > > > (deftype foo-with-x (x) (satisfies 'foo-with-x-p)) ; No `x'! > > > > deftype is like defmacro really. > > > > So you could write: > > > > (deftype foo-with-x (x) > > `(satisfies ',(intern (format nil "FOO-WITH-~S-P" x))) > > > > But you would need to have defined also the predicate with the same name > > at compilation-time (or, when the type is used). > > > > > > > > cl-user> (deftype foo-with-x (x) > > `(satisfies ,(intern (with-standard-io-syntax (format nil > > "FOO-WITH-~S-P" x))))) > > FOO-WITH-X > > cl-user> (defstruct foo x) > > FOO > > cl-user> (defstruct bar y) > > BAR > > cl-user> (defun foo-with-x-p (o) (typep o 'foo)) > > FOO-WITH-X-P > > cl-user> (defun foo-with-y-p (o) (typep o 'bar)) > > FOO-WITH-Y-P > > cl-user> (typep (make-foo) '(foo-with-x x)) > > T > > cl-user> (typep (make-foo) '(foo-with-x y)) > > NIL > > cl-user> (typep (make-bar) '(foo-with-x y)) > > T > > cl-user> (typep (make-bar) '(foo-with-x x)) > > NIL > > cl-user> > > > > > (typep (make-foo :x 42) '(foo-with-x 42)) > > > > > > I.e., there is no way to pass the x to foo-with-x-p, is there? > > > > Nope. foo-with-x-p ie. the function given to satisfies must be the name > > of a predicate of the whole object. > > > > For something like: (typep (make-foo :x 42) '(foo-with-x 42)) > > you'd have to do: > > > > > > cl-user> (deftype foo-with-x (value) > > `(satisfies ,(intern (with-standard-io-syntax (format nil > > "FOO-WITH-X=~S-P" value))))) > > FOO-WITH-X > > cl-user> (defun foo-with-x=42-p (s) (= (foo-x s) 42)) > > FOO-WITH-X=42-P > > cl-user> (typep (make-foo :x 42) '(foo-with-x 42)) > > T > > cl-user> (typep (make-foo :x 33) '(foo-with-x 42)) > > NIL > > cl-user> > > > > Of course, what we'd want, is to generate the function or closure when > > the deftype is expanded. This is difficult, since we need to provide > > satisfies a function name, and it must be defined at compilation-time. > > > > > > I had a CLRFI that proposed to have lambda in satisfies, and that shows > > an example of what has to be done without a lambda. Cf. attachments. > > > > Note: this clrfi is not completely thought out, since for forms such as: > > > > (deftype restricted-list (element-type) > > `(and (satisfies proper-list-p) > > (satisfies ,(lambda (list) > > (every (lambda (item) (typep item > > ',element-type)) > > list))))) > > > > there is no closure (we build a new lambda expression for each use of > > the type. > > > > If we allowed (satisfies (lambda (...) ...))) we'd have to indicate in > > what lexical environment the lambda expression would be evaluated > > (assumedly, the lexical environment of the deftype body). I have not > > thought about the consequences of that. > > > > -- > > __Pascal Bourguignon__ > > >