[gambit-list] How to distinguish procedures from procedures?
Dimitris Vyzovitis
vyzo at hackzen.org
Fri Mar 27 08:47:12 EDT 2020
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 at 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):
>
>
> (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
>
>
>
> > On Mar 27, 2020, at 7:06 AM, Jörg F. Wittenberger <
> Joerg.Wittenberger at softeyes.net> wrote:
> >
> > 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
> >
> > _______________________________________________
> > Gambit-list mailing list
> > Gambit-list at iro.umontreal.ca
> > https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list
>
>
> _______________________________________________
> Gambit-list mailing list
> Gambit-list at iro.umontreal.ca
> https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20200327/8a24fb3d/attachment.htm>
More information about the Gambit-list
mailing list