220121-関数プログラミングについて


エンクロージャ


Closerとは?


外部関数の内部関数またはこれらの原理を指す用語にアクセスできます.これはscopeによれば,内部関数の範囲内では外部関数の範囲内の変数にアクセスできるが,逆の概念は実現できないことを意味する.簡単に言えば、次のコードを使用できます.

使用例


コードソース
public class Store {
	private String storeNo = "9000";
    
    public void lambdaClosure() {
    	Function<String, Integer> lambdaFunction = i -> {
        	System.out.println(this.storeNo);
            	return null;
		};
    }
}
StoreクラスのメソッドlambdaClosureは内部にlambdaFunctionを有し、この場合、外部メソッドはlambdaClosureであり、内部メソッドはlambdaFunctionである.このRamda関数の内部でthis.storeNoという名前のインスタンスフィールドを参照します.この場合、自身の範囲外の変数を使用するため、Closerと呼ばれます.

じゅんかんすう


純関数とは?


従来のプログラミング関数は数学関数とは異なる性質を有する.数学の関数がinputが計算値を表す形式である場合、プログラミングの関数はその値を計算する一連のプロセスを含む.したがって,プログラミング関数はプロセスまたは方法と呼ばれる.メソッドに含まれる計算では、外部値が頻繁に参照されます.この場合、外部値によっては入力値が同じであっても異なる結果を出力することができる.
このため,マルチスレッド環境などリソースに同時にアクセスできる環境では,同一入力値の期待値を判断することは困難である.これは、テストとデバッグを困難にする要因です.従って,関数式プログラミングでは純粋な関数の概念が求められる.
本当に数学で使われている関数のように、同じパラメータを入力すると、外部環境にかかわらず、常に一定値の関数が出力されます.このように記述された関数には副作用はありません.関数の外部環境を参照するか、依存性がないためです.したがって,簡単にテストを行い,簡潔なコードを生成することができる.

使用例

// not pure
class example {
	
    public String name = "seyeong"; // 이 필드의 값에 따라 아래 함수의 출력 결과가 바뀐다. 
    
    public String introduce(int age) {
    	return String.format("안녕하세요. 저는 %d살인 %s입니다.", age, name);
    }
    
// pure
    public String introduce(String name, int age) {
        BiFunction<Integer, String, String> introduce =
                (a, n) -> String.format("안녕하세요. 저는 %d살인 %s입니다.", a, n);
        return introduce.apply(age, name);
    }
}        

高次関数


高次関数とは?


関数を引数または戻り関数として受け入れる関数を高次関数と呼ぶ.高校時代に学んだ合成関数のように,関数間ではパラメータや戻り関数として関数を受け入れることができる.

使用例


JAvaのstreamやListなどで提供されるforEach、map、reduce、filterなど.実際に用いることにより,データ処理過程を表す関数を簡潔に表すことができる.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
	// for문을 활용한 출력
        for (int i = 0; i < numbers.size(); i++) {
        	System.out.println(numbers.get(i));
        }
        
        // forEach 함수를 이용함
     	numbers.forEach(System.out::println);
foreachなどの高次関数を用いて,内部反復を用いてfor文を非表示にし抽象的に操作することができる.ではforeachの内部操作はどのように実現されているのでしょうか.
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
JAva ListのforEach関数コード.関数型インタフェースConsumer(戻り値のない関数を表すパラメータ値).
(System.out::println)はvalue->システムです.out.println(value)と同じです.
つまり、これは人の子で伝わる動作に相当します.
次にforEachはリストオブジェクトから簡単に要素を取り出して動作を適用する.
foreachは、パラメータとして関数を受け入れ、データ内の各要素に関数を適用する高次関数です.

プログラミングモデルとは?


これは開発者がコードを書くときの観点だと思います.
どのような機能を実現するためにコードを作成しても、次の観点があります.
  • 実際に実装された機能の流れに従ってコードを記述する->プロセス向けプログラミング
  • 機能を実現するために必要なデータの動作と属性はどれらがありますか?それを組み合わせてオブジェクトとして管理し、情報交換と機能の実現->オブジェクト向けプログラミング
  • すべての機能は独立して1つのユニットブロックに分割され、必要な機能に従って組み合わされる->関数プログラミング
  • このパターンの必要性は,コードを記述する原則を提案することに由来すると考えられる.それぞれのコードスタイルがあるが,複数の開発者が集まって開発する環境では,統一的な原則が必要である.
    そして、この原則は私たちが直面している問題を効果的に解決できる原則が望ましい.現在広く用いられているオブジェクト向けや関数型などの例は,開発過程で遭遇する様々な問題を解決するための方法論である.
    頻繁に変更される要求を効果的に反映するために、繰り返し使用されるコードを減らして再利用するために、コードの可読性を高めるために、など様々な目的で発展してきた形なので、パターンを守れば、コードの統一性を高め、効率的なコードを作成できると思います.

    オブジェクトと関数



    オブジェクト向け

  • オブジェクトのプロパティと機能をカプセル化します.
  • は、関連オブジェクト間の継承により、不要なコード重複を低減し、コードの多様性を確保し、変化に柔軟に対応することができる.
  • メソッドは、
  • オブジェクトの状態を共有することができる.
  • かんすうしきプログラミング

  • 機能は、純関数単位で管理されます.
  • は、簡潔な関数間の接続によって複雑な機能を作成し、内部論理は小関数として抽象化される.
  • 関数内部パラメータとして得られた値は不変性を有し、このパラメータを保存または保存せず、関数外部を参照しない.
  • 共通点

  • の両方のパターンには、重複コードを低減し、効率的に再利用できる単位が存在する.