【问题标题】:Recursion going infinite in clojure and not returning the values在clojure中递归无限并且不返回值
【发布时间】:2019-05-28 23:38:59
【问题描述】:

我是clojure的新手。在这里你可以看到函数 fp_fun。我正在使用这个函数,它会变成无限的。我认为它没有返回值。请让我知道答案。提前致谢

(defn fp_fun
([x y row col vec]

(if (or (< x 0) (< y 0) (>= x row) (>= y col))
  0)
(if (= vec[x y] "@") 
1)
(if (= vec[x y] "#")
0)

(def x1 (+ x 1))

(def y2 (- y 1))
(if (= ( (fp_fun x y2 row col vec)) 1  )
1)
(if (= ( (fp_fun x1 y row col vec)) 1  ) 
1)

1)
(println "!" x y)
0
) )

【问题讨论】:

    标签: recursion clojure clojurescript maze


    【解决方案1】:

    首先我将应用 emacs 自动格式化程序,然后让我们了解这里每个表达式的含义

    (defn fp_fun
      ([x y row col vec]
       (if (or (< x 0)
               (< y 0)
               (>= x row)
               (>= y col))
         0)
       (if (= vec[x y] "@")
         1)
       (if (= vec[x y] "#")
         0)
       (def x1 (+ x 1))
       (def y2 (- y 1))
       (if (= ( (fp_fun x y2 row col vec)) 1  )
         1)
       (if (= ( (fp_fun x1 y row col vec)) 1  )
         1)
       1)
      (println "!" x y)
      0) )
    

    最初这不会编译,因为在 main 函数体之后有两个额外的表达式。

    clojure 中有两种主要的表达式形式,它们定义了它们看起来基本相似的函数

    ((defn [args here]
       expression-that-returns-the-result-of-this-function-here)
    

    第二种形式,如果有不止一种方法可以使用不同数量的参数调用此函数

    (defn
      ([one-arg]
       result-expression-here)
      ([fist-arg second-arg]
       other-result-expression-here))
    

    你所拥有的是两者兼而有之,所以让我们删除最后两个表达式:

     (println "!" x y)
    

    0
    

    这给我们留下了

    (defn fp_fun
      ;; this function always takes 5 args, so prefer the basic form
      ([x y row col vec]
    
       ;; this first expression does absolutly nothing and it totally ignored
       (if (or (< x 0)
               (< y 0)
               (>= x row)
               (>= y col))
         0)
    
       ;; this next expression is also ignored, only the last value in a function determines it's result
       (if (= vec[x y] "@")
         1)
    
       ;; so this one does nothing as well
       (if (= vec[x y] "#")
         0)
    
       ;; these two define some global variables
       ;; using def inside a function is almost always better done with a let expression
       (def x1 (+ x 1))
       (def y2 (- y 1))
    
       ;; this will always run because none of the above statements cause the function to
       ;; stop and return it's value early.
       (if (= ( (fp_fun x y2 row col vec)) 1  )
         1)
    
       ;; and  then the stack will overflow before we get here
       (if (= ( (fp_fun x1 y row col vec)) 1  )
         1)
       1))
    

    接下来我们可以嵌套表达式,以便前面的表达式可以控制函数的结果:

     (defn fp_fun [x y row col vec]
       (if (or (< x 0)
               (< y 0)
               (>= x row)
               (>= y col))
         0
         (if (= (vec x y) "@")
           1
           (if (= (vec x y) "#")
             0
             (let [x1 (+ x 1)
                   y2 (- y 1)]
               (if (= (fp_fun x y2 row col vec) 1)
                 1
                 (if (= (fp_fun x1 y row col vec) 1)
                   1)))))))
    

    我希望给你一个结构来构建你的函数,重要的是每个函数只返回一个结果,这个结果是函数中最后一个表达式返回的结果。所以通常该表达式中嵌套了其他表达式。

    随着我们添加更多 if 表达式,它开始看起来有点嵌套,并且有一个常见的模式 if 后跟 = 幸运的是 clojure 有 cond,用于条件宏,用于干净地表达模式,如这个

     (cond
       (or (< x 0) (< y 0) (>= x row) (>= y col)) 0
       (= (str(get-in board [x y])) "@")          1
       (= (str (get-in board [x y])) "#")         0
       (= (find_path x (- y 1) row col board) 1)  1
       (= (find_path (+ x 1) y row col board) 1)  1
       (and (>= x 0) (< y col))  (if (= (find_path x (+ y 1) row col board) 1)
                                   1
                                   0)
       :defautl nil) ;; i'm not sure you intended to default to nil
    

    【讨论】:

    • 您好,感谢您的回答,但是如果我添加 4 个 if 语句并再次进入 for 循环怎么办。你能告诉我吗? (defn find_path [x y row col board] (if (or (&lt; x 0) (&lt; y 0) (&gt;= x row) (&gt;= y col)) 0 (if (= (str(get-in board [x y])) "@") 1 (if (= (str (get-in board [x y])) "#") 0 (if (= (find_path x (- y 1) row col board) 1) 1 (if (= (find_path (+ x 1) y row col board) 1) 1 (if (and (&gt;= x 0) (&lt; y col)) (if (= (find_path x (+ y 1) row col board) 1) 1 0) )))))))
    • 还有一件事是我仍然遇到同样的问题。如果我再添加一个条件,它将进入无限循环您第一次给我的解决方案。最终,如果我添加另一个表达式,它将进入无限循环。你现在给我的解决方案也是如此
    猜你喜欢
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 2016-04-14
    • 2016-05-27
    • 2011-02-16
    • 2022-07-21
    相关资源
    最近更新 更多