udem-dlteam / libs

Repo to develop new libraries for Gambit
5 stars 1 forks source link

SRFI 27: Sources of Random Bits #16

Open lassik opened 4 years ago

lassik commented 4 years ago

https://srfi.schemers.org/srfi-27/srfi-27.html

According to Gambit's manual, this is already built-in. We just need to add a (srfi 27) library wrapper.

lassik commented 4 years ago

Some procedures such as random-integer are in the empty namespace, which I just learned is different from the ## namespace. Can you access things in the empty namespace from within a define-library form?

feeley commented 4 years ago

One way is to use an explicit namespace declaration in your code, for example:

(define-library (foobar)
  (export stuff)
  (import (scheme base))
  (begin
    (##namespace ("" pp)) ;; map pp to empty namespace
    (define (stuff x)
      (pp x))))
lassik commented 4 years ago

Nice. That doesn't seem to affect re-exports, however.

These don't currently work:

(define-library (srfi 27)
  (export random-integer)
  (begin (##namespace ("" random-integer))))

(define-library (srfi 27)
  (import (only (scheme base) define))
  (export random-integer)
  (begin (##namespace ("" random-integer))
         (define random-integer random-integer)))

(define-library (srfi 27)
  (import (only (scheme base) define let))
  (export random-integer)
  (begin (define random-integer
           ((lambda ()
              (namespace ("" random-integer))
              random-integer)))))
feeley commented 4 years ago

These explicit ##namespace declarations are purely local to the code implementing the body (as they should be since they are at a lower level than the module system).

lassik commented 4 years ago

Actually this was my mistake:

(define-library (srfi 27)
  (import (only (scheme base) define let))
  (export random-integer)
  (begin (define random-integer
           ((lambda ()
              (namespace ("" random-integer))
              random-integer)))))

This works fine:

(define-library (srfi 27)
  (import (only (scheme base) define lambda))
  (export random-integer)
  (begin (define random-integer
           ((lambda ()
              (##namespace ("" random-integer))
              random-integer)))))

I can do the wrappers using this technique.

feeley commented 4 years ago

OK... BTW it is shorter to do (let () (##namespace ("")) random-integer) .

lassik commented 4 years ago
$ gsi gambit/libs/
Gambit v4.9.3

> (define original random-integer)
> (eq? original random-integer)
#t
> (import (srfi 27))
> (apropos "random-integer")
"srfi/27#" namespace:
  random-integer
empty namespace:
  random-integer
> srfi/27#random-integer
#<procedure #2 random-integer>
> (eq? srfi/27#random-integer random-integer)
#t
> (eq? srfi/27#random-integer original)
#t
lassik commented 4 years ago

OK... BTW it is shorter to do (let () (##namespace ("")) random-integer) .

You're right. I didn't realize Gambit supports a let without variables.

lassik commented 4 years ago

Seems let with no variables is standardized in R7RS. The body must still have at least one expression.

feeley commented 4 years ago

The shim approach will work for now, but with reexportation it will be possible to eliminate the srfi/27#random-integer variable and to allow the compiler to do more optimizations (not specifically with random-integer but for primitives that are inlined/constant-folded/etc such as bitwise-and).

I'm currently working on implementing reexportation...

lassik commented 4 years ago

Great! How difficult is it to implement? If it's just a few days, I'll wait until it's done before doing the SRFI wrappers.

feeley commented 4 years ago

BTW, you might be interested in knowing that in the external representation for procedures #<procedure #N name-of-procedure> the name of the procedure comes from looking up the value in the global environment (to determine the name of the global variable that contains that procedure). Here's an example:

> (define original random-integer)
> original
#<procedure #2 random-integer>
> (set! random-integer 42)
> original
#<procedure #2 original>

The reexportation feature should be available later today.

lassik commented 4 years ago

Makes sense. In a similar vein, Emacs has an apropos-value command that looks for a particular Lisp value in all global variables and lets you search for e.g. a string that you know is stashed somewhere. Pretty wild.

Once again, thank you for your impressive dedication in taking care of Gambit.