decent way of nested definition in scheme - scheme

I want to define a constant foo using an auxiliary function, say, bar. And I want to hide bar inside the definition of foo, so I come with this code:
(define foo
(define (bar n)
(+ n n))
(bar 1))
However, this definition causes syntax errors in many scheme implementations(mit-scheme, racket, guile, etc.).
I have three workarounds but none of them seems satisfactory:
(define foo1
((lambda ()
(define (bar n)
(+ n n))
(bar 1))))
(define foo2
(let ((bar (lambda (n) (+ n n))))
(bar 1)))
(define (foo3)
(define (bar n)
(+ n n))
(bar 1))
foo1 uses lambda to create an environment of writing auxiliary definitions and the parentheses seem somehow confusing.
foo2 uses let expression but I can no longer use the syntactic sugar (define (f n) ...) => (define f (lambda (n) ...))
foo3 requires less modification comparing with the original one, but every time I want this value, I have to call (foo3) and do the computation all over again.
My questions are:
I think this kind of nested definition makes sense, but why it is considered a syntax error?
is there any decent way to write the definition of foo?

If I understand your question correctly, another idiomatic way to do this in Racket would be to use a module.
This module could be defined using a separate file:
;; foo.rkt
#lang racket
(define (bar n)
(+ n n))
(define foo (bar 1))
(provide foo)
;; use-foo.rkt
#lang racket
(require "foo.rkt")
foo
Or via a module form within one file:
#lang racket
(module 'foo-mod racket
(define (bar n)
(+ n n))
(define foo (bar 1))
(provide foo))
(require 'foo-mod)
foo
Is this concise compared to your examples? Of course not. But in practice this sort of encapsulation usually works fine at a module granularity.
For instance a private helper like bar might be useful in defining multiple other functions or constants.
Often the file form is more convenient: If a helper like bar is not nested, but instead at the module top level for foo.rkt, it's easier to debug it in a REPL.
p.s. Racket provides a define-package form for compatibility with Chez Scheme, but it's not idiomatic in Racket; instead you'd use a submodule.

Your original code has a syntax error because the required syntax for define of an identifier is
(define <identifier> <expression>)
but your syntax is
(define <identifier> <definition> <expression>)
You need some way to group the <definition> and the <expression>. What you are looking for is something that allows lexical definitions - in Scheme this is a syntactic form with a <body>. The syntactic forms for this are a lambda or any let (and variants) or a 'programmatic' begin.
But, this is easily done in Scheme w/o needing Racket extensions or extra, empty lexical environments or a <body> syntactic form. Just use what you considered 'unsatisfactory'
(define foo
(let ((bar (lambda (x) (+ x x))))
(bar 1)))
or even
(define foo
((lambda (x) (+ x x)) 1))
Too much sugar, even syntactic sugar, my have adverse health consequences...

foo1 is also equivalent to the following:
(define foo1
(let ()
(define (bar n)
(+ n n))
(bar 1)))
Is that more acceptable-looking to you?

Answering your questions:
define can only be used in certain ways, as mandated by the specification. What you want to do isn't covered by the specification, hence the error. As you know, define assigns a name to the value of an expression, it's just that you can't directly create internal definitions in its context.
But there are other expressions that allow creating new bindings in this context. IMHO foo2 is the best option here, and it's idiomatic, too. And if bar were a recursive definition, you could use letrec.
But if loosing a bit of syntactic sugar bothers you (because of the way procedures are defined inside a let expression), then try using local, it'll work in Racket:
(define foo
(local [(define (bar n) (+ n n))]
(bar 1)))

Related

Is letrec only meant for defining procedures?

Is Scheme's letrec only meant for defining procedures, especially recursive ones? I am asking because it appears to be possible to bind non-procedures using letrec. For example, (letrec ((x 1) (y 2)) (+ x y)). If Scheme's letrec is only meant for procedures, then why isn't its syntax constrained to allow procedures only?
Consider this use of letrec to define two mutually recursive procedures:
(letrec ((is-even? (lambda (n)
(let ((n (abs n)))
(if (= n 0)
#t
(is-odd? (- n 1))))))
(is-odd? (lambda (n)
(let ((n (abs n)))
(if (= n 0)
#f
(is-even? (- n 1)))))))
(is-even? 123))
If we use Common Lisp's LABELS instead of Scheme's letrec, these two mutually recursive procedures would be defined like this instead:
(labels ((even-p (n)
(let ((n (abs n)))
(if (= n 0)
t
(odd-p (- n 1)))))
(odd-p (n)
(let ((n (abs n)))
(if (= n 0)
nil
(even-p (- n 1))))))
(even-p 123))
If letrec is only useful for defining procedures, then why isn't its syntax constrained like that of LABELS to allow only procedures in its initialization forms?
It is mostly useful for binding procedures, yes: the variables bound by letrec can't refer to their own bindings until afterwards, so something like
(letrec ((x (list x)))
x)
Does not work: see my other answer.
However first of all it would be a strange restriction, in a Lisp-1 like Scheme, to insist that letrec can only be used for procedures. It's also not enforcable other than dynamically:
(letrec ((x (if <something>
(λ ... (x ...))
1)))
...)
More importantly, letrec can be used in places like this:
(letrec ((x (cons 1 (delay x))))
...)
which is fine, because the reference to the binding of x is delayed. So if you have streams, you can then do this:
;;; For Racket
(require racket/stream)
(letrec ((ones (stream-cons 1 ones)))
(stream-ref ones 100))
It is useful for defining procedures, but it is not only for that.
The difference between let* and letrec is defined in the manual:
Like let, including left-to-right evaluation of the val-exprs, but the locations for all ids are created first, all ids are bound in all val-exprs as well as the bodys, and each id is initialized immediately after the corresponding val-expr is evaluated.
The order in which ids are bound is significant here, as let* would not be useful for defining mutually-recursive procedures: the first procedure would have an unbound id for the second procedure.
As your example comes directly from the manual I think you should see that CS information is often dense and terse when reading, but it does say very clearly what the difference is with letrec.

Class methods can't be used for andmap?

While working on a Racket program for managing employee time sheets, I found that I cannot use a class's member method for andmap.
#lang racket
(define example%
(class object%
(super-new)
(define/public (is-even? n)
(even? n))
(define/public (test)
(println
;; Next line causes error.
(andmap is-even? '(2 3 4))))))
;; if the following line is used, everything works properly
;;(andmap even? '(2 3 4))))))
(let ([tmp (new example%)])
(send tmp test))
DrRacket gives the following error message on attempt to run this simple program:
class: misuse of method (not in application) in: is-even?
Of course I don't need to use andmap ... It is just a luxury since I can feed a lambda and the result of map into addmap and get the same functionality...
Unfortunately, this doesn't work either, giving the same error as the previous program...
#lang racket
(define example%
(class object%
(super-new)
(define/public (iseven? n)
(even? n))
(define/public (test)
(println
(let ([true? (lambda
(v)
(equal? v #t))])
(andmap true?
;; map also refuses to use my class's method...
;; so much for my hacky workaround idea.
(map iseven? '(2 3 4))))))))
(let ([tmp (new example%)])
(send tmp test))
I like to fix my own problems so I looked up the given error message. I didn't find anything related. This leads to the following question: Why can't andmap, map, etc. use a class's method for their procedure argument?
PS: The actual class is significantly more complicated, but this is a minimal, verifiable example. :)
In Racket, a method is actually implemented by a macro that rewrites
(method arg ...)
to
(method-impl this arg ...)
where method-impl is bound either to the method implementation itself (if the method is private or final) or to some code that fetches the right method implementation from the class's vtable.
You can eta-expand the method name, like this:
(andmap (lambda (x) (is-even? x)) xs)
or you can use for/and:
(for/and ([x (in-list xs)]) (is-even? x))
You just have to use is-even? (or any other method name) in operator position.
As to why Racket's class library works that way: I'm not sure. It would be possible to make method names used as expressions (ie, not in operator position) do the lambda wrapping automatically; the current implementation deliberately doesn't do that, but I'm not sure what the rationale is.

Scheme/Guile: Variable self-re-definition inside a function

I feel that understanding this subtlety might help me to understand how scope works in Scheme.
So why does Scheme error out if you try to do something like:
(define (func n)
(define n (+ 1 n))
n)
It only errors out at runtime when calling the function.
The reason I find it strange is because Scheme does allow re-definitions, even inside functions. For example this gives no error and will always return the value 5 as expected:
(define (func n)
(define n 5)
n)
Additionally, Scheme also seems to support self-re-definition in global space. For instance:
(define a 5)
(define a (+ 1 a))
gives no error and results in "a" displaying "6" as expected.
So why does the same thing give a runtime error when it occurs inside a function (which does support re-definition)? In other words: Why does self-re-definition only not work when inside of a function?
global define
First off, top level programs are handled by a different part of the implementation than in a function and defining an already defined variable is not allowed.
(define a 10)
(define a 20) ; ERROR: duplicate definition for identifier
It might happen that it works in a REPL since it's common to redefine stuff, but when running programs this is absolutely forbidden. In R5RS and before what happened is underspecified and didn't care since be specification by violating it it no longer is a Scheme program and implementers are free to do whatever they want. The result is of course that a lot of underspecified stuff gets implementation specific behaviour which are not portable or stable.
Solution:
set! mutates bindings:
(define a 10)
(set! a 20)
define in a lambda (function, let, ...)
A define in a lambda is something completely different, handled by completely different parts of the implementation. It is handled by the macro/special form lambda so that it is rewritten to a letrec*
A letrec* or letrec is used for making functions recursive so the names need to be available at the time the expressions are evaluated. Because of that when you define n it has already shadowed the n you passed as argument. In addition from R6RS implementers are required to signal an error when a binding is evaluated that is not yet initialized and that is probably what happens. Before R6RS implementers were free to do whatever they wanted:
(define (func n)
(define n (+ n 1)) ; illegal since n hasn't got a value yet!
n)
This actually becomes:
(define func
(lambda (n)
(let ((n 'undefined-blow-up-if-evaluated))
(let ((tmpn (+ n 1)))
(set! n tmpn))
n)))
Now a compiler might see that it violates the spec at compile time, but many implementations doesn't know before it runs.
(func 5) ; ==> 42
Perfectly fine result in R5RS if the implementers have good taste in books.
The difference in the version you said works is that this does not violate the rule of evaluating n before the body:
(define (func n)
(define n 5)
n)
becomes:
(define func
(lambda (n)
(let ((n 'undefined-blow-up-if-evaluated))
(let ((tmpn 5)) ; n is never evaluated here!
(set! n tmpn))
n)))
Solutions
Use a non conflicting name
(define (func n)
(define new-n (+ n 1))
new-n)
Use let. It does not have its own binding when the expression gets evaluated:
(define (func n)
(let ((n (+ n 1)))
n))

How can I unsplice a list of expression into code?

I have an experiment for my project, basically, I need to embedded some s-expression into the code and make it run, like this,
(define (test lst)
(define num 1)
(define l (list))
`#lst) ; oh, this is not the right way to go.
(define lst
`( (define num2 (add1 num))
(displayln num2)))
I want the test function be like after test(lst) in racket code:
(define (test lst)
(define num 1)
(define l (list))
(define num2 (add1 num)
(displayln num2))
How can I do this in racket?
Update
The reason I would like to use eval or the previous questions is that I am using Z3 racket binding, I need to generate formulas (which uses racket binding APIs), and then I will fire the query at some point, that's when I need to evaluate those code.
I have not figured out other ways to go in my case...
One super simple example is, imagine
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))
I have some model to analyze the constructs (so I am not using racketZ3 directly), during each analyzing point, I will map the data types in the program into the Z3 types, and made some assertions,
I will generate something like:
At allocation site, I will need to make the following formula:
(smt:declare-fun arr_z3 () IntList)
(define len (make-length 10))
Then at the array set site, I will have the following assertions and to check whether the 3 is less then the length
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat)
Then finally, I will gather the formulas generated as above, and wrap them in the form which is able to fire Z3 binding to run the following gathered information as code:
(smt:with-context
(smt:new-context)
(define len (make-length 10))
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat))
This is the super simple example I can think of... making sense?
side note. Z3 Racket binding will crash for some reason on version 5.3.1, but it mostly can work on version 5.2.1
Honestly, I don’t understand what exactly you would like to achieve. To quote N. Holm, Sketchy Scheme, 4.5th edition, p. 108: »The major purpose of quasiquotation is the construction of fixed list structures that contain only a few variable parts«. I don’t think that quasiquotation would be used in a context like you are aiming at.
For a typical context of quasiquotation consider the following example:
(define (square x)
(* x x))
(define sentence
'(The square of))
(define (quasiquotes-unquotes-splicing x)
`(,#sentence ,x is ,(square x)))
(quasiquotes-unquotes-splicing 2)
===> (The square of 2 is 4)
Warning: if you're not familiar with how functions work in Scheme, ignore the answer! Macros are an advanced technique, and you need to understand functions first.
It sounds like you're asking about macros. Here's some code that defines test to be a function that prints 2:
(define-syntax-rule (show-one-more-than num)
(begin
(define num2 (add1 num))
(displayln num2)))
(define (test)
(define num1 1)
(show-one-more-than num1))
Now, I could (and should!) have written show-one-more-than as a function instead of a macro (the code will still work if you change define-syntax-rule to define), but macros do in fact operate by producing code at their call sites. So the above code expands to:
(define (test)
(define num1 1)
(begin
(define num2 (add1 num1))
(displayln num2)))
Without knowing the problem better, it's hard to say what the correct approach to this problem is. A brute force approach, such as the following:
#lang racket
(define (make-test-body lst)
(define source `(define (test)
(define num 1)
(define l (list))
,#lst))
source)
(define lst
`((define num2 (add1 num))
(displayln num2)))
(define test-source
(make-test-body lst))
(define test
(parameterize ([current-namespace (make-base-namespace)])
(eval `(let ()
,test-source
test))))
(test)
may be what you want, but probably not.

How can i overload a function at run time in Scheme?

rt.
I want to redefine a function at run time so that i can change the behavior of the system at run time.
thanks.
(define (foo x) ...stuff...)
(set! foo (lambda (x) ...different stuff...))
It might be advisable to use let to do this locally, this can also apply to keywords in this sense:
(let ((define +))
(define 2 3)) ; ===> 5
Or even redefine them to constants, remember, Scheme is a lisp-1:
(let ((define 2) (+ 4))
(- define +)) ; ===> -2
Or even:
(let ((quote /))
'3) ===> 1/3
Doing it only locally preserves the functional style.
Assuming you want to overload a function you defined earlier, simply define it again. This also works for redefining functions such as car and cdr, e.g. to make car into cdr:
(define (car x) (cdr x))
However, I think you won't be able to affect other already defined functions with such a redefinition, so a system function which uses car will still use the original system car and not yours:
(define (test x) (car x))
(define (car x) (cdr x))
(test '(1 2 3))
1
I guess the reason for this is that internally the symbols disappear once a function gets read or evaluated and the symbols are replaced by what they're bound to; in this case, the actual code of the function. So rebinding a symbol to a different function won't affect the rest of your already defined code. This is usually a good thing because it helps uphold referential transparency.
If you want to redefine scheme keywords such as lambda or cond, use let-syntax (see http://community.schemewiki.org/?scheme-faq-language)

Resources