Quotation Strings - SICP Comparison Edition" />
Original | JavaScript | |||||||||
If we can form compound data using symbols, we can have lists such as (a b c d) (23 45 17) ((Norah 12) (Molly 9) (Anna 7) (Lauren 6) (Charlotte 4)) Lists containing symbols can look just like the expressions of our language: (* (+ 23 45) (+ x 9)) (define (fact n) (if (= n 1) 1 (* n (fact (- n 1)))))
In order to manipulate symbols we need a new element in our language:
the ability to quote a data object. Suppose we want to
construct the list (a b). We can't
accomplish this with (list a b), because
this expression constructs
a list of the values of a and
b rather than the symbols themselves.
This issue is well known in the context of
natural languages, where words and sentences may be regarded either as
semantic entities or as character strings (syntactic entities). The
common practice in natural languages is to use quotation marks to
indicate that a word or a sentence is to be treated literally as a
string of characters. For instance, the first letter of
We can follow this same practice to identify lists and symbols that are to be treated as data objects rather than as expressions to be evaluated. However, our format for quoting differs from that of natural languages in that we place a quotation mark (traditionally, the single quote symbol ') only at the beginning of the object to be quoted. We can get away with this in Scheme syntax because we rely on blanks and parentheses to delimit objects. Thus, the meaning of the single quote character is to quote the next object.[2] Now we can distinguish between symbols and their values: (define a 1) (define b 2) (list a b) (1 2) (list 'a 'b) (a b) (list 'a b) (a 2) Quotation also allows us to type in compound objects, using the conventional printed representation for lists:[3] (car '(a b c)) a (cdr '(a b c)) (b c) In keeping with this, we can obtain the empty list by evaluating '(), and thus dispense with the variable nil. One additional primitive used in manipulating symbols is eq?, which takes two symbols as arguments and tests whether they are the same.[4] Using eq?, we can implement a useful procedure called memq. This takes two arguments, a symbol and a list. If the symbol is not contained in the list (i.e., is not eq? to any item in the list), then memq returns false. Otherwise, it returns the sublist of the list beginning with the first occurrence of the symbol: (define (memq item x) (cond ((null? x) false) ((eq? item (car x)) x) (else (memq item (cdr x))))) For example, the value of (memq 'apple '(pear banana prune)) is false, whereas the value of (memq 'apple '(x (apple sauce) y apple pear)) is (apple pear). There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.
There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.
There is currently no solution available for this exercise. This textbook adaptation is a community effort. Do consider contributing by providing a solution for this exercise, using a Pull Request in Github.
|
So far, we have used strings in order to display messages, using the functions display and error (as for example in exercise 1.22). We can form compound data using strings and have lists such as list("a", "b", "c", "d") list(23, 45, 17) list(list("Jakob", 27), list("Lova", 9), list("Luisa", 24)) In order to distinguish strings from names, we surround them with double quotation marks. For example, the JavaScript expression z denotes the value of the name z, whereas the JavaScript expression "z" denotes a string that consists of a single character, namely the last letter in the English alphabet in lower case. Via quotation marks, we can distinguish between strings and names: const a = 1; const b = 2; list(a, b); [1, [2, null]] list("a", "b"); ["a", ["b", null]] list("a", b); ["a", [2, null]] In section 1.1.6, we introduced === and !== as primitive predicates on numbers. From now on, we shall allow two strings as operands of === and !==. The predicate === returns true if and only if the two strings are the same, and !== returns true if and only if the two strings are not the same.[6] Using ===, we can implement a useful function called member. This takes two arguments: a string and a list of strings or a number and a list of numbers. If the first argument is not contained in the list (i.e., is not === to any item in the list), then member returns null. Otherwise, it returns the sublist of the list beginning with the first occurrence of the string or number: function member(item, x) { return is_null(x) ? null : item === head(x) ? x : member(item, tail(x)); } For example, the value of member("apple", list("pear", "banana", "prune")) is null, whereas the value of member("apple", list("x", "y", "apple", "pear")) is list("apple", "pear").
|
threeis not the phrase
one plus two.Quotation is powerful because it gives us a way to build expressions that manipulate other expressions (as we will see when we write an interpreter in chapter 4). But allowing statements in a language that talk about other statements in that language makes it very difficult to maintain any coherent principle of what
equals can be substituted for equalsshould mean. For example, if we know that the evening star is the morning star, then from the statement
the evening star is Venuswe can deduce
the morning star is Venus.However, given that
John knows that the evening star is Venuswe cannot infer that
John knows that the morning star is Venus.
the sameif they consist of the same characters in the same order. Such a definition skirts a deep issue that we are not yet ready to address: the meaning of
samenessin a programming language. We will return to this in chapter 3 (section 3.1.3).