2010-11-26 4 views
1

私はちょうどクールチェーニングがどのように、物事をより読みやすくするかについて考えていました。変数への機能の束を適用する際の言語の多くでは、あなたはこのような何か書きたい:極端に連鎖する言語?

i(h(g(f(x)))) 

をそして、あなたはouter-すると、左右または最も内側からそれを読まなければなりません最も。最初にf、次にgなどを適用します。しかし、それが鎖になっていれば、それはより多くのように見えるでしょう

x|f|g|h|i 

あなたは正常な人間のように読むことができます。だから、私の質問は、そういう言語がいくつかあるに違いありません。彼らは何ですか?これらのファンシーパンツの機能プログラミング言語は何ですか?このため


、私は通常、私は別の行にそれを分割し、それをより読みやすくすることができるように一時変数の全体の束を作成し終わる:

a = f(x) 
b = g(a) 
c = h(b) 
what_i_really_wanted_all_along = i(c) 

私の魔法の言語でのWHERE、変数が間に合わずに長すぎる場合でも、別の行に分割することができます。

x | f 
    | g 
    | h 
    | i 
+0

笑@DVK。そのタグを追加していただきありがとうございます:D – mpen

+1

「機能構成」と呼ばれています。質問のタイトルを修正してください。 –

+0

@ S.Lott:必要があると感じたら修正できます。私はそれが何と呼ばれたのか分からなかった。それを "間違った"ままにしておけば、他の人が実際に何が呼び出されたかを知ることができます。 – mpen

答えて

3

これは関数型プログラミングに排他的ではありません関数の構成の概念全体が関数型プログラミングの領域に正当に存在するため、関数型言語で最もよく実装されています。オブジェクト指向曲げて任意の言語は、クラスのインスタンスを返すメソッドのために、連鎖している一つのことについては

、:

obj.method1().method2().method3(); // JavaScript 
MyClass->new()->f()->g()->i(); # Perl 

代わりに、この最も有名な、まだ少なくとも「プログラミング言語」の例連鎖パターンは完全に非OOで機能しないものになるでしょう...あなたはそれを推測しました、Unixのパイプ。 〜のように、ls | cut -c1-4 | sort -n。シェルプログラミングは言語と見なされるので、完全に有効な例です。

+0

はい、連鎖は*可能です*ただし、そのようにクラスを構築する場合のみです。あなたがクラスを制御できない場合、それを別のクラスのメソッドに渡したい場合、またはメソッドが 'this'を返さない場合はどうなりますか? – mpen

+0

@Ralph - 非OOインスタンスを返す例の2番目の部分を参照してください – DVK

+0

シェルは私が心に留めていたものですが、それはとても素晴らしい "プログラミング言語"ではありません。それに全面的なプログラムを書いている人は誰も知らないのですか? – mpen

5

はい、F#にパイプラインオペレータ|>(転送パイプオペレータとも呼ばれ、逆パイプ<|)があります。 x |> f |> g |> h |> i

チェック実生活の使用状況の良いアイデアを与えるこのblog post

あなたは次のように書きます。

+0

クレイジー...前向きと後ろ向きパイプは実際には便利ですか、それとも混乱につながりますか?あなたはどちらの方法を区別する必要がありますか? – mpen

+0

ほとんどの場合、私はフォワードパイプを使用します。それほど多くの後方のパイプはありません。 – Stringer

+0

そのブログ記事は、私が説明したいと思っていた配管の特典を正確に説明しています:) – mpen

2
+3

彼らがそこに与える例は、 'desort =(reverse。sort)'です。これは実際には* sort * firstを実行するので、まだそれを後方に読む必要があります。それは私には意味がありませんか? – mpen

+3

@Ralph:「それは私には意味がありませんか?」そのようなハスケルの人々は好きです。おそらく、それを好きで、あなたのバージョンを後方に呼び出すHaskellプログラマーの本当の多くがあります。判断を予約すると良いかもしれません。 –

+0

@ S.Lott:彼自身にそれぞれ。私は彼らにそれを好きな理由があると確信しています。私はちょうど*私の意見を述べています。それにかかわらず、この質問は「前方合成」または「左から右へのパイピング」またはあなたが何を持っているかについてです。 – mpen

2

あなたは何を記述している本質的流暢インターフェース・パターンです。

ウィキペディアは言語の数から良い例があります。

http://en.wikipedia.org/wiki/Fluent_interface

とMartin Fowler氏は、ここで彼の書き込みをアップしています

http://www.martinfowler.com/bliki/FluentInterface.html

DVKが指摘するように - 任意のオブジェクト指向言語をメソッドが属するクラスのインスタンスを返すことができるところで、この機能を提供することができます。

+0

また、クラスがそのように設計されている場合のみ、* can *できます。私はこれが標準である言語を探していたが、特別なケースではなかった。 – mpen

+0

ああ、申し訳ありません。 –

+0

PS:Fluent Interfaceはこのための正しい言葉のように聞こえます:)ありがとう。 (私のコメントがマイナスになることを意味するものではありませんでした) – mpen

3

さて、あなたは、JavaScriptとその親族でこれを行うことができます:あなたが見ることができるように

function compose() 
{ 
    var funcs = Array.prototype.slice.call(arguments); 
    return function(x) 
    { 
     var i = 0, len = funcs.length; 
     while(i < len) 
     { 
      x = funcs[i].call(null, x); 
      ++i; 
     } 
     return x; 
    } 
} 

function doubleIt(x) { print('Doubling...'); return x * 2; } 

function addTwo(x) { print('Adding 2...'); return x + 2; } 

function tripleIt(x) { print('Tripling...'); return x * 3; } 

var theAnswer = compose(doubleIt, addTwo, tripleIt)(6); 
print('The answer is: ' + theAnswer); 
// Prints: 
// Doubling... 
// Adding 2... 
// Tripling... 
// The answer is: 42 

は、関数は、左から右へとどちらのオブジェクトも機能は、特別な実装を必要とするお読みください。秘密はすべてcomposeです。

+0

+1は、クラス自体に焼き付ける必要がないソリューションを提案するためのものです。私はそれを使用しているかどうかはわかりませんが、面白いです:) – mpen

1

通常、数学をやっていないのであればMathematicaを使うことはできませんが、確かにPostfix表記をサポートするのに十分柔軟です。実際には、独自の表記法を定義することもできますが、簡単にするためにPostfixを使用しましょう。

あなたは入ることがあります。

Postfix[Sin[x]] 

をPostfixの表記に変換

x // Sin 

を取得するには。取得するには

MapAll[Postfix, Cos[Sin[x]]] 

:あなたはより深い表現を持っている場合、またはPostfixのを見ることができる

(Postfix[x]//Sin)//Cos 

を[x]は最初、Mathematicaのxのよう後で評価される式です。

逆に、あなたが入力してもよい:

x // Sin // Cos 

はもちろん

Cos[Sin[x]] 

で取得するか、あなたはPostfix形式でのPostfixを使用し、非常に頻繁に使用されるイディオムを使用することができます。

Cos[x] // Postfix 

取得する

x // Cos 

HTH!

BTW: 答えは私の魔法の言語はどこですか?、これを参照してください。

(x//Sin 
    // Cos 
    // Exp 
    // Myfunct) 

Myfunct[E^Cos[Sin[x]]] 

PSを与える:読者:)に運動したよう...どのようにn個varsの取る機能のためにこれを行うには?

static class Extensions 
{ 
    static T f<T>(this T x) { return x; } 
    static T g<T>(this T x) { return x; } 
    ... 
} 

LINQのは非常に広範囲にこれを使用しています。

x.f() 
.g() 
.h() 
.i(); 

方法は、このように宣言されている場合:少し簡潔場合

2

C#の拡張メソッドは、あなたの魔法の言語に非常に近い何かを成し遂げます。

+0

はい...Linqがこのようにしていることに気がついたので、実際にはこれが出てきましたが、Pythonではリスト内包表記などが逆になっています。 – mpen

1

先に述べたように、以下のように、Haskellは、関数合成をサポートしてい

(i . h . g . f) x、に相当する:i(h(g(f(x))))

これは数学関数組成物のための操作の標準順序です。しかし、これを後ろ向きにしている人もいます。これは、標準ライブラリControl.Categoryで使用される表記法である

infixr 1 >>>, <<< 
(<<<) = (.) -- regular function composition 
(>>>) = flip (.) -- flipped function composition 

(f >>> g >>> h >>> i) x 
    -- or -- 
(i <<< h <<< g <<< f) x 

:アプローチが優れている上での討論にあまり得ることなく、私はあなたが簡単に反転し、組成演算子を定義することができることを指摘したいと思います。 (実際の型署名は一般化され、関数以外の他のものでも機能しますが)。あなたがしたい構文に近い

infixr 0 $ 
infixl 0 # 
f $ x = f x -- regular function application 
(%) = flip ($) -- flipped function application 

i $ h $ g $ f $ x 
    -- or -- 
x % f % g % h % i 

:あなたはまだ終わりであること、パラメータに悩まさしている場合は、関数適用演算子のバリアントを使用することができます。私の知る限り、%はHaskellの組み込み演算子ではありませんが、$は組み込み演算子ではありません。私は中置のビットを見てきました。

(((x % f) % g) % h) % i -- intended 

及びません:あなたは好奇心旺盛であれば、上記のようなコード解析を行い専門性のthats

x % (f % (g % (h % i))) -- parse error (which then leads to type error) 
+0

S.Lottがこのように答えたなら、私はずっと感謝していたでしょう。今それはクールです:)ありがとう!そして、あなたは正しい、最後に 'x'を持っていても、私は盗んだだろう:) – mpen

関連する問題