【问题标题】:How to call function from hashmap in Scala如何从Scala中的hashmap调用函数
【发布时间】:2011-12-30 00:50:54
【问题描述】:

我对 scala 还很陌生,基本上我希望有几个函数与哈希图中的字符串耦合。 但是,我在subscribers.get(e.key)(e.EventArgs); 收到错误。说明 Option[EventArgs => Unit] 不带参数... 示例代码:

object Monitor {
    val subscribers = HashMap.empty[String, (EventArgs) => Unit ]

    def trigger(e : Event){
      subscribers.get(e.key)(e.EventArgs);

    }

    def subscribe(key: String, e: (EventArgs) => Unit) {
      subscribers += key -> e;
    }

}

【问题讨论】:

    标签: list function scala methods hashmap


    【解决方案1】:

    Mapget 方法为您提供了值的Option,而不是值。因此,如果在地图中找到密钥,您将获得Some(value),否则,您将获得None。因此,您需要首先“展开”该选项,以确保实际上存在可以调用的函数值(调用 apply on):

    def trigger(e: Event): Unit =
      subscribers.get(e.key).foreach(_.apply(e.EventArgs))
    

    def trigger(e: Event): Unit =
      subscribers.get(e.key) match {
        case Some(value) => value(e.EventArgs)
        case None =>
      }
    

    有很多关于解释 Scala 的 Option 类型的帖子。例如this onethis one

    另请注意 Luigi 关于使用不可变映射(默认 Map)和 var 的评论。

    【讨论】:

    • 谢谢!这里的所有这些 cmets 都非常有用!
    【解决方案2】:

    由于 get 方法返回 Option,您可以在其上使用 'map':

    subscribers.get(e.key).map(f => f(e.EventArgs))
    

    甚至更短:

    subscribers.get(e.key) map (_(e.EventArgs))
    

    【讨论】:

    • 在“地图”上使用地图是 IMO 的正确方式。它使您免于模式匹配和 NoSuchElementException
    【解决方案3】:

    get 只接受一个参数。所以subscribers.get(e.key) 返回一个选项,而您试图将(e.EventArgs) 提供给该选项的apply 方法(不存在)。

    另外,尝试将subscribers 设为var(或选择可变集合类型)。目前你有一个不可变的集合和一个不可变的变量,所以你的地图不能改变。一种更惯用的声明方式是

    var subscribers = Map[String, EventArgs => Unit]()
    

    【讨论】:

      【解决方案4】:

      HashMap.get() 在 Scala 中的工作方式与在 Java 中略有不同。 get() 不是返回值本身,而是返回 Option。 Option 是一种特殊类型,可以有 2 个值 - Some(x)None。在第一种情况下,它告诉“地图中有 some 具有这样一个键的值”。在第二种情况下,它告诉“不,地图中的此键没有任何内容 (none)”。这样做是为了强制程序员检查 map 是否真的有一个对象,并避免NullPointerException,它在 Java 代码中经常出现。

      所以你需要这样的东西:

      def trigger(e: Event) {
        val value = subscribers.get(e.key)
        value match {
          case None => throw new Exception("Oops, no such subscriber...")
          case Some(f) => f(e.EventArgs)
        }
      }
      

      您可以在 Scala here 中找到有关 Option 类型和模式匹配的更多信息。

      【讨论】:

      • 您提供的链接本身并不是很有用。 Bub 中引用的链接实际上是这样,所以让我们在这里给它信用:blog.tmorris.net/scalaoption-cheat-sheet
      • @AndreasScheinert:我提供的链接不仅仅是关于 Option 类,而是关于整体安全编程,特别是关于他们在 HashMap 中使用它的原因。所以不,我认为您的链接在这种具体情况下比原始链接更有用。
      • 在非常低程度上有用 IMO 作者没有询问如何使用 Option 来远离 null。他使用了一张地图,并惊讶于他没有“得到”他所期望的。所以 3 个单语句在这里似乎很重要: 1. 你得到 Option 包装的值 2. 你可以得到(但 IMO 你不应该 3. 使用 map on Option 你可以使用'ignore None' 策略。如果那时OP仍然问为什么地图。获取值被包装了链接可以给出解释。另外我不喜欢这个例子,因为它把 null 放在地图上......
      • @AndreasScheinert:Seba K 被一个错误弄糊涂了。我解释了他为什么得到它 - 指向 Option 的指针。如果我是 Scala 新手并且看到了这种不寻常的行为(get 返回的不是值,而是一些包装器),我的下一个问题是“这个包装器是什么以及他们为什么把它放在那里”。您可能同意或不同意我的观点,但 1) 问题已得到解答; 2) 答案正确。所有附加信息可能对作者有用或无用,但符合 SO 规则良好答案的条件。
      猜你喜欢
      • 2020-07-16
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      相关资源
      最近更新 更多