#clojure log - Mar 03 2015

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:00 h_: how might I serialize a function such that I could write it to a file and recall an identical function from that file at a later time?

0:00 puredanger: https://github.com/technomancy/serializable-fn

0:01 h_: hooray! thank you friend

0:04 puredanger: enjoy!

0:08 h_: `3`3

0:08 <3<3 even!

2:36 je: is there a way from the repl to "inspect" data to explore all the interfaces it implements and all the classes it inherits from

2:36 amalloy: &(ancestors clojure.lang.PersistentVector)

2:36 lazybot: ⇒ #{clojure.lang.IMeta java.lang.Comparable clojure.lang.Indexed clojure.lang.IPersistentVector java.lang.Iterable java.util.List clojure.lang.Associative clojure.lang.IObj clojure.lang.APersistentVector clojure.lang.Reversible java.lang.Object clojure.lang.Seqable clo... https://www.refheap.com/98040

2:37 je: I want to identify commonality for dispaching in a multimethod

2:38 amalloy: nice thanks

2:42 TEttinger: (inc amalloy)

2:42 lazybot: ⇒ 231

3:34 dm3: hello

3:34 daniel`: hi

3:34 dm3: is there an "approved" way to detect if a sequence is lazy?

3:35 I know there's a clojure.lang.LazySeq, but does it cover all cases?

4:15 justin_smith: dm3: it's the only lazy type in clojure. Though they can hide.

4:15 ,(type (cons :a (range)))

4:15 clojurebot: clojure.lang.Cons

4:15 justin_smith: that's a cons, but it's tail is lazy

4:15 ,(type (range))

4:15 clojurebot: clojure.lang.LazySeq

4:18 dm3: I'm trying to enforce stricter semantics for an fn which operates in a dynamic scope

4:18 know that there'll be trouble with nested lazy sequences, but forcing the outer one should cover 95% of use cases

4:18 godd2: *opens lein repl* (reduce + (range)) ; oh god what have I done

4:19 dm3: guess just checking if it's a sequence and doall'ing would be enough

4:19 justin_smith: dm3: if you know you won't get (range) or (iterate ...)

4:19 dm3: yes

4:20 justin_smith: you could also do a clojure.walk/postwalk, which will hit every subtree, and try to fully descend every subtree

4:20 hmmm. maybe just a (dorun (tree-seq ...))

4:27 dm3: justin_smith: thanks

4:29 justin_smith: ,(tree-seq coll? seq [:a [:b {:c 0 :d 1 :e #{1 2 3}}]])

4:29 clojurebot: ([:a [:b {:e #{1 3 2}, :c 0, :d 1}]] :a [:b {:e #{1 3 2}, :c 0, :d 1}] :b {:e #{1 3 2}, :c 0, :d 1} ...)

4:35 TEttinger: &(tree-seq coll? seq [:a [:b {:c 0 :d 1 :e #{1 2 3}}]])

4:35 lazybot: ⇒ ([:a [:b {:e #{1 3 2}, :c 0, :d 1}]] :a [:b {:e #{1 3 2}, :c 0, :d 1}] :b {:e #{1 3 2}, :c 0, :d 1} [:e #{1 3 2}] :e #{1 3 2} 1 3 2 [:c 0] :c 0 [:d 1] :d 1)

4:35 justin_smith: aint no room for a lazy seq to hide in there

4:35 TEttinger: I have no idea how tree-seq works

4:36 justin_smith: TEttinger: it returns every sub tree

4:36 and every sub-tree of each sub-tree

4:36 the first arg is the function which tells you if a thing has sub-trees

4:36 the second arg is the thing that returns the sub-trees, if it has them

5:40 dysfun: what do i need to do to correctly inflate a ns-qualified symbol in an edn file to a value? let's assume for now that the code is in the classpath

5:43 aha, find-var

5:58 ggherdov: ,(->> '([1 :a] [2 :c]) (sorted-map-by <))

5:58 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: ([1 :a] [2 :c])>

5:58 ggherdov: ,(->> '([1 :a] [2 :c]) (apply (sorted-map-by <)))

5:58 clojurebot: [2 :c]

5:58 ggherdov: ,(->> '([1 :a] [2 :c]) flatten (apply (sorted-map-by <)))

5:58 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: PersistentTreeMap>

5:59 ggherdov: you have a list of keyvals (as vectors), and want to build a sorted-map-by. How do you do?

5:59 Glenjamin: (doc into)

5:59 clojurebot: "([to from] [to xform from]); Returns a new coll consisting of to-coll with all of the items of from-coll conjoined. A transducer may be supplied."

6:00 TEttinger: ,(into (sorted-map-by <) '([1 :a] [2 :c]) )

6:00 clojurebot: {1 :a, 2 :c}

6:00 ggherdov: thanks TEttinger Glenjamin

6:00 TEttinger: np

7:35 razum2um: dnolen: what's the status of cljs support of promise/deliver/deref ?

7:35 dnolen: razum2um: no support is planned, JS is single-threaded

7:50 razum2um: dnolen: yes, but what king of abstraction should we use to "fix" callback hell?

7:50 dnolen: razum2um: core.async

7:50 razum2um: besides of core.async :)

7:50 say, setTimeout

7:51 dnolen: razum2um: core.async is the best solution

7:52 razum2um: dnolen: but there is a lot of promise-solutions as libraries (besides ES6 promisses) - why not to map them and choose one of the polyfill for older browsers?

7:53 dnolen: razum2um: I don't really have anything else to say on this topic than what I've already said. Sorry.

7:53 razum2um: dnolen: ok then, thanks :)

7:54 sveri: razum2um: I guess you are free to create your own abstractions over one of the existing libraries

7:54 If you feel the need for them

7:55 razum2um: sveri: yes, native calls to js/.. work, but I just worder why promise is not implemented

7:57 sveri: I see :-)

8:03 dnolen: razum2um: if it wasn't clear earlier, JS promise abstractions are nothing like the Clojure promise abstraction which has blocking semantics for deref. This would imply duplicating core.async but would require whole program transform.

8:04 razum2um: it hasn't been done because the semantics can't be preserved

8:04 without too a big tradeoff

8:27 piranha: hey all! I'm trying to call Java method with spread arguments (...): http://cr.openjdk.java.net/~sundar/jdk.nashorn.api/8u40/javadoc/jdk/nashorn/api/scripting/NashornScriptEngineFactory.html#getScriptEngine-java.lang.String...-

8:27 rs-example.server.render> (.getScriptEngine f "-pcc" "-ot=true")

8:27 java.lang.ClassCastException: Cannot cast java.lang.String to [Ljava.lang.String;

8:27 and it fails with this ^

8:27 am I doing something wrong?

8:28 ah! (into-array String ["a", "b"]) helps

8:46 sveri: Hi, anyone knows how to properly handle umlaute with transit? transit converts umlaute wrong and makes weird chars of it, see this: http://pastebin.com/7Z8x3C5d

8:47 Eremox: How do i stop cider from swapping to error-buffer and set it to just print the error message in the repl instead?

8:49 dnolen: sveri: I don't think transit-clj will handle that for you by default, http://stackoverflow.com/questions/15356716/how-can-i-convert-unicode-string-to-ascii-in-java

8:50 sveri: perhaps worth opening an enhancement issue w/ transit-java

8:51 sveri: dnolen: thank you, I will do that. Not sure exactly, but this is something I would expect to be handled by the library

8:51 dnolen: sveri: perhaps, not sure about the perf implications though

8:52 sveri: dnolen: maybe it can be made optional, however, thank you, I open an issue :-)

9:23 borkdude: I might be brainnumbed, but is there an easier way to update the val in a map? (update-in {:foo "bar"} [:foo] count)

9:23 of a collection of maps that is

9:23 so (map #(update-in ....))

9:24 gfredericks: borkdude: clojure 1.7 has update

9:24 borkdude: gfredericks yes, I heared.

9:24 gfredericks when is it out?

9:25 gfredericks: dunno; prismatic/plumbing also has it in the meantime

9:25 borkdude: k

9:26 gfredericks: ,(defmacro map-> [& exprs] `(map #(-> % ~@(butlast exprs)) ~(last exprs)))

9:26 borkdude: https://github.com/clojure/clojure/blob/2e76c57d3b7672ce5eca096ed2059d9a1dd379d0/src/clj/clojure/core.clj#L5909

9:26 clojurebot: #'sandbox/map->

9:27 gfredericks: ,(->> [{:foo 12} {:foo 13} {:foo 92}] (map-> (* 2) (inc)))

9:27 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.Number>

9:27 gfredericks: whoopsiedoodle

9:27 ,(->> [{:foo 12} {:foo 13} {:foo 92}] (map-> (update :foo * 2)))

9:27 clojurebot: ({:foo 24} {:foo 26} {:foo 184})

9:28 gfredericks: no idea if map-> is defined in some lib somewhere

9:28 borkdude: gfredericks thanks ;)

9:29 gfredericks: np

9:51 borkdude: gfredericks I found reduce-kv also handy

9:53 gfredericks: borkdude: for your original question?

9:53 borkdude: gfredericks yes

9:53 gfredericks it was a little bit different than I asked, but eventually this is what I needed. didn't know about this one yet

9:54 jcromartie: .

9:56 gfredericks: ,

9:56 jcromartie: excuse me

9:56 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

9:56 jcromartie: I was cleaning my keyboard

9:56 :P

9:56 ,(((

9:56 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

9:56 gfredericks: ,())))

9:56 clojurebot: ()

9:56 jcromartie: I have a recipe for pain

9:57 a Clojure app that depends on Ruby gems to be available at runtime

9:57 I think binstubs may be the answer

9:57 I dunno

9:58 it's particularly troublesome with Emacs and Cider launching the REPL process

9:58 I can't figure that one out

10:01 loliveira: I would like to run java -jar my_uber.jar —repl and get a repl. Do you know how to do that?

10:03 jcromartie: what was that cider-related channel?

10:05 katratxo: loliveira: https://github.com/clojure/tools.nrepl#embedding-nrepl-starting-a-server

10:14 justin_smith: loliveira: java -cp my_uber.jar clojure.main

10:14 or that

10:14 but clojure.main will give you a repl

10:15 loliveira: katratxo: justin_smith: thank you!

10:15 it worked. =)

10:15 * TimMc sends a patch to GNU getopts to accept — as --

10:17 justin_smith: loliveira: if you prefer the nrepl repl to the clojure one, you can launch the nrepl server from your own app (or even from the clojure repl) as described in katratxo 's link, and then connect to it with "lein repl :connect N" where N is the port number it opens

10:19 loliveira: justin_smith: I will try the nrepl approach.

10:19 justin_smith: I will put the follow up.

10:23 justin_smith: loliveira: a trick I often use is to have an optional environment variable, which if set, I turn on an nrepl server from my process

10:23 loliveira: justin_smith: good idea.

10:23 justin_smith: but the java -cp ... clojure.main is useful for if I want to just run some code with exactly the setup that would be available on the server

10:24 not running the app, but just running some code that I think might have failed in production for example

10:25 (I used this recently to verify that tomcat was making the serving of resources inside the jar with unusual names 404)

10:33 loliveira: aggred

10:34 justin_smith: I have the same need that you had.

10:36 justin_smith: loliveira: another trick that I needed in that case, because this was a war file and not a jar file, I needed to also explicitly add the clojure.core to the class path because of how wars are packed up

10:36 probably not an issue in your case

10:37 loliveira: i used to deploy wars.

11:21 timvisher: what's the state of clojure servers at this point? last i heard you really weren't supposed to serve out of embedded jetty in prod using `lein ring server`, but people weren't thrilled with tomcat, some people were using application servers (way heavier than i need), and some people were thrilled with http-kit (which is embedded in the app so you can just `lein run`?)

11:22 justin_smith: timvisher: I think http-kit and aleph are great options, and using lein to run in prod is a bad idea

11:22 better to create an uberjar and use java -jar ... or java -cp ...

11:23 lein is a great dev tool, but it doesn't help you much in production

11:23 schmir: the boot people advertise using boot in production

11:23 timvisher: justin_smith: indeed. :) i've heard that over the years but never dove into why. is there a good doc somewhere that expresses that?

11:23 justin_smith: that's a choice I wouldn't be likely to make, but I know that a lot of people use lein in prod too

11:24 timvisher: for starters, lein starts up an extra vm you don't need. It also sets jvm options that optimize startup time at the expense of performance (turning down the JIT options)

11:25 timvisher: but even if it wasn't actively reducing performance, it's functionality I don't need, a program I don't need to install, and an extra place for things to break that can be removed from the prod environment

11:25 timvisher: justin_smith: all good points

11:25 michaelr`: anything out there which converts html to clean, formatted hiccup?

11:25 timvisher: do you also embed an nrepl server?

11:26 michaelr`: bet you pandoc could do it! (or at least get you stupid close) :)

11:26 but i haven't heard of anything

11:26 justin_smith: timvisher: I use an environment variable to optionally start nrepl (local host only, ssh tunnel to connect)

11:26 timvisher: michaelr`: actually, i take that back. doesn't enlive get you very close?

11:26 i suppose it wouldn't pretty print, but that's why clojure.pprint is a thing

11:26 bja: michaelr`, I think I've used hickory for that before

11:27 timvisher: https://github.com/cgrand/enlive

11:27 guess it depends what you mean by clean

11:27 justin_smith: timvisher: the nrepl optionally being started in it's own thread from the function that starts the web server

11:27 timvisher: justin_smith: and then start up the nrepl server internal to the app?

11:27 nice

11:27 michaelr`: hickory give hiccup but it's full of empty strings and empty attribute maps

11:27 justin_smith: right, the app's logic turns on the server if the env var is set

11:28 timvisher: one caveat that doesn't affect most of us: don't run nrepl on a machine that is actually multi-user, because anyone on the machine can access the nrepl port and get the full permissions of the user running the clojure process

11:28 but who uses multi user machines for anything nowadays anyway

11:28 michaelr`: i need to import html which the designer built into my om views

11:29 which are written in hiccup (sablono)

11:29 so I thought that I must not be the first to do that :)

11:29 justin_smith: michaelr`: the reason hickory gives you empty strings (or strings with spaces) is that this ensures that the rendering gives you an identical document to the intial input, whitespace and all

11:30 michaelr`: justin_smith: that's fine by me, but it doesn't help with my use case :)

11:30 justin_smith: rihgt

11:30 I think enlive's html-resource likely gives you a cleaner data structure

11:31 or whatever the function is that gives you a data structure from an html file - forgetting the name

11:31 Glenjamin: there's a list here: https://github.com/weavejester/hiccup/wiki/Converting-html-to-hiccup

11:32 justin_smith: Glenjamin: nice!

11:32 michaelr`: Glenjamin: a list!? cool

11:32 justin_smith: (inc Glenjamin)

11:32 lazybot: ⇒ 16

11:32 Glenjamin: it's a fairly short list

11:32 bja: michaelr`, this solution on stack overflow seems to work in my repl pretty well: https://stackoverflow.com/questions/11094837/is-there-a-parser-for-html-to-hiccup-structures

11:32 it uses enlive

11:32 justin_smith: still, we can assume weavejester will update it occasionally

11:33 bja: yeah, that's what I use (or very close to it)

11:34 michaelr`: bja: thanks, let me check that too..

13:11 daGrevis: hi! how is lein test finding tests? i would like to split my core_test.clj into many files

13:11 also, are new kids using lein test or there's another better testing framework out there?

13:12 gfredericks: daGrevis: `lein test` looks through all the namespaces under /test, I think

13:12 so it sounds like you just want to make more namespaces

13:12 normally namespaces <--> files are 1-to-1, with corresponding names

13:13 clojure.test is fine for a lot of people; depends on your taste

13:14 daGrevis: gfredericks, okay, thanks! clojure.test works fine for me too :P

13:15 emaczen: I'm trying to update two lazySeqs in an atom with swap!

13:16 (swap! state update-in [:waste :foundation] rest conj (first waste))

13:16 The keywords have the same name as the arguments passed into the method

13:17 gfredericks: I'm having trouble figuring out what you're going for there

13:17 emaczen: This swap form should do the same thing as (push (pop waste) foundation)

13:17 hiredman: emaczen: that is a race condition

13:17 emaczen: I want to update the lazySeqs given by :waste and :foundation in atom state

13:18 I want the function rest applied to the waste (to remove the first element) and I want to put the first element of waste at the front of foundation

13:19 gfredericks: (swap! state (fn [{:keys [waste] :as current-state}] (-> current-state (update-in [:waste] rest) (update-in [:foundation] conj (first waste)))))

13:20 I think that's basically what you're describing; I have no idea what race condition hiredman is referring to

13:20 emaczen: gfredericks: Thanks very much!

13:20 hiredman: (swap! state update-in [:waste :foundation] rest conj (first waste)) is grabing the first of waste out side of the swap, so it isn't part of the case, so waste in the atom could change

13:21 cas

13:22 assuming this is in some kind of let like (let [{:keys [waste]} @state] ....)

13:25 gfredericks: ah yeah; I tripped up on passing conj to rest and didn't bother interpreting the code any further :)

13:25 emaczen: hiredman is right you definitely want to be careful to do all the reading inside the update function

13:25 which my code does

13:43 anybody know of anything similar to clojure.core/format but that accepts names instead of positional args?

13:44 I'm imagining another throwing helper (macro?) for catch-data that lets your errmsg strings reference values in your ex-data map

13:45 I know about strint in the incubator lib; that could sort of be twisted into the role but it's arbitrary eval so a little different

13:49 daGrevis: i'm trying to make a test setup that creates two browser instances and passes them to test each time. this is what i have so far, but it seems that deftest have no mechanism to accept params. :( https://gist.github.com/b072e75c3a3453723a5d

14:17 crack_user: hello guys

14:26 cap10morgan: given that clojure.lang.Keyword is not part of the public API, what is the idiomatic way of converting a clojure.lang.Keyword into a java.lang.String *from Java code*?

14:27 jjttjj: I have a bunch of data i need to pull from various APIs and store somewhere persistant and query somehow with clojure. It's just to figure out my taxes and i want it to be quick/easy/hacky as possible. Does this sound like a case for mongo or is there anything better? Anything that lets me just persist clojure structures without dealing with file io?

14:32 hiredman: filesystems are a thing these days

14:35 delaney: so i've been learning a bit of clojure in my spare time. something that I can't quite grok. is there a way to de/serialize persistent data structures? for example have a map, add/remove keys and store both versions to edn/fressian/etc. how do you deserialize back to the shared/persistent state where they share most of the same memory space?

14:36 LauJensen: Gents - Ive updated to the most recent version of cider, and now C-M-x no longer drops the result of eval in the repl. Is that intentional or have I borked a setting?

14:36 chouser: delaney: generally, you don't.

14:37 delaney: hmm, i was a afraid of that

14:37 once you save/load you lose a lot of the benefits it seems

14:37 chouser: if you use normal serialization (edn, fressian, transit) you'll get *one* version, and when you read it back in you'll get a whole new unshared data structure

14:37 delaney: right

14:38 is there (not 'normal)?

14:38 :P

14:38 like a memory dump

14:38 chouser: sure, you can serialize the operations applied to a value instead

14:38 delaney: so a transaction log

14:38 chouser: yup

14:40 then you could tag various versions in the transaction log, and when deserializing grab references to those tagged version. Once thats done, those tagged versions would share the memory for their common sub-values.

14:40 delaney: i work mostly in C# and trying to justify time towards clojure, but in practice having a hard time. i love the theory of it but most of the concrete examples seem easier there. sure part of it is familiarity.

14:41 chouser: immutable values have benefits, even in contexts where you don't get structural sharing

14:41 delaney: well yeah, but i already do that in C#

14:41 chouser: in fact, structural sharing isn't really a benefit so much as an attempt to reduce the cost

14:41 delaney: but more from convention than lang level granted

14:42 chouser: ah, well, if you've already got immutability and high-order functions, that is indeed a couple of major talking points removed in an argument for clojure

14:42 delaney: but there is no D in stm's acid beyond things like datomic it seems

14:42 chouser: let's see, what's left -- immutable locals, s-expressions (macros), ...

14:43 delaney: yeah i like the idea of Om, which is what got me interested in clojure (already using react from js land)

14:45 agarman_: C# is a good language, especially as unnecessary syntax keeps getting pruned away each release

14:46 delaney: agarman_: right. if it was a while ago then yeah there is a big diff (and being tied to jvm for sure). maybe its also when looking at the clojure examples or tutorials it just is crazy terse to grok

14:46 the syntax is simple, the complexity moves into the function calls

14:47 again hopefully that melts away with time

14:47 i love the idea of having the same lang server and client side for sure, and edn seems slicker than json for my wants

14:49 agarman_: if you have an opportunity to learn F#, and force yourself to not use mutable (mostly records, tuples & object expressions) you'll have most of the big benefits of Clojure.

14:51 delaney: well i've always loved the jvm's speed, just not the root lang. the clojurescript and even closure-clr makes it seem like there is something there i just don't quite see yet. in no way was it trying to avoid clojure, if anything seeing if i'm just approaching it wrong.

14:51 agarman_: Clojure's atoms & refs are nice though. core.async is great too.

14:55 Even though C# & F# have syntax trees, reflection emit & reified generic containers these are poor substitutes for a good macro system.

14:59 delaney: i sounds dumb but i can't see my need for macros. i know there are canonical examples like (what if you want to write 'if')

14:59 i see they help you basically write compilers, but for the stuff i do it seems weird

14:59 LauJensen: Gents - Ive updated to the most recent version of cider, and now C-M-x no longer drops the result of eval in the repl. Is that intentional or have I borked a setting?

15:00 delaney: like you can't write a macro that does matrix math faster by preprocessing

15:02 agarman_: delaney: C# delegates are all syntactic sugar put in by the special logic in the compiler. If you had macros in C#, you could write that.

15:03 delaney: C# async methods, dynamics, var & many many other items are written as changes to the C# compiler. These could all be done via a library if C# supported macros.

15:04 delaney: i get that, but those constructs are there now. could you write a macro that does that transaction log thing i was talking about before.

15:04 take every map/array function and throw into a transact log?

15:06 amalloy: delaney: for one thing, the compiler would be a lot simpler if it *didn't* have to include that stuff, and could let macros do it instead

15:06 but if you are looking for a simple useful example, i offer https://github.com/amalloy/useful/blob/96f665/src/flatland/useful/map.clj#L6

15:06 so that you can write (keyed [x y z]) instead of {:x x, :y y, :z z}

15:07 agarman_: delaney: you can do a write to transact log in Clojure but you'd usually do it by wrapping the vars that make the changes rather than writing macros

15:10 but that logs operations on map/vector functions instead

15:13 delaney: so why wouldn't you do as a macro?

15:18 agarman_: it may be implemented with macros, but the better usage would be to (transact-log/start) and have that rewrite the vars for the functions that are relevant. So when someone calls (conj ...), (map ...), etc you get your transaction log written without having to change existing calls. It's like AoP but with all of your language already in an IOC container

15:18 amalloy: i don't know that a mass modification of vars is really such a great solution either...

15:19 agarman_: amalloy: It would terrify me.

15:20 for debugging purposes, not so scary.

15:20 amalloy: i disagree. conj and map are called *a lot*. i'd be surprised if you could even get meaningful debug output by modifying their vars, given how much they're called by the standard library

15:20 like, map calls map

15:21 agarman_: true

15:22 * agarman_ turned debug logging on in a hibernate application yesterday. **USELESS**

15:22 amalloy: well, at least java's logging libraries let you turn on debug logging for particular classes/packages individually

15:23 agarman_: yep

15:23 that was an accident of trying to use matthias's inspect library on a piece of clojure in the big Java app

18:25 emaczen: can you multi-method dispatch on just keywords?

18:26 arrdem: sure if your dispatch operation is clojure.core/identity

18:26 emaczen: I'm thinking if my user clicks on two places, then I can make a set of functions for each two-combination

18:27 arrdem: can you give me an example?

18:28 I'm very new to this

18:28 arrdem: yeah sure one minute

18:31 emaczen: https://www.refheap.com/98087

18:31 emaczen: is that helpful?

18:31 emaczen: arrdem: Thanks, I will try this out

18:32 how will this work for pairs?

18:32 pairs of keywords?

18:33 arrdem: emaczen: the dispatch-fn is applied to all arguments.

18:33 emaczen: so try invoking that function with a pair [:foo :bar]

18:34 emaczen: For this line: (defmethod identity-dispatch :foo [foo] "Got a foo!")

18:35 what is the type of foo inside the [] ?

18:35 arrdem: emaczen: foo is simply a symbol naming the value of the 1st and in this case only argument.

18:41 emaczen: arrdem: I keep getting 'No method in multimethod 'pop-pushable?' for dispatch value: [nil

18:41 nil];

18:41 how do I call these methods exactly?

18:41 I'll try wrapping them in a vector first

18:42 That didn't work either

18:42 arrdem: emaczen: can you give me a sample input pair?

18:43 emaczen: (pop-pushable :foo :bar) or (pop-pushable [:foo :bar])

18:43 emaczen: I tried both of those

18:44 arrdem: emaczen: in the form (defmethod identity-dispatch :foo [foo] "Got a foo!") the keyword :foo is the dispatch value for which the method tail returning the strung (fn [foo] "Got a foo!") will be invoked.

18:44 emaczen: when you invoke a dispatch identity multimethod with the pair [:foo :bar], you need to have a method registered for that pair.

18:45 bah I'm sorry I'm doing this wrong.

18:45 emaczen: can you refheap what you have now?

18:46 emaczen: arrdem: Sure, I am trying to make a klondike solitaire game

18:46 Can you look at a pastebin?

18:46 arrdem: sure

18:49 emaczen: arrdem: http://paste.lisp.org/+34P1.

18:50 arrdem: do you get the idea?

18:50 arrdem: emaczen: yeah.

18:51 emaczen: (waste @state) could be :waste, unless there's more code you didn't paste.

18:51 justin_smith: emaczen: the args to your defmulti and your defmethod don't agree in arity

18:52 arrdem: based on the dispatch it would have to be (::waste @state), which looks like it would always be nil

18:53 arrdem: Ah. @justin_smith yeah I see the arity missmatch.

18:53 emaczen: What is the arity mismatch?

18:54 justin_smith: emaczen: your multi takes one arg, the method you create for it takes two

18:54 identity isn't a two argument function, but your defmethod is

18:54 emaczen: I'm not even sure why the multi takes one.... All I did was make the dispatch function be identity

18:54 arrdem: emaczen: if you dispatch on the _pair_ [::waste ::foundation], you have only given the body one argument.

18:54 justin_smith: emaczen: and identity takes two arguments

18:55 emaczen: you could change your dispatch function to be vector

18:55 and then the arities would work

18:55 (defmulti pop-pushable? vector)

18:55 because you can call vector on two args, and it returns the two args such that you can dispatch on them

18:56 or maybe list would be better, it would work the same either way

18:57 arrdem: justin_smith: dispatching on first should be fine...

18:57 justin_smith: in case you want non-constant args elsewhere :P

18:57 justin_smith: arrdem: he matches on two args though

18:57 emaczen: give me a few seconds/minutes -- I am following, but I know this is going to take me a little bit of time to get to work

18:57 arrdem: justin_smith: (foo [dispatch-a dispatch-b] . args)

18:57 amalloy: arrdem: (first x y) doesn't return x

18:58 arrdem: amalloy: correct me if I'm wrong, but I thought that multimethods did (<dispatch-fn> (seq args))

18:58 not (apply <dispatch-fn> args)

18:58 amalloy: arrdem: that is wrong

18:59 the dispatch fn receives exactly the same args as the method does

19:00 justin_smith: arrdem: emaczen: https://www.refheap.com/98090

19:00 that's how you dispatch on two arguments

19:00 arrdem: "This function will be applied to the arguments to the multimethod in order to produce a dispatching value."

19:00 gotcha.,

19:00 on clojure.org/multimethods but not in the docstring. right.

19:00 emaczen: justin_smith: cool!

19:01 I have a new question now...

19:01 I want to dispatch on these two keywords and an integer

19:01 err wait

19:01 sorry

19:02 justin_smith: (fn [a b & optional] [a b])

19:02 it will dispatch on the first two, and the multi itself will get all the args

19:02 emaczen: I just want the integer to be an argument to the function

19:02 justin_smith: they are all arguments

19:03 for clarity, when I said "the multi itself" I mean the form defined in defmethod, that was badly worded

19:03 emaczen: Wait, (defmethod foo [:a :b] [a b i] ... )

19:03 justin_smith: right

19:04 emaczen: cool!

19:04 justin_smith: that would work with the dispatch function I shared above

19:04 because the dispatch just checks the first two args, ignoring the rest

19:04 dfletcher: Ahhh sweet. UI editable with WindowBuilder, main program logic in Clojure. This is what I was after, thanks for the help earlier channel :)

19:05 * dfletcher should write a blog post

19:05 justin_smith: emaczen: updated the paste to show optional args on a defmulti https://www.refheap.com/98090

19:06 dfletcher: sounds cool, I would like to read it

19:07 emaczen: justin_smith: sweet

19:10 how do I remove a defmulti definition from the REPL

19:10 rufoa: you can use interop to do (.addMethod

19:10 so perhaps similar

19:11 look in clojure.lang.MultiFn

19:11 arrdem: $grim clojure.core/remove-all-methods

19:11 lazybot: http://grimoire.arrdem.com/1.6.0/clojure.core/remove-all-methods

19:11 justin_smith: emaczen: it is a def, you can do (def multi-fn-name nil)

19:11 arrdem: $grim clojure.core/remove-method

19:11 lazybot: http://grimoire.arrdem.com/1.6.0/clojure.core/remove-method

19:11 dfletcher: heh oops justin_smith wrong chan. #eclipse helped me figure out how to make this work ;)

19:11 justin_smith: haha

19:11 OK

19:11 dfletcher: is it a clojure thing at all?

19:12 emaczen: arrdem: doesn't that just remove all the methods of the multi?

19:12 arrdem: emaczen: remove-method can remove the method associated with a specific dispatch value.

19:12 dfletcher: my main program logic is in clojure and i pass a window to my clojure main (that was built using some nice gui tools in Eclipse [WindowBuilder])

19:12 justin_smith: emaczen: arrdem: to remove the mutli altogether just do (def your-multi nil)

19:13 *multi

19:13 dfletcher: actually heh maybe I don't even want to pass the window here. but as a test (.show window) is working nicely :>

19:13 emaczen: thanks!

19:13 justin_smith: this is needed in order to redefine multis, because they are defonce

19:14 that's a trick I learned from technomancy, hope he joins us here again some day

19:15 emaczen: isn't technomancy on #emacs a lot?

19:15 justin_smith: yeah, he seems to be taking a break from this channel

19:16 amalloy: $karma technomancy

19:16 lazybot: technomancy has karma 162.

19:16 godd2: I just ordered his keyboard a week and a half ago. can't wait to solder that together

19:18 This one, if anyone's interested: http://atreus.technomancy.us/

19:23 emaczen: justin_smith: I'm still struggling and I'm following your example practically to a tee

19:23 justin_smith: emaczen: is there a specific thing that isn't working?

19:24 emaczen: I'll make a paste

19:26 https://www.refheap.com/98091

19:26 I am calling the method like: (pop-pushable? [::waste ::foundation] 2)

19:27 justin_smith: emaczen: why the vector?

19:27 (pop-pushable? ::waste ::foundation 2)

19:27 should work with the definitions you have there

19:27 emaczen: I tried it like that too and it still says wrong number of args

19:28 I'm going to try restarting my repl

19:28 justin_smith: did you do (def pop-pushable? nil) before redefining the defmulti?

19:29 because just running defmulti again will not replace the old dispatch

19:29 it's varargs, it should only complain about argument count if you provide less than 2 args

19:29 emaczen: justin_smith: yeah, I didn't set it to nil

19:30 justin_smith: $source defmulti

19:31 lazybot: defmulti is http://is.gd/nhS5dG

19:31 justin_smith: emaczen: look at the when-not near the bottom of the definition of defmulti

19:31 it doesn'

19:31 t do anything if the multi is already a multi

19:31 so assigning to nil explicitly is needed in order to redefine the dispatch

19:32 well, asigning to anything that is not a multimethod, or deleting the var itself from the namespace

19:32 but the former is easier

19:33 emaczen: I get a null pointer exception now

19:34 justin_smith: you need to redefine the multifn and it's methods after assigning to nil

19:34 emaczen: justin_smith: I think this is actually in the definition of my multi-method... lol

19:34 I'll keep playing with it

19:34 justin_smith: oh, OK then :)

19:35 here's a funny one:

19:35 blake_: Can map return a map? =P

19:35 justin_smith: ,(nth nil 2)

19:35 clojurebot: nil

19:35 justin_smith: ,(nth () 2)

19:35 clojurebot: #<IndexOutOfBoundsException java.lang.IndexOutOfBoundsException>

19:36 justin_smith: blake_: you can use (into {} (map ...))

19:36 that makes the map eager of course, because {} cannot be lazy

19:36 blake_: justin_smith: Sure, I was just noting the lexical oddity.

19:36 justin_smith: ahh, OK

19:36 yeah, that bugs me sometimes

19:37 blake_: Homophones, man. How do they work?

19:37 amalloy: obviously we should just call them dictionaries

19:37 i think these are actually hononyms, right, not just homophones

19:37 justin_smith: ,(def territory {})

19:37 clojurebot: #'sandbox/territory

19:37 blake_: Yes. There's also "associative arrays", though 'tis cumbersome.

19:37 justin_smith: amalloy: homonym

19:38 oh, they are homophones too

19:38 as many homonyms are

19:38 blake_: justin_smith: All homophones are homonyms. No, strike that, reverse it.

19:38 ALl homonyms ar ehomophones.

19:38 amalloy: blake_: injective cartesian relations

19:38 justin_smith: there are homophones that are not homonyms

19:38 there are homonyms that are not homophones

19:38 like read

19:38 blake_: amalloy: That's good jargon!

19:38 justin_smith: that is homonym but not homophone

19:39 blake_: justin_smith: Well, but not at the same time.

19:39 emaczen: clojure.core/swap!

19:39 ([atom f] [atom f x] [atom f x y] [atom f x y & args])

19:39 amalloy: blake_: huh?

19:39 blake_: justin_smith: If you're saying "red" and "reed", they're no longer homonyms (or homophones).

19:39 justin_smith: I'm just saying, all four options are available: a, b, both a and b, neither a nor b

19:39 emaczen: What do the the different vectors [atom f] [atom f x] mean?

19:40 justin_smith: blake_: I mean "I read it" and "I will read it"

19:40 emaczen: different possible inputs?

19:40 method overloading I mean?

19:40 justin_smith: emaczen: possible arities of a function

19:40 blake_: amalloy: lol, sorry, I thought you were suggesting "injective cartesian relations" as a new way of saying "map".

19:40 justin_smith: emaczen the only kind of overloading we have is argument count

19:40 amalloy: blake_: i was

19:40 i'm objecting to your homonym/homophone claims

19:41 justin_smith: lead and lead are probably a better example, since read and read have similar origins/meanings

19:41 justin_smith: much better example, thanks

19:41 blake_: amalloy: Homophones include homonyms, if I'm not mistaken. Homonyms are homophones that are spelled the same.

19:41 amalloy: blake_: no. homophones are pronounced the same (as the -phone suffix suggests)

19:41 justin_smith: blake_: no, I already explained

19:42 amalloy: homonyms are spelled the same

19:42 justin_smith: some homophones are homonyms, but not all, some homonyms are homophones, but not all

19:43 amalloy: what i don't quite get is the difference between a homonym and homograph

19:43 blake_: Mmmmmm. OK, we're using different definitions. "lead" and "lead" are homographs.

19:43 justin_smith: blake_: these words are in the dictionary

19:44 blake_: Sorry, this is my default:

19:44 In non-technical contexts, the term "homonym" may be used (somewhat confusingly) to refer to words that are either homographs or homophones.

19:44 http://en.wikipedia.org/wiki/Homonym

19:44 justin_smith: blake_: homograph is a synonym for homonym

19:44 blake_: I recommend that page there.

19:45 emaczen: what does {:keys [some variable]} do?

19:45 justin_smith: emaczen: argument destructuring by keyword

19:45 ,(let [{:keys [a b]} {:a 1 :b 2}] (+ a b))

19:45 clojurebot: 3

19:46 justin_smith: blake_: fascinating, I didn't realize that more technical definition existed

19:47 blake_: justin_smith: Yeah. It actually is a lot better than the common definition, which causes much confusion.

19:47 justin_smith: (inc blake__

19:47 err

19:47 (inc blake_)

19:47 lazybot: ⇒ 1

19:47 blake_: (Or, when some jackass uses the non-common definition without quailfying.)

19:47 justin_smith: wat

19:47 blake_: lol

19:47 I lost my braces.

19:47 (inc {blake})

19:47 lazybot: ⇒ 2

19:47 blake_: lol


19:48 justin_smith: what was that unicode? I am in a tty and I just got a replacement character

19:48 (identity blake_)

19:48 lazybot: blake_ has karma 1.

19:49 emaczen: ,(def m {:a 1 :b 2 :c 3})

19:49 clojurebot: #'sandbox/m

19:49 emaczen: (update-in m :a (fn [x] (+ x 1)))

19:49 ,(update-in m :a (fn [x] (+ x 1)))

19:49 clojurebot: #<UnsupportedOperationException java.lang.UnsupportedOperationException: nth not supported on this type: Keyword>

19:50 emaczen: why doesn't that work?

19:50 justin_smith: emaczen: [:a]

19:50 amalloy: emaczen: you are forgetting the brackets again

19:50 emaczen: thanks guys!

19:56 blake_: For finding all the unique keys in a sequence of maps "(keys (apply merge x1))". Tacky?

19:59 emaczen: I need to update two lazySeqs in an atom -- I want to remove the first element of one of the lazySeqs and conjoin it to the front of the other.

19:59 Can you guys give me some advice?

20:00 swap! only takes one function

20:00 amalloy: emaczen: write a pure function that takes in two lazy seqs and returns two new ones

20:00 forgetting about the atom entirely

20:00 then, once that works, adapt it to your atom

20:04 emaczen: amalloy: I made my function, now how do I correctly pass the arguments?

20:04 justin_smith: it should have exactly one argument

20:05 emaczen: (defn pop-push [l1 l2] [(rest l1) (conj l2 (first l1))])

20:05 That is my function

20:05 amalloy: emaczen: what is in your atom, and what does your function look like?

20:06 emaczen: amalloy: there are two lazySeqs (lists) in the Atom that are relevant for pop-push

20:06 amalloy: emaczen: write your function so that it takes as input exactly whatever object is currently in the atom. like, how are you storing two things in one atom? as a list? then your function should take a list and return a list. as a map? then your function should take a map and return a map

20:07 emaczen: amalloy: The atom is a map

20:12 vas: Hi. I want to have short-ids for a bunch of posts that live in a datomic database. I am thinking maybe I can devise a hash function that will figure out the entity ID from the letters and numbers of the short ID (for example, 17592186045438 would map to a667qq2 or some such). Is this a reasonable approach?

20:13 justin_smith: vas: what would you do to handle collisions?

20:14 emaczen: amalloy: The two lazySeqs (lists) are values in the map?

20:14 (defn pop-push [l1 l2] [(rest l1) (conj l2 (first l1))])

20:14 vas: justin_smith: excellent point. does it make more sense to add a unique identifier "on the fly" to the datomic entities?

20:14 (and maybe just go incrementally?)

20:15 justin_smith: vas: that would likely be simpler

20:15 vas: you got some good words in them fingers. thanks yet again friend

20:16 justin_smith: unless there is some clever scheme for short IDs that handle collisions elegantly (for all I know there might be), in which case use that of course

20:16 I try

20:16 emaczen: amalloy: should pop-push take a map? Or should it take two lists?

20:16 amalloy: emaczen: it should take exactly what is in your atom

20:16 justin_smith: emaczen: if you want to update a map, have it take a map

20:18 emaczen: I'm trying to use swap!

20:18 So I am trying to make the function that swap! takes

20:18 justin_smith: in that case, have it take a map, and return one

20:19 emaczen: justin_smith: I will try that

20:22 (defn pop-push [m]

20:22 (update-in m [:waste] (fn [] (conj (first (:deck @state)) (:waste @state))))

20:22 (update-in m [:deck] rest))

20:22 Oops

20:22 justin_smith: emaczen: that would work if you chained it using ->

20:22 emaczen: I'll make a paste for this

20:22 amalloy: emaczen: remember, this is a pure function. it doesn't take in an atom of a map, but a map

20:23 justin_smith: no, there are at least two other things wrong

20:23 justin_smith: yes, you are right

20:24 amalloy: emaczen: try what i was suggesting: forget about the atom entirely. (def sample-map '{:waste (1 2 3) :deck (4 5 6)}), and then write a function that takes in sample-map and returns a new map the way you want it

20:24 emaczen: so I removed, the dereferencing

20:24 amalloy: once you have that, the atom will be super-easy to add

20:25 justin_smith: emaczen: you want no reference to the state global

20:25 just use the map that gets passed in

20:25 emaczen: Okay, let me try this again

20:25 ludbek: does anyone here know how to use clojurescript for meteor development?

20:26 godd2: ludbek quick google leads to meteor-clojurescript: https://github.com/mystor/meteor-clojurescript

20:27 emaczen: (defn pop-push [m]

20:27 {:waste (conj (:waste m) (first (:deck m)))

20:27 :deck (rest (:deck m))})

20:27 How about that?

20:27 ludbek: @godd2, i tried it, but the compiled code some 27k big

20:27 @godd2 is it supposed to be so?

20:28 justin_smith: emaczen: if you use -> chained update-in, (or at least a merge) it would work even if you added more keys to the map

20:28 amalloy: emaczen: that looks pretty good to me

20:28 godd2: ludbek No clue. You might be able to tweet ben orenstein and ask him. I know he does a lot of clojurescript as of late

20:28 justin_smith: emaczen: it's really common to add keys to a map, so code that needs to be edited to add the extra keys is often regretted

20:28 amalloy: emaczen: that function should now just work: (swap! some-atom pop-push)

20:29 emaczen: justin_smith: I'll try the chained variant once this works

20:30 amalloy: Thanks so much! This should take me pretty far :D

20:32 ludbek: @godd2 thanks

20:45 emaczen: justin_smith: the other function that I was asking about first works too :)

20:45 thanks so much guys!

20:46 gfredericks: does anybody know of an approach to using schema or something similar to describe coersions as well as vanilla schemas?

20:49 justin_smith: emaczen: it shouldn't, unless the update-ins are chained with ->

20:49 emaczen: or is that what you mean?

20:50 emaczen: I'm not using update-ins.

20:51 justin_smith: oh, I thought that was what you meant by the other function

20:51 emaczen: (fn [m]

20:51 {:waste (conj (:waste m) (nth n (:deck m)))

20:51 :deck (nthrest (:deck m) n)})))

20:51 I'm doing that

20:51 other function refers to the multi-method questions I had earlier

20:51 justin_smith: oh, OK

21:02 emaczen: how can I get the first 3 elements of a list?

21:02 Is there a function like nthrest?

21:02 justin_smith: (take 3 l)

21:03 emaczen: cool!

21:04 amalloy: nthrest is the opposite, it would remove the first 3

21:04 justin_smith: when would you use nthrest instead of drop?

21:05 amalloy: probably never. but they have different laziness characteristics

21:05 justin_smith: where drop is lazier?

21:05 amalloy: so in theory you might have situations where you'd prefer nthrest

21:05 yeah

21:15 xapak: Hello.

21:17 I’m new to Clojure (I may have tried it before, but this time is for real), and I’d like to know what projects do you recommend to check their source code for “elegantness” and “succinctness”. I’ve been tasked to do a CLI, but also the library part of it (functional), so I’d like to follow some code guideliness besides just the Best Practices on “paper”.

21:20 emaczen: justin_smith: how can I define two optional paramters to a multi?

21:21 I tried just adding another argument as well placing another &

21:34 justin_smith: all the args after the first two are put in one collection

21:35 ,((fn [& args] args) 1 2 3 4)

21:35 clojurebot: (1 2 3 4)

21:35 emaczen: is it treated as var args or as a list inside the function?

21:36 justin_smith: it is var args, which means that inside the function it is a list

21:36 emaczen: There isn't another way to do it?

21:36 justin_smith: you can use destructuring

21:36 but that's just destructuring the list

21:37 ,((fn [& [a b c]] c) 1 2 3)

21:37 clojurebot: 3

21:37 emaczen: justin_smith: cool! I'm happy with that

21:51 skynet9001: is there a good way to see out of date dependencies in a lein project?

21:52 gfredericks: lein ancient

21:52 which might be a plugin

21:52 skynet9001: thanks

21:52 gfredericks: np

21:53 xapak: I’ll ask again in case it was missed:

21:53 I’m new to Clojure (I may have tried it before, but this time is for real), and I’d like to know what projects do you recommend to check their source code for “elegantness” and “succinctness”. I’ve been tasked to do a CLI, but also the library part of it (functional), so I’d like to follow some code guideliness besides just the Best Practices on “paper”.

21:55 justin_smith: xapak: flatland/useful, the various ring libraries, pretty much anything from prismatic

21:56 xapak: Prismatic... I seem to have heard or something from them before.

21:56 justin_smith, awesome, thanks. :)

21:56 justin_smith: xapak: they make schema, plumbing, and graph

22:05 skynet9001: anyone here use the chestnut webapp template?

22:20 I'm getting "ReferenceError: goog is not defined" after using lein ring uberwar on a chestnut project and deploying on tomcat, any ideas?

22:21 justin_smith: skynet9001: how are you building your cljs? are you turning on optimizations?

22:22 skynet9001: justin_smith: looks like :optimizations :none

22:23 justin_smith: try running 'lein with-profile -dev,+uberjar cljsbuild once' before making the uberwar

22:26 skynet9001: will try that, thanks

22:31 so that didn't work, but I'm looking at the /public/js/ directory and it's missing the out.js.map file, although I have :sourcemap "resources/public/js/out.js.map" defined in the cljs build

22:32 I don't see the resources/public/js/out.js.map file in the project, how do I create it?

22:42 justin_smith: cljsbuild should create that. maybe cljsbuild clean then build again?

23:03 skynet9001: still nothing, weird

23:03 I had it working on another machine earlier today, maybe something's misconfigured on this vm

23:04 this is all just the base chestnut template

23:07 justin_smith: I don't see what vm config could break chestnut

23:08 skynet9001: I think on this one I had installed openjdk 8 before installing 7, maybe that had something to do with it

23:08 gonna try a fresh start

23:20 Guthur: Hi, I'm trying to create my own leningen template standard-project. I created the project with lein new template standard-project editted it and then ran lein install

23:20 there were no errors but when I try to use my template with lein new standard-project foo it gives the following...

23:20 Failed to resolve version for standard-project:lein-template:jar:RELEASE

23:21 any suggestions?

23:27 ddellacosta: is there a reason to use atoms vs. dynamic vars for configuration of libs?

23:27 or even something else?

23:33 justin_smith: ddellacosta: a global atom will usually limit how a lib can be used

23:35 ddellacosta: justin_smith: so, if I make configuration an atom, that's going to ensure that/restrict it so that the configuration is accessible across threads, no?

23:35 vs. dynamic vars being thread-local--that's the big distinction, am I right?

23:35 justin_smith: I think the cleanest is the c.j.jdbc approach of a configuration arg, that a client can esaily partially apply

23:38 yeah, an atom means a global config, dynamic vars, thresd local, configuration argument is lexically scoped

23:38 ddellacosta: justin_smith: trying to understand what you mean here--you're talking basically about config always getting passed in as fn args, basically?

23:38 justin_smith: in reference to c.j.j being ideal

23:38 (if that's the case would agree)

23:38 justin_smith: a map ad the first arg, yeah

23:39 the first, because we have partial

23:43 the atom and dynamic var versions can be implemented by the end user in two lines of code

23:43 (given the explicit argument version existing, and taking the config as the first arg)

23:44 the others are not so flexible

Logging service provided by n01se.net