I was afraid of that. Another wart in the CLHS. Even if the Type Police will tell me that "it's for my own good". :)
Cheers -- MA On Thu, Feb 22, 2024 at 12:38 PM Martin Simmons <mar...@lispworks.com> wrote: > 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__ > > > > > >