Skip to content

RFC: handling partial functions in Rust libraries #1945

@catamorphism

Description

@catamorphism

I don't have a specific proposal, but I do want to discuss principles for how to handle partial functions in the standard libraries. Examples of partial functions are option::get (undefined on none), vec::last (undefined on empty vectors), and map::get (undefined for keys not bound in the map).

One approach is to "totalize" these functions by lifting their results into the option type: for example, vec::last would return none if invoked on an empty vector and some(x) on a non-empty vector, for some x. (That was the behavior until today.)

Another approach is to use typestate to specify preconditions so that we write total functions on a smaller domain, rather than partial functions on a bigger domain.

Finally, perhaps the simplest approach is for library functions to fail with an uncaught exception when error conditions arise.

I prefer either the first or second approach over the third (ideally I would prefer the second, but clearly there has been some hesitance to use typestate in anger). My preference is informed by my experience with Haskell where the use of functions like fromJust or head in cases where the invariants don't really hold (and the compiler doesn't help by checking those invariants) is a major pain. If you know an invariant, you should be able to write it down and express it either through types or typestate (whether it's types or typestate is more of an implementation detail to me).

However, I just changed vec::last to fail on an empty vector, for consistency with some of the existing vec code. I'd like to arrive at some guiding principles here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions