【问题标题】:Clojure to Scala translation: L System updateClojure 到 Scala 的翻译:L 系统更新
【发布时间】:2013-11-30 10:45:15
【问题描述】:

我正在尝试为一个类项目建模一个 L 系统,但在使用了几个月的 Clojure 之后,我正在努力使用 Scala 的 reduce/fold 和类型系统来实现这一目标。

在 Clojure 中,我会写

user> (defn update-state [translation-map, state]
          (mapcat #(get translation-map %1 [%1]) state))
user> (def translations {"a" ["b", "a", "b"]})
user> (update-state translations ["a"])
["b", "a", "b"]

这个技巧有效,因为我隐式定义了(update-state "b") => ["b"],并且我使用clojure.core/mapcat 来处理concat 一起翻译的值。

因此,如果我们两次应用此操作,我们会看到示例 L 系统的行为符合预期..

user> (->> ["a"] 
           (update-state translations)
           (update-state translations))
["b", "b", "a", "b", "b"]

我的 Scala 尝试是

package me.arrdem.planter;
import scala.collection.mutable.{HashMap,LinkedList};

class LSystem[keytype,fntype] {
  var _invoke_map = HashMap[keytype,fntype]()
  var _tr_map = HashMap[keytype,Seq[keytype]]()

  def translate(s:Seq[keytype], k:keytype) : Seq[keytype] = {
    s ++ (if(_tr_map contains(k)) _tr_map.get(k) else (k))
  }

  def step(s:Seq[keytype]) : Seq[keytype] = {
    s foldRight(LinkedList[keytype]())(translate)
  }
}

在我看来,除了类型检查器抱怨之外,这应该可以工作

ERROR: type mismatch;  found   : Seq[Any]  required: Seq[keytype] : line 9
ERROR: type mismatch;  found   : keytype  required: scala.collection.GenTraversableOnce[?] : line 9
ERROR: type mismatch;  found   : keytype  required: scala.collection.GenTraversableOnce[?] : line 9

现在,当我读到这篇文章时,隐含的错误是表达式(if(_tr_map contains(k)) _tr_map.get(k) else (k)) 被类型推断为Seq[Any] 而不是Seq[keytype]

由于两个结果是 1) 找到密钥 -> Seq[keytype] 和 2) 未找到密钥 -> 单例元组 (k),这怎么可能,我该如何纠正?

干杯

【问题讨论】:

    标签: scala clojure


    【解决方案1】:

    尝试替换:

    s ++ (if(_tr_map contains(k)) _tr_map.get(k) else (k))
    

    与:

    s ++ _tr_map.get(k).getOrElse(Seq[keytype](k))
    

    您的问题是HashMap.get(k) 返回一个Option,而kkeytype,而不是++ 运算符所期望的Seq[keytype]

    现在对于您的第二个问题,除非您更改参数的顺序,否则您不能 foldRight 使用您的翻译功能。

    您可以foldLeftreverse

      def step(s: Seq[keytype]): Seq[keytype] = {
        s.foldLeft(Seq[keytype]())(translate)
      }
    

    或将您的 translate 函数更改为:

     def translate(k:keytype, s:Seq[keytype]) : Seq[keytype] = {
         s ++ _tr_map.get(k).getOrElse(Seq[keytype](k))
     }
    

    然后你可以foldRight:

    def step(s: Seq[keytype]): Seq[keytype] = {
      s.foldRight(Seq[keytype]())(translate)
    }
    

    【讨论】:

      【解决方案2】:
      // Seq needs to be 'right' parameter : (foldRight means accumulator is right)
      def translate(k: keytype, s:Seq[keytype]) : Seq[keytype] = {
          s ++ (if(_tr_map contains(k)) _tr_map.get(k).get else Seq(k))
      
                                   // Hashmap.get returns an option so you need another get
                                   // in else condition you need Seq(k)
      }
      
      def step(s:Seq[keytype]) : Seq[keytype] = {
      
         s.foldRight(Seq[keytype]())(translate)
      
         // need dotted syntax for foldRight
         // or (s foldRight Seq[keytype]()) (translate)
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 1970-01-01
        • 2017-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多