0

I have been reading the first chapter of "The Little Schemer". The problem is, some examples work in DrRacket like (eq? "foo" "foo") and some don't like (car ("a" "b")) or (cdr ("a" "b")) because of

application: not a procedure;
 expected a procedure that can be applied to arguments
  given: "a"
  arguments...:

Can you point me why these example do not work?

Feisty Otter
  • 134
  • 1
  • 8
  • 2
    Are you sure those are the proper examples? `(car ("a" "b"))` is simply invalid Scheme; should it not be `(car '("a" "b")`? with the apostrophe. `("a" "b')` tries to treat it as a function call using `"a"` as a function, which, given that it is a string, is not a function. – Zorf Jan 25 '20 at 08:35
  • So whenever you need to pas a list as an agrument you prepend it with `'` apostrophe? – Feisty Otter Jan 25 '20 at 08:50
  • 2
    Yes. Note that none of the data is being evaluated so if you need a list with calculated elements you use `cons` or `list` instead. Your list is made with `(list "a" "b") which is the same as `(cons "a" (cons "b" '()))` and in these the strings get evaluated so you can replace them with a variables like `(list var "b")` while `'(var "b")` is with the symbol var. – Sylwester Jan 25 '20 at 10:11
  • 1
    Read note 1 on page 3. – molbdnilo Jan 26 '20 at 10:35

1 Answers1

3

These examples don't work because they're not legal Scheme. I'm not familiar with the book, but it may be the case that it has been typeset in a way which may make it slightly hard to transcribe examples from it without the mistake you've made. To see why they're not you need to think about how the system evaluates things. Here is a simple-minded and partial description of how that might work (real implementations do something much hairier than this, and this description is partial not least because it contains no explanation for how we get the bindings of things at all).

To evaluate something:

  • is it something special like a string or a number or something like that, in which case its value is just itself;
  • is it a symbol, in which case look up the binding for that symbol and that is the value;
  • is it a compound form like (foo ...)? If it is, then –
    • look at its first element: is it a special magic thing we know about? If it is then do an appropriate special thing (see below);
    • otherwise evaluate all of the elements of the compound form in any order you like – the value of the first element should be a function, and the value is the result of applying this function to the values of the remaining elements.

So we can use these rules to try to evaluate (car ("a" "b")).

  • the form is a compound form, so we need to take the compound form case;
  • car is not any kind of special thing, so we don't hit that case;
  • so, evaluating the elements of the form (I'll do it left to right for simplicity) –
    • car is a symbol, so look up its value which is a function;
    • ("a" "b") is a compound form, and its first element is not special –
      • evaluate its elements, both of which are literal strings whose value is themselves;
      • and now try to apply the value of first element to the values of all the others, and fail, because it is a string not a function.

OK, so this can't work. To make it work we need to go back and look at a case in the evaluation rules: when evaluating a compound form we sneak a look a the first element to decide if it is some special magic thing we know about and in that case we do something special. There are a small number of such special magic things: the only one that we care about here is quote. The special rule for this is:

  • if we see a compound form whose first element is quote, which will look like (quote ...), then –
    • it should have exactly two elements, so it should look like (quote <x>) for some <x>;
    • the value of the form is <x> with no further attempt to evaluate <x>.

So, for instance:

  • the value of (quote x) is the symbol x;
  • the value of (quote (1 2 3)) is the list (1 2 3);
  • the value of (quote "x") is the string "x" (you don't need quote in this case, since strings already evaluate to themselves by the very first rule above, but it does not hurt).

So to go back to the form we wanted to evaluate, what we actually need is (car (quote ("a" "b"))). When evaluating this:

  • the form is a compound form, so we need to take the compound form case;
  • car is not any kind of special thing, so we don't hit that case;
  • so, evaluating the elements of the form (I'll do it left to right for simplicity) –
    • car is a symbol, so look up its value which is a function;
    • (quote ("a" "b")) is a compound form –
      • its first element is special, since it is quote;
      • so use the rule for quote and the result is ("a" "b");
    • now apply the value of car to ("a" "b"), and the result is "a".

So then there is one more trick: (quote <x>) occurs a lot, so there is a special syntax for it, which is a single ': 'x reads identically to (quote x). This just makes source code less verbose. So this gives the final form of the working version of what you're trying to do:

(car '("a" "b"))

Finally, the reason Lisps need quote is an interesting thing to think about, but off-topic for this answer.

  • the book uses different fonts to indicate the need to quote those lists, but it does not include the quote by itself. and those fonts are not nearly dissimilar enough, are only slightly different. not too newbie-friendly, that. – Will Ness Jan 31 '20 at 06:40
  • @WillNess: Oh, that's horrid. I thought I had a copy somewhere but clearly I don't, because I'd have remembered that. –  Jan 31 '20 at 12:13
  • the need for `quote` is one of the main points against the Lisp/Scheme syntax in Wadler's "calculating is better than scheming", IIRC. the Little books could've used all caps for auto-quoted symbols, for instance. (that's what I would/[do](https://stackoverflow.com/questions/34888245/alan-kays-eval-apply-einstein-moment/34910496#34910496)). – Will Ness Jan 31 '20 at 16:04