递归在 clojure 中变得无限并且不返回值
Recursion going infinite in clojure and not returning the values
我是 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
) )
首先我将应用 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) )
最初这不会编译,因为在主要函数体之后有两个额外的表达式。
clojure 中有两种主要的表达式形式定义了它们看起来基本相似的函数
((defn [args here]
expression-that-returns-the-result-of-this-function-here)
第二种形式 if for 当有不止一种方法可以使用不同的参数数量调用此函数时
(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)))))))
我希望给你一个结构来构建你的函数,重要的部分是每个函数 returns 只有一个结果,这个结果是函数中最后一个表达式返回的结果。所以通常该表达式中嵌套了其他表达式。
当我们添加更多 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
我是 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
) )
首先我将应用 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) )
最初这不会编译,因为在主要函数体之后有两个额外的表达式。
clojure 中有两种主要的表达式形式定义了它们看起来基本相似的函数
((defn [args here]
expression-that-returns-the-result-of-this-function-here)
第二种形式 if for 当有不止一种方法可以使用不同的参数数量调用此函数时
(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)))))))
我希望给你一个结构来构建你的函数,重要的部分是每个函数 returns 只有一个结果,这个结果是函数中最后一个表达式返回的结果。所以通常该表达式中嵌套了其他表达式。
当我们添加更多 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