Skip to content

Commit af06abd

Browse files
firejoxRX14
authored andcommitted
Make StaticArray and Slice .map to return their own type (#5124)
1 parent a4f8161 commit af06abd

File tree

5 files changed

+95
-4
lines changed

5 files changed

+95
-4
lines changed

spec/std/slice_spec.cr

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,32 @@ describe "Slice" do
362362
3.times { a.includes?(b.shift).should be_true }
363363
end
364364

365+
it "does map" do
366+
a = Slice[1, 2, 3]
367+
b = a.map { |x| x * 2 }
368+
b.should eq(Slice[2, 4, 6])
369+
end
370+
371+
it "does map!" do
372+
a = Slice[1, 2, 3]
373+
b = a.map! { |x| x * 2 }
374+
a.should eq(Slice[2, 4, 6])
375+
a.to_unsafe.should eq(b.to_unsafe)
376+
end
377+
378+
it "does map_with_index" do
379+
a = Slice[1, 1, 2, 2]
380+
b = a.map_with_index { |e, i| e + i }
381+
b.should eq(Slice[1, 2, 4, 5])
382+
end
383+
384+
it "does map_with_index!" do
385+
a = Slice[1, 1, 2, 2]
386+
b = a.map_with_index! { |e, i| e + i }
387+
a.should eq(Slice[1, 2, 4, 5])
388+
a.to_unsafe.should eq(b.to_unsafe)
389+
end
390+
365391
it "creates empty slice" do
366392
slice = Slice(Int32).empty
367393
slice.empty?.should be_true

spec/std/static_array_spec.cr

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,27 @@ describe "StaticArray" do
109109
a[2].should eq(1)
110110
end
111111

112-
it "maps!" do
112+
it "does map" do
113+
a = StaticArray[0, 1, 2]
114+
b = a.map { |e| e * 2 }
115+
b.should eq(StaticArray[0, 2, 4])
116+
end
117+
118+
it "does map!" do
113119
a = StaticArray(Int32, 3).new { |i| i + 1 }
114120
a.map! { |i| i + 1 }
115121
a[0].should eq(2)
116122
a[1].should eq(3)
117123
a[2].should eq(4)
118124
end
119125

120-
it "map_with_index!" do
126+
it "does map_with_index" do
127+
a = StaticArray[1, 1, 2, 2]
128+
b = a.map_with_index { |e, i| e + i }
129+
b.should eq(StaticArray[1, 2, 4, 5])
130+
end
131+
132+
it "does map_with_index!" do
121133
a = StaticArray(Int32, 3).new { |i| i + 1 }
122134
a.map_with_index! { |e, i| i * 2 }
123135
a[0].should eq(0)

src/kernel.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ STDOUT = (IO::FileDescriptor.new(1, blocking: LibC.isatty(1) == 0)).tap { |f| f.
55
STDERR = (IO::FileDescriptor.new(2, blocking: LibC.isatty(2) == 0)).tap { |f| f.flush_on_newline = true }
66

77
PROGRAM_NAME = String.new(ARGV_UNSAFE.value)
8-
ARGV = (ARGV_UNSAFE + 1).to_slice(ARGC_UNSAFE - 1).map { |c_str| String.new(c_str) }
8+
ARGV = Array.new(ARGC_UNSAFE - 1) { |i| String.new(ARGV_UNSAFE[1 + i]) }
99
ARGF = IO::ARGF.new(ARGV, STDIN)
1010

1111
# Repeatedly executes the block, passing an incremental `Int32`

src/slice.cr

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,44 @@ struct Slice(T)
236236
@pointer.shuffle!(size, random)
237237
end
238238

239+
# Invokes the given block for each element of `self`, replacing the element
240+
# with the value returned by the block. Returns `self`.
241+
#
242+
# ```
243+
# slice = Slice[1, 2, 3]
244+
# slice.map! { |x| x * x }
245+
# slice # => Slice[1, 4, 9]
246+
# ```
247+
def map!
248+
check_writable
249+
250+
@pointer.map!(size) { |e| yield e }
251+
self
252+
end
253+
254+
# Returns a new slice where elements are mapped by the given block.
255+
#
256+
# ```
257+
# slice = Slice[1, 2.5, "a"]
258+
# slice.map &.to_s # => Slice["1", "2.5", "a"]
259+
# ```
260+
def map(*, read_only = false, &block : T -> U) forall U
261+
Slice.new(size, read_only: read_only) { |i| yield @pointer[i] }
262+
end
263+
264+
# Like `map!`, but the block gets passed both the element and its index.
265+
def map_with_index!(&block : (T, Int32) -> T)
266+
check_writable
267+
268+
@pointer.map_with_index!(size) { |e, i| yield e, i }
269+
self
270+
end
271+
272+
# Like `map`, but the block gets passed both the element and its index.
273+
def map_with_index(*, read_only = false, &block : (T, Int32) -> U) forall U
274+
Slice.new(size, read_only: read_only) { |i| yield @pointer[i], i }
275+
end
276+
239277
def copy_from(source : Pointer(T), count)
240278
check_writable
241279

src/static_array.cr

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,27 @@ struct StaticArray(T, N)
165165
self
166166
end
167167

168-
# Like `map`, but the block gets passed both the element and its index.
168+
# Returns a new static array where elements are mapped by the given block.
169+
#
170+
# ```
171+
# array = StaticArray[1, 2.5, "a"]
172+
# tuple.map &.to_s # => StaticArray["1", "2.5", "a"]
173+
# ```
174+
def map(&block : T -> U) forall U
175+
StaticArray(U, N).new { |i| yield to_unsafe[i] }
176+
end
177+
178+
# Like `map!`, but the block gets passed both the element and its index.
169179
def map_with_index!(&block : (T, Int32) -> T)
170180
to_unsafe.map_with_index!(size) { |e, i| yield e, i }
171181
self
172182
end
173183

184+
# Like `map`, but the block gets passed both the element and its index.
185+
def map_with_index(&block : (T, Int32) -> U) forall U
186+
StaticArray(U, N).new { |i| yield to_unsafe[i], i }
187+
end
188+
174189
# Reverses the elements of this array in-place, then returns `self`.
175190
#
176191
# ```

0 commit comments

Comments
 (0)