-
Notifications
You must be signed in to change notification settings - Fork 19
/
form.tex
199 lines (161 loc) · 5.5 KB
/
form.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
\chapter{Forms}
The reader will have noted that the Scheme example
programs provided thus far are also s-expressions.
This is true of all Scheme programs: Programs are data.
Thus, the character datum \q{#\c} is a program, or a
{\em form}. We will use the more general term {\em
form} instead of {\em program}, so that we can deal
with program fragments too.
Scheme evaluates the form \q{#\c} to the value \q{#\c},
because \q{#\c} is self-evaluating. Not all
s-expressions are self-evaluating. For instance the
symbol s-expression
\q{xyz} evaluates to the value held by the {\em variable}
\q{xyz}. The list s-expression
\q{(string->number "16")}
evaluates to the number 16.
Not all s-expressions are valid programs. If you typed
the dotted-pair s-expression \q{(1 . 2)} at the Scheme
listener, you will get an error.
Scheme evaluates a list form by examining the first
element, or {\em head}, of the form. If the head
evaluates to a procedure, the rest of the form is
evaluated to get the procedure’s arguments, and the
procedure is {\em applied} to the arguments.
If the head of the form is a {\em special form}, the
evaluation proceeds in a manner idiosyncratic to that
form. Some special forms we have already seen
are \q{begin}, \q{define}, and \q{set!}. \q{begin} causes its
subforms to be evaluated in order, the result of the
entire form being the result of the last subform.
\q{define} introduces and initializes a variable.
\q{set!} changes the binding of a variable.
\index{procedure}
\index{lambda@\q{lambda}}
\section{Procedures}
We have seen quite a few primitive Scheme procedures,
e.g., \q{cons}, \q{string->list}, and the like. Users
can create their own procedures using the special form
\q{lambda}. For example, the following defines a
procedure that adds \q{2} to its argument:
\q{
(lambda (x) (+ x 2))
}
The first subform, \q{(x)}, is the list of parameters.
The remaining subform(s) constitute the procedure’s
body. This procedure can be called on an argument,
just like a primitive procedure:
\q{
((lambda (x) (+ x 2)) 5)
|evalsto 7
}
If we wanted to call this same procedure many times, we
could create a replica using \q{lambda} each time, but
we can do better. We can use a variable to hold the
procedure value:
\q{
(define add2
(lambda (x) (+ x 2)))
}
We can then use the variable \q{add2} each time we need
a procedure for adding \q{2} to its argument:
\q{
(add2 4) |evalsto 6
(add2 9) |evalsto 11
}
\index{procedure!parameters}
\subsection{Procedure parameters}
The parameters of a \q{lambda}-procedure are specified
by its first subform (the form immediately following
the head, the symbol \q{lambda}). \q{add2}
is a single-argument — or {\em unary} — procedure, and so its parameter
list is the singleton list \q{(x)}. The symbol \q{x}
acts as a variable holding the procedure’s argument.
Each occurrence of \q{x} in the procedure’s body refers
to the procedure’s argument. The variable \q{x} is
said to be {\em local} to the procedure’s body.
We can use 2-element lists for 2-argument procedures,
and in general, {\em n}-element lists for {\em
n}-argument procedures. The following is a 2-argument
procedure that calculates the area of a rectangle. Its
two arguments are the length and breadth of the
rectangle.
\q{
(define area
(lambda (length breadth)
(* length breadth)))
}
Notice that \q{area} multiplies its arguments, and so
does the primitive procedure \q{*}. We could have
simply said:
\q{
(define area *)
}
\subsection{Variable number of arguments}
Some procedures can be called at different times with
different numbers of arguments. To do this, the
\q{lambda} parameter list is replaced by a single
symbol. This symbol acts as a variable that is bound
to the list of the arguments that the procedure is
called on.
In general, the \q{lambda} parameter list can be a list
of the form \q{(x ...)}, a symbol, or a dotted pair of
the form \q{(x ... . z)}. In the dotted-pair case, all
the variables before the dot are bound to the
corresponding arguments in the procedure call, with the
single variable after the dot picking up all the
remaining arguments as one list.
%examples
\index{apply@\q{apply}}
\section{\q{apply}}
The Scheme procedure \q{apply} lets us call a procedure
on a {\em list} of its arguments.
\q{
(define x '(1 2 3))
(apply + x)
|evalsto 6
}
In general, \q{apply} takes a procedure, followed by a
variable number of other arguments, the last of which
must be a list. It constructs the argument list by
prefixing the last argument with all the other
(intervening) arguments. It then returns the result of
calling the procedure
on this argument list. E.g.,
\q{
(apply + 1 2 3 x)
|evalsto 12
}
\index{begin@\q{begin}}
\section{Sequencing}
We used the \q{begin} special form to bunch together a
group of subforms that need to be evaluated in
sequence. Many Scheme forms have {\em implicit}
\q{begin}s. For example, let’s define a 3-argument procedure that
displays its three arguments, with spaces between
them. A possible definition is:
\q{
(define display3
(lambda (arg1 arg2 arg3)
(begin
(display arg1)
(display " ")
(display arg2)
(display " ")
(display arg3)
(newline))))
}
\index{begin@\q{begin}!implicit}
In Scheme, \q{lambda}-bodies are implicit \q{begin}s.
Thus, the \q{begin} in \q{display3}’s body isn’t needed, although it doesn’t
hurt. \q{display3}, more simply, is:
\q{
(define display3
(lambda (arg1 arg2 arg3)
(display arg1)
(display " ")
(display arg2)
(display " ")
(display arg3)
(newline)))
}