【问题标题】:Scala implicitly vs implicit argumentsScala 隐式与隐式参数
【发布时间】:2014-03-26 17:54:12
【问题描述】:

我是 Scala 新手,当我查看不同的项目时,我看到了两种处理隐式参数的风格

scala]]>def sum[A](xs:List[A])(implicit m:Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
sum:[A](xs:List[A])(implicit m:Monoid[A])A

scala]]>def sum[A:Monoid](xs:List[A]): A ={
     val m = implicitly[Monoid[A]]
     xs.foldLeft(m.mzero)(m.mappend)
   }
sum:[A](xs:List[A])(implicit evidence$1:Monoid[A])A

根据这两个函数的类型,它们是匹配的。两者有区别吗?为什么要隐式使用隐式参数?在这个简单的例子中,感觉更加冗长。

当我在 REPL 中使用没有隐式的东西运行上述内容时,我收到以下错误

带有隐式参数

<console>:11: error: could not find implicit value for parameter m: Monoid[String]

隐式地和 a: Monoid

<console>:11: error: could not find implicit value for evidence parameter of type Monoid[String]

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    在某些情况下,隐式形式参数不直接用于将其作为参数的方法体中。相反,它只是变成了一个隐式 val,可以传递给另一个需要相同(或兼容)类型的隐式参数的方法。在这种情况下,没有明显的隐式参数列表很方便。

    在其他情况下,上下文绑定表示法,它是显式隐式参数的严格语法糖,在美学上被认为是可取的,即使需要实际参数,因此必须使用implicitly 方法来获得它。最好的。

    鉴于两者之间没有语义差异,因此选择是基于相当主观的标准。

    随心所欲。最后请注意,从一个更改为另一个不会破坏任何代码,也不需要重新编译(尽管我不知道 SBT 是否具有足够的区别性,可以放弃重新编译可以看到更改定义的代码)。

    【讨论】:

    • “请注意,从一个更改为另一个不会破坏任何代码,也不需要重新编译”:这在技术上是不正确的。将隐式参数显式指定为命名参数 是完全正确的(尽管不常见)。所以你可以做sum(List(1,2,3))(m=someMonoidInstance)。用上下文绑定替换声明中的隐式参数会将隐式参数名称从m 更改为evidence$1,从而中断上述调用。参数名称(包括隐式名称)是接口的一部分,有好有坏。吹毛求疵,但仍然。
    • 好吧,好吧……这简直是天方夜谭!
    • "在其他情况下,上下文绑定表示法(它是显式隐式参数的严格语法糖)在美学上被认为是可取的,即使需要实际参数,因此必须使用隐式方法得到它。”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 2021-05-02
    • 2020-12-08
    • 2015-02-19
    • 1970-01-01
    • 2018-06-03
    • 2011-08-29
    相关资源
    最近更新 更多