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__ >