Skip to content

ArrayView::join and FixedArray::join #2125

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 28, 2025
26 changes: 2 additions & 24 deletions array/array.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -301,28 +301,6 @@ pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for Array[X] with arbi
}

///|
pub fn join(self : Array[String], separator : String) -> String {
match self {
[] => ""
[hd, .. tl] => {
let mut size_hint = hd.length()
for s in tl {
size_hint += s.length() + separator.length()
}
size_hint = size_hint << 1
let buf = StringBuilder::new(size_hint~)
buf.write_string(hd)
if separator == "" {
for s in tl {
buf.write_string(s)
}
} else {
for s in tl {
buf.write_string(separator)
buf.write_string(s)
}
}
buf.to_string()
}
}
pub fn join(self : Array[String], separator : @string.View) -> String {
self[:].join(separator)
}
7 changes: 5 additions & 2 deletions array/array.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package "moonbitlang/core/array"
import(
"moonbitlang/core/bytes"
"moonbitlang/core/quickcheck"
"moonbitlang/core/string"
)

// Values
fn[T] copy(Array[T]) -> Array[T]

fn[A, B] filter_map(Array[A], (A) -> B?) -> Array[B]

fn join(Array[String], String) -> String
fn join(Array[String], @string.StringView) -> String

fn[A] last(Array[A]) -> A?

Expand Down Expand Up @@ -47,6 +48,7 @@ impl FixedArray {
from_array[T](Array[T]) -> Self[T]
from_iter[T](Iter[T]) -> Self[T]
is_sorted[T : Compare](Self[T]) -> Bool
join(Self[String], @string.StringView) -> String
last[A](Self[A]) -> A?
makei[T](Int, (Int) -> T) -> Self[T]
map[T, U](Self[T], (T) -> U) -> Self[U]
Expand Down Expand Up @@ -75,7 +77,7 @@ impl Array {
copy[T](Self[T]) -> Self[T]
filter_map[A, B](Self[A], (A) -> B?) -> Self[B]
from_iter[T](Iter[T]) -> Self[T]
join(Self[String], String) -> String
join(Self[String], @string.StringView) -> String
last[A](Self[A]) -> A?
makei[T](Int, (Int) -> T) -> Self[T]
push_iter[T](Self[T], Iter[T]) -> Unit
Expand All @@ -100,6 +102,7 @@ impl ArrayView {
foldi[A, B](Self[A], init~ : B, (Int, B, A) -> B) -> B
iter[A](Self[A]) -> Iter[A]
iter2[A](Self[A]) -> Iter2[Int, A]
join(Self[String], @string.StringView) -> String
map[T, U](Self[T], (T) -> U) -> Array[U]
map_inplace[T](Self[T], (T) -> T) -> Unit
mapi[T, U](Self[T], (Int, T) -> U) -> Array[U]
Expand Down
12 changes: 12 additions & 0 deletions array/array_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,18 @@ test "Array[String]::join" {
inspect([].join(" "))
}

///|
test "Array[View]::join" {
let arr = ["a", "b", "c"][:]
inspect(arr.join(","), content="a,b,c")
inspect(["a", "b", "c"][:].join(","), content="a,b,c")
inspect(["a", "b", "c"][:].join(""), content="abc")
inspect(["a", "b", "c"][:].join(" "), content="a b c")
inspect(["123", "456"][:].join(""), content="123456")
inspect(["aaa", "bbb", "ccc"][:].join(" "), content="aaa bbb ccc")
inspect([][:].join(" "))
}

///|
test "Array::pop_back" {
let arr = [1]
Expand Down
51 changes: 51 additions & 0 deletions array/fixedarray.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,47 @@ pub fn[A] FixedArray::last(self : FixedArray[A]) -> A? {
}
}

///|
/// Concatenate strings within an array into a single complete string.
///
/// Example:
///
/// ```moonbit
/// test "FixedArray::join" {
/// let fixed_array:FixedArray[String]=["1","2","3"]
/// inspect!(fixed_array.join(","), content="1,2,3")
/// }
/// ```
pub fn FixedArray::join(
self : FixedArray[String],
separator : @string.View
) -> String {
let len = self.length()
if len == 0 {
return ""
}
let first = self[0]
let mut size_hint = first.length()
for i = 1; i < len; i = i + 1 {
size_hint += separator.length() + self[i].length()
}
let string = StringBuilder::new(size_hint~)
if separator.is_empty() {
for i = 0; i < len; i = i + 1 {
string.write_string(self[i])
}
} else {
string.write_string(self[0])
let separator = separator.to_string()
for i = 1; i < len; i = i + 1 {
// TODO: use `write_view` when available
string.write_string(separator)
string.write_string(self[i])
}
}
string.to_string()
}

///|
test "FixedArray::last/empty" {
let empty : FixedArray[Int] = []
Expand Down Expand Up @@ -1197,6 +1238,16 @@ test "FixedArray::last/multiple_elements" {
inspect(FixedArray::last(multiple_elements_array), content="Some(5)")
}

///|
test "FixedArray::join" {
let fixed_array : FixedArray[String] = ["1", "2", "3"]
inspect(fixed_array.join(","), content="1,2,3")
inspect(fixed_array.join(""), content="123")
inspect(fixed_array.join(" "), content="1 2 3")
let fixed_array_empty : FixedArray[String] = []
inspect(fixed_array_empty.join(","), content="")
}

///|
pub impl[X : @quickcheck.Arbitrary] @quickcheck.Arbitrary for FixedArray[X] with arbitrary(
size,
Expand Down
40 changes: 40 additions & 0 deletions array/view.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,46 @@ pub fn[T] View::to_array(self : View[T]) -> Array[T] {
}
}

///|
/// Concatenate strings within an array into a single complete string.
///
/// Example:
///
/// ```moonbit
/// test "View::join" {
/// let a:Array[String]=["1","2","3"]
/// let array_view = a[:]
/// inspect!(array_view.join(","), content="1,2,3")
/// }
/// ```
pub fn View::join(self : ArrayView[String], separator : @string.View) -> String {
match self {
[] => ""
[hd, .. tl] => {
let mut size_hint = hd.length()
for s in tl {
size_hint += s.length() + separator.length()
}
size_hint = size_hint << 1
let buf = StringBuilder::new(size_hint~)
buf.write_string(hd)
if separator is "" {
for s in tl {
buf.write_string(s)
}
} else {
let separator = separator.to_string()
for s in tl {
// TODO : use `write_view` when available
buf.write_string(separator)
buf.write_string(s)
}
}
buf.to_string()
}
}
}

///|
pub impl[X : Show] Show for View[X] with output(self, logger) {
logger.write_iter(self.iter())
Expand Down
Loading