質問

それを記述するためのシステムを提案する高次の手続きそれにより私な手順を返します。のようなもの:

(define (Proc a b c)
  (lambda (x) ( #| method body here in terms of a b c and x |# )))

新しい手順は、私だけのように:

(define ProcA (Proc a1 b1 c1)) ; Would create ProcA that has 1 argument

類似の課題れている間に行うことができる言語に対応していない高次の手順を定義する Proc この代わりに4 3引数は、この手続きを定義する ProcA, のように:

(define (Proc a b c x) ( #| method body -- does not return any procedure |# )
(define (ProcA x) (Proc a1 b1 c1 x))

ではなぜあなファズ約高の順序を示す。私何かが足りない?

役に立ちましたか?

解決

で観察する機能を返す機能と同様に機能する二つの論争することができます。これを"Currying".別の言い方をすれば、機能AからBの論理的な意味、とはB、または:

A => B.

していただきました場合、AとBとC、A、BとC:

(A => (B => C)) <==> ((A, B) => C)

が高次機能を明らかにすることは必ずしも機能を返します。 高次機能に関する機能と引数.これは大きな違いは、HOFsは非常に強力なプログラミングツールです。

例えば、このウ機能:

map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : (map f xs)

この高次の機能は機能 f 適用すべての要素をリストアップしました。言語なHOFsというかこの機能は、ループまたは類似したものの、言語とHOFsできる電話 f 各要素のリストの中の単純な話のようになります:

map f myList

確かに、制を構築します言語または近似的に高次の機能が 言語る上でき識を自制を構築しま.スキームの確認.

他のヒント

ここで引数を要約しようとはしませんが、関数型プログラミングの問題、John Hughesは、高階関数は「結合」するためのより効果的な方法を提供するので有用であると主張します。プログラムの一部であるため、コードの再利用が容易になります。これらの例は、あまり使われなくなった非常に古い言語で書かれていますが、それでも簡単に理解でき、説得力があります。ジョンの論文を読むことは、あなたの質問に対する詳細な答えを得る良い方法です。

これは、実現可能性よりも考え方に関するものです。関数をファーストクラスの市民として扱い、関数を操作して他の関数を作成するなどの観点から考えることができます。

明らかに、これを他の言語で実行またはシミュレートできますが、構文メカニズムでない場合は、追加またはハックとして扱われます。

OK。ただし、2番目の例では、コンパイル時に a1 b1 、および c1の事前に定義されたリストを使用してそのプロシージャを作成しています。 。最初の例では、実行時に ProcA を呼び出すときに作成します。必要に応じてさまざまなものを作成できるため、さらに興味深いことができます。

変換関数または配列を介したソートアルゴリズムを考えてください。ここで、関数のユーザーが関数を引数として渡すことで関数の動作を指定できるように、本当に柔軟にしたいです。

さて、次の手続きプロトタイプを使用してソートアルゴリズムを作成します。

sort(Array a, void (*fn)(a::element_type, a::element_type));

その関数のユーザーは、適切なfnを渡すことで、降順または昇順を指定することができます。

適切にシミュレートするには、内部クラスが必要です。最初の場合、Procはa、b、cで閉じられます。 2番目の場合、ProcAの呼び出し元は、a1、b1、およびc1が他のプロシージャに渡される方法を制御できません。xのみを制御できます。したがって、a1、b1、c1を制御する方法は、より高いスコープ(モジュールレベルなど)のuse変数を使用することであり、これにより関数が純粋ではなくなります。その場合、呼び出し間で同じ引数を指定した場合、ProcAが同じ結果を返すことを保証できません。 Procの場合と同じように、同じ引数で呼び出した場合、同じ結果が発生することを常に確認できます。

たとえば、選択ボックスを使用する場合、javascriptで高階関数を使用します。オプションが選択されたときに呼び出される関数を渡すことができます。私にとっての唯一の違いは、コードを簡素化し、冗長性を減らすことでした。

コードをクリーンアップする方法、ローカライズ可能な冗長性があり、相違点がある場合は、高次関数をサポートする他の言語でも同じことがわかります。関数で行われます。

C#がこれをサポートするようになったので、今ではもっと主流になっていることがわかりました。 :)

関数が関数を受け入れたり返したりする場合、高階関数と呼ばれます(HOF)。 C、C ++、またはJavaから来た経験の浅いプログラマーにとって、高階関数は魔法のように聞こえますが、非常に単純です。 2 + 3の結果を返す単純な関数を想像してください。

(define (foo) (+ 2 3)) ;; (foo) => 5

それは退屈な関数で、常に2から3を追加します。3だけでなく、ユーザーが指定した数に2を追加するように一般化するとどうなりますか?

(define (foo n) (+ 2 n)) ;; (foo 10) => 12

言語が高階関数をサポートしていない場合、関数と値(数値、ブール値、リストなど)は2つの異なるものであると考えるように強制されます。ただし、関数型プログラミング(FP)では、両者の区別があいまいです。関数と値の唯一の違いは、 2 または #t または '(abc):引数として渡すか、関数から戻るか、変数に格納するか、リストに入れることができます。たとえば、小さな関数をさらに一般化して、 n に2を追加するだけでなく、2を n で乗算したり、2つの数値を受け入れる他の関数を適用したりできます。 :

(define (foo f n) (f 2 n))
;; (foo + 10) => 12
;; (foo * 10) => 20
;; (foo expt 10) => 1024

関数が数値または文字列の処理と同じ方法で処理できることに気付いた場合、匿名関数(FPの専門用語では&#8220; lambdas&#8221;と呼ばれます)は完全に理にかなっています。匿名関数は実際にはより基本的であり、&#8220;通常&#8221;通常の名前付き関数よりも、名前付き関数は、変数に数を入れてそれを複数回使用するように、変数に入れられる単なる匿名関数です。

(+ 2 2) ;; is no different from:
(let ((a 2)) (+ a a))
(lambda (x y) (* x y)) ;; is no different from:
(define (foo x y) (* x y)) ;; which is an abbreviation for:
(define foo (lambda (x y) (* x y))).

したがって、HOFを使用すると、関数を汎用化し、柔軟性を高めることができます。関数を見て、その背後にあるロジックを見ると、何かがデータに作用する場合、他の何かもおそらくできるかもしれないことを理解できます。 2つの数字を加算すると、おそらく乗算したり、減算したり、指数を累乗したりできます。毎回毎回新しい関数を作成する代わりに、関数でなければならない追加のパラメーターを受け入れることができます。

FPでは、たとえばリストを操作するときなど、常にHOFを使用します。 3つの関数はFPの基本です: map filter および foldl map は、引数が1つの関数を受け入れ、この関数をリストのすべての要素に適用し、要素が変更された新しいリストを返します。 filter は、引数が1つの述語(ブール値を返す関数)を受け入れ、述語をリストのすべての要素に適用し、述語を満たさない要素が削除された新しいリストを返します。

(map (lambda (n) (+ n 1)) '(1 2 3 4 5) ;; '(2 3 4 5 6)
(define (foo n) (+ n 1))
(map foo '(1 2 3 4 5)) ;; '(2 3 4 5 6)
(filter (lambda (n) (> n 3)) '(1 2 3 4 5)) ;; '(4 5)
(define (bar n) (> n 3))
(filter bar '(1 2 3 4 5)) ;; '(4 5)

想像してみてください。1アリティ関数のリストがあります。もう一度、関数で何でもできますし、それをデータ構造に保存することもできます。そして、それらのすべてを同じ数、および結果のリストを取得します。

(let ((xs (list (lambda (x) (+ x 1))
                (lambda (x) (* x 2))
                (lambda (x) (- x)))))
  (map (lambda (f) (f 10)) xs)) ;; => (11 20 -10)

結論:プログラミング言語が関数型プログラミングの概念を適切にサポートしている場合、高階関数により柔軟性と汎用性が可能になり、コードがより強力になります

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top