We have identified in
Lisp
JavaScript
some of the elements that must appear in any powerful programming language:
-
Numbers and arithmetic operations are primitive data and
procedures.
functions.
-
Nesting of combinations provides a means of combining operations.
-
Constant declarations that associate names with values provide a
limited means of abstraction.
Now we will learn about
procedure definitions,
function declarations,
a much more powerful abstraction technique by which a compound
operation can be given a name and then referred to as a unit.
We begin by examining how to express the idea of
squaring.
We might say,
To square something, multiply it by itself.
To square something, take it times itself.
This is expressed in our language as
Original |
JavaScript |
(define (square x) (* x x))
|
function square(x) {
return x * x;
}
|
We can understand this in the following way:
Original |
JavaScript |
(define (square x) (* x x))
;; ^ ^ ^ ^ ^ ^
;; To square something, multiply it by itself.
|
function square( x ) { return x * x; }
// ^ ^ ^ ^ ^ ^ ^
// To square something, take it times itself.
|
We have here a
compound procedure,
compound function,
which has been given the name square. The
procedure
function
represents the operation of multiplying something by itself. The thing to
be multiplied is given a local name, x,
which plays the same role that a pronoun plays in natural language.
Evaluating the
definition
declaration
creates this compound
procedure
function
and associates it with the name
square.
The general form of a procedure definition
The simplest form of a function declaration
is
Original |
JavaScript |
(define ($\langle \textit{name} \rangle$ $\langle\textit{formal parameters}\rangle$) $\langle \textit{body} \rangle$)
|
function $name$($parameters$) { return $expression$; }
|
The
$\langle \textit{name}\rangle$
$name$
is a symbol to be associated with the
procedure
function
definition in the environment.
The
$\langle \textit{formal parameters}\rangle$
$parameters$
are the names used within the body of the
procedure
function
to refer to the
corresponding arguments of the
procedure.
function.
Original |
|
JavaScript |
The
$\langle \textit{body} \rangle$
is an expression
that will yield the value of
the procedure
application when the formal parameters are replaced by
the actual arguments to which the
procedure
is applied.
The $\langle \textit{name} \rangle$
and the
$\langle \textit{formal parameters} \rangle$
are grouped within
parentheses, just as they would be in an actual call to the procedure
being defined.
|
|
The $parameters$
are grouped within
parentheses and separated by commas, as they will be in an application
of the function being declared.
In the simplest form, the
body of a function declaration is a single
return statement,
which consists of the keyword
return
followed by the return expression
that will yield the value of the function application, when the
formal
parameters are replaced by the actual arguments to which the function
is applied. Like constant declarations and expression statements,
return statements
end with a semicolon.
|
Original |
|
JavaScript |
Having defined square,
we can now use it:
|
|
Having declared square,
we can now use it in a
function application expression, which we turn into a statement
using a semicolon:
|
Original |
JavaScript |
(square 21)
441
|
square(21);
441
|
Original |
|
JavaScript |
|
|
Function applications are—after operator
combinations—the second kind of combination of
expressions into larger expressions that we encounter.
The general form of a function application is
$function$-$expression$($argument$-$expressions$)
where the
$function$-$expression$
of the application specifies
the function to be applied to the comma-separated
$argument$-$expressions$.
To evaluate a function application, the interpreter follows
a procedure
quite similar to the procedure for operator combinations described in
section [1.1.3].
- To evaluate a function application, do the following:
-
Evaluate the subexpressions of the application, namely
the function expression and the argument expressions.
-
Apply the function that is the value of the function expression
to the values of the argument expressions.
|
Original |
JavaScript |
(square (+ 2 5))
49
|
square(2 + 5);
49
|
Original |
|
JavaScript |
|
|
Here, the argument expression is itself a compound expression,
the operator combination 2 + 5.
|
Original |
JavaScript |
(square (square 3))
81
|
square(square(3));
81
|
Original |
|
JavaScript |
|
|
Of course function application expressions can also serve as argument expressions.
|
We can also use square
as a building block in defining other
procedures.
functions.
For example, $x^2 +y^2$ can be expressed as
Original |
JavaScript |
(+ (square x) (square y))
|
square(x) + square(y)
|
We can easily
define
declare
a
procedure
sum-of-squares
function
sum_of_squares
that, given any two numbers as arguments, produces the
sum of their squares:
Original |
JavaScript |
(define (sum-of-squares x y)
(+ (square x) (square y)))
(sum-of-squares 3 4)
|
function sum_of_squares(x, y) {
return square(x) + square(y);
}
|
Original |
JavaScript |
(sum-of-squares 3 4)
25
|
sum_of_squares(3, 4);
25
|
Now we can use
sum-of-squares
sum_of_squares
as a building block in constructing further
procedures:
functions:
Original |
JavaScript |
(define (f a)
(sum-of-squares (+ a 1) (* a 2)))
|
function f(a) {
return sum_of_squares(a + 1, a * 2);
}
|
Original |
JavaScript |
(f 5)
136
|
f(5);
136
|
Original |
|
JavaScript |
Compound
procedures are used in exactly the same way as primitive
procedures. Indeed, one could not tell by looking at the definition
of sum-of-squares given above whether
square was built into
the interpreter, like + and
*,
or defined as a compound procedure.
|
|
In addition to compound functions, any JavaScript environment provides
primitive functions that are built into the interpreter or loaded
from libraries.
Besides the primitive functions provided by the operators,
the JavaScript environment used in this book includes
additional primitive functions
such as the function
math_log,
which computes the natural logarithm of its argument.
These additional primitive functions are used in exactly the same way as
compound functions; evaluating the application
math_log(1) results in the number 0.
Indeed, one could not tell by looking at the definition of
sum_of_squares given above whether
square was built into the
interpreter, loaded from a library, or defined as a compound function.
|
1.1.4
Compound Procedures
Functions