Nonstrict Language in Terms of Strict Language

Jack Waugh — 2001-07-27 14:25:20

Is Joy a suitable notation in which to demonstrate how to
implement/simulate/model a functional programming language where the
functions are nonstrict in their arguments, on top of a functional
programming language where the functions are strict in thier
arguments (which Joy is, under either interpretation)?

This is a trick question, because actually I don't know how to
demonstrate this in applicative notation (although I know it can be
done).

Manfred von Thun — 2001-07-30 04:53:34

On Fri, 27 Jul 2001, Jack Waugh wrote:

> Is Joy a suitable notation in which to demonstrate how to
> implement/simulate/model a functional programming language where the
> functions are nonstrict in their arguments, on top of a functional
> programming language where the functions are strict in thier
> arguments (which Joy is, under either interpretation)?

Just adding to the discussion that already occurred..

The terms "strict" and "non-strict" come from Church's lambda calculus
(For some introduction and references, see "Rationale" and "Joy compared"
on the main Joy page). They only make sense in languages in which there
is (explicit or hidden, implicit) lambda abstraction. The Schoenfinkel-
Curry combinatory calculus does not have lambda abstraction, but it does
have function application. So that is an applicative language in which
the question of (non-)strictness does not arise.

In the early days of Joy I often wondered whether Joy is strict or not,
and there were times when I changed my mind quite frequently. Only later
did I realise that again the question does not arise because Joy does
not have lambda abstraction - it uses quotation to do a similar job.

Nevertheless, one could still formulate a similar question about Joy.
In a way the answer is obvious: an operator like "square" takes
its parameter off the stack, where it has to be a number and not an
unevaluated expressions which would evaluate to a number. So, that
would seem to make Joy strict in some extended sense of the word.
2 3 + square ==> 25

On the other hand, it is possible to pass an unevaluated expression,
a quotation as a parameter, and evaluate that as needed - typically
by the i combinator (or perhaps nullary or unary).
[ 2 3 + ] i square ==> 25

We may define two versions of "square":
DEFINE
eval-square == dup *;
unev-square == i dup *.

So, even if the sense of "(non-)strict" can be extended to a concate-
native language, it is not the language but the operators that are
one or the other.

One of the advantages of "lazy" evaluation or "call-by-need" as
implemented in Miranda and Haskell is that the combinatory calculus
on which they are based internally provides the advantages of
the security of non-strictness and the efficiency of strictness.
Incidentally, in a concatenative language you get that same efficiency
by defining, say, square with dup. In a language with abstraction
you would say something like
DEFINE
square(x) == x * x
with the formal parameter x twice on the right hand side. This leads to
the potentially wasteful double evaluation of the parameter in a
call such as
square(2 + 3)
which would expand as call by name to
(2 + 3) * (2 + 3)
Now the (2 + 3) has to be evaluated twice. But with call by value
the (2 + 3) is evaluated once, before the substutition, and the
expansion is
5 * 5
In Joy you get that advandage by using dup.

There are some standard examples of how non-strict functions
can be defined even in the case where the evaluation of the
argument is undefined, but I cannot remember the examples at
the moment. Anybody got a better memory?

- Manfred