#clojure log - Dec 02 2014

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

2:02 schrotti: greetings

2:04 i'd like to perform thread-safe memcached operations with spyglass, thus want to ask if the following approach leads to this: get the data to be worked on from memcached and reference it with a ref, perform all the work synchronous on the ref and write the final ref value back to memcached

2:05 want to write it as idomatic as possible, thur avoiding explicit locking, that would allow me to perform i/o operations in the locked section

2:08 andyf: schrotti: By thread-safe you mean you want to read one or more values from memcached, calculate modified values, and write back the modified values, and be guaranteed that no other thread in the same JVM process can read any of those same values while you have them ?checked out'?

2:08 And you plan on there being at most one JVM process, but perhaps many threads in that JVM process?

2:10 lain1: Hello. I'm trying to use quil fun-mode to write a simple game. key-pressed is [old-state event] -> new-state and I can get the key that was pressed out of the event. However key-released is just old-state -> new-state so I'm confused how I'm supposed to know which key was released. Anyone have experience with quil?

2:12 schrotti: andyf: correct

2:15 andyf: schrotti: I don?t know if there is a way to do that. memcached seems to have little or nothing in the way of multi-key atomic operations

2:16 lain1: Hmm, looks like there's a (raw-key) function which gets the most recently pressed or released key. Bit clunkier than getting it as a parameter but I'll use that. O well

2:18 schrotti: andyf: yea i know, in a python implementation of the api i set a lock-key in memcached to tell other jvm process (different hosts) this one is being worked on, which actually also should be sufficient for thread within on process on the same jvm

2:18 but within python i locked that critical sections within the code too

2:21 now it seems there's still the time between setting the lock-key in memcache, getting the data i want to fiddle with and ref it.

2:23 andyf: schrotti: If there is only one JVM process, why do you need the data in memcached?

2:23 So the data is still there if the JVM process dies?

2:24 schrotti: andyf: there will be multiple jvm processes at some point in time

2:24 want to use memcache for session data

2:25 andyf: So you need a way to prevent multiple JVM processes from accessing overlapping sets of key/value pairs in memcached in parallel? I don't think refs in one JVM process can help you there.

2:26 schrotti: andyf: thats why i write a key to memcache, that tells the other processes that a certain key is currently being worked on

2:28 andyf: schrotti: Using a memcached cas operation? I don't think normal get/set operations on single keys will prevent races there.

2:29 dysfun: sound like you need a distributed lock mechanism (like redcache, but for memcached) or redis (which supports limited transactionality)

2:29 s/redcache/redlock/

2:31 schrotti: andyf, dysfun thanks for the input i take a look at them

2:32 andyf: schrotti: Example of race for a simple try at using a special key value as a makeshift lock: Every process tries to write to key "global_lock" with a value equal to the name of the keys they want to work on atomically. Process 1 reads "global_lock" and sees it is empty. Then process 2 does. Process 1 writes "global_lock" the set of keys "a, b, c" that it wants access to. Then process 2 does.

2:33 Neither has any way to look at the memcached contents and tell that it isn't the only one.

2:33 You could run something like Baker's mutual exclusions algorithm on top of memcached, but there must be a better way.

2:34 dysfun: i suspect redlock relies on redis transactions

2:34 but it's been a while since i poked at redis

2:35 i'm sure it's findable with enough googling

2:35 andyf: If you want transactions, it seems best to use a database that provides them.

2:36 dysfun: i think some projects don't have the option of choosing postgres

2:37 schrotti: i could use postgres for it

2:38 dysfun: but it's session data, right?

2:38 schrotti: but trying to get away from due to future demands and also just using it to store session data later is kind of overkill

2:39 andyf: dysfun: Why do you say that about postgres? You mentioned transactions being available in redis, so that statement confuses me.

2:39 dysfun: okay, start again. stop talking about building your implementation and start talking about what you want to achieve :)

2:40 andyf: redis transactions are fun. we use redlock for many operations. if you want real transactions, you use something with real transactions

2:40 schrotti: dysfun: session handling for a distributed service

2:41 andyf: and about your example i could use the memcache add function, that only adds a key if it doesn't already exists

2:41 but theres still network delay

2:41 dysfun: but it returns a value to indicate whether it added the key?

2:42 schrotti: yes it'll return true or false respectively

2:42 dysfun: well, that's your mutex then

2:43 (if (set-lock-key!) ... (show-error))

2:44 andyf: as long as memcached doesn't age out that mutex

2:45 dysfun: I've not used redis for transactions. When you say they are fun, do you mean they don't really work as transactions in some way? Or that they are inconvenient to use for some kinds of transactions?

2:46 dysfun: andyf: you know how clojure STM works? redis does a similar thing. except without automatic retry. you'll be wanting carmine to help with that

2:55 schrotti: (dotimes [i 10] (future (while (false? @(mc/add mc-client "lock" 5 i))) (let [r (mc/get mc-client "test") new (inc r)] (mc/set mc-client "test" (* 60 60 24) new) (mc/delete mc-client "lock"))))

2:56 that works

2:57 andyf: schrotti: Unless "lock" is ever aged out of the cache, but perhaps you can prevent that from happening.

2:58 schrotti: andyf: the lock needs to age out, what if the thread fails at some point and doesn't release the global lock?

2:58 all the other processes, threads would deadlock in this case

2:58 andyf: What if it ages out when the process still thinks it has the lock?

2:58 schrotti: andyf: true

2:59 andyf: Again, there may be ways to prevent that, but they probably rely on limiting how long a process can hold the lock, in real-time

2:59 schrotti: that's why it only performs as less operations as possible

2:59 andyf: Just please don't make someone lose property or other valuables if it doesn't work :)

3:00 schrotti: hehe

3:00 andyf: I'm assuming we aren't talking about human lives or health.

3:01 If it's just "ah, someone may have to reload their browser window when this fails", all kinds of hacks have been done.

3:02 schrotti: andyf: it certainly is for health related sensor data

3:02 andyf: then I'm scared you are asking these questions.

3:04 schrotti: andyf: everyone starts somewhere, been only 1 year in the coporate world, and because it's about health data, i want to do the best

3:04 that's why i reimplenting the api, that i wrote previously in python, which is a mess because it was the first rest-api i ever wrote in python. trying to learn from mistakes

3:04 andyf: I don't mean you should not ask questions. I mean, I hope all of this design goes through review of people who know the failure modes of transactional systems before it becomes part of a product, and they suggest something else.

3:05 failure modes of someone trying to implement transactions, but incorrectly, I mean.

3:05 schrotti: andyf: unfortunately that won't happen :/. that's why i have to do my best.

3:06 and in this case it is the session handling for a mobile client

3:06 andyf: so what happens if some of this health related sensor data is reported incorrectly?

3:06 schrotti: thus it does not interfere with the critical point of sending or receiving data

3:07 andyf: I mean, if this code doesn't implement locking correctly, are we saying they have to hit reload on a mobile client and delay getting the correct data, or does it mean they get incorrect data?

3:08 schrotti: it means they would have to reload/relogin on the mobile client, thus possibly receiving data delayed

3:08 andyf: It wouldn't ever happen that someone accidentally gets data from a different session, for example?

3:09 schrotti: andyf: nope

3:10 andyf: I do hope that is true, but if you do not see the failure modes of your example code above, how did you reach the conclusion that only delay of correct data is possible?

3:10 dreamPilot: hey any CLJS people here ?

3:12 schrotti: andyf: if the client didn't receive a session token i due time, that it can use to get the data, it can retry this operation. there's is no specific/critical health data related to any session.

3:13 the session is just a means of validating a given user and password for a mobile client, that uses the token to ask for data

3:14 and because the lock expires after a couple of seconds, the client will be able to aquire a session at some point

3:15 but it does not interfere with receiving any critical data

3:16 andyf: Sorry if I'm not being more helpful -- I would if I had more experience with what you are working on. Perhaps someone else will read this and join in or contact you.

3:17 schrotti: andyf: that's totally fine, you already provided me with valuable thoughts for the brain

3:17 +enough

3:23 Empperi: is there any kind of less css support for clojure as a library, not a leiningen plugin?

3:23 I'd love to use garden but our web designer guys don't really want or have time to learn clojure so it's not an option

3:24 we can live with precompiled less css which is then saved as .css file and pushed to git, but really would like not to do it

3:25 so an optimal solution for us would be a garden like library but which preprocesses less files

3:26 schrotti: andyf: if you're interested -> http://neopythonic.blogspot.tw/2011/08/compare-and-set-in-memcache.html this one provides an example on how to avoid deadlocks and race conditions. and also by limiting the amount of retries, a thread/process performs to acquire the lock.

3:26 kenrestivo: Empperi: there's a lein-less but i haven't used it

3:26 http://crossclj.info/ns/lein-less/latest/project.clj.html

3:27 Empperi: yeah, but that's just a npm wrapper which compiles less files to css

3:27 so not really what I asked for

3:27 I don't want to generate that css into disc

3:27 I just want to serve it

3:28 so in development mode the css is generated everytime from scratch when it is requested and in production mode the generated css would be cached

3:28 I've done less compiler wrappers in java and I could do that in Clojure too but don't feel like it right now if there is an existing solution out there

3:32 SagiCZ1: why cant case have default value?

3:33 ,(case 1 0 "yes" :default "no")

3:33 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching clause: 1>

3:34 andyf: SagiCZ1: It can have a default: http://clojuredocs.org/clojure.core/case Leave out :default

3:34 SagiCZ1: ,(case 1 0 "yes" "no")

3:34 clojurebot: "no"

3:34 Empperi: ,(case 0 "yes" :default "no")

3:34 clojurebot: "no"

3:34 SagiCZ1: andyf: thank you

3:35 Empperi: i think that is wrong

3:35 Empperi: yes I realized that myself too :)

3:35 been sleeping way too little lately

3:35 SagiCZ1: np

3:35 Empperi: 8 week old baby at home, need I say more...

3:36 SagiCZ1: congratulations

3:36 Empperi: thanks

3:36 schrotti: Empperi: congrats

3:36 Empperi: thanks

3:36 schrotti: mine could come anytime now ^^

3:36 Empperi: ,(repeatedly "thanks")

3:36 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn>

3:36 TEttinger: Empperi, baby bjorne, have a baby be a fashion statement

3:36 SagiCZ1: not that making babies is particularly hard

3:36 Empperi: crap, too little sleep :D

3:36 ,(constantly "thanks")

3:36 clojurebot: #<core$constantly$fn__4346 clojure.core$constantly$fn__4346@1e7d0fe>

3:36 TEttinger: ,(repeat 10 "you're welcome")

3:36 clojurebot: ("you're welcome" "you're welcome" "you're welcome" "you're welcome" "you're welcome" ...)

3:37 andyf: SagiCZ1: For males it isn't -- I would recommend not making such a statement to a female :)

3:37 SagiCZ1: haha true that

3:38 ddellacosta: anyone know how to do an "update ... returning" using clojure.java.jdbc?

3:38 seancorfield: ping

3:47 folks, what does fn* do?

3:50 andyf: ddellacosta: It is the guts of the implementation underlying clojure.core/fn

3:50 Like the macro clojure.core/fn, but without many of the options

3:51 ddellacosta: andyf: thanks. I'm struggling to understand what it is doing all over c.j.j, for example here: https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L695

3:51 looks like it's consistently getting called w/metadata {:once true} but not sure what that means

3:52 I find this codebase quite confusing, I feel like it uses a very specific style which I haven't seen elsewhere

3:53 andyf: In that particular case, it is defining a function that is bound to symbol exec-and-return-keys, which is later called inside of with-db-transaction.

3:53 ddellacosta: andyf: that much I get--I just don't understand why it is used at all. What does {:once true} do?

3:53 andyf: {:once true} has something to do with allowing the function to clear local variables after use, I think. In any case it is a time and/or memory optimization that shouldn't affect correct operation unless you are holding on to the head of a large sequence.

3:54 ddellacosta: andyf: I see, thanks for the explanation

3:54 yeah, it would make sense if most of the arcana in this lib is optimization stuff

4:02 SagiCZ1: how do i make a list from map keys and vals? {:a 0 :b 2} --> (:a 0 :b 2)

4:04 ,(zipmap {:a 0 :b 2})

4:04 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core/zipmap>

4:05 SagiCZ1: ,(flatten {:a 0 :b 2})

4:05 clojurebot: ()

4:10 andyf: ddellacosta: Relevant Google group thread: https://groups.google.com/forum/#!searchin/clojure/malloy$20once/clojure/Ys3kEz5c_eE/3St2AbIc3zMJ

4:10 SagiCZ1: andyf, sorry to bother you but do you have any idea how to achieve what i asked for?

4:10 ddellacosta: andyf: thanks so much!

4:11 very helpful

4:11 andyf: SagiCZ1: I think (interleave (keys m) (vals m)) may be correct

4:12 SagiCZ1: andyf: perfect, thank you!

4:12 (inc andyf)

4:20 andyf: maybe more cryptic: (mapcat identity m)

4:23 hellofun`: andyf did you say core/fn was a macro??

4:23 hellofunk: maybe i misread

4:23 andyf: yes, it is.

4:24 cfleming: hellofunk: Yes, it is

4:24 hellofunk: andyf officially isn't it a special form?

4:24 cfleming: Along with defn, let, and many others.

4:24 andyf: clojure.core/fn is a macro implemented with defmacro. It expands to a special form fn*

4:25 Not all, but many things that you often think of as special forms actually are implemented as macros

4:25 hellofunk: interesting. the (doc fn) just says it is a special form. usually the doc shows if something is a macro

4:25 andyf: let -> let*

4:25 cfleming: reify -> reify*, deftype -> deftype*

4:25 andyf: Try (source fn)

4:25 cfleming: The * forms are actually interpreted by the compiler.

4:25 Well, compiled is perhaps a better word.

4:26 hellofunk: well that is quite interesting.

4:26 listen, andyf, i would like to thank you. thank you most earnestly for brining this matter to my imminent attention

4:26 cfleming: ,(macroexpand '(fn [x] x))

4:26 clojurebot: (fn* ([x] x))

4:27 cfleming: ,(macroexpand '(let [a :a] a))

4:27 clojurebot: (let* [a :a] a)

4:27 andyf: If you'd like a complete list of things that are 'really special':

4:28 ,(keys clojure.lang.Compiler/specials)

4:28 clojurebot: (& monitor-exit case* try reify* ...)

4:28 hellofunk: andyf i already know that list

4:28 Wall-E, blueberries, Belgian beer. those are the things that are "really special"

4:45 kral: namaste

4:47 TEttinger: ,(rand-nth ["Hey" "Yo" "Hi!" "Hola"])

4:47 clojurebot: "Hola"

4:47 clgv: :P

5:04 schmir: I'd like to automatically coerce a joda localdate object to an sqldate in clojure.java.jdbc. is that possible?

5:09 klokbaske: Hey! Any ring users here?

5:09 andyf: ~anyone

5:09 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

5:10 klokbaske: I'm trying to find my stacktrace when ring returns an error 500

5:10 But it's seemingly nowhere to be found

5:11 weavejester: Do you have anything to catch the exception, e.g. Cider, or to display the stacktrace, e.g. wrap-stacktrace?

5:12 klokbaske: I have cider running, and I've added wrap-stacktrace

5:13 I've checked various buffers in emacs but nothing there either

5:14 roderyk: Could someone explain what I'm doing wrong with this snippet of core.async [cljs]? The browser is giving me a most unhelpful message: http://pastebin.com/H6G1dNs5

5:19 weavejester: klokbaske: Which version of Ring are you running?

5:19 klokbaske: 1.3.1

5:21 weavejester: 1.3.1

5:23 weavejester: klokbaske: Okay, so wrap-stacktrace will catch any Throwable... What does the webpage/command line look like when the error occurs?

5:23 Are you running it locally?

5:24 klokbaske: weavejester: yes I'm running locally. Nothing in the commandline. I'm just doing a curl, and I only get a header with a code 500

5:24 weavejester: klokbaske: Is wrap-stacktrace the last middleware you use?

5:25 klokbaske: weavejester: yes, last one.

5:26 weavejester: klokbaske: That should catch any throwable then, and even if it didn't, you should see at least the exception printed.

5:26 klokbaske: Which adapter are you using?

5:26 Kneiva: schmir: I think you can get java.util.Date from LocalDate. Can that be used to create clojure.java.jdbc.sqldate?

5:26 klokbaske: weavejester: I'm using jetty

5:27 weavejester: roderyk: I can't see anything wrong with that, unless you're missing a require somewhere?

5:27 klokbaske: Okay... that's odd. Jetty's usually pretty good about reporting errors.

5:28 klokbaske: I think I'd need to see your project. I can't think of any reason why you wouldn't be seeing an error.

5:28 klokbaske: Unless your code is returning an empty 500 response explicitly.

5:29 klokbaske: Nope, it's not. I have a homemade handler that cannot seem to handle a list, but does handle a map. I wonder if my handler swallows the error

5:29 I think I'll try disabling it.

5:30 schmir: Kneiva: sure. but I was hoping for an automatic conversion.

5:40 triss: hey all. I'm following this heroku/clojure tutorial. everything goes well until i set up the postgresql server on this page: https://devcenter.heroku.com/articles/getting-started-with-clojure#provision-a-database

5:41 i get this error upon running the code:

5:41 org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of clojure.lang.Keyword. Use setObject() with an explicit Types

5:41 value to specify the type to use.

5:41 hellofunk: if i want a recursive fn in a let binding, does it recur on the let var name, or on a name defined in the fn itself? i.e. (let [a (fn b [] .. (b ..))]) -- is that (b ..) correct or would (a ..) suffice?

5:42 roderyk: weavejester: thanks; was accidentally using an old version of core.async

5:42 triss: does anyone know how to set the type of data? I presume I need to tell postgresql to expect a string or specify to clojure what typ the thing is its recording.

5:45 clgv: hellofunk: you can just use `recur`

5:46 hellofunk: or did you mean non-tail recursive?

5:47 hellofunk: non-tail recursive #(let [a (fn b [x, s] (if (pos? n) (b (dec n)) (recur (dec n) (* n s)))] (a 5 1))

5:47 hellofunk: clgv recur would work in my case. but suppose it is not tail recursive? i always get confused which name a fn in a let refers to -- the name given to fn or the name assigned in let

5:47 clgv: ,(let [a (fn b [x, s] (if (pos? n) (b (dec n)) (recur (dec n) (* n s)))] (a 5 1))

5:47 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

5:48 vijaykiran: triss: Can't you use type hints ? ^String etc. ?

5:48 clgv: ,(let [a (fn b [x, s] (if (pos? n) (b (dec n), (* n s)) s)] (a 5 1))

5:48 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]>

5:48 clgv: ,(let [a (fn b [x, s] (if (pos? n) (b (dec n), (* n s)) s))] (a 5 1))

5:48 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: n in this context, compiling:(NO_SOURCE_PATH:0:0)>

5:48 vijaykiran: triss: http://clojure.org/java_interop#Java%20Interop-Type%20Hints

5:48 clgv: ,(let [a (fn b [x, s] (if (pos? x) (b (dec x), (* x s)) s))] (a 5 1))

5:48 clojurebot: 120

5:49 clgv: hellofunk: `a` is not bound to the function while the function is defined

5:49 hellofunk: clgv ok so inside the fn, the name of "a" is not used

5:49 got it

5:49 clgv: hellofunk: yeah, it either is not bound at all or bound to a previous value in the lexical scope

5:53 hyPiRion: Assume I have the syntax-quoted form `(let [f# foo g# baz] (bar f# (expr-with g#))), but bar is a macro I want to expand at syntax-quote time. What's the best way to handle this?

5:55 daniel__: trying emacs again with evil-mode, cider, clojure-mode

5:55 .clj keep opening in fundamental mode, so no syntax highlighting

5:57 vijaykiran: daniel__: did you get it to work ? or is that a question ?

5:57 daniel__: https://github.com/danielstockton/dotfiles/blob/master/emacs

5:57 its a question

5:57 vijaykiran: okay - you might need a hook

5:58 daniel__: similar to line 35

5:58 daniel__: can't find anything like that mentioned in any of the package docs

5:59 triss: vijaykiran... unfortunately that didn't work

5:59 I specified a type hint for the record function

6:00 vijaykiran: daniel__: the automode is in clojure-mode

6:01 daniel__: try adding a require ? perhaps the clojure-mode isn't auto-loaded in your setting

6:01 daniel__: vijaykiran: that worked

6:01 cheers

6:03 hellofunk: hyPiRion interesting, you are saying you want it to expand, and then a additional expansion after it expands, due to the macro. is that not what happens?

6:09 hyPiRion: hellofunk: it happens, but I need to print the form out, then read it back in in a different environment

6:09 which doesn't have the same namespaces available

6:11 I found out that it wasn't sufficient to solve my problem anyway, so I'll have to handle this differently.

6:21 martinklepsch: how can I create a string like "\/some\/uri.html"?

6:21 ,(str "\/some\/uri.html")

6:21 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \/>

6:21 martinklepsch: ,(str "\\/some\\/uri.html")

6:21 clojurebot: "\\/some\\/uri.html"

6:22 martinklepsch: I render this through chesire's generate string and it turns up in the result with two backslashes per slash

6:30 clgv: hyPiRion: at syntax quote time? can you give an example what that would do?

6:31 martinklepsch: print it and you see the actual characters

6:32 martinklepsch: clgv: that's what I thought too but when I pass it to chesire I still end up with two backslashes even though println shows only one

6:32 clgv: martinklepsch: backslashes are used to escape special characters like newline "\n" but hence backslash itself needs to be escaped

6:32 martinklepsch: clgv: data.json has an option for this, I'll try this now

6:33 clgv: martinklepsch: maybe it is using `pr` instead of `print` ?

6:33 TEttinger: ,(pr "\\/some\\/uri.html")

6:33 clojurebot: "\\/some\\/uri.html"

6:34 TEttinger: ,(print "\\/some\\/uri.html")

6:34 clojurebot: \/some\/uri.html

6:34 TEttinger: pr is so it can be consumed by clojure, as if in source

6:34 martinklepsch: clgv: could be

6:35 hellofunk: how do you check if something is an atom, such as + :a varname, etc? I was looking for atom? but it's not there. I could check if something is not a collection like (not (coll? ..)) but that seems verbose

6:35 clgv: ,atom?

6:35 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: atom? in this context, compiling:(NO_SOURCE_PATH:0:0)>

6:35 clgv: ,(instance? clojure.lang.Atom (atom 0))

6:35 clojurebot: true

6:36 hellofunk: clgv that is equally verbose. shouldn't have to query the implementation's class name

6:36 by the way, by atom I am not referring to a reference type, rather a classic lisp atom. symbol? seemed close, but it doesn't cover everything of course

6:37 is this the only way? (defn my-atom? [a] (not (coll? a)))

6:37 clgv: hellofunk: oh you can just ask whether it is not one of the collection types

6:39 hellofunk: since there might be arbitrary many collection and atom classes - this predicate is impossible to write. would be different if all the collections share a common interface.

6:39 hellofunk: makes sense

6:39 clgv: hellofunk: so for clojure data you might be able to write that predicate for given clojure version

6:40 hellofunk: you could also first detect the non-atoms you are interested and everything else is classified as atom - depends on your use cases whether this is appropriate

6:40 hellofunk: sure

6:41 i think common lisp has something like atom? which is what i was looking for. no bid deal.

6:43 clgv: hellofunk: it is probably easier over there since all collections are based on lists

6:43 so non-list is atom

6:46 hyPiRion: clgv: I want something that can transform `(let [f# 1] (.. f# toString hashCode)) into '(clojure.core/let [f__1 1] (. (. f__1 toString) hashCode))

6:46 That only expands "..", in this case

6:48 CookedGryphon: Does anybody have any suggestions for how to test core.async with timeouts?

6:49 I want to set the test up to say behave as if these events came in and then this timeout fired etc

6:49 obviously without actually waiting for the timeout to fire

6:49 clgv: hyPiRion: just tried that syntax quote. is the problem that `toString` and `hashCode` get a namespace prefix?

6:50 hyPiRion: or do you need the "expanded name" of the gensym?

6:55 ah. selective expansion

6:55 hyPiRion: you could do that with zach tellmans walking lib?

6:55 hyPiRion: riddley

6:57 hyPiRion: if I remember correctly you can also manipulate tools.macro's macroexpand-all to not expand given forms.

6:58 hyPiRion: it has an internal machanism therefore but does not provide an option to initialize its data from the macroexpand functions

7:03 hyPiRion: clgv: I know about it, just wondered if there was an easy way out

7:03 figured out a better solution in the end either way

7:03 clgv: ok. what did you do?

7:06 hyPiRion: I avoided the problem altogether :)

7:10 clgv: :)

7:37 noncom: have anyone tried clojure monger lib? i want to update an existing document, adding fields to it.. the only way i have found is to 1) download the document, 2) merge it on my side, upload the merged doc

7:37 is there any way to perform the merge on the db side ?

7:38 the (update) functions seems like it should be able to do that, but i am not sure how to make it work.. currently it simply replaces the document

7:47 vijaykiran: noncom: is monger.collection/update what you are using ?

7:47 noncom: vijaykiran: yes, this is it

7:47 vijaykiran: noncom: can you gist the code that isn't working?

7:48 noncom: here: https://www.refheap.com/94284

7:49 see, if i do not first fetch an existing document, then merge it with data manually, then it will simply *replace* the doc in the db

7:49 so i have to manuall y merge the maps

7:49 vijaykiran: 1 min

7:49 noncom: i have tried playing with the :upsert param but it does not change much..

7:49 ok

7:49 vijaykiran: why are you using :upsert ?

7:50 ah, okay :)

7:50 noncom: :)

7:51 edw: ,(+)

7:51 clojurebot: 0

7:51 clgv: ,(*)

7:51 clojurebot: 1

7:51 noncom: ,(-)

7:51 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/->

7:51 noncom: :(

7:52 clgv: haha

7:52 noncom: booom! )

7:52 hyPiRion: - is not a monoid

7:52 ,(->)

7:52 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/->>

7:52 hyPiRion: ,(->>)

7:52 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/->>>

7:52 noncom: heeh

7:53 ,(<)

7:53 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/<>

7:53 clgv: hyPiRion: operators are no monids ;)

7:53 noncom: ,(bit-and)

7:53 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/bit-and>

7:53 clgv: +o

7:53 hyPiRion: clgv: this is true

7:53 noncom: is (bit-and) a monoid ?

7:53 looks like np

7:53 no

7:54 ,(bit-or)

7:54 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/bit-or>

7:54 noncom: oh well..

7:54 ok ok

7:54 clgv: not every function needs a zero arity. ;)

7:55 Deraen: noncom: http://clojuremongodb.info/articles/updating.html#using_set_operator

7:55 hyPiRion: ,(apply distinct? []) ; :-(

7:55 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/distinct?>

7:56 vijaykiran: noncom: I think you need to use $set

7:56 noncom: just like you do on mongo shell

7:56 noncom: https://github.com/michaelklishin/monger/blob/master/src/clojure/monger/operators.clj#L116

7:57 clgv: ,(distinct [])

7:57 clojurebot: ()

7:57 clgv: ;)

7:57 hyPiRion: I am still confused about that one.

7:57 clgv: yeah, update-in was pretty bad for empty paths as well

7:58 noncom: Deraen, vijaykiran: oh wow, right! $set does the right thing!

7:58 (distinct (list))

7:58 ,(distinct (list))

7:58 clojurebot: ()

7:58 noncom: ,(distinct (vector))

7:58 clojurebot: ()

7:59 clgv: distinct is lazy, hence the list like return

7:59 distinct is a good candidate for a transducer

8:00 noncom: (apply distinct? (list)) cannot operate on that argument because (distinct?) has no meaning over an empty collecion i think

8:01 hyPiRion: Boils down to: Are all elements in an empty collection different?

8:01 I can verify that no element in an empty collection is equal to another element, but I don't know if that equates to the above.

8:02 noncom: i am sure there is a pocket of math that has already considered this case..

8:03 hyPiRion: From wikipedia: "Two or more things are distinct if no two of them are the same thing."

8:03 clgv: hyPiRion: from a math point of view that shoud evaluate to true

8:03 hyPiRion: which makes (distinct? x) sort-of weird

8:05 noncom: http://www.thefreedictionary.com/distinct

8:05 meanings 2, 3 and 5 from the first group for the adj are applicable :)

8:06 meaning 1 is not :D

8:06 clgv: noncom: meaning (1) - every item of the empty list is distinguishable from all the others

8:07 noncom: clgv: how do you know that if you've never ever seen them? :D

8:08 clgv: noncom: that's the point, there is no element in the list, hence that predicate is true

8:08 noncom: well, i can't say more except for that it gives creeps to me :D

8:08 an empty set is the ultimate true..

8:09 clgv: noncom: not really if your are interested in existence of elements with properties it is false ;)

8:11 noncom: so, anyhow, it turns out that emptiness is the truth..

8:12 isn't that from buddhism or somewhere.. ?

8:12 clgv: sounds like "zen" ;)

8:13 noncom: so now i am sure all that whole zen or buddhism thing is just a way to experience the groups theory in person

8:17 l3dx: I tried to mash together some of these snippets -> https://github.com/james-henderson/chord but I'm not able to fetch the message from the server. is this because the samples are simplified, or should it be possible without go-loops?

8:24 clgv: l3dx: there is an example project. does that work?

8:25 l3dx: haven't tried it, but it uses go-loop

8:28 that's probably what I want though, but as this is my first go at core.async I wanted to take baby steps

8:29 combining the client send / server send snippets might not even make sense :)

8:34 clgv: l3dx: well you can consider starting from a working small project as baby steps as well. you can start to alter that project to what you want bit by bit

8:35 l3dx: yeah, sure :)

8:59 puredanger: Bronsa: you around?

9:07 crispin: hi everyone!

9:08 I have a question: What is the difference between binding and let

9:08 other then the binding binds the args in parallel, while let does them one at a time

9:08 other than that... is there any difference?

9:08 when would I use binding instead of let?

9:10 clgv: crispin: binding is for thread local variables

9:11 crispin: those named similar to "*foo*" declared with metada ^:dynamic

9:11 llasram: `binding` binds a new value to an existing Var (usually a top-level persistent thing) for the dynamic, thread-local scope of the `binding` form

9:11 `let` creates a new local lexical identifier for a value

9:15 stuartsierra: More fundamentally, with `let` only code within the text body of the `let` can see the symbols. With `binding`, the values are visible to any code inside the body of the `binding` AND any functions called from there.

9:16 Bronsa: puredanger: hi

9:17 clgv: crispin: you can use `binding` only with names that can be resolved to existing variables

9:18 noncom|2: who can explain that:

9:19 ,(def bs (.toBytes "heeeey" "utf-8"))

9:19 clojurebot: #<CompilerException java.lang.IllegalArgumentException: No matching method found: toBytes for class java.lang.String, compiling:(NO_SOURCE_FILE:0:0)>

9:19 noncom|2: oops

9:19 ,(def bs (.getBytes "heeeey" "utf-8"))

9:19 clojurebot: #'sandbox/bs

9:19 noncom|2: (.-length bs)

9:19 ,(.-length bs)

9:19 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: length for class [B>

9:19 noncom|2: why no matching field ?

9:19 how to access length ?

9:20 opqdonut: ,(alength (.getBytes "heeeeey" "utf-8"))

9:20 clojurebot: 7

9:20 opqdonut: ,(doc alength)

9:20 clojurebot: "([array]); Returns the length of the Java array. Works on arrays of all types."

9:20 opqdonut: I think count works also

9:20 ,(count (.getBytes "heeeeey" "utf-8"))

9:20 clojurebot: 7

9:20 opqdonut: but is less efficient

9:24 nonuby: if my clojure 1.6 simple web apps depends on compojure (https://github.com/weavejester/compojure/blob/master/project.clj) and I dont use an :exclusions in project.clj does this mean that both clojure 1.6 and clojure 1.5.1 are loaded and thus nearly double startup time (given jvm alone startup really is neglible nowdays)

9:25 weavejester: nonuby: No, only one version of the package is loaded.

9:25 nonuby: which is the top level one in my web app project.clj?

9:26 weavejester: nonuby: The one that's chosen is the one "closest" to your project file. So anything in your project file will be preferred, then first-level dependencies, then second-level dependencies and so forth.

9:26 nonuby: so you only specify exclusions if you suspect two sibling dependencies at same closest level might be battling over a specific downstream dependencies

9:27 weavejester: nonuby: Right, or if a closer dependency is overriding a newer but further away dependency.

9:32 triss: so lets say i want to write a library for myself and have no intention of putting it on clojars]

9:32 how do i add the library to my dependancies in project.clj if its just a bundle of local files?

9:33 kungi: triss: you can use toolk like apache archiva and create your own maven repository

9:33 triss: or you can use lein install to install it into your local maven repository and just use it in your project.clj

9:34 triss: ah so lein install means i can then just stick the libs name in my project.clj and get on with things?

9:35 kungi: triss: yes

9:35 triss: splendid...

9:35 kungi: triss: oh yes

9:35 triss: I'll be serving my app up on heroku

9:35 any one know how would i make sure the library makes it up there when i do a git commit?

9:49 hellofunk: amalloy are you around?

9:49 guess not.

9:49 crispin: clgv llasram stuartsierra: thanks. will experiment

9:50 justin_smith: it's very early west coast time right now - he'll likely be awake in a couple of hours

9:51 hellofunk: justin_smith i just realized that. thanks, i forgot what time it is there in u.s.

9:53 puredanger: (inc Bronsa)

9:54 lazybot sleeping?

9:55 hyPiRion: ~lazybot

9:55 justin_smith: must be knocked offline

9:55 clojurebot: lazybot is a lazybut

9:55 justin_smith: I have a login on that box, but I don't think I have perms to restart it

9:55 FriedBob: You don't get a name like lazybot by doing work.

9:55 puredanger: well anyhow, thanks to Bronsa for knowing too much about how AOT works and explaining it to me

9:57 noncom|2: i need to publish an existing jar to clojars

9:57 i have no pom for it

9:57 can anyone tell me what to do ?

10:02 llasram: noncom|2: for your .-length q from earlier: the Java `array.length` syntax is Java syntactic sugar for a JVM array-length operation. There's no actual .-length property, which is why that Clojure syntax doesn't work

10:04 noncom|2: For deploying an arbitrary jar to Clojars, you can use maven: http://maven.apache.org/guides/mini/guide-3rd-party-jars-remote.html

10:04 With e.g. https://github.com/ato/clojars-web/wiki/pushing as your destination repo

10:07 noncom|2: llasram: so the only way to get a correct pom is to use mvn ?

10:08 hyPiRion: noncom|2: you can make one from lein too, using lein pom. But you'd probably have to use mvn to deploy

10:09 noncom|2: A better solution is to ask the original author to publish it.

10:09 noncom|2: it is actually the dropbox official java drivers

10:10 they just don't have them on clojars..

10:10 i fear they won't be quick enough to react also..

10:11 hyPiRion: noncom|2: https://www.dropbox.com/developers/core/sdks/java ? That one's already deployed

10:11 stuartsierra: http://search.maven.org/#search%7Cga%7C1%7Cdropbox

10:11 The Maven world is much bigger than Clojars :)

10:11 hyPiRion: [com.dropbox.core/dropbox-core-sdk "1.7"]

10:12 1.7.7, rather.

10:13 noncom|2: oh!

10:15 btw, as a question for the future, can i fetch jars from maven repos other than clojars ?

10:16 there must be a lein project param for that ?

10:16 kungi: noncom|2: there is

10:16 noncom|2: oh ok, then in case of the situation, i will try that too

10:16 kungi: noncom|2: the :repositories key

10:17 hyPiRion: noncom|2: maven central is bundled by default, btw

10:17 Clojure is put there, for example.

10:20 deadghost: I feel dumb typing (in-ns 'project.core) and (in-ns 'project.other-other-ns) all the time

10:21 and switching back and forth via typing

10:21 is there something more alt-tabish

10:22 llasram: deadghost: your editor integration should provide something

10:22 deadghost: what are you using?

10:22 deadghost: emacs

10:22 llasram: With CIDER?

10:22 deadghost: yes

10:22 llasram: cider-repl-set-ns, by default bound to C-c M-n

10:27 deadghost: http://i.imgur.com/9fW0xw9.png

10:27 whyyyy

10:28 llasram: Because ztellman is hilarious

10:29 Glenjamin: haha

10:36 hyPiRion: obligatory http://aphyr.com/media/context.html

10:37 llasram: Oh is that the ztellmen presentation slide generator?

10:37 hyPiRion: yes

10:38 clgv: hyPiRion: seems not business ready, there are no charts ;)

10:38 tim___: I got "despite our best efforts, optimization is mutable", true dat.

10:39 llasram: "abstraction supercedes essence"

10:39 I can see how one could argue that

10:40 hyPiRion: "macro is a function monster"

10:44 EvanR: parenthetically, ALEPH => DERRIDA -?> DECOMPLECTION

10:45 referential transparency assumes infinite resources, this guy is off putting even without audio

10:47 Glenjamin: you know those are random, right?

10:47 EvanR: the last one is not

10:47 Glenjamin: oh right

10:47 EvanR: this attitude, i think i am beginning to grok, and be able to reproduce in isolation

10:48 Glenjamin: i was fairly sure he said lazy evaluation assumes infinite resources

10:48 EvanR: "dont try to do anything right because startup 1 out of 5234 ended up with way too much workload"

10:48 "and failed"

10:49 llasram: EvanR: I think you're missing a lot of context

10:49 EvanR: dont worry about the other startups which just failed for other reasons, and start ups that succeed and do not ever encounter the google-sized problems

10:49 llasram: XYZ is contextual, oh no, i forgot to right that one down

10:50 its not a presentation without being melodramatic, i think this gets in the way of real world problems (for most problem solvers)

10:51 justin_smith: EvanR: he is explicitly talking about what you do when you hit performance limits. If you don't hit those limits, you obviously don't need that advice.

10:51 EvanR: obviously!

10:51 if only any job i ever had thought that was obvious

10:52 granted i didnt invent google or youtube

10:53 eraserhd: Is it possible to use a clojar from a maven project? How would one set the groupId and artifactId for something that advertises itself as '[ring-mock "0.1.5"]?

10:54 justin_smith: EvanR: I'm actually a big fan of the pragmatism in ztellman's stuff (and the same pragmatism in Clojure core). Purity is nice, but you should make a note of performance issues when your code is in every user's bottleneck (and with the lang, or a good lib, it will be)

10:54 llasram: eraserhd: The group-id is the same as the artifact-id

10:55 eraserhd: It should work fine, just adding clojars as a repository

10:55 EvanR: justin_smith: if this is about clojures implementation or design specifically, then nevermind

10:56 eraserhd: llasram: Ah, thanks.

10:59 tbaldridge: justin_smith: EvanR: once, over drinks, I Rich said something that stuck with me: "don't assume that some optimization that works well for a megacorp will work well for you"

10:59 hellofunk: i have a compojure route like this: (route/resources "/") in my resources/public i have /images/image.png. when i run this locally, the image routes and appears fine. when i deploy to heroku, it is a broken link. any ideas?

11:00 tbaldridge: I think the example was SPDY, it may save hundreds of thousands for Google, but it's an utter waste of time for a site with just a few servers.

11:00 weavejester: hellofunk: Which version of Ring/Compojure are you using?

11:00 hellofunk: weavejester compojure 1.1.8

11:01 weavejester but why would it be a versioning issue if it works fine on my local hosted with the same version as it is when deployed to heroku?

11:02 weavejester: hellofunk: Well, if you're up to date then it's easier to debug. I don't need to think about whether you might be hitting a known bug.

11:03 EvanR: tbaldridge: i wish, when faced with suggestions for web-scale killer hacks, i had some sort of simulation or model that i could run and see if it could make a damn of a difference, rather than relying on my reputation or badass demeanor to prove a point to someone who shouldnt believe me at all

11:03 hellofunk: weavejester well its a production app so we don't update too quickly without our own testing. i suspect there is something else going on here.

11:04 weavejester: hellofunk: Maybe. Sometimes production setups are different enough to development setups to make a difference. What happens when you access the image hosted on Heroku? A 404? A 500?

11:04 EvanR: ,(some #{'a 'b 'c} ['e 'f 'g])

11:04 clojurebot: nil

11:04 weavejester: hellofunk: Are you starting from an uberjar or Leiningen? Are you using lein ring or lein run?

11:04 EvanR: ,(some #{'a 'b 'c} ['e 'f 'b])

11:04 clojurebot: b

11:05 tbaldridge: EvanR: not sure I understand

11:05 hellofunk: weavejester it's a 404

11:06 weavejester i am running on heroku which i think uses uberjar

11:06 * EvanR mumbles incoherently behind the channel somewhere

11:06 hellofunk: weavejester locally i am just starting the server with jetty from repl

11:06 weavejester: hellofunk: Try building the uberjar and seeing if that works or contains the file?

11:07 EvanR: ,(some #{'a 'b 'c} 'b)

11:07 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>

11:07 hellofunk: weavejester i must admit i have never built an uberjar before, have not had the need. i will lookup how to do this (I have no Java background)

11:07 weavejester: hellofunk: It's just "lein uberjar"

11:07 hellofunk: weavejester then how do i inspect its contents?

11:08 weavejester: hellofunk: If Heroku is using an uberjar, it'll just use that command.

11:08 hellofunk: jar -tf foo.jar

11:08 hellofunk: Or just unzip it. Jars are zips.

11:08 hellofunk: weavejester thanks it is building now.

11:08 justin_smith: weavejester: hellofunk: emacs or vi will open the insides of jars as if they were directories and let you open the files inside

11:09 s/vi/vim

11:09 hellofunk: weavejester it creates both a standalone as well as snapshot, which is the one i am interested in?

11:09 weavejester: hellofunk: The standalone just contains all of the dependencies. You want the normal jar.

11:10 hellofunk: Come to think of it, "lein jar" would have worked as well if all you wanted to do was look at the jar's content.

11:11 hellofunk: weavejester the file is in the jar under public/images as expected.

11:12 weavejester: hellofunk: If you execute the uberjar (the standalone one) with "java -jar", does it work as expected?

11:13 hellofunk: And does the image have the right headers? Content type, etc.?

11:13 hellofunk: weavejester actually i think i found the issue. one moment i shall update.

11:15 fairuz: Hi guys. I require a library called clojurewerkz.ogre.core. I did check their source code and this ns do exist. But in my repl, it says java.io.FileNotFoundException: Could not locate clojurewerkz/ogre/core__init.class or clojurewerkz/ogre/core.clj on classpath:

11:15 Any suggestions? thanks

11:16 justin_smith: fairuz: on github it doesn't exist in the current version https://github.com/clojurewerkz/ogre/tree/master/test/clojurewerkz/ogre maybe you are looking at the wrong version of the source

11:16 hellofunk: weavejester so the image name is quite long and one character was the wrong case. apparently this is forgiven when launching to localhost for some reason, while it is not forgiven when launching from heroku. not sure why that would be, but glad I found it.

11:17 weavejester: hellofunk: Are you developing on a mac?

11:17 hellofunk: weavejester: yes

11:17 justin_smith: hellofunk: osx? case insensitive file systems suck

11:17 weavejester: hellofunk: The default mac file system is case insensitive, while Heroku likely uses Linux, and is case sensitive

11:17 EvanR: its not case insensitive

11:18 hellofunk: so guys, i'm curious. you are saying the case sensitivity of the OS trumps the web server software? weavejester, justin_smith

11:18 justin_smith: EvanR: what isn't?

11:18 hellofunk: not the OS. The filesystem.

11:18 fairuz: justin_smith: hm I'm confuse. But in src/clojure/clojurewerkz/core there's core.clj. Is this not it?

11:18 EvanR: ffs i dont have my mac

11:18 weavejester: hellofunk: The web server is built on the filesystem.

11:18 justin_smith: if the filesystem is case insensitive, it gives you the same file regardless of case changes

11:19 fairuz: that would be clojurewerks.core.core

11:19 eraserhd: Hrmm, is there a built-in way to convert a bean to a map?

11:19 justin_smith: fairuz: but I don't see that file in the repo anywhere

11:19 eraserhd: bean

11:20 ,(bean (java.util.Date.))

11:20 clojurebot: {:day 2, :date 2, :time 1417537095208, :month 11, :seconds 15, ...}

11:20 fairuz: I'm using this release (2.5.0.0) https://github.com/clojurewerkz/ogre/tree/c00351d0e08e9b34d0e62f4654c74f13b9608313

11:20 EvanR: how did i survive in an office full of OSX for two years without running into a problem with this case insensitive filesystem oO

11:20 hellofunk: very interesting, fellas. Now OSX does offer the ability to set the drive to a case sensitive system, so maybe I should have done that when I partitioned it. weavejester justin_smith

11:20 fairuz: ***src/clojure/clojurewerkz/ogre

11:21 justin_smith: fairuz: are you sure lein is giving you that exact version of the lib?

11:21 fairuz: we have at least established that some versions of ogre don't have the core ns

11:21 hellofunk: these are the popular options: Mac OS Extended, Mac OS Extended (Journaled), Mac OS (Case-sensitive), and Mac OS (Case-sensitive, Journaled) any other Mac devs, what do you use on your system?

11:22 fairuz: justin_smith: I can just check in .m2?

11:22 justin_smith: fairuz: lein deps :tree

11:22 Glenjamin: i tend to create a case sensitive partition for shared dev stuff

11:22 weavejester: I use the default case-insensitive filesystem, but run tests on a Linux box.

11:22 justin_smith: fairuz: or, while lein is running, look at the output of ps x to see the classpath, which will include the path to the specific jar it is using in the running process

11:22 Glenjamin: having two files with names that differ only by case sucks

11:23 weavejester: There are some who develop against vagrant to be as close as possible the production environment.

11:23 justin_smith: Glenjamin: I think his issue was that the file was referred to in another file with mixed case

11:23 weavejester: But I've never found it to be that huge an issue.

11:23 Glenjamin: ah right, deploying to case sensitive

11:24 eraserhd: justin_smith: Thanks! I thought there was, but brain fart.

11:24 justin_smith: Glenjamin: so things work locally because fs is insensitive, break remotely where case sensitive

11:25 Glenjamin: yeah

11:26 fairuz: justin_smith: I have [clojurewerkz/ogre "2.5.0.0"] in lein deps :tree

11:27 justin_smith: fairuz: well, that's weird

11:27 fairuz: justin_smith: I'm using instarepl of LightTable if it makes any difference

11:28 justin_smith: yeah, if you are getting the right version of the dep but the namespace isn't found, I have no explanation for that.

11:32 fairuz: hmm this is weird

11:34 justin_smith: fairuz: did you verify via the process listing that that is the version in the classpath of the running instance?

11:37 fairuz: justin_smith: It's not in the classpath from the ps x

11:37 There's another one that is not in the classpath too, but I can use it just fine.

11:38 This further confuses me :D

11:41 ordnungswidrig: fairuz: what does clojure.java.classpath/classpath return?

11:41 hellofunk: amalloy i got a question for you about 4clojure

11:42 well, i guess you're not around, my bad.

11:42 justin_smith: hellofunk: stull not 9 am yet west coast time

11:42 hellofunk: justin_smith lol yep.

11:44 brucehauman: seangrove: when javascript is reloaded ala figwheel the source maps and corresponding source doesn't seem to be reloaded.

11:44 fairuz: justin_smith: there's this entry -> #<File /home/vagrant/.m2/repository/clojurewerkz/ogre/2.5.0.0/ogre-2.5.0.0.jar>

12:31 Glenjamin: brucehauman: thanks for following that up btw

12:31 been liking figwheel so far

12:31 used it for a clojurescript intro workshop, mostly "just worked"

12:33 brucehauman: thanks man! trying to put a bunch more effort into it this week

12:34 Glenjamin: how feasible do you think it'd be to work as lib rather than a lein plugin?

12:34 i had a few headaches trying to get something similar to chestnut, where the repl/server/figwheel are all in the same process

12:35 https://github.com/defshef/defshef12 what i ended up with, adding the repl listener into the ring handler namespace

13:05 l1x: justin_smith: do you remember the last week convo about using (do all (pmap ...))

13:05 actually it is 10x faster than doseq

13:05 so yes it is worth to do (doall (pmap (.... even if you are in a thread

13:06 SagiCZ1: hi.. when i do (last (take 10 (iterate foo init))) the foo never gets executed, whats wrong?

13:06 justin_smith: l1x: cool

13:06 ,(last (take 10 (iterate + 1)))

13:06 SagiCZ1: ,(last (take 10 (iterate inc 0)))

13:07 clojurebot: 1

13:07 9

13:07 SagiCZ1: it works here.. i dont understand

13:07 justin_smith: is foo lazy internally?

13:07 SagiCZ1: it has conj....

13:09 but it doesnt even get called.. i have debug print right at the beginning

13:10 justin_smith: do you know that the thing invoking it gets called?

13:11 and if it is in a thread, are you directly using its terminal, or is it an environment like cider or fireplace where the default root binding of *out* may not be immediately visible?

13:12 eg. cider creates *nrepl server foo* which gets some misplaced print output

13:15 SagiCZ1: oh, actually it's the *nrepl-server foo* buffer that gets it - you can see it with (.start (Thread. #(println "hi")))

13:16 SagiCZ1: i need to investigate this more.. seems really weird, i will come back later if i still cant figure it out

13:47 ,(println "100")

13:47 ,(println 100)

13:47 clojurebot: 100\n

13:47 100\n

13:47 SagiCZ1: ok this was the problem.. i thought i had the same parameters

13:47 ,(take "10" (range 12))

13:47 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>

13:48 SagiCZ1: the exception got swallowed somewhere

14:07 hellofunk: is anyone here using the cursive plugin for intellij?

14:09 nullptr: hellofunk: going out on a limb here, but i think cfleming is probably using it...

14:10 SagiCZ1: hellofunk: i am using it extensively

14:11 cfleming is the author and frequents this channel too

14:11 hellofunk: i was curious if cursive provides function arg and arity hints for clojurescript code?

14:11 SagiCZ1: hellofunk: not sure.. works for clojure though

14:12 hellofunk: emacs does this for clojure too, but for cljs it seems to be hard to find this feature

14:16 seancorfield: ddellacosta: you pinged me last night - did you figure out the answer?

14:17 SagiCZ1: if i want to build executable jar with leiningen, do i have to specify all namespaces to be :aot in project.cls?

14:18 llasram: SagiCZ1: Just the :main namespace, which also needs to :gen-class

14:18 SagiCZ1: llasram: cool

14:18 thanks

14:21 when trying to run the executable jar i get NoClassDefFoundError clojure/lang/IFn

14:27 nevermind, it creates two jars, works like a charm

14:32 hellofunk: what happened to the 2014 State of Clojure survey results? they were apparently taken offline https://cognitect.wufoo.com/forms/state-of-clojure-2014/

14:32 nullptr: http://blog.cognitect.com/blog/2014/10/20/results-of-2014-state-of-clojure-and-clojurescript-survey

14:33 hellofunk: nullptr thanks i guess they have a broken link on their other blog post

15:09 justin_smith: so I have a problem that is likely solved by checking if the arg is an instance of AFn, but before I decide on that, what is implementing AFn supposed to convey?

15:10 my main criteria is I want to match protocol methods, multimethods, and functions, but not symbols and keywords

15:10 and AFn lets me differentiate between those

15:11 ordnungswidrig: justin_smith: can you give more context? Why do you need to differentiate?

15:11 justin_smith: since all of them implement IFn, but only the former list are AFn

15:12 ordnungswidrig: I would not rely on that fact and check if it's a symbol or keyword if it's what you want.

15:12 justin_smith: ordnungswidrig: callable (all of them) vs. a thing that is meant to be called with args

15:12 other things are callable but not in the list of things I want either

15:12 ordnungswidrig: what about (fn [] "boo!")

15:12 it's callable but without args.

15:12 justin_smith: that is fine

15:13 my "with args" thing was sloppy, sorry

15:13 ordnungswidrig: give me more context

15:13 stuartsierra: `AFn` is mostly an implementation detail; not intended to convey anything.

15:13 ordnungswidrig: why not (not (or (symbol? x) (keyword? x)))

15:14 justin_smith: ordnungswidrig: it is a router for handling requests, and so far we had a whitelist of "if it's a function, use that, otherwise resolve the symbol or use the var" etc. but I would like something a bit more resilient (so that for example a user can supply a multimethod or protocol function and expect it to work)

15:14 ordnungswidrig: well, checking for a symbol or var might not be your job as a router.

15:15 justin_smith: ordnungswidrig: the api explicitly says if you supply a symbol, it resolves that symbol at runtime

15:15 ordnungswidrig: which api?

15:15 justin_smith: this is so that a routing table can be expressed as edn

15:15 the api of the lib I am currently fixing

15:15 ordnungswidrig: I see.

15:16 :-)

15:16 I would then define a multimethod for the types that does the right thing for a) a symbol b) a var c) anything else (e.g. a function)

15:17 justin_smith: yeah, right now its a cond statement deciding what to store when building the routing table. I was hoping for something more general and elegant than adding more special cases, but that seems to be the path forward.

15:17 ordnungswidrig: or check with `fn?` which evaluates to true for functions, protocol functions and multimethods

15:18 justin_smith: ,(fn? print-method)

15:18 clojurebot: false

15:18 justin_smith: nope

15:18 ordnungswidrig: hm

15:18 mabye just protocols

15:18 justin_smith: that's exactly what I was using for the test before ?

15:18 ordnungswidrig: ok, I still don

15:19 't get the usecase. If it's defined in EDN you cannot have a function there, just symbols, right?

15:19 justin_smith: which is why I came up with this whole "test for AFn" thing, but if as stuartsierra says AFn is not meant to convey anything useful, than I'll just add some clauses to the cond statement or maybe make it a multimethod

15:19 ordnungswidrig: you *can* supply edn

15:19 ordnungswidrig: I see.

15:19 djames: For run, I'm building up a REPL-based Clojure game

15:19 justin_smith: you can also supply a data structure containing things like functions or vars as handler

15:19 djames: err. for fun! (and to run) haha

15:20 ordnungswidrig: justin_smith: I'd go with a multimethod

15:20 justin_smith: yeah, then the user can extend the multimethod for their magic thing that should also route

15:20 good advice, thanks

15:20 djames: I'm thinking about quick ways to make it multiplayer

15:20 justin_smith: (inc ordnungswidrig)

15:20 djames: if each player has a REPL, they could use nrepl to connect

15:20 ordnungswidrig: djames: what kind of game?

15:21 justin_smith: amalloy: can you restart lazybot? I don't think I have the privs

15:21 stuartsierra: justin_smith: It will probably be easiest to test for the specific types you're looking for rather than search for some predicate which perfectly separates them.

15:21 justin_smith: stuartsierra: you're right, thanks. I think I'll use a multimethod, which means user's can extend it.

15:21 *users

15:22 djames: ordnungswidrig: well, it happens to be about voting and elections, but that doesn't matter too much

15:22 having a REPL could allow people to cheat by looking too much into the game state atom, but I'm ok with that to start

15:22 ordnungswidrig: I was more asking is it round based or "live"

15:23 or realtime

15:23 djames: it would be a fun way to introduce friends to clojure as well

15:23 justin_smith: djames: you could use an IPC queue for game events

15:23 djames: round-based but some actions could be concurrent -- no need to wait for others, for example, to "run polls" or "create an ad"

15:23 justin_smith: s/ipc/message

15:24 ie. rabbitmq or hornetq

15:25 djames: justin_smith: possibly. i'm starting simpler... here's what I'm wondering about. if each player connects to a shared REPL, they could hack it

15:25 ordnungswidrig: djames: mabye this will help http://blog.xebia.com/2014/08/25/vert-x-with-core-async-handling-asynchronous-workflows/

15:25 djames: which is ok to start I suppose

15:26 I think what I want is a way for each player to have their own REPL

15:26 then I could write some simple nrepl code to pull the game state from a shared REPL

15:27 of course a browser interface would be better once the gameplay is figured out. the game isn't really designed yet

15:32 justin_smith: djames: yeah, you could use a web server or a raw socket to send the messages between the repls, but beyond a fairly a small scale, a proper inter-process message queue is actually the simpler solution, compared to hacking your own whatever state-sharing solution

15:33 EvanR: state sharing across the network?

15:33 justin_smith: EvanR: beats having everyone use the same repl I guess

15:34 djames: justin_smith: interesting poitn

15:34 justin_smith: EvanR: multi-player games do require shared state

15:34 EvanR: i object to such a concept

15:34 djames: I wonder what setup the bot competitions use... probably a central server with shared state and some private information

15:34 bots only get the information that they would need

15:34 justin_smith: EvanR: I look forward to your new, revolutionary, stateless game concept

15:35 EvanR: in realtime action multiplayer games, you dont synchronize your *separate* states because it would be too slow

15:35 if you did synchronize, its still not sharing

15:35 djames: justin_smith: exactly. I don't play chess a move at a time, I create an immutable value that holds the entire game

15:35 justin_smith: but they aren't playing the game if there isn't shared state

15:35 EvanR: thats not true

15:35 unless this is specifically chess

15:36 djames: i was joking

15:36 (Some people view time as an illusion)

15:36 anyhow, this seems like a silly misunderstanding standing in for a proper debate

15:36 EvanR: because of internet latency, there is a necessary idea of approximately equal distinct states, players usually do not care if things are slightly off

15:37 djames: if we all explained what we were actually saying, I don't think there would be much disagreement

15:37 thanks for the ideas

15:37 EvanR: in any case, i was wonder how you were sharing states across the network in the sense of clojure sharing data structures among distinct values

15:38 djames: my purpose is to start very simple because I haven't designed, much less play-tested a turn-based strategy game

15:38 the simplest is one REPL

15:38 justin_smith: EvanR: I think you are using a much more specific and concrete definition of "shared state" than I was. I didn't mean that it was synchronized and identical to all clients, just that there is some method of agreeing eventually on the events that have occured in a shared domain.

15:39 djames: if/when the single-REPL approach does not cut it, I'm thinking about going to one master REPL with various client REPLs connected via nrepl

15:40 justin_smith: djames: I guess if you trust all the players with full access to the server

15:40 djames: at this point, yes. prototyping. e.g. what rules make for fun games, reasonable length, etc.

15:41 EvanR: whats the benefit of the repl, a ready-made command line?

15:41 justin_smith: in that case, you could have all the clients use the same nrepl server, and call that good - only one nrepl server process need exist

15:41 djames: yep!

15:42 Glenjamin: you might be able to implement any future protections as nrepl middleware anyway

15:43 EvanR: seems like real protection would be kind of hard to accomplish

15:43 halting problem?

15:43 justin_smith: EvanR: Glenjamin: it could use clojail like lazybot does

15:43 Glenjamin: well, you can just whitelist, rather than blacklist

15:44 xemdetia: EvanR, maybe you should look at this article for ideas http://www.gamasutra.com/view/feature/131503/1500_archers_on_a_288_network_.php

15:44 EvanR: how do you blacklist an infinite loop

15:44 Glenjamin: thread + timeout

15:44 justin_smith: EvanR: ##(loop [] (recur))

15:44 arrdem: Proof of nontermination? anyone?

15:44 Glenjamin: ,(reduce + (range))

15:44 clojurebot: eval service is offline

15:44 Glenjamin: dno't need proof for a game, just an execution cap :)

15:45 justin_smith: oops, the above was supposed to call lazybot, who is out

15:45 Glenjamin: ,(reduce + (range))

15:45 EvanR: xemdetia: yeah i read that a long time ago, its awesome

15:45 arrdem: justin_smith: lazybot is down? I thought you fixed him!

15:45 clojurebot: eval service is offline

15:45 EvanR: way before quake3

15:45 arrdem: ,1

15:45 clojurebot: eval service is offline

15:45 Glenjamin: hrm, i'm sure that should timeout rather than eval service offline

15:45 justin_smith: arrdem: hey, the uptime was great

15:45 EvanR: justin_smith: surely thats not literally enough

15:45 justin_smith: arrdem: but clearly not 100% fixed yet

15:46 arrdem: hum maybe clojurebot is actually having heartburn too

15:46 djames: xemdetia thanks for sharing that: this part is interesting "The PCs would basically synchronize their game watches in best war-movie tradition, allow players to issue commands, and then execute in exactly the same way at the same time and have identical games."

15:46 Glenjamin: EvanR: the main issue is protecting from sideeffects, computation can be limited relatively easily with threads

15:46 xemdetia: djames, I thought so too. I thought it would be helpful in EvanR's case because it sounds like he is trying to do the same thing with having synchronized distributed state.

15:47 justin_smith: xemdetia: djames is the one trying to do that actually, EvanR just has opinions about how to do it

15:47 xemdetia: sorry I didn't parse far enough back :(

15:47 djames: xemdetia: that was written in 2001 before "big data" and "distributed systems" were invented *smirk*

15:48 justin_smith: xemdetia: happens to the best of us

15:48 djames: EvanR: good luck with your game! haha

15:48 xemdetia: djames, 'distributed systems' was definitely a term for a long time if you are from mainframeland

15:49 EvanR: starcrafts infamous "synchronization failed"

15:49 because one player had a slow internet

15:49 none of this matters because djames is doing a turn-based game

15:51 djames: EvanR: not too mention that I am not stuck with a 28.8 modem either

15:51 xemdetia: depending on the type of turn based game you could still have a lot of the same problems

15:51 EvanR: 28.8 could have great latency!

15:51 xemdetia: unless it is completely isolated turn-taking

15:51 djames: some turn-based games allow for interesting game play by resolving async orders in lockstep

15:51 EvanR: duke3d played great, until someone picked up your phone

15:51 justin_smith: xemdetia: hell, I have the same problem with board games when we are playing in person and one person just takes way too long making a move and doesn't even realize it was their turn

15:52 aaelony: I think the docstring for pmap should contain a note to use shutdown-agents when done. I always forget that.. There is a note in the examples section, but the doc string I think would be preferable.

15:52 djames: Diplomacy has a set of rules for combining (and deconflicting if needed) "asynchronous" player actions.

15:52 justin_smith: git merge: the game

15:52 xemdetia: justin_smith, true enough. I haven't played a board game in quite a while so I forget

15:53 EvanR: in civilization (some number less than latest) you could not do shit if it wasnt your turn, nice and simple!

15:53 djames: this has been fun, thanks for the articles and ideas

15:53 xemdetia: a turned based game just has a poorly specified tick timer :)

15:54 djames: justin_smith: git branch: the game where you never lose

15:54 not sure what turn to make? just branch the game and see what happens

15:54 Glenjamin: having a defined tick means it doesn't have to be a typing contest

15:55 see also: emulator snapshotting

15:55 justin_smith: Glenjamin: even muds had defined ticks (but you still get typing contests / trigger contests because the ticks were short)

15:58 EvanR: minecrafts "ticks" are so annoying

15:58 every tick, do like 100 probabilistic effects to every block in view

15:58 like 100 times a second

15:58 arrdem: what kind of game are we chatting about? real turn based or pseudo-real time?

15:59 xemdetia: I think it is more the concept of synchronization of player moves

15:59 arrdem: isn't this the minimum diff problem which is NP hard?

16:00 pepijndevos: Is there something like into-with?

16:00 ordnungswidrig: pepijndevos: into-with?

16:01 pepijndevos: I want to turn a seq with duplicated into a map, merging the duplicates.

16:01 Like merge-with but for a seq of pairs.

16:01 EvanR: thats a reduce right

16:02 pepijndevos: uuuhm... it could be a reduce, yes.

16:02 justin_smith: yeah, probably easiest to do in a reduce

16:02 (inc reduce)

16:02 :(

16:02 arrdem: into is just reduce with some magic to use transients

16:03 justin_smith: arrdem: plus a pretty specific and limited reduction function

16:03 arrdem: yarp

16:08 EvanR: is there a form that lets me locally use a different namespace

16:09 amalloy: (inc reduce)

16:09 lazybot: ⇒ 1

16:09 justin_smith: amalloy: thanks

16:09 (inc reduce)

16:09 lazybot: ⇒ 2

16:09 justin_smith: (inc ordnungswidrig)

16:09 lazybot: ⇒ 2

16:10 amalloy: pepijndevos: it sounds like merge-with

16:10 Glenjamin: ,(merge-with merge [[:a 1] [:b 2]])

16:10 amalloy: (apply merge-with into {} (for ...)) is a useful pattern

16:10 clojurebot: [[:a 1] [:b 2]]

16:10 Glenjamin: ,(merge-with merge (hash-map [:a 1] [:b 2]))

16:10 clojurebot: {[:a 1] [:b 2]}

16:11 pepijndevos: amalloy, it does, but that really only works on maps

16:11 Glenjamin: meh, for is better

16:11 amalloy: pepijndevos: that's what the (for ...) is about. convert your inputs into the map shape you want

16:11 Glenjamin: $source merge-with

16:11 lazybot: merge-with is http://is.gd/eoJ3Mo

16:11 justin_smith: pepijndevos: well, if you want things merged the way maps would be, doesn't making maps out ofthem make sense?

16:12 pepijndevos: ,(merge-with + {} [[1 2] [1 2]])

16:12 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.util.Map$Entry>

16:12 amalloy: ,(apply merge-with into {} (for [x '(a b c) y '(1 2 3)] {x [y]}))

16:12 clojurebot: {c [1 2 3], b [1 2 3], a [1 2 3]}

16:12 amalloy: ,(apply merge-with + {} (for [x '(a b c) y '(1 2 3)] {x y}))

16:12 clojurebot: {c 6, b 6, a 6}

16:12 pepijndevos: the expected result would be {1 4) for my example.

16:13 ah... interesting

16:15 EvanR: with-ns seems deprecated

16:16 Bronsa: ,with-ns

16:16 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: with-ns in this context, compiling:(NO_SOURCE_PATH:0:0)>

16:16 arrdem: not even in 1.4...

16:16 where even are you seeing that?

16:16 justin_smith: &(apply merge-with + {} (for [[k v] [[1 2] [1 2]]] {k v}))

16:16 lazybot: ⇒ {1 4}

16:16 EvanR: google clojure with-ns

16:17 Bronsa: ah clojure-contrib

16:17 justin_smith: ^^ pepijndevos I think that's what you are looking for?

16:17 arrdem: lol @ contrib

16:17 pepijndevos: yea

16:19 ordnungswidrig: &(reduce (fn [m [k v]] (update-in m [k] (fnil + 0) v)) [[1 2] [1 2]]))

16:19 lazybot: ⇒ [1 4]

16:20 ordnungswidrig: Is there a reducing function which uses multiple cores for a associative reducer function?

16:20 maybe using divide and conquer?

16:20 EvanR: fold

16:20 justin_smith: ordnungswidrig: checkout out core.reducers

16:21 http://clojure.org/reducers

16:21 ordnungswidrig: *doh*

16:21 EvanR: you should definitely profile to make sure doing this actually helps

16:22 thearthur: Does The reduce function does this on vectors out of the box

16:22 justin_smith: EvanR: good point. The fact that the default partitioning is 512 elements is illustrative I think

16:22 thearthur: no

16:22 thearthur: regular reduce does not create any new threads or use a thread pool, it does everything in the same thread where it is called

16:23 unless you pass in a reducing function that uses threads of course...

16:25 ordnungswidrig: &(r/fold (partial merge-with +) (r/map (partial apply hash-map) [[1 2] [1 2]]))

16:25 lazybot: java.lang.RuntimeException: No such namespace: r

16:25 ordnungswidrig: (clojure.core.reducers/fold (partial merge-with +) (clojure.core.reducers/map (partial apply hash-map) [[1 2] [1 2]]))

16:25 justin_smith: ordnungswidrig: the bots don't let you make / use threads anyway

16:25 ordnungswidrig: &(clojure.core.reducers/fold (partial merge-with +) (clojure.core.reducers/map (partial apply hash-map) [[1 2] [1 2]]))

16:25 lazybot: java.lang.ClassNotFoundException: clojure.core.reducers

16:26 * ordnungswidrig gives up

16:26 justin_smith: you would need to require the ns

16:26 Bronsa: ,(require 'clojure.core.reducers)

16:26 clojurebot: #<FileNotFoundException java.io.FileNotFoundException: Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath.>

16:26 EvanR: ,(boolean true)

16:26 clojurebot: true

16:26 EvanR: ,(boolean false)

16:26 clojurebot: false

16:26 EvanR: is there a boolean? function

16:27 Bronsa: EvanR: no

16:27 justin_smith: (defn boolean? [x] (contains? #{true false} x))

16:27 Bronsa: ,(def boolean? (some-fn true? false?))

16:27 clojurebot: #'sandbox/boolean?

16:27 justin_smith: or that

16:28 arrdem: would be entertained to see a benchmark shootout between those and the obvious (or) implementation

16:28 ordnungswidrig: a macro please!

16:28 Bronsa: arrdem: some-fn is equivalent to the or impl

16:28 arrdem: Bronsa: initially? I totally buy that it'll be equivalent once the JIT has a good look at it.

16:29 Bronsa: arrdem: it's unrolled

16:29 justin_smith: $source some-fn

16:29 lazybot: some-fn is http://is.gd/iPgf2J

16:29 Bronsa: arrdem: for the 1-arity, the impl is (or (f x) (g x))

16:29 justin_smith: yeah, very aggressively unrolled

16:29 arrdem: Bronsa: gotcha.

16:30 Bronsa: so remember that logic database thing I was playing with for ASTs?

16:30 Bronsa: yeah

16:30 arrdem: Bronsa: turns out that core.logic has a better one built in

16:30 Bronsa: go figure :P

16:30 arrdem: gonna try and rebuild Oxcart atop that over Christmas. Should be fun :D

16:30 should also make stuff like partial application and inlining trivial.

16:31 Bronsa: arrdem: nice. I've always been a bit worried about core.logic's performance for it to be useful for usage with t.a

16:32 arrdem: Bronsa: yeah not gonna lie I'm concerned that this is gonna blow up in my face, but it'll be a fun experiment and it's easy to backport to my fully transient equivalent (the cutaway crap) if core.logic proves too slow.

17:25 puredanger: why not (defn boolean? [b] (instance? Boolean b))

17:27 amalloy: puredanger: that is probably a better definition

17:27 arrdem: oh good java.lang.Boolean is final I was worried for a minute there.

17:27 justin_smith: ,((some-fn false? true?) (Boolean. nil)) ;; puredanger amalloy

17:27 clojurebot: false

17:28 hiredman: well, (def boolean? (some-fn true? false?)) is cross platform

17:28 justin_smith: ,(Boolean. nil)

17:28 clojurebot: false

17:28 hiredman: (maybe?)

17:28 EvanR: yurg?

17:28 arrdem: hiredman: ideally

17:28 EvanR: is "boolean" even a standard type?

17:28 amalloy: justin_smith: well, if you use the Boolean constructor you deserve what you get

17:29 puredanger: exactly

17:29 EvanR: ,(type true)

17:29 clojurebot: java.lang.Boolean

17:29 puredanger: it's only purpose is to create Clojure wat examples :)

17:29 justin_smith: amalloy: just showing that some things that are Boolean are not one of the booleans we care about

17:29 amalloy: puredanger: it messes up plenty of other stuff

17:30 like i remember discovering that when you write Boolean/FALSE to an ObjectOutputStream and read it back in, what you get out is (Boolean. false)

17:30 puredanger: yeah, deserialization is one place where you can run into this

17:31 although in actual Java serialization I assume Boolean objects do the proper readResolve to give you the canonical version

17:31 EvanR: oO

17:31 all i need is a dynamic check for "booleanness" ;_;

17:32 puredanger: I think (defn boolean? [b] (instance? Boolean b)) is the best impl

17:32 EvanR: thats predicated on the java backend right

17:33 just making sure

17:33 puredanger: yes

17:33 there's a ticket out there in jira to create more of these type predicates (which could be made portable by the platform)

17:34 amalloy: puredanger: no, in actual java serialization they don't; that's what i was complaining about

17:34 puredanger: that surprises me

17:34 EvanR: ,(contains? #{true false} nil)

17:34 clojurebot: false

17:34 puredanger: http://dev.clojure.org/jira/browse/CLJ-1298 is the predicate ticket I referred to

17:34 although it doesn't actually have boolean?

17:36 EvanR: ,(str (type nil) " is not a valid option, buster")

17:36 clojurebot: " is not a valid option, buster"

17:36 EvanR: uhg

17:36 justin_smith: ,(pr-str nil)

17:36 clojurebot: "nil"

17:36 arrdem: I have Bronsa's some-fn and puredanger's instance getting to the ns times in a trivial attempt to benchmark

17:36 amalloy: ,(let [a (java.io.ByteArrayOutputStream.) _ (.writeObject (java.io.ObjectOutputStream. a) false) x (.readObject (java.io.ObjectInputStream. (java.io.ByteArrayInputStream. (.toByteArray a))))] (map #(System/identityHashCode %) [x false]))

17:36 clojurebot: #<CompilerException java.lang.ExceptionInInitializerError, compiling:(NO_SOURCE_PATH:0:0)>

17:37 dbasch: a groups of Booleans are restoring the home of George Boole

17:37 amalloy: puredanger: well, in a real repl that prints two different numbers

17:37 puredanger: I believe you :)

17:37 EvanR: justin_smith: that is awesome

17:37 puredanger: everything about serialization is wrong

17:37 amalloy: i was double-checking for myself; last time i tried it was like four years ago

17:37 Bronsa: ,clojure.lang.IAtom

17:37 clojurebot: clojure.lang.IAtom

17:38 Bronsa: nice, didn't realize that one got commited already

17:38 hiredman: :/

17:38 puredanger: early alpha

17:38 justin_smith: didn't Goetz mention something about a bunch of things about serialization being messed up for backward compatibility reasons because they released a half-backed impl too soon?

17:38 puredanger: yes

17:39 there are some internal java paths that let you do object construction without calling the constructor buried in the serialization guts

17:39 hiredman: get ready for the land slide of things without atomic semantics that implement IAtom

17:39 puredanger: you can use those for great evil

17:40 EvanR: can i do "list interpolation" '(x y $z w) :3

17:40 KnightsWhoSayNi: `(x y ,z w) ?

17:41 stuartsierra: ,(let [stuff [3 4 5]] `(1 2 ~@stuff 6 7))

17:41 clojurebot: (1 2 3 4 5 ...)

17:41 TEttinger: oh yeah, that thing

17:45 EvanR: so with ` i get a lot of my symbols (when i print them out of the repl) now qualified fully

17:45 puredanger: syntax quote will do that

17:46 EvanR: why does it do that, is there a way to disable that

17:47 justin_smith: EvanR: for making macros less buggy

17:48 puredanger: some of the things in tools.macro might be better suited for template-like use cases https://github.com/clojure/tools.macro

17:48 justin_smith: and you can use `(~'x) but that's kind of ugly

17:48 EvanR: so a symbol has some understood namespace, is there such a thing as a "free" symbol

17:48 justin_smith: EvanR: ` is generating namespaces symbols out of unnamespaced ones

17:49 a normal symbol doesn't usually have a namespace

17:49 noonian: ,'foo

17:49 clojurebot: foo

17:49 justin_smith: ,(.getNs 'foo)

17:49 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: getNs for class clojure.lang.Symbol>

17:49 justin_smith: err

17:49 amalloy: EvanR: free symbols cause a lot of problems when used in macros, and ` is mostly used in macros, so its default behavior is to not emit any such symbols

17:49 justin_smith: ,(map namespace 'foo 'bar/foo 'baz/foo)

17:49 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol>

17:50 justin_smith: ,(map namespace ['foo 'bar/foo 'baz/foo])

17:50 clojurebot: (nil "bar" "baz")

17:51 justin_smith: ,(.getNamespace 'foo) ; that's what I was trying initially

17:51 clojurebot: nil

17:51 EvanR: well, ill use (list ... 'symbol ....)

17:52 amalloy: EvanR: what is an example of an actual list you are building here?

17:53 EvanR: there is some code (list {field t} '=> t) which becomes ({:shit t1} => t1)

17:54 amalloy: well, that seems like a reasonable way to write it. i'm curious what you need that => for at all, though?

17:55 EvanR: well something else is going to look for that in the second position to differentiate it from something else, hypothetically

17:56 also when they get nested, its going to be easier to read and write than if they were just omitted

17:57 amalloy: EvanR: that sounds like a terrible data structure though, right? like, instead of lists where the second symbol means something different, why not a map like {:differentiator '=> :condition {{field t} t}}

17:57 noonian: looks like its a macro for writing midje tests possibly

17:59 EvanR: amalloy: right, well my way of doing what youre doing is [discrimcode a b c ...] and then core.match

17:59 but right now im not doing that

17:59 what i said earlier is hypothetical at best

18:04 whats an idiomatic way to have a counter, incremented in place. an atom with a number in it?

18:05 mdrogalis: EvanR: Yeah.

18:06 benzap: so I have a basic situation that I know should work, but doesn't

18:07 ,(defn foo [x & {:keys [bar] :or {bar "ha"}}] (println x bar))

18:07 clojurebot: #'sandbox/foo

18:08 benzap: ,(foo 1 :bar "test")

18:08 clojurebot: 1 test\n

18:08 benzap: ,(defn bar [x & args] (apply foo x args))

18:08 clojurebot: #'sandbox/bar

18:09 benzap: (bar x :bar "test")

18:09 ,(bar x :bar "test")

18:09 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:0:0)>

18:09 benzap: ,(bar 1 :bar "test")

18:09 clojurebot: 1 test\n

18:09 benzap: ...

18:09 amalloy: yeah, that works fine. you have some other problem

18:11 benzap: ,(defn bar [x & {:keys [bar] :or {bar "haha"} :as args}] (apply foo x args))

18:11 clojurebot: #'sandbox/bar

18:11 benzap: ,(bar 1 :bar "test")

18:11 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No value supplied for key: [:bar "test"]>

18:11 amalloy: benzap: mhm. because args is a map there, not a seq

18:11 benzap: ah

18:11 do I need to convert it to a seq?

18:12 amalloy: benzap: i mean, there are things you can do to make this work

18:12 but by far the easiest is to use {:keys ...} instead of & {:keys ...}

18:12 look at all this trouble the varargs are causing you, and the only advantage is that you save the two {} characters when calling the function

18:12 benzap: yeah true, but it looks pretty

18:13 EvanR: make love not varargs

18:13 justin_smith: benzap: use of vararg keys is also harder to compose - it's nice to be able to just pass the map along

18:14 alexyakushev: benzap: vararg key-value arguments are usually used in user-facing functions

18:15 amalloy: alexyakushev: even in user-facing functions they're not great

18:16 alexyakushev: amalloy: Maybe. But my argument was that they are definitely not great deeper in the callstack

18:16 benzap: yeah, I converted it away from varargs, and I don't have any troubles now

18:17 alexyakushev: Hm, good to see this point is now updated here http://dev.clojure.org/display/community/Library+Coding+Standards

18:17 I remember it used to promote unrolling kw arguments

18:17 amalloy: benzap: it's way easier to deal with stuff when there's an actual object, with a name, representing it; varargs are like "a bunch of disconnected things" all with no name. that's fine sometimes, eg for the args to +, but for option maps, where you might want to do anything at all other than destructure them once, having a value representing it makes stuff easier

18:18 arrdem: alexyakushev: someone is gonna figure out that I fixed it eventually :P shhhhh

18:18 amalloy: oh, that's nice, alexyakushev

18:19 alexyakushev: arrdem: you better hurry spreading the word before I steal all the credit

18:20 arrdem: alexyakushev: as long as the change doesn't get rolled back I could care less.

18:22 alexyakushev: arrdem: you mean you couldn't care less :p

18:23 arrdem: that

18:48 cfleming: hellofunk: Yes, that all works equivalently for clj and cljs

18:59 EvanR: what does it mean when i get this error, and the backtrace has nothing within any of my source code

18:59 ArityException Wrong number of args (1) passed to: type-checker$what-is-type-in$fn--14540$fn clojure.lang.AFn.throwArity (AFn.java:437)

19:00 im using the right number of arguments everywhere

19:00 maybe i need to reload the repl

19:01 did not help

19:01 backtrace just says stuff like lazy seq, clojure core

19:01 amalloy: EvanR: print the whole stacktrace, paste it to refheap or something

19:02 EvanR: im trying to do a into {} map on a map

19:02 amalloy: if it says nothing meaningful to *you*, that doesn't mean there's nothing meaningful in it

19:03 EvanR: https://www.refheap.com/dd171e33c648f6a446818dfe8

19:05 it does have three lines from my source code in there

19:05 amalloy: okay, so the sequence you are trying to dump into a map is lazy, and realizing it causes an exception

19:05 EvanR: cripes

19:05 amalloy: ie, you have written (into {} (map f xs)), and takes too many args

19:05 er

19:05 f takes more than one arg

19:06 EvanR: ok, its (fn [k v] ...) but i think it needs to be (fn [[k v]] ...)

19:06 amalloy: according to the exception message you pasted earlier, that f is what-is-type-in

19:06 EvanR: well thats not right, may thats just what function the function is in

19:06 justin_smith: yeah [[k v]] is what you want for mapping over a hash-map

19:07 EvanR: lovely

19:07 amalloy: justin_smith: yes, although (for [[k v] m] ...) is almost always clearer than (map (fn [[k v]] ...) m)

19:07 it also has the advantage that this sort of mistake is immediately apparent

19:07 because (for [k v m] ...) will immediately fail to compile

19:08 EvanR: i used for [[k v] m] [k ...] instead

19:08 and it worked

19:08 and thats more clear?

19:08 hyPiRion: ,(fn [m] (for [k v m] [k v]))

19:08 clojurebot: #<sandbox$eval25$fn__26 sandbox$eval25$fn__26@e28d65>

19:09 amalloy: hyPiRion: har har, where is the u+FEFF?

19:10 EvanR: well i wrote a map values function, and i cant be arsed to import the dang module its in ...

19:10 i wish it was just built in

19:10 hyPiRion: between the k and the v – I'm a bit surprised I haven't removed this "handy" keyboard shortcut already. I accidentally use it pretty often

19:11 EvanR: F11F FE1F F00F FEff

19:11 i smell the blood of an englishmen

19:22 dbasch: the link to alpha4 remains broken, in case someone cares http://clojure.org/downloads

19:22 amalloy: hah, that url

19:23 .../1.7.0-alpha3/clojure-1.7.0-alpha4.zip

19:23 dbasch: the script to generate that page is also alpha

19:23 amalloy: dbasch: it's a challenge: if you can't figure out how to fix the url, you don't deserve to download the latest alpha

19:24 dbasch: but if you know how to fix the url you’re probably using leiningen anyway

19:46 devn: off topic: pretty cool visualization of an ongoing DDoS http://map.ipviking.com/

19:53 profil: Hey guys, which is faster, running rest on a set or running disj? How can I find this information?

19:54 noonian: devn: that is mesmerizing to watch

19:55 hiredman: profil: disj will return a set, rest will not

19:56 profil: hiredman: alright, and I guess disj is faster than running (set (rest set))?

19:58 hiredman: well rest returns a seq, which has O(n) membership testing, and sets have something like O(log_32n) for membership, given a structure with O(n) membership testing, how effeciently could you turn it in to something with O(log_32 n) membership testing?

20:00 profil: O(n log_32 n)?

20:02 justin_smith: devn: hah, lots of people targeting st. louis right now

20:04 dbasch: profil: why would you want to call rest on a set anyway? do you want to remove a random element?

20:04 noonian: i'm trying to figure out what is the island between africa, south america, and antarctica thats labeled Mil/Gov

20:05 profil: dbasch: no, the first element?

20:05 dbasch: profil: sets have no order

20:05 justin_smith: profil: the "first element" of a set is not defined

20:05 profil: dbasch: yeah I understood that now..

20:06 justin_smith: it's an implementation detail

20:06 profil: its too late.. I'm tired :D

20:06 hyPiRion: It is in an ordered set

20:06 profil: but its okay to use first on a set right?

20:07 justin_smith: hyPiRion: oh?

20:07 hyPiRion: justin_smith: ##(first (sorted-set 3 4 1)) always returns 1

20:07 lazybot: ⇒ 1

20:08 justin_smith: hyPiRion: wait, I misparsed the "it" to refer to profil's set, I know ordered sets exist :)

20:08 ssk: how complete is apache spark clojure binding

20:08 justin_smith: profil: sure, but who knows which item you'll get ##(first #{:a :b :c :d :e :f :g :h})

20:08 lazybot: ⇒ :e

20:08 dbasch: profil: “okay” depends on what you want

20:09 profil: justin_smith, dbasch: I dont really care, I just want any item

20:09 hyPiRion: then first is okay

20:09 profil: I am porting a flood fill algorithm from javascript to clojure :)

20:09 using sets for cells which has been visited, and which should be visited

20:09 justin_smith: there is also ##(rand-nth #{:a :b :c :d :e :f :g :h}) if you care in that you want it to be random and not just implementation defined

20:09 lazybot: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentHashSet

20:10 justin_smith: :(

20:10 dbasch: &(first (set [5 6 7 8]))

20:10 lazybot: ⇒ 7

20:14 dbasch: noonian: Bouvet Island

20:14 noonian: thats what i thought

20:14 profil: I have a vector which contains vectors, is there a nicer way to get a value from that than using "(nth (nth vec x) y)"?

20:14 noonian: all info says its uninhabited

20:14 dbasch: noonian: it has a tld, .bv

20:15 justin_smith: ,(([[:a :b :c] [:d :e :f]] 1) 2) ; profil

20:15 clojurebot: :f

20:15 justin_smith: ,(get-in [[:a :b :c] [:d :e :f]] [1 2]) ; profil

20:15 clojurebot: :f

20:16 profil: justin_smith: ah nice, get-in would be best, thanks :)

20:16 justin_smith: strictly requires vecs, will break with lazy-seq or list

20:17 profil: yeah, I am using vectors. Parsing json arrays turns into vectors :)

20:18 justin_smith: get-in has the bonus that it also works with hash-maps enclosing / nested with vectors

20:19 profil: a

20:19 oh nice, thanks for your help :)

20:19 justin_smith: ,(get-in {:a [1 2 3]} [:a 1])

20:19 clojurebot: 2

20:20 profil: ,(get-in {"layout" [[1 2] [3 4]]} ["layout" 1 1])

20:20 clojurebot: 4

20:20 profil: yey :)

20:31 ssk: (eval '(+ 2 3 5))

20:40 josiah14: what's the advantage of using defn over declare if declare ensures that my function will be available no matter when/where in the program I call it?

20:40 justin_smith: josiah14: all declare does is create a var, it doesn't give it any value

20:41 josiah14: ah, understood

20:41 justin_smith: you eventually need to use def, or defn, or intern, or ... something to assign that value

20:41 josiah14: so I would have to use defn and declare together for functions

20:41 that makes sense.

20:42 justin_smith: ,(declare f)

20:42 clojurebot: #'sandbox/f

20:42 justin_smith: ,f

20:42 clojurebot: #<Unbound Unbound: #'sandbox/f>

20:42 josiah14: I'm feeling that Clojure is going to be fairly easy to pick up for me given I already know Haskell

20:43 I wasn't sure how much my knowledge would xfer, but knowing Java already, and knowing Haskell, it feels sort of like, oh, I get it

20:43 nullptr`: josiah14: very likely true

20:44 justin_smith: yeah, between Java for the underlying libs / apis, Haskell for the fp concepts, and scheme for the trivial syntax, you're most of the way there

20:44 we also get a few idioms and naming conventions from scheme

20:46 josiah14: ah, gotcha

20:46 yah, I don't know Scheme

20:46 justin_smith: out of the three, scheme is the simpler one by far

20:47 josiah14: but my hope is that learning Clojure will get me close enough that i could just pick it up and a week if I wanted to use it for some scripting or something

20:47 yah, I hear people praise Scheme all the time for its simplicity

20:48 justin_smith: well, depending on your definition of "scripting", Clojure might not be a great choice. Clojure is best at long-running processes that can use as much RAM as they need to execute tasks efficiently, once minimal resource usage and fast startup time become desirable, Clojure becomes less desirable.

20:49 josiah14: I still have some learning on Haskell to do, but it's for things like, how the 'F' do I use a hashmap, or efficiently parse strings/text, without the use of state, and learning the crazy monadic implementations they have for solving those problems

20:49 justin_smith: but I love using Clojure for long running tasks on dedicated servers, it is awesome for that

20:51 josiah14: justin_smith: for Scripting I was talking about Scheme. I figured, if I learned enough Clojure to build the sample Twitter app from the Rails tutorial by starting with Ring and building up from there, Scheme should be simple enough to pick up when I want something for a short running process

20:51 justin_smith: hh

20:51 yeah, that makes sense

21:36 schrotti: hm can't i use into with swap!?

21:37 always get an arity exception

21:37 kenrestivo: example?

21:37 schrotti: (swap tasks into @tasks [(future (inc 1))])

21:37 (def tasks (atom []))

21:37 +!

21:38 puredanger: the @tasks there is implicit and not needed

21:38 TEttinger: ,(let [tasks (atom [])] (swap! tasks into [(future (inc 1))]))

21:38 clojurebot: #<SecurityException java.lang.SecurityException: no threads please>

21:38 TEttinger: future ban

21:38 ,(let [tasks (atom [])] (swap! tasks into [(inc 1)]))

21:38 clojurebot: [2]

21:38 schrotti: puredanger: thanks

21:39 puredanger: keep in mind that swap functions may be retried in the case of collision so they typically should not have side effects

21:39 TEttinger: the atom syntax is a little tricky at first but quickly gets familiar

21:39 schrotti: thanks for the hints, appreciate it

21:40 nikki93: is the book "clojure programming" from o'reilly still relevant/up-to-date for the latest version of clojure?

21:41 TEttinger: mostly, yeah, I think that's the one I have. I didn't read the whole thing but it explained atom, var, agent, ref very well

21:42 nikki93: cool

21:42 and would you guys recommend that vs. "clojure for the brave and true"?

21:42 puredanger: they're both good; different styles

21:42 nikki93: I'm planning to use emacs with cider etc. and have a little bit of lisp experience from land of lisp, and lots of general coding experience

21:43 puredanger: Stu mentioned to me recently that he checks the code examples for every new version of Clojure and he has made 0 code changes from 1.2 through 1.6 for his Clojure book

21:44 in general, we try to make things relatively stable across releases

21:45 which means that the Clojure books mostly age by not including new stuff rather than actively being wrong

21:45 if I get off of irc and work on it instead, we will hopefully get our book into beta in a month or so https://pragprog.com/book/vmclojeco/clojure-applied

21:46 nullptr`: puredanger: looking forward to it!

21:46 puredanger: I'm looking forward to being done with it!

21:47 nullptr`: speaking of "new stuff", is there any plan to cover transducers or core.async?

21:47 puredanger: in our book? definitely.

21:48 nullptr: that's great, both i think could benefit from extended coverage

21:48 puredanger: unfortunately I spend my days making the stuff I wrote the night before out of date

21:48 kenrestivo: +1 for async. it seems most of the knowledge of it is folklore still.

21:48 puredanger: we will not be a canonical or exhaustive resource, but I think it will have more coverage than anything else out there

21:49 kenrestivo: there's an art form to using it right, i think

21:49 puredanger: I think a ~100 pg short book only on core.async would be killer

21:49 I'm not going to write it :)

21:49 kenrestivo: one can quickly get into a kind of async hell with channels everywhere and trying to keep track of all the different kinds of messages that can be sent/received

21:50 nullptr: agreed. you probably know the people who are qualified, talk them into it!

21:50 gfredericks: call it One Weird Macro

21:50 puredanger: I don't think Tim B has any interest. Someone tell Stuart to do it. :)

21:51 kenrestivo: are there oddities of transducers which need documenting? i watched rich's presentation, and after hearing his analogy to peeling apples, it all made sense

21:51 puredanger: plenty :)

21:51 nullptr: gfredericks: ha!

21:51 puredanger: making new ones all the time :)

21:52 kenrestivo: i haven't used them in production yet. waiting for 1.7

21:52 nullptr: yeah, i think weird eager/lazy implications could consume quite a few pages

21:52 puredanger: some of the benchmarking I've done is really promising - I think when used pervasively, they are going to be really important for some applications

21:53 for example, you can see a bit of it at http://dev.clojure.org/jira/browse/CLJ-1546 where I've been reworking vec

21:55 there's a chart attached with a lot of timings. vec on PersistentList (which goes via IReduce paths instead of seq paths) is ~7 secs for 1024 element list vs 28 sec for into.

21:55 that's not even transducers but what can sit at the bottom

21:55 when the vec stuff there is combined with the Iterable improvements on http://dev.clojure.org/jira/browse/CLJ-1499, I see similarly big improvements on maps and sets

21:56 and I have a few scratch times for a few new transducers in http://dev.clojure.org/jira/browse/CLJ-1601 (adding distinct, interpose, and map-indexed transducers)

21:57 ex: distinct with seq - 821 micro sec vs 43 micro sec for transducer version

21:57 nullptr: wow, juicy stuff

21:57 puredanger: all of those are effectively done and waiting for inclusion still

21:58 when you start to combine these so you can get a single very fast pass instead of many layers of sequence functions, it adds up

22:00 still in work are new reducible versions of range, cycle, iterate, keys, vals

22:00 nullptr: yes, and given the typical data oriented nature of clojure code this isn't theoretical -- good stuff indeed

22:01 puredanger: I'm finding it pretty easy to put into practice - it does really require you to separate how you think about the algorithm part vs the output part

22:01 the two functions to transduce that is

22:06 TEttinger: this is great stuff, puredanger

22:06 speeding up sequential data operations should be a massive boost to idiomatic clojure performance

22:08 puredanger: well, unfortunately you don't get it all for free. you do have to explicitly use transducers but I think that's an easy thing to do in many cases.

22:08 when we can integrate Zach's unrolled small collections, I think we will see a lot of programs become automatically faster

22:08 TEttinger: Zach being ztellman?

22:09 puredanger: yeah. while we had the opportunity, I did some code review with him at the conj and I think it should be no problem to get that into 1.8.

22:09 TEttinger: that dude is the clojure performance wizard

22:09 puredanger: this is http://dev.clojure.org/jira/browse/CLJ-1517 I'm talking about

22:11 in service of the vec enhancements, I did some histograms of programs to see typical sizes of collections being passed around. unsurprisingly, tons of collections < 10 elements.

22:13 TEttinger: oh yeah, that's what I'd expect too

22:25 cfleming: puredanger: I want that change.

22:25 puredanger: which?

22:25 cfleming: small collections

22:25 puredanger: me too. but it's not going to make it in 1.7.

22:25 cfleming: I think that's going to be a great addition to Clojure

22:26 Yeah, I understand. That's one of those changes I'd consider running a patched version for.

22:26 puredanger: it has some pretty wide impacts - Zach's done the dev work but not the integration part of it. I know of a few problem areas that will need some attention.

22:27 cfleming: Interesting, what are the problems there? I talked to him at the conj, I know that he didn't do the integration to instantiate the unrolled collections.

22:27 But that doesn't seem too problematic.

22:27 puredanger: 80% of it is easy and then there's the other 80%

22:28 cfleming: Hah.

22:28 puredanger: there's an existing issue with how constant collections are represented in bytecode that Nicola and I have both spent a fair amount of time on and Rich has looked at a couple of patches even.

22:29 it mostly comes up right now on PAM/PHM confusion but now we will have not 2 but 8 or 9 or whatever implementations which I think will make it far more obvious

22:29 and extend to vectors

22:30 cfleming: Ok, interesting. Is there a jira issue for that?

22:30 puredanger: presumably PAM goes away - that will impact some stuff but I'm not really sure what

22:30 yeah….

22:30 cfleming: Yeah, it'll be interesting to see how much code inadvertently relies on PAM being sorted.

22:31 puredanger: a couple actually

22:31 well that aspect is retained by Zach's collections

22:31 cfleming: Ah ok.

22:31 puredanger: not sorted - ordered

22:31 cfleming: Yeah, maintained in insertion order is a better way to put it.

22:31 Wild_Cat: what changes are being considered for small collections?

22:31 emaczen: Does anyone have experience configuring MongoDB with a Luminus webapp?

22:31 puredanger: some tickets - http://dev.clojure.org/jira/browse/CLJ-1093

22:32 Wild_Cat: see http://dev.clojure.org/jira/browse/CLJ-1517

22:32 Wild_Cat: also, Guest1882 is spamming in queries. Any ops there?

22:32 cfleming: Wild_Cat: Also see http://blog.factual.com/using-clojure-to-generate-java-to-reimplement-clojure, it's a good read.

22:32 puredanger: oh yeah, much better pointer :)

22:34 someone has suggested adding more ops here and I'd be happy to do that but I'm not sure how to make that happen or who exactly current ops are

22:35 Wild_Cat: puredanger, cfleming: excellent, reading that now. Thanks.

22:35 justin_smith: puredanger: I know technomancy has ops

22:35 cfleming: puredanger: I'm also dying to use transducers in Cursive, I use sequences all over the place, and I have a ton of use cases for reduce-like things that are a pain to implement using actual reduce (mostly 1-N transforms, or M-N transforms).

22:36 I'm hoping I'll be able to provide a quickfix to auto-convert threaded forms to transducer use.

22:36 puredanger: cfleming: I hope that you can use them soon :)

22:36 hiredman: technomancy is/was the newest op, but he isn't in?

22:36 puredanger: cfleming: in some cases that's obvious but in others I think it really requires rethinking parts of your program

22:37 like merely replacing sequence transformations with transducers wrapped in a sequence call is probably not what you really want

22:37 cfleming: puredanger: Yeah, no doubt. I need to try some manual translations to get an idea of how to do it first - any suggestions for tricky cases welcome.

22:37 puredanger: but I haven't really done this kind of refactoring on any scale so maybe there are

22:38 cfleming: Right, but as long as it produces equivalent working code, it's probably a good start to a refactoring, and should be faster.

22:38 I'd probably mostly want to convert to transduce, which is not exactly equivalent but mostly.

22:38 puredanger: probably. it also has different laziness semantics though. in many cases, you won't notice but in some you will

22:39 cfleming: transduce is importantly different in separating the transformation from the final reducing function

22:39 cfleming: Yeah, no doubt. Still, since it's a manual change I can assume the user knows what they're doing.

22:40 puredanger: Yeah, like I say I haven't done any of this manually yet so I'm still not sure what I want. But I'm hopeful that I can provide some automatic translations that will be pretty helpful.

22:40 * puredanger places where you are collecting the result into a collection are better served by into in most cases

22:40 puredanger: which will automatically use transients if possible

22:41 cfleming: I'm planning to implement a new duplicated code inspection in v14, so hopefully it'll also be able to automatically suggest extracting common transformations.

22:41 puredanger: cool

22:42 cfleming: Yeah - I'm imagining a series of options for the transfomation - switch to sequence, switch to transduce with into etc.

22:42 puredanger: there are definitely some common patterns

22:42 cfleming: When I get a moment I'll try it out and send it to you guys to try out - you've done this a lot more than me.

22:43 Thanks for that JIRA pointer BTW, interesting.

22:44 puredanger: being able to switch something like (->> s (filter odd?) (map inc) (reduce +)) into (transduce (comp (filter odd?) (map inc)) + s) would be cool

22:45 andyf: Is an email to clojure-Dev nominating other ops a way to proceed ?

22:45 puredanger: I don't even think that's necessary?

22:45 just whoever can do the thing needs to do the thing

22:46 (I am a pretty dumb irc user so I don't even know how to do whatever I would need to do but I'm sure that's google-able :)

22:46 cfleming: puredanger: Right, that should be relatively straightforward, as long as the thread form only contains core seq functions.

22:47 Since the user has to explicitly request the transformation, as long as it doesn't totally break code I think it'll be useful.

22:47 justin_smith: puredanger: whoever has ops now has the power to add other users to the list of people who can get ops. The right way to do it is to register them as people who can get ops via chanserv, and then they can ask chanserv for ops priveleges whenever needed.

22:47 puredanger: the second half of that says things I don't understand but I am on board :)

22:48 justin_smith: puredanger: chanserv is an automated thing - you say "I want my privs" and if you are on the right list it turns those privs on

22:48 puredanger: the next time I see technomancy on here I'll ask him about it

22:48 where "you" == some registered nick?

22:49 kenrestivo: for some reason, the discussion of unrolling loops me reminds me of f_unroll_loops and gentoo

22:49 justin_smith: puredanger: yeah, "/msg chanserv help" for the basics

22:53 puredanger: thx

22:53 justin_smith: I think amalloy would make a good op

22:54 puredanger: for sure

22:55 amalloy: last time this came up, technomancy found out he had some kind of limited ops and couldn't promote anyone else

22:55 justin_smith: who does chanserv think is in control?

22:55 puredanger: ah

22:55 justin_smith: chanserv says rhickey

22:56 puredanger: he's on here all the time :)

22:56 justin_smith: well, rhickey can just do a quick login and give full ops to technomancy, and then technomancy can do the rest

22:57 puredanger: does that mean that no one has rights? probably chouser too I'd guess.

22:57 justin_smith: maybe someone else has those privs - but rhickey definitely does

22:58 kenrestivo: last @'s i've seen in recent years have been chouser and technomancy

23:04 puredanger: good times…. http://clojure-log.n01se.net/date/2008-02-01.html

23:05 justin_smith: nice

23:08 puredanger: in putting together the data for the conj timeline shirt I went back and read a ton of old #clojure logs and commit logs - so weird to be able to travel back to that time with such high fidelity

23:08 it repeatedly freaked me out to see things get developed in java and c# in parallel too

23:10 hiredman: nostalgia as a service

23:10 schrotti: hehe

23:27 hiredman: my first interactions with a number of past and present coworkers are preserved in the logs of #clojure

23:35 kenrestivo: ~seen rhickey

23:35 clojurebot: It's greek to me.

23:35 lasericus: Would anyone be so kind as to tell me why this expression ((partial assoc {:text "flarp"} :id) (-> {:foo 45} vals first)) evaluates to {:id 45, :text "flarp"} while this expression (-> {:foo 45} vals first (partial assoc {:text "flarp"} :id)) reduces to a partially-applied function?

23:35 justin_smith: $seen rhickey

23:35 lazybot: rhickey was last seen quitting 76 weeks and 1 day ago.

23:35 kenrestivo: $seen chouser

23:35 lazybot: chouser was last seen joining on clojure 4 weeks and 4 days ago.

23:35 kenrestivo: $seen technomanc

23:35 lazybot: I have never seen technomanc.

23:35 kenrestivo: $seen technomancy

23:35 lazybot: technomancy was last seen talking on #leiningen 4 hours and 47 minutes ago.

23:36 kenrestivo: alright, there's the relevant metrics

23:38 TEttinger: lasericus: -> inserts the data that was returned by the previous threaded form as the first argument to the next form. (partial assoc {:text "flarp"} :id)) becomes (partial :foo assoc {:text "flarp"} :id)) there

23:39 I'm guessing that's the problem

23:39 you can defn the fn earlier or use let

23:39 lasericus: TEttinger: Interesting. Let me riddle what you just typed for a moment.

23:39 kenrestivo: you could try the hack of (#(assoc ....))

23:41 yeah, the -> is sticking the output of "first" after partial. you could try hacking it to use ->> instead ....

23:41 or, when i find myself having to do nasty hacks to make a perfectly OCD -> thread, i give up and just use nested parens instead

23:41 justin_smith: also, you can stick ->> inside ->

23:41 kenrestivo: sometimes aspberger's isn't really an advantage.

23:42 lasericus: I would imagine - now that I'm re-reading the ->> docs - that simply replacing -> with ->> in my above example would have resulted in the desired behavior (given that the result of the form immediately before partial would be used as the last argument to partial).

23:42 justin_smith: ,(-> {:foo 45} vals first (->> (assoc {:text "flarp"} :id)))

23:42 clojurebot: {:id 45, :text "flarp"}

23:43 justin_smith: ,(->> {:foo 45} vals first (assoc {:text "flarp"} :id)) ; actually

23:43 clojurebot: {:id 45, :text "flarp"}

23:43 justin_smith: but sometimes there is reason to use the prior version

23:43 you don't even want partial there

23:44 lasericus: justin_smith: Bizarre. It appears to me that the expression (assoc {:text "flarp"} :id) would result in an ArityException.

23:44 justin_smith: lasericus: macros

23:45 ->> doesn't do anything at runtime, it transforms the input before it is compiled

23:45 lasericus: justin_smith: Ah, yes. Thanks for the help.

23:53 TEttinger: lasericus: aspberger's is awesome for maintaining focus, so are adderall and its family of stimulants. with their powers combined, they form THE ATTENTION SQUAD!

23:54 err, ^ kenrestivo

23:59 kenrestivo: lazybot: no, assoc needs to know what key to assoc to , and what data to stuff in there. if you just do (assoc feh :meh) there's someting missing

Logging service provided by n01se.net