Fork me on GitHub
#beginners
<
2016-09-09
>
credulous01:09:38

Hi, I’m probably mis-using atoms and have confused myself thoroughly

credulous01:09:03

I have an atom that maps a string id (it’s coming from a database, it was awkward to convert to a keyword) to an array of maps

credulous01:09:21

(def actions_by_card (atom {}))

credulous01:09:16

It gets populated OK, and I can map over it etc… the first element is

credulous01:09:31

(first @actions_by_card)

credulous01:09:58

["2gs89taaDEwd2Ruzi" [{:context {}, :card_id “2gs89taaDEwd2Ruzi      …. more maps   }]]

credulous01:09:05

But I can’t access it directly

credulous01:09:33

(@actions_by_card "2gs89taaDEwd2Ruzi”)

credulous01:09:48

CompilerException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to clojure.lang.IFn, compiling:(cavalry_stats/core.clj:137:1)

(get @actions_by_card "2gs89taaDEwd2Ruzi”)
;; -> nil

credulous01:09:24

What am I missing?

seancorfield02:09:26

It sounds like you populated it incorrectly — it has a lazy sequence in it, instead of a map.

seancorfield02:09:34

How are you populating it?

jeeq04:09:02

Hi guys, I have trouble connecting to nrepl through cider. I have project created with re-natal (re-natal init projectname). Then I go into emacs and jack-in… from there I’m not sure how to start figwheel to see changes on ios (simulator and device)

jeeq04:09:45

when I do > re-natal use-figwheel and > lein figwheel ios, figwheel server starts and I have to open up separate terminal to > re-natal xcode. doing that gives me repl on my terminal but I’m not using emacs cider at this point at all…

mordocai04:09:09

@jeeq based on http://cljsrn.org/ you may want to ask #cljsrn if you don't get an answer here

jeeq04:09:17

@mordocai Thank you

akiva04:09:05

@jeeq, I generally launch two REPLs. One for Figwheel and one for the server. I’ve no familiarity with re-natal but you should probably start solving this by minimizing the issue and just making sure you can establish any connection and then expand from there.

jeeq05:09:35

Will do. Thank you @akiva

cameronbourke07:09:19

Factory functions, how do I create a function that returns a map?

cameronbourke07:09:27

(defn factory [value]
	({:key value}))

cameronbourke07:09:28

I tried ^ but when I call it (factory "value”) I get the error: > ArityException Wrong number of args (0) passed to: PersistentArrayMap

st07:09:46

@cameronbourke you return a list. The first element of a list is always considered as a function. in your case this function is the map itself. a map is a function that returns value for a known key. So, your error is that the map complains about missing required argument. e.g

user=> ({:a 1} :a)                                                                                                                               │
1
what you want to do is simply:
(defn factory [value]                                                                                                                     
 {:key value})                                                                                                                         
user=> (factory 1)                                                                                                                               
{:key 1}

cameronbourke07:09:13

@st Thanks! That makes sense. But isn’t the syntax for defn macro defn <name> [<args>] (<body>)?

st07:09:35

nope, syntax is (defn name “documentation” [args] body) or (for multi-arity) (defn name “documentation” ([args1] body1) ([args2] body2)) documentation is optional.

cameronbourke07:09:53

That is really cool how you can have seperate bodies for each argument. Thanks for clarifying that @st

st07:09:25

Indeed. remember that documentation string goes just after name of function.

alexisvincent09:09:15

Hi guys. A real beginners question here. Im using cursive with intellij and trying to get some kind of hot reloading env setup.

(defproject natbox "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "Eclipse Public License"
            :url  ""}
  :dependencies [[org.clojure/clojure "1.8.0"]]
  :profiles {:dev {:dependencies [[org.clojure/tools.namespace "0.2.11"]]
                   :source-paths ["dev"]}})
this is my project.clj… I assume now that I need to make a cursive repl and specify the dev profile… But when I do, I get the following error
Error loading clojure.tools.nrepl.server: Could not locate clojure/tools/nrepl/server__init.class or clojure/tools/nrepl/server.clj on classpath.
Error loading complete.core: Could not locate complete/core__init.class or complete/core.clj on classpath.
Exception in thread "main" java.lang.ClassNotFoundException: clojure.tools.nrepl.server, compiling:(/private/var/folders/9s/txldqs4x1ts59q6qblrn133c0000gn/T/form-init6119612237788758823.clj:1:773)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6875)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.access$300(Compiler.java:38)
	at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6269)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6868)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.analyze(Compiler.java:6625)
	at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:6001)
	at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5380)
	at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3972)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6866)
	at clojure.lang.Compiler.analyze(Compiler.java:6669)
	at clojure.lang.Compiler.eval(Compiler.java:6924)
	at clojure.lang.Compiler.eval(Compiler.java:6917)
	at clojure.lang.Compiler.load(Compiler.java:7379)
	at clojure.lang.Compiler.loadFile(Compiler.java:7317)
	at clojure.main$load_script.invokeStatic(main.clj:275)
	at clojure.main$init_opt.invokeStatic(main.clj:277)
	at clojure.main$init_opt.invoke(main.clj:277)
	at clojure.main$initialize.invokeStatic(main.clj:308)
	at clojure.main$null_opt.invokeStatic(main.clj:342)
	at clojure.main$null_opt.invoke(main.clj:339)
	at clojure.main$main.invokeStatic(main.clj:421)
	at clojure.main$main.doInvoke(main.clj:384)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.lang.Var.invoke(Var.java:383)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.Var.applyTo(Var.java:700)
	at clojure.main.main(main.java:37)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:497)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.ClassNotFoundException: clojure.tools.nrepl.server
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at clojure.lang.DynamicClassLoader.findClass(DynamicClassLoader.java:69)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at clojure.lang.DynamicClassLoader.loadClass(DynamicClassLoader.java:77)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at clojure.lang.RT.classForName(RT.java:2168)
	at clojure.lang.RT.classForName(RT.java:2177)
	at clojure.lang.Compiler$HostExpr.maybeClass(Compiler.java:1030)
	at clojure.lang.Compiler.macroexpand1(Compiler.java:6807)
	at clojure.lang.Compiler.analyzeSeq(Compiler.java:6854)
	... 33 more

Process finished with exit code 1
Exception starting REPL: java.lang.InterruptedException

dominicm09:09:41

@alexisvincent https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md#default-profiles > The profiles listed above are active during development, Scattered above this is: :user, :dev, :system, and :base

dominicm09:09:49

Your :dev profile should be automatic

alexisvincent09:09:15

@dominicm I set +dev and that worked. But Ill try without quickly

jazzydag15:09:56

I use compojure-api to build a REST API with Swagger documentation. I would like to have the main entry at /api (for instance, it could be /v1 or /v2). I set the :basePath swagger route parameter to /api. And when I went to the swagger doc page, there was a Can't read swagger JSON from . My different api routes didn't begin by a /api.

dorianc.b15:09:52

Hello everyone, I’m new to clojure so I just wanted to introduce myself

shaun-mahood15:09:28

@dorianc.b: Hi, glad to have you on board!

shaun-mahood15:09:44

You starting to learn for hobby projects or using it for work?

dorianc.b15:09:45

Hobby projects I guess. I just started to learn programming. My first language was Java and I wanted to pick up functional programming so clojure seemed like a good fit since I could still use some of the java classes if I still need them

dorianc.b15:09:26

I just started reading the book Clojure for the brave and the true and I’m really liking the simple syntax.

shaun-mahood15:09:22

@dorianc.b: That's a great book to start with. It's really a fun language to learn and use, and this channel is a great place to ask questions when you run into things you aren't sure of - don't be shy, we've all been through the learning curve and there's a ton of stuff to learn.

abarylko17:09:06

Anybody using plumatic/schema ?

val_waeselynck18:09:27

@abarylko occasionally yes

straistra18:09:19

How would I load an external file in Clojurescript? I'm thinking of using the markdown-clj for easier formatting of significant amount of text, but I'm having some issues figuring out how to load a simple file in Clojurescript. It can't be too difficult, what obvious thing am I missing?

mordocai19:09:24

@straistra I'm having a surprisingly hard time getting my use case to work, but in general https://github.com/cljsjs/packages/wiki/Creating-Externs

mss19:09:20

kind of a weird and highly specific q, but is there some idiomatic way to merge two lists of maps to get the following result? e.g. ({:id 1 :some-string “abc”} {:id 2 :some-string “def”} {:id 3 :some-string “ghi”}) and ({:id 1 :some-num 123} {:id 2 :some-num 456} {:id 4 :some-num 789}) results in (({:id 1 :some-string “abc”} {:id 1 :some-num 123}) ({:id 2 :some-string “def”} {:id 2 :some-num 456}) ({:id 3 :some-string “ghi”}) ({:id 4 :some-num 789}))

mordocai19:09:40

@straistra Oh, I read that wrong. You mean just loading a file not loading external javascript right?

credulous19:09:46

I have a sequence of maps of statistics I’ve gathered from a system. I’d like to add up the elements. Some of the elements are nested maps.

credulous19:09:55

{:total_edit_time 285,
   :messages_sent 1,
   :followups 0,
   :bounces 0,
   :users
   {:DHL2DbhKFWx6LhKw9
    {:locked 1, :total_edit_time 285, :drafts_sent 1, :replies 1}},
   :campaigns
   {:7dmBTxuzpjjwHXzKL
    {:total_edit_time 285, :drafts_sent 1, :replies 1}},
   :reply_received true}
  {:total_edit_time 1016,
   :messages_sent 0,
   :followups 0,
   :bounces 0,
   :users {:W4byrxBxghnsrezbN {:locked 1, :total_edit_time 1016}},
   :campaigns {:F2etLeSKAopLKHKxa {:total_edit_time 1016}},
   :last_lock_time
   #object[org.joda.time.DateTime 0x661adcfb "2016-09-07T07:31:49.637-07:00"]}

credulous19:09:35

there are two of them.

credulous19:09:03

The code I’ve got that reduces the sequence is really long and wordy. I wondered if there was an elegant way to do it.

seancorfield19:09:21

Are you just looking for any occurrence of a specific key, regardless of depth?

straistra20:09:55

@mordocai Yeah, just a file. Essentially a text file. It's really easy in clojure, but clojurescript is baffling me.

straistra20:09:25

Does the http://clojure.java.io work in Clojurescript? If so, then I am sorted. But I kind of figured it wouldn't work in javascript. Maybe my assumptions are wrong.

credulous20:09:52

@seancorfield Yes, and the output should have the superset of keys in, i.e., the “user” map

credulous20:09:11

Some of the keys don’t add obviously - I can exclude those in whatever way including stripping them

mordocai20:09:15

@straistra I don't think so. I think slurp should work if all you need is to load the whole file at once, but i'm barely into clojurescript and haven't needed it yet

credulous20:09:53

Right now I have a (defn summarize [rec1 rec2] …) function that does every little bit manually, then I use it to reduce over the sequence

credulous20:09:58

but that seems clunky

straistra20:09:52

@mordocai Isn't slurp part of the http://java.io (or reader, to be specific)? Because slurp doesn't actually work in Clojurescript. At least not without doing some require or whatnot first.

mordocai20:09:34

@straistra Okay, it may be then. Are you wanting to do the markdown parsing at compile time or run time? Do you want the file read at compile time or run time? Node or browser?

straistra20:09:42

@mordocai Well, I am running it through Reagent. I guess I could manually type in some javascript, but I don't know any. Can't be too hard...

mordocai20:09:46

@straistra Well, since you won't have a file API in the browser, I imagine you need to load the file into a string at compile time one way or another. Not sure how you'd do that exactly. Might try asking with the specifics in #clojurescript

straistra20:09:55

@mordocai Yeah, thanks. It's not an immediate concern, but I was a bit surprised how I hit a sudden wall trying to do this.

mordocai20:09:28

@straistra: I'd be surprised if it wasn't a solved problem, I just don't know enough to point you to it really

abarylko20:09:00

@val_waeselynck How would you go about defining a schema based on another schema?

seancorfield22:09:14

@credulous I think you should be able to do that fairly easily with a recursive function that uses reduce-kv on each map... I'm away from my desk right now but I'll try to run up an example when I get back... If you can post a complete example as a Gist or on RefHeap or PasteBin and put the link here, that will help me test.

seancorfield22:09:45

But basically the reduce-kv would check the value and if it's numeric, use update to add it to an accumulator map (with fnil to provide 0 if the key doesn't exist), and if it's a map, call summarize recursively with the accumulator map to produce a new accumulator, else ignore it (just return the accumulator as-is).

seancorfield22:09:07

@credulous something like this (not well tested): (defn summarize [data acc] (reduce-kv (fn [acc k v] (cond (number? v) (update acc k (fnil + 0) v) (map? v) (summarize v acc) :else acc)) acc data)) and then (->> {} (summarize rec1) (summarize rec2))

seancorfield22:09:20

(excuse formatting)

codonnell22:09:09

@credulous another option using the specter library:

(->> data (traverse (recursive-path [] MapWalker [map? (multi-path (must :total-edit-time) [MAP-VALS MapWalker])]) (reduce + 0))

seancorfield22:09:02

That looks like a lot more "magic" but that's kinda the point of Specter I guess...

codonnell23:09:33

@seancorfield I don't think it's so crazy. It defines a recursive path named MapWalker that continues navigation if the structure is a map and navigates to both the :total-edit-time key if it exists as well as recursively following the MapWalker path again on each of the map values.

codonnell23:09:00

The net effect is navigating to the value of :total-edit-time in any nested map.

codonnell23:09:07

I suppose this is more of an intermediate usage of specter, and certainly the internals of specter are pretty magical. However, I think it exposes a pretty clean API.

seancorfield23:09:43

Note that my suggestion would sum up all keys that had numeric values, not just that one key. It wasn't clear to me what you were really looking for...

codonnell23:09:10

Ah, good point. I may have misread the question.

seancorfield23:09:27

I saw Nathan's talk on Specter but I haven't seen a use case for it in anything I've run across so far.

codonnell23:09:29

Personally, I find myself using it whenever I have more nested data structures. It's also pretty good at navigating recursive structures, like a graph/tree.

codonnell23:09:21

As with any library, there's some learning curve. But I think once you grok how paths are put together, specter locates data within data structures extremely efficiently and clearly.