Clojure to Scala翻译:L系统更新

时间:2013-11-30 10:45:15

标签: scala clojure

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

在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),这怎么可能,我该如何纠正呢?

干杯

2 个答案:

答案 0 :(得分:2)

尝试更换:

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

使用:

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

您的问题是HashMap.get(k)返回Optionkkeytype,而不是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)
}

答案 1 :(得分:1)

// 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)
}