Hi,
A few questions regarding procedures:
There are several classes of objects passing the `procedure?` predicate.
- Is there a full list?
- How expensive are those at startup initialization and call time? (A rough ordering would do. Just to avoid expensive ones when there's the option.)
- I tend to use the following receipe to control the global exports with gambit (currently nailed in practice to 0.9.2 for use with lambdanative). Does imply any runtime overhead vs. no use of `let` and resorting to gambits namespace facility?
(define my-exported-proc #f)
(let (...) (define (my-private-proc ...) ...) (define (my-to-be-exported ...) ...) (set! my-exported-proc my-to-be-exported))
- The real question of mine: How could I create additional runtime predicates for procedures with minimal overhead? Any way to attach tags to procedures? (Let's rule out the trivial solution to collect procedures which should pass the predicate in a data structure and look it up.)
I need something where this fiction make sense (upper case be "dunno how"):
;; ATTACH-TAG! is compiletime, maybe even only compiletime. (define-macro (bless! proc tag) `(ATTACH-TAG! ,proc ',tag))
(define (make-blessed tag) (lambda (obj) (and (procedure? obj) (eq? (GET-TAG obj) tag))))
(define ispure? (make-blessed 'pure))
(bless! + 'pure)
;;; at runtime:
(ispure? +) ; => #t (ispure? -) ; => #f ;; yeah, we forgot to bless is :-/
Thanks so much
Jörg
Afficher les réponses par date
The easiest solution that comes to mind is to use a weak eq? hash table to attach the information to the procedures (or any object):
(define info (make-table test: eq? weak-keys: #t))
(define (inc x) (+ x 1)) (define (squ x) (* x x))
(table-set! info inc "increment function") (table-set! info squ "square function")
(define (show proc) (pretty-print (list proc 'is (table-ref info proc "unknown"))))
(show inc) ;; prints: (#<procedure #2 inc> is "increment function") (show squ) ;; prints: (#<procedure #3 squ> is "square function") (show car) ;; prints: (#<procedure #4 car> is "unknown")
Another solution that is a bit hackish is to use a wrapper closure that stores the information in the closure’s free variables. The implementation is a bit more complicated because closures are represented differently by the compiler and interpreter:
(define-type procinfo comment)
(define (attach comment proc) (let ((@procinfo (make-procinfo comment))) (lambda args (##first-argument @procinfo) ;; keep @procinfo in the free vars (apply proc args))))
(define (get-comment proc default)
(define (extract x) (if (procinfo? x) (procinfo-comment x) default))
(cond ((not (##closure? proc)) default) ((##interp-procedure? proc) (let ((rte (##interp-procedure-rte proc))) (extract (and (vector? rte) (= 2 (vector-length rte)) (vector-ref rte 1))))) (else (extract (##closure-ref proc 1)))))
(define dec (attach "decrement function" (lambda (x) (- x 1))))
(pp (get-comment dec "unknown")) ;; prints: "decrement function" (pp (get-comment inc "unknown")) ;; prints: "unknown" (pp (get-comment car "unknown")) ;; prints: "unknown"
Yet another way is to use the builtin ##decompile procedure (or the ##subprocedure-info primitive it calls):
(declare (debug)) ;; keep source code in the compiled code
(define (cube x) "this is the cube function" (expt x 3))
(##decompile cube) ;; => (lambda (x) "this is the cube function" (expt x 3))
The cell containing the procedure’s information (and accessed by ##subprocedure-info and ##subprocedure-parent-info) is embedded in the generated code and is read-only. Gambit would have to be extended to make it mutable.
Marc
The closure trick is neat -- perhaps we can use it for docstrings, which is a commonly requested feature in Gerbil.
-- vyzo
On Fri, Mar 27, 2020 at 2:29 PM Marc Feeley feeley@iro.umontreal.ca wrote:
Marc,
On Fri, 27 Mar 2020 08:28:53 -0400 Marc Feeley feeley@iro.umontreal.ca wrote:
The easiest solution that comes to mind is to use a weak eq? hash table to attach the information to the procedures (or any object):
.....
thank you soo much.
Looks very helpful. I need to digest that. Thanks again.
Jörg