Fork me on GitHub
#beginners
<
2017-11-05
>
athomasoriginal00:11:07

I see there are quite a few ways to convert strings to numbers. Is there a best practice for this? The strings I want to convert are always, in this case, going to be numeric strings. My approach right now is using cljs.reader/read-string

mingp00:11:31

@tkjone It may depend on the details of what you want. But, generally speaking, I'd recommend you stick to the most restrictive thing that works. In this case, that might be Integer/parseInt / Double/parseDouble.

mingp00:11:57

read-string does a lot of different things, which can lead to some unexpected bugs later on down the line.

athomasoriginal00:11:39

yeah, thats what I was worried about. Thanks! I will update to Integer

derpocious02:11:35

Hey guys, this might be a stupid question-what are "special forms"?

derpocious02:11:05

I looked up pieces of clojure syntax like def and let, and I see in the clojure docs that they are called "special forms".

derpocious02:11:13

But I'm wondering what they are under the hood. Are they functions? Are they macros? Or is there something more "special" about them?

noisesmith02:11:00

special forms are implemented in java as part of the compiler

noisesmith02:11:50

they are outside the normal things that are all implemented as regular java classes or as clojure code - they are special symbols the compiler looks for that guide the compilation of code

noisesmith02:11:32

eg. let (or really let* which let uses) because it can create bindings, if because it can select which things execute at runtime, fn (actually, fn* which fn uses) because it can bind and capture values and make code that runs later

noisesmith02:11:22

also do and quote

derpocious03:11:55

intersting, so is it possible for me to write custom special forms in my clojure project?

phronmophobic03:11:15

not really, you’d have to fork the main clojure project to do so

phronmophobic03:11:27

the good news is that you don’t need to

phronmophobic03:11:05

everything else in clojure is defined in terms of the special forms and the basic rules for evaluation (eg. numbers evaluate to themselves)

phronmophobic03:11:29

it’s kinda neat watching the language bootstrap itself from such few primitives

phronmophobic03:11:12

even defn isn’t a special form

derpocious03:11:07

interesting. thanks!

yonatanel07:11:25

Is there some turnkey solution for attaching debug messages to functions down a call-chain, but adding extra context I only have up the call chain? Maybe something like dire lib, but having more context than the original args. Kinda like a reverse exception. For example, I have a corralation-id that I'd like included in all messages, but I don't want to propagate it everywhere.

Lucas Barbosa12:11:43

Is there a quick way to reset a namespace in nREPL using Emacs and Cider?

athomasoriginal14:11:38

I am writing some ClojureScript and I have run something every few seconds. My current implementation is using js/setInterval but I wanted to know if there is a more idiomatic way of doing this?

ajs15:11:07

Core.async with timeout channels

dpsutton15:11:57

@lvbarbosa when you are in the repl, hit , and you should see a menu pop up. there should be an option for ,refresh. in addition there is cider-refresh which should do what you are asking I think

rcustodio17:11:24

hi… is there an easy way to get the field?? (pr-str (:pred %1)) "clojure.core/contains?") the value from pred is (clojure.core/fn [%] (clojure.core/contains? % :phone))

rcustodio17:11:39

The field is :phone

rcustodio17:11:09

the full of spec (explain-data) is {:path [], :pred (clojure.core/fn [%] (clojure.core/contains? % :phone)), :val {:type "company", :document {:number "123", :x 1}}, :via [:atrium.company.validator/company], :in []}

derpocious17:11:17

hey guys, I would expect this code to print "hi 1", "hi 2", ...

derpocious17:11:39

But it just prints "hi " nil, and I'm not sure why.

derpocious17:11:44

(map (prn "hi " %) [1 2 3 4 5])

rcustodio17:11:52

The code you’ve putted above throws an error, here is the code (map #(prn "hi" %) [1 2 3 4 5])

derpocious17:11:12

Interesting, what is the reason for adding the #? Does it have to do with map returning a lazy seq?

rcustodio17:11:45

it’s a macro for (fn [& args])

rcustodio17:11:07

because in (map) the first arg is a function

rcustodio17:11:30

all maps must have the parser function

derpocious17:11:21

ahhhh ok true.

derpocious17:11:46

but then if I do (map (fn [& args] (prn "hi " %)) [1 2 3 4 5]) it doesn't print the numbers anymore

rcustodio17:11:15

because you must use the args now

rcustodio17:11:39

(get args 0)

derpocious17:11:49

(map (fn [& args] (prn "hi " (get args 0))) [1 2 3 4 5])

noisesmith18:11:57

get won't work on a list, you'll need nth

+user=> ((fn [& args] (get args 0)) "a" "b" "c")
nil
+user=> ((fn [& args] (nth args 0)) "a" "b" "c")
"a"

noisesmith18:11:25

or eg. first if you just want the first arg, or destructuring if you want to bind multiple args to names by position

noisesmith18:11:18

@rcustodio also #() isn't a macro for (fn [& args]) - it decides how many args to create based on how many you use in the body

+user=> '#(do %)
(fn* [p1__165#] (do p1__165#))
+user=> '#(do % %2 %3)
(fn* [p1__168# p2__169# p3__170#] (do p1__168# p2__169# p3__170#))
+user=> '#(do % %2 %3 %&)
(fn* [p1__173# p2__174# p3__175# & rest__176#] (do p1__173# p2__174# p3__175# rest__176#))

noisesmith18:11:42

so really the translation there is (fn [x] (prn "hi" x)) or #(prn "hi" %)

noisesmith18:11:36

or, another valid translation if you want to try a classic fp style is (partial prn "hi") which returns a function that adds all args to the arg list of prn and then calls it

noisesmith18:11:00

+user=> (map (partial prn "hi") [1 2 3])
("hi" 1
"hi" 2
"hi" 3
nil nil nil)

rcustodio18:11:12

atrium.core=> (string/join " " (re-find #":[a-z_-]+" "(clojure.core/contains? % :email)"))
": e m a i l"
why is doing that?

ajs18:11:31

and to show you don't need to refer to all the args, try this at your repl: '#(do %8)

seancorfield18:11:21

@rcustodio Not sure what you're asking there -- which part of the result don't you understand?

rcustodio18:11:08

I don’t want it to have spaces, i’m trying to parse spec errors to return it

rcustodio18:11:10

(map #(string/join " " (concat (map (fn [x] (str x)) (:path %1)) (str (re-find #":[a-z_-]+" (pr-str (:pred %1)))))) (filter #(string/includes? (pr-str (:pred %1)) "clojure.core/contains?") (:clojure.spec.alpha/problems (validator/assert {:type "company" :document {:number "123" :x 1}}))))

rcustodio18:11:42

I will use concat to get the “path” in nested, but when I use join , this happens (": c o r p o r a t e _ n a m e" ": c o u n t r y" ": b i l l i n g _ a d d r e s s" ": a d d r e s s" ": e m a i l" ": p h o n e" ":document : t y p e")

rcustodio18:11:54

":document : t y p e"

derpocious18:11:51

thanks guys that helps. Although, when I do (map (fn [x] (println "hi " x)) [1 2 3 4 5]) I see that it returns the strings but doesn't print anything to the console.

sundarj19:11:44

map is lazy: it's only meant to be used with pure functions. for side-effects (like println), use run! or mapv @U2UJ5Q8LD

sundarj19:11:26

(let [foo (map (fn [x] (println "hi " x)) [1 2 3 4 5])])
nil

(let [foo (run! (fn [x] (println "hi " x)) [1 2 3 4 5])])
hi  1
hi  2
hi  3
hi  4
hi  5
nil

seancorfield18:11:57

@rcustodio (str/join " " "Hello!") will produce "H e l l o !"

seancorfield18:11:39

re-find produces a string, not a collection. str/join expects a collection so it implicitly calls seq on its argument.

rcustodio19:11:38

How could I join a list ’(“:corporate_name” “:document :type”)

rcustodio19:11:43

I think that is the final

seancorfield19:11:03

Right, and str/join would work on that -- but you don't have that. You have a string, not a collection.

seancorfield19:11:19

Use re-seq instead of re-find and you'll get a sequence.

seancorfield19:11:32

boot.user=> (str/join " " (re-find #":[a-z_-]+" "(clojure.core/contains? % :email)"))
": e m a i l"
boot.user=> (str/join " " (re-seq #":[a-z_-]+" "(clojure.core/contains? % :email)"))
":email"

rcustodio19:11:54

Hmm, I see, thanks for the help

antique22:11:09

This feels like a dumb question but how do you express this js in clojurescript var map = new mapboxgl.Map({container: 'map',style: ''});

athomasoriginal22:11:45

You might something like this

(def map (Map. mapboxgl #js {:container "map" :style ""}))

antique22:11:59

Thanks for the help, but it’s still not working. A potential problem is that I am just pulling the js in a html script tag and trying to call the functions as no one has made a cljsjs of mapbox yet.

athomasoriginal23:11:09

@matt.a.renfro Okay, I was able to get it to work like this:

(def newmap (.-Map js/mapboxgl))

(newmap. #js {:container "map" :style ""})
If you still want to assign it to map like in your js example of var map = ... . you would do this:
(set! js/map (newmap. #js {:container "map" :style ""}))

athomasoriginal23:11:48

For future reference, CLJS should be able to call any global/namespaced JS code. This is one of its strengths. The part that confuses me, and maybe someone else could provide an answer, is how to call the constructor Map in one line. So how would one make this line work:

(set! js/map (Map. js/mapboxgl #js {:container "map" :style ""}))

athomasoriginal23:11:49

The issue is with Map. but I am not quite sure how to make it work, which is why I broke it into something I knew would work

antique23:11:13

@tkjone I’ve been looking at everything you wrote and seeing what js gets generated and I figured it out with the one liner (new js/mapboxgl.Map map-opts) Thank you for the help 🙂