2011-09-07 5 views
5

私は関数をn回適用するローンパターンを持っていますが、 'i'はインクリメント変数です。 "時折"、私は関数が渡されて、 '私'にアクセスできるようにしたいと思いますが、渡されたすべての関数に 'i'を受け入れるためのparamを定義する必要はありません。以下の例...スカラーローンパターン、オプションの関数パラメーター

def withLoaner = (n:Int) => (op:(Int) => String) => { 
    val result = for(i <- 1 to n) yield op(i) 
    result.mkString("\n") 
} 

def bob = (x:Int) => "bob" // don't need access to i. is there a way use() => "bob" instead? 
def nums = (x:Int) => x.toString // needs access to i, define i as an input param 

println(withLoaner(3)(bob)) 

println(withLoaner(3)(nums)) 
+0

質問には関係ありませんが、def f:(args)= exprをdef f(args)= expr(一般的にはそうしているかどうかはわかりません)と書くのであれば、 defよりも。 –

答えて

11
def withLoaner(n: Int) = new { 
    def apply(op: Int => String) : String = (1 to n).map(op).mkString("\n") 
    def apply(op:() => String) : String = apply{i: Int => op()} 
} 

(それはローンのパターンに関連しているかどうかはわかりません)

編集コメントで要求されるように少し説明。

あなたがスカラーについて知っているか分かっていないこと、そしてあなたがそのコードに潜んでいないことがわかりません。だから申し訳ありませんが、私はちょうど明白なことを信じています。

最初に、スカラプログラムは特性/クラス(シングルトンオブジェクトも含む)とメソッドで構成されています。実行されるすべてはメソッドによって行われます(コンストラクタを別にしておく)。関数(メソッドとは対照的に)は、さまざまなFunctionN特性(引数の数N)の(サブタイプの)インスタンスです。それらのそれぞれには実際の実装であるapplyメソッドがあります。 あなたが

val inc = {i: Int => i + 1} 

を記述する場合、それが

val inc = new Function1[Int, Int] {def apply(i: Int) = i + 1} 

に脱糖される(与えられて、Function1を拡張する匿名クラスを定義する方法を適用し、インスタンスを作成する)

だから、関数を記述することは、むしろより多くのを持っています単純な方法よりも軽い。また、オーバーロード(同じ名前のいくつかのメソッド、署名によって異なる、ちょうど私が上で行ったこと)、名前付き引数、または引数のデフォルト値を使用することはできません。

一方、関数はファーストクラスの値です(メソッドとしては返されず、結果として返されます)。それらは必要に応じて自動的に関数に変換されますが、その際にいくつかのエッジが存在する可能性があります。あるメソッドがメソッドとして呼び出されるのではなく、関数値としてのみ使用されることを意図している場合は、関数を書くほうが良いかもしれません。

そのapply方法と機能fは、(あまりにも働く)f(x)なくf.apply(x)で呼び出されるため、コールの値(括弧及び0以上の引数に続く値)にScalaのdesugars関数呼び出し表記方法applyf(x)f.apply(x)の構文砂糖です。これは、タイプがfであれば動作しますが、FunctionNのいずれかである必要はありません。

withLoanerで行われていることは、オブジェクトを返すことです(匿名型ですが、クラスを個別に定義してインスタンスを返す可能性があります)。オブジェクトには2つの方法があり、1つはInt => Stringを受け取り、もう1つは() => Stringを受け取ります。 withLoaner(n)(f)の場合はwithLoaner(n).apply(f)を意味します。 fに適切なタイプがある場合は、適切な適用方法が選択されます。そうでない場合は、コンパイルエラーが発生します。 withLoanerは方法、ではない値であるとして、(ちょうど同様withLoaner.apply.apply(n)を意味するかもしれないこと、またはそれを止めることはない)あなたはwithLoaner(n)を不思議念の

withLoaner.apply(n)を意味するものではありません。

+0

これは素晴らしいですね。非常に素晴らしい。これが何をしているのか少し説明してもらえますか?また、def f(args)= exprがより一般的な/より良い方法であると言っていますか?なぜか分かりません... – eptx

+0

優秀なディディエド。ありがとうございました! – eptx

関連する問題