Question:How to I turn Read-Line into a usable vector to pass in to another function to do work.
(defn iAcceptUserInputAsAVector [a b c] ( )) ; I do work with the userInput as a vector
(defn input []
(let [userKeyboardInput ( read-line)]
(
[userKeyboardInput]; doesnt work I tried (vector userKeyboardInput)
)
)
)
Update 1: My Progress so far thanks to noisesmith
(defn input []( let [userKeyBoardInput [(read-line)]]
(println userKeyBoardInput)
))
Update 2 My current solution and working... I imagine it can be done so much better
(defn split-by-whitespace [s]
(clojure.string/split s #"\s+"))
(defn input []
( let [userKeyBoardInput [(split-by-whitespace(read-line))]]
;Then insanity below is because I have to convert to integers, list then a vector. Why? map returns list
;which I dont need instead I need a vector []
;Also the initial entry is returned as [[]] which I need to convert to [] for map to be able to take
;it as parameter. There probably a better way. Show me...
(def x (into[](map #(Integer/parseInt %) (into [](flatten [userKeyBoardInput])))))
(println x)
(myLoopFunc x); basically it takes my vector and does something .. not important
))
Parenthesis are not a grouping construct in Clojure.
There are two major errors in your code:
((read-line)) this gets a string via read-line and then attempts to execute it. This will fail, strings do not implement IFn.
([userKeyboardInput]) if the code even got this far, this would fail as well, because you can't call a vector as a function without providing any arguments.
In clojure, wrapping something in parens usually means you want to execute it as a function. Adding extraneous parens will easily break things.
I will comment on how to improve your current solution (source code comments removed, linenumbers added):
01: (defn split-by-whitespace [s]
02: (clojure.string/split s #"\s+"))
03:
04: (defn input []
05: ( let [userKeyBoardInput [(split-by-whitespace(read-line))]]
06: (def x (into[](map #(Integer/parseInt %) (into [](flatten [userKeyBoardInput])))))
07: (println x)
08: (myLoopFunc x)
09:
10: ))
The function split-by-whitespace looks good. Note that it already returns a vector. (Suppose read-line returned "6 34 12". Then split-by-whitespace will give you ["6" "34" "12"]). So when you call it in line 5, you do not need the [] around your call, because you don't want a vector in a vector. Therefore, you no longer need flatten. You can just map over the vector you already have. Then a function that did the desired transformation for you would look like this:
(defn string->number-vector ; name is verbose but meaning is clear :)
[s]
(into []
(map #(Integer/parseInt %)
(split-by-whitespace s))))
And you might call it with (myLoopFunc (string->number-vector (read-line))).
Related
I have a list of I/O functions to run in a game, but need to collect the value from a function somewhere in the middle of the do
(defn setup-steps [game-state]
(do (io/clear-screen)
(print-welcome-message)
(initial-setup) ;; value to be collected
(io/clear-screen)
(io/print-board game-state)))
Is there a smart way to return the value from somewhere in the middle of a do?
Down the line, I am using the return value of setup-steps to update an atom, like so:
(defn game-loop [game]
(while (:game-in-progress? #game)
;; Here is where I am using the results
(->> (s-io/setup-steps #game) (state/updater game))
(while (:game-in-progress? #game)
(->> (m-io/turn-steps #game) (state/updater game)))
(->> (eg-io/end-game-steps #game) (state/updater game)))
(eg-io/exit-game))
Where
(defn updater
"Updates the game state.
This is the only place where the game atom is modified."
[game update-params]
(swap! game merge update-params))
I'm sure you could write a macro for this, but I don't really understand macros yet.
And maybe I am thinking about this the wrong way... Is it more idiomatic to dow the swap!ing inside setup-steps?
Any reason you can't assign the result in a let and return it at the end of the function?
(defn setup-steps [game-state]
(io/clear-screen)
(print-welcome-message)
(let [v (initial-setup)] ;; value to be collected
(io/clear-screen)
(io/print-board game-state)
v))
EDIT: Got rid of the redundant do that Ryan Asensio mentioned.
Fundamentally the only way to do this is with let, as clartaq shows. But if you find this distasteful there are a number of ways you could wrap this up in a macro to make it prettier to look at and also more clear about what you're doing. Here is the simplest one, which I like to call returning:
(defmacro returning [x & more]
`(let [x# ~x]
(do ~#more)
x#))
(defn foo []
(x)
(y)
(returning (z)
(a)
(b)))
The do in returning is of course superfluous, but I think it's still useful to emphasize that more is evaluated only for side effects.
So I know this isn't the best method of solving this issue, but I'm trying to go through a list of lines from an input file, which end up being expressions. I've got a list of expressions, and each expression has it's own list thanks to the split-the-list function. My next step is to replace characters with id, ints with int, and + or - with addop. I've got the regexes to find whether or not my symbols match any of those, but when I try and replace them, I can only get the last for loop I call to leave any lasting results. I know what it stems down to is the way functional programming works, but I can't wrap my head around the trace of this program, and how to replace each separate type of input and keep the results all in one list.
(def reint #"\d++")
(def reid #"[a-zA-Z]+")
(def readdop #"\+|\-")
(def lines (into () (into () (clojure.string/split-lines (slurp "input.txt")) )))
(defn split-the-line [line] (clojure.string/split line #" " ))
(defn split-the-list [] (for [x (into [] lines)] (split-the-line x)))
(defn tokenize-the-line [line]
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
(for [x line] (clojure.string/replace x readdop "addop")))
(defn tokenize-the-list [] (for [x (into [] (split-the-list) )] (tokenize-the-line x)))
And as you can probably tell, I'm pretty new to functional programming, so any advice is welcome!
You're using a do block, which evaluates several expressions (normally for side effects) and then returns the last one. You can't see it because fn (and hence defn) implicitly contain one. As such, the lines
(for [x line] (clojure.string/replace x reid "id"))
(for [x line] (clojure.string/replace x reint "int"))
are evaluated (into two different lazy sequences) and then thrown away.
In order for them to affect the return value, you have to capture their return values and use them in the next round of replacements.
In this case, I think the most natural way to compose your replacements is the threading macro ->:
(for [x line]
(-> x
(clojure.string/replace reid "id")
(clojure.string/replace reint "int")
(clojure.string/replace readdop "addop")))
This creates code which does the reid replace with x as the first argument, then does the reint replace with the result of that as the first argument and so on.
Alternatively you could do this by using comp to compose anonymous functions like (fn [s] (clojure.string/replace s reid "id") (partial application of replace). In the imperative world we get pretty used to running several procedures that "bash the data in place" - in the functional world you more often combine several functions together to do all the operations and then run the result.
I am trying to read numbers from input and printing them back in Clojure till I read the number 42. A really basic thing to make sure I know how to read input. Taken from codechef
I have written this program. Might not be good clojure.
(defn universe
[]
(let [num (line-seq (java.io.BufferedReader. *in*))]
(if (not= num 42)
(do
(println num)
(recur (universe))
)
)
)
)
My understanding is that line-seq lazily evaluates from whatever reader is given. In this case the standard input.
So I have let it be num. Then if num is not 42 I print it and then recursively call universe. But it throws exception
Mismatched argument count to recur, expected: 0 args, got: 1,
I have seen an example and recur does take an argument. Looking at the official documentation I couldn't see the syntax for this. So why am I getting this error?
recur does not take the name of the location to recur to. Instead the recur special form jumps back up to the closest function or loop expression, whichever is closer. It then passes it different arguments. This lets you go through the same block of code repeatedly as you work through the data, and there is no function call overhead.
In your case it's recurring up to the function call:
(defn universe [] ...
and trying to pass it an argument, which fails because universe, the function, does not accept any arguments. perhaps you intended to put a loop expression around the if?
user> (defn universe
[]
(let [numbers (line-seq (java.io.BufferedReader. *in*))]
(loop [numbers numbers]
(let [num (first numbers)]
(if (not= (Integer/parseInt num) 42)
(do
(println num)
(recur (rest numbers))))))))
#'user/universe
user> (universe)
3 ;; typed 3
nil ;; typed 42
or where you intending to recur back to the top of the function, in which case just call (recur) instead of (recur universe)
I am missing an important point about defmulti and defmethod. I've read several books' explanation of defmulti, and I'm still confused.
I want to get a random value depending on whether or not it's a transaction or an amount like 100.00
I want to call (random-val) and either get back an avail-trans value or random decimal amount. I have experimented with putting the functions in a map, but I get the same value back for avail-trans, a \B.
(def^:dynamic map-val {:trans (random-trans) :amt (random-amount)})
Here is the smallest amount of code to show what I'm doing that is not working. I'd appreciate any pointers or help.
(def^:dynamic avail-trans [\B \W \D \A])
(defn random-trans
[]
(nth avail-trans (.nextInt random (count avail-trans))))
(defn random-amount
[]
(float (/ (.nextInt random (count (range 1 10000))) 25 )))
The following is not constructed correctly, but I'm not sure why or how to fix the problem:
(defmulti random-val :val-type)
(defmethod random-val :trans []
(random-trans))
(defmethod random-val :amt []
(random-amount))
Calling (random-val :trans) results in this error:
java.lang.IllegalArgumentException: No method in multimethod 'random-val' for dispatch value: null (NO_SOURCE_FILE:0)
A multimethod is created with defmulti; you're doing that right. defmulti needs a name and a dispatch function (and a docstring, plus some options, if you desire, but forget about those).
(defmulti random-val identity)
When you implement the multimethod with defmethod, you need to specify the name of the multimethod you're implementing, the dispatch value it should match, and then the function tail (arglist plus whatever you want it to do).
(defmethod random-val :trans [t] (random-trans))
(defmethod random-val :amt [t] (random-amt))
You're getting java.lang.IllegalArgumentException: No method in multimethod 'random-val' for dispatch value: null (NO_SOURCE_FILE:0) because when the dispatch function you assigned random-val, :val-type is applied to any other keyword, it gives you null. When Clojure tries to look up a method to match that dispatch value, it fails.
But even if it didn't fail there, your defined methods have 0 arity (take no values), so you need to fix that, too (done above).
Finally, this doesn't seem like a good use for protocols. Just use your two separate function, random-amount and random-trans.
Note, too, that Clojure's website has a good explanations of multimethods.
You get the same value back every time for avail-trans '\B' because you are evaluating the function when you associate it in your map map-val, thus binding the value B forever against the key ':trans' in map-val, instead of the function randon-trans itself.
If you remove the parens around your function assignments in map-val, it will work just fine. Then there is no need for multimethods, which are probably not appropriate as #isaac-hodes suggests.
This works for me in the REPL:
(def avail-trans [\B \W \D \A])
(def random (java.util.Random.))
(defn random-trans []
(nth avail-trans (.nextInt random (count avail-trans))))
(defn random-amount []
(float (/ (.nextInt random (count (range 1 10000))) 25 )))
; No parens around function names
(def map-val {:trans random-trans :amt random-amount})
(println ((:trans map-val)))
(println ((:amt map-val)))
I have a sequence (foundApps) returned from a function and I want to map a function to all it's elements. For some reason, apply and count work for the sequnece but map doesn't:
(apply println foundApps)
(map println rest foundApps)
(map (fn [app] (println app)) foundApps)
(println (str "Found " (count foundApps) " apps to delete"))))
Prints:
{:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(2)>} {:description another descr, :title apptwo, :owner jim, :appstoreid 1235, :kind App, :key #<Key App(4)>}
Found 2 apps to delete for id 1235
So apply seems to happily work for the sequence, but map doesn't. Where am I being stupid?
I have a simple explanation which this post is lacking. Let's imagine an abstract function F and a vector. So,
(apply F [1 2 3 4 5])
translates to
(F 1 2 3 4 5)
which means that F has to be at best case variadic.
While
(map F [1 2 3 4 5])
translates to
[(F 1) (F 2) (F 3) (F 4) (F 5)]
which means that F has to be single-variable, or at least behave this way.
There are some nuances about types, since map actually returns a lazy sequence instead of vector. But for the sake of simplicity, I hope it's pardonable.
Most likely you're being hit by map's laziness. (map produces a lazy sequence which is only realised when some code actually uses its elements. And even then the realisation happens in chunks, so that you have to walk the whole sequence to make sure it all got realised.) Try wrapping the map expression in a dorun:
(dorun (map println foundApps))
Also, since you're doing it just for the side effects, it might be cleaner to use doseq instead:
(doseq [fa foundApps]
(println fa))
Note that (map println foundApps) should work just fine at the REPL; I'm assuming you've extracted it from somewhere in your code where it's not being forced. There's no such difference with doseq which is strict (i.e. not lazy) and will walk its argument sequences for you under any circumstances. Also note that doseq returns nil as its value; it's only good for side-effects. Finally I've skipped the rest from your code; you might have meant (rest foundApps) (unless it's just a typo).
Also note that (apply println foundApps) will print all the foundApps on one line, whereas (dorun (map println foundApps)) will print each member of foundApps on its own line.
A little explanation might help. In general you use apply to splat a sequence of elements into a set of arguments to a function. So applying a function to some arguments just means passing them in as arguments to the function, in a single function call.
The map function will do what you want, create a new seq by plugging each element of the input into a function and then storing the output. It does it lazily though, so the values will only be computed when you actually iterate over the list. To force this you can use the (doall my-seq) function, but most of the time you won't need to do that.
If you need to perform an operation immediately because it has side effects, like printing or saving to a database or something, then you typically use doseq.
So to append "foo" to all of your apps (assuming they are strings):
(map (fn [app] (str app "foo")) found-apps)
or using the shorhand for an anonymous function:
(map #(str % "foo") found-apps)
Doing the same but printing immediately can be done with either of these:
(doall (map #(println %) found-apps))
(doseq [app found-apps] (println app))