Fork me on GitHub
#beginners
<
2017-11-29
>
noisesmith00:11:04

ins)user=> (run! println (range 10))
0
1
2
3
4
5
6
7
8
9
nil

smith.adriane00:11:15

and that’s what I reach for even when I’m not using core/async

seancorfield05:11:01

@clojurian The great thing about this channel is that everyone here is either a beginner or someone who has decided to be in this channel to help beginners. That means there are never any dumb questions here 🙂

abiduzair42009:11:50

Hello everybody, I have started learning clojure 2 weeks back. I tried to do few programs to get familiar with syntaxes. So i was trying to print this:

*
**
***
****
*****
******
*******
********
*********

abiduzair42009:11:34

So I wrote a program with two methods which look something like this:

user=> (defn print-row [num]
  #_=> (loop [iter 0]
  #_=> (if(< iter num)
  #_=> (do (print "*")
  #_=> (recur (inc iter)))
  #_=> (println ""))))
#'user/print-row
user=> (defn print-a-triangle [num]
  #_=> (loop [iter 0]
  #_=> (if(< iter num)
  #_=> (do (print-row iter)
  #_=> (recur (inc iter)))
  #_=> (print ""))))
#'user/print-a-triangle

sammy.castaneda9011:11:19

I’m also fairly new to clojure, but here’s how I would do it:

user=> (defn print*line[x] (cond (> x 0) (do (print "*") (recur (- x 1))) :else (print "\n")))
#'user/print*line
user=> (print*line 5)
*****
nil
user=> (defn print-pyramid [x] (cond (> x 0) (do (print-pyramid (- x 1)) (print*line x))))
#'user/print-pyramid
user=> (print-pyramid 5)
*
**
***
****
*****
nil
Note that the nil at the end is what the function returns (I think) Also, this is just copy-pasted from the terminal, no formatting

sammy.castaneda9011:11:06

let me know if something is not clear

abiduzair42011:11:54

yeah this is a good way of doing.

schmee12:11:53

here’s is how I would do it:

(run! println (map #(take % (repeat "*")) (range 1 10)))

schmee12:11:24

everytime you use recur you should try to find a solution that doesn’t use it, often it is possible to write it in a more declarative way

schmee12:11:12

just saw that this had already been posted outside the thread, sry for noise…

abiduzair42017:11:30

No problem. Thanks mate! @

gdeer8117:11:05

@ better late than never, my over-engineered solution with documentation and prose. feel free to play around with it, refactor it, or comment on it; that's what gists are for https://gist.github.com/gdeer81/6d93e6938ef0ed1a0264d4a34e635d66

abiduzair42020:11:39

Thanks @ that's great

sammy.castaneda9009:11:58

@ can you explain why recur is not a good thing to use in general?

schmee10:11:57

@sammy.castaneda90 sometimes recur is necessary, but very often there is a solution available that uses clojures sequence functions (such as take, take-while, repeatedly etc etc) and a function such as map, filter or reduce that will be shorter, more idiomatic, and easier to understand for those used to functional programming 🙂

schmee10:11:33

learning to recognize these situations and building this “inventory” of sequence functions is one of the major challenges every new clojure programmer coming from an OOP or imperative background has to face 🙂

abiduzair42009:11:38

I get a feeling that I'm not writing declarative code. this stuff up here looks more of imperative code. so i would like to ask you how could we re-write the same code in declarative manner ?

gon11:11:19

an example could be

(map #(clojure.string/join (repeat % "*")) (range 1 10))

joshkh11:11:10

regular expressions are not my forte and i'm having trouble using one in clojure. i have a regex pattern that i know works for splitting a string on spaces unless they're wrapped in quotes: [^\s"']+|"([^"]*)"|'([^']*)' here's a working example: https://regex101.com/r/qqDz70/1 the escaped pattern looks like so: #"[^\\s\"']+|\"([^\"]*)\"|'([^']*)'" and a working example uses Java's regexMatcher.find() method to build a list of matched groups: https://stackoverflow.com/questions/366202/regex-for-splitting-a-string-using-space-when-not-surrounded-by-single-or-double how can i translate this to clojure? re-find is giving me unexpected results:

user=> (re-find #"[^\\s\"']+|\"([^\"]*)\"|'([^']*)'" "one two three")
["one two three" nil nil]
thanks!

carr0t11:11:28

To expand a bit:

(defn print-a-triangle [num]
  (println
    (clojure.string/join
      "\n"
      (map #(clojure.string/join (repeat % "*"))
           (range 1 num))))

carr0t11:11:43

(formatting is weird I know, I formatted it to fit my window and then realised everyone else probably had different window widths anyway)

abiduzair42011:11:30

This is cool stuff. Thanks guys! @gon @sammy.castaneda90 @carr0t

joshkh11:11:19

this gets me a little closer but only returns the first match:

user=> (re-find (re-matcher (re-pattern "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'") "This is a string"))
["This" nil nil]

joshkh11:11:37

never mind, figured it out 🙂

user=> (let [matcher (re-matcher (re-pattern "[^\\s\"']+|\"([^\"]*)\"|'([^']*)'") "This is \"a string\" with quotes")]
  (map (partial (comp last (partial take-while some?))) (take-while (comp some? first) (repeatedly #(re-find matcher)))))
("This" "is" "a string" "with" "quotes")