Skip to content

Commit 830e22a

Browse files
committed
Merge branch 'scans' of https://github.com/pbzdyl/functionaljava into pbzdyl-scans
2 parents 520f412 + 9bbdf22 commit 830e22a

2 files changed

Lines changed: 155 additions & 0 deletions

File tree

core/src/main/java/fj/data/Array.java

100644100755
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,144 @@ public <B> B foldLeft(final F2<B, A, B> f, final B b) {
291291
return foldLeft(curry(f), b);
292292
}
293293

294+
/**
295+
* Performs a fold left accummulating and returns an array of the intermediate results.
296+
* This function runs in constant stack space.
297+
*
298+
* @param f The function to apply on each argument pair (initial value/previous result and next array element)
299+
* @param b The beginning value to start the application from.
300+
* @return The array containing all intermediate results of the left-fold reduction.
301+
*/
302+
@SuppressWarnings({"unchecked"})
303+
public <B> Array<B> scanLeft(final F<B, F<A, B>> f, final B b) {
304+
final Object[] bs = new Object[a.length];
305+
B x = b;
306+
307+
for (int i = 0; i < a.length; i++) {
308+
x = f.f(x).f((A) a[i]);
309+
bs[i] = x;
310+
}
311+
312+
return new Array<B>(bs);
313+
}
314+
315+
/**
316+
* Performs a left-fold accummulating and returns an array of the intermediate results.
317+
* This function runs in constant stack space.
318+
*
319+
* @param f The function to apply on each argument pair (initial value/previous result and next array element)
320+
* @param b The beginning value to start the application from.
321+
* @return The array containing all intermediate results of the left-fold reduction.
322+
*/
323+
public <B> Array<B> scanLeft(final F2<B, A, B> f, final B b) {
324+
return scanLeft(curry(f), b);
325+
}
326+
327+
/**
328+
* Performs a left-fold accummulating using first array element as a starting value
329+
* and returns an array of the intermediate results.
330+
* It will fail for empty arrays.
331+
* This function runs in constant stack space.
332+
*
333+
* @param f The function to apply on each argument pair (next array element and first array element/previous result)
334+
* @return The array containing all intermediate results of the left-fold reduction.
335+
*/
336+
@SuppressWarnings({"unchecked"})
337+
public Array<A> scanLeft1(final F<A, F<A, A>> f) {
338+
final Object[] bs = new Object[a.length];
339+
A x = get(0);
340+
bs[0] = x;
341+
342+
for (int i = 1; i < a.length; i++) {
343+
x = f.f(x).f((A) a[i]);
344+
bs[i] = x;
345+
}
346+
347+
return new Array<A>(bs);
348+
}
349+
350+
/**
351+
* Performs a left-fold accummulating using first array element as a starting value
352+
* and returns an array of the intermediate results.
353+
* It will fail for empty arrays.
354+
* This function runs in constant stack space.
355+
*
356+
* @param f The function to apply on each argument pair (next array element and first array element/previous result)
357+
* @return The array containing all intermediate results of the left-fold reduction.
358+
*/
359+
public Array<A> scanLeft1(final F2<A, A, A> f) {
360+
return scanLeft1(curry(f));
361+
}
362+
363+
/**
364+
* Performs a right-fold accummulating and returns an array of the intermediate results.
365+
* This function runs in constant stack space.
366+
*
367+
* @param f The function to apply on each argument pair (previous array element and initial value/previous result)
368+
* @param b The beginning value to start the application from.
369+
* @return The array containing all intermediate results of the right-fold reduction.
370+
*/
371+
@SuppressWarnings({"unchecked"})
372+
public <B> Array<B> scanRight(final F<A, F<B, B>>f, final B b) {
373+
final Object[] bs = new Object[a.length];
374+
B x = b;
375+
376+
for (int i = a.length - 1; i >= 0; i--) {
377+
x = f.f((A) a[i]).f(x);
378+
bs[i] = x;
379+
}
380+
381+
return new Array<B>(bs);
382+
}
383+
384+
/**
385+
* Performs a right-fold accummulating and returns an array of the intermediate results.
386+
* This function runs in constant stack space.
387+
*
388+
* @param f The function to apply on each argument pair (previous array element and initial value/previous result)
389+
* @param b The beginning value to start the application from.
390+
* @return The array containing all intermediate results of the right-fold reduction.
391+
*/
392+
public <B> Array<B> scanRight(final F2<A, B, B> f, final B b) {
393+
return scanRight(curry(f), b);
394+
}
395+
396+
/**
397+
* Performs a right-fold accummulating using last array element as a starting value
398+
* and returns an array of the intermediate results.
399+
* It will fail for empty arrays.
400+
* This function runs in constant stack space.
401+
*
402+
* @param f The function to apply on each argument pair (previous array element and last array element/previous result)
403+
* @return The array containing all intermediate results of the right-fold reduction.
404+
*/
405+
@SuppressWarnings({"unchecked"})
406+
public Array<A> scanRight1(final F<A, F<A, A>>f) {
407+
final Object[] bs = new Object[a.length];
408+
A x = get(length() - 1);
409+
bs[length() - 1] = x;
410+
411+
for (int i = a.length - 2; i >= 0; i--) {
412+
x = f.f((A) a[i]).f(x);
413+
bs[i] = x;
414+
}
415+
416+
return new Array<A>(bs);
417+
}
418+
419+
/**
420+
* Performs a right-fold accummulating using last array element as a starting value
421+
* and returns an array of the intermediate results.
422+
* It will fail for empty arrays.
423+
* This function runs in constant stack space.
424+
*
425+
* @param f The function to apply on each argument pair (previous array element and last array element/previous result)
426+
* @return The array containing all intermediate results of the right-fold reduction.
427+
*/
428+
public Array<A> scanRight1(final F2<A, A, A> f) {
429+
return scanRight1(curry(f));
430+
}
431+
294432
/**
295433
* Binds the given function across each element of this array with a final join.
296434
*

tests/src/test/scala/fj/data/CheckArray.scala

100644100755
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ object CheckArray extends Properties("Array") {
6262
a.foldLeft(((a: Array[String], b: String) => array[String](scala.Array(b): _*).append(a)), empty[String]),
6363
a.reverse.foldRight((a: String, b: Array[String]) => array[String](scala.Array(a): _*).append(b), empty[String])))
6464

65+
property("scans") = forAll((a: Array[Int], z: Int) => {
66+
val add = (x: Int, y: Int) => x + y
67+
val left = a.scanLeft(add, z)
68+
val right = a.reverse().scanRight(add, z).reverse()
69+
70+
arrayEqual(Equal.anyEqual[Int]).eq(left, right)
71+
})
72+
73+
property("scans1") = forAll((a: Array[Int]) =>
74+
(a.length() > 0) ==> {
75+
val add = (x: Int, y: Int) => x + y
76+
val left = a.scanLeft1(add)
77+
val right = a.reverse().scanRight1(add).reverse()
78+
79+
arrayEqual(Equal.anyEqual[Int]).eq(left, right)
80+
})
81+
6582
property("bindLeftIdentity") = forAll((a: Array[String], s: String) => {
6683
def f(s: String) = array[String](scala.Array(s.reverse): _*)
6784
arrayEqual(stringEqual).eq(

0 commit comments

Comments
 (0)