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