moonbitlang / core

MoonBit's Core library
https://moonbitlang.com/
Apache License 2.0
584 stars 72 forks source link

[Feature request] a unified trait is needed for various `View`s #341

Open shamiao opened 5 months ago

shamiao commented 5 months ago

As I saw in the current core, a concrete VecView can be obtained by op_as_view(start_including, end_excluding) operator. Although not yet implemented, similar viewing logic may be applied to other linear containers like Array or List.

I suggest adding View[T] built-in trait as an abstraction of a minimum subset of methods for any View. A suggested definition is:

/// View[T] is a logical contiguous sequence of T with random access by index. (Not guaranteed to be contiguous in memory)
pub trait[T] View[T] {    // <- not supported by compiler yet
    length[T](Self) -> Int
    op_get[T](Self, Int) -> T
    as_iter[T](Self) -> Iter[T]
}

This allows Char, String and Bytes related methods work for various data sources, without bloating the numbers of methods at the same time.

// before
let a = Buffer::make(256);
a.write_string("DEV")
a.write_sub_string("ELOPEZZZ", 0, 5)
a.write_char('R')
println(a.to_string())  // -> DEVELOPER

// after - assuming exists: 
//   fn write[Char](self: Buffer, view: impl View[Char]) -> Unit
//   fn view(self: Char) -> impl View[Char]
//   fn view(self: String) -> impl View[Char]
//   fn subview(self: String, start: Int, end: Int) -> impl View[Char]
let a = Buffer::make(256);
a.write("DEV".view())
a.write("ELOPEZZZ".subview(0, 1))
a.write('R'.view())
println(a.to_string())  // -> DEVELOPER
// before
let moon = Bytes::of_string("MOON")
let mo = Bytes::[0x6d, 0x00, 0x6f, 0x00, 0x7a, 0x00]
moon.blit(0, mo, 0, 4)
moon.blit_from_string(4, "on", 0, 2)
println(moon.to_string()) // -> moon

// after - assuming exists:
//   fn blit(self: Bytes, source: impl View[Byte]) -> Unit
//   fn op_as_view(self: Bytes, start: Int, end: Int) -> impl View[Byte]
//   fn view_bytes(self: String) -> impl View[Byte]
let moon = Bytes::of_string("MOON")
let mo = Bytes::[0x6d, 0x00, 0x6f, 0x00, 0x7a, 0x00]
moon.blit(0, mo[0..4])
moon.blit(4, "on".view_bytes())
println(moon.to_string()) // -> moon

This feature cannot be completed by a simple PR, since it requires generic traits to be implemented by the compiler first.

This request is directly inspired by the std::slice of Rust language. Very rough, polishment & discussion required.

fantix commented 5 months ago

I did something similar to unify Bytes and BytesView: Loadable and Storable. They are used in a way like this:

pub fn copy(dst : Storable, src : Loadable, len : Int) -> Unit {
  for i = 0; i < len; i = i + 1 {
    dst[i] = src[i]
  }
}