5

この関数を想定しましょう:

def autoClosing(f: {def close();})(t: =>Unit) = {
    t
    f.close()
}

そしてこのスニペット:

val a = autoClosing(new X)(_)
a {
 println("before close")
}

最初の部分をカレーすることは可能ですか?何かのようなもの:

val a = autoClosing(_) { println("before close") }

クローズを実行する必要のあるオブジェクトを送信し、それらに対して同じブロックを実行できるようにするには?

4

3 に答える 3

10

はい、プレースホルダー文字のタイプを指定する限り、指定したスニペットは機能します。

したがって、探しているコードは次のとおりです。

val a = autoClosing(_: {def close();}) { println("before close") }

これはコンパイルされ、期待どおりに機能します:)。

いくつかのメモ:

  • メソッド、のようなもの、または適切なインターフェイスAnyRefを持つ型の型エイリアスを定義すると、作業が楽になります。closetype Closeable = AnyRef {def close()}
  • コードスニペットautoClosing(_: Closeable){ ... }は、実際には次の拡張匿名関数と同等ですc: Closeable => autoClosing(c){ ... }。ワイルドカード文字は、部分的に適用された関数の省略形です。_この場合、タイプ推論機能は残念ながらタイプを推論できないため、タイプを指定する必要があります。

それが役に立てば幸い、

--Flaviu Cipcigan

于 2009-12-17T11:24:45.717 に答える
6

または、パラメータを反転することもできます。

def flip[A1, A2, B](f: A1 => A2 => B): A2 => A1 => B = x1 => x2 => f(x2)(x1)

あなたの場合:

val a = flip(autoClosing){ println("before close") }

編集:人間のパーサーを助けるためにいくつかの中括弧を追加しました:

def flip[A1, A2, B](f: (A1 => (A2 => B))): (A2 => (A1 => B)) = {
    x1 => (x2 => f(x2)(x1))
}

(A1 => (A2 => B))Flipは関数をに変換します(A2 => (A1 => B))

scala> def x(x1 : Int)(x2 : Long) = 1.0 * x1 / x2
x: (Int)(Long)Double

scala> val f = flip(x)
f: (Long) => (Int) => Double = <function>

scala> val g = f(1)
g: (Int) => Double = <function>

scala> val h = g(2)
h: Double = 2.0

scala> x(1)(2)
res0: Double = 0.5
于 2009-12-17T14:15:33.917 に答える
3

最近、たくさんの人がScalaの質問に答えてくれるのを見てうれしいです。しかし、それは私が何かを思い付くのを難しくします。これがFlaviuソリューションの代替案です。

val a: {def close();} => Unit = autoClosing(_) { println("before close") }

もちろん、適切な解決策は、autoClosingを使用方法と互換性のある方法で定義することです。

于 2009-12-17T18:55:49.873 に答える