You can undo the knots in the flow of control by refactoring some of the code out into a separate function; this will work in C and in Clojure too.
Here's my stab at it. Hand translated and not tested, so it could be buggy.
(defn foo []
(let [foo2 (fn []
(if cond3 "something again")
(bar))]
(if somecondition
(do
"some code"
(if cond2
-1
(do
"some code again"
(foo2))))
(foo2))))
UPDATE with some explanation.
Because ajay asked, I'd like to expose a little of the thinking that led me to the above solution.
; shortcuts
c1 = somecondition
c2 = cond2
c3 = cond3
; truth table (this helped me a bit with my thinking but didn't go directly into the design)
c1 c2 c3 results
----------------
T T . "some code" -1
T F T "some code" "some code again" "something again" bar()
T F F "some code" "some code again" bar()
F . T "something again" bar()
F . F bar()
The way Clojure works, there's no "return". A Clojure function always returns the last expression to be evaluated. If we want to produce the same side effects (from "some code", "some code again" and "something again") and result as the C/Java code, we need to make the code run in such a way that the result is really the last thing executed.
The only way to be able to return -1
is to rework the code so there is a branch from the start that ends - really ends - at "-1". That means that the following code must be called from within one of the other IF
branches. In fact, it appears in two branches. So as not to have to repeat the code, I pulled it into a function of its own.
Here's the translation of my code to pseudocode:
function foo2:
if c3 then
"something again"
endif
bar()
function foo:
if c1 then
"some code"
if c2 then
-1 <-- end 1
else
"some code again"
foo2 <-- end 2
endif
else
foo2 <-- end 3
endif
end 1 is your tricky "return -1
". end 2 includes "some code again
", end 3 doesn't. Both end 2 and end 3 test c3, maybe do "something again
" and then return bar()
.