【问题标题】:Why this function is returning nil?为什么这个函数返回 nil?
【发布时间】:2015-02-21 18:08:34
【问题描述】:

我正在学习 Clojure 和函数式编程,为了练习,我正在研究 4clojure 问题。

这个功能,(不是最好的方法..我知道)正在工作。 (反向交错)但是,该功能正在重新调整零。

(defn reverse_interleave
  [coll ss]
  (let [xx (dec ss)]
    (loop [coll (reverse coll) s xx _ss ss ret `()]
      (if (nil? (first coll)) (do (println :ret ret) ret))
      (when-let [x (first coll)]
                        (recur 
                          (rest coll)
                          (if (zero? s) xx (dec s))
                          (if (or (= 1 _ss) (zero? _ss)) 0 (dec _ss))
                          (if (zero? _ss)
                            (map-indexed #(if (= % s) (cons x %2) %2) ret)
                            (cons (list x) ret))
                            ))
      )) ret)


(reverse_interleave (range 9) 3)

问题是……为什么?

【问题讨论】:

  • 您在循环中定义了一个变量ret,但它不会存在于循环之外。函数中的最后一个 ret 在循环之外,所以它不是同一个变量。当你评估你的代码时,你甚至会得到一个关于它的 CompilerException。
  • klebervirgilio,你能稍微改进一下你的问题标题——只是标题吗?

标签: clojure


【解决方案1】:

请务必记住,Clojure 并不像大多数命令式语言那样真正执行语句。使用do,可以评估多个表达式的副作用,然后返回最后一个的值,并且像letfn 这样的几个结构包含一个隐含的do。但是除了最后一个之外的任何表达式都不可能停止评估并说“我们完成了”,除非它抛出异常。因此,整行

(if (nil? (first coll)) (do (println :ret ret) ret))

只能从它的副作用看出。它将评估为ret 中的值或nil,然后将被丢弃。

然后我们打开一个when-let。因为它是when 的变体,如果满足条件,它将返回其主体的值,否则将返回nil。主体是指向recur的指令到循环的开始,所以这个循环只能在值nil处终止。
自然的解决方法似乎是将if 表单的最后一个括号移到when-let 之后,这样整个表单就是else-case 的值。您的代码也无法为我编译,因为它在创建它的循环之外使用名称 ret,但随着它的消失,它似乎按预期工作:

(defn reverse_interleave
  [coll ss]
  (let [xx (dec ss)]
    (loop [coll (reverse coll) s xx _ss ss ret `()]
      (if (nil? (first coll)) 
        (do (println :ret ret) ret)
        (when-let [x (first coll)]
          (recur 
           (rest coll)
           (if (zero? s) xx (dec s))
           (if (or (= 1 _ss) (zero? _ss)) 0 (dec _ss))
           (if (zero? _ss)
             (map-indexed #(if (= % s) (cons x %2) %2) ret)
             (cons (list x) ret))))))))

(reverse_interleave (range 9) 3)
;;returns ((0 3 6) (1 4 7) (2 5 8))

【讨论】:

    猜你喜欢
    • 2018-02-19
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多