简体   繁体   English

在scala中用作Map的值

[英]functions as values of Map in scala

I am trying to create a map of lambda functions in Scala 我正在尝试在Scala中创建lambda函数的映射

val identity = ((x:Any) => x)
val propmap = Map("references-count" -> identity, 
    "title" -> ((x:List[String]) => x(0)),
    "score" -> identity,
    "issued" -> ((x:List[Any]) => x(0)))

when I type propmap("score") or propmap("title") the output I get is the same: <function1> . 当我输入propmap("score")propmap("title") ,我得到的输出是相同的: <function1>

Running identity(10.1) returns the expected result. 运行identity(10.1)返回预期结果。 However 然而

val f1 = propmap("score") f1(10.9)

results in: 结果是:

Name: Unknown Error
Message: <console>:29: error: type mismatch;
 found   : Double(10.9)
 required: List[String]
       f1(10.9)
          ^
StackTrace: 

Seemingly the function is overwritten. 似乎该函数被覆盖。 Where to go for the besung immutabilty? 到哪里去寻求被遗弃的不变性?

The problem is the type of propmap. 问题是propmap的类型。

Scala infers the type as String, (List[String] => Any) Scala将类型推断为String,(List [String] => Any)

The reason for that is that scala needs to infer a type which matches ALL values. 这样做的原因是,scala需要推断出一个匹配所有值的类型。 The String as key is obvious but for the function, it needs to find a function type which matches all functions. 字符串作为键很明显,但是对于函数来说,它需要找到与所有函数匹配的函数类型。 Since all functions have 1 parameter this would be function1. 由于所有函数都有1个参数,因此它将为function1。

If you look at the definition of function1 you would see it is: 如果查看function1的定义,您将看到:

trait Function1[-T1, +R] extends AnyRef

This means that it needs to find the first type to be the most constrictive. 这意味着它需要找到最严格的第一种类型。 In this case this is List[String] and therefore it expects a function List[String]=>Any (this actually makes sense because you want a type you can use on ALL functions). 在这种情况下,它是List [String],因此需要一个函数List [String] => Any(这实际上很有意义,因为您希望可以在所有函数上使用的类型)。

So scala automatically converts your identity function to be (x: List[String] => x) in practice and therefore when you try to pass it a number it fails. 因此,scala实际上会自动将您的标识函数转换为(x:List [String] => x),因此,当您尝试传递给它一个数字时,它将失败。

Possible solutions: 可能的解决方案:

The first solution as mentioned by @KotWarm would be to use asInstanceOf: @KotWarm提到的第一个解决方案是使用asInstanceOf:

val f1 = propmap("score").asInstanceOf[Any ⇒ Any]
println(f1(10.9))

The second solution would be to rewrite the functions to use Any, for example: 第二种解决方案是重写函数以使用Any,例如:

val propmap = Map("references-count" -> identity,
                  "title" -> ((x: Any) => x.asInstanceOf[List[String]](0)),
                  "score" -> identity,
                  "issued" -> ((x: Any) => x.asInstanceOf[List[Any]](0)))

Because scalac determined the type of collection as 因为scalac将集合类型确定为

propmap: scala.collection.immutable.Map [String, List [String] => Any]

Determine the type of your collection explicitly so that the compiler knows what you want to get 明确确定集合的类型,以便编译器知道您要获取的内容

Here is an example code 这是一个示例代码

    val identity = ((x:Any) => x)
    val propmap = Map[String,_ => _]("references-count" -> identity,
        "title" -> ((x:List[String]) => x(0)),
        "score" -> identity,
        "issued" -> ((x:List[Any]) => x(0)))

But to execute the methods you must cast the type 但是要执行这些方法,您必须强制转换类型

    val f1 = propmap("score").asInstanceOf[Any ⇒ Any]
    println(f1(10.9))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM