Suppose I have something like this:
(define pair (cons 1 (lambda (x) (* x x))
If I want to return the front object of the pair I do this:
(car pair)
And it returns 1. However when the object is a procedure I don't get the exact description of it.
In other words:
(cdr pair)
returns #<procedure>
and not (lambda (x) (*x x))
.
How do I fix this?
Although there's no way to do this generally, you can rig up something to do it for procedures that you define.
Racket struct
s can define a prop:procedure
that allows the struct to be applied (called) as a procedure. The same struct can hold a copy of your original syntax for the function definition. That's what the sourced
struct is doing, below.
The write-sourced
stuff is simply to make the output cleaner (show only the original sexpr, not the other struct fields).
The define-proc
macro makes it simpler to initialize the struct -- you don't need to type the code twice and hope it matches. It does this for you.
#lang racket
(require (for-syntax racket/syntax))
;; Optional: Just for nicer output
(define (write-sourced x port mode)
(define f (case mode
[(#t) write]
[(#f) display]
[else pretty-print])) ;nicer than `print` for big sexprs
(f (sourced-sexpr x) port))
(struct sourced (proc sexpr)
#:property prop:procedure (struct-field-index proc)
;; Optional: Just to make cleaner output
#:methods gen:custom-write
[(define write-proc write-sourced)])
;; A macro to make it easier to use the `sourced` struct
(define-syntax (define-proc stx)
(syntax-case stx ()
[(_ (id arg ...) expr ...)
#'(define id (sourced (lambda (arg ...) expr ...)
'(lambda (arg ...) expr ...)))]))
;; Example
(define-proc (foo x)
(add1 x))
(foo 1) ; => 2
foo ; => '(lambda (x) (add1 x))
The procedure cons
evaluates its arguments: 1 is self-evaluating to 1; (lambda ...)
evaluates to an anonymous procedure. If you want to 'prevent' evaluation, you need to quote
the argument, as such:
> (define pair (cons 1 '(lambda (x) (* x x))
> (cdr pair)
(lambda (x) (* x x))