How to follow the Simply Scheme book with DrRacket - scheme

I'd like to be able to manipulate sentences so that I can take them as an input and return an output based on things like the individual letters. For example, an ends-e command that would return all of the words that end in "e":
(ends-e '(only the good die young))
=> '(the die)
Unfortunately, "e" is a string, and '(only the good die young) is a sentence. Scheme has trouble understanding a sentence as a data type (because it isn't one). How do I turn a sentence that the user inputs with a quote and parentheses into something I can manipulate and return in the same sentence format?
This book: https://people.eecs.berkeley.edu/~bh/ssch8/higher.html#ft1 outlines some functions that can manipulate sentences and words, but posts a footnote at the bottom saying "Like all the procedures in this book that deal with words and sentences... [the] procedures in this chapter are part of our extensions to Scheme."
How do I get those extensions? I looked in a later chapter, but my understanding of the language is too rudimentary to understand how to create those procedures myself.
These are the error messages I get when I try to turn '(h) into a datatype scheme can understand.
Welcome to DrRacket, version 6.12 [3m].
Language: sicp, with debugging; memory limit: 128 MB.
> (symbol->string '(h))
. . symbol->string: contract violation
expected: symbol?
given: (mcons 'h '())
> (list->string '(h))
. . list->string: contract violation
expected: (listof char?)
given: '(h)
> (string->list '(h))
. . string->list: contract violation
expected: string?
given: (mcons 'h '())
> (string->symbol '(h))
. . string->symbol: contract violation
expected: string?
given: (mcons 'h '())
>
This means I cant ask scheme if '(h) is equal to "h". I can't even ask it if '(h) is equal to '(h)!
> (eq? '(h) "h")
#f
> (eq? '(h) '(h))
#f
>

In DrRacket there is a Simply Scheme compatibility language
1. From the Package Manager
Open the Package Manager: in DrRacket choose the menu "File" then choose "Package Manager...".
In the tab "Do What I Mean" find the text field and enter: "simply-scheme" without the quotes.
Click the "Install" button. This produces smoe output. When you can click "close output" it's finished and you may close the window.
Test it. Make sure DrRacket has "Determine language from source" in
the bottom left corner. Write the following program and click RUN:
#lang simply-scheme
(se (butlast (bf "this"))
"world")
; ==> (hi "world")
I was a little confused since SICP and Simply Scheme are two different books. SICP has their own specified procedures from their book and in DrRacket there is a specific language, #lang sicp, for that flavor of Scheme too. I've written a similar answer on how to install sicp.

Related

How to `apply` a macro/syntax in Racket?

Suppose I have a list of arguments args and a macro/syntax f that takes a variable number of arguments. How do I apply f to args? Apparently apply doesn't work here.
For example, suppose I have a list of values bs and I want to know if they're all true, so I try (apply and bs) but I get the error "and: bad syntax". The workaround I came up with is (eval `(and . ,bs)) but I'm wondering if there is some standard way to achieve this sort of thing.
Update
A bunch of possible duplicates have been suggested, but most of them are just about the and example. This suggested question seems to be the same as mine, but the answer there is not very helpful: it basically says "don't do this!".
So maybe the point is that in practice this "apply + macro" question only comes up for macros like and and or, and there is no useful general question? I certainly ran into this issue with and, and don't have much Scheme experience, certainly no other examples of this phenomenon.
This is an XY problem. Macros are part of the syntax of the language: they're not functions and you can't apply them to arguments. Conceptually, macros are like functions which map source code to other source code, and which are called at compile time, not run time: trying to use them at run time is a category error. (In Common Lisp macros are, quite literally, functions which map source code to other source code: in Scheme I'm not quite so clear about that).
So if you have a list and you want to know if all its elements are true, you call a function on the list to do that.
It's easy to write such a function:
(define (all-true? things)
(cond [(null? things)
#t]
[(first things)
(all-true? (rest things))]
[else #f]))
However Racket provides a more general function: andmap: (andmap identity things) will either return false if one of things is not true, or it will return the value of the last thing in the list (or #t if the list is empty). (andmap (lambda (x) (and (integer? x) (even? x))) ...) will tell you if all the elements in a list are even integers, for instance.
There is also every which comes from SRFI 1 and which you can use in Racket after (require srfi/1). It is mostly (exactly?) the same as andmap.
One thing people sometimes try to do (and which you seem to be tempted to do) is to use eval. It may not be immediately clear how awful the eval 'solution; is. It is awful because
it doesn't, in fact, work at all;
insofar as it does work it prevents any kind of compilation and optimisation;
last but not least, it's a pathway to code injection attacks.
Let's see how bad it is. Start with this:
> (let ([args '(#t #t #f)])
(eval `(and ,#args)))
#f
OK, that looks good, right? Well, what if I have a list which is (a a a b): none of the elements in that are false, so, let's try that:
> (let ([args '(a a b)])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
Oh, well, can I fix that?
> (let ([args '(a a b)]
[a 1] [b 2])
(eval `(and ,#args)))
; a: undefined;
; cannot reference an identifier before its definition
No, I can't. To make that work, I'd need this:
> (define a 1)
> (define b 2)
> (let ([args '(a a b)])
(eval `(and ,#args)))
2
or this
> (let ([args '('a 'a 'b)])
(eval `(and ,#args)))
'b
Yes, those are quotes inside the quoted list.
So that's horrible: the only two cases it's going to work for is where everything is either defined at the top level as eval has no access to the lexical scope where it is called, or a literal within the object which may already be a literal as it is here, because everything is now getting evaluated twice.
So that's just horrible. To make things worse, eval evaluates Scheme source code. So forget about compiling, performance, or any of that good stuff: it's all gone (maybe if you have a JIT compiler, maybe it might not be so awful).
Oh, yes, and eval evaluates Scheme source code, and it evaluates all of it.
So I have this convenient list:
(define args
'((begin (delete-all-my-files)
(publish-all-my-passwords-on-the-internet)
(give-all-my-money-to-tfb)
#t)
(launch-all-the-nuclear-missiles)))
It's just a list of lists of symbols and #t, right? So
> (eval `(and #,args)
; Error: you are not authorized to launch all the missiles
; (but all your files are gone, your passwords are now public,
; and tfb thanks you for your kind donation of all your money)
Oops.
It would be nice to be able to say, if I have a list that I want to check some property of that doing so would not send all my money to some person on the internet. Indeed, it would be nice to know that checking the property of the list would simply halt, at all. But if I use eval I can't know that: checking that every element of the list is (evaluates to) true may simply never terminate, or may launch nuclear weapons, and I can generally never know in advance whether it will terminate, or whether it will launch nuclear weapons. That's an ... undesirable property.
At the very least I would need to do something like this to heavily restrict what can appear in the list:
(define (safely-and-list l)
(for ([e (in-list l)])
(unless
(or (number? e)
(boolean? e))
(error 'safely-and-list "bad list")))
(eval `(and ,#l)))
But ... wait: I've just checked every element of the list: why didn't I just, you know, check they were all true then?
This is why eval is never the right solution for this problem. The thing eval is the right solution for is, well, evaluating Scheme. If you want to write some program that reads user input and evaluates, it, well, eval is good for that:
(define (repl (exit 'exit))
(display "feed me> ")
(flush-output)
(let ([r (read)])
(unless (eqv? r exit)
(writeln (eval r))
(repl exit))))
But if you think you want to apply a macro to some arguments then you almost certainly have an XY problem: you want to do something else, and you likely don't understand macros.

What is the type of the following expression in Scheme?

I am trying to understand what is the type of the following statement in Scheme:
#&\a
what is the type of the expression above?
is it a comment?
In Racket, #&\a is an immutable box containing a symbol.
(box? #&\a) ; #t
(unbox #&\a) ; 'a
(symbol? (unbox #&\a)) ; #t
(immutable? #&\a) ; #t
Refer to Reading Boxes.
#&\a is not valid Scheme code.
Anything starting with # is typically a reader macro of some sort. In Scheme all from reading numbers in specific bases, vector literals and booleans start with the # and this is remnants from the time Scheme was interpreted under a MacLISP host. It would use reader macro to do the right thing at read time. Common Lisp has the same functionality today.
Examples:
'#(1 2 3) ; a vector of 3 elements
#f ; boolean false (everything else is thruthy)
#x10 ; 16 read in hexadecimal
It's not uncommon for an implementation to expand features beyond the report and the report does not ban this. Thus any implementation can add other reader macros and it won't affect Scheme code since you'll never use those in Scheme code, only in the implementers new Scheme dialect. I don't think there exist one Scheme implementation that only implement the report and nothing else.

SICP Ch5 eceval compiler in Racket: set-cdr! into quoted list (not a dup)

This is not a duplicate of
set-car!, set-cdr! unbound in racket? or
of
Implement SICP evaluator using Racket
or of
How to install sicp package module in racket?,
but rather a follow-up question because the solutions proposed therein do not
work for me. First, the need: Section 5.5.5 of SICP, the compiler plus
explicit-control evaluator (code here in "ch5-eceval-compiler.scm"), are
entirely dependent on set-car! and set-cdr! into explicit quoted lists. I
would like to copy and modify this code without a complete, bottom-up rewrite in
immutable form. I'd also accept a reference to a scheme implementation that can
run the code out-of-the-box or with some minimal, straightforward adaptation,
i.e., a scheme that has set-car! and set-cdr! or some
work-around. Neither guile nor racket give me an easy time running this code.
EDIT: mit scheme will load the eceval compiler. I'm leaving the question up for those who might want to get it going in racket (I would rather, for example).
Here is a deeper explanation, including the things I explored and tried out, and
how I diagnosed the quoted list as the deepest problem. When I hand-converted
the quoted list into an mquoted nest of mlists, the code broke in much worse
ways and the rabbit hole got much deeper. I had to revert after a couple of
hours of delicate brain surgery that failed.
Here is an MVE of the kind of structure that section 5.5.5 relies on. This is small, but structurally like the real thing:
(define foo '(a b))
(set-cdr! foo '(c))
The real thing starts like this:
(define eceval
(make-machine
'(exp env val proc argl continue unev
compapp ;*for compiled to call interpreted
)
eceval-operations ;; ----------------------------------------------
'( ;; <<<<<<<<======== BIG QUOTED LIST CAUSING TROUBLE / NOT MCONSES!
;;SECTION 5.4.4, as modified in 5.5.7 ;; -------------------------------
;;*for compiled to call interpreted (from exercise 5.47)
(assign compapp (label compound-apply))
;;*next instruction supports entry from compiler (from section 5.5.7)
(branch (label external-entry))
read-eval-print-loop
(perform (op initialize-stack))
(perform
(op prompt-for-input) (const ";;; EC-Eval input:"))
...
and goes on for quite a while. The evaluator is the "machine-code" in the quoted
list, and various generated code does set-car! and set-cdr! into registers
and environment frames and other things. The code fails on load.
There seems to be no easy way to convert the evaluator into immutable form
without a full rewrite, and I'm trying to avoid that. Of course, set-car! and
set-cdr! are not available in #lang racket, and I don't think they're in
guile, either (at least guile refused to load "ch5-eceval-compiler.scm,"
throwing a mutability error, on which I did not dig deeper).
One solution proposed in
set-car!, set-cdr! unbound in racket? is
to rewrite the code using mcons, mcar, mlist, etc. according to (require
compatibility/mlist) (require rnrs/mutable-pairs-6). Those compatibility
packages have no replacement for quote, so I tried writing my own mquote. I
spent a couple of hours on such a refactoring, but the exercise was not
converging, just going deeper and deeper down the rabbit hole and ending up with
even deeper problems. It seems that to pursue even a refactoring I must
understand more semantics about "ch5-eceval-compiler.scm," and if I must, I
might as well rewrite it in immutable form.
Easier solutions proposed in
set-car!, set-cdr! unbound in racket?
are to use #lang sicp or #lang r5rs. There follows three experiments that
referenced other answers on stack overflow:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable
set-cdr!: undefined;
cannot reference an identifier before its definition
in module: "/usr/share/racket/pkgs/r5rs-lib/r5rs/main.rkt"
-----------------------------------------------
which points to a place where set-cdr! is clearly defined:
...
(module main scheme/base
(require scheme/mpair
racket/undefined
(for-syntax scheme/base syntax/kerncase
"private/r5rs-trans.rkt")
(only-in mzscheme transcript-on transcript-off))
(provide (for-syntax syntax-rules ...
(rename-out [syntax-rules-only #%top]
[syntax-rules-only #%app]
[syntax-rules-only #%datum]))
(rename-out
[mcons cons]
[mcar car]
[mcdr cdr]
[set-mcar! set-car!] ;; --------------------------
[set-mcdr! set-cdr!] ;; <<<<<<<<======== LOOK HERE
[mpair? pair?] ;; --------------------------
[mmap map]
[mfor-each for-each])
= < > <= >= max min + - * /
abs gcd lcm exp log sin cos tan not eq?
call-with-current-continuation make-string
symbol->string string->symbol make-rectangular
exact->inexact inexact->exact number->string string->number
...
Here is a similar failure with #lang sicp
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
Error: struct:exn:fail:contract:variable
set-cdr!: undefined;
cannot reference an identifier before its definition
in module: "/home/rebcabin/.racket/7.2/pkgs/sicp/sicp/main.rkt"
----------------------------------------------------
pointing to code that only indirectly defines set-cdr!, but clearly in the
appropriate package:
....
#lang racket
(require racket/provide ;; --------------------------------------------
(prefix-in r5rs: r5rs) ;; <<<<<<<<======== PULL IN SET-CDR! ETC. HERE?
(rename-in racket [random racket:random])) ;; ------------------------
(provide (filtered-out (λ (name) (regexp-replace #px"^r5rs:" name ""))
(except-out (all-from-out r5rs) r5rs:#%module-begin))
(rename-out [module-begin #%module-begin]))
(define-syntax (define+provide stx)
(syntax-case stx ()
[(_ (id . args) . body) #'(begin
(provide id)
(define (id . args) . body))]
[(_ id expr) #'(begin
(provide id)
(define id expr))]))
...
I dig deeper into
Implement SICP evaluator using Racket
and find
(require (only-in (combine-in rnrs/base-6
rnrs/mutable-pairs-6)
set-car!
set-cdr!))
(define foo '(a b))
(set-cdr! foo '(c))
foo
yielding
Error: struct:exn:fail:contract
set-mcdr!: contract violation
expected: mpair?
given: '(a b)
argument position: 1st
other arguments...:
'(c)
This error implies that the problem really is the quoted list. I don't have an
easy way to make the big quoted list in eceval into an mlist or chain of
mcons. I tried it and it's very verbose and error prone, plus I think the code
that loads eceval scans and patches that list, so it uses other list operations.
I had to revert after going south in a bad way.
Perhaps I missed some way to automate the transformation, a macro, but that's a
deeper rabbit hole (my scheme macro-fu is too old).
So I'm stuck. Nothing easy or recommended works. I'd like to either (1) know a scheme implementation that will run this code (2) some way I can implement set-car! and set-cdr! in racket (3) some other kind of work around (4) or maybe I just made a stupid mistake that one of you kind people will easily fix.
I tried (by either running racket directly or running it via DrRacket)
#lang sicp
(define foo '(a b))
(set-cdr! foo '(c))
foo
and it outputs (a c).
This also works:
#lang r5rs
(define foo '(a b))
(set-cdr! foo '(c))
(display foo)
To answer your question regarding the implementation of SICP (which I am currently maintaining), you are correct that (prefix-in r5rs: r5rs) will import set-cdr!.
Update: I just installed Geiser and now experienced the same problem that you did when I C-c C-b. However, C-c C-a works as expected.
Personally, I would use racket-mode instead of Geiser.
Mit-scheme will load the eceval compiler from the code drop mentioned in the question. On Ubuntu, mit-scheme loads with sudo apt-install mit-scheme. The geiser package of emacs finds mit via run-mit. The problem is solved.

Scheme how to remove extra message? like ;Value ;Unspecified return value in GNU Scheme

I am computer science student in university, and my professor give me assignment about Scheme..
then, i set up the scheme 9.2 version, and try to this but, i'm gonna be crazy because of this![enter image description here][1]
52 error> (display "hi")
hi
;Unspecified return value
what is that? ;Unspecified return value
i wanna just display "hi" !
i have questions, how to remove that and how call like that? error code?, check text? or... what? there is a word?
thanks to read....
Your are using the read-eval-print loop. This has the effect that every expression you feed it has a response. If you don't like that you can run the program instead of using the REPL.
How to run a program is not covered by the standard so you need to check the documentation for your chosen implementation.
Here is an example using Ikarus:
#!r6rs
(import (rnrs))
(+ 4 5)
(display "Hello, world!")
(newline)
I've saved it as test.scm and I start it like this:
$ ikarus --r6rs-script test.scm
Hello, world!
$
Notice the result of (+ 4 5) is not displayed. It is dead code since the value is calculated, but then thrown away since it is not used and then continues to evaluate the next expression. Nothing is printed unless you explicit ask it to. In Ikarus REPL you'll see this:
> (+ 4 5)
9
> (display "Hello, world!")
Hello, world!> (newline)
>
It doesn't print the undefiend value #<void>> in the Ikarus REPL. To see it you need to display it:
(display (if #f #t))
; ==> #<void> (not printed by the REPL), but `display` will print `#<void>`

Why is this legal (racket) scheme?

I was going through htdp and found this somewhere in the beginning :-
Explain why the following sentences are illegal definitions:
1. (define (f 'x) x)
However, it works fine in racket:
> (define (f 'x) x)
> (f 'a)
3
> (define a 5)
> (f a)
3
Obviously, I'm missing something ... what, exactly ?
Short answer: you should not be using the full "#lang racket" language. The teaching languages strip out the potentially confusing advanced features of the language that you're encountering.
In this case, your definition is being interpreted as a function called f with an optional argument called quote whose default value is provided by 'x'.
Set the language level to Beginning Student, and you'll get a much more reasonable answer.
This line does not work for me in Racket: (define (f 'x) x). The error reported is define: not an identifier for procedure argument in: (quote x).
What language are you using? did you try to run the above line in the interaction window?

Resources