Operate numbers with pi-sum but report wrong stringp error - elisp

I learned the following code pattern which abstract sum
#+BEGIN_SRC scheme :results value
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
(define (pi-sum a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 2))))
a
(lambda (x) (+ x 4))
b))
(pi-sum 1 11)
#+END_SRC
#+RESULTS:
: 0.372005772005772
With elisp
#+begin_src emacs-lisp :session sicp :lexical t
(defun sum(term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
(defun pi-sum(a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 2))))
a
(lambda (x) (+ x 4))
b))
#+end_src
#+RESULTS:
: pi-sum
It seem works good until pass in arguments
ELISP> (pi-sum 1 11)
*** Eval error *** Wrong type argument: stringp, 1
Have no ideas where arguments in (pi-sum a b) are specified as string?

Your code is calling the term function, which is documented as follows:
(term PROGRAM)
Start a terminal-emulator in a new buffer. The buffer is in Term mode;
see ‘term-mode’ for the commands to use in that buffer.
You can see the details of the error if you set debug-on-error:
(setq debug-on-error t)
(pi-sum 1 11)
You'll get a backtrace like this:
Debugger entered--Lisp error: (wrong-type-argument stringp 1)
make-process(:name "terminal" :buffer #<buffer *terminal*> :command ("/bin/sh" "-c" "stty -nl echo rows 25 columns 81 sane 2>/dev/null;if [ $1 = .. ]; then shift; fi; exec \"$#\"" ".." 1))
apply(make-process (:name "terminal" :buffer #<buffer *terminal*> :command ("/bin/sh" "-c" "stty -nl echo rows 25 columns 81 sane 2>/dev/null;if [ $1 = .. ]; then shift; fi; exec \"$#\"" ".." 1)))
start-process("terminal" #<buffer *terminal*> "/bin/sh" "-c" "stty -nl echo rows 25 columns 81 sane 2>/dev/null;if [ $1 = .. ]; then shift; fi; exec \"$#\"" ".." 1)
apply(start-process "terminal" #<buffer *terminal*> "/bin/sh" "-c" "stty -nl echo rows 25 columns 81 sane 2>/dev/null;if [ $1 = .. ]; then shift; fi; exec \"$#\"" ".." 1 nil)
term-exec-1("terminal" #<buffer *terminal*> 1 nil)
term-exec(#<buffer *terminal*> "terminal" 1 nil nil)
make-term("terminal" 1)
term(1)
(+ (term a) (sum term (next a) next b))
(if (> a b) 0 (+ (term a) (sum term (next a) next b)))
sum((lambda (x) (/ 1.0 (* x (+ x 2)))) 1 (lambda (x) (+ x 4)) 11)
pi-sum(1 11)
You need to change your sum function to use funcall to call the term and next functions you're passing to it:
(defun sum(term a next b)
(if (> a b)
0
(+ (funcall term a)
(sum term (funcall next a) next b))))
With this revised definition of sum, calling pi-sum gives the expected answer:
(pi-sum 1 11)
0.372005772005772

Related

Racket "eval" a datum

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

Previous result in Chez Scheme

In the Chez Scheme REPL, is it possible to get the previous result? For example in ruby's irb repl, underscore can be used.
For example can I do the following?
> (+ 2 3)
5
> (+ 1 <something>)
And get 6?
Chez Scheme does not have a built in way to do this, but being scheme, we can roll our own:
(define repl
(let ([n 1])
(lambda (expr)
(let-values ([vals (eval expr)])
(for-each (lambda (v)
(unless (eq? (void) v)
(let ([sym (string->symbol (format "$~a" n))])
(set! n (+ n 1))
(printf "~a = " sym)
(pretty-print v)
(set-top-level-value! sym v))))
vals)))))
(new-cafe repl)
repl is now a function that takes an expression, evaluates it, stores the non-void results into ids of the form $N where N is monotonically increasing, and prints out the results. new-cafe is a standard chez function that manages the Reading, Printing, and Looping parts of REPL. It takes a function that manages the Evaluation part. In this case, repl also needs to manage printing since it shows the ids associated with the values.
Edit:
I found a slightly better way to do this. Instead of having a custom repl, we can customize only the printer. Now this function is no longer responsible for also evaluating the input.
(define write-and-store
(let ([n 1])
(lambda (x)
(unless (eq? (void) x)
(let ([sym (string->symbol (format "$~a" n))])
(set! n (+ n 1))
(set-top-level-value! sym x)
(printf "~a = " sym)
(pretty-print x)
(flush-output-port (console-output-port)))))))
(waiter-write write-and-store)
A simple usage example:
> (values 1 2 3 4)
$1 = 1
$2 = 2
$3 = 3
$4 = 4
> (+ $1 $2 $3 $4)
$5 = 10

not a procedure; expected a procedure that can be applied to arguments given: #<void> in scheme

I got it print sub (A 3333) (A 4444), but I can't figure out to print out both
sub (A 3333) (A 4444)
add (R 0) (R 1)
(define tree '("S" ( ("-"("A" 3333 )("A" 4444))) ("W" (("+" ("R" 0) ("R" 1))))))
(define (OperandNode on)
(display on))
(define (TwoOperandNode x)
(car x)
(if(equal? (car x) "-")
((display "sub")
(OperandNode (cadr x))
(OperandNode (caddr x)))))
(TwoOperandNode (caadr tree))
(define (WhileNode h)
(car h)
(if(equal? (car h) "+")
((display "add")
(WhileNode (cadr h))
(WhileNode (caddr h)))))
(WhileNode (caaadr tree))
You know that for the following form:
(+ 1 2)
The parts are evaluated, eg. + gets evaluated ta procedure #<procedure:+> and the numbers get evaluated to themselves. Then Scheme applies it and gets the result 3. Now look at what you have done in WhileNode:
((display "add") (WhileNode (cadr h)) (WhileNode (caddr h))) ; ==
(#<void> ...) ; throws error
So the parts get evaluated here to. However the problem is that the expression in operator position, (display "add"), returns #<void>. It doesn't know how to continue from this. In Java the same code would look like this:
System.out.println("add")(WhileNode(cadr(h)), WhileNode(caddr(h)));
In Scheme its perfectly natural to have expressions in operator position, but it must evaluate to a procedure:
(define (abs-proc x)
(if (positive? x)
values
-))
((abs-proc -5) -5) ; ==
(- -5) ; ==
; ==> 5
((abs-proc 3) 3) ; ==
(values 3) ; ==
; ==> 3

Unable to understand the error in Guile Scheme Code

I am trying to print a Pascal's Triangle on terminal using Guile Scheme.
What is Pascal's Triangle?
Here is the script:
#!/usr/local/bin/guile \
-e main -s
!#
(define (fact-iter product counter max-count)
(if (> counter max-count)
product
(fact-iter (* counter product) (+ counter 1) max-count)))
(define (factorial n)
(fact-iter 1 1 n))
(define (n-C-r n r)
(/ (factorial n) (* (factorial (- n r)) (factorial r))
)
)
(define (row-iter r l n)
(cond ((= r 0) ((display 1) (row-iter (+ r 1) l n)))
((and (> r 0) (< r l)) ((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n)))
((= r l) (display 1))
)
)
(define (line-iter l n)
(cond ((<= l n) ( (row-iter 0 l n)
(line-iter (+ l 1) n) ) )
)
)
(define (pascal-triangle n)
(line-iter 0 n) )
(define (main args)
(pascal-triangle (string->number (car (cdr args)) 10))
)
File name is pascalTriangle.scm
The Shebang notation on the top has correct path to guile.
I have given the permissions by chmod +x pascalTriangle.scm
Run the program using the command ./pascalTriangle.scm 5
When run, the above script, the following output/error is observed:
1Backtrace: In ice-9/boot-9.scm:
157: 5 [catch #t #<catch-closure ac8400> ...]
In unknown file:
?: 4 [apply-smob/1 #<catch-closure ac8400>]
In ice-9/boot-9.scm:
63: 3 [call-with-prompt prompt0 ...]
In ice-9/eval.scm:
432: 2 [eval # #]
In /home/tarunmaganti/./pascalTriangle.scm:
27: 1 [line-iter 0 4]
In unknown file:
?: 0 [#<unspecified> #<unspecified>]
ERROR: In procedure #<unspecified>:
ERROR: Wrong type to apply: #<unspecified>
Notice that, the first character of the output is 1 which implies that the code executed until first part of procedure row-iter i.e., (display 1) and there might be an error after it.
But the output says that error is in procedure line-iter. I do not understand.
I would appreciate if any error in the program is pointed-out and corrected to make it print a Pascal's Triangle.
Edit1: I edited the error/output text, I replaced '<' and '>' with HTML entities. The text inside the angular brackets wasn't visible before.
The problem is that you have added excess parentheses around your consequence expressions in cond. Since cond has explicit begin you code that looks like this today:
(define (row-iter r l n)
(cond ((= r 0)
;; you see the double (( ?
((display 1)
(row-iter (+ r 1) l n)))
((and (> r 0) (< r l))
;; you see the double (( ?
((display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n)))
((= r l)
;; without double (( and thus ok
(display 1))))
Needs to have it's excess parentheses removed like this:
(define (row-iter r l n)
(cond ((= r 0)
(display 1)
(row-iter (+ r 1) l n))
((and (> r 0) (< r l))
(display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n))
((= r l)
(display 1))))
If you would have used if instead you would have to use begin:
(define (row-iter r l n)
(if (= r 0)
(begin
(display 1)
(row-iter (+ r 1) l n))
(if (and (> r 0) (< r l))
(begin
(display (n-C-r l r))
(display " ")
(row-iter (+ r 1) l n))
(display 1))))
Just fixing this procedure wont fix you problem since you have the same error in line-iter as well. You might see double (( in the beginning of each cond term but unless you are doing something fancy you should not expect it anywhere else.
When adding excess parentheses ((display "something") #t) it gets interpreted as (display "something") will return a procedure and that you want to check what the result of that procedure with argument #t will become. When all the parts is evaluated it fails since then it finds out the undefined value is not a procedure. There are cases where it works:
((if (< x 0) - +) x 1) ; absolute increment value without changing sign
Here you see the first part gets evaluated to the result of evaluating - when x is less than zero. If it's -10 the result would be -11 and if it is 10 the procedure applied will be the evaluation of + with the result 11.
Later it will find that the value 3 isn't a procedure and you get th eerror. and to get the result Scheme should do (apply 3 '(#t))and it detects that 3 (in your case whatdesiplayreturns which is an unspecified value)
Scheme interprets this by evaluating(display (n-C-r l r)` which prints something and the returned value, which by the spec i undefined and thus free choice of the implementers, is then applied as a procedure because of excess parentheses.
In Guile the result of values undefined in the spec becomes a singleton that displays #<unspecified> and that is ignored by the REPL. You might find a Scheme implementation where the unspecified value is a procedure that takes no arguments where your implementation will work flawlessly but will not be portable.
The error as stated by Sylwester in his answer is in ((display (n-C-r l r)) (display " ") (row-iter (+ r 1) l n))) expression. The statement indeed interprets this by evaluating ((display (n-C-r l r)) which prints something and return undefined value and is applied as a procedure considering ((display (n-C-r l r)) as excessively parenthesized.
I resolved the problem using the Sequencing. The begin special form is used to combine multiple statements and returns the value of the last statement.
Sequencing in MIT-Scheme. This worked in guile scheme too.
Syntax of begin special form: (begin <e1> <e2> <e3>....<en>)
It returns return value of <en> expression.
Here is the changed code:
(define (row-iter n r)
(cond ((= r 0) (begin (display 1) (display " ") (row-iter n (+ r 1))))
((and (> r 0) (< r n)) (begin (display (n-C-r n r)) (display " ") (row-iter n (+ r 1))))
((= r n) (display 1))
)
)
Although the output isn't properly formatted as a "triangle", we can get left indented pascal triangle after changing the code.
By running ./pascalTriangle 5, we get the output as
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1

Scheme what are symbols good for and evaluate them

I'm quite new to scheme and I'm not so sure of something about quote and symbols.
Here is what I understand:
'a
-> a
'()
->(list)
'(1 2 3)
(list 1 2 3)
'(1 . 2)
(cons 1 2)
''a
(quote a)
So:
'(1 . 'a)
(1 quote a) => (list 1 quote a)
What I'd like to achieve is the following.
((let ((x 1) (y 2))
(lambda(f) ,f)) 'x)
-> 1
I send a symbol to the function and the symbol should be evaluated to the current scope which in this case would return 1.
Instead, I have this error:
*** ERROR IN #<procedure #4>, (console)#243.32 -- Unbound variable: unquote
It's as if unquote was only available from within quote itself.
EDIT
I was just reading some docs and found the function: "eval" which seems to do what I was looking for.
(define a 'foobar)
(define foobar 2)
(eval a)
-> 2
(define a 'x)
(define f (let ((x 1) (y 2))
(lambda (h) (eval h))))
(f a)
*** ERROR -- Unbound variable: y
(f y)
*** ERROR IN (console)#278.4 -- Unbound variable: y
But I'm not sure to really understand.
Here is a stacktrace in chicken
Error: unbound variable: x
Call history:
<syntax> (f (quote x))
<syntax> (quote x)
<syntax> (##core#quote x)
<eval> (f (quote x))
<eval> (eval h) <--
Edit2
Eval is Evil but I guess it's quite important to know how it works.
So after reading the answer of Ankur, I was pretty sure that it was a problem of scope and it is in fact it. So from what I understand, It appears that eval may be trying to evaluate anything using "globals".
> (define a 11)
> (define b 'a)
> (eval b)
11
> (let ((a 10)) (eval b))
11
> (let* ((a 10) (b 'a)) (eval b))
11
> (let* ((a 10) (b 'a)) b)
a
> (let* ((c 10) (d 'c)) d)
c
> (let* ((c 10) (d 'c)) (eval d))
*** ERROR -- Unbound variable: c
Eval in scheme is clearly evil!
It's as if unquote was only available from within quote itself.
Yes, you can only do unquoting inside a quoted expression as that is where only unquoting make sense, i.e you are quoting an expression (not want to evaluate the items in the expression) but want a specific part of the expression to be evaluated, in that case you use unquote.
(define a 10)
`(a b ,a) ==> '(a b 10)
In the last expression i want a and b to be unevaluated but the 3rd element i.e a should be evaluated and be replaced with its value hence we use unquote for that.
Your code:
(define f (let ((x 1) (y 2))
(lambda (h) (eval h))))
The param for f has to be an unevaluated expression because the param h is evalued using eval.
hence you need to use (f 'a).
NOTE: (f 'y) will not work because the scope of y which was created using let is gone.
For this case in particular you don't need to quote the expression to be evaluated, this will work:
(let ((x 1) (y 2))
((lambda (f) f) x))
=> 1
In the code in the question, be aware that the variable x only exists in the scope of the let that defined it; the outermost 'x symbol will only be that, a symbol with no relation to the x inside the let expression:
((let ((x 1) (y 2))
(lambda (f) f)) 'x)
=> 'x

Resources