Syntax Error in Racket equal? - scheme

I am trying pass in a list input to conversation and have the function check to see if the first element in another list (keyword) matches to the first element of the list that user passed in. If the two match then output a zero otherwise pass the tail of the inputted list recursively back to itself.
(define keyword '(am I))
(define (conversation input)
(cond
((equal? (car keyword) (car input)) 0)
(else (conversation (cdr input)))))
The error I get is:
car: contract violation
expected: pair?
given: '()
I understand that equal? compares two elements, a pair, but what I do not understand is why it would create an error when the car of both lists are both exactly an element. Any help would be much appreciated, I'm assuming the solution is rather simple but I can't seem to see it.
My goal is create several functions that pattern match and output appropriate dialog but without the use of regular expressions or other libraries. There is no mandate not to use the two mentioned above but I would like to do it without them to get a better understanding of the logic and the code. Thanks for the help!

The first thing to consider is that you have no condition of failure. You assume there's either a match now with the car, or there will be a match later with the cdr. But there may be no match at all, and you will cdr down your list until your list is '(). As there is no such thing as the car of '() you are getting an error when you try to extract it. Therefore the first thing to do is make sure you've handled this case. I don't know what you intend to do in this case, so I have made the procedure return #f.
Next you consider what to do if the symbols do match. In your case you are choosing to return 0. This part seems to have no problems.
Finally, we consider what to do if the cars do not match. In this case we continue searching the input. This part seems to have no problems.
(define (conversation input)
(cond ((null? input) #f)
((eq? (car input) (car keyword))
0)
(else
(conversation (cdr input)))))

Related

Why do list-tail raise-exception? Why do we haven't closure property with respect to cdr?

If you evaluate (list-tail '(1 2) 3) at guile scheme. You will get an exception.
It would be smarter to have an '() as answer.
Overall why do we haven't closure property with respect to cdr combinator? What complications may arise?
Examples to make my point clearer
Now (cdr (cdr (cdr '(1 2))) -> raise-exception
Should be (cdr (cdr (cdr ... (cdr '(1 2))...))) -> ()
Then we would automatically have properly working list-tail
(define (list-tail list n)
(if (= n 0)
list
(list-tail (cdr list) (- n 1)))
Group-by then could be written elegantly and exceptionless
(define (group-by list-arg n)
(if (null? list-arg)
'()
(cons (list-head n) (list-tail n))))
The historic answer is that:
Originally, the Lisp 1 and 1.5 languages created by John MacCarthy did not allow (CDR NIL). The CDR function required a cons cell argument.
The idea that it would be convenient for (CDR NIL) to just return NIL came from a dialect called Interlisp (but may have been present elsewhere).
In the 1960's, there was another major dialect of Lisp called MacLisp (two decades before the Apple Mac, unrelated).
According to The Evolution of Lisp by Peter Gabriel and Guy Steele, some MacLisp people held a pow-wow with Interlisp people in 1974:
In 1974, about a dozen persons attended a meeting at MIT between the MacLisp and Interlisp implementors, including Warren Teitelman, Alice Hartley, Jon L White, Jeff Golden, and Guy Steele. There was some hope of finding substantial common ground, but the meeting actually served to illustrate the great chasm separating the two groups, in everything from implementation details to overall design philosophy. [...] In the end only a trivial exchange of features resulted from “the great MacLisp/Interlisp summit”: MacLisp adopted from Interlisp the behavior (CAR NIL) → NIL and (CDR NIL) → NIL, and Interlisp adopted the concept
of a read table.
Both Interlisp and MacLisp are ancestral dialects to Common Lisp, which also has the forgiving car and cdr.
Further remarks are made in the above paper on this matter, begining with:
The adoption of the Interlisp treatment of NIL was not received with universal warmth.
You can see from this fifty, sixty years ago, Lisp people were already divided into camps, and didn't agree on everything. Whether the car of an empty list should just yield the empty list, or error out is a very old issue.
Ashwin Ram, presently director of AI at Google, put in his own opinion in favor of forgiving cdr in 1986, when he composed this poem.
It still remains a divisive issue that is a matter of opinion.
It is undeniable that the flexible car, cdr and their derivatives can help you "code golf" list processing code.
It's also true that such code-golfed code sometimes handles only happy cases without error checking, which can cause problems in some circumstances.
For instance, some list that is assumed to always have three items is subject to (caddr list) to get the third item. But, due to some bug, it has only two. Now the code just ran off with the nil value, which may cause a problem somewhwere else. For instance, suppose the value is expected to be a string, and in some totally different function elsewhere, nil is passed to some API that needs a string and blows up. Now you're hunting through the code to discover where this nil came from.
People who write Lisp interpreters or compilers that rely on the forgiving destructuring performed by car and cdr end up producing something that accepts bad syntax silently.
For instance
(defun interpret-if (form env)
(let ((test (car form))
(then (cadr form))
(else (caddr form)))
(if (interpret-expr test env)
(interpret-expr then env)
(interpret-expr else env))))
This is actually a very nice example for discussing both sides of the issue.
On the one hand, the code is succinct, and nicely supports the optional else clause: the user of this interpreter can do:
(if (> x y)
(print "x is greater than y"))
In interpret-if, the else variable will pull out a nil, and that will get handed off to (eval expr else env) where it just evaluates to nil, and everything is cool; the optionality of else was obtained from free thanks to caddr not complaining.
On the other hand, the interpreter doesn't diagnose this:
(if) ;; no arguments at all
or this:
(if (> x y)) ;; spec says "then" is required, but no error!
However, all these issues have nice solutions and ways of working that don't require tightening up the list accessor functions, so that we can resort to the succinct coding when we need to. For instance, the interpreter could use pattern matching of some kind, like Common Lisp's rudimentary destructuring-bind:
(defun interpret-if (form env)
(destructuring-bind (test then &optional else) form
(if (interpret-expr test env)
(interpret-expr then env)
(interpret-expr else env))))
destructuring-bind has strict checking. It generates code with car, caddr and other functions under the hood, but also error checking code. The list (1 2 3) will not be destructured by the pattern (a b).
You have to look at the entire language and how it is used and what else is in it.
Introducing forgiving car and cdr into Scheme might give you less mileage than you think. There is another issue, which is that the only Boolean false value in Scheme is #f. The empty list () in Scheme is not false.
Therefore, even if car is forgiving, code like this cannot work.
Suppose the third element of a list is always a number, or else it doesn't exist. In Lisp, we can do this to default to zero:
(or (third list) 0)
for that to work in Scheme in the default 0 case, (third list) would have to return the Boolean false value #f.
A plausible approach might be to have different default values for car and cdr:
(car ()) -> #f
(cdr ()) -> ()
However, that is rather arbitrary: it works in some circumstances, but fails in situations like:
;; if list has more than two items ...
(if (cddr list) ...)
If cddr returns () by default, then that is always true, and so the test is useless. Different defaulting for car and cdr would probably be more error prone than common defaulting.
In Lisp, the forgiving list accessors work in a synergistic way with the empty list being false, which is why once upon a time I was quite surprised to learn that the forgiving list accessors came in fairly late into the game.
Early Scheme was implemented as a project written in Lisp, and therefore to interoperate smoothly with the host language, it used the same convention: () being NIL being the empty list and false. This was eventually changed, and so if you're wishing to have that back, you're asking for Scheme to revert a many-decades-old decision which is next to impossible now.
Object-oriented programming weighs in on this also. The fact that (car nil) does something instead of failing is an instance of the Null Object Pattern, which is something useful and good. We can express this in the Common Lisp object system, in which it practically disappears:
Suppose we had a car function which blows up on non-conses. We could write a generic function kar which doesn't, like this:
;; generic fun
(defgeneric kar (obj))
;; method specialization for cons class: delegate to car.
(defmethod kar ((obj cons))
(car obj))
;; specialization for null class:
(defmethod kar ((obj null))) ;; return nil
;; catch all specialization for any type
(defmethod kar ((obj t))
:oops)
Test:
[1]> (kar nil)
NIL
[2]> (kar '(a . b))
A
[3]> (kar "string")
:OOPS
In CLOS, the class null is that class whose only instance is the object nil. When a method parameter specializes to null, that method is only eligible when the argument for that parameter nil.
The class t is the superclass of everything: the top of the type spindle. (There is a bottom of the type spindle also, the class named nil, which contains no instances and is a subclass of everything.)
Specializing methods on null lets us catch method calls with nil parameters. Thanks to CLOS multiple dispatch, these can be thus handled in any parameter position. Because of that, and null being a class, the Null Object Pattern disappears in CLOS.
If you're debating Lisp with OOP people, you can present (car nil) can be spoken about as being the Null Object pattern.
The inconvenience of explicit null handling is recognized in numerous newer programming languages.
A common feature nowadays is to have null safe object access. For instance
foo.bar
might blow up if foo is null. So the given language provides
foo?.bar
or similar, which will only dereference .bar if foo isn't nil, otherwise the expression yields nil.
When languages add foo?.bar, they do not throw away foo.bar, or make foo.bar behave like foo?.bar. Sometimes you want the error (foo being nil is a programming error you want to catch in testing) and sometimes you want the default.
Sometimes you want the default, so you can collapse multiple levels of default and catch an error:
if (foo?.bar?.xyzzy?.fun() == nil) {
// we coudn't have fun(); handle it
// this was because either foo was nil, or else bar was nil,
// or else xyzzy was nil, or else fun() returned nil.
} else {
// happy case
}
cdr is only allowed on pairs. When you reach the end of the list, the value is (), which is not a pair, so you get an error.
You can check for this in your list-tail procedure to allow it to be more permissive.
(define (list-tail list n)
(if (or (= n 0) (not (pair? list)))
list
(list-tail (cdr list) (- n 1)))
Using (not (pair? list)) will also allow it to work for improper lists like (1 2 . 3). It will keep returning 3 for any n >= 2.
"You will get an exception."
This is a problem with many core libraries, and not just Scheme. Take Haskell's core library:
tail [1] -- []
tail [] -- error
head [1] -- 1
head [] -- error
As you know, the technical name for a function like this is a Partial Function. It is a function that doesn't work for some inputs, leading to errors.
So, yes, you can define your own version. One thing, though - what should be returned in the end condition? Should (list-tail '(1 2) 3) return () or should it return 0? If I'm trying to get a value to add to another number, then 0 would be appropriate. If I'm using cons to gather values then () would be appropriate. I guess that's why the function is left as partial.
"Right. I was interested why scheme was designed that way, without car/cdr closure property. Is it feature or just design flaw. It's more like scheme is less consistent than Common Lisp, rather strict."
Common Lisp returns NIL when it runs out of list:
(car '(1)) ; 1
(car '()) ; NIL
(cdr '(1)) ; 1
(cdr '()) ; NIL
In this case you would have to test for NIL, and if you wanted a zero instead make the replacement.
Why Scheme didn't have this is due to its minimalistic design. The report was so under-specified you could do pointer arithmetic and just let the program segfault since any faulty scheme code was deemed not scheme and pigs could fly. Later reports, like R7RS, requires much more error checking since it is required to signal errors in many situations where just undefined behavior would be OK in early reports.
With today's Scheme we can easily create car and cdr that does what you want:
#!r7rs
(define-library
(sylwester pair-accessors)
(export car cdr)
(import (rename (scheme base) (car base:car) (cdr base:cdr))
(except (scheme base) (car cdr)))
(begin
(define (car v)
(if (pair? v)
(base:car v)
'()))
(define (cdr v)
(if (pair? v)
(base:cdr v)
'()))))
So in your library or program you just import (scheme) (or (scheme base)) without car and cdr and also import (sylwester pair-accessors) and you're in business. Alternatively you can make a (scheme base) or (scheme) that replaces all accessors with you own safe ones using a macro to produce them all.
The only thing you cannot do is inject your version of car/cdr into already defined libraries since that would require some late binding or monkey-patching, but that isn't supported by the language. I'm fascinated by these things and would love to make a OO-scheme where you can augment standard procedures with some CLOS-ish late binding where all core functions under the hood are indeed methods so that you can define your own objects and accessors and that standard libraries and user libraries created for normal pairs would just work out of the box for your new data structures that has pair like features.

What is the use of 'when' in Scheme?

I'm triying to use when in Scheme but i dont know why at the last element of my list appears .#void>.
Here is my code
(define (genlist x y)
(when
(< x y)
(cons x (genlist (+ x 1) y))))
And this is my output =>
(2 3 4 5 6 7 8 9 . #void>)
We use when when we need to write an if without an else part, and/or when we need to write more than one expression inside the if. Only the last expression's value gets returned, hence we use it mostly for the side effects. To understand it better, in Racket this:
(when <condition>
<exp1>
<exp2>
<exp3>)
Is equivalent to this:
(if <condition>
(begin
<exp1>
<exp2>
<exp3>)
(void)) ; implementation-dependent
The same considerations apply to unless, except that the condition is surrounded with a (not ...).
The source of your problems (and the reason why it's a code smell to have an if without an else) is that your code is not handling the case when (>= x y). Ask yourself, what should you do in that case? Simple, return an empty list! that's the base case of the recursion that's missing from your code.
You would need to use (if (< x y) (cons ...) '()) to produce a proper list.
when (and it's counterpart unless) is mostly for doing side effects (like printing something out) in a context where the result is not used.
e.g. (when debug-mode? (print "got here"))
when is an one armed ifs with implicit begin. The following examples are the same:
(if (any odd? lst)
(begin
(set! some-binding #t)
(display "Found an odd element")))
(when (any odd? lst)
(set! some-binding #t)
(display "Found an odd element"))
And you can use unless instead of using not in the predicate:
(if (not (any odd? lst))
(set! some-binding #f))
(unless (any odd? lst)
(set! some-binding #f))
Peter Norvig made a nice book about Lisp style and in it he addresses this:
Be as specific as your data abstractions warrant, but no more.
if for two-branch expression
when, unless for one-branch statement
and, or for boolean value only
cond for multi-branch statement or expression
So while you can write all your logic using if it will not be the easiest code to read. Other might use the term principle of least surprise. Even though the book is for Common Lisp much of it can be used in Scheme as well. It's a good read if you want to program any lisp dialect professionaly.
For when and unless this is applies much better to Scheme as you have no idea what an implementation might return in the event the predicate evaluates to #f while in CL you could abuse when since it's destined to return nil in such cases.
In you code you are trying to return something and letting the implementation choose what should happen when the predicate failes is what causes the #<void>. When the return matter you should always use two armed if:
(if test-expression
then-expression
else-expression)
Note there is no else keyword.

Procedure expected 2 arguments plus optional arguments with keywords

I am running a program using the command line version of Racket.
At some point I call:
(sort(some-function (car set) (POWER (cdr set))))
The sort procedure looks like this:
(define (sort l)
(if (null? l)
'()
(insert (car l)
(sort (cdr l)))))
But when I run the program, it says:
Welcome to Racket v5.1.1.
> > > > > > procedure sort: expects 2 arguments plus optional arguments with keywords #:cache-keys? and #:key, given 1: (some-function (car set) (POWER (cdr set)))
Why does it say sort expects two arguments? When running it through the Racket GUI, I have no problems.
It seems that you're trying to execute Racket's built-in sort procedure, which in fact receives 2 arguments (a list and a comparison procedure) plus optional arguments with keywords.
Make sure that the sort procedure you defined is in fact the one that gets called, by defining it first before the point where you're actually using it, or just to be sure rename it to say, mysort and use that name consistently - because anyway it's not always a good idea to overwrite existing procedures.

Accessing a stored list in Racket

Is there a way to access a stored list in Racket without passing it new data? A list of past responses is stored using the following code in a program I'm working on.
(define (storage response lst)
(cons response lst))
This makes a list by taking a response to a question and a previous list. I don't want to change what's in the list just simply see what's inside it. If other code is needed I will be happy to show what I have.
The standard way to access a list's elements in Racket is by using the first and rest procedures (or equivalently: car and cdr) to recursively iterate over a list. For example, let's say that you want to find out if the list contains the "404" response:
(define responses '("302" "403" "404" "505"))
(define (find-response lst response)
; the list is empty, the element was not found
(cond ((empty? lst)
#f)
; `first` accesses the first element in the list
((equal? (first lst) response)
#t)
(else
; `rest` advances to the next elements in the list
(find-response (rest lst) response))))
(find-response responses "404")
=> #t
(find-response responses "201")
=> #f
Of course, once you learn how this works, you can move and use existing procedures, for example member as suggested in the other answers. Please take a look at the list procedures available for use, you'll see that the most frequent operations are already implemented and at your disposal.
As currently constructed, you created a function called storage that takes response and a list and returns a new list with response as the head and lst as the tail.
If you want to get the head or tail of (storage a l) then you just call (car (storage a l)) or (cdr (storage a l))- it's just a list.
Yes, there is a way to access a stored list without passing it as new data. See page 25, Section 6.3.2 in the Scheme R5RS Specification for a full list of 'list accessing' functions. Racket probably has more; other Scheme versions may have additional ones.
Here is an example. To test if a 'response' has been seen already:
(member response lst)
to count the number of responses:
(length lst)

Dereference variable inside list

Is it possible to dereference a variable contained inside a list, to obtain its value? For example:
(define one 1)
(define two 2)
(define list '(one two))
(display (list-ref list 0))
Here list-ref references to one, and display shows one in letters. Could instead one dereference to the value contained by the homonym variable?
Eval can definitely solve this problem... but like most situations where eval is applicable, it's a large and dangerous hammer.
Matthew Flatt's blog post on this topic has become the go-to explanation:
http://blog.racket-lang.org/2011/10/on-eval-in-dynamic-languages-generally.html
Here's how you might do it without eval in Racket. Stripping away the cruft, "dict-ref" can find a named
element (or elements) in an "association list".
#lang racket
(define data
'((one 1)
(two 2)))
(define wanted-list '(two one))
;; evaluates to '((2) (1)):
(for/list ([wanted wanted-list])
(dict-ref data wanted))
That's happening because the quoted list contains two symbols, one and two. Try the following:
(display (eval (list-ref list 0)))
To resolve that symbol.

Resources