【问题标题】:multiple independent implicits in ScalaScala中的多个独立隐式
【发布时间】:2012-05-02 23:29:20
【问题描述】:

Scala 很酷。但有时也会因为许多看似武断的限制以及不符合我预期的事情而感到非常沮丧。

在这种情况下,我用 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 是任意且不必要的限制,但就这样吧。所以我尝试将隐式参数列表拆分为两个单独的参数列表,每个列表都有一个隐式。不走运——Scala 似乎也阻止了你拥有多个隐式参数列表(另一个看似任意的限制)。

我对如何解决这个问题一无所知。有什么建议吗?

此外,目前是否有任何尝试在未来的 Scala 版本中修复对隐式的一些限制(和/或提出一种比清单更不可见的解决类型擦除损坏的方法,这在 IMO 中是丑陋的) ?

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    这是一个非常尴尬的方法。九个显式名称参数?隐式选择转换函数?我不确定清单是这里最严重的问题。

    无论如何,你可以

    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) }
    }
    

    然后使用它而不是你得到的两个参数。定义所有默认转换器,例如

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

    然后如果用户需要显式填写一个,他们可以提供函数并隐式转换。

    【讨论】:

    • 谢谢,我会试试的。这看起来很尴尬,因为我正在尝试解决 Scala 的非功能。我希望您能够声明一个或多个名称,以及一些命名参数,例如:option[Int]("ngram", "n-gram", default = 3, help = """something""").
    【解决方案2】:

    您始终可以在implicitly[T] 的上下文中获取T 类型的implicit。因此,如果您需要显式编写编译器提供的隐式Manifest[T],您可以使用implicitly[Manifest[T]] 来完成。

    只要你想在隐式参数列表中提供一个参数,而另一个保持不变,只要隐式地使用[TheTypeOfTheImplicit] 作为你不想改变的参数,它就可以工作。

    对于清单,Predef 恰好有一个快捷方式,即 manifest[T](即 implicitly[Manifest[T]]

    注意:implicitly 不是魔法,它只是def implicitly[T](implicit e: T) = e,在Predef.

    【讨论】:

    • 谢谢。我想避免让用户明确填写清单,因为它确实是一个实现功能;这就是我接受另一个答案的原因。
    猜你喜欢
    • 1970-01-01
    • 2012-01-10
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多