alias a name for the clause of a macro - scheme

I would like to alias some racket 2htdp functions/macros, so that I can translate them in another language for my children.
Things which are functions I can simply alias with define. I'm having trouble with the big-bang structure; If I try to alias on-tick for instance, everytime I get big-bang: [new-name] clauses are not allowed within big-bang.
I tried various variants of define-syntax but I could not make it work so far (that said, I'm a complete racket newbie).
Something like this works (well, ladja is not defined):
#lang racket
(require 2htdp/universe 2htdp/image)
(big-bang 0
(on-tick (lambda (x) (+ x 1)))
(to-draw (lambda (x) (place-image ladja 150 x (prazni-prostor 300 300))))
(stop-when (lambda (x) (= x 300))))
But this doesn't (triggers the error):
#lang racket
(require 2htdp/universe 2htdp/image)
(define new-name on-tick)
(big-bang 0
(new-name (lambda (x) (+ x 1)))
(to-draw (lambda (x) (place-image ladja 150 x (prazni-prostor 300 300))))
(stop-when (lambda (x) (= x 300))))
I see that big-bang is a macro, so that explains the issue: I guess I would have to be able to force my macro to be evaluated first, somehow?

If you're writing a module that you would require into your program, then you can use provide with rename-out to provide an alias:
In big-bang-with-new-name.rkt:
#lang racket
(require 2htdp/universe 2htdp/image)
(provide big-bang
to-draw
stop-when
empty-scene
(rename-out [on-tick new-name]))
Using it in another file:
#lang racket
(require "big-bang-with-new-name.rkt")
(big-bang 0
[new-name (lambda (x) (+ x 1))]
[to-draw (lambda (x) (empty-scene 200 200))]
[stop-when (lambda (x) (= x 300))])
Many macros use free-identifier=? to recognize keywords like this. Rename transformers cooperate with free-identifier=? to create exact aliases. This means you can also define new-name as a rename transformer in the main file like this:
#lang racket
(require 2htdp/universe 2htdp/image)
(define-syntax new-name (make-rename-transformer #'on-tick))
(big-bang 0
[new-name (lambda (x) (+ x 1))]
[to-draw (lambda (x) (empty-scene 200 200))]
[stop-when (lambda (x) (= x 300))])

Related

How to fix the 'cannot change constant' error

I have this code so far
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))
it gives me the error define-values: assignment disallowed;
cannot change constant
constant: max
I'm not sure how to fix this or what it means.
In DrRacket in the bottom left there is a dropdown where you can select lanaguage. From there you can select "Choose language" and click "Show details". For legacy languages such as R5RS you have the option "Disallow redefinition of initial bindings".
Now according to the R5RS your redefinition can only extend the functionality and that for the data types the original binding worked with should work the same in the new definition. The reason for this is the ability to constant fold the code. Thus the code below is invalid:
(define + -)
(+ 5 3)
; ==> 7
This might look strange but the program is in violation with the report and because of that the result might as well have been the string "banana" as far as the report is concerned. In R5RS you need to make it compatible for it to be Scheme:
(define numeric-max max)
(define max
(lambda (v1 . vs)
(if (number? v1)
(apply numeric-max v1 vs)
(lambda (x) (numeric-max (v1 x) ((car vs) x))))))
With R6RS you are free of this by not importing the binding at all:
#!r6rs
(import (except (rnrs base) max))
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))
If you want to make max available you can do the same as in R5RS with named imports:
#!r6rs
(import (except (rnrs base) max)
(only (rnrs control) case-lambda)
(rename (rnrs base) (max numeric-max)))
(define max
(case-lambda
((v1 v2)
(if (number? v1)
(numeric-max v1 v2)
(lambda (x) (numeric-max (v1 x) (v2 x)))))
(args
(apply numeric-max args))))
And of coruse this works in #lang racket as well:
#lang racket
(require (rename-in racket/base [max numeric-max]))
(define max
(case-lambda
((v1 v2)
(if (number? v1)
(numeric-max v1 v2)
(lambda (x) (numeric-max (v1 x) (v2 x)))))
(args
(apply numeric-max args))))
The problem you are facing is that max is already defined and you are trying to re-define it.
More importantly, name max is not appropriate for what you are trying to use it for. You are calling max with couple of arguments that are functions. It returns a lambda that can be invoked with a variable.
Your envisioning usage such as
((max sin cos) 10)
A name such as max-proc-value would be more appropriate and will avoid the problem that you have run into.
If you put this in the definition window (the upper one) everything works.
#lang racket
(define (max f g)
(define (int-max x y)
(if (> x y) x y))
(lambda (x) (int-max (f x) (g x))))

Internal Definitions in Block Structure

(define (sqrt x)
  (define (good-enough? guess x)
    (< (abs (- (square guess) x)) 0.001))
  (define (improve guess x)
    (average guess (/ x guess)))
  (define (sqrt-iter guess x)
    (if (good-enough? guess x)
        guess
        (sqrt-iter (improve guess x) x)))
  (sqrt-iter 1.0 x))
I can't seem to wrap my head around around internal block structure. If the syntax for define is: (define procedure arg arg body). How are you able to define all the other local-scope variables inside the top-level define?
Is there a syntax exception for defines?
The syntax for define is not (define procedure arg .. body). It is either (define (name . args) defines ... body1 bodyn ...) which is a shortcut for (define name (lambda args defines ... body1 bodyn ...)). Note that x ... means zero or more so (lambda (a b) (+ a b)) is fine but (lambda (a b) (define (test) (+ a b))) isn't.
Internal define is handled by the lambda syntax. Basically it gets rewritten to a letrec. So
(define (sqrt x)
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001))
(define (improve guess x)
(average guess (/ x guess)))
(define (sqrt-iter guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt-iter 1.0 x))
Becomes:
(define sqrt
(lambda (x)
(letrec ((good-enough? (lambda (guess x)
(< (abs (- (square guess) x)) 0.001)))
(improve (lambda (guess x)
(average guess (/ x guess))))
(sqrt-iter (lambda (guess x)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))))
(sqrt-iter 1.0 x))))
Obviously the reason for using local define is to keep it flatter and more readable than letrec. Keeping the same name even though they are totally different beasts that are handled by different parts of the implementation is a simplification for scheme programmers but harder to grasp and understand if you try to figure out how scheme implementations work.

Is there a Scheme toString method for a procedure?

I want to be able to take a procedure and see what it looks like. Is this possible?
For example, let's say I have:
(define (some-func x)
(+ x 1))
What I want to do is apply some amazing function (say, stringify) to some-func and be able to look at its guts.
\> (stringify some-func)
"(lambda (x) (+ x 1))"
I haven't found any Racket libraries that do it. Can it be done?!
In R6RS, there is no sure way to determine if two procedures are equivalent; even an expression like (let ((p (lambda () 42))) (eqv? p p)) is not guaranteed to be true.
R7RS addresses that by using the concept of "location tags", where each lambda expression generates a unique location tag. Then eqv? works for procedures by comparing location tags: thus, (let ((p (lambda () 42))) (eqv? p p)) is true, and (eqv? (lambda () 42) (lambda () 42)) is false.
There is no reliable way to get the source of a procedure (many implementations macro-expand and compile the procedures, discarding the original source), and even if you could, you could not use it to compare if two procedures are "equal", because of closures (and that two procedures could have the same "source" but have their free variables bound to different things). For example, consider the two expressions (let ((x 1)) (lambda () x)) and (let ((x 2)) (lambda () x)). They have the same "source", but nobody in their right mind would claim that they are equivalent in any way.
Note, you could easily implement a define alternative to keep the source around. You don't avoid the lexical issues but, modulo that, you've got something with limited use.
(define name->source-mapping '())
(define (name->source name)
(cond ((assq name name->source-mapping) => cdr)
(else #f)))
(define (name->source-extend name source)
(set! name->source-mapping (cons (cons name source) name->source-mapping))
(define-syntax define-with-source
((_ (name args ...) body1 body2 ...)
(define name
(begin (name->source-mapping-extend 'name '(lambda (args ...) body1 body2 ...))
name->source-mapping))
(lambda (args ...) body1 body2 ...)))))
[Above does not replace (define name value) syntax; consider the above an example only.]

Static signature for higher order function in Bigloo Scheme

Does anyone know how to create a static signature for a higher order function in the module export section in the Bigloo Scheme language?
Here is how far I got
(module test
(export (adder ::double)))
(define (adder x)
(lambda (y)
(set! x (+ x y))
x))
The following will work, but I want to keep all the type data in the module declaration
(module test
(export (adder ::double)))
(define (adder x)
(lambda (y::double)::double
(set! x (+ x y))
x))

How to write a macro that maintains local state?

This seems to work, it's a macro that expands to successive integers depending on how many times it has been expanded.
;; Library (test macro-state)
(library
(test macro-state)
(export get-count incr-count)
(import (rnrs))
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
)
;; Program
(import (rnrs) (for (test macro-state) expand))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
(write (list (m) (m) (m)))
(newline)
;; prints (1 2 3)
But it's clumsy to me because the macro state *count* and the macro m itself are in different modules. Is there a better way to do this in r6rs, preferably one that doesn't split the implementation over two modules?
EDIT
I should make it clear that although this example is just a single macro, in reality I'm looking for a method that works when multiple macros need to share state.
You can make the state local to the macro transformer:
(define-syntax m
(let ()
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1)))
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count))))))))
Edited to add: In Racket, you can also do this:
(begin-for-syntax
(define *count* 0)
(define (get-count) *count*)
(define (incr-count) (set! *count* (+ *count* 1))))
(define-syntax m
(lambda (x)
(syntax-case x ()
((m) (begin (incr-count) (datum->syntax #'m (get-count)))))))
But I don't think R6RS has anything that corresponds to begin-for-syntax.

Resources