0

スカラはかっこいい。しかし、一見恣意的に見える多くの制限や、期待どおりに機能しないことが原因で、非常にイライラすることもあります.

この場合、Scala で引数解析ライブラリを作成しました。次の機能があります。

def option[T](
  name1: String, name2: String = null, name3: String = null,
  name4: String = null, name5: String = null, name6: String = null,
  name7: String = null, name8: String = null, name9: String = null,
  default: T = null.asInstanceOf[T],
  metavar: String = null,
  choices: Seq[T] = null,
  aliases: Map[T, Iterable[T]] = null,
  help: String = "")
(implicit convert: (String, String, ArgParser) => T, m: Manifest[T]) = {
  optionSeq[T](nonNullVals(name1, name2, name3, name4, name5, name6,
    name7, name8, name9),
    metavar = metavar, default = default, choices = choices,
    aliases = aliases, help = help)(convert, m)
}

基本的に、これは特定の型の通常のオプション引数を宣言します。タイプに適したデフォルトのコンバーターで埋められる暗黙の関数があります。暗黙のマニフェストもあります。これは、特定のことを条件付けできるようにする必要があるため必要です。

これは、デフォルト以外のコンバーターを実際に提供しようとするまで機能しました。書かれているように、コンバーターを提供するだけでなく、マニフェストも提供する必要がありますが、その方法はわかりません。とにかく、それはひどく醜いです-マニフェストは、. JVM が壊れている可能性があり、エンド ユーザーに公開すべきではありません。

Scala では、単一の引数リストに暗黙的な引数と非暗黙的な引数を混在させることができないことは既に知っています。IMO は恣意的で不必要な制限ですが、それでも構いません。そこで、暗黙の引数リストを 2 つの別個の引数リストに分割して、それぞれに 1 つの暗黙的な引数リストを作成してみました。運が悪かった -- Scala はまた、複数の暗黙の引数リストを持つことを妨げているようだ (これも恣意的な制限のように見える)。

これを回避する方法がわかりません。提案?

また、将来の Scala バージョンでこれらの制限のいくつかを暗黙的に修正する現在の試みはありますか?

4

2 に答える 2

3

のコンテキストでいつでもimplicitof 型を取得できます。したがって、コンパイラが提供するはずの暗黙的なものを明示的に記述する必要がある場合は、.Timplicitly[T]Manifest[T]implicitly[Manifest[T]]

これは、暗黙的なパラメーター リストに引数を指定し、他の引数を変更しない場合はいつでも機能します。変更したくない引数には、暗黙的に [TheTypeOfTheImplicit] を使用するだけです。

マニフェストの場合、Predefたまたまそのためのショートカットがありmanifest[T]ますimplicitly[Manifest[T]]

注:implicitlyは魔法ではありませんdef implicitly[T](implicit e: T) = ePredef.

于 2012-05-02T23:56:29.677 に答える
3

とてもむずかしい方法です。9 つの明示的な名前引数? 変換関数の暗黙の選択? ここでマニフェストが最悪の問題であるかどうかはわかりません。

とにかく、あなたはできます

class Converter[T: Manifest](val f: (String, String, ArgParser) => T) {
  def m = manifest[T]
}
implicit def function_to_converter[T: Manifest](f: (String, String, ArgParser) => T) =
  new Converter { def apply(s1: String, s2: String, ap: ArgParser) = f(s1,s2,ap) }
}

そして、あなたが持っている2つの引数の代わりにそれを使用してください. 次のようなすべてのデフォルトのコンバーターを定義します

implicit val convert_to_int: Converter = (s1: String, s2: String, ap: ArgParser) => ...

ユーザーが明示的に入力する必要がある場合は、関数を指定するだけで暗黙的に変換できます。

于 2012-05-03T00:44:47.727 に答える