I got this program:
(define a 2)
(define (goo x)
(display x) (newline)
(lambda (y) (/ x y)))
(define (foo x)
(let ((f (goo a)))
(if (= x 0)
x
(f x))))
and I asked to compare the evaluation results between the applicative and normal order on the expression (foo (foo 0)).
As I know, in applicative order, (display x) in function goo will print x and after it the program will collapse because y isn't defined. But when I run it in Scheme nothing happens. What is the reason?
(foo 0) evaluates to this code:
(define (goo 2)
(display 2) (newline)
(lambda (y) (/ 2 y)))
(define (foo x)
(let ((f (goo 2)))
(if (= 0 0)
0
((lambda (y) (/ 2 y)) 0))))
and prints 2, returning 0. While (foo 4) evaluates to:
(define (goo 2)
(display 2) (newline)
(lambda (y) (/ 2 y)))
(define (foo 4)
(let ((f (goo 2)))
(if (= 4 0)
4
((lambda (y) (/ 2 y)) 4))))
and prints 2, returning 0.5.
Related
Can I define a variable inside a procedure? It seems to me I can only define another procedure inside procedures. I came up with this question while doing exercises from SICP and (rand) is not what I want because it generates two different random numbers, while I want a same number in those two positions.
(define (try x)
(define (rand) (+ 1 (random (- x 1))))
(= (rand) (expmod (rand) x x)))
I have included codes of expmod below.
(define % remainder)
(define (square a) (* a a))
(define (even? a) (= (% a 2) 0) )
(define (expmod base pow mod)
(cond
((= pow 0)
1)
((even? pow)
(% (square (expmod base (/ pow 2) mod)) mod))
(else
(% (* base (expmod base (- pow 1) mod) ) mod))))
Yes, of course you can. In particular
(define (x ...) ...)
is just a shorthand for
(define x (lambda (...) ...))
So you are already defining a variable: rand, whose value is a function.
What you probably want is:
(define (try x)
(define rand (+ 1 (random (- x 1)))
(= rand (expmod rand x x)))
Which in turn is the same as
(define (try x)
(let ([rand (+ 1 (random (- x 1)))])
(= rand (expmod rand x x))))
Yes, you can.
(define (try x)
(define rand (+ 1 (random (- x 1))))
(= rand (expmod rand x x)))
You also have to know that = and try also are variables and they evaluate to procedures. Usually a procedure is created like this:
(define double (lambda (n) (+ n n)))
However there is a short way to write itL
(define (double n) (+ n n))
Now look at your code. Aren't you creating a variable rand to a lambda with the short syntax?
(define (rand) (+ 1 (random (- x 1))))
evaluating rand should give you some sort of procedure output like #<procedure: rand> and calling it (rand) will execute (+ 1 (random (- x 1). These kind of procedures are called thunks and are typically used to delay evaluation.
One thing you cannot do in Scheme is to define a top level variable from a procedure. eg.
(define (make-test v)
(define test v))
(make-test 5)
(displayln test) ; unbound variable
The reason is that in a procedure it will always make a local binding that only lives inside that closure. One could define a top level variable and then set it:
(define test 0) ; make a top level variable
(define (update-test v)
;; since no other that top level is named test,
;; that is the binding this is updating.
(set! test v))
(update-test 5)
(display test) : prints 5
(define (try x)
(define rand (+ 1 (random (- x 1))))
(= (rand) (expmod (rand) x x)))
(define (try x)
(let ((rand (+ 1 (random (- x 1)))))
(= (rand) (expmod (rand) x x))))
Either of these works.
I have to make a function "alternate" which return another function depending of the number of time "alternate" is called.
I first try a simple counter with the square function and it worked well.
(define square
(let ((a 0))
(lambda (x)
(begin
(set! a (+ a 1))
(writeln a)
(* x x)))))
(map square '(1 2 3 4))
It returns as expected
1
2
3
4
'(1 4 9 16)
I want my program below to display
1
2
3
4
'(2 1 6 2)
But I don't know why it seems the counter stays to one. So my program display
1
'(2 4 6 8)
(define alternate
(let ((a 0))
(lambda (f g selector)
(begin
(set! a (+ a 1))
(writeln a)
(if (selector a)
(lambda (x) (f x))
(lambda (x) (g x)))))))
(map (alternate (lambda (x) (* x 2))
(lambda (x) (/ x 2))
odd?)
(first-n-integers 4))
Ps: (first-n-integers 4) return a list
'(1 2 3 4)
The problem is that alternate is executing exactly once and returning a single lambda as its result - instead of that you want to apply it every time. This should work:
(define (alternate f g selector)
(let ((a 0))
(lambda (x)
(set! a (+ a 1))
(writeln a)
(if (selector a)
(f x)
(g x)))))
For example:
(map (alternate (lambda (x) (* x 2))
(lambda (x) (/ x 2))
odd?)
(first-n-integers 4))
1
2
3
4
'(2 1 6 2)
(define (map2 liste1 liste2)
(define (gj x y)
(/ (+ x y) 2))
(if (or (null? liste1) (null? liste2))
'()
(cons (gj (car liste1) (car liste2)) (map2 (cdr liste1) (cdr liste2)))))
Is procedure gj an anonymous procedure since it's within another procedure?
gj is not anonymous since it has a name, which happens to be visible only within the scope of map2.
Examples of anonymous procedures would be:
> ((lambda (x) (* 2 x)) 10)
^^^^^^^^^^^^^^^^^^^^
20
or
> (map (lambda (x) (+ x 1)) '(10 20 30))
^^^^^^^^^^^^^^^^^^^^
'(11 21 31)
which have no name and cannot be referred to after the expression in which they are defined.
Note that
(define (gj x y)
(/ (+ x y) 2))
is the same as
(define gj
(lambda (x y)
(/ (+ x y) 2)))
so here the procedure is bound to identifier gj and therefore it's no longer anonymous.
I am trying to write a representation of pairs that does not use cons, car or cdr but still follows the property of pairs, i.e., (car (cons x y)) should be x and (cdr (cons x y)) should be y.
So here is one solution that I got from the SICP book:
(define (special-cons x y)
(lambda (m) (m x y)))
I was able to write another solution but it can only allow numbers:
(define (special-cons a b)
(* (expt 2 a)
(expt 3 b)))
(define (num-divs n d)
(define (iter x result)
(if (= 0 (remainder x d))
(iter (/ x d) (+ 1 result))
result))
(iter n 0))
(define (special-car x)
(num-divs x 2))
(define (special-cdr x)
(num-divs x 3))
Is there any other solution that allows for pairs for any object x and object y?
What about structs (Racket) or record-types (R6RS)?
In Racket:
#lang racket
(struct cell (x y))
(define (ccons x y) (cell x y))
(define (ccar cl) (cell-x cl))
(define (ccdr cl) (cell-y cl))
(define (cpair? cl) (cell? cl))
(define x (ccons 1 2))
(cpair? x)
=> #t
(ccar (ccons 1 2))
=> 1
(ccdr (ccons 3 4))
=> 4
This is a good way of doing it.
#lang racket
(define (my-cons x y)
(lambda (p)
(if (= p 1) x y)))
(define (my-car pair)
(pair 1))
(define (my-cdr pair)
(pair 2))
Here is the test
> (my-car (my-cons 1 '(2 3 4)))
1
> (my-cdr (my-cons 1 '(2 3 4)))
'(2 3 4)
The classic Ableson and Sussman procedural implementation from Structure and Interpretation of Computer Programs (section 2.1.3):
(define (cons x y)
(define (dispatch m)
(cond ((= m 0) x)
((= m 1) y)
(else (error "Argument not 0 or 1 -- CONS" m))))
dispatch)
(define (car z)
(z 0))
(define (cdr z)
(z 1))
Rptx's solution is roughly equivalent, and this is presented for reference.
I found code for generating Sierpinski carpet at http://rosettacode.org/wiki/Sierpinski_carpet#Scheme - but it won't run in the DrRacket environment or WeScheme. Could someone provide solutions for either environments?
It looks like this code runs fine in DrRacket after prepending a
#lang racket
line indicating that the code is written in Racket. I can provide more detail if this is not sufficient.
I've translated the program to run under WeScheme. I've made a few changes: rather than use (display) and (newline), I use the image primitives that WeScheme provides to make a slightly nicer picture. You can view the running program and its source code. For convenience, I also include the source here:
;; Sierpenski carpet.
;; http://rosettacode.org/wiki/Sierpinski_carpet#Scheme
(define SQUARE (square 10 "solid" "red"))
(define SPACE (square 10 "solid" "white"))
(define (carpet n)
(local [(define (in-carpet? x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))]
(letrec ([outer (lambda (i)
(cond
[(< i (expt 3 n))
(local ([define a-row
(letrec ([inner
(lambda (j)
(cond [(< j (expt 3 n))
(cons (if (in-carpet? i j)
SQUARE
SPACE)
(inner (add1 j)))]
[else
empty]))])
(inner 0))])
(cons (apply beside a-row)
(outer (add1 i))))]
[else
empty]))])
(apply above (outer 0)))))
(carpet 3)
Here is the modified code for WeScheme. WeScheme don't support do-loop syntax, so I use unfold from srfi-1 instead
(define (unfold p f g seed)
(if (p seed) '()
(cons (f seed)
(unfold p f g (g seed)))))
(define (1- n) (- n 1))
(define (carpet n)
(letrec ((in-carpet?
(lambda (x y)
(cond ((or (zero? x) (zero? y))
#t)
((and (= 1 (remainder x 3)) (= 1 (remainder y 3)))
#f)
(else
(in-carpet? (quotient x 3) (quotient y 3)))))))
(let ((result
(unfold negative?
(lambda (i)
(unfold negative?
(lambda (j) (in-carpet? i j))
1-
(1- (expt 3 n))))
1-
(1- (expt 3 n)))))
(for-each (lambda (line)
(begin
(for-each (lambda (char) (display (if char #\# #\space))) line)
(newline)))
result))))