Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala隐式_Scala_Compiler Errors_Implicit - Fatal编程技术网

Scala隐式

Scala隐式,scala,compiler-errors,implicit,Scala,Compiler Errors,Implicit,我试图在我的代码中使用一些隐含的魔法,但问题非常简单,我在这里将其提取出来。这似乎有点奇怪,因为从我所读到的内容来看,以下内容应该是有效的 implicit class Foo(value: Double) { def twice = 2*value } 2.0.twice implicit def strToDouble(x: String) = Try(x.toDouble) match { case Success(d) =>

我试图在我的代码中使用一些隐含的魔法,但问题非常简单,我在这里将其提取出来。这似乎有点奇怪,因为从我所读到的内容来看,以下内容应该是有效的

   implicit class Foo(value: Double) {
      def twice = 2*value
    }

    2.0.twice

    implicit def strToDouble(x: String) = Try(x.toDouble) match {
      case Success(d) => d
      case Failure(_) => 0.0
    }

    strToDouble("2.0").twice
    val a: Double = "2.0"
    val b: Double = "equals 0.0"
    "2.0".twice 
    
我得到一个编译错误

 value twice is not a member of String
[error]     "2.0".twice
我知道编译器,tweep是为
Double
s定义的,而不是
String
s。但我确实告诉过你如何从
字符串
s转换为
双精度
s,而且这里没有歧义(据我所知),所以你不应该注意到
“2.0”。两次
可以通过执行
strToDouble(“2.0”)。两次

我是不是遗漏了什么?或者,这是一种优化,这样编译器就不会尝试所有可能的
隐式排列(我认为它会以超指数的方式增长为阶乘)。我想我真的在寻找对这一点的确认或拒绝


谢谢

如果您希望扩展方法在隐式转换之后仍然适用,您可以修改隐式类的定义

implicit class Foo[A](value: A)(implicit ev: A => Double) {
  def twice: Double = 2 * value
}

implicit def strToDouble(x: String): Double = ???

2.0.twice   //compiles
"2.0".twice //compiles
我给您介绍了编译器,
tweep
是为
Double
s定义的,而不是
String
s。但我 您是否已经告诉过如何从
String
s转换到
Double
s,并且没有 这里有歧义(据我所知),所以你不应该 请注意,
“2.0”。可以通过执行
strToDouble(“2.0”)。两次

根据规范,隐式转换仅适用于三种情况

2.0.两次
转换为
Foo(2.0).两次
是第二种情况,将
“2.0”
转换为
strToDouble(“2.0”)
是第一种情况。正如您所看到的,没有任何项目可以将它们应用在一起。所以,如果你想让它们同时适用,你应该像我上面所展示的那样明确地指定它们

同样,如果您定义了从
A
B
和从
B
C
的转换,这并不意味着您有从
A
C
的转换

case class A(i: Int)
case class B(i: Int)
case class C(i: Int)
implicit def aToB(a: A): B = B(a.i)
implicit def bToC(b: B): C = C(b.i)

A(1): B    // compiles
B(1): C    // compiles
// A(1): C //doesn't compile

如果您希望扩展方法在隐式转换之后仍然适用,那么可以修改隐式类的定义

implicit class Foo[A](value: A)(implicit ev: A => Double) {
  def twice: Double = 2 * value
}

implicit def strToDouble(x: String): Double = ???

2.0.twice   //compiles
"2.0".twice //compiles
我给您介绍了编译器,
tweep
是为
Double
s定义的,而不是
String
s。但我 您是否已经告诉过如何从
String
s转换到
Double
s,并且没有 这里有歧义(据我所知),所以你不应该 请注意,
“2.0”。可以通过执行
strToDouble(“2.0”)。两次

根据规范,隐式转换仅适用于三种情况

2.0.两次
转换为
Foo(2.0).两次
是第二种情况,将
“2.0”
转换为
strToDouble(“2.0”)
是第一种情况。正如您所看到的,没有任何项目可以将它们应用在一起。所以,如果你想让它们同时适用,你应该像我上面所展示的那样明确地指定它们

同样,如果您定义了从
A
B
和从
B
C
的转换,这并不意味着您有从
A
C
的转换

case class A(i: Int)
case class B(i: Int)
case class C(i: Int)
implicit def aToB(a: A): B = B(a.i)
implicit def bToC(b: B): C = C(b.i)

A(1): B    // compiles
B(1): C    // compiles
// A(1): C //doesn't compile

首先,隐式转换不好;更喜欢扩展方法其次,没有显式返回类型的隐式转换更加危险第三,隐式类也应该是一个值类,因此扩展方法
隐式类Foo(private val value:Double)扩展AnyVal
-最后但并非最不重要的一点是,编译器永远不会应用多个隐式转换。否则,它将非常缓慢和复杂;我相信你会在这里找到你的大部分答案:我认为这是一种保护,而不是一种优化。考虑到所有内容都可以转换为字符串,这也意味着在字符串上定义的任何扩展方法都可以在任何内容之上工作。我还想说,潜在的无休止的隐式转换可以非常容易地冻结编译器,同时对正在发生的事情给出很少的提示。@LuisMiguelMejíaSuárez First:是的,我同意。但是,我尝试使用的库需要为
Seq[T]
创建隐式,我必须为
Seq[Seq[T]
Seq[Seq[Seq[…]]
等的每个实现创建隐式,因此我希望定义一个
flatMap
隐式,这将减少
Seq[Seq[T]]
to
Seq[T]
然后这将推广到所有深度。第二:我没有在这里声明返回类型,因为它不是问题的核心,但我接受你的观点。最后:这似乎证实了我的观点,即这是一个optimisation@niurepu为什么库会要求您添加隐式转换?而且,我相信这对t是有意义的与将一个
Seq[Seq[T]]
与一个
Seq[Seq[T]]
平铺不同的是,嵌套的Seq越多,操作就越复杂,试图隐藏这一点会隐藏很多复杂性,并且很容易让人们设计非常糟糕的抽象(在任何情况下,Seq都不好,使用具体的集合代替)-最后,这不是一个真正的优化,而是一个决定语言语义的设计决策…首先,隐式转换是不好的;更喜欢扩展方法。-第二,没有显式返回类型的隐式转换更危险。-第三,隐式类也应该是一个值类,因此没有ov扩展方法
隐式类Foo(私有val值:Double)上的erhead扩展AnyVal
——最后但并非最不重要的一点是,编译器永远不会应用多个隐式转换。否则,它将非常缓慢和复杂;宁可在字符串上编写两次额外的扩展方法
。我相信您会在这里找到大多数答案:我将此称为保护,而不是