ccl icon indicating copy to clipboard operation
ccl copied to clipboard

NFUNCTION with a constructed LAMBDA

Open digikar99 opened this issue 3 years ago • 2 comments

On SBCL, the following works:

CL-USER> (let ((lambda-list '(a))
               (body         'a))
           (compile nil `(sb-int:named-lambda (my-fun-name) ,lambda-list ,body)))
#<FUNCTION (MY-FUN-NAME) {52EAE99B}>
NIL
NIL

Is there an equivalent way to do things on CCL without using eval?

CL-USER> (let ((lambda-list '(a))
               (body         'a))
           (compile nil `(ccl:nfunction (my-fun-name) (lambda ,lambda-list ,body)))) 
; raises error about invalid lambda expression
; Evaluation aborted on #<CCL::COMPILE-TIME-PROGRAM-ERROR #x30200229194D>.

digikar99 avatar Mar 19 '21 20:03 digikar99

The best I can find is ccl::cheap-eval-function, e.g. (ccl::cheap-eval-function 'foo '(lambda () 42) nil). I assume that someday cl:compile could be extended to accept nfunction forms.

phoe avatar Mar 19 '21 20:03 phoe

Hmm, the difference seems minor, and compute-cost is not a concern for the purpose. So, either should work I guess. (EDIT: May be the difference adds up for larger function bodies?)

CL-USER> (let ((lambda-list '(a))
               (body         'a))
           (time (loop repeat 1000
                       do (ccl::cheap-eval-function '(my-fun-name)
                                                    `(lambda ,lambda-list ,body) nil))))
(LOOP REPEAT 1000 DO (CCL::CHEAP-EVAL-FUNCTION '(MY-FUN-NAME) (LIST* 'LAMBDA (LIST* LAMBDA-LIST (LIST BODY))) NIL))
took 268,474 microseconds (0.268474 seconds) to run.
       3,313 microseconds (0.003313 seconds, 1.23%) of which was spent in GC.
During that period, and with 12 available CPU cores,
     272,559 microseconds (0.272559 seconds) were spent in user mode
          32 microseconds (0.000032 seconds) were spent in system mode
 10,192,000 bytes of memory allocated.
NIL

CL-USER> (let ((lambda-list '(a))
               (body         'a))
           (time (loop repeat 1000
                       do (eval `(ccl:nfunction (my-fun-name)
                                                (lambda ,lambda-list ,body))))))
(LOOP REPEAT 1000 DO (EVAL (LIST* 'NFUNCTION (LIST* '(MY-FUN-NAME) (LIST (LIST* 'LAMBDA (LIST* LAMBDA-LIST (LIST BODY))))))))
took 272,228 microseconds (0.272228 seconds) to run.
       2,987 microseconds (0.002987 seconds, 1.10%) of which was spent in GC.
During that period, and with 12 available CPU cores,
     276,055 microseconds (0.276055 seconds) were spent in user mode
           0 microseconds (0.000000 seconds) were spent in system mode
 10,240,096 bytes of memory allocated.
NIL

digikar99 avatar Mar 19 '21 20:03 digikar99