I am trying to find the cube root of a number using Newton's method. I wrote scheme procedures as follows:
(define (cbrt x)
(cbrt-iter 1.0 x))
(define (cbrt-iter guess x)
(if (good-enough? guess x) guess (cbrt-iter (improve guess x) x)))
(define (good-enough? guess x)
(< (- guess (improve guess x)) 0.00001))
(define (improve guess x)
(/ (+ (/ x (* guess guess)) (* 2 guess)) 3))
(cbrt 27)
(cbrt 8)
(cbrt 64)
Actually I am working on Exercise 1.8 of the famous (or may be infamous) book SICP. then I run scheme < cuberoot.scm and got the following result:
MIT/GNU Scheme running under GNU/Linux
Type `^C' (control-C) followed by `H' to obtain information about interrupts.
Copyright (C) 2019 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 September 5, 2019 at 11:51:46 AM
Release 10.1.10 || Microcode 15.3 || Runtime 15.7 || SF 4.41 || LIAR/x86-64 4.118
1 ]=> (define (cbrt x)
(cbrt-iter 1.0 x))
;Value: cbrt
1 ]=> (define (cbrt-iter guess x)
(if (good-enough? guess x) guess (cbrt-iter (improve guess x) x)))
;Value: cbrt-iter
1 ]=> (define (good-enough? guess x)
(< (- guess (improve guess x)) 0.00001))
;Value: good-enough?
1 ]=> (define (improve guess x)
(/ (+ (/ x (* guess guess)) (* 2 guess)) 3))
;Value: improve
1 ]=> (cbrt 27)
;Value: 1.
1 ]=> (cbrt 8)
;Value: 1.
1 ]=> (cbrt 64)
;Value: 1.
1 ]=>
End of input stream reached.
Post proelium, praemium.
The program is always producing 1. as a result. I also tried adjusting the threshold value in good-enough? procedure from 0.00001 to 0.0001 and so on but that didn't worked.
Please explain what went wrong and how to fix that.
You need to include an (abs ...) in good-enough?, otherwise you don't just see if two values are close enough, but just if one value is greater than another (approximately).
(define (good-enough? guess x)
(< (abs (- guess (improve guess x))) 0.00001))
MIT-SCHEME can help you, see Tracing Procedures in MIT-Scheme. Tracing is a way for the interpreter to indicate what expression currently being computed, and what result it yields. After having entered your definitions, you can trace your procedures as follows:
(trace cbrt-iter)
(trace good-enough?)
(trace improve)
(trace cbrt)
Here is the interaction with input 64:
1 ]=> (cbrt 64)
[Entering #[compound-procedure 15 cbrt]
Args: 64]
[Entering #[compound-procedure 12 cbrt-iter]
Args: 1.
64]
[Entering #[compound-procedure 13 good-enough?]
Args: 1.
64]
[Entering #[compound-procedure 14 improve]
Args: 1.
64]
[22.
<== #[compound-procedure 14 improve]
Args: 1.
64]
[#t
<== #[compound-procedure 13 good-enough?]
Args: 1.
64]
[1.
<== #[compound-procedure 12 cbrt-iter]
Args: 1.
64]
[1.
<== #[compound-procedure 15 cbrt]
Args: 64]
;Value: 1.
Each time you call a traced procedure, you see:
[Entering ...]
Each time that procedure exits, its value is printed:
[XYZ
<== <CALL THAT PRODUCED THE VALUE>]
Here, you can see that (improve 1. 64) returned 22, and that 22 is a good-enough value, from the result of (good-enough? 1. 64). Then you can see that (cbrt-iter 1. 64) returned 1.
Related
i'm porting SRFI 105 "Curly infix" to Racket.
I wrote a "reader" that works and the SRFI 105 is packaged with a REPL that works already with little change (only one line modified as far as ia can remember) but i'm facing a difficulty, being not easy with the Racket ecosytem of building lanaguages:
-first how can i make my implementation parse, not only the main program, but possibly include files? i.e if i have a (include "infix-file.scm") i want the reader/parser to load and parse it before the expansion step which is too late and more difficult
here the beginning of my specialised code (the rest is as the official SRFI 105) file SRFI-105.rkt:
#lang racket
(require syntax/strip-context)
(provide (rename-out [literal-read read]
[literal-read-syntax read-syntax]))
(define (literal-read in)
(syntax->datum
(literal-read-syntax #f in)))
(define (literal-read-syntax src in)
(define lst-code (process-input-code-rec in))
`(module anything racket ,#lst-code))
;; read all the expression of program
;; a tail recursive version
(define (process-input-code-tail-rec in) ;; in: port
(define (process-input acc)
(define result (curly-infix-read in)) ;; read an expression
(if (eof-object? result)
(reverse acc)
(process-input (cons result acc))))
(process-input '()))
; ------------------------------
; Curly-infix support procedures
; ------------------------------
and here is an example of source file using it:
#lang reader "SRFI-105.rkt"
(- (+ 3 3)
{2 + 2})
{5 + 2}
(define (fibonacci n)
(if (< n 2)
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(fibonacci 7)
(define (fib n)
(if {n < 2}
n
{(fib {n - 1}) + (fib {n - 2})} ))
(fib 11)
and the obvious results:
Welcome to DrRacket, version 8.2 [cs].
Language: reader "SRFI-105.rkt", with debugging; memory limit: 128 MB.
2
7
13
89
>
-second, i know how to make a #lang "my language.rkt" parse the following code but i do not know how to integrate the working SRFI 105 REPL in Racket ecosystem (for now it works in a separate file than parser).
here the official SRFI 105 that already work in Racket with minor changes:
; --------------
; Demo of reader
; --------------
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
;{1 + 1}
;(+ 1 1)
;2
;(define k {1 + 1})
;(define k (+ 1 1))
;#<void>
;k
;k
;2
; repeatedly read in curly-infix and write traditional s-expression.
(define (process-input)
(let ((result (curly-infix-read)))
(cond ((not (eof-object? result))
(let ((rv (eval result ns)))
(write result) (display "\n")
(write rv)
(display "\n"))
;; (force-output) ; flush, so can interactively control something else
(process-input)) ;; no else clause or other
)))
(process-input)
Damien
a possible solution is to use 'require' instead of 'include' for loading a source file from another and adding one more
#lang reader "SRFI-105.rkt" at the beginning of each loaded file.
example of main file loading another .rkt file
#lang reader "SRFI-105.rkt"
(require "examples-curly-infix2.rkt")
(- (+ 3 3)
{2 + 2})
{5 + 2}
(define (fibonacci n)
(if (< n 2)
n
(+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
(fibonacci 7)
(define (fib n)
(if {n < 2}
n
{(fib {n - 1}) + (fib {n - 2})} ))
(fib 11)
and here is the loaded file:
#lang reader "SRFI-105.rkt"
{7 * 3}
execution will output this:
Welcome to DrRacket, version 8.2 [cs].
Language: reader "SRFI-105.rkt", with debugging; memory limit: 128 MB.
21
2
7
13
89
21 is coming from the 'required' file,
note that instead of include you can not control at which line number the file will be loaded with require (they are loaded at the beginning)
I'm trying to level up on metaprogramming in Racket and realized I don't know how to take a datum and simply "eval" it.
If I have
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (second x))))
I get
: "Five": (+ 2 3)
: "Twelve": (* 6 2)
: "Three": (- (/ 21 3) 4)
Which is not actually what I want - I want to actually evaluate that list to get the answer.
I'm sure this is simple (perhaps something I need to involve syntax for?) but I'm just missing the picture now. How do I do that?
Edit:
I want to evaluate the s-exp just before displaying, not in the initial list. This is why I figure I might need syntax since I would (I think) have to inject the current syntax context.
Eval is almost always the wrong choice, but eval is what you are looking for:
#lang racket
(define base-ns (make-base-namespace))
(for ((x '(("Five" (+ 2 3))
("Twelve" (* 6 2))
("Three" (- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (eval (second x) base-ns))))
Alternative 1: Lambda / thunks
(for ((x `(("Five" ,(thunk (+ 2 3)))
("Twelve" ,(thunk (* 6 2)))
("Three" ,(thunk (- (/ 21 3) 4))))))
;; notice double parentheses to call the thunk
(displayln (format "~s: ~s" (first x) ((second x)))))
A thunk is just syntax sugar for a lambda with no arguments.
I've played a little around having procedures that can print their sources. Thus you can make your own thunk that has the original structure as structure as I demonstrate with my visual lambda:
(struct proc (src obj)
#:property prop:procedure (struct-field-index obj)
#:transparent
#:methods gen:custom-write
[(define (write-proc x port mode)
((case mode
[(#t) write]
[(#f) display]
[else pretty-print])
(proc-src x)
port))])
(define-syntax lambda*
(syntax-rules ()
((_ . rest)
(proc '(lambda* . rest) (lambda . rest)))))
(define test (lambda* (x y) (+ x y)))
test ; ==> #(struct:closure (lambda* (x y) (+ x y)) #<procedure>)
(proc-src test) ; ==> (lambda* (x y) (+ x y))
(proc-obj test) ; ==> #<procedure>
((proc-obj test) 1 2) ; ==> 3
(test 1 2) ; ==> 3
(display test) ; prints (lambda* (x y) (+ x y))
Use backquote together with unquote which is
;; backquote: `
;; unquote: ,
;; there is also splice list: ,#
(for ((x `(("Five" ,(+ 2 3))
("Twelve" ,(* 6 2))
("Three" ,(- (/ 21 3) 4)))))
(displayln (format "~s: ~s" (first x) (second x))))
;; "Five": 5
;; "Twelve": 12
;; "Three": 3
I'm trying to learn scheme and trying some solutions from this thread.
SICP Exercise 1.3 request for comments
I'm also interested in emacs, so I start both together. In emacs I'm using Racket v6.1.
My problem, strange behavior of one solution:
(define (square x) (* x x))
(define (sum-of-squares x y)
(+ (square x) (square y)))
(define (min x y)
(if (< x y) x y))
(define (min x y)
(if (< x y) x y))
(define (solution a b c)
(sum-of-squares (square (max a b)) (square (max c (min a b)))))
(solution 2 3 4)
337
(solution 1 2 3)
97
No clue what's going on. Expected first 25 and second 13.
So this can easily be explained by substitution:
(solution 2 3 4) is the same as:
(sum-of-squares (square (max 2 3)) (square (max 4 (min 2 3))))
(sum-of-squares (square 3) (square 4))
(sum-of-squares 9 16)
(+ (square 9) (square 16))
(+ 81 256)
; ==> 337
So I hope you have seen why you don't get 25 and can go fix that?
Supposed MIT-Scheme 9.2 and these procedures:
(define (max x y) (if (<= x y) y x))
(define (maxall l) (reduce max 0 l))
the procedures are compiled (p. 51, Ch. 6 in User's Manual):
1 ]=> maxall
;Value 3: #[compiled-procedure 3 ("foo" #x4) #x3 #x1b9ee4]
and it works:
1 ]=> (maxall '(1 3 2))
;Value: 3
but profiling with with-stack-sampling failed:
1 ]=> (with-stack-sampling 10 maxall)
;Stack-sampling...
;The procedure #[compiled-procedure 3 ("foo" #x4) #x3 #x1b9ee4] has been called with 0 arguments; it requires exactly 1 argument.
;To continue, ...
Interpreter says wrong number of arguments, but I don't think so
because the usage of with-stack-sampling is described in p. 51 of User's manual:
with-stack-sampling interval procedure
Applies procedure to zero arguments. ...,
How did I do wrong? and How should I apply the function to an argument with profiling it?
The version info: Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b) macosx-unix-clang-x86-64
The code is actually for exercise 1.3.1 in SICP:
(define (product term a next b)
(define (iter a result)
(if (> a b)
result
(iter (next a) (* (term a) result))
)
)
(iter a 1)
)
(define (get-pi n)
(define (next x) (+ x 2))
(define (term x) (* x x))
(* 8 n (/ (product term 4 next n) (product term 3 next (+ n 1))))
)
The output:
#;102> (get-pi 165)
3.13208714360219
#;103> (get-pi 167)
3.13220081034665
#;104> (get-pi 169)
3.13231179078142
#;105> (get-pi 170)
0.0
Why the result became 0.0?
Thank you!
Chicken doesn't implement the full numeric tower by default. You need to (use numbers).
I don't have Chicken installed, but you might have to use (exact->inexact (get-pi 170)) to get the same results as before.