[gambit-list] How to distinguish procedures from procedures?

Marc Feeley feeley at iro.umontreal.ca
Fri Mar 27 08:28:53 EDT 2020


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





More information about the Gambit-list mailing list