※この文章はまだ書きかけです
始めに
前回の投稿のコメントでの指摘を修正したソースをアップしています。
また、reduceを実装して感じたことをまとめます。
前回の投稿の修正
Javaで関数型言語のreduceを実装してみるのコメント欄で指摘のあった点を踏まえてソースを修正しました
reduceを実装して感じたこと
以下の観点でまとめます
- 末尾再帰と最適化
- ループは直感的ではない(個人的な主観です。異論はたくさんあると思います。)
- データ構造を探索する人と探索した人が見つけたものを使う人
修正後のソース
FuncTest.java
package test;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
public class FuncTest {
static public class Reduce<T>{
//外部に公開するメソッドはpublicにする
public T reduce(Collection<T> b,Function<T> f){
return reduce(b,f,null);
}
//内部のロジックを処理するの使うメソッドはprivateにする
private T reduce(Collection<T> b,Function<T> f,T t){
Deque<T> a = new ArrayDeque<T>(b);
//スタックの要素がなくなったら再帰処理を終了する
if(a.size()==0){
return t;
}
//要素数1のリストが渡された場合
else if (a.size() == 1){
//最初に再帰処理が呼び出された時の処理
if(t==null)return a.pop();
//2回目以降に再帰処理が呼び出された場合は引数で渡された合計値と
//スタックの先頭を引数で渡されたインナークラスのメソッドに渡す
else{ t = f.aply(t,a.pop());}
}
//要素数2以上のリストが渡された場合
else
{
//最初に再帰処理が呼び出された時の処理
//Stackの一番目と2番目を引数にセットする
if(t==null){t = f.aply(a.pop(),a.pop());}
//2回目以降に再帰処理が呼び出された場合は引数で渡された合計値と
//スタックの先頭を引数で渡されたインナークラスのメソッドに渡す
else{t = f.aply(t,a.pop());}
}
return reduce(a,f,t) ;
}
}
//Functionクラスのインターフェイス abstractクラスで定義する
static abstract class Function<T>{
public abstract T aply(T a, T b);
}
//配列の中身をすべて足し算します
static class FunctionAsAdd<T> extends Function<Integer>{
public Integer aply(Integer a, Integer b){return a+b;};
}
//配列の中身をすべて掛け算します
static class FunctionAsMultiplication<T> extends Function<Integer>{
public Integer aply(Integer a, Integer b){return a*b;};
}
//配列の文字列をすべて連結します
static class FunctionAsString<T> extends Function<String>{
public String aply(String a, String b){return a+b;};
}
public static void main(String args[]){
List<Integer>list = new ArrayList<Integer>();
Collections.addAll(list, 1,2,3,4,5,6,7,8,9,10);
System.out.println(
(new Reduce<Integer>())
.reduce(list,new FunctionAsAdd<Integer>())
);//55が表示される
System.out.println((new Reduce<Integer>())
.reduce(list,new FunctionAsMultiplication<Integer>())
);//3628800が表示される
List<String> stringList= Arrays.asList(
new String[]{"1","2","3","4","5","6","7","8","9"});
System.out.println((new Reduce<String>())
.reduce(stringList,new FunctionAsString<String>())
);//123456789が表示される
}
}