2011-09-21 26 views
42

私はScala composeandThenメソッドでチュートリアルPattern matching & functional compositionに従っています。そのような例があります:ComposeとandThenのメソッド

scala> def addUmm(x: String) = x + " umm" 
scala> def addAhem(x: String) = x + " ahem" 

val ummThenAhem = addAhem(_).compose(addUmm(_)) 

私はエラーを取得、それを使用しようとすると:

<console>:7: error: missing parameter type for expanded function ((x$1) => addAhem(x$1).compose(((x$2) => addUmm(x$2)))) 
    val ummThenAhem = addAhem(_).compose(addUmm(_)) 
          ^
<console>:7: error: missing parameter type for expanded function ((x$2) => addUmm(x$2)) 
    val ummThenAhem = addAhem(_).compose(addUmm(_)) 
              ^
<console>:7: error: type mismatch; 
found : java.lang.String 
required: Int 
    val ummThenAhem = addAhem(_).compose(addUmm(_)) 

しかし、この作品を:

val ummThenAhem = addAhem _ compose addUmm _ 

あるいは

val ummThenAhem = addAhem _ compose addUmm 

チュートリアルのコードで何が問題になっていますか?後者の表現は括弧のない最初の表現と同じではないのですか? composeドキュメントから

答えて

38

addAhemを治療するための

scala> val ummThenAhem = (addAhem _).compose(addUmm _) 
ummThenAhem: String => java.lang.String = <function1> 

書くべき方法です。 composeメソッドは関数で定義されています。 addAhem _はメソッドごとにaddAhemを変換するので、composeを呼び出すことができます。 composeは、関数を引数として想定しています。 をaddUmmの関数に変換することにより、メソッドaddUmmを与えています(アンダースコアは、関数が予期される関数を自動的に関数に変換するため、アンダースコアを省略することができます)。だからあなたのコード:

addAhem _ compose addUmm 

は、私はあなたが提供されたリンクを見ていなかったPS

(addAhem _).compose(addUmm) 

なく

addAhem(_).compose(addUmm(_)) 

と同じです。

+0

は、andThenの例は次のようになります。。 'ヴァルahemThenUmm = addAhem(_)andThen(addUmm(_))' それは 'ヴァルahemThenUmm1 =(addAhem _)andThenのようになります(addUmm ) ' –

+0

私は丸い括弧で書かれた部分についてはあまりよく分かりません。少なくともScala 2.10.2では、コンパイラ*はメソッドを自動的に関数に変換しません。回避策は、 'addAhem'と' addUmm'を関数として宣言し、 'compose'や' andThen'が '_'なしで動くようにすることです。 –

5

Composes two instances of Function1 in a new Function1, with this function applied last.

はあなたがaddAhemaddUmmとして部分的に適用される機能(すなわちfunction1

scala> addAhem _ 
res0: String => java.lang.String = <function1> 
2

このチュートリアルは以前のバージョンのScala(おそらく2.7.7以前)向けに書かれたものだと思います。

addUhum(_).compose(addAhem(_)) 

機能に持ち上げ、まだあなたならば、その構文で動作します。つまり、今のタイプの推論は、上で失敗する原因型システムへの拡張、それ以来、コンパイラではいくつかの変更がありました書き込み:

addUhum(_) 
45

さて、この:

addUhum _ 

はETAの拡張です。メソッドを関数に変換します。一方、これは:

addUhum(_) 

は無名関数です。実際には、このパラメータは適用されず、全体が関数に変換されるという点で、部分関数アプリケーションです。それは次のように拡張されます

x => addUhum(x) 

拡大のための正確な規則を説明するのは少し難しいですが、基本的に、関数はもっとも内側の式の区切り文字で「開始」します。例外は部分関数アプリケーションで、パラメータの代わりに_が使用されている場合、 "x"が関数の外に移動します。とにかく

、これは、それが拡張する方法です:

val ummThenAhem = x => addAhem(x).compose(y => addUmm(y)) 

残念ながら、型inferencerは、xまたはyの種類を知りません。必要に応じて、パラメータ-Ytyper-debugを使用して試した内容を正確に確認することができます。完全の便宜上