Unbound variable error when loading a procedure from an external file - scheme

I'm using Chicken Scheme 4.9.0.1 on a Cloud9 hosted workspace, built from source.
I was trying it out with this (I mostly code with python, so I apologize for the weird parens syntax):
(define load-module
(lambda (filepath)
(begin
(load filepath)
)
)
)
(define print
(lambda (command)
(begin
(display command)
(newline)
)
)
)
(load-module "../src/Basics.scm")
(print (exponent 5 2))
where exponent was:
(define (exponent num pow)
(if (equal? pow 1)
num
(* num (exponent num (- pow 1))
)
)
)
But it gives me the following error:
Started /home/ubuntu/workspace/test.scm
CHICKEN
(c) 2008-2014, The Chicken Team
(c) 2000-2007, Felix L. Winkelmann
Version 4.9.0.1 (stability/4.9.0) (rev 8b3189b)
linux-unix-gnu-x86-64 [ 64bit manyargs dload ptables ]
bootstrapped 2014-06-07
; loading /home/ubuntu/workspace/project1/src/test.scm ...
; loading ../src/Basics.scm ...
Error: unbound variable: pow
Call history:
<eval> [append] (cons item (reverse target))
<eval> [append] (reverse target)
<eval> [append] (reverse (cons item (reverse target)))
<eval> [append] (cons item (reverse target))
<eval> [append] (reverse target)
<eval> [append] (reverse (cons item (reverse target)))
<eval> [append] (cons item (reverse target))
<eval> [append] (reverse target)
<eval> [append] (reverse (cons item (reverse target)))
<eval> [append] (cons item (reverse target))
<eval> [append] (reverse target)
<syntax> (print (exponent 5 2))
<syntax> (exponent 5 2)
<eval> (print (exponent 5 2))
<eval> (exponent 5 2)
<eval> [exponent] (equal? pow 1) <--
I tried the same procedure on a different scheme implementation (biwascheme, using their online REPL) and it worked. When I added the code directly into the file that i was working on without loading it from a separate file, then it works.
Why does it give that unbound variable error only when it loads from a separate file?

Works fine for me. Compiled Chicken with the same version on Ubuntu, down to the specific revision.
Your call history looks very strange. More specifically:
<eval> [append] (reverse target)
<syntax> (print (exponent 5 2))
The [append] (reverse target) portion looks weird. Your exponent function (as described) does not call that. Even assuming the history was wrong and that was actually inside the print function, I've checked library.scm and that history does not make sense either.
This leads me to believe that the Basics.scm file being loaded is, for some reason, not the one you are expecting and you ended up with a different, non-working version of exponent.
You could ask Chicken to display the contents of the file to make sure. Something such as:
(with-input-from-file "../src/Basics.scm"
(lambda ()
(display (read))))
The result should match the expected content.

Related

Problems about Scheme with postfix

Here is my code about postfix in scheme:
(define (stackupdate e s)
(if (number? e)
(cons e s)
(cons (eval '(e (car s) (cadr s))) (cddr s))))
(define (postfixhelper lst s)
(if (null? lst)
(car s)
(postfixhelper (cdr lst) (stackupdate (car lst) s))))
(define (postfix list)
(postfixhelper list '()))
(postfix '(1 2 +))
But when I tried to run it, the compiler said it takes wrong. I tried to check it, but still can't find why it is wrong. Does anyone can help me? Thanks so much!
And this is what the compiler said:
e: unbound identifier;
also, no #%app syntax transformer is bound in: e
eval never has any information about variables that some how are defined in the same scope as it is used. Thus e and s does not exist. Usually eval is the wrong solution, but if you are to use eval try doing it as as little as you can:
;; Use eval to get the global procedure
;; from the host scheme
(define (symbol->proc sym)
(eval sym))
Now instead of (eval '(e (car s) (cadr s))) you do ((symbol->proc e) (car s) (cadr s)). Now you should try (postfix '(1 2 pair?))
I've made many interpreters and none of them used eval. Here is what I would have done most of the time:
;; Usually you know what operators are supported
;; so you can map their symbol with a procedure
(define (symbol->proc sym)
(case sym
[(+) +]
[(hyp) (lambda (k1 k2) (sqrt (+ (* k1 k1) (* k2 k2))))]
[else (error "No such operation" sym)]))
This fixes the (postfix '(1 2 pair?)) problem. A thing that I see in your code is that you always assume two arguments. But how would you do a double? eg something that just doubles the one argument. In this case symbol->proc could return more information:
(define (symbol->op sym)
(case sym
[(+) (cons + 2)]
[(double) (cons (lambda (v) (* v v)) 1)]
[else (error "No such operation" sym)]))
(define op-proc car)
(define op-arity cdr)
And in your code you could do this if it's not a number:
(let* ([op (symbol->op e)]
[proc (op-proc op)]
[arity (op-arity op)])
(cons (apply proc (take s arity)
(drop s arity)))
take and drop are not R5RS, but they are simple to create.

Why might the Scheme `filter` form not process list elements 'in order'?

(filter procedure list) applies procedure to each element of list
and returns a new list containing only the elements for which procedure
returns true.
(R. Kent Dybvig The Scheme Programming Language)
(online)
What may not be apparent from this description is that, while the elements in the returned
list occur in the same order as in list, the order of calls of procedure is not
specified in R6RS. (Racket, however, applies the procedure "to each element from first to last")
A recently active answer
mentions that it requires a filterfunc which works over its argument list
in order. How should one write this function?
An answer with my explanation of the issue is supplied.
What order might a Scheme implementation use, and why? Let's try it (all code run in Chez Scheme REPL):
Display order of applications
> (filter (lambda (x) (display x) (even? x))
'(0 1 2 3 4 5)))
452301(0 2 4)
>
Why this order?
R6RS implementations must check that list is a proper list
ends with the empty list:
> (filter (lambda (x) (display x) (even? x))
'(0 1 2 . 3)))
Exception in filter: (0 1 2 . 3) is not a proper list
>
no circularity:
> (define xs '(0 1 2 3))
> (set-cdr! (cdddr xs) (cdr xs))
> (filter (lambda (x) (display x) (even? x)) xs)
Exception in filter: (0 1 2 3 1 2 ...) is not a proper list
>
the implementation of filter in Chez Scheme which checks these requirements
while filtering, resulting in the "452301" order of predicate applications,
can be seen here
(lines 589-617: a version is included as a spoiler below as an alternative to scrolling through
the source on github)
What?
The Chez Scheme code uses a "tortoise and hare" algorithm
to detect cycles. Without error checks the code could be:
> (let ([filter
(lambda (pred? ls)
(let f ([fast ls])
(if (pair? fast)
(let ([rest (f (cdr fast))])
(if (pred? (car fast))
(cons (car fast) rest)
rest))
'())))])
(filter (lambda (x) (display x) (even? x))
'(0 1 2 3 4 5)))
543210(0 2 4)
>
(the identifier fast is used to match the Chez Scheme code: could be ls otherwise)
How can one change this to call pred? "from first to last"?
replace the rest variable with an accumulator (compare the following with 3 above;
the changes are small, but filtered elements are consed to acc,
so it has to be reversed to give the result):
> (let ([filter
(lambda (pred? ls)
(let f ([fast ls] [acc '()])
(if (pair? fast)
(f (cdr fast)
(if (pred? (car fast))
(cons (car fast) acc)
acc))
(reverse acc))))])
(filter (lambda (x) (display x) (even? x))
'(0 1 2 3 4 5)))
012345(0 2 4)
>
So 4 could be used as the required filterfunc. It would be an interesting exercise
to add error checks like the Chez Scheme implementation, which is effectively:
(define (filter pred? ls)
(unless (procedure? pred?)
(error #f "not a procedure" pred?))
(or (let f ((pred? pred?) (fast ls) (slow ls))
(if (pair? fast)
(let ((fast1 (cdr fast)))
(if (pair? fast1)
(and (not (eq? fast1 slow))
(let ((fast2 (cdr fast1)))
(let ((rest (f pred? fast2 (cdr slow))))
(and rest
(if (pred? (car fast))
(if (pred? (car fast1))
(if (eq? rest fast2)
fast
(list* (car fast)
(car fast1) rest))
(cons (car fast) rest))
(if (pred? (car fast1))
(if (eq? rest fast2)
fast1
(cons (car fast1) rest))
rest))))))
(and (null? fast1)
(if (pred? (car fast))
fast
'()))))
(and (null? fast) '())))
(error #f "circular/improper list" ls)))
It involves you should not use mutation of some external variable inside procedure and it supposes the implementation may apply parallelism, for example map-reduce.

Adding "Simply Scheme" language to DrRacket

I want to work through this book: http://www.eecs.berkeley.edu/~bh/ss-toc2.html. But I'm having trouble to get the "Simply Scheme" language working. The code won't run.
#lang planet dyoo/simply-scheme:2
(parse ’(4 + 3 * 7 - 5 / (3 + 4) + 6))
I keep getting the following error message: "parse: unbound identifier in module in: parse".
Take a look at this page, it has complete instructions. Simply do this:
#lang racket
(require (planet dyoo/simply-scheme:2:2))
Also be aware that the ’ character is incorrect, for quoting use ', this probably happened because you copy-pasted code with wrong typesetting.
And of course, after the above is done, you have to define the procedures explained in chapter 18, they're not defined in the package you just imported! this will work for sure:
(define (parse expr)
(parse-helper expr '() '()))
(define (parse-helper expr operators operands)
(cond ((null? expr)
(if (null? operators)
(car operands)
(handle-op '() operators operands)))
((number? (car expr))
(parse-helper (cdr expr)
operators
(cons (make-node (car expr) '()) operands)))
((list? (car expr))
(parse-helper (cdr expr)
operators
(cons (parse (car expr)) operands)))
(else (if (or (null? operators)
(> (precedence (car expr))
(precedence (car operators))))
(parse-helper (cdr expr)
(cons (car expr) operators)
operands)
(handle-op expr operators operands)))))
(define (handle-op expr operators operands)
(parse-helper expr
(cdr operators)
(cons (make-node (car operators)
(list (cadr operands) (car operands)))
(cddr operands))))
(define (precedence oper)
(if (member? oper '(+ -)) 1 2))
(define (compute tree)
(if (number? (datum tree))
(datum tree)
((function-named-by (datum tree))
(compute (car (children tree)))
(compute (cadr (children tree))))))
(define (function-named-by oper)
(cond ((equal? oper '+) +)
((equal? oper '-) -)
((equal? oper '*) *)
((equal? oper '/) /)
(else (error "no such operator as" oper))))
(parse '(4 + 3 * 7 - 5 / (3 + 4) + 6))
=> '(+ (- (+ (4) (* (3) (7))) (/ (5) (+ (3) (4)))) (6))
(compute (parse '(4 + 3 * 7 - 5 / (3 + 4) + 6)))
=> 30 2/7
There is also a module allowing you to run "Simply Scheme" here:
https://gist.github.com/alexgian/5b351f367169b40a4ad809f0bb718e1f
You can just run it and then type your code in interactively, no need for an installation like the Planet/dyoo code mentioned above.
Should you wish to, though, you can also install it, so that all you have to do then is to prefix any program with #lang simply-scheme and it will work.
Instructions for how to do so can be seen here:
https://groups.google.com/forum/#!topic/racket-users/jHPtw3Gzqk4
in the message by Matthew Butterick, June 4 2018.
This version takes care of some stuff not done the dyoo code, for instance
> (first 'american)
'a
> (first 'American)
"A"
> (every butfirst '(AmericAn Legacy CODE))
'("mericAn" egacy "ODE")
I.e. incorrect mixing of strings and symbols, instead of
> (first 'american)
a
> (first 'American)
A
> (every butfirst '(AmericAn Legacy CODE))
(mericAn egacy ODE)
as it should be.
The dyoo implementation might be more complete for docs, etc, though
However, as noted in the answer above, you will still have to enter the code for the parse function yourself, as this was the intention of the authors.
I had to revert to DrRacket 5.4.1 in order to get both Simply Scheme and SICP to work.

programmatic way to stop a function after certain time and debug enclosed variables

A long-run function like infinite loop:
> (define appendInf
(lambda (lst)
(appendInf (cons 1 lst)))
In Chez Scheme, make-engine can achieve the stopping after ticks:
> (define eng
(make-engine
(lambda ()
(appendInf '()))))
While of course with the scope of lst I get error when:
> (eng 50
list
(lambda (new-eng)
(set! eng new-eng)
(length lst)))
Exception: variable lst is not bound
If I want to get the value 'lst' in appendInf when the time limit is reached, I use set!:
> (define lst '())
> (define appendInf
(lambda (ls)
(set! lst (cons 1 ls))
(appendInf lst)))
now I can get:
> (eng 50
list
(lambda (new-eng)
(set! eng new-eng)
(length lst)))
8
So for every variable within the function I want to trace, a global variable needs to be added, and one more transforming by adding (set!…).
is this a correct way to handle any enclosed variables?
if yes to 1, in Scheme is there a better way to achieve this?
is there any programming language that can more easily
implement this kind of debugging?
Well. I'm using racket and it has a pretty good debugger and does standard r6rs as well as non-standard racket.
;; macro to do the heavy work
(define-syntax recdb
(syntax-rules ()
((_ thunk fun a1 ...)
(let ((orig-fun fun)(ethunk thunk))
(fluid-let ((fun (lambda args
(if (ethunk)
(apply orig-fun args) ;; set breakpoint on this
(apply orig-fun args)))))
(fun a1 ...))))))
;; a time-thunk generator
(define (period-sec sec)
(let ((time-done (+ sec (current-seconds))))
(lambda ()
(if (< time-done (current-seconds))
(begin
(set! time-done (+ sec (current-seconds)))
#t)
#f))))
;; a round-thunk generator
(define (rounds n)
(let ((rounds-to-go n))
(lambda ()
(if (zero? rounds-to-go)
(begin
(set! rounds-to-go (- n 1))
#t)
(begin
(set! rounds-to-go (- rounds-to-go 1))
#f)))))
;; my never ending procedure
(define (always n)
(always (+ n 1)))
;; one of the ones below to implement
(recdb (rounds 10) always 0))
(recdb (period-sec 1) always 0)
;; functions with auxillary procedures need to have their gut changed for it to work
(define (fib n)
(define (fib-aux n a b)
(if (= n 0)
a
(fib-aux (- n 1) b (+ a b))))
(recdb (period-sec 2) fib-aux n 0 1))
;; trying it
(fib 200000)
Now. Just run the debugger and set breakpoint (right click expression in the macro and choose "Pause at this point") where it's indicated in the code and you have a way to examine the variables every x seconds or x times.
Happy debugging :)

scheme - equal function with lists

I wrote this program:
(define find-combination
{lambda (a b)
(if (eq? ((quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b)))))
(display "1*v1" + ((quotient (car a) (car b))*"v2"))
(display "0*v1" + "0*v2"))})
(find-combination (list 2 2) (list 2 1))
a and b are two lists. Its give me the next problem: procedure application: expected procedure, given: 1; arguments were: 2.
I didn't get what is the problem. Someone can help me? Thank u.
First of all you have too much brackets after eq? - what you wrote means evaluating (quotient (car a) (car b)) and treating it as a function with argument (quotient (car (cdr a)) (car (cdr b))). The error means that first thing was evaluated to 1 and your interpreter expected it to be a procedure, not an integer. This line should be:
(if (eq? (quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b))))
or even:
(if (eq? (quotient (car a) (car b)) (quotient (cadr a) (cadr b)))
Apart from that, lines with display calls are wrong - Scheme doesn't have an infix notation, so + and * are out of place.
First of all you have a set of curly braces in your code(the one before lambda)
Also you have another set of paranthesis around the parameters you passed to eq?
It should be something like this:
(eq? (quotient (car a) (car b)) (quotient (car (cdr a)) (car (cdr b))))
In Scheme and Racket, parentheses change the meaning of things.
1
is a number, but
(1)
is a call to 1 as a function... but 1 is a number, not a function, so this will cause the error you describe.
Your use of curly braces is also a little unsettling to me.

Resources