Reputation: 569
(define hypot
(lambda (a b)
(sqrt (+ (* a a) (* b b)))))
I would like to know if "define" would be considered as an imperative language feature! As long as I know imperative feature is static scoping. I think it is an imperative feature since "define" create a global binding and static scoped looks at global binding for any variable definition where as in dynamic it looks at the current most active binding.
Please help me find the correct answer!! And I would like to know why or why not?
Upvotes: 2
Views: 669
Reputation: 30237
You've put your finger on a subtle and contentious issue. There have long been two informal camps on how define
should work, which I would label (very imperfectly, and very controversially!) as the static vs. dynamic camps.
The static camp sees define
as a non-side-effecting top-level declaration—it's a syntax that simply defines a name in a top-level scope, just like let
is a syntax that defines a name in a local scope. A bit more precisely, this camp tends to see the top-level environment as equivalent to a big letrec
with all the define
s as the bindings, and all "loose" top-level expressions as the body. This is, incidentally, similar to the way that simple compilers work—read the whole program from one or more files, figure out all of the top-level bindings and generate code with knowledge of the whole program's source text.
The dynamic camp, on the other hand, tends to conceive of the top-level environment as a mutable data structure to which bindings can be added at runtime, and define
is then an operation that modifies the top-level environment. This is, incidentally, similar to how simple interactive interpreters work—read definitions interactively from input, one at a time, and incorporate them into the environment as the user provides them.
To give one example, the SLIB library is one that I recall has been criticized for being much too firmly in the "dynamic" camp. If you read Section 1.1 on "features", you see this right from the beginning:
SLIB maintains a list of features supported by a Scheme session. The set of features provided by a session may change during that session.
The documentation for the require
form that you use in SLIB to "load" modules continues with this:
Procedure: require feature
- If
(provided? feature)
is true, then require just returns.- Otherwise, if feature is found in the catalog, then the corresponding files will be loaded and
(provided? feature)
will henceforth return#t
. That feature is thereafter provided.- Otherwise (feature not found in the catalog), an error is signaled.
If you read this carefully, you will be struck that it's framing the whole thing as modules being "loaded" at runtime—and not as compile-time linking, which is foreign to the design.
So a "session" is a set of bindings whose keys—not just their values—changes during the runtime of the program. Programs are able to mutate the session with provide
and require
. They are able to directly observe the mutation with provided?
. And it is implied that they can indirectly observe the set of identifiers bound in top-level environment change as a result of require
—a call to require
causes procedure invocations that would result in a runtime error before its invocation to no longer be so afterwards.
So we can't help but conclude that going by the philosophy of the people who designed this library, define
is imperative. But not every Scheme user or implementer shares this philosophy.
Upvotes: 1
Reputation: 1413
First off Scheme is lexically scoped. Define usually is not limited to top level bindings like it is in Racket. It can create bindings within other procedure bodies.
In some implementations define can manipulate state but only for top level definitions. Otherwise it acts like let and binds a variable to the local scope. To actually take advantage of the top-level rebinding programatically is difficult.
So define doesn't introduce an imperative style into scheme code. Compare define to set! and its relatives, which by modify the variable in whatever environment it is bound, thereby allowing imperative style in scheme code.
Upvotes: 0
Reputation: 31145
In a Scheme program (define var expr)
statement is both a declaration and an initialization. Declarations introduce a new name into the scope. Declarations and initialization are present in both imperative and declarative languages.
However if the same variable is defined twice, then define
behave as an assignment - which belongs to the imperative paradigm.
Upvotes: 4