Clojure:使用带有列表推导的字符串

时间:2016-01-31 23:16:14

标签: clojure list-comprehension clojurescript

我正试图从Martin Odersky的功能性编程课程中编写6.7课程的clojure版本。原文是用Scala编写的。

这个概念是取一个电话号码(作为一个字符串),并根据一个单词词典产生一个可能的短语列表。

因此,translate("7225247386")会产生短语" Scala很有趣"

这里是Gist with the full Scala version

这是我的attempt using Clojure

最终'编码'问题出现了。功能 Scala版本是

def encode(number: String): Set[List[String]] =
if (number.isEmpty) Set(List())
else {
    for {
        split <- 1 to number.length
        word <- wordsForNum(number take split)
        rest <- encode(number drop split)
        } yield word :: rest
}.toSet

使用我的Clojure版本

    (defn encode
      "Takes a number as a string. Returns all the different ways to encode that number as a list of words"
  [number]
  (if (empty? number)
    (vector)             
    (for [split (range 0 (count number))      
          word  (words-from-number (subs number 0 split)) 
          remainder (encode (subs number split))]    
      (concat word remainder))))

问题似乎是字符串不断转换为字符列表;这就是为什么我使用(subs number 0 split)而不是(take split number)

的原因

上面的一个版本,只是发现第一个单词似乎在正确的轨道上......

    (defn encode
  [number]
  (for [split (range 0 (count number))
        word (words-from-number (subs number 0 split))]
    word))

(encode "7225247386") => ("pack" "rack" "sack" "Scala")

...但是在递归调用中加入&#39;编码&#39;剩下的数字字符串只返回一个空列表。

任何建议都将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:1)

您可以使用clojure.string/join将字符序列转换回字符串。

您的代码中有一些位与原始Scala版本略有不同:

  • Scala版本的范围从1开始,你的范围从0
  • 开始
  • Scala版本的if-&gt; true返回嵌套集合
  • 您将两个序列连接在一起,而不是“列入”列表

我创建了一个可能不完全正确的修改版本(没有根据Scala版本的输出检查它),但希望能帮到你:

(defn encode
  "Takes a number as a string. Returns all the different ways to encode that number as a list of words"
  [number]
  (if (empty? number)
    #{()}
    (for [split (range 1 (inc (count number)))
          word  (words-from-number (join (take split number)))
          remainder (encode (join (drop split number)))] 
      (cons word remainder))))

我可能感兴趣的是我刚刚实现了相同的翻译:https://gist.github.com/ponzao/6095989