fir-lang / fir

MIT License
26 stars 3 forks source link

Interchanging `Str` and `StrView`s #3

Closed osa1 closed 1 month ago

osa1 commented 4 months ago

A Str is a UTF-8 encoded immutable unicode string.

A StrView is a view into a Str. This type is always unboxed, and can be created as a result of a pattern match.

This distinction is useful and allows things like pattern matching on a string and binding the rest of the matched string in a local variable in an efficient way.

However it also means that we have two types for strings and for common operations like startsWith or string equality we need to convert between types manually. For example:

trait Eq[T]:
    fn __eq(self, other: T): Bool

impl Eq[Str]:
    fn __eq(self, other: Str): Bool = ...

impl Eq[StrView]:
    fn __eq(self, other: StrView): Bool = ...

With these definitions, if I have a Str and a StrView, I have to manually convert one to the other to compare. Similarly:

fn Str.startsWith(self, prefix: Str): Bool = ...

fn StrView.startsWith(self, prefix: StrView): Bool = ...

Since creating a StrView from a Str is cheap (the other way requires allocation and copying the contents), we could use it in arguments when possible:

-- Both methods take `StrView` argument now.
fn Str.startsWith(self, prefix: StrView): Bool = ...
fn StrView.startsWith(self, prefix: StrView): Bool = ...

But the Eq trait definitions doesn't allow this, as the other parameter has type T (i.e. same type as self).

Secondly, even if we could use StrView somehow, having to manually convert one to the other will be annoying.

Some ideas:

osa1 commented 1 month ago

I've merged these two types. Str is now a view into an Array[U8], with the invariant that the viewed part is a valid UTF-8 encoding.