Clojurians
#beginners
<
2018-01-29
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

derpocious05:01:55

Hey all, I'm trying to host a simple Reagent and Re-Frame project on github's gh-pages, but it's not working for me

derpocious05:01:42

I'm getting the error "Failed to load resource: the server responded with a status of 404 () http://jimtheman.github.io/:11 Uncaught ReferenceError: kablamo is not defined at http://jimtheman.github.io/:11"

derpocious05:01:19

btw kablamo is the name is the whole project (scaffolded it with 'lein new re-frame kablamo")

derpocious05:01:10

I just ran lein cljsbuild once min and pushed the stuff in kablamo/resources/public to the branch named gh-pages

seancorfield05:01:38

Seems to be working for me @derpocious -- what am I supposed to see?

derpocious05:01:12

there should be yellow and red lines moving around forming some text

derpocious05:01:21

For me it just shows a blank blue page

derpocious05:01:33

and the errors in the console

seancorfield05:01:28

I see the moving text -- and the re-frisk debugger pop-out.

seancorfield05:01:54

And that's with Microsoft Edge on Windows 10 so it's not like the bar is very high... :slightly_smiling_face:

derpocious05:01:22

hmm I just tried on a different computer, and that one is showing the errors also

derpocious05:01:27

just a blank blue page

derpocious05:01:24

anyway, I have to go to sleep. will try more tomorrow. thanks

noisesmith05:01:51

it works for me - just a warning, it is trying to connect to figwheel on my localhost, and while I'm not certain I could mess with your server by connecting to the app via figwheel, I'm also not certain I couldn't

sb07:01:30

gniazdo is beginner friendly too

petr.mensik09:01:01

What is the relationship between new Clojure Deps and other dependendency management tools like Lein? Are they complementary or do I still have to use only project.clj to define the dependencies? https://clojure.org/guides/deps_and_cli

petr.mensik09:01:54

Because I really like featues like referencing dependency directly from Github however I don't understand from the article if I can use it directly in my project or only for REPL development purposes

seancorfield09:01:53

@petr.mensik tools.deps is a low-level library that other tools can build on top of. In the Boot world we have https://github.com/seancorfield/boot-tools-deps that brings pretty much all the (readonly) functionality of tools.deps to Boot.

seancorfield09:01:25

I think there are efforts to produce Leiningen plugins to do all this but they are not so far along yet.

seancorfield09:01:23

The main difference is that clj and tools.deps are about running Clojure code, not building artifacts etc. Boot (and Leiningen) are about building and deploying artifacts.

petr.mensik09:01:55

@seancorfield Thanks for clarification :slightly_smiling_face:

seancorfield09:01:31

I'm constantly surprised at the questions around tools.deps but I guess the Clojure/core folks are just failing to communicate what its purpose really is... It doesn't replace lein / boot.

petr.mensik09:01:00

@seancorfield I understand that tools.deps is not a build tool however I didn't quite grasp how it complements with dependency management tools we already have

petr.mensik09:01:32

There is no mention of Leiningen nor Boot in the article so I guess that's what causes the confusion (at least it caused it in my case :slightly_smiling_face: )

seancorfield09:01:51

Yeah, I think maybe @alexmiller needs to think about the message around that?

seancorfield09:01:56

We've been using deps.edn files at work for ages (albeit in a different format) so tools.deps has just seemed like a natural adjunct to existing build tools to me...

seancorfield09:01:12

...but I guess we're not "typical" :slightly_smiling_face:

gklijs10:01:26

I wonder what to do with leiningen if you have a build with dependencies on github. Most likely they will be included in the sources I think? In oder for other projects depending on it not getting them also from github?

nickstares015:01:34

Can someone help me understand how this works?

(def line "foo:bar")
           (clojure.string/split line #":") ;; => ["foo" "bar"]
             (into {}   (clojure.string/split line #":")) ;; =>    java.lang.Character cannot be cast to java.util.Map$Entry 
             (into {}   [(clojure.string/split line #":")]) ;; => {"foo" "bar"}

nickstares015:01:13

to be more specific, I don't understand why the second doesn't work and the third does

benjaminster15:01:58

2nd form is trying to put strings into a map instead of trying to put kv pairs in

manutter5115:01:31

into {} expects a list of lists, with the inner set of lists each having 2 items corresponding to the key and the value

nickstares015:01:59

ah, ok. didn't realize that it was expecting a list of lists. that makes sense

sundarj15:01:12

into is essentially (reduce conj coll1 coll2), and as such operations on collections

sundarj15:01:33

while vectors are also collections, in the case of putting them into a map, they are single values

manutter5115:01:37

I’m over-simplifying a bit, but that’s the specific case you’re seeing anyway.

sundarj15:01:11

so you need the vectors for the k/v of the map, and then a collection around that for the reduce

nickstares015:01:38

yeah i guess it wouldn't make much sense for it to take just a vector, since it could have an arbitrary number of elements instead of 2

nickstares015:01:15

thanks for your help!

sundarj15:01:13

notice that if you use conj directly, you don't need the wrapping:

=> (conj {} [:a 2])
{:a 2}

sundarj15:01:37

=> (conj {} (clojure.string/split "foo:bar" #":"))
{"foo" "bar"}

rauh15:01:20

@nickstares0 Note, it's not a "list of lists" it's a "coll" of "vectors", if you did a (into {} [(seq (str/split "foo:bar" #":"))]) it would also fail. It works since str/split returns a vector

feihong.hsu16:01:23

i have a lein project, and it was working fine yesterday, but now when i do lein run, it just hangs. it prints one line that says: 2018-01-29 10:26:58,081 [main] DEBUG org.jboss.logging - Logging Provider: org.jboss.logging.Slf4jLoggerProvider but nothing happens and if i refresh my browser it says it can’t connect to the server. what could be causing this?

nickstares016:01:12

ah, gotcha. so

(into {} (seq [(clojure.string/split "foo:bar" #":")]))
works because it could be any coll of vectors

manutter5116:01:56

@feihong.hsu It looks like something is getting stuck during server start-up. Maybe you have an invalid configuration setting somewhere? What changed since yesterday?

carvalhogvm16:01:31

Can someone help me? What would be the idiomatic way to do some action depending on which key a map has? I have a list of maps like [{ :x 1 } {:y 2}] and I want to do something if the map has the first structure and something different for the other. I can have many different structures.

feihong.hsu16:01:32

@manutter51 that’s the weird thing. i haven’t changed any configuration settings in more than a week (that i know of). when i create a new leiningen project, it’s able to start up just fine. but if i did have an invalid configuration setting, wouldn’t it error out instead of just hanging?

manutter5116:01:05

@feihong.hsu I dunno, it’s kind of hard to tell. Do you know what changed since the last time it ran correctly? Have you done a lein clean lately?

alexmiller17:01:43

do ctrl-\ to dump your stack and see where it’s hung (or if it’s a separate process you can kill -3 the pid)

alexmiller17:01:53

or use jstack

feihong.hsu17:01:35

@manutter51 so i finally found the problem but it wasn’t a change in configuration. it was an additional require that i put in env/dev/clj/user.clj. at first i thought it was a problem with circular imports, but i remember that when i did that before, i got an error message. the other weird thing is that i have another source file that has very similar imports and that one doesn’t cause the app to hang. happy to provide a link to my source code on github if that would help.

feihong.hsu17:01:43

@manutter51 argh, ignore the above. it doesn’t have anything to do with require. i was making a call to a function inside user.clj, but that function was not able to complete for some reason.

oliv17:01:45

yesterday I’ve asked about sending message between producer/consumers using channels. finally I could manage and was able to solve https://gist.github.com/tdantas/4d172af3451054290dc67541f5f71d60 cheers and thx guys

victtorferreiralima17:01:18

Hey guys how can I count key-value to a new object some like this: input -> {:type1 [{:type type1}] :type2 [{:type type2} {:type type2} {:type type2}]} output -> {:type1 1 :type2 3}

sundarj18:01:50

you could do

(into {} (map (juxt key (comp count val))) {})

tjtolton18:01:26

wow. real glad I was trolling this to learn this usage of juxt. didn't know how to reason about this function until now. clever.

tjtolton19:01:36

just for the sake of providing you options to reason about, @victtorferreiralima, that's the kind of thing I would typically see as

#(zipmap (keys %) (map count (vals %))
but I kind of dig the usage of juxt.

sundarj19:01:36

(map count (vals %)) can be replaced with (map (comp count val) %) also

josh_tackett19:01:00

(map (fn [base_item]
                       (prn "TEST")
                       (map (fn [target_item]
                              (prn "TEST")
                              (when (match-percent-logic base_item
                                                         target_item)
                                [base_item target_item]))
                            items))
                     items)

josh_tackett19:01:14

`java.lang.NullPointerException: null Reflector.java:26 clojure.lang.Reflector.invokeInstanceMethod /Users/jtackett/Desktop/Foodbam/food_matching/src/food_matching/match.clj:145 food-matching.match/match-percent-logic /Users/jtackett/Desktop/Foodbam/food_matching/src/food_matching/match.clj:107 food-matching.match/match-percent-logic /Users/jtackett/Desktop/Foodbam/food_matching/src/food_matching/match.clj:183 food-matching.match/matching-engine[fn] core.clj:2646 clojure.core/map[fn] LazySeq.java:40 clojure.lang.LazySeq.sval LazySeq.java:49 clojure.lang.LazySeq.seq RT.java:521 clojure.lang.RT.seq core.clj:137 clojure.core/seq core_print.clj:46 clojure.core/print-sequential`

josh_tackett19:01:30

what am I messing up here?

noisesmith19:01:21

the error is inside match-percent-logic

josh_tackett19:01:47

@noisesmith but first line in match-percent-logic is a prn and I don't see the prn

noisesmith19:01:10

also, FYI, a nested map can usually be replaced with for (for [x items y items :when (match-percent-logic x y)] [x y]) *(fixed the binding names to match)

noisesmith19:01:34

@josh_tackett the stack trace says that match-percent-logic was called

josh_tackett19:01:41

I'll look deeper

josh_tackett19:01:49

@noisesmith why am I seeing my prn's in the output of the map?

josh_tackett19:01:05

(("Starting match algorithm . . . " "Item 1 > > > " <result> . . .

noisesmith19:01:11

because map is lazy

noisesmith19:01:19

the prints happen as the items are realized

noisesmith19:01:32

if you capture the output of map, you can make more sense of it

noisesmith19:01:09

eg (def foo (doall ...)) (now all the printlns are done) (pprint foo)

josh_tackett19:01:41

(doall 
                  (map (fn [base_item]
                         (map (fn [target_item]
                                (when (match-percent-logic base_item
                                                           target_item)
                                  [base_item target_item]))
                              items))
                       items))

noisesmith19:01:47

a favorite trick of mine is to use data side effects instead of i/o side effects

noisesmith19:01:51

right but inside a def

noisesmith19:01:05

because the def will just return nil

josh_tackett19:01:19

(let [
        _ (prn "Items - > " items)
        ;; Now do the N^2 checking to see if the matches...well...match
        matches (doall 
                  (map (fn [base_item]
                         (map (fn [target_item]
                                (when (match-percent-logic base_item
                                                           target_item)
                                  [base_item target_item]))
                              items))
                       items))

        ]
    matches)

josh_tackett19:01:29

still seeing the prn's

noisesmith19:01:32

that still doesn't fix it

noisesmith19:01:00

you probably need a nested doall

josh_tackett19:01:01

just using mapv and mapv

noisesmith19:01:10

sure, that's another way to accomplish it

noisesmith19:01:19

anyway, what I was saying about capturing data side effects rather than doing i/o side effects (defonce debug (atom [])) (map (fn [x] (swap! debug conj {:x x}) (f x)) items)

noisesmith19:01:41

then you can programatically access and work with the values being captured, instead of just reading them on the screen

josh_tackett19:01:17

@noisesmith ok now we're talking, was just about to ask you how to speed up this algo so its not N^2

noisesmith19:01:49

clojure.math.combinatorics might help there

josh_tackett19:01:03

What's that for?

noisesmith19:01:19

for efficiently generating combinations of an input

josh_tackett19:01:12

I don't think applies here

josh_tackett19:01:23

I'm basically doing millions of string comparisons with a nested map

noisesmith19:01:40

a nested map is a naiive way to get all combinations of two items in an input

noisesmith19:01:38

if you only want distinct combinations, or only want combinations where the two items are not the same, there's optimizations possible

josh_tackett19:01:56

No I'm looking at fuzzy string comparison

josh_tackett19:01:00

@noisesmith ^^^

josh_tackett19:01:25

so basically the fastest way to see which items in the list match each other via a fuzzy string comparison

noisesmith19:01:27

I'm talking about the wrapping context, that's the thing that is n^2

noisesmith19:01:56

you map items inside map items, which means you are comparing every pair of elements in items

noisesmith19:01:35

if the thing you want to optimize isn't in the code you've shared I can't help much with that unless you show more

noisesmith19:01:14

you could use a memoized function for the comparison, so that you never calculate the same comparison twice

noisesmith19:01:23

depending on whether you expect the data to repeat

josh_tackett19:01:05

all I need to optimize is what I've shared @noisesmith so maybe I'm just confused

josh_tackett20:01:29

what is best way to optimize nested (map (map ...) ...)?

dpsutton20:01:21

i think his point is that the only way you can optimize map map is to do less work. and to do less work you need to know what you are doing and figure out a way to prune the search space. but all we know is that you need to compare all strings. and if so, there's no short cut around that

josh_tackett20:01:48

:disappointed:

noisesmith20:01:16

well, the shortcut could be eliminating duplicate comparisons, or caching the comparison function with memoize

noisesmith20:01:23

but you need more context to know for sure

josh_tackett20:01:41

@noisesmith maybe I can make some of the process async to speed it up?

noisesmith20:01:35

you could parallelize sure

josh_tackett20:01:03

how would you parallize that loop?

noisesmith20:01:09

check out the reducers namespace - there's probably something there that's optimal https://clojure.org/reference/reducers

noisesmith20:01:18

in fact, there's drop-in replacements for map in there iirc

noisesmith20:01:09

looks like what you would want is fold with the map transducer

noisesmith20:01:04

(or maybe r/map which isn't a transducer (precedes those) but has similar purpose)

josh_tackett20:01:55

so just swap map for r/map ?

josh_tackett20:01:12

just wrap it in fold

noisesmith20:01:13

not quite - you need to put it inside a fold, which needs a reducing function

noisesmith20:01:36

the reducing function would basically be a conj - also your when can become r/filter I think

josh_tackett20:01:23

[#object[clojure.core.reducers$folder$reify__6593 0x67999bad "[email protected]"]

josh_tackett20:01:31

(mapv (fn [base_item]
                        (mapv (fn [target_item]
                                (r/filter (match-percent-logic base_item
                                                               target_item)
                                          [(:din base_item)
                                           (:din target_item)]))
                              items))
                      items)

josh_tackett20:01:44

so now I'm getting objects, do I just need to deref them?

noisesmith20:01:52

r/filter needs to be inside r/fold

noisesmith20:01:08

I was saying that once you use r/fold and r/map, you can also use r/filter and simplify that inner logic

josh_tackett20:01:34

(r/map (fn [base_item]
                        (r/fold
                          conj
                          (r/map (fn [target_item]
                                  (r/filter (match-percent-logic base_item
                                                                 target_item)
                                            [(:din base_item)
                                             (:din target_item)]))
                                items)))
                      items)

noisesmith20:01:57

r/map has to be inside r/fold

josh_tackett20:01:07

hahaha should have known

josh_tackett20:01:16

should I just wrap the outer loop in fold?

noisesmith20:01:51

I'd take the time to read the clojure guide on reducers - I haven't used them seriously yet, but your use case looks like a good one for reducers

josh_tackett20:01:56

(r/fold
                   conj
                   (r/map (fn [base_item]
                            (r/fold
                              conj
                              (r/map (fn [target_item]
                                       (r/filter (match-percent-logic base_item
                                                                      target_item)
                                                 [(:din base_item)
                                                  (:din target_item)]))
                                     items)))
                          items))

josh_tackett20:01:11

so that works, but the response is a bunch of objects

josh_tackett20:01:14

rather than the actual result

josh_tackett20:01:35

@noisesmith maybe I should move this to actual clojure channel?

noisesmith20:01:19

maybe? these are still beginner questions, but use your best judgment - I think some of the examples in the "Using Reducers" section on the clojure guide I linked to look a lot like your use-case

josh_tackett20:01:33

(r/fold
                   conj
                   (r/map (fn [base_item]
                            (r/fold
                              conj
                              (r/map (fn [target_item]
                                       (r/filter (match-percent-logic base_item
                                                                      target_item)
                                                 [(:din base_item)
                                                  (:din target_item)]))
                                     items)))
                          items))
I run this loop and get a bunch of objects: #object[clojure.core.reducers$folder$reify__6593 0x20038b5c "[email protected]"] What is the best way to get the actual result?

josh_tackett20:01:39

so I agree this is a great lib

josh_tackett20:01:46

but nothing in there says how to deref after

josh_tackett20:01:53

it just shows the result...well...working haha

noisesmith20:01:55

Using Reducers shows it

josh_tackett20:01:13

not really though right?

josh_tackett20:01:17

(require '[clojure.core.reducers :as r])
(r/fold + (r/filter even? (r/map inc [1 1 1 2])))
;=> 6

josh_tackett20:01:30

but that's not very different from what I have

josh_tackett20:01:35

and they just show the reuslt

noisesmith20:01:38

it looks like either (into [] ...) or (r/foldcat ...)

josh_tackett20:01:22

nah still objects

noisesmith20:01:25

r/map might not work directly in the nested way - you might need an inner foldcat, into, or fold

josh_tackett20:01:37

(r/foldcat
                   (r/map (fn [base_item]
                            (r/foldcat
                              (r/map (fn [target_item]
                                       (r/filter (match-percent-logic base_item
                                                                      target_item)
                                                 [(:din base_item)
                                                  (:din target_item)]))
                                     items)))
                          items))

josh_tackett20:01:42

but they have a nested map in their example?

josh_tackett20:01:34

foldcat is just the same as (r/fold conj ....)

josh_tackett20:01:42

So just got it working, but ironically its not any faster hahaha

noisesmith20:01:26

hmm... well it's implicitly parallelizing supposedly - what was the final thing that made it work?

josh_tackett20:01:38

I removed the r/filter and got an actual result

josh_tackett20:01:03

I'm going to try it with more items and see the difference in speed

josh_tackett20:01:53

let's see what they say in #clojure @noisesmith

josh_tackett20:01:13

Also @noisesmith do you know a way to make sure that loops don't return a bunch of nils but rather just skip the result?

josh_tackett20:01:20

[["28622" "28622"] nil nil nil nil nil nil nil nil nil]

josh_tackett20:01:25

this is forcing me to go through the list again

noisesmith20:01:13

you can use (vec (keep ...)) instead of mapv

noisesmith20:01:48

or use for which takes a :when syntax

noisesmith20:01:07

if you are OK with [[a b] nil] turning into [a b] you can use mapcat instead of map

noisesmith20:01:28

or (into [] (mapcat ...) coll)

ghadi20:01:53

I would suggest breaking this thing apart @josh_tackett... too much going on in one expression

ghadi20:01:21

get the inner part working, give it a name, get the other layers working

josh_tackett20:01:10

@ghadi yes after we get it working I'll obviously make it more modular

ghadi20:01:28

that is backwards

ghadi20:01:42

it's not working because it isn't decomposed

ghadi20:01:50

and you don't know where the error is

josh_tackett20:01:19

its actually work now :wink:

josh_tackett20:01:44

sometimes its easier to see the function all together rather than trying to follow through many defn's

josh_tackett20:01:45

@noisesmith that reducer lib was a big help thank you