1
1
defmodule Array do
2
+ @ behaviour Access
2
3
@ moduledoc """
3
4
A wrapper module for Erlang's array.
4
5
"""
@@ -15,7 +16,7 @@ defmodule Array do
15
16
Creates a new, extendible array with initial size zero.
16
17
The default value is the atom nil, not undefined.
17
18
"""
18
- @ spec new ( ) :: t
19
+ @ spec new ( ) :: t
19
20
def new ( ) do
20
21
% Array { content: :array . new ( { :default , nil } ) }
21
22
end
@@ -85,7 +86,7 @@ defmodule Array do
85
86
86
87
@ doc """
87
88
Folds the elements of the array using the given function and initial accumulator value.
88
- The elements are visited in order from the lowest index to the highest.
89
+ The elements are visited in order from the lowest index to the highest.
89
90
90
91
If `fun` is not a function, the call raises `ArgumentError`.
91
92
"""
@@ -96,7 +97,7 @@ defmodule Array do
96
97
@ doc """
97
98
Folds the elements of the array right-to-left using the given function and initial accumulator value.
98
99
The elements are visited in order from the highest index to the lowest.
99
-
100
+
100
101
If `fun` is not a function, the call raises `ArgumentError`.
101
102
"""
102
103
@ spec foldr ( t , acc , ( index , element , acc -> acc ) ) :: acc when acc: var
@@ -184,7 +185,7 @@ defmodule Array do
184
185
@ doc """
185
186
Maps the given function onto each element of the array.
186
187
The elements are visited in order from the lowest index to the highest.
187
-
188
+
188
189
If `fun` is not a function, the call raises `ArgumentError`.
189
190
"""
190
191
@ spec map ( t , ( index , element -> any ) ) :: t
@@ -260,7 +261,7 @@ defmodule Array do
260
261
Folds the elements of the array right-to-left using the given function and initial accumulator value,
261
262
skipping default-valued entries.
262
263
The elements are visited in order from the highest index to the lowest.
263
-
264
+
264
265
If `fun` is not a function, the call raises `ArgumentError`.
265
266
"""
266
267
@ spec sparse_foldr ( t , acc , ( index , element , acc -> acc ) ) :: acc when acc: var
@@ -270,7 +271,7 @@ defmodule Array do
270
271
@ doc """
271
272
Maps the given function onto each element of the array, skipping default-valued entries.
272
273
The elements are visited in order from the lowest index to the highest.
273
-
274
+
274
275
If `fun` is not a function, the call raises `ArgumentError`.
275
276
"""
276
277
@ spec sparse_map ( t , ( element -> any ) ) :: t
@@ -320,16 +321,45 @@ defmodule Array do
320
321
@ spec to_orddict ( t ) :: [ { index , element } ]
321
322
def to_orddict ( % Array { content: c } ) ,
322
323
do: :array . to_orddict ( c )
323
- end
324
324
325
- defimpl Access , for: Array do
326
- def get ( arr , idx ) do
327
- Array . get ( arr , idx )
325
+ @ doc """
326
+ Access behavior `fetch/2` callback.
327
+ """
328
+ def fetch ( arr , idx ) do
329
+ { :ok , get ( arr , idx ) }
328
330
end
329
331
332
+ @ doc """
333
+ Access behavior `get/3` callback
334
+ """
335
+ def get ( arr , idx , value ) do
336
+ if size ( arr ) < idx do
337
+ get ( arr , idx )
338
+ else
339
+ value
340
+ end
341
+ end
342
+
343
+ @ doc """
344
+ Access behavior `get_and_update/3` callback
345
+ """
330
346
def get_and_update ( arr , idx , fun ) do
331
- { get , update } = fun . ( Array . get ( arr , idx ) )
332
- { get , Array . set ( arr , idx , update ) }
347
+ value = get ( arr , idx )
348
+ case fun . ( value ) do
349
+ { get , update } -> { get , set ( arr , idx , update ) }
350
+ :pop -> { value , set ( arr , idx , nil ) }
351
+ end
352
+ end
353
+
354
+ @ doc """
355
+ Access behavior `pop/2` callback
356
+ """
357
+ def pop ( arr , idx ) do
358
+ if size ( arr ) < idx do
359
+ { get ( arr , idx ) , set ( arr , idx , nil ) }
360
+ else
361
+ { nil , arr }
362
+ end
333
363
end
334
364
end
335
365
0 commit comments