I am new to clojure. Here you can see the function fp_fun. I am using this function and it goes to infinite. I think it is not returning the values. Please let me know the answer. Thanks in advance
(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
) )
To start with I'll apply the emacs auto formatter, then let's work through what each expression here means
(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) )
Initially this will not compile because there are two extra expressions after the main function body.
There are two main forms of the expression in clojure that defines functions they look basically like
((defn [args here]
expression-that-returns-the-result-of-this-function-here)
the second form if for when there are more than one way to call this function with different nubmers of arguments
(defn
([one-arg]
result-expression-here)
([fist-arg second-arg]
other-result-expression-here))
what you have is a bit of both so let's remove the last two expressions:
(println "!" x y)
and
0
that leaves us with
(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))
Next we can nest the expressions so that the earlier ones get to control the result of the function:
(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)))))))
I hope that gives you a structure to build your function from, the important part is that each function returns exactly one result, that result is whatever is returned by the last expression in the function. So usually that expression has other expressions nested in it.
As we add more if expressions it is starting to look a bit deeply nested and there is a common pattern of if
followed by =
fortunatly clojure has the cond
, for conditional, macro for cleanly expressing patterns like this
(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