Hi Al,
On a practical level, I would be sad if vector-ref, for example, was
"impure", and thus compiling a vector-ref invalidated all previously-
checked globals for the current scope. Likewise, I would prefer to
declare a procedure using vector-ref as pure, to let csc know that it
does not modify globals (or the filesystem etc).
The function vector-ref doesn't stop being pure (i.e. referentially
transparent) depending how you use it. The function is always
referentially transparent -- the expression (vector-ref some-global-vec)
isn't. Quoting from "Functional Programming in C++" by Ivan Čukić:
> We’re going to define purity more precisely now, through a concept
called referential transparency. Referential transparency is a
characteristic of expressions, not just functions. Let’s say an
expression is anything that specifies a computation and returns a
result. We’ll say an expression is referentially transparent if the
program wouldn’t behave any differently if we replaced the entire
expression with just its return value. If an expression is referentially
transparent, it has no observable side effects, and therefore all
functions used in that expression are pure.
(p.104)
I think that part just decides whether the procedure is "pure", for
whatever purity means. That doesn't say anything about what compiling a
call to such a "pure" procedure means (can memoize the value or not,
need to re-check globals or closures afterwards or not etc).
Both the Declarations and Types manual pages say clearly it means
"referencial transparency."
And RE local state, that you asked in another email: my understanding is
that that refers to variables belonging to the closure, that survive
across calls. E.g.:
(define foo
(let ((x 0))
(lambda (y)
(set! x (add1 x))
(* 2 y))))
siiky