I have been reading from the courses CS61A (Spring 2011) from Berkeley Opencourseware and MIT 6.001 from OCW. One uses STk (called as stk-simply) and the other uses mit-scheme as programming language for the lectures.
I just wrote a simple square root procedure using Heron's method. The file was saved as sqrt.scm
;; setting an accuracy or tolerance to deviation between the actual and the expected values
(define tolerance 0.001)
;; gives average of two numbers
(define (average x y)
(/ (+ x y) 2))
;; gives the absolute values of any number
(define (abs x)
(if (< x 0) (- x) x))
;; gives the square of a number
(define (square x) (* x x))
;; tests whether the guess is good enough by checking if the difference between square of the guess
;; and the number is tolerable
(define (good-enuf? guess x)
(< (abs (- (square guess) x)) tolerance))
;; improves the guess by averaging guess the number divided by the guess
(define (improve guess x)
(average (/ x guess) guess))
;; when a tried guess does not pass the good-enuf test then the tries the improved guess
(define (try guess x)
(if (good-enuf? guess x)
guess
(try (improve guess x) x)))
;; gives back square root of number by starting guess with 1 and then improving the guess until good-enuf
(define (sqr-root x)
(try 1 x))
This works fine in STk.
sam#Panzer:~/code/src/scheme$ sudo stk-simply
[sudo] password for sam:
Welcome to the STk interpreter version 4.0.1-ucb1.3.6 [Linux-2.6.16-1.2108_FC4-i686]
Copyright (c) 1993-1999 Erick Gallesio - I3S - CNRS / ESSI <eg#unice.fr>
Modifications by UCB EECS Instructional Support Group
Questions, comments, or bug reports to <inst#EECS.Berkeley.EDU>.
STk> (load "sqrt.scm")
okay
STk> (sqr-root 25)
5.00002317825395
STk>
But not in scheme.
sam#Panzer:~/code/src/scheme$ sudo scheme
[sudo] password for sam:
MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.
Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Thursday October 27, 2011 at 7:44:21 PM
Release 9.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/i386 4.118 || Edwin 3.116
1 ]=> (load "sqrt.scm")
;Loading "sqrt.scm"... done
;Value: sqr-root
1 ]=> (sqr-root 25)
;Value: 1853024483819137/370603178776909
1 ]=>
I checked the manuals but I was unable to find the cause. Can anyone let me know why is this? Or is there an error in the code which I am ignoring?. I am a beginner in both scheme & STk.
Try this, now the code should return the same results in both interpreters (ignoring tiny rounding differences):
(define (sqr-root x)
(exact->inexact (try 1 x)))
The answer was the same all along, it's just that MIT Scheme is producing an exact result by default, whereas STk is returning an inexact value. With the above code in place, we convert the result to an inexact number after performing the calculation. Alternatively, we could perform the conversion from the beginning (possibly losing some precision in the process):
(define (sqr-root x)
(try 1 (exact->inexact x)))
This quote explains the observed behavior:
Scheme numbers are either exact or inexact. A number is exact if it was written as an exact constant or was derived from exact numbers using only exact operations. A number is inexact if it was written as an inexact constant, if it was derived using inexact ingredients, or if it was derived using inexact operations. Thus inexactness is a contagious property of a number.
You'd have both answers look the same if in MIT Scheme you had written:
(sqr-root 25.)
since 'inexactness' is 'sticky'
Related
Ok, this is a fairly basic question: I am following the SICP videos, and I am a bit confused about the differences between define, let and set!.
1) According to Sussman in the video, define is allowed to attach a value to avariable only once (except when in the REPL), in particular two defines in line are not allowed. Yet Guile happily runs this code
(define a 1)
(define a 2)
(write a)
and outputs 2, as expected. Things are a little bit more complicated because if I try to do this (EDIT: after the above definitions)
(define a (1+ a))
I get an error, while
(set! a (1+ a))
is allowed. Still I don't think that this the only difference between set! and define: what is that I am missing?
2) The difference between define and let puzzles me even more. I know in theory let is used to bind variables in local scope. Still, it seems to me that this works the same with define, for instance I can replace
(define (f x)
(let ((a 1))
(+ a x)))
with
(define (g x)
(define a 1)
(+ a x))
and f and g work the same: in particular the variable a is unbound outside g as well.
The only way I can see this useful is that let may have a shorter scope that the whole function definition. Still it seems to me that one can always add an anonymous function to create the necessary scope, and invoke it right away, much like one does in javascript. So, what is the real advantage of let?
Your confusion is reasonable: 'let' and 'define' both create new bindings. One advantage to 'let' is that its meaning is extraordinarily well-defined; there's absolutely no disagreement between various Scheme systems (incl. Racket) about what plain-old 'let' means.
The 'define' form is a different kettle of fish. Unlike 'let', it doesn't surround the body (region where the binding is valid) with parentheses. Also, it can mean different things at the top level and internally. Different Scheme systems have dramatically different meanings for 'define'. In fact, Racket has recently changed the meaning of 'define' by adding new contexts in which it can occur.
On the other hand, people like 'define'; it has less indentation, and it usually has a "do-what-I-mean" level of scoping allowing natural definitions of recursive and mutually recursive procedures. In fact, I got bitten by this just the other day :).
Finally, 'set!'; like 'let', 'set!' is pretty straightforward: it mutates an existing binding.
FWIW, one way to understand these scopes in DrRacket (if you're using it) is to use the "Check Syntax" button, and then hover over various identifiers to see where they're bound.
Do you mean (+ 1 a) instead of (1+ a) ? The latter is not syntactically valid.
Scope of variables defined by let are bound to the latter, thus
(define (f x)
(let ((a 1))
(+ a x)))
is syntactically possible, while
(define (f x)
(let ((a 1)))
(+ a x))
is not.
All variables have to be defined in the beginning of the function, thus the following code is possible:
(define (g x)
(define a 1)
(+ a x))
while this code will generate an error:
(define (g x)
(define a 1)
(display (+ a x))
(define b 2)
(+ a x))
because the first expression after the definition implies that there are no other definitions.
set! doesn't define the variable, rather it is used to assign the variable a new value. Therefore these definitions are meaningless:
(define (f x)
(set! ((a 1))
(+ a x)))
(define (g x)
(set! a 1)
(+ a x))
Valid use for set! is as follows:
(define x 12)
> (set! x (add1 x))
> x
13
Though it's discouraged, as Scheme is a functional language.
John Clements answer is good. In some cases, you can see what the defines become in each version of Scheme, which might help you understand what's going on.
For example, in Chez Scheme 8.0 (which has its own define quirks, esp. wrt R6RS!):
> (expand '(define (g x)
(define a 1)
(+ a x)))
(begin
(set! g (lambda (x) (letrec* ([a 1]) (#2%+ a x))))
(#2%void))
You see that the "top-level" define becomes a set! (although just expanding define in some cases will change things!), but the internal define (that is, a define inside another block) becomes a letrec*. Different Schemes will expand that expression into different things.
MzScheme v4.2.4:
> (expand '(define (g x)
(define a 1)
(+ a x)))
(define-values
(g)
(lambda (x)
(letrec-values (((a) '1)) (#%app + a x))))
You may be able to use define more than once but it's not
idiomatic: define implies that you are adding a definition to the
environment and set! implies you are mutating some variable.
I'm not sure about Guile and why it would allow (set! a (+1 a)) but
if a isn't defined yet that shouldn't work. Usually one would use
define to introduce a new variable and only mutate it with set!
later.
You can use an anonymous function application instead of let, in
fact that's usually exactly what let expands into, it's almost
always a macro. These are equivalent:
(let ((a 1) (b 2))
(+ a b))
((lambda (a b)
(+ a b))
1 2)
The reason you'd use let is that it's clearer: the variable names are right next to the values.
In the case of internal defines, I'm not sure that Yasir is
correct. At least on my machine, running Racket in R5RS-mode and in
regular mode allowed internal defines to appear in the middle of the
function definition, but I'm not sure what the standard says. In any
case, much later in SICP, the trickiness that internal defines pose is
discussed in depth. In Chapter 4, how to implement mutually recursive
internal defines is explored and what it means for the implementation
of the metacircular interpreter.
So stick with it! SICP is a brilliant book and the video lectures are wonderful.
The book defines block structure in Chapter 1, allowing you to 'package' defines inside a procedure definition.
Consider this mean-square definition for example:
(define (mean-square x y)
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(average (square x) (square y)))
when I run (mean-square 2 4) I correctly get 10.
My question is, are the internal definitions ( square and average in this toy case ) run each time I invoke the mean-square procedure via the interpreter? If so, isn't that inefficient? and if not, why?
If the code is somewhat naively compiled, there could be some overhead. The reason is that the inner functions are defined in a brand new lexical environment that is freshly instantiated on each entry into the function. In the abstract semantics, each time the function is called, new lexical closures have to be captured and wired into the correct spots in that environment frame.
Thus it boils down to how much of this can the compiler optimize away. For instance it can notice that neither of the functions actually references the surrounding lexical environment. (The x and y references in these functions are to their own parameters, not to those of the surrounding mean-square). Which means they both be moved to the top level without changing semantics:
(define (__anon1 x) (* x x))
(define (__anon2 x y) (/ (+ x y) 2))
(define (mean-square x y)
(define square __anon1)
(define average __anon2)
(average (square x) (square y)))
And since now square and average are effectively simple aliases (aliases for global entities that are generated by the compiler, which the compiler knows aren't being manipulated by anything outside of its control), the values they denote can be propagated through:
(define (mean-square x y)
(__anon2 (__anon1 x) (__anon1 y)))
It's not a problem. When the mean-square procedure is compiled, all the nested procedures are also compiled. It doesn't need to re-compile them every time you invoke the mean-square procedure.
I think the other answers have probably convinced you that the case you give really doesn't need to have any overhead: the local definitions can be just compiled away. But it's worth thinking about how a system might approach cases where this can't be done.
Consider a definition like this:
(define (make-searcher thing)
(define (search in)
(cond [(null? in)
#f]
[(eqv? (first in) thing)
in]
[else (search (rest in))]))
search)
Well, the local search procedure definitely can't be compiled away here, because it's returned from make-searcher. And it's even worse than that: (make-searcher 1) and (make-searcher 2) need to return different procedures, because ((make-searcher 1) '(1 2 3)) is (1 2 3) while ((make-searcher 2) '(1 2 3)) is (2 3).
So this sounds completely hopeless: the local search procedure not only has to be a procedure (it can't be compiled away), it has to be remade each time.
But in fact things are not nearly so bad. Lexical scope means that the system can know exactly what bindings are visible to search (in this case, a binding for thing as well as its argument). So what you can do, for instance, is compile a bit of code which looks up the values of these bindings in a vector. Then, the thing that is returned from make-search packs together the compiled code of search with a vector of bindings. The compiled code is always the same, only the vector needs to be created and initialised each time.
Imagine this code:
(let ((a expr))
(do-something-with a))
It is the same as:
((lambda (a)
(do-something-with a))
expr)
In an interpreter it might create the lambda each time before calling it while other
languages might turn it into (do-something-with expr). The report doesn't want to touch non functional requirements other than guaranteed tail recursion. In all the serious implementations lambdas are cheap.
Since you mention racket:
File test_com.rkt
#lang racket
(define (mean-square x y)
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(average (square x) (square y)))
(display (mean-square 2 4))
Terminal commands:
raco make test_com.rkt
raco decompile compiled/test_com_rkt.zo
Resulting output:
(module test_com ....
(require (lib "racket/main.rkt"))
(provide)
(define-values
(mean-square)
(#%closed
mean-square49
(lambda (arg0-50 arg1-51)
'#(mean-square #<path:/home/westerp/compiled/test_com.rkt> 2 0 14 136 #f)
'(flags: preserves-marks single-result)
(/ (+ (* arg0-50 arg0-50) (* arg1-51 arg1-51)) '2))))
(#%apply-values print-values (display '10)) ; the only code that matters!
(void)
(module (test_com configure-runtime) ....
(require '#%kernel (lib "racket/runtime-config.rkt"))
(provide)
(print-as-expression '#t)
(void)))
While mean-square has got their local procedures inlined, because I gave it literal values it will never call it so all it does is (display '10) and then exit.
This is of course if you do make or exe. From DrRacket the language options that enabled debugging and better trace and error messages will run slower.
I am learning Scheme, coming from a background of Haskell, and I've run into a pretty surprising issue - scheme doesn't seem to have custom data types??? (ie. objects, structs, etc.). I know some implementations have their own custom macros implementing structs, but R6RS itself doesn't seem to provide any such feature.
Given this, I have two questions:
Is this correct? Am I missing a feature that allows creation of custom data types?
If not, how do scheme programmers structure a program?
For example, any function trying to return multiple items of data needs some way of encapsulating the data. Is the best practice to use a hash map?
(define (read-user-input)
(display "1. Add todo\n2. Delete todo\n3. Modify todo\n")
(let ((cmd-num (read)))
(if (equal? cmd-num "1") '(("command-number" . cmd-num) ("todo-text" . (read-todo)))
(if (equal? cmd-num "2") '(("command-number" . cmd-num) ("todo-id" . (read-todo-id)))
'(("command-number" . cmd-num) ("todo-id" . (read-todo-id)))))))
In order to answer your question, I think it might help to give you a slightly bigger-picture comment.
Scheme has often been described as not so much a single language as a family of languages. This is particularly true of R5RS, which is still what many people mean when they say "Scheme."
Nearly every one of the languages in the Scheme family has structures. I'm personally most familiar with Racket, where you can define structures with
struct or define-struct.
"But", you might say, "I want to write my program so that it runs in all versions of Scheme." Several very smart people have succeeded in doing this: Dorai Sitaram and Oleg Kiselyov both come to mind. However, my observation about their work is that generally, maintaining compatibility with many versions of scheme without sacrificing performance usually requires a high level of macro expertise and a good deal of Serious Thinking.
It's true that several of the SRFIs describe structure facilities. My own personal advice to you is to pick a Scheme implementation and allow yourself to feel good about using whatever structure facilities it provides. In some ways, this is not unlike Haskell; there are features that are specific to ghc, and generally, I claim that most Haskell programmers are happy to use these features without worrying that they don't work in all versions of Haskell.
Absolutely not. Scheme has several SRFIs for custom types, aka. record types, and with R7RS Red edition it will be SRFI-136, but since you mention R6RS it has records defined in the standard too.
Example using R6RS:
#!r6rs
(import (rnrs))
(define-record-type (point make-point point?)
(fields (immutable x point-x)
(immutable y point-y)))
(define test (make-point 3 7))
(point-x test) ; ==> 3
(point-y test) ; ==> 7
Early Scheme (and lisp) didn't have record types and you usually made constructors and accessors:
Example:
(define (make-point x y)
...)
(define (point-x p)
...)
(define (point-y p)
...)
This is the same contract the record types actually create. How it is implemented is really not important. Here are some ideas:
(define make-point cons)
(define point-x car)
(define point-y cdr)
This works most of the time, but is not really very safe. Perhaps this is better:
(define tag (list 'point))
(define idx-tag 0)
(define idx-x 1)
(define idx-y 2)
(define (point? p)
(and (vector? p)
(positive? (vector-length p))
(eq? tag (vector-ref p idx-tag))))
(define (make-point x y)
(vector tag x y))
;; just an abstraction. Might not be exported
(define (point-acc p idx)
(if (point? p)
(vector-ref p idx)
(raise "not a point")))
(define (point-x p)
(point-acc p idx-x))
(define (point-y p)
(point-acc p idx-y))
Now if you look the the reference implementation for record types you'll find they use vectors so the vector version and R6RSs isn't that different.
Lookup? You can use a vector, list or a case:
Example:
;; list is good for a few elements
(define ops `((+ . ,+) (- . ,-)))
(let ((found (assq '+ ops)))
(if found
((cdr found) 1 2)
(raise "not found")))
; ==> 3
;; case (switch)
((case '+
((+) +)
((-) -)
(else (raise "not found"))) 1 2) ; ==> 3
Of course you have hash tables in SRFI-125 so for a large number of elements its probably vice. Know that it probably uses vector to store the elements :-)
Are there any good solution with brackets and line breaks to make a scheme expression like this clearly arranged?
(* (cond ((> a b) a)
((< a b) b)
(else -1))
(+ a 1))
I would go for something like this:
(* (cond
((> a b) a)
((< a b) b)
(else -1))
(+ a 1))
I don't use brackets in addition to parentheses, and the point here is to align the arguments of cond and *.
There are coding style guidelines you can follow that makes your code readable by you and other programmers. How your code was presented it is utterly unreadable.
I agree with #uselpa that the formattign in his answer is OK and it even is ok by the guidelines. I might have done something like this:
;;; Returns the Parker square of
;;; two nebulous numbers
(define (fun-name a b)
(define biggest
(cond
((> a b) a)
((< a b) b)
(else -1)))
(* biggest (+ a 1)))
This shows two things. A comment might help explaining what the procedure does and local bindings might shed some light on what's happening in the first step and reduces the complexity and ease readability. No matter what language you are writing in these are good things.
I am using scheme since 40 years, not in job but for studying the SICP.
In the first time I put every parentheses pair with it own indentation and every closing parenthese on its own line.
(*
(cond
( (> a b)
a
)
( (< a b)
b
)
( else
-1
)
) ;; cond
(+ a 1)
) ;; product
Maybe the code is not easier to read than a more compact code, but while writing it was more clear to me.
Several years later, after learning python I changed my style total.
(In python the indentation is a syntatic element. You have no {} like in C and Java.) I used only the indentation to structure my code and put the closing parentheses in the same row. My code looks as in the earlier answers.
Important is to use an editor, which shows matching parentheses.
In short: Be careful to structure your code by graphic elements. There are several possibilities to do it.
How to efficiently generate a list of million random elements in scheme? The following code hits maximum recursion depth with 0.1 million itself.
(unfold (lambda(x)(= x 1000000)) (lambda(x)(random 1000)) (lambda(x)(+ x 1)) 0)
It really depends on the system you're using, but here's a common way to do that in plain scheme:
(let loop ([n 1000000] [r '()])
(if (zero? n)
r
(loop (- n 1) (cons (random 1000) r))))
One note about running this code as is: if you just type it into a REPL, it will lead to printing the resulting list, and that will usually involve using much more memory than the list holds. So it's better to do something like
(define l ...same...)
There are many other tools that can be used to varying degrees of convenience. unfold is one of them, and another is for loops as can be found in PLT Scheme:
(for/list ([i (in-range 1000000)]) (random 1000))
I don't know much scheme but couldn't you just use tail-recursion (which is really just looping) instead of unfold (or any other higher-order function)?
Use the do-loop-construct as described here.
Some one correct me if I am wrong but the Fakrudeen's code should end up being optimized away since it is tail recursive. Or it should be with a proper implementation of unfold. It should never reach a maximum recursion depth.
What version of scheme are you using Fakrudeen?
DrScheme does not choke on a mere million random numbers.
Taking Chicken-Scheme as implementation, here is a try with some results.
(use srfi-1)
(use extras)
(time (unfold (lambda(x)(= x 1000000))
(lambda(x)(random 1000))
(lambda(x)(+ x 1)) 0))
(time (let loop ([n 1000000] [r '()])
(if (zero? n)
r
(loop (- n 1) (cons (random 1000) r)))))
(define (range min max body)
(let loop ((current min) (ret '()))
(if (= current max)
ret
(loop (+ current 1) (cons (body current ret) ret)))))
(time (range 0 1000000 (lambda params (random 1000))))
The results are here with csc -O3 t.scm
0.331s CPU time, 0.17s GC time (major), 12/660 GCs (major/minor)
0.107s CPU time, 0.02s GC time (major), 1/290 GCs (major/minor)
0.124s CPU time, 0.022s GC time (major), 1/320 GCs (major/minor)
As you can see, the version of the author is much more slowlier than using plain tail recursive calls. It's hard to say why the unfold call is much more slowlier but I'd guess that it's because it taking a lot more time doing function calls.
The 2 other versions are quite similar. My version is almost the same thing with the exception that I'm creating a high order function that can be reused.
Unlike the plain loop, it could be reused to create a range of function. The position and current list is sent to the function in case they are needed.
The higher order version is probably the best way to do even if it takes a bit more time to execute. It is probably also because of the function calls. It could be optimized by removing parameters and it will get almost as fast as the named let.
The advantage of the higher order version is that the user doesn't have to write the loop itself and can be used with an abstract lambda function.
Edit
Looking at this specific case. Ef we are to create a million of element ranged between 0 and 999, we could possibly create a fixed length vector of a million and with values from 0 to 999 in it. Shuffle the thing back after. Then the whole random process would depend on the shuffle function which should not have to create new memory swapping values might get faster than generating random numbers. That said, the shuffle method somewhat still rely on random.
Edit 2
Unless you really need a list, you could get away with a vector instead.
Here is my second implementation with vector-map
(time (vector-map (lambda (x y) (random 1000)) (make-vector 1000000)))
# 0.07s CPU time, 0/262 GCs (major/minor)
As you can see, it is terribly faster than using a list.
Edit 3 fun
(define-syntax bigint
(er-macro-transformer
(lambda (exp rename compare)
(let ((lst (map (lambda (x) (random 1000)) (make-list (cadr exp)))))
(cons 'list lst)))))
100000
0.004s CPU time, 0/8888 GCs (major/minor)
It's probably not a good idea to use this but I felt it might be interesting. Since it's a macro, it will get executed at compile time. The compile time will be huge, but as you can see, the speed improvement is also huge. Unfortunately using chicken, I couldn't get it to build a list of a million. My guess is that the type it might use to build the list is overflowing and accessing invalid memory.
To answer the question in the comments:
I'm not a Scheme professional. I'm pretty new to it too and as I understand, the named loop or the high order function should be the way to go. The high order function is good because it's reusable. You could define a
(define (make-random-list quantity maxran)
...)
Then thats the other interesting part, since scheme is all about high order functions. You could then replace the implementation of make-random-list with anything you like. If you need some compile time execution, define the macro otherwise use a function. All that really matters is to be able to reuse it. It has to be fast and not use memory.
Common sense tells you that doing less execution it will be faster, tail recursive calls aren't suppose to consume memory. And when you're not sure, you can hide implementation into a function that can be optimized later.
MIT Scheme limits a computation's stack. Given the size of your problem, you are likely running out of stack size. Fortunately, you can provide a command-line option to change the stack size. Try:
$ mit-scheme --stack <number-of-1024-word-blocks>
There are other command-line options, check out mit-scheme --help
Note that MIT Scheme, in my experience, is one of the few schemes that has a limited stack size. This explains why trying your code in others Schemes will often succeed.
As to your question of efficiency. The routine unfold is probably not implemented with a tail-recursive/iterative algorithm. Here is a tail recursive version with a tail recursive version of 'list reverse in-place':
(define (unfold stop value incr n0)
(let collecting ((n n0) (l '()))
(if (stop n)
(reverse! l)
(collecting (incr n) (cons (value n) l)))))
(define (reverse! list)
(let reving ((list list) (rslt '()))
(if (null? list)
rslt
(let ((rest (cdr list)))
(set-cdr! list rslt)
(reving rest list)))))
Note:
$ mit-scheme --version
MIT/GNU Scheme microcode 15.3
Copyright (C) 2011 Massachusetts Institute of Technology
This is free software; see the source for copying conditions. There is NO warranty; not even
for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Image saved on Tuesday November 8, 2011 at 10:45:46 PM
Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/x86-64 4.118 || Edwin 3.116
Moriturus te saluto.