Redeem the source procedure in the racket?

Does the racket have something like a guile procedure-procedure function, for example:

(define (plus-one x) (+ 1 x))
(source of the plus-one procedure) → (quote (+ 1 x))

I am trying to do something similar to a debugging tool for novice students, in which they can see a partial or full evaluation of a particular function when they play with its behavior in 2htdp / universe. Therefore, I could use the macro for this case, except in my program, I still would like the definition to look exactly the same as usual, so I can’t just quote it first and examine it later, if not redefined definition ... what might be good, but I would appreciate how best to do this.

+3
source share
3 answers

The problem you are facing is related to language restriction for beginners: usually higher-order functions are a syntax error in the language, because beginners do not yet know about them.

There is a way to discard this. Your procedure source may be flagged as one of the exceptions to this limitation using provide-higher-order-primitive , which is specifically designed to work with BSL.

Here is what your library looks like with it:

#lang racket/base
(require lang/prim
         racket/bool
         (for-syntax racket/base))

(provide define/save-source)
(provide-higher-order-primitive procedure-name (fn))
(provide-higher-order-primitive procedure-source (fn))


(define *procedure-name-hash* (make-hash))  
(define *procedure-source-hash* (make-hash))  
(define (save-source! fn name body)  
   (hash-set! *procedure-name-hash* fn name)
   (hash-set! *procedure-source-hash* fn body))

(define (procedure-name fn)
  (hash-ref *procedure-name-hash* fn false))
(define (procedure-source fn)
  (hash-ref *procedure-source-hash* fn false))

(define-syntax define/save-source
  (syntax-rules ()
    ((_ (name formals ...) body-expressions ...)
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name (λ(formals ...) body-expressions ...))
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name value)
     (define name value))))

BSL programs that use this should be able to use the name of the procedure and the source of the procedures.

+1
source

I did something like this:

(provide (rename-out (def/help define)
                     (define-syntax/help define-syntax))
         help)

(define-syntax def/help
  (syntax-rules ()
    ((_ name description signature (λ(vs ...) exps ...))
     (begin
       (add-help! 'name description 'signature '(λ(vs ...)))
       (define name (λ(vs ...) exps ...))))))
...
> (require "working.ss")
> (define (plus a b) (+ a b))
X define: bad syntax in: (define (plus a b) (+ a b))
> (define plus
    "Add two numbers"
    (int int -> int)
    (λ(a b) (+ a b)))
> (help plus)
plus
Add two numbers
(int int -> int)
(λ (a b))

( , .) , , , ?

+1

:

( (rename-out (define/save-source define)) procedure-source)

(define *procedure-name-hash* (make-hash))  
(define *procedure-source-hash* (make-hash))  
(define (save-source! fn name body)  
   (hash-set! *procedure-name-hash* fn name)
   (hash-set! *procedure-source-hash* fn body))

(define (procedure-name fn)
  (hash-ref *procedure-name-hash* fn false))
(define (procedure-source fn)
  (hash-ref *procedure-source-hash* fn false))

(define-syntax define/save-source
  (syntax-rules ()
    ((_ (name formals ...) body-expressions ...)
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name (λ(formals ...) body-expressions ...))
     (begin
       (define name (λ(formals ...) body-expressions ...))
       (save-source! name 'name '(λ(formals ...) body-expressions ...))))
    ((_ name value)
     (define name value))))

and in repl:

> (define/save-source (plus-one x) (+ 1 x))
> (procedure-source plus-one)
(λ (x) (+ 1 x))
> (plus-one 3)
4
> 

What is strange is that in the student replica I get:

> (procedure-source update-target)
(cons 'λ (cons (cons 'x empty) (cons (cons '+ (cons 'x (cons 20 empty))) empty)))
> (update-target 30)
function call: expected a defined function name or a primitive operation name after an open parenthesis, but found something else
0
source

All Articles