Can't load Simply Scheme code - scheme

I'm having trouble with loading the code for the Berkeley Scheme course Simply Scheme, specifically this code. I've tested it in many different versions of Scheme. In Chicken, I get this error:
#;1> (load "simply.scm")
; loading simply.scm ...
Error: (symbol->string) bad argument type - not a symbol: #<procedure (? wd)>
Call history:
<syntax> (##core#if (empty? x) (##core#begin (whoops "Invalid argument to FIRST: " x)) (##core#if (word? x) (......
<syntax> (empty? x)
<syntax> (##core#begin (whoops "Invalid argument to FIRST: " x))
<syntax> (whoops "Invalid argument to FIRST: " x)
<syntax> (##core#if (word? x) (##core#begin (word-first x)) (##core#begin (whoops "Invalid argument to FIRST:...
<syntax> (word? x)
<syntax> (##core#begin (word-first x))
<syntax> (word-first x)
<syntax> (##core#begin (whoops "Invalid argument to FIRST: " x))
<syntax> (whoops "Invalid argument to FIRST: " x)
<syntax> (##core#undefined)
<syntax> (word->string word->string)
<eval> (word->string word->string)
<eval> (string? wd)
<eval> (number? wd)
<eval> (symbol->string wd) <--
Just for comparison, Racket gives this error:
Welcome to Racket v6.3.
> (load "simply.scm")
simply.scm:20:12: set!: cannot mutate module-required identifier
in: number->string
context...:
/home/hercynian/racket/collects/racket/private/misc.rkt:87:7
. . . which doesn't seem to be the same thing. This is beyond my rank beginner skills to fathom. Any ideas what's wrong with simply.scm?

It seems to work with:
guile (2.0.11),
chicken's intepreter (4.10.0),
gambit's interpreter gsi (4.2.8),
mit-scheme (9.1.1)
Racket will not do, afaik you'd have to modify this file quite heavily (at least change set! to define and probably wrap it all in module? -- but I'm no racket guy)
Here's what I would do:
download this simply.scm file once again, just to be sure (your chicken error suggests somewhere you miss "let", maybe in line 264 (def. of word) or 310 (def. of first)?),
try the above scheme implementations, in case you do get any errors, paste them here,
in case you don't have these versions (which would be weird, but I don't know your situation), and are doing the course on your own, try to do it without simply.scm, and any time you find something's missing in your scheme, try to copy only that definition from simply.scm (or modify your code so that it's not needed) -- that's the hardcore way.

I see from the error that you are using DrRacket IDE or racket binary.
Racketeer and SO-er Danny Yoo has made a Racket module language to support Simply Scheme in the racket language suite. In Racket with the bottom left dropdown set to "Determine language from source" and replace the definitions window, including the #lang line to the following:
#lang planet dyoo/simply-scheme:2
(se (butlast (bf "this"))
"world")
And press RUN. It will download and install the language and then you'll see the answer (hi "world"). The first time around you might see an error, but my experience is that it will go away on a consecutive run.
The definitions will have all the simply scheme features described in the the documentation. Happy hacking!

Related

unbound identifier in module for Dr Racket

Just trying to make a simple program to start to learn Scheme, and I keep on getting this error message. Here is my code:
#lang racket
(define (1+) (+ 1 x))
and I get the error "unbound identifier in module"
Figured it out... I needed the variable in the name of it
(define (1+ x) (+ 1 x))

What is the racket translation of this piece of lisp code?

;; loads a board from the given file
;; it expects the board to be in the format of a single S-expression:
;; a list of nine lists, each containing 9 numbers
(defun get-board-from-file file
(let ((in (open file :if-does-not-exist nil)))
(when in (return-from get-board-from-file (read in)))
(when (not in) (format t "~%Unable to open file ~A" file))
)
)
This is part of a soluton for a sudoku solver.
Try the following, it's a functional equivalent of the Lisp code in the question, but written in Racket:
(define (get-board-from-file file)
(with-handlers ([exn:fail:filesystem?
(lambda (exn) (printf "~%Unable to open file ~A" file))])
(call-with-input-file file
(lambda (in) (read in)))))
The above code handles an exception if the file doesn't exist, and makes sure that the port is closed after the file is read.

How to print racket check-expect results in terminal

I have the following racket code:
(require test-engine/racket-tests)
(define (square val)
(* val val))
(check-expect (square 3) 9)
When I execute the script in DrRacket using the Beginning Student language, I get the following output in the application console (the view is called “Interactions” in DrRacket):
The test passed!
When I execute the same script in the Terminal via racket my_script.rkt I do not see any output. I checked racket --help but I don’t see any viable option. How can I execute the script in the Terminal and have the same line printed out?
The following works for me in both DrRacket and in the terminal:
#lang racket/base
(require test-engine/racket-tests)
(define (square val)
(* val val))
(check-expect (square 3) 9)
(test)
and prints
The only test passed!
Note that had to add (test) to make this happen, both in DrRacket and on the command line, according to this doc.

Setting mode through a function in Emacs Lisp

I have the following code in my .emacs file, which works as you'd expect:
;; Ruby
(global-font-lock-mode 1)
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t)
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.rsel$" . ruby-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.rhtml$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.erb$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("\\.prawn$" . html-mode) auto-mode-alist))
(setq auto-mode-alist (cons '("Rakefile$" . ruby-mode) auto-mode-alist))
However, my attempts to DRY it up a bit fail:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(mapcar
(lambda (filename-pattern)
(setq
auto-mode-alist
(cons '(filename-pattern . mode) auto-mode-alist)))
filename-pattern-list))
;; Ruby
(global-font-lock-mode 1)
(autoload 'ruby-mode "ruby-mode" "Ruby editing mode." t)
(set-mode-for-filename-patterns
ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
... with the following error:
Debugger entered--Lisp error: (void-variable ruby-mode)
(set-mode-for-filename-patterns ruby-mode (quote ("\\.rb$" "\\.rsel$" "\\.rhtml$" "\\.erb$" "\\.prawn$" "Rakefile$" "Gemfile$")))
eval-buffer(#<buffer *load*> nil "/home/duncan/.emacs" nil t) ; Reading at buffer position 1768
load-with-code-conversion("/home/duncan/.emacs" "/home/duncan/.emacs" t t)
load("~/.emacs" t t)
#[nil "\205\264
I'm a bit confused here ... in particular, I don't understand how ruby-mode is void & so can't be passed to a function, but can be consed into a pair?
Any pointers (heh) would be greatly appreciated.
In the form:
(cons '("\\.rb$" . ruby-mode) ...
ruby-mode is part of a quoted list. That means it is read as a symbol name, not evaluated as a variable. In other words, Emacs sees it as the symbol ruby-mode and accepts it as is.
In the form:
(set-mode-for-filename-patterns
ruby-mode
'("\\.rb$"
"\\.rsel$"
...
ruby-mode is not quoted, and so is read as the argument to a function. Function arguments are evaluated. Which means Emacs reads ruby-mode, recognizes it as a symbol, and tries to evaluate it. Evaluating a symbol means looking for the value that it points to, which in this case doesn't exist.
EDIT:
Your function still doesn't work, there's another problem. You've used a quoted list inside set-mode-for-filename-patterns. This works fine in your original code:
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
as you are in effect manually supplying the value for filename-pattern and mode. Inside your function, you need these symbols to be evaluated, which doesn't happen when they're quoted! The result is that instead of adding each different string from your list to auto-mode-alist, you get the symbol filename-pattern instead.
To fix this, you need to recognize that the '(filename-pattern . mode) is meant to produce a cons cell with the values of filename-pattern and mode. Which we can produce with (cons filename-pattern mode). So the corrected function would be:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(mapcar
(lambda (filename-pattern)
(setq
auto-mode-alist
(cons (cons filename-pattern mode) auto-mode-alist)))
filename-pattern-list))
And the corrected function call is:
(set-mode-for-filename-patterns
'ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
Look here:
(setq auto-mode-alist (cons '("\\.rb$" . ruby-mode) auto-mode-alist))
----------------------------^
This is a quote which means you prevent the evaluation of the next
form, thus '("\\.rb$" . ruby-mode) is equivalent to (cons '"hello"
'ruby-mode).
But when you call the function set-mode-for-filename-patterns the
arguments are first evaluate then their result is passed to the
function. That's why evaluation (set-mode-for-filename-patterns
ruby-mode ..) raise an error, because the emacs-lisp interpreter tries
to evaluate ruby-mode as a variable, but ruby-mode has no value in
this context hence the error (void-variable ruby-mode). What you
want here, is to pass the symbol ruby-mode so you have to quote it
like this (set-mode-for-filename-patterns 'ruby-mode ...)
Note that you could have set a value to ruby-mode mode with let.
(let ((ruby-mode 'ruby-mode))
(set-mode-for-filename-patterns ruby-mode ...))
Here when the argument the form (set-...) is evaluated it evaluates
ruby-mode and can find a value for it (which is the symbol
ruby-mode) and then pass it to the function.
I think set-mode-for-filename-patterns is an interesting function. I'm going to add it to my config but use a more optimized implementation.
The implementations here all add one item to the auto-mode-alist variable for each file suffix. Emacs searches this list every time it finds a file. So the shorter the auto-mode-alist, the faster Emacs will find files.
This version is probably slower at startup but faster when finding files:
(defun set-mode-for-filename-patterns (mode filename-pattern-list)
(push (cons (regexp-opt filename-pattern-list) mode)
auto-mode-alist))`
This will work with the the same call:
(set-mode-for-filename-patterns
'ruby-mode
'("\\.rb$"
"\\.rsel$"
"\\.rhtml$"
"\\.erb$"
"\\.prawn$"
"Rakefile$"
"Gemfile$"))
If you look at the value of auto-mode-alist you'll see that many of the built-in modes use regexps for the same performance reason.
BTW, I advise that you just trust regexp-opt to do the right thing. The regexps it makes are pretty hard on the eye (and brain).

Scheme: Proper application of the eval function?

at work I encountered a basic problem when trying to implement a configuration script with Scheme. To avoid the need of inventing an artificial and restricted language the script should contain actual code. This code shall be evaluated later on. To make the configuration work as desired it has to have access to certain variables. These variables are only known in the context of the evaluation. Therefore the configuration script has to be evaluated in the current environment. Here is a primitive example of what I am talking about:
(let ((a #t))
(wr "a is ..."
(eval '(if a "true" "false"))))
When running this code I'd always get an error message telling me that the variable 'a' is unknown. So the question is: Do you know how to evaluate frozen code inside the current environment?
P.S.: I use the bigloo compiler.
/////////////////////////////////////////////
EDIT: //////////////////////////////////////////////////////
When using the approach suggested by Chris I came to another interesting problem, the usage of the case keyword. The following two examples both use the same case construction which should trigger the output of a "yes!" line. Unfortunately they behave differently.
Usual -> output is "yes!" as expected:
(define testit "test")
(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
With eval -> output is surprisingly "no":
(define env (null-environment 5))
(eval '(define testit "test") env)
(eval '(case testit
(("test")
(begin (newline) (write "yes!") (newline)))
(else
(begin (newline) (write "no!") (newline)))))
Does that make any sense?
eval cannot access lexical variables, such as those defined using let.
Instead, you have to create an environment, and populate it with the variables you want to make available. For example:
(define env (null-environment 5))
(eval '(define a #t) env)
(wr "a is ..."
(eval '(if a "true" "false") env))
To answer your edit, you aren't passing env as an argument to the last eval. testit doesn't exist in the environment that eval creates if that argument isn't given.
That may be a typo, but if not, that's your problem.

Resources