On 13-05-03 07:11 PM, Gábor Lehel wrote:

> So this has been bouncing around in the back of my head, and now actual
> thoughts have congealed there. Essentially, while I think this is a very
> good defense of why Rust doesn't have purity, it's not so convincing to
> me as a defense of why it *shouldn't* have purity. (I don't know if it
> was intended as one.)

It was intended as an explanation for why we (those who've been
trying-and-failing on this front for a while -- in my case over 7 years
now) are tired of trying and don't much want to retry. I feel there are
more fruitful areas for us to spend our effort. That's subjective of course.

> C++ is C++. It has multiple concepts for *everything*. That something is
> complicated in C++ does not imply that it has to be complicated by
> necessity.

Agreed. I'm arguing that I don't want to follow them down certain paths
into complexity.

Note: they expanded the definition of constexpr in a
non-backwards-compatible way in c++1y.

> This is unfair even to C++. Const methods are the same thing in spirit
> as `&self` versus `&mut self` in Rust. Macros in C++ and Rust alike are
> for code generation, not computation.

I don't think that's a meaningful distinction when we're looking at the
applications "at compile-time". If it were, it'd be a lot easier to
characterize "templates". But it's not. They may run during compliation;
but they're all turing complete.

> That leaves templates and constexpr. Which, indeed, have a lot of
> overlap, and neither is a subset of the other (constexpr functions can't
> do types while templates can't do values of user-defined types other
> than enums, for example). Both are restricted to dealing in things that
> can be evaluated at compile time.* The part of templates that deals in
> types corresponds to Rust's generics, while the part of templates that
> can calculate the Fibonacci numbers is a historical semi-accident.
> Constexpr expressions (and hence functions) correspond to Rust's
> attempts to define a constant expression subgrammar.

I agree with this characterization. And I think the constant expression
subgrammar + macros probably fits most of the compile-time needs
constexpr-as-a-function-qualifier is pointed at. Maybe not all, but I
suspect close-to enough to be tolerable.

> Again this is something I can definitely accept. Can't argue with
> history. It would be nice to know for context how the old system worked.
> Is there documentation anywhere?

Hm. Probably not a singular form of it aside from "our older manuals".
We've had _a_ manual (of varying degrees of accuracy) online since we
published in 2010. It's mutated over time. I'm not sure which point is
the best to inspect the effect system. Somewhere around spring 2011 maybe?

> FWIW it's not really a most conservative intersection. They can't run it
> on the GPU or evaluate it at compile time either (except by compiling
> and running it, which is what Template Haskell does). What they have is
> a semantic notion of purity. If there's no way for pure code to observe
> different values (or the user running the program different effects) at
> different times, it's good to go, even if it requires unsafePerformIO to
> implement. Using unsafePerformIO to cheat is frowned upon* and more
> importantly isn't reliable.

Ok. Then its purpose is the same as our 'io' qualifier was, more or
less. We first set it to the default, then non-default (changing the
required annotation to 'pure') and then removed it entirely. Because
almost everything wound up non-pure, in an honest program, or the
intersection-points were too much of a hassle (pure wanting to call impure).

> Right. As above I can readily accept that it's not an easy question,
> that the right design hasn't been found, and that earlier attempts
> haven't worked out. What I find harder to accept is that there doesn't
> exist *any* definition of purity that would be superior to nothing at
> all. C++ derives some benefit from constexpr. Haskell derives a lot of
> benefit from enforced purity. Surely there is some point in the design
> space which would be beneficial for Rust. Perhaps a wiki page collecting
> the various options with their applications, benefits, and drawbacks
> would be helpful?

C++ derives the ability to evaluate at compile time from constexpr.
Haskell you're saying doesn't do that (aside from template haskell,
which you're excluding) so I assume the benefits you're pointing to are
in the more-narrow space of "increasing your confidence that code has no
IO effects", yes? And you mean this in a way that _isn't_ already
covered by rust's system for control over mutability.

That's certainly beneficial. I'm just pointing out that the previous
times we tried to encode that benefit, we found that the costs of it
outweighed the benefits. Users soured on the mechanism, felt it was too
wordy, awkward and confusing.

> (FWIW I sorta suspect the presence of mutability and lifetimes in the
> type system might make an observable notion of purity a la Haskell
> easier to define, but I haven't thought it all the way through.)

It's possible. I won't stop you from making a wiki page wherein you try
to find a very lightweight way of re-encoding the concept of IO effects.
I know we've all been sympathetic to the desire. It's just .. it seems
that the cognitive budget available for it is very slim, and there are
significant interaction costs from most approaches we've tried.

-Graydon


_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to