[Accepted with Modifications] SE-0235: Add Result to the Standard Library


(John McCall) #41

There should be a toolchain up with Result fairly soon; it would be great if we could get some early testing of this potential incompatibility to see how much of a problem it really is.


(Svein Halvor Halvorsen) #42

Result is a success or a failure.


(Matthew Johnson) #43

I don’t think this is accurate. Result is a value that is often produced by a success or a failure. This distinction is subtle but important and is why I am disappointed by the change from Value / Error to Success / Failure. I think type names should focus on describing the value they represent, they should not focus on describing the process that produced the value. The mistake of Success and Failure is that it emphasizes the process rather than the value that is represented.


(Jordan Rose) #44

There's nothing specific about the standard library here, but yes, Result.Result doesn't work as a way to reference a type named "Result" in a module named "Result", because name lookup prioritizes types over modules right now. EDIT: I don't think this is good behavior but someone would have to find the time to sit down and fix it.

Another way to resolve the ambiguity is to use scoped imports, which are preferred over regular imports: import enum Result.Result.


(Matthew Johnson) #45

This is good to know, thanks for sharing!


(John McCall) #46

Currently, lookup prefers declarations from the current module over imported names. The generalization of that rule would be that declarations from module M are preferred over declarations from modules that M depends on. Since Swift is the unique root in the dependency tree, that would innoculate us against the specific problems of introducing a new top-level type name.


(Jordan Rose) #47

Unfortunately, every module implicitly imports Swift, so that rule doesn't work here!


(John McCall) #48

Why not? It would mean that a Result in a module you import would always hide the Result from the standard library, because you’re importing two different modules but they have a dependency so they have a shadowing relationship, which is what we want (from a source-compatibility perspective).

It’s good that everything depends on Swift in this case.


(Jordan Rose) #49

Hm. I was thinking that the correct rule is "look in every import to see what it thinks 'Result' means, recursively" (and that's roughly what's implemented once you've started looking in modules), but if the correct rule is "if this name is shadowed on any path, ignore it in favor of the shadowing decl", then we do get the desirable source compat behavior. It does make it harder to refer to Swift.Result, though, and I don't like that adding an import can change the meaning of existing type names that way (rather than just adding overloads or making things ambiguous).

We should probably split off discussing changes to module name lookup into a separate thread.


(John McCall) #50

It does make it harder to refer to Swift.Result, though, and I don't like that adding an import can change the meaning of existing type names that way (rather than just adding overloads or making things ambiguous).

I think these are just costs we have to accept.

We should probably split off discussing changes to module name lookup into a separate thread.

That's a reasonable request. But we might have to consider changes here soon if this is a seriously compatibility problem, which it's shaping up to be.


(Dave Abrahams) #51

That is true in the same sense that Int is a value that is often representing a number (e.g. but might have come from C and therefore represent a boolean value). If we had wanted a semantics-free type like Optional, we'd have gone for a type like Either<Left, Right>.

I think type names should focus on describing the value they represent, they should not focus on describing the process that produced the value. The mistake of Success and Failure is that it emphasizes the process rather than the value that is represented.

I argued for Success and Failure because the names Value and Error describe only the type constraints on the corresponding parameter, which is redundant with what's written in the declaration of Result and a waste of potential expressive power. Type parameter and associated type and variable names should describe the role that the named entity plays in context, so that they illuminate code at their use site. Success and Failure do that much better than Value and Error, IMO.


(Sean Heber) #52

Was result() considered as a name for get()? I think that might be a more descriptive name at the point of use.