[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