Fork me on GitHub
#beginners
<
2017-05-16
>
Petrus Theron10:05:31

Getting this exception with Boot+Reagent on ClojureScript reload: Uncaught TypeError: goog.dom.htmlToDocumentFragment is not a function I did some digging and found some things about an older version of cljs, but I can't tell if this is my bug or a weird dependency mixture issue. Full exception:

Uncaught TypeError: goog.dom.htmlToDocumentFragment is not a function
    at adzerk$boot_reload$display$construct_hud_node (display.cljs:93)
    at adzerk$boot_reload$display$insert_container_BANG_ (display.cljs:104)
    at display.cljs:126
    at core.cljs:4311
    at Function.cljs.core.swap_BANG_.cljs$core$IFn$_invoke$arity$2 (core.cljs:4311)
    at cljs$core$swap_BANG_ (core.cljs:4304)
    at adzerk$boot_reload$display$display (display.cljs:120)
    at client.cljs:37
    at cljs.core.MultiFn.G__11975__3 (core.cljs:10168)
    at cljs.core.MultiFn.G__11975 [as call] (core.cljs:10277)

stardiviner11:05:12

I have a hash map like: {"Number" "1", "Cluster" "M2"}, I'm using map on it like this: (map #(% "Cluster") my-map-data). There there any other ways better than #(% "Cluster")?

gekkostate13:05:03

@stardiviner Are you trying to get the value for the keys?

gekkostate14:05:22

You can try (vals m)

gekkostate14:05:41

In Clojure you can't modify the original map (or any "original" variable). What you want to try and do is make functions which you can plug into other functions to get the result you are looking for.

stardiviner14:05:29

In this case, what should I do?

gekkostate14:05:59

Are you trying to add the values of one map to another?

dpsutton14:05:14

this is frequencies, i believe

stardiviner14:05:54

No, I created an empty map, then want to use a key as a number counter for counting how many times the character occurs.

stardiviner14:05:05

Leaving for a while.

gekkostate14:05:24

Yea, @dpsutton is correct. Use (frequencies m) and that will get you your result. So (frequencies temp-collection) will return {"A" 3, "B" 1, "C" 2, "D" 1}

vitruvia17:05:09

What is the quickest way to test if any value in a sequence equals a number? Like in (or (= 5 (1 2 3 4 5))) but this example doesn't work

marcusf17:05:13

Hi, I'm new to Clojure and I have a silly problem.

(defn currTime[]
	(.format (new java.text.SimpleDateFormat "hh:mm") (java.util.Date.)))

(defn log[text]
	(println (apply str [(currTime) " " text])))

(def awesomebutton (button :text "Sometext"))

(listen awesomebutton :action (fn [e] ((log "clicked!"))))
When clicking the button, the text prints but also causes a nullpointer exception
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
I've no idea what's wrong

sassafras17:05:30

@vitruvia one way: (some #{num} '(num1 num2 num3 etc)) will return num if it's there

sassafras17:05:38

or nil otherwise

john17:05:26

@marcusf Try changing ((log "clicked")) to (log "clicked") /wild guess

marcusf17:05:50

Thanks @john, that works

matan20:05:36

okay this is silly, but I can't println from one of my functions, even when it begins with a doall

matan20:05:42

I need that to debug one function the dirty way, even though usually I'd have tests to avoid the need in the first place.

matan20:05:44

if anyone uses a library that drops you into a repl from a line of code of your choice, that would be a nice replacement, but otherwise I wonder what might it potentially be with doall not working for me.. and believe me this function gets called (verified that by replacing the println with throwing an exception).

matan20:05:12

also by the docs of doall (https://clojuredocs.org/clojure.core/doall) I'd assume that the println would happen by the time my program finished, even if not right away.

matan20:05:53

I'm obviously missing something :snow_cloud:

dpsutton20:05:55

I believe your issue is that str doesn't force lazy sequences, which your filters are

dpsutton20:05:14

use clojure.string/join

noisesmith20:05:54

@matan my favorite way to debug is (defonce debug (atom [])) at the top level, then (swap! debug conj {:context :some-context :a a :b b ... ...}) inside my function

noisesmith21:05:15

that gives me actual data I can play with in my repl - including evidence of how many times the function has run

noisesmith21:05:37

also, one of the things you could capture in the hash-map is *out* - maybe something else is binding it weirdly?

vitruvia21:05:24

Can you use a varible assigned with let to create a second variable? Like (let [a b c (* 2 a)])

dpsutton21:05:37

@matan i'm assuming you're seeing something similar to this

vitruvia21:05:42

nvm I already tested my question, the answer is yes

matan21:05:10

@dpsutton I am using an exception to see what's going on (pretty silly). E.g. this works.

(throw (Exception. (str (row-examination (first (filter #(= (key (first %)) "19329") gold))
                                                 (first (filter #(= (key (first %)) "19329") test))))))
Not sure about your code snippet

matan21:05:36

Other than using an exception not sure how to apply doall so that it works

dpsutton21:05:54

where are you using doall? i didn't see it in your code

dpsutton21:05:24

but str doesn't realize a lazy sequence. you should use clojure.string/join to get all of them

matan21:05:17

what is the closest point to where one wants a side-effect to happen, that a doall wrapper should be placed?

dpsutton21:05:52

can you post your example?

dpsutton21:05:56

something a bit more concrete?

dpsutton21:05:25

because i believe that doall will do what you expect it to except coerce lazy sequences of strings. so i want to see more concretely what you're doing

dpsutton21:05:21

first thing, never return true if something and false if not something, just return the something

dpsutton21:05:31

(every? identity ((juxt straight? flush?) hand)) should be a "clever way to do it"

dpsutton21:05:59

juxt does exactly what you were thinking there, distributing hand across the functions

dpsutton21:05:19

since and is a macro we can't apply it here though

noisesmith21:05:46

(and (straight? hand) (flush? hand)) seems like a winner to me

noisesmith21:05:55

it returns the right value, it’s easy to read

vitruvia21:05:22

@dpsutton thanks but what is wrong with returning true? The exercise asks me to return either true or false

noisesmith21:05:39

what do straight? and flush? return?

noisesmith21:05:49

I would assume by name they return true or false

noisesmith21:05:58

if so, the and will also return true or false

vitruvia21:05:02

yes they do

vitruvia21:05:07

I see what you mean

noisesmith21:05:22

@vitruvia the problem with (if true true false) and (if false true false) is both can just be replaced by the condition

noisesmith21:05:39

it’s needlessly verbose - provides no meaning, and doesn’t change the result

matan21:05:02

@dpsutton I wrap my entire function with doall the same one copied above, I can copy again

matan21:05:18

It would be very hard to reduce the problem to an example

vitruvia21:05:30

But this is only the case if the functions being called return true or false, right? As in the case of straight? and flush?

dpsutton21:05:54

you'll get into truthiness issues. up to you how you want to keep your functions

dpsutton21:05:37

matan, that function you pasted earlier didn't have balanced parens and i didn't a doall. just wondering if you could give me a complete picture

noisesmith21:05:50

@vitruvia the accepted rule is that any function ending in ? should return true or false

noisesmith21:05:56

which is why we assume the if is redundant

vitruvia21:05:21

Thanks again

noisesmith21:05:48

it’s possible to use boolean to force a “truthy” or “falsey” result into a real true/false where that matters

noisesmith21:05:00

,(map boolean [nil false true 1 :a])

vitruvia21:05:32

where would this be useful?

matan21:05:54

the println forms won't work regardless how I wrap with doall. I resort to keyhole debug by uncommenting the exception form.

dpsutton21:05:06

what do you wrap with doall?

matan21:05:20

tried several ways, which is the right one?

dpsutton21:05:57

(let [rows (doall (map row-examination gold test)) ... is the one that seems to actually do work here

dpsutton21:05:03

but row-examinations has no println's in it so you wohn't see anything

dpsutton21:05:25

but since you filter it multiple times i can't imagine its not realized

matan21:05:11

my general question is ― what is the most closest point where doall wrapping should be performed, relative to where one wants to execute side-effects

dpsutton21:05:01

i don't think that's a well-formed statement. doall by its signature can only take a single collection. so point to where a collection is created in your code

matan21:05:50

okay, thanks!

matan23:05:05

mystery solved: I was using with-out-str on the function that kicks off the rest of the functions cascade. my printlns ended in an output file.

(spit (io/file "output" "raw.edn") (with-out-str (pprint output)))

matan23:05:20

I did that to get EDN nicely printed to a file, using pprint. Obviously that negates the ability to println anywhere inside lazy collections that are evaluated in the lazy EDN collection this is printing. 🙈

noisesmith23:05:19

@matan remember I suggested saving the value of *out* to an atom? that would have revealed it

matan23:05:42

I missed that message doh!

matan23:05:30

okay, digging this @noisesmith

matan23:05:23

for further safety, is there any API for doing what pprint is doing, as string building, without sending it to stdout like pprint does? resorting to with-out-str seems like something I might wish to avoid.

noisesmith23:05:00

pprint takes a “writer” arg

> (doc clojure.pprint/pprint)
-------------------------
clojure.pprint/pprint
([object] [object writer])
  Pretty print object to the optional output writer. If the writer is not provided,
print the object to the currently bound value of *out*.
nil

noisesmith23:05:32

so you can give it a StringWriter or whatever

matan23:05:36

mmmm right, sorry about that one

matan23:05:25

how would that work with spit?

noisesmith23:05:42

peregrine.circle=> (def sw (java.io.StringWriter.))
#'peregrine.circle/sw
peregrine.circle=> (pprint {:a 0 :b 1 :c 2 :d 3} sw)
nil
peregrine.circle=> (str sw)
"{:a 0, :b 1, :c 2, :d 3}\n"

noisesmith23:05:38

you can provide a stringwriter to spit, instead of a string, it just works

noisesmith23:05:54

peregrine.circle=> (spit "foo.edn" sw)
nil
peregrine.circle=> (slurp "foo.edn")
"{:a 0, :b 1, :c 2, :d 3}\n"

mobileink23:05:57

@noisesmith for us slowbies, can you please give an example of how you then use debug? my debug strategy is "sprinkle code liberally with (log/trace... ); season to taste." works but not so optimal.

noisesmith23:05:55

@mobileink (-> debug deref count) (-> debug deref peek keys) (-> debug deref peek :foo type) etc.

noisesmith23:05:06

this is all done with up-arrow and editing the end of the line, of course

noisesmith23:05:24

I very quickly get the info I want, then I can use it with the functions in the repl, fix my code, etc.

noisesmith23:05:00

or even (-> debug deref (->> (map :foo) frequencies)) - to see all the data coming in in a bigger picture

mobileink23:05:15

good demo of the usefulness of threading macros - easy to throw another fn in the chain

noisesmith23:05:28

exactly, it makes interactive exploration very easy

noisesmith23:05:50

of course it can also help to do a (def foos *1) at some point

noisesmith23:05:04

to capture something of interest with the help of the repl

noisesmith23:05:49

also, you can spit the data you captured in the debug atom somewhere into an edn file, and slurp it into a unit test 😄

mobileink23:05:07

i'm in! dadgummit now i'm gonna have to rewrite all my log stuff.

matan23:05:22

I'm still not seeing the light on this debugging scheme, probably a couple of hours debugging with exceptions throwing, has taken its toll...

noisesmith23:05:33

I mean, logging is still useful, I just find actually capturing the data useful when fixing something specific

noisesmith23:05:17

@matan the idea is that if you capture the data as data, instead of (just?) printing, you can do smarter things with it, and the language can help you

noisesmith23:05:29

instead of like trying to count parens to be sure what the structure is

noisesmith23:05:16

I log for things that will be interesting whether I’m debugging something right now or not, but if I want to know what’s happening to data in a specific context, nothing beats being able to directly use the data in the repl

mobileink23:05:23

idle question: the sayid debugger guy was wondering why he's not getting more love. my theory: the repl plus techniques like this almost eliminate the need for a debugger. do you ever use a debugger? i never have for clojure.

matan23:05:26

that idea I got alright

matan23:05:19

> but if I want to know what’s happening to data in a specific context, nothing beats being able to directly use the data in the repl that sounds like there's a secret drop-to-repl macro to embed

matan23:05:33

some languages have that actually

noisesmith23:05:50

@mobileink I tried, but due to some details about how clojure handles and clears locals etc. I find just being able to access the data and fiddle with it much more useful compared to stopping the world to interact with a breakpoint

noisesmith23:05:42

@matan but I don’t want to stop the world - since my data is immutable I can just capture it and poke at it later

mobileink23:05:37

that debug atom trick really deserves a prominent place on the "Debugging Clojure Code" page.

noisesmith23:05:53

I didn’t make it up, I forget where I learned it

noisesmith23:05:56

someone shared it on IRC

mobileink23:05:02

@matan what do you mean by "drop to repl"?

noisesmith23:05:52

oh, maybe you mean you usually don’t have a repl running when running your app?

mobileink23:05:19

you can embed a repl, if you want.

noisesmith23:05:42

yeah - I launch a socket repl, even on the server

mobileink23:05:04

i usually run everythun in a repl during dev.

noisesmith23:05:28

and it’s actually very rare that I copy paste code into a repl on a remote server (if my boss asks, I officially never do that, haha)

matan23:05:28

then when do you paste it into source files and see it still works?

noisesmith23:05:51

@matan in dev I reload definitions usually

noisesmith23:05:23

but really, my main repl interaction is trying out smaller pieces of what will eventually become my code - seeing what works or doesn’t work with the data at hand

noisesmith23:05:29

like playing with playdoh

matan23:05:37

I do that a lot

matan23:05:56

But injecting adequate data is kind of cumbersome to me in the repl

noisesmith23:05:05

but you don’t need to inject anything

matan23:05:05

It feels like dependency injection is missing

noisesmith23:05:08

you capture it

noisesmith23:05:16

the data is there if your app runs

noisesmith23:05:21

you just save it for later

matan23:05:46

if I spit it it is there for later but otherwise...

matan23:05:52

I mean the data

noisesmith23:05:03

right, and I use spit to an edn file, and then I slurp and read from my unit test

noisesmith23:05:07

I literally do this

noisesmith23:05:45

I should make a lib that simplifies it (spit-to-test-data x) / (read-from-test-data x)

noisesmith23:05:48

that would be cool

matan23:05:18

I can likely adopt that

mobileink23:05:20

i do this kind of thing all the time in boot.

noisesmith23:05:21

with like a config defaulting to “test/resources/” as a place to put the data

matan23:05:51

this is more for a blog post though 🙂 or I've been coding for 12 hours

mobileink23:05:15

buck up, man! you can make another 8!

matan23:05:52

I can, but I don't know if I want to 😂

mobileink23:05:54

real programmers count in days.😉

matan23:05:22

Then they die without having lived 😉

mobileink23:05:58

no, without having shipped, which is more important.

mobileink23:05:20

i hit the wal on my badassly wunnerful fix all probs lib about 2 months ago. now i just flap my jaws on clojurians until i can recover.

matan23:05:40

fix all probs lib?

mobileink23:05:02

it's less stressful than, youknow, making code work.

matan23:05:58

mobileink: what do you mean?

mobileink23:05:11

i mean it's easier to talk about code than to actually code, i guess. 16 hour coding days are wonderful, but only to a point. at some point you begin to want to chop your fingers off, so you offer some kind advice on clojurians, and gradually you recover and get back to work, heh.

matan23:05:47

yeah I know what you mean

matan23:05:01

take note that there are serious health effects if you keep this habit

matan23:05:23

try to pace it more balanced if you are not force labored into this 🙂 like it's North Korea

mobileink00:05:24

i do what the code tells me to do. 😉 sometimes.

matan23:05:12

`(pprint output string-writer) (spit (io/file "output" "raw.edn") string-writer))`

noisesmith23:05:54

oh yeah I just checked - pprint wraps its body in with-pretty-writer, and with-pretty-writer uses with-out-str

noisesmith23:05:10

you could use a real logger 😄 - too bad that’s overcomplicated on the jvm

matan23:05:18

I use timbre for logging my own messages, when I'm really into logging

matan23:05:47

A bit nicer than Java logging tradition

matan23:05:04

But the codebase of it kind of sloppy if you look inside

matan23:05:06

Some departing thoughts: spitting and slurping from/to the repl is nice, but the workflow is kind of broken in that. there ought to be something more elegant, to avoid people inventing all kinds of crazy debugging schemes taken from 30 years ago

matan23:05:11

Call me spoiled 🙂

matan23:05:52

Sorry for all the trouble and thanks for the help, signing off