[racket] iterative lazy space-safe or not?
Hi,
> I don't have any concrete measurements. The implementation is as fast
> as I could make it, but it's still pretty slow -- for example, when
> you compare it with a naive implementation.
Naive implementation --- do you mean non-composable promises (i.e. delays)
or graph reductions (or STG or whatever)?
> Most of the hit is due to
> doing the right thing wrt exceptions: when there's an exception when a
> promise is forced, the exception is stored as the "value" and will be
> re-raised when forced again. For example, if you do this:
>
> (define a (delay (/ (random 2))))
> (force a)
>
> and get an error, you should get an error for future forces too.
Yes. I believe this is right thing to do and I think (or want to think)
that other languages, OCaml, Scala, F# or whatever, do the same.
(I'll have to check myself...)
But the penalty is incurred only when an exception is raised during
the initialization; am I correct? I.e, if the initialization is
successful, no cost is incurred due to this.
You may well know it, but in Java, classes are initialized lazily and
initialization failure is memorized so that later attempts to initialize
the same class fail again. But, IIRC, they degenerate uncaught exceptions
during initialization to an initialization-failure exception.
I have not thought about the impact of this carefully, though.
> > It's simple and works, which is nice; isn't it?
>
> It's very fragile, and when it breaks it's very hard to find out how
> to fix it.
Will you explain how/why it is fragile?
It looks conceptually simple.
You rewrite
let rec x = y, y = M in E[x]
into
let rec x = M, y = x in E[x]
The two graphs must be extensionally equivalent.
Keiko