clojure with multiple if statements - clojure

when I call the math() function, to "times", the REPL returns nil. when I use "add", it works fine... help!
(defn math [opr x y ]
(if(= opr "times")
(* x y)
)
(if(= opr "add")
(+ x y)
)
)
(math "times" 8 8)

The problem is that your function is a sequence of two-clause if-forms.
Clojure performs the elements of the sequence in turn, returning the
result of the last.
If the condition fails, a two-clause if-form returns nil.
The quickest repair is, as WeGi suggested, to nest the ifs:
(defn math [opr x y]
(if (= opr "times")
(* x y)
(if (= opr "add")
(+ x y))))
However, there are better ways:
(defn math [opr x y]
(case opr
"add" (+ x y)
"times" (* x y)))
... and, leaving C / Java idioms behind, ...
(defn math [opr x y]
((case opr
"add" +
"times" *)
x y))
... or ...
(defn math [opr x y]
(({"add" +, "times" *} opr) x y))

I like using a cond statement for multiple conditions.
;; Will return nil if the cond statement fails all the predicates
(defn math [opr x y ]
(cond (= opr "times") (* x y)
(= opr "add") (+ x y)))
WeGi is correct in that Clojure will always return the last statement in the function.

condp works when all your predicates have the same structure:
(defn my-calc
[operator x y]
(condp = operator
"times" (* x y)
"plus" (+ x y)))
=> (var user/my-calc)
(my-calc "times" 2 3)
=> 6
(my-calc "plus" 2 3)
=> 5

In Clojure the last statement is the Return Statement. So Clojure Checks for "times", even if it is true it checks then for "add" and because your call is made with "times" the second if evaluates to nil. Which is returned.
You could use do or nest your if statements to solve your Problem.

Related

Clojure eval with Math functions

I'm having problems eval-ing a LazySeq returned by Deriva:
(use 'clojure.core.matrix)
(use 'com.lambder.deriva.core)
(def f1 '(cos (* x y)))
(def f2 '(sin (* x y)))
(def f [f1 f2])
(def u ['x 'y])
(def x 4)
(def y 3)
(defn jacobian [f u]
(map #(partial-derivative f %) u)
)
Returns a LazySeq
((vector (* (* -1 (sin (* x y))) y) (* (cos (* x y)) y)) (vector (* (* -1 (sin (* x y))) x) (* (cos (* x y)) x)))
Which can be successfully eval-ed using the REPL:
(eval (into [] (jacobian f u)))
Results in the correct matrix
[[1.609718754001305 2.5315618761974763] [2.1462916720017398 3.3754158349299686]]
If I put the eval inside the clj file and lein run
(defn -main
[]
(eval (into [] (jacobian f u)))
)
I get Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol: sin in this context, compiling:(/tmp/form-init2786363415298022761.clj:1:113) since eval works in a different namespace.
Is there any way to include the clojure.math functions in the temporary namespace generated by eval? Or is there a better way to evaluate the expression?
Maybe you need to use java.lang.Math/sin function of java.
Consider using syntax-quote (`) instead quote (') to obtain fully qualified symbols that you can later eval:
's
=> s
`s
=> user/s
See more about quoting here:
https://blog.8thlight.com/colin-jones/2012/05/22/quoting-without-confusion.html

Loop destructuring in Clojure

Is there a way for destructuring the recur bindings in a loop?
So for example if i want to let y stay unchanged in
(loop [x 1 y 1] (if (< x 5) (recur (inc x) _ ) (println "result:" x y))
I know this is not possible, but how could i get a similar thing like _ in sequential destructuring for recur?
Assuming y never changes inside the loop, you can just wrap everything in a let that binds a value to y, or even place your loop in a function that receives y as an argument.
let
(let [y 1]
(loop [x 1]
(if (< x 5)
(recur (inc x))
(println "result:" x y)))
defn
(defn loop-with [y]
(loop [x 1]
(if (< x 5)
(recur (inc x))
(println "result:" x y)))

Why aren't my if statements working?

I'm extremely new to Clojure and very new to functional programming. I'm expecting this to return True or False but it's just infinitely recursing and it doesn't seem to be hitting true at all.
My test data set is this:
(def y (list 1 2 3 4)) ; and I'm passing in 2 for X.
(defn occursIn [x y]
(if (= y nil)
"False"
(if (= x first y )
"True"
(occursIn x (rest y))
)
)
)
Try this, and please pay attention to the recommended way to format your code - don't leave lonely parentheses on a line by themselves, they're not like {} in other programming languages:
(defn occursIn [x y]
(if (empty? y)
"False"
(if (= x (first y))
"True"
(occursIn x (rest y)))))
You forgot to call first on the y list, like this:
(first y)
Also, notice that the base case isn't working as you expected. Use this test instead:
(empty? y)
For completeness' sake, here's a more idiomatic way to write the same procedure - but beware of the edge case pointed by #omiel in the comments, this won't work if x is false or nil:
(defn occursIn [x y]
(if (some #(= x %) y)
"True"
"False"))
An even better solution, free from the edge case - as suggested by #mange in the comments:
(defn occursIn [x y]
(if (every? #(not= x %) y)
"False"
"True"))
Oscar's answer is correct and helpful, but I just thought I'd provide an alternate answer which demonstrates how to make a function which is closer to your original function, while still being relatively idiomatic clojure:
(defn occurs-in [needle haystack]
(if-let [[head & tail] (seq haystack)]
(if (= needle head)
"True"
(recur needle tail))
"False"))
In this case I've:
used destructuring to extract head/tail instead of using first/rest on a sequence.
used if-let to bind those names only if haystack is non-empty (that is, if (seq haystack) is truthy).
used recur instead of occurs-in to ensure that this function will be compiled to use tail call elimination, so it calls itself again without using an additional stack frame.
This may not be an issue for small inputs, but it's essential to make it work for calls like (occurs-in 1000000 (range))
In terms of idiomatic naming, see that I've used occurs-in instead of occursIn: generally lisps use hyphens (lisp-case) instead of camel case (camelCase) for names.
Before we do anything else, let's replace "True" with boolean true and "False" with boolean false. The reason for doing this will become apparent.
The fundamental problem is that rest never returns nil. It returns the empty list () instead. And (rest ()) is (). So you get an endless sequence of recursive calls that ultimately blow the top off the stack.
next does return nil where rest returns (). So use next instead of rest and at least we get an answer:
(def aList (list 1 2 3 4))
(defn occursIn [x y]
(if (= y nil)
false
(if (= x first y)
true
(occursIn x (next y))
)
)
)
(occursIn 2 aList)
; false
... but the wrong answer. Why? As #OscarLopez says, you are missing parentheses around first y to call first upon the argument y. As it stands,
(= x first y)
tests whether x, first, and y are all equal. There is only one way this can happen:
(occursIn first first)
; true
... not what we want. So, let's call first instead of comparing it:
(defn occursIn [x y]
(if (= y nil)
false
(if (= x (first y))
true
(occursIn x (next y))
)
)
)
(occursIn 2 aList)
; true
It works.
Actually, the base case does work:
(occursIn 2 ())
; false
... but only because the next call turns () into nil: queasy.
And it does misfire searching for nil:
(occursIn nil ())
; true
... because (first ()) returns nil and nil pretends to be () when asked to be a sequence (this is called nil punning), so (first nil) is nil.
So, again following Oscar, we had better test whether y is empty, not whether it is nil:
(defn occursIn [x y]
(if (empty? y)
false
(if (= x (first y))
true
(occursIn x (next y))
)
)
)
(occursIn nil ())
; false
The logic is now correct. Let's make it clearer by using and and or instead of ifs with explicit true and false results (a code smell, in my view):
(defn occursIn [x y]
(and (not (empty? y))
(or (= x (first y))
(occursIn x (next y))
)
)
)
The code reads easily now. It is to do this that we used the proper boolean values.
Only two more changes:
If you look up empty?, you'll find that (empty? y) means (not
(seq y)), so (not (empty? y)) means (not (not (seq y))), which is
equivalent to (seq y).
The recursive call to occursIn is the last thing that happens: it
is said to be in tail position. We can therefore replace it by
recur. This consumes no stack, so puts no limit on the length of
the sequence that can be searched.
So we end up with ...
(defn occursIn [x y]
(and (seq y)
(or (= x (first y))
(recur x (next y))
)
)
)

How to execute "do" on elements in a sequence in clojure

I've been trying to figure out how to execute expressions that are stored as elements in a sequence. For example, here are two expressions in a sequence:
user=> (def z '((println 'x) 'y))
#'user/z
user=> z
((println (quote x)) (quote y))
Trying to use do or doall on them doesn’t seem to do anything
user=> (do z)
((println (quote x)) (quote y))
user=> (doall z)
((println (quote x)) (quote y))
The output I am trying to get is if I were to execute them not as a sequence but as a list of arguments
user=> (do (println (quote x)) (quote y))
x
y
I tried mapping eval but that gives me an extra nil and returns a list
user=> (map eval z)
(x
nil y)
Any help would be greatly appreciated!
Do is a macro that evaluates its args, and returns the last one. let, fn, for among others contain implicit do bodies.
In your map example, the "extra nil" is the return value of the println, and it is actually the x that is extra (it is the printed output interleaved with the sequence that map returns).
Your definition of z does not create executable objects, but lists. Lists just evaluate to themselves when used.
Do you need to evaluate expressions stored as literals?
It is easy to wrap each each one as a thunk (a function of no arguments).
user> (def z [#(println 'x) #(do 'y)])
#'user/z
We can use reduce to execute them all, and only return the last one.
user> (reduce (fn [_ e] (e)) nil z)
x
y
here x is printed, and y is returned.
If you really need to use a list with eval, you can substitute it as apropriate above ((e) becomes (eval e) and z gets your original definition).
(def z '((println 'x) 'y))
Your z definition has a quote saying DON'T EVALUATE ME. So z is defined as an unevaluated expression. You want to evaluate unevaluated code so naturally you'll want to use eval; however (eval z) won't work because (println x) will print x but return the value nil. (nil y) will not work and isn't what you want.
What you do want is do; do only returns the value of the last expression so used here nil does not get in the way and you execute all your expressions. You want your end result to be:
(do (println 'x)
'y))
Let's transform z to look like that.
(cons 'do z)
=> (do (println (quote x)) (quote y))
Looking familiar? eval it!
(eval (cons 'do z))
=> x
y
You're looking to eval code here.
user=> (def z '(do (println "hey!" 'x) 'y))
#'user/z
user=> (eval z)
hey! x
y
Note that I added the do so that both expressions would be evaluated. The code in the question contained an error.
((println 'x) 'y)
First thing that would occur would be to print 'x and println returns nil, so the expression would then look like this.
(nil 'y)
nil is not a function, but it's being evaluated at the head of the list, so that's an error. Or a null pointer exception in this case.
user=> (def z '((println 'x) 'y))
#'user/z
user=> (eval z)
x
NullPointerException user/eval674 (NO_SOURCE_FILE:1)

Arithmetic and clojure functions on core.logic lvars

Two related questions in one:
Can Clojure's core.logic module perform arithmetic, logical comparison, etc, like ordinary Prolog? I am envisioning something like the following:
(defrel points person n)
(fact :bob 2)
(fact :charlie 3)
(run* [q] (fresh [x y]
(points :bob x)
(points :charlie y)
(< x y)
(== q (+ x y))))
=> (5)
In this example, neither the logical comparison (< x y) nor the attempted binding of q to (+ x y) works. I suppose that this is because I'm working with LVars, not integers at this point, and I can't make these comparisons because the symbols aren't yet bound. But it works in prolog:
points(bob, 2).
points(charlie, 3).
?- points(bob, X), points(charlie, Y), Result is X + Y.
=> Result = 5.
In a similar vein, can I somehow use Clojure functions (which return booleans or other "truthy" values) as logic predicates? In other words, to use functions to tell Minikanren which terms unify or not. Something along the lines of:
(defmagic startswithhi-o [v]
(.startsWith v "hi"))
(defrel person n)
(fact person "bob")
(fact person "hillary")
(run* [q]
(fresh [n]
(person n)
(startswithhi-o n)
(== q n)))
=> ("hillary")
If I try things like this I get errors also complaining that the LVars aren't bound. Is there a way to do this?
Lastly if anyone has read this far, I might as well ask: are there plans to incorporate probabilistic logic into core.logic, along the lines of:
http://dtai.cs.kuleuven.be/problog/ ?
I'm not holding my breath but it would be awesome!
Non-relational arithmetic is possible via project.
(run 1 [q]
(fresh [x y]
(== x 1)
(== y 2)
(project [x y]
(== q (+ x y)))))
(3)
I believe the Prolog example given is also non-relational.
The second half of your question can also be solved via project, but you must be careful that you always input a ground value.
(defn startwith [x]
(project [x]
(== true (.startsWith x "hi"))))
PS: Hold your breath for Constraint Logic Programming to come to core.logic!
I believe you have to "project" (nonrel/project) a logic variable to its binding before you can apply a function to it:
(defrel points person n)
(fact points :bob 2)
(fact points :charlie 3)
(run* [q]
(exist [x y]
(points :bob x)
(points :charlie y)
(project [x y]
(== true (< x y))
(== q (+ x y)))))
Note that exist substitutes for fresh in the original snippet and the additional argument for the fact declarations.