提升方法运行时出错
Error in lifting method to function
我有一个带有隐式参数的方法。在 2 种情况下将其转换为函数时出现错误:
1:
def action(implicit i:Int) = i + " in action"
val f = action _
然后我收到 WhosebugError。
2:
def action(implicit i:Int) = i + " in action"
val f = action(_)
然后我得到一个错误:缺少参数类型
我必须这样写:
val f = (i:Int) => action(i)
没关系。如果 'action' 的参数不是 implicit ,则所有情况都是正确的。那么如何解释,我想念什么?
如果您将函数的参数指定为 implicit
,您是在邀请编译器为您提供该参数的值。那么编译器如何找到这些值呢?它查找在各种 范围 .
中已声明为 implicit
值的相同类型的值(在您的情况下为 Int
)
(为简单起见,我将在此示例中仅使用局部作用域,但您可能需要阅读有关此主题的内容。Programming in Scala, 3rd Ed 是很好的第一步。)
请注意,implicit
值的名称将被忽略并且与程序无关,编译器仅查看 implicit
值的类型。如果在同一作用域中找到具有所需类型的多个 implicit
值,则编译器将抱怨 不明确的隐式值 .
例如,下面提供了一个带有隐式参数和当前范围内该参数默认值的函数:
def greetPerson(name: String)(implicit greeting: String) = s"$greeting $name!"
implicit val defaultGreeting = "Hello" // Implicit value to be used for greeting argument.
val y = greetPerson("Bob") // Equivalent to greetPerson("Bob")(defaultGreeting).
val z = greetPerson("Fred")("Hi")
注意y
只是"Hello Bob!"
的一个String
值,而z
是一个字符串,其值为"Hi Fred!"
;它们都不是函数。
另请注意 greetPerson
是一个 curried 函数。这是因为 implicit
参数不能与同一参数列表中的常规非 implicit
参数混合。
通常,使用常见类型(Int
、Boolean
、String
等)作为 implicit
参数的值是一种不好的做法。在一个大程序中,您的作用域中可能有很多不同的 implicit
值,您可能会选择一个意想不到的值。出于这个原因,标准做法是将这些值包装在 案例 class 中。
如果您尝试创建一个值来提供另一个函数(即 部分应用的函数)的一些参数,那么它看起来像这样:
def greetPerson(greeting: String, name: String) = s"$greeting $name!"
val sayHello = greetPerson("Hello", _: String)
val y = sayHello("Bob") // "Hello Bob!"
val sayHi = greetPerson("Hi", _: String)
val z = sayHi("Fred") // "Hi Fred!"
在这两种情况下,我们都在创建 部分应用函数(sayHi
和 sayHello
)调用 greetPerson
与 greeting
参数指定,但允许我们指定 name
参数。 sayHello
和 sayHi
仍然只是值,但它们的值是 部分应用函数 而不是常量。
根据您的情况,我认为后一种情况可能更适合您...
我还会阅读下划线字符 (_
) 在 Scala 中的使用方式。在部分应用的函数声明中,它对应于稍后将提供的参数。但它还有很多其他用途。我认为除了阅读 Scala 并学习如何以及何时使用它们之外别无选择。
我有一个带有隐式参数的方法。在 2 种情况下将其转换为函数时出现错误:
1:
def action(implicit i:Int) = i + " in action"
val f = action _
然后我收到 WhosebugError。
2:
def action(implicit i:Int) = i + " in action"
val f = action(_)
然后我得到一个错误:缺少参数类型
我必须这样写:
val f = (i:Int) => action(i)
没关系。如果 'action' 的参数不是 implicit ,则所有情况都是正确的。那么如何解释,我想念什么?
如果您将函数的参数指定为 implicit
,您是在邀请编译器为您提供该参数的值。那么编译器如何找到这些值呢?它查找在各种 范围 .
implicit
值的相同类型的值(在您的情况下为 Int
)
(为简单起见,我将在此示例中仅使用局部作用域,但您可能需要阅读有关此主题的内容。Programming in Scala, 3rd Ed 是很好的第一步。)
请注意,implicit
值的名称将被忽略并且与程序无关,编译器仅查看 implicit
值的类型。如果在同一作用域中找到具有所需类型的多个 implicit
值,则编译器将抱怨 不明确的隐式值 .
例如,下面提供了一个带有隐式参数和当前范围内该参数默认值的函数:
def greetPerson(name: String)(implicit greeting: String) = s"$greeting $name!"
implicit val defaultGreeting = "Hello" // Implicit value to be used for greeting argument.
val y = greetPerson("Bob") // Equivalent to greetPerson("Bob")(defaultGreeting).
val z = greetPerson("Fred")("Hi")
注意y
只是"Hello Bob!"
的一个String
值,而z
是一个字符串,其值为"Hi Fred!"
;它们都不是函数。
另请注意 greetPerson
是一个 curried 函数。这是因为 implicit
参数不能与同一参数列表中的常规非 implicit
参数混合。
通常,使用常见类型(Int
、Boolean
、String
等)作为 implicit
参数的值是一种不好的做法。在一个大程序中,您的作用域中可能有很多不同的 implicit
值,您可能会选择一个意想不到的值。出于这个原因,标准做法是将这些值包装在 案例 class 中。
如果您尝试创建一个值来提供另一个函数(即 部分应用的函数)的一些参数,那么它看起来像这样:
def greetPerson(greeting: String, name: String) = s"$greeting $name!"
val sayHello = greetPerson("Hello", _: String)
val y = sayHello("Bob") // "Hello Bob!"
val sayHi = greetPerson("Hi", _: String)
val z = sayHi("Fred") // "Hi Fred!"
在这两种情况下,我们都在创建 部分应用函数(sayHi
和 sayHello
)调用 greetPerson
与 greeting
参数指定,但允许我们指定 name
参数。 sayHello
和 sayHi
仍然只是值,但它们的值是 部分应用函数 而不是常量。
根据您的情况,我认为后一种情况可能更适合您...
我还会阅读下划线字符 (_
) 在 Scala 中的使用方式。在部分应用的函数声明中,它对应于稍后将提供的参数。但它还有很多其他用途。我认为除了阅读 Scala 并学习如何以及何时使用它们之外别无选择。