Lisp HUG Maillist Archive

Understanding satisfies clauses and eval-when

Hi,

I'm using LispWorks and wrote a deftype using a satisfies clause:

(defun cardp (object)
  (and (stringp object)
       (= (length object) 2)
       (find (char object 0) "A23456789TJQK")
       (find (char object 1) "cdhs")))

(deftype card ()
  "Cards are two-letter strings made of a rank followed by a suit."
  '(and (string 2) (satisfies cardp)))

It seems to work fine for me. But the Google Common Lisp Style Guide says "Implementations may, and some will, invoke SATISFIES-specified function at compile-time to test various relevant objects. That is why any function specified in a SATISFIES clause MUST accept objects of any type as argument to the function, and MUST be defined within an EVAL-WHEN".

So when I put it in an eval-when like this:
(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun cardp (object)
    (and (stringp object)
         (= (length object) 2)
         (find (char object 0) "A23456789TJQK")
         (find (char object 1) "cdhs"))))

In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.

If I want it to be a compiled function, what should I do?

I guess I can do something like:
(unless (compiled-function-p #'cardp)
  (compile 'cardp))

Or even just (compile 'cardp), but I'm not sure where the best place for it is (inside the same eval-when, or outside of it), or if there's something else I should be doing.

Mitch

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Re: Understanding satisfies clauses and eval-when



On 15 Sep 2019, at 19:43, Mitchell Chung <mkc94@hotmail.com> wrote:

Hi,

I'm using LispWorks and wrote a deftype using a satisfies clause:

(defun cardp (object)
 (and (stringp object)
      (= (length object) 2)
      (find (char object 0) "A23456789TJQK")
      (find (char object 1) "cdhs")))

(deftype card ()
 "Cards are two-letter strings made of a rank followed by a suit."
 '(and (string 2) (satisfies cardp)))

It seems to work fine for me. But the Google Common Lisp Style Guide says "Implementations may, and some will, invoke SATISFIES-specified function at compile-time to test various relevant objects. That is why any function specified in a SATISFIES clause MUST accept objects of any type as argument to the function, and MUST be defined within an EVAL-WHEN".

So when I put it in an eval-when like this:
(eval-when (:compile-toplevel :load-toplevel :execute)
 (defun cardp (object)
   (and (stringp object)
        (= (length object) 2)
        (find (char object 0) "A23456789TJQK")
        (find (char object 1) "cdhs"))))

In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.

If I want it to be a compiled function, what should I do?

I guess I can do something like:
(unless (compiled-function-p #'cardp)
 (compile 'cardp))

Or even just (compile 'cardp), but I'm not sure where the best place for it is (inside the same eval-when, or outside of it), or if there's something else I should be doing.

One simple way to ensure what you want, is to put the definition of cardp in a separate file, and to specify it as a dependency in the asd.

If you insist on keeping everything in a single file,  I would, for sake of clarity and simplicity write it as:

(eval-when (:compile-toplevel :load-toplevel :execute)
 (defun cardp (object)
   (and (stringp object)
        (= (length object) 2)
        (find (char object 0) "A23456789TJQK")
        (find (char object 1) "cdhs"))))

(eval-when (:compile-toplevel)
  (compile ‘cardp))


-- 
__Pascal J. Bourguignon__




Re: Understanding satisfies clauses and eval-when

On 15 Sep 2019, at 18:43, Mitchell Chung <mkc94@hotmail.com> wrote:

In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.

What this means is that, at compile time, CARDP is available as a function, but in LW it is not yet compiled.  That means that any typechecks done at compile-time might be a bit slower.

At run time (after your code is loaded), the function is compiled.  For instance, if I have a file "ts.lisp" containing:

    (eval-when (:compile-toplevel :load-toplevel :execute)
      (defun cardp (object)
        (and (stringp object)
             (= (length object) 2)
             (find (char object 0) "A23456789TJQK")
             (find (char object 1) "cdhs"))))
    
    (deftype card ()
     "Cards are two-letter strings made of a rank followed by a suit."
     '(and (string 2) (satisfies cardp)))

Then (in a cold Lisp):

- if you (compile-file "ts") then (compiled-function-p #'cardp) will be nil
- if you say (compile-file "ts: :load t) then (compiled-function-p #'cardp) will be true

Unless you are doing a huge number of typechecks at compile time it's hard to see that this would matter.

--tim 

RE: Understanding satisfies clauses and eval-when

Thanks for your replies, Pascal and Tim.

 

After doing some experiments, what’s happening to me is that I often use the LispWorks editor’s “Compile Defun” (Ctrl+Shift+C) or “Compile Buffer” (Ctrl+Shift+B) commands during development, and it results in (compiled-function-p #’cardp) being nil, similar to (compile-file “ts”) without :load t. Both of Pascal’s suggestions make (compiled-function-p #’cardp) true, or I can stop using those commands and use something else like asdf:load-system.

 

 

From: Tim Bradshaw <tfb@tfeb.org>
Sent: Sunday, September 15, 2019 1:12 PM
To: Mitchell Chung <mkc94@hotmail.com>
Cc: lisp-hug@lispworks.com
Subject: Re: Understanding satisfies clauses and eval-when

 

On 15 Sep 2019, at 18:43, Mitchell Chung <mkc94@hotmail.com> wrote:

 

In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.

 

What this means is that, at compile time, CARDP is available as a function, but in LW it is not yet compiled.  That means that any typechecks done at compile-time might be a bit slower.

 

At run time (after your code is loaded), the function is compiled.  For instance, if I have a file "ts.lisp" containing:

 

    (eval-when (:compile-toplevel :load-toplevel :execute)

      (defun cardp (object)

        (and (stringp object)

             (= (length object) 2)

             (find (char object 0) "A23456789TJQK")

             (find (char object 1) "cdhs"))))

    

    (deftype card ()

     "Cards are two-letter strings made of a rank followed by a suit."

     '(and (string 2) (satisfies cardp)))

 

Then (in a cold Lisp):

 

- if you (compile-file "ts") then (compiled-function-p #'cardp) will be nil

- if you say (compile-file "ts: :load t) then (compiled-function-p #'cardp) will be true

 

Unless you are doing a huge number of typechecks at compile time it's hard to see that this would matter.

 

--tim 

 

Re: Understanding satisfies clauses and eval-when

Just thinking about it, I would expect that a function inside EVAL-WHEN gets compiled with an editor compile-defun/region/buffer command.

You might check with LispWorks support and propose it as a feature.

Another way would be to use the menu command: File > Compile and Load ...

Regards

Rainer Joswig


Am 16.09.2019 um 03:23 schrieb Mitchell Chung <mkc94@hotmail.com>:

Thanks for your replies, Pascal and Tim.
 
After doing some experiments, what’s happening to me is that I often use the LispWorks editor’s “Compile Defun” (Ctrl+Shift+C) or “Compile Buffer” (Ctrl+Shift+B) commands during development, and it results in (compiled-function-p #’cardp) being nil, similar to (compile-file “ts”) without :load t. Both of Pascal’s suggestions make (compiled-function-p #’cardp) true, or I can stop using those commands and use something else like asdf:load-system.
 
 
From: Tim Bradshaw <tfb@tfeb.org> 
Sent: Sunday, September 15, 2019 1:12 PM
To: Mitchell Chung <mkc94@hotmail.com>
Cc: lisp-hug@lispworks.com
Subject: Re: Understanding satisfies clauses and eval-when
 
On 15 Sep 2019, at 18:43, Mitchell Chung <mkc94@hotmail.com> wrote:
 
In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.
 
What this means is that, at compile time, CARDP is available as a function, but in LW it is not yet compiled.  That means that any typechecks done at compile-time might be a bit slower.
 
At run time (after your code is loaded), the function is compiled.  For instance, if I have a file "ts.lisp" containing:
 
    (eval-when (:compile-toplevel :load-toplevel :execute)
      (defun cardp (object)
        (and (stringp object)
             (= (length object) 2)
             (find (char object 0) "A23456789TJQK")
             (find (char object 1) "cdhs"))))
    
    (deftype card ()
     "Cards are two-letter strings made of a rank followed by a suit."
     '(and (string 2) (satisfies cardp)))
 
Then (in a cold Lisp):
 
- if you (compile-file "ts") then (compiled-function-p #'cardp) will be nil
- if you say (compile-file "ts: :load t) then (compiled-function-p #'cardp) will be true
 
Unless you are doing a huge number of typechecks at compile time it's hard to see that this would matter.
 
--tim 

Re: Understanding satisfies clauses and eval-when

Yes, it is a bug that prevents it from being a compiled function in this case.

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/


>>>>> On Mon, 16 Sep 2019 12:34:49 +0200, Rainer Joswig said:
> 
> Just thinking about it, I would expect that a function inside EVAL-WHEN gets compiled with an editor compile-defun/region/buffer command.
> 
> You might check with LispWorks support and propose it as a feature.
> 
> Another way would be to use the menu command: File > Compile and Load ...
> 
> Regards
> 
> Rainer Joswig
> 
> 
> > Am 16.09.2019 um 03:23 schrieb Mitchell Chung <mkc94@hotmail.com>:
> > 
> > Thanks for your replies, Pascal and Tim.
> >  
> > After doing some experiments, what’s happening to me is that I often use the LispWorks editor’s “Compile Defun” (Ctrl+Shift+C) or “Compile Buffer” (Ctrl+Shift+B) commands during development, and it results in (compiled-function-p #’cardp) being nil, similar to (compile-file “ts”) without :load t. Both of Pascal’s suggestions make (compiled-function-p #’cardp) true, or I can stop using those commands and use something else like asdf:load-system.
> >  
> >  
> > From: Tim Bradshaw <tfb@tfeb.org> 
> > Sent: Sunday, September 15, 2019 1:12 PM
> > To: Mitchell Chung <mkc94@hotmail.com>
> > Cc: lisp-hug@lispworks.com
> > Subject: Re: Understanding satisfies clauses and eval-when
> >  
> > On 15 Sep 2019, at 18:43, Mitchell Chung <mkc94@hotmail.com <mailto:mkc94@hotmail.com>> wrote:
> >  
> > In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.
> >  
> > What this means is that, at compile time, CARDP is available as a function, but in LW it is not yet compiled.  That means that any typechecks done at compile-time might be a bit slower.
> >  
> > At run time (after your code is loaded), the function is compiled.  For instance, if I have a file "ts.lisp" containing:
> >  
> >     (eval-when (:compile-toplevel :load-toplevel :execute)
> >       (defun cardp (object)
> >         (and (stringp object)
> >              (= (length object) 2)
> >              (find (char object 0) "A23456789TJQK")
> >              (find (char object 1) "cdhs"))))
> >     
> >     (deftype card ()
> >      "Cards are two-letter strings made of a rank followed by a suit."
> >      '(and (string 2) (satisfies cardp)))
> >  
> > Then (in a cold Lisp):
> >  
> > - if you (compile-file "ts") then (compiled-function-p #'cardp) will be nil
> > - if you say (compile-file "ts: :load t) then (compiled-function-p #'cardp) will be true
> >  
> > Unless you are doing a huge number of typechecks at compile time it's hard to see that this would matter.
> >  
> > --tim 
> 
> 

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

RE: Understanding satisfies clauses and eval-when

Thanks Rainer and Martin.

I was thinking the "Compile and Load Buffer File" command is pretty similar and it's compiled, and was thinking in terms of having to load afterwards, so I am glad I could hear others' thoughts.

-----Original Message-----
From: owner-lisp-hug@lispworks.com <owner-lisp-hug@lispworks.com> On Behalf Of Martin Simmons
Sent: Tuesday, September 17, 2019 9:07 AM
To: lisp-hug@lispworks.com
Subject: Re: Understanding satisfies clauses and eval-when

Yes, it is a bug that prevents it from being a compiled function in this case.

-- 
Martin Simmons
LispWorks Ltd
https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.lispworks.com%2F&amp;data=02%7C01%7C%7Cbb91dbf644f14666497e08d73b898773%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637043334177286207&amp;sdata=0BjmVuQOp7FtgiYpUDA87sF3U9Cx8FGJfBwCR%2FRElAA%3D&amp;reserved=0


>>>>> On Mon, 16 Sep 2019 12:34:49 +0200, Rainer Joswig said:
> 
> Just thinking about it, I would expect that a function inside EVAL-WHEN gets compiled with an editor compile-defun/region/buffer command.
> 
> You might check with LispWorks support and propose it as a feature.
> 
> Another way would be to use the menu command: File > Compile and Load ...
> 
> Regards
> 
> Rainer Joswig
> 
> 
> > Am 16.09.2019 um 03:23 schrieb Mitchell Chung <mkc94@hotmail.com>:
> > 
> > Thanks for your replies, Pascal and Tim.
> >  
> > After doing some experiments, what’s happening to me is that I often use the LispWorks editor’s “Compile Defun” (Ctrl+Shift+C) or “Compile Buffer” (Ctrl+Shift+B) commands during development, and it results in (compiled-function-p #’cardp) being nil, similar to (compile-file “ts”) without :load t. Both of Pascal’s suggestions make (compiled-function-p #’cardp) true, or I can stop using those commands and use something else like asdf:load-system.
> >  
> >  
> > From: Tim Bradshaw <tfb@tfeb.org> 
> > Sent: Sunday, September 15, 2019 1:12 PM
> > To: Mitchell Chung <mkc94@hotmail.com>
> > Cc: lisp-hug@lispworks.com
> > Subject: Re: Understanding satisfies clauses and eval-when
> >  
> > On 15 Sep 2019, at 18:43, Mitchell Chung <mkc94@hotmail.com <mailto:mkc94@hotmail.com>> wrote:
> >  
> > In LispWorks, (compiled-function-p #'cardp) now returns NIL, SBCL returns T.
> >  
> > What this means is that, at compile time, CARDP is available as a function, but in LW it is not yet compiled.  That means that any typechecks done at compile-time might be a bit slower.
> >  
> > At run time (after your code is loaded), the function is compiled.  For instance, if I have a file "ts.lisp" containing:
> >  
> >     (eval-when (:compile-toplevel :load-toplevel :execute)
> >       (defun cardp (object)
> >         (and (stringp object)
> >              (= (length object) 2)
> >              (find (char object 0) "A23456789TJQK")
> >              (find (char object 1) "cdhs"))))
> >     
> >     (deftype card ()
> >      "Cards are two-letter strings made of a rank followed by a suit."
> >      '(and (string 2) (satisfies cardp)))
> >  
> > Then (in a cold Lisp):
> >  
> > - if you (compile-file "ts") then (compiled-function-p #'cardp) will be nil
> > - if you say (compile-file "ts: :load t) then (compiled-function-p #'cardp) will be true
> >  
> > Unless you are doing a huge number of typechecks at compile time it's hard to see that this would matter.
> >  
> > --tim 
> 
> 

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
https://nam11.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.lispworks.com%2Fsupport%2Flisp-hug.html&amp;data=02%7C01%7C%7Cbb91dbf644f14666497e08d73b898773%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637043334177286207&amp;sdata=I8BG2w2o%2BnxDeZtqNpBJeAbUfoYyfHFsSYjiZV6Z3UA%3D&amp;reserved=0

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-hug@lispworks.com
http://www.lispworks.com/support/lisp-hug.html

Updated at: 2020-12-10 08:29 UTC