This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # beginners (91)
- # cider (34)
- # cljsrn (6)
- # clojure (95)
- # clojure-gamedev (4)
- # clojure-serbia (7)
- # clojure-spec (5)
- # clojure-uk (27)
- # clojurescript (42)
- # data-science (1)
- # datascript (2)
- # datomic (4)
- # duct (10)
- # emacs (11)
- # fulcro (21)
- # luminus (3)
- # lumo (24)
- # off-topic (2)
- # other-languages (2)
- # ring (2)
- # shadow-cljs (39)
- # spacemacs (9)
- # tools-deps (2)
Hi, I am having a little bit of problem with lazy sequence
I when I print I get lazy sequence. You can look here https://stackoverflow.com/questions/50538819/lazy-sequence-clojure
(require '[clojure.string :as str]) ;;READ CUST.TXT (def my_str(slurp "cust.txt")) (defn esplit [x] (str/split x #"\|" )) (def cust (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n"))))))) ;;func to print (for [i cust] (do (println (str (subs (str i) 2 3) ": [" (subs (str i) 5 (count (str i))))))) ;;CODE TO SEARCH CUST (defn cust_find [x] (for [i cust :when (= (first i) x )] (str (nth i 1)))) (type (cust_find "2")) ;;READ PROD.TXT (def my_str(slurp "prod.txt")) (def prod (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n"))))))) ;;func to print (for [i prod] (do (println (str (subs (str i) 2 3) ": [" (subs (str i) 5 (count (str i))))))) ;;CODE TO SEARCH PROD (defn prod_find [x y] (for [i prod :when (= (first i) x )] (nth i y))) (prod_find "2" 1) (def my_str(slurp "sales.txt")) (def sales (vec (sort-by first (vec (map esplit (vec (str/split my_str #"\n"))))))) ; (for [i (range(count sales))] (cust_find (nth (nth sales i) 1))) ; (defn fill_sales_1 [x] ; (assoc x 1 ; (cust_find (nth x 1)))) ; (def sales(map fill_sales_1 (sales))) (def sales (vec (for [i (range(count sales))] (assoc (nth sales i) 1 (doall (str (cust_find (nth (nth sales i) 1)))))))) ; (for [i (range(count sales))] (assoc (nth sales i) 2 (str (prod_find (nth (nth sales i) 2) 1)))) (for [i sales] (println i))
Hi @kushalkanungo1991 -- Welcome to Clojure! You're stumbling over one of the things that people from an imperative background find most confusing when they are first learning...
If you want to do something with side-effects -- where you essentially throw the result away -- you want
(doseq [i sales] (println i))
You're also approaching the overall implementation in a way that suggests an imperative, step-by-step program, using
def to "set variables" as you go through the file which is likely to lead you into problems.
Try to avoid using
def to create Vars that are bound to expressions: those all execute when you load the namespace and it's much better/safer to avoid side-effects when you load a namespace. Make all of them functions, and call them as needed.
Also look at
let as a way of setting up local bindings of name to expression values (`def` creates global names).
There are a lot of places where you're calling
str) that you won't need as you start to understand how sequence functions are used.
Could someone please walk me through how this is calculating the result? It is the
apply that is throwing me here:
So the result of the call
(defn add-points [& pts] (vec (apply map + pts)))
(add-points [5 10] [3 8])is
[8 18]. I'm not sure how mapping the apply is taking the first argument of each vector and adding them, and then the same with the second element of each vector.
Does it already make sense to you why
(map + [[5 10] [3 8]]) returns
(8 18), or would it help to walk through that, too?
although running that in the repl gives a "cannot cast clojure.lang.PersistentVector to java.lang.Number"?
So most often you will see
map used with just 2 arguments: a function (like
+) and a sequence, e.g.
(map + [3 5]), which returns the sequence
(3 5). Here map is causing the function calls
(+ 3) which returns 3 and
(+ 5) which returns 5.
map can also take any number of sequences, like this:
(map + [5 10] [3 8]). In a case like that, map will make these function calls instead:
(+ 5 3) then
(+ 10 8), calling the function given to map with the first element of each sequence, then with the second element of each sequence, etc.
yes. And it can do that given any number of sequences, e.g.
(map + [5 10] [3 8] [-1 2]) return
add-points has parameters
[& pts], where the
& means that any number of parameters can be supplied after that point, and they are all collected into a sequence and bound to the local
apply, the call to
map would have only 2 arguments, the function
+ and the sequence
apply, the call to
map now has n+1 arguments: the function
+ and one argument for each element of the sequence
haha... yeah I got what you meant haha..... you mean you don't have answers to every possible question scripted? 😛
how do i use clojure 1.9?
this is my lein -v
Leiningen 2.8.1 on Java 1.8.0_171 OpenJDK 64-Bit Server VM
you could set your project.clj to use
[org.clojure/clojure "1.9.0"] instead of
they upped the default from 1.8 to 1.9 https://github.com/technomancy/leiningen/issues/2373
i am aware of that 😄 but is string you are using there gotten from some unsafe source - parseLong
@lockdown- You couldn't
Long/parseLong to a sequence of strings --
apply unrolls the arguments so your call would be equivalent to
(Long/parseLong "1" "2") which is not legal.
parseLong can take a second argument --
radix -- but it must be an
@lockdown- That's a valid concern. Reading Clojure gets easier with experience/practice. I would probably write a small wrapper, depending on what I wanted the behavior to be on a parse failure, e.g.,
(defn ->long ([x] (->long 0)) ([x default] (if (number? x) (long x) (try (Long/parseLong x) (catch Throwable _ default)))))
(map ->long ["1" "2"])
(map #(->long % ::invalid) ["1" "not-a-number" "2"])
@lockdown- A test? Well, your choices with parsing are either: throw an exception or return some sort of "invalid" value. The best choice in any given situation depends on what you plan to do with the data. If you want to parse every element in a sequence and just throw away the "bad" ones, returning a flag value is useful, because then it's "just data" and you can do what you want with it. If you throw an exception, you have to decide whether you want to give up all your processing or try to catch that and does something with it etc.
If you run
(map #(Long/parseLong %) some-large-collection) and the 1,000th element can't be parsed... you get nothing (but an exception). If you return some sort of value instead of throwing an exception, you still have the option of getting those 999+ valid values back.
(you could even just return the exception itself -- as a value -- and then filter those out or report on them or whatever)
(map #(try (Long/parseLong %) (catch Throwable t t)) ["1" "not-a-number" "2"]) -- then
(remove (partial instance? Throwable) ..) would give you just the numbers and
(filter (partial instance? Throwable) ..) would give you the exceptions (to report on etc)
clojure.core also contains
Throwable->map so you can convert an exception into a Clojure data structure for programmatic analysis etc.
@lockdown- The cheatsheet currently contains about 85% of the functions, macros, and Vars defined in core. I believe this might be the up to date list of things in core that are not in the cheatsheet: https://github.com/jafingerhut/clojure-cheatsheets/blob/master/src/clj-jvm/TODO.txt#L209-L391
@andy.fingerhut very useful thanks, (and you just cleared the meaning of the list with a commit 😉 ) - is there any reason you specified a range in the github link?
I specified a range because before I did the commit, it was the complete list of things not on the cheatsheet. Now the range is incomplete, but at least it points you in the correct part of the linked file.
I know there's a performance penalty but is there an idiomatic way to prepend to a vector and maintain the vector?
@lockdown- If the vector returned from the fn is small, I doubt it will be much of an overhead.
FWIW, I used
criterium and timed a few options:
user=> (bench (vec (cons 'foo big-vec))) Evaluation count : 3769620 in 60 samples of 62827 calls. Execution time mean : 16.200287 µs Execution time std-deviation : 312.821213 ns ... user=> (bench (into ['foo] big-vec)) Evaluation count : 4092720 in 60 samples of 68212 calls. Execution time mean : 14.736989 µs Execution time std-deviation : 72.225193 ns ... user=>
big-vecbeing a 1,000-element vector.
I think the answer to the original question is - no, it’s not idiomatic to pretend to a vector