#clojure log - Dec 10 2014

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

0:03 irctc: hi

0:04 I was wondering if someone could tell me why this seemingly basic program (6 lines) doesn't work as intended http://lpaste.net/116138

0:06 I guess everyone is sleeping

0:06 I'll try again tomorrow

0:06 tired anyway

0:06 gfredericks: irctc: conj isn't side-effecting

0:07 it returns a new data structure, which you're ignoring

0:07 irctc: so I need to use something else or take in the new structure?

0:07 gfredericks: use the new structure

0:07 irctc: how'

0:08 gfredericks: depends on what you're trying to do; your whole example is based on side effects which is not the normal style of programming

0:08 irctc: I'm trying to add data to a vector, then sort the vector and print the head

0:09 the data comes from input

0:09 so I have to add incrementally

0:09 I can do this very easily but I don't seem to understand just the data gathering

0:10 (I've tested the rest of the program and it works)

0:12 thanks for the hint I'll keep googling

1:27 Javran: 大白兔!

1:27 sorry wrong channel

1:39 justin_smith: $mail irctc the easy way to do it is to make the vector an extra loop parameter, and put the conj inside the recur. Also, look up peristent data strucures, immutibility is one of the most fundamental concepts in Clojure.

1:39 lazybot: Message saved.

2:15 dysfun: there's got to be a better way to debug macros than macroexpand and friends

2:16 justin_smith: having as little code as possible inside macros, and doing the real work in functions?

2:24 fairuz: Hi guys. I've seen a lot of #( ... ). Is this some syntatic sugar to something? I suspected it's the same thing as (fn [] ...) ?

2:24 justin_smith: ,'#(+ % %)

2:24 clojurebot: (fn* [p1__25#] (+ p1__25# p1__25#))

2:25 justin_smith: ,'#(apply + %&)

2:25 clojurebot: (fn* [& rest__50#] (apply + rest__50#))

2:26 fairuz: cool

2:27 ,'(+ 1 2)

2:27 clojurebot: (+ 1 2)

2:27 fairuz: ,'#(+ 1 2)

2:27 clojurebot: (fn* [] (+ 1 2))

2:27 fairuz: ,'#(+ 1 %)

2:27 clojurebot: (fn* [p1__123#] (+ 1 p1__123#))

2:27 fairuz: cool got it. Thanks!

2:28 pretty neat

2:28 justin_smith: yeah, quote is often handy for figuring out anything with a # in it

2:28 (that is, reader things)

2:29 fairuz: ah ok

2:29 but why the * at fn* ?

2:29 justin_smith: fn* is the underlying implementation of fn

2:30 fairuz: ah ok

2:31 justin_smith: it is almost identical, except it doesn't do the same destructuring - if you look at the source to fn, it's a complicated macro constructing a call to fn*

2:32 it also handles things like :pre and :post

2:37 fairuz: Just want to shoot my question about Liberator's defresource here. I have this :location #(build-entry-url (get % :request) (get % ::id)) in my defresource. How it knows what to put as the functions arguments? In this case I assume there are 2 since there are 2 %

2:39 seancorfield: fairuz: no, that's just one argument

2:39 % is the same as %1

2:39 multiple arguments would be %1 %2 etc

2:39 fairuz: oh

2:39 new thing again :) thanks

2:39 neat neat

2:40 seancorfield: so it calls build-entry-url with two arguments, the :request key of the argument and the :id key of the argument

2:41 dysfun: justin_smith: well yeah, of course i've minimised them, but the output looks fine...

2:42 fairuz: seancorfield: ok

2:42 ,'#(% %1 %2)

2:42 andyf: dysfun: Colin Fleming might be working on some enhancements to Cursive to show macro-expansions step by step

2:42 clojurebot: (fn* [p1__25# p2__26#] (p1__25# p1__25# p2__26#))

2:42 andyf: dysfun: pprint can help longer macro expansions look a bit more readable.

2:42 schrotti: hm has someone advise on how to conditionally load namespaces or resources? currently i use an env variable and the load fn, to load a .clj file with definitions into a namespace. i'd like to do this to make the app more modular and to easily add support for other storage backends.

2:44 justin_smith: schrotti: better to define a multimethod or protocol, and use the implementation that the runtime code passes in

2:44 schrotti: justin_smith: i'm using protocols already

2:45 dysfun: andyf: that sounds promising

2:45 https://www.refheap.com/6ddc06df791b72447725807f9 # if you try to even (macroexpand '(dev-prelude)) it complains with an error. i can't for the life of me figure out why

2:45 i've stepped through all the individual macro invocations and i can't see what the problem is

2:46 justin_smith: schrotti: in that case, code to the protocol functions, and that way the decision of which impl to use is isolated to one place in the code. You can use a change in classpath to determine which impl gets loaded.

2:46 schrotti: justin_smith: but how to define which implementation should be used during runtime? i don't like to throw conditional statements in everywhere. and theres also the problem how the storage backends access tables/keys.

2:47 andyf: dysfun: :Private should be :private, but I doubt that is the issue.

2:47 justin_smith: so instead of having everything in src/ you can also have foo-backend/bar/storage_impl.clj and quux-backend/bar/storage_impl.clj and decide at launch which is on the classpath

2:47 that is going to be a lot cleaner than conditional load

2:47 dysfun: andyf: yeah, it'd be nice if that one was flagged up heh

2:47 andyf: I don?t know if it is kosher to use ~ or ~@ with a macro inside ? never tried it.

2:48 dysfun: hrm, i just assumed it would work tbh

2:49 schrotti: justin_smith: but i don't understand how to implement the decision which one should be on the classpath, tried it already with require

2:50 andyf: it might. I just don?t recall seeing it before, and don?t know what happens.

2:50 dysfun: ,(defmacro tm [] `(println ~(quote foo)))

2:50 clojurebot: #'sandbox/tm

2:50 dysfun: (macroexpand '(tm))

2:50 ,(macroexpand '(tm))

2:50 clojurebot: (clojure.core/println foo)

2:50 schrotti: justin_smith: is it possible that you can provide me a small example?

2:50 dysfun: andyf: looks like ~ works

2:51 well, quote is a special form i suppose

2:51 justin_smith: schrotti: it would be a question of launch profiles (easiest to do via lein) lein with-profile :foo run where foo adds foo-backend/ to the source-paths

2:52 schrotti: justin_smith: ah thanks now i understand

2:52 justin_smith: example of profile-specific paths setup here https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L160

2:52 amalloy: andyf: ` and ~ are just reader shorthands for functions that build lists. there's no reason they would care whether there's a macro involved

2:54 sm0ke: how do i call a super method in a deftype?

2:55 dysfun: sm0ke: a super method? are you sure?

2:55 justin_smith: sm0ke: I don't know - I don't even know if it is possible actually. But proxy has proxy-super.

2:55 dysfun: well, deftype can inherit

2:55 sm0ke: yep proxy has , gen-class also has :expose or something

2:55 dysfun: justin_smith: since when?

2:56 justin_smith: oh wait, deftype can't do concrete inheritance, only protocols and interfaces

2:56 my bad

2:56 amalloy: the first problem i see with dysfun's dev-prelude is that midje.sweet gets namespace-qualified to like clojure.core/midje.sweet

2:56 dysfun: nice spot

2:56 justin_smith: sm0ke: so there's your answer: you can't call the super, because there is no way to have a super

2:57 dysfun: however, that doesn't fix it :/

2:57 sm0ke: ,(deftype Foo [] Object)

2:57 clojurebot: sandbox.Foo

2:57 amalloy: dysfun: "it complains with an error" is a complaint i generally decline to do anything with

2:57 dysfun: sm0ke: when you're doing undocumented things, you get to keep the pieces

2:57 justin_smith: sm0ke: Object is special cased, not as a superclass, but just to let you override methods on Object

2:58 dysfun: amalloy: how about "it complains with IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Var clojure.lang.RT.seqFrom (RT.java:505)" ?

2:58 amalloy: the errors are printed because they're useful; saying there's an error but not gisting it is just teasing

2:58 dysfun: better, but a whole stacktrace would be much easier

2:58 dysfun: sorry, i didn't realise i wasn't being helpful enough

2:58 how can i generate you a stacktrace?

2:58 justin_smith: clojure.repl/pst is the easy way

2:59 amalloy: dysfun: (.printStackTrace *e *out*), immediately after your failing call to macroexpand

2:59 pst is evil

2:59 justin_smith: why is that?

2:59 dysfun: https://www.refheap.com/94664

2:59 amalloy: justin_smith: it tries to be too smart

2:59 hides a lot of useful information

2:59 justin_smith: I had no idea

3:00 amalloy: see? that output came from pst, and it's useless garbage

3:00 dysfun: can you try again, with the longer form?

3:00 dysfun: https://www.refheap.com/94665

3:01 amalloy: fipp.printer? how is fipp getting involved?

3:01 dysfun: i don't even know what fipp is

3:01 justin_smith: it's a pretty printer

3:01 amalloy: this looks like a stacktrace from nrepl

3:01 dysfun: this is from lein repl

3:01 amalloy: weeeeeird

3:02 dysfun: would you like me to do it at a plain java prompt?

3:02 er clojure prompt

3:02 amalloy: dysfun: that would be great, yeah. sorry to make you go through that horror

3:02 but it does look like something is going wrong in lein repl itself

3:02 dysfun: heh. i can live with typing one thing into it

3:02 justin_smith: I bet something weird is happening in a "pretty printing" middleware

3:02 dysfun: i note that this happens outside of lein repl too, incidentally

3:03 justin_smith: so what's the cause/symptom again? I missed it in the scrollback

3:03 amalloy: justin_smith: dysfun gisted some code that throws an exception when you macroexpand it

3:03 it looks fine to me, so i asked for the macroexpansion stacktrace

3:04 dysfun: gah, how do i open a clojure repl when i don't know where the clojure jar is?

3:04 amalloy: dysfun: java -cp `lein classpath` clojure.main

3:04 dysfun: ty

3:05 justin_smith: if nil-macros returned a var instead of a list, you would see that var/sequence error

3:05 andyf: puget and whidbey are in that stacktrace, too.

3:05 dysfun: amalloy: and *e doesn't appear to work. how can i get you a stacktrace?

3:05 justin_smith: dysfun: additionally, you as using (do ~@(map ...)) to generate the return value from nil-macros

3:06 amalloy: really?

3:06 justin_smith: I would not be surprised if that did not return a collection

3:06 dysfun: oh hang on

3:06 no, it's because it *worked*

3:06 amalloy: lovely

3:06 sm0ke: ,(deftype Foo [x] Object)

3:06 clojurebot: sandbox.Foo

3:06 sm0ke: ,(Foo 1)

3:06 clojurebot: #<RuntimeException java.lang.RuntimeException: Expecting var, but Foo is mapped to class sandbox.Foo>

3:06 sm0ke: ,(Foo. 1)

3:06 clojurebot: #<Foo sandbox.Foo@fc374c>

3:06 sm0ke: how do i access the x now?

3:07 dysfun: amalloy: would it help if i disabled all my nrepl middleware?

3:07 justin_smith: ,(.x (Foo. 1))

3:07 clojurebot: #<CompilerException java.lang.IllegalArgumentException: Unable to resolve classname: Foo, compiling:(NO_SOURCE_PATH:0:0)>

3:07 sm0ke: hehe

3:07 amalloy: dysfun: well, there's either a bug in leiningen, or in some of your middleware

3:07 sm0ke: ,(deftype Foo [x] Object)

3:07 clojurebot: sandbox.Foo

3:07 sm0ke: ,(.x (Foo. 1))

3:07 clojurebot: 1

3:07 amalloy: i'm guessing it's a fipp-related middleware, so turn them off until it stops breaking

3:07 sm0ke: oops

3:07 amalloy: then file a bug at the one that is breaking things

3:08 sm0ke: wow embarasing, thanks justin_smith

3:08 * dysfun has just disabled all of them, will try now

3:08 amalloy: it is probably whidbey?

3:09 dysfun: it hadn't even occurred to me that a pretty printer would perform such action at a distance

3:10 okay, replicated with all nrepl middleware disabled

3:10 amalloy: the foundational tools you use need to be rock-solid, because you'll never suspect they're the problem

3:10 andyf: It is tough to test every case when code is involved.

3:11 amalloy: dysfun: replicated, as in the issue still occurs? with the same stacktrace inside whidbey and fipp? that seems unlikely

3:11 maybe whidbey is part of nrepl now, i dunno

3:11 andyf: pprint by itself goes into an infinite loop for forms containing Vars created by defprotocol.

3:11 dysfun: the same error message

3:11 new stacktrace :)

3:11 https://www.refheap.com/94666

3:12 amalloy: oh

3:12 dysfun: just remove the ~@ around nil-macros completely

3:13 justin_smith: haha, I called it

3:13 amalloy: the problem is obvious now that there's not this weird fipp thing distracting me :)

3:13 dysfun: oh

3:13 andyf: what is the problem?

3:13 dysfun: right, yeah

3:13 * dysfun feels stupid now

3:13 dysfun: thanks folks

3:14 and of course the reason it worked in the clojure repl is because it went into 'live' mode

3:14 justin_smith: <justin_smith> dysfun: additionally, you as using (do ~@(map ...)) to generate the return value from nil-macros ... <justin_smith> I would not be surprised if that did not return a collection

3:14 amalloy: justin_smith: but that's not actually right

3:14 justin_smith: OK

3:14 what is it then?

3:14 amalloy: nil-macros returned a list, as expected

3:15 but it's a macro

3:15 so you should either just call it, eg with (in-live (nil-macros ...)), or else make it into a function and then splice it in

3:15 you can't make it a macro *and* splice it in

3:16 andyf: I should have listened to my vague misgivings about that.

3:16 amalloy: because if you do, nil-macros gets called at macroexpansion time! and it returns a var, of course, which you try to splice into the user's code

3:16 justin_smith: OK. I would have said "since it's a macro you don't get the list it returns" but I guess my understanding of the world of macros is still insufficient

3:16 cfleming: dysfun andyf: I have a prototype of a stepping macroexpander parked - the issue was that naive stepping (i.e. stepping from start to finish) is really tedious. You need to be able to select a form to expand, but that's surprisingly hard to do if you want to properly respect &env

3:16 dysfun andyf: I'm hoping to get back to that soon.

3:16 justin_smith: and with my simplified explanation "it doesn't return a list" actually makes sense. But I understand that your explanation is much more accurate.

3:18 (inc amalloy)

3:18 lazybot: ⇒ 204

3:18 dysfun: justin_smith: well, you aren't technically wrong, you just could have been more correct :)

3:18 amalloy: hmmm, i'm trying to think of a simpler example to make the distinction clear

3:20 dysfun: (inc amalloy)

3:20 lazybot: ⇒ 205

3:21 amalloy: justin_smith: actually, maybe my old blog post on macro-writing macros is enough: have you read http://amalloy.hubpages.com/hub/Clojure-macro-writing-macros ? it's got the opposite side of this coin, the inverse of the mistake dysfun made

3:23 justin_smith: so the alternate solution is that dysfun could still use ~@, and define his impl as functions rather than macros

3:24 and those would get used and expanded properly

3:24 dysfun: amalloy: heh, that macro is insane

3:24 amalloy: justin_smith: right

3:25 which i tried to say, with "so you should either just call it, eg with (in-live (nil-macros ...)), or else make it into a function and then splice it in"

3:25 but i can see how that might not be clear

3:25 justin_smith: so the standard "put your impl in a function, and only use a macro for the syntax part" advice helps here too

3:25 dysfun: except in this case, where the goal is removal

3:25 so it does have to be a macro

3:26 justin_smith: dysfun: until the last step, you can just be constructing lists

3:26 you can easily remove items from a list

3:26 and finally splice the lists into what the macro returns

3:26 zot: what might i do to debug if (shutdown-agents) doesn't actually shutdown fast anymore? i assume that one of my go blocks is doing something errant, but i can't find it yet :/

3:26 amalloy: dysfun: no, it doesn't have to be a macro. try this: put the ~@ back in, and change nil-macros from defmacro to defn

3:27 you should get equivalent behavior

3:27 like justin_smith is saying, you only need one defmacro as the outer shell; inside that, everything can be functions

3:27 dysfun: i thought ` was only valid inside macros?

3:27 amalloy: ,`x

3:27 clojurebot: sandbox/x

3:28 dysfun: hrm

3:28 amalloy: ` is just a shorthand for functions that build lists

3:28 you can even see in your own nil-macro: that's a function, which contains `!

3:29 dysfun: i must have been drunk when i wrote this

3:29 amalloy: that's a ^:Possibility

3:29 dysfun: :)

3:29 andyf: zot: Do you use any of future, clojure.java.shell/sh, or pmap

3:29 ?

3:29 justin_smith: dysfun: learning is state dependent, the more you code while drunk the better you will be at coding drunk.

3:29 zot: andyf: core.async only

3:30 andyf: Those are functions, not namespaces.

3:30 dysfun: justin_smith: i used to work at an investment bank. drinking at lunch was practically mandatory. my drunken perl is quite something

3:30 justin_smith: :)

3:30 rhg135: justin_smith: tp a point only

3:30 Look at m$

3:31 zot: andyf: i don't follow what you mean

3:31 andyf: I mean, do you use the functions future, or pmap, or sh?

3:31 zot: no, i do not.

3:32 dysfun: amalloy: i do not get equivalent behaviour. i get unable to resolve symbol now

3:32 #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: facts in this context, compiling:(tk0/util/macros.clj:49:18)>

3:32 zot: andyf: although i realize after answering that a third-party library might. looking now.

3:33 amalloy: oh, sure

3:33 zot: indeed, it does use future.

3:33 amalloy: you'd have to make some more changes than i said, because you'd need to quote things

3:33 dysfun: *nod*, i was about to test quoting them

3:33 amalloy: ~@(nil-macros 'facts ...)

3:33 clojurebot: Huh?

3:33 amalloy: clojurebot: stuff it

3:34 clojurebot: excusez-moi

3:34 amalloy: that's right

3:34 andyf: zot: You currently have a call to (shutdown-agents) in your program just before it exits?

3:34 zot: yep. otherwise i get to wait. but not even calling that just sits.

3:34 s/not/now/

3:35 andyf: zot: I?m not sure, but maybe if a future was created and its function is doing some long-running thing, the process will not exit? Is there much CPU utilization when your program fails to exit?

3:36 amalloy: does core.async even use the agents threadpool?

3:36 andyf: amalloy: I do not know, but zot says one of his third-party libs uses future

3:36 amalloy: ah, i missed that

3:39 zot: ugh. this is tricky. apparently i'm still a liar. the old version of the lib did. the current one doesn't. i'm ignorantly running the slightly new, so my grep gave me wrongness. (https://github.com/pingles/clj-kafka/blob/0.1.2-0.8/src/clj_kafka/consumer/zk.clj#L48 versus newer 0.2.8-0.8.1.1 tag)

3:40 justin_smith: zot: yeah, any impl of kafka is going to be doing some threaded stuff

3:40 zot: yes, as i would expect

3:40 i would just hope that it cleans up when using with-open / with-resource [their built in similar wrapper]

3:40 justin_smith: and the jvm won't shut down until those threads are good and ready

3:41 zot: i must be misusing it someplace :/

3:42 justin_smith: the underlying zookeeper lib is creating the threads, I think

3:42 also, top level namespace, which is terrible

3:44 found this gem in the zookeeper javadoc: "The request doesn't actually until the asynchronous callback is called."

3:45 zot: lol. except, ugh.

3:45 justin_smith: yeah, instantiating a ZooKeeper object implicitly creates a thread, the connection establishment is async

3:45 zot: but there was a time when it shutdown gracefully. so i must have done something wrong. (or i'm using it in a new/different way, and have forgotten.)

3:46 justin_smith: zot: you could try explicitly call .close on your zookeeper client? or does clj-kafka even expose that to you?

3:47 oh, it is already doing with-resource / zk/close

3:47 and furthermore, you already mentioned this

3:47 I am slowly catching up

3:47 zot: and it's greatly appreciated :)

3:48 justin_smith: zot: I have an ulterior motive here, I may have client work coming up that uses kafka, so this is a good chance to figure some stuff out

3:48 zot: yeah, i'm doing (kcore/with-resource [kc (make-kafka-consumer cfg)] kcons/shutdown …) which afaict is the right way

3:49 note that afa = not very far.

3:49 justin_smith: zot: backing up to another approach entirely - if you connect to your app in jvisualvm, you could check which threads remain active when it should be shutting down

3:49 zot: often the threads have informative names, otherwise you can see what code they are running

3:50 actually even jstack should suffice

3:50 zot: this sounds like exactly what i would want to do. it's new ground, but useful. i've not worked in the JVM in years, so it's mostly a black box to me ;)

3:50 justin_smith: zot: jvisualvm and jstack both come with the JDK if you have it

3:50 zot: i do. will play and see what i learn. thanks!

3:51 justin_smith: jstack will give you a stack trace for every thread - that should help

3:51 andyf: This isn't much additional info, but I did just run a toy test verifying that even calling shutdown-agents, any futures that are not finished will postpone the exiting from the JVM. But you may have known that already.

3:52 zot: i did not — i've still never used futures in clojure. every day is still learning new things.

3:57 andyf: When I tried jstack on a JVM waiting to exit with a future that was not done, the process showed up with a name like "clojure-agent-send-off-pool-0"

3:57 which is what the Clojure runtime names such threads by default, if you do not override it.

3:58 uh, I meant "thread" not "process" there.

3:59 zot: cool, nice to know. i'm checking it now.

4:00 justin_smith: andyf: well, given how rare Windows users are in the Clojuresphere, we can almost take pthreads for granted :)

4:00 cblop: does anyone know how to feed core.logic's pldb relations and facts from a vector?

4:00 zot: shall i assume that a thread in the state 'runnable' would willingly shutdown, and that the problems are likely WAITING (parking) threads?

4:01 cblop: i'm having problems because macros like db-rel require symbols as part of the relations

4:01 schrotti: justin_smith: maybe i'm still missing something, but to me it seems, that the way you suggested requires me to build an uberjar for each backend implementation

4:01 justin_smith: zot: this may help https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.State.html

4:03 schrotti: yeah, that solution would require a different uberjar for different backends. But one option could be separating those backends to their own jars, and providing those to the jvm separately on the classpath along with the uberjar

4:03 schrotti: I acknowledge that this is awkward

4:05 schrotti: backing up, you could have multiple namespaces that implement the same protocol, and pass the protocol implementation to the code that uses it. Then the conditional is only in one place at least. And it does not require using load at all.

4:06 schrotti: I kind of like the default assumption that a given namespace is only implemented in one place. I could easily foresee weird debugging experiences with a codebase that handled this in an idiosyncratic way.

4:09 zot: justin_smith: it seems likely that this is my problem: https://gist.github.com/anonymous/cf3023be4cce85ef67bb ; still trying to read, when the a (take N …) around the message block ought to have allowed this to close and stop trying to read. the rest are either in waiting / waiting_timed state, or appear to be normal jvm threads. am i crazy?

4:10 justin_smith: yeah, those are both stuck in polling state it looks like?

4:12 zot: appears to be. i'm curious if there's something bad that kcore/with-resource is being called within a core.async/thread call, since i just wrapped the shutdown handler, and it doesn't appear to be getting called.

4:14 justin_smith: zot: it's after 1 am my time, so I need to turn in. Good luck though.

4:14 zot: nope, makes no difference when i pull it out of the thread. ok. live with it and file an issue i guess.

4:14 tnx, sleep well

4:35 nonuby: using clojure.java.jdbc if I want to do an update! with col1 = col1 + 1 (on the db side) how would one accomplish that?

4:36 clgv: nonuby: that's not clojure specific, but sql specific. so you should find enough material on that online ;)

4:36 nonuby: clgv, i get that, found it, was looking for execute! not update! (a map friednly wrapper around execute!)

4:37 clgv: nonuby: good :)

4:45 SagiCZ1: can i somehow let the producer in core.async know that i wont be consuming anymore?

4:46 clgv: not through the channel I guess. you can only build up backpressure through the channel

4:46 does it even make sense not to consume products?

4:47 SagiCZ1: does it make sense to produce when no one is consuming?

4:50 kenrestivo: async macroeconomics.

4:51 SagiCZ1: let say the producer is keeping some expensive resource opened, so once it know that no one wants to consume, it can close the resource

4:54 clgv: SagiCZ1: sure, I was questioning the asymmetry itself

5:01 rritoch: Is there any way to type right on the function? When I try

5:01 (defn ^void myfun [] ...) I get an error

5:01 Err, to type hint void return type that is.

5:02 SagiCZ1: rritoch: i dont think so.. type hinting is to avoid reflection.. there is no reflection with void

5:04 rritoch: SagiCZ1: Ok thanks, I'm mostly using type hinting for improved documentation since the interface should automatically apply the correct types

5:05 SagiCZ1: rritoch: i am not sure that's a good idea.. well it probably can't hurt..

5:12 schrotti: hm why isn't the :uberjar-exclusions not working :/

5:14 i'd like to exclude app/storage/core.clj, with the following regex #".*storage/core.clj"

5:36 dysfun: hrm, lein repl times out, but :headless/:connect works fine. any clues?

5:39 rritoch: dysfun: If there is a possiblity that one of your repositories is offline or frozen you could try :update :never in your project.clj, and if your using :aot sometimes doing a precompile via lein compile can help. I've run into timeouts a few times for larger apps, 90% of the time my internet connection is to blame.

5:39 dysfun: i have all of the deps locally

5:39 and i am not using :aot

5:40 rritoch: dysfun: Even if you have your deps locally, it will still check the online repositories for newer versions

5:40 dysfun: i'm only using clojars

5:41 rritoch: dysfun: Ok I can't help you then. These are the only situations that have lead to me getting timeouts errors.

5:41 dysfun: :/

5:42 rritoch: dysfun: Is it possible that you have an infinite loop in code that's executing at compile time?

5:42 dysfun: if that was the case, it wouldn't work under :headless, surely?

5:46 rritoch: dysfun: Probably, the inf. compile loop was just a wild-guess. I really haven't run into a timeout when I precompile and disable downloading. Maybe you can try aot compiling it and see if it does any better. Aot compiled code loads faster.

5:47 dysfun: there just isn't enough code there to take ages, frankly

5:49 hrm, you may have been right actually

5:49 one of the deps was in maven central

5:49 and that seems to have just started working

5:50 but that seems an implausible outage

5:50 rritoch: dysfun: Plugins aren't aot-compiled, even if you want them to be. At least I haven't figured out a way to aot compile a plugin. So when you ran without aot, even though you don't have much code, the plugin code had to be compiled which was probably taking too long.

5:58 dysfun: hrm, it's cider-nrepl!

5:59 when i comment out their middleware, it works fine

6:02 rritoch: dysfun: Well at least your up and running, when I have timeouts like that it usually ends to a lot of f-words flying around until it's solved.

6:14 dysfun: believe me, i know that state well

6:14 rritoch: If you have an atom with a map where one of the keys contain an atom, is it possible and reliable to call swap! within the swap! method to ensure that the code remains thread-safe?

6:18 noncom: rritoch: ofcourse

6:18 but

6:19 you actually need to retreive the inner atom and call swap on it

6:19 it will remain the same atom

6:19 you do not need to re-include it again into the top one

6:19 rritoch ^

6:21 rritoch: i thought more and wanted to add that if you need to ensure the two atoms be changed as a single transaction, not like 2 thread-safe transactions, then them need to be refs

6:21 but as i said, i think that swapping only the inner atom will suffice for you

6:21 clgv: you cant convince a clojure function to have void as return

6:22 rritoch: ^^

6:22 rritoch: for primitive types you need to use this pattern (defn f ^long [^double x ...] ...)

6:23 rritoch: clgv: Thanks. I've had no problem with types so far, just the void which wasn't working.

6:23 clgv: rritoch: for general type hints up to clojure 1.6 you should prefer (defn ^String f [...] ...) - if I remember correctly that wont be needed in 1.7 anymore

6:23 rritoch: if thats the case you only type hint the argvector

6:29 rritoch: clgv: What about array types, can they be type hinted?

6:30 clgv: (defn ^{:tag (resolve (symbol "[I"))} foo [] ) compiles, but I'm not sure it's valid.

6:50 dysfun: rritoch: longs = array[long]

6:50 and similar appendings of 's' DTRT with other types

6:51 hydo: Any of you ever seen a funky classcastexception saying 'cant cast x.y.z to [Lx.y.z? packages are the same aside from the '[L'? Not the easiest thing to search google for.

6:53 clgv: rritoch: you can hint them as strings. but that has only effect on type inference and not the return type

6:54 rritoch: no the above form you provided probably wont work. I think I tried something like that myself. just use (defn ^"[I" foo [] ...)

7:00 rritoch: hydo: That is actually related to my discussion with clgv, you need to use make-array, the L means it is an array and your passing a single class instance.

7:01 hydo: !

7:01 noncom: hydo: [L is an array of longs

7:01 hydo: Thank you! No idea how long it would have taken me to figure that out.

7:01 noncom: actually that is a general java convention name

7:01 not clojure-specific

7:02 hydo: I'm coming from cl, so it's all greek to me. heh

7:02 clgv: hydo: probably a java function with variable arguments, right?

7:03 Bronsa: noncom: not a convention, it's from the jvm specs

7:03 clgv: a trick to figure out the class #(.getCanonicalName (Class/forName "[I"))

7:03 hydo: Well, no, the java call would be sender.getInventory().addItem(thing); Not sure if it takes a variable amount of arguments.

7:03 clgv: ,(.getCanonicalName (Class/forName "[I"))

7:03 clojurebot: "int[]"

7:04 clgv: hydo: the javadoc or source will tell you ;)

7:04 hydo: Yea, that's what I'm hunting :)

7:04 Actually, first I'm going to hunt a drink.

7:05 Bronsa: you can use reflection if you can't find the javadoc or the source

7:11 hydo: Bronsa: interestingly, it's cl.lang.reflector.boxarg that's throwing the exception.

7:12 rritoch: hydo: Here is some code which may make it more clear. ##(type (make-array (class {}) 5))

7:12 lazybot: ⇒ [Lclojure.lang.PersistentArrayMap;

7:12 rritoch: hydo: As you can see [L gets added for any array

7:12 andrewmcveigh: Is anyone from clojars.org here? I can't access https://clojars.org from our (shared) IP. Do you run a blocklist?

7:13 rritoch: hydo: accept primitive types which have their own [x symbols.

7:15 hydo: Yes, that does make it a little more clear. and, of course, you were right. The type signature (if you'll let me call it that) is (Item... items), which I'm assuming in java parlance means 'one or more'.

7:35 clgv: andrewmcveigh: do you use a proxy?

7:36 hydo: yes thats the varargs syntactic sugar

7:37 andrewmcveigh: clgv: No. No proxies here.

7:38 clgv: Everything was running fine last night.

7:38 clgv: andrewmcveigh: you can access the clojars.org implementation on github. I doubt that they run a permanent blocklist.

7:40 andrewmcveigh: clgv: Yeah, I doubt it too, just a bit weird.

7:55 mindbender1: How do I check if a UUID is valid?

7:55 hipsterslapfight: mindbender1: you mean to spec for a certain version?

7:56 mindbender1: hipsterslapfight: yeah

7:56 hipsterslapfight: http://stackoverflow.com/questions/7905929/how-to-test-valid-uuid-guid

7:56 ugh wrong window sorry

7:56 oh welp this is #clojure and i'm an idiot. sorry mindbender1 :v

7:57 mindbender1: np. Checking it out. thanks!

8:04 Is the no clojure library that handles uuid and issues realted to it?

8:04 *related

8:04 clgv: clj-uuid was mentioned yesterday

8:22 mindbender1: clgv: thanks

9:06 saltsa: hello, I had a very strange problem. When using (printf "%s\n" "foo") the texts didn't necessarily printed to the stdout at all. But when using (println (format "%s" "foo")) it worked correctly. Both worked in REPL but when running the software from JAR, it did print nothing.

9:07 this has something to do with the terminal buffering but i'm wondering why it didn't even displayed those messages after the program did exit?

9:10 wunki: all of a sudden I keep getting that clojure can't find any java classes

9:10 resulting in errors as: Caused by: java.lang.IllegalArgumentException: No matching method: sha1Hex

9:10 anyone have a clue how to debug this?

9:13 SagiCZ1: are you calling sha1Hex in some interop call?

9:13 seems like you are sending wrong parameters to the method

9:14 wunki: SagiCZ1: this is being called in the carmine library (redis)

9:15 SagiCZ1: but even if I remove or change this library, it will spit up a different error in which it says it can't find a java method

9:16 SagiCZ1: could be some sort of build error.. when this happen i invalidate caches and restart my ide

9:17 wunki: SagiCZ1: invalidate caches with `lein clean`?

9:17 SagiCZ1: are you not using repl for this?

9:17 wunki: I can't even get into the repl :(

9:17 SagiCZ1: and what ide/editor are you using?

9:19 wunki: `lein repl` in the console and also Emacs/Cider

9:20 julio: what is this channel about ?

9:20 SagiCZ1: julio: clojure the programming language

9:20 wunki: i guess some people who know more about emacs will help you

9:20 julio: Thank you SagiCz1 !

9:21 wunki: SagiCZ1: yeah, but this is not an editor problem. Must be some build artifacts or typo somewhere. But have no clue how to debug this.

9:22 SagiCZ1: i would check the objects you are passing with the 'type' function to make sure you have correct types of parameters

9:28 ppppaul: i'm having a lot of problems trying to use alts! with cljs

9:28 does anyone have any resources they know of that could guide me through?

9:29 zsh

9:40 rritoch: saltsa: I would suggest trying a different version of Java, check the output of (System/getProperty "java.vm.version") and make sure that is the same version your running it with. Based on the sources for the latest versions of clojure the only difference between the two methods is they both call java.io.PrintWriter.write but the println also calls java.io.PrintWriter.append to apply the newline.

9:40 saltsa: If that doesn't work you can always try using a new version of clojure. Either way this appears to be a java specific issue as I've never run into this problem.

9:41 saltsa: rritoch: in fact I did notice some differences between jdk 1.6 and 1.8

9:44 craigglennie: Good morning. I am building a toy webscraper to learn clojure, and I have a list of URLs to process. I’d like to do them in parallel, what’s the best way to go about it? I’m reading about core.async, but also wondering if there’s a simpler parallel map operation available

9:44 wunki: pmap?

9:44 clojurebot: pmap is not what you want

9:44 wunki: haha, thanks bot

9:46 craigglennie: wunkl: The docs say it’s “only useful for computationally intensive functions”, but I’m pretty sure I’ll be bounded by network IO. Still, I could try it.

9:49 clgv: craigglennie: clojure.core.reducers or maybe core.async

9:49 rpaulo: craigglennie: you can't do much about the networking part. only amortize the connection setup by reusing the same connection when the URLs point to the same server

9:51 craigglennie: Conceptually pmap seems to be exactly what I want - map my download function over my list of URLs, but in parallel

10:00 ppppaul: (go (print (alts! (to-chan [1 2 3 4])))) should this work in cljs? i'm only getting errors saying i have an undefined function being called

10:03 dnolen_: ppppaul: should work, perhaps forgot to :refer something?

10:08 ppppaul: https://gist.github.com/boxxxie/783427920e949eaf70c4

10:09 dnolen_, would you be able to look at that... i've been stuck on this for a whiel :(

10:09 ordnungswidrig: craigglennie: IIRC pmap uses a pool that is optimized if cpu bound (cores +2 or like that). I'd expect that core.async will work better

10:10 dnolen_: ppppaul: looks like you don't know how alts! works yet :) read the docs look for examples

10:10 ppppaul: :D

10:11 ordnungswidrig: craigglennie: maybe this is what you want: http://eng.climate.com/2014/02/25/claypoole-threadpool-tools-for-clojure/

10:11 dnolen_: ppppaul: (alts! [chan0 chan1 ...]) is the signature

10:11 ppppaul: i tried that as well... let me try again

10:11 dnolen_: ppppaul: also (alts! [[chan0 value-to-write] ...) works

10:12 ppppaul: it returns a vector of [value chan]

10:12 ppppaul: i get the same error when i wrap in a vector

10:13 craigglennie: ordnungswidrig: Thanks. I just realised that since I’m using Phantom I probably want a number of browser instances reading URLs off a queue (or similar). So I don’t think pmap would work there (unless the function I supplied instantiated a Phantom instance each time, but that’s going to be slow).

10:14 dnolen_: ppppaul: update the gist with what you are trying

10:15 ppppaul: ok

10:15 updated

10:15 dnolen_, ^

10:19 dnolen_: ppppaul: gist is not working code, only include the one that you think should work, comment out everything else

10:19 i.e. don't include multiple failing things

10:19 only *one*

10:20 ppppaul: updated dnolen_

10:21 ordnungswidrig: craigglennie: it's not a sin to use the java.util.concurrent classes for such tasks.

10:23 dnolen_: ppppaul: I'm going to try this - last point about gists - post minimal cases that people can test quickly, all the other dependencies are noise.

10:23 ppppaul: i'll remove them now

10:25 craigglennie: ordnungswidrig: I’ll take a look at that too. Thanks.

10:27 clgv: craigglennie: pmap is not what you want. since you probably want to use a couple hundred threads for downloading and processing

10:27 pmap only use "processor core count + 2"

10:31 dnolen_: ppppaul: are you looking at your compile warnings - compiling that gist I get a compiler warning about `to-chan` be an undeclared var

10:31 ppppaul: i added it to the refers

10:32 dnolen_: ppppaul: gist works fine for me

10:33 ppppaul: try a `lein cljsbuild clean` perhaps something got in a bad state during your experimentation

10:33 ppppaul: ok

10:35 omg

10:35 stuff is working now

10:35 dysfun: i wish to provide a first run wizard for my ring webapp. i'm reading a config file in the ring init handler, from which i determine if the first-run needs to be run. this is too late to conditionally change which routes are loaded through a simple (def .. (if... . is there a recommended way to handle this?

10:36 ppppaul: i have conflicting emotions at the moment

10:37 weavejester: dysfun: You could set a var or atom, and then use a delay to define your handler.

10:38 dysfun: Or write your own main function that defines your handler function on the fly from a configuration.

10:38 dysfun: actually, i already have a main(), this is for running from 'lein ring server'

10:38 (because free reloading)

10:38 weavejester: dysfun: Well, if you already have a main, you could just add in wrap-reload to get the reloading capability.

10:39 ppppaul: thanks dnolen_

10:39 weavejester: dysfun: Lein-Ring tends to make some flexibility compromises for ease of use.

10:39 dnolen_: ppppaul: np

10:39 dysfun: weavejester: *nod*

10:39 okay, well wrap-reload sounds like a great option. thanks

10:40 justin_smith: saltsa: use (flush) because printf does not flush automatically

10:40 saltsa: that's likely your issue

10:40 dysfun: weavejester: what does it use to open a browser window?

10:40 weavejester: dysfun: Lein-Ring just adds the wrap-reload and wrap-stacktrace functions automatically, but they can be manually added.

10:40 dysfun: Um, it's in clojure.core. Let me look up the name

10:41 dysfun: clojure.java.browse/browse-url

10:41 dysfun: brilliant, thanks :)

10:41 * dysfun also feels like lein-ring is demystified all of a sudden

10:42 weavejester: Incidentally, I tend to use a pattern like: (fn [config] (routes ...)) in my applications these days

10:43 So I generate my routes from a config map, usually supplied by Component

10:43 dysfun: *nod*

10:43 that's roughly what i had in mind :)

10:43 ordnungswidrig: weavejester: interesting, this matches my observation that `defxxx` macros tend to fall short for this kind of "wiring". I moved from `defresource` to `(fn [xxx] (resource ...))` recently.

10:44 justin_smith: "def* considered harmful"

10:44 weavejester: ordnungswidrig: Yeah, most of the time I'm not sure if def* macros are worth it. They tend to make things look more magical than they really are.

10:45 ordnungswidrig: ordnungswidrig: and that's not only blunder but also giving you all kind of headaches because you find yourself trapped in macro land.

10:45 * ordnungswidrig needs a t-shirt: "trapped in macro land".

11:00 SagiCZ1: no love for defn?

11:02 sm0ke: ,:a/122

11:02 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :a/122>

11:02 sm0ke: ,:a/w122

11:02 clojurebot: :a/w122

11:02 TEttinger: heh

11:03 Bronsa: ,:100

11:03 clojurebot: :100

11:03 TEttinger: namespace rules, weird

11:03 Bronsa: ,::100

11:03 clojurebot: :sandbox/100

11:03 Bronsa: :foo/100

11:03 ,m:foo/100

11:03 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: m:foo/100>

11:03 Bronsa: ,:foo/100

11:03 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :foo/100>

11:03 TEttinger: is that a bug?

11:03 sm0ke: this is a blocker for me

11:04 Bronsa: I just don't start keywords with a digit and live happy.

11:04 sm0ke: :D

11:04 Bronsa: definitely a bug TEttinger, not sure wich behaviour should be expected between ::100 and :foo/100 though

11:04 zB0hs: is there a way to have lein-exec pull deps from project.clj rather than having to explicitly specify in your clj file?

11:05 puredanger: keywords/symbols with a leading digit currently work by accident

11:05 TEttinger: a happy accident?

11:05 puredanger: i.e., the regex accidentally allows it by backtracking

11:06 I pushed a fix for that in 1.6 and we discovered that it broke a lot of people's code so we reverted

11:06 sm0ke: puredanger: is it intentionally disallowed for something like ##:a/11aa

11:06 TEttinger: ,:a/122

11:06 clojurebot: :a/122

11:07 TEttinger: done

11:07 sm0ke: what

11:07 ,:a/11

11:07 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :a/11>

11:07 sm0ke: ,:a/122

11:07 clojurebot: #<RuntimeException java.lang.RuntimeException: Invalid token: :a/122>

11:07 TEttinger: sm0ke, there's a \ufeff in there :P

11:07 puredanger: I'd say the behavior and docs are inconsistent around all of it

11:07 sm0ke: :D

11:07 puredanger: there is a ticket to clarify the docs and make the regex intentionally admit what we support

11:08 Bronsa: puredanger: this is where having a reader spec would help. if it was clear from the start what is allowed and what is not we could just tell those people "sorry, you have a bug"

11:08 puredanger: I'm not arguing

11:09 http://dev.clojure.org/jira/browse/CLJ-1286

11:09 devn: im glad that it hasn't been nailed down 100% TBH

11:09 but it might be time...

11:12 puredanger: Bronsa: I was looking at the reduce stuff in that range ticket just now… the difficulty is that the new LongRange implements both IReduce (when reducing over the sequence) and IChunk (when serving as one chunk of a chunked sequence) and those two forms of .reduce() have different semantics wrt reduced right now

11:12 Bronsa: puredanger: ouch.

11:12 puredanger: the code in the ticket is essentially aligning them on a single semantic

11:12 Bronsa: puredanger: an IChunk RangeSeq is out of the question?

11:13 puredanger: there are several possible ways to resolve it

11:14 for example not using the same class for both purposes or allowing it to support both senses (although the code is otherwise identical, so that's annoying and confusing)

11:14 Bronsa: puredanger: I'm obviously not the one to make those decisions but it's my opinion that a correct approach, whatever it may be, doesn't require users to explicitely (preserve-reduced f) on .reduce

11:14 puredanger: I think it's fairly confusing to have two interfaces with a reduce() method that have different semantics

11:15 Bronsa: puredanger: right I'd be much happier with IChunk/chunk_reduce

11:15 puredanger: that is another option

11:15 but it breaks any external impls of IChunk (if there are any)

11:15 Bronsa: puredanger: gvec is the only one I'm aware of

11:15 puredanger: I mean external to clojure itself

11:15 Bronsa: right, core.rrb-vectors and stuff

11:16 puredanger: there is both gvec's ArrayChunk and PV's ArrayChunk

11:16 of course, changing the semantics of reduce() also potentially breaks external users

11:16 s/users/implementers/

11:16 or maybe both :)

11:19 saltsa: justin_smith: yeah, flush is, but should those buffers be automatically flushed when the program exists? The stdout is just a normal terminal.

11:20 justin_smith: saltsa: I think the OS will gladly throw away your resources, including your output buffer

11:20 Bronsa: puredanger: FWIW a quick search on github for c.l.IChunk hasn't shown any users other than from clojure forks. rrb-vectors itself is not using it

11:21 saltsa: justin_smith: I'm quite sure some other programming languages will always flush the output. But at least changing that printf to println fixed it

11:21 justin_smith: saltsa: like I said, you can just call (flush)

11:22 or, that's what I tried to say, at least

11:23 saltsa: also, if you ended the printf with a \n that may have gotten an auto-flush. Not sure of that though.

11:28 joobus: is aleph the 'event-driven' framework for clojure?

11:29 and does one need to worry about threads in clojure when serving a web site? I've been reading about java having support for lightweight threads in the jvm, so I'm not sure I need to worry about serving one thread per request.

11:30 justin_smith: joobus: there are thread-pools, but no out of the box lightweight threads. They are just OS threads.

11:30 http-kit and aleph use pools iirc, jetty uses a thread per request (re-used out of a pool)

11:31 joobus: i'm trying to determine if i need to go the way of aleph, or if serving ring/http-kit behind nginx is good enough

11:31 justin_smith: you need nginx no matter what I would say

11:31 it has security features that the other web servers don't provide

11:32 joobus: right now i use twisted in python which requires writing all code a certain way to handle deferreds, and I don't know if there is huge benefit to aleph over http-kit

11:32 i agree on nginx's other features

11:32 justin_smith: also, aleph is not a framework, it's a server

11:33 aleph uses netty: http://netty.io/wiki/thread-model.html

11:34 that isn't the right page for info about their thread usage actually...

11:34 yeah, it looks like netty uses a thread-pool

11:40 kenrestivo: what reference type would you recommend for holding a mirror of external state, but which will get updated every few milliseconds with a polling loop. the state will need to be both read and written from the application

11:41 in other words, i have to poll, but also need to write. either i'll be updating it or the external world will be. and writes will be a transform of the existing (external) state

11:43 justin_smith: an agent makes sense (with both the polling process and your app's own logic updating the agent state)

11:43 atoms would introduce retries, which seems like a bad idea for your use case

11:43 as would refs

11:44 kungi: I am trying to use the component / reload workflow with this example. When I run `lein repl` `go` and then change any println statement ant then `reset` no changes occur. What am I doing wrong? https://gist.github.com/Kungi/47493fbb9de4aadc0629

11:50 nboskovic: Which should I get, On Lisp, ANSI Common Lisp or SICP?

11:51 kungi: nboskovic: On Lisp is for free, SICP is also free, and the other one I don't know.

11:52 nboskovic: Yes, I know

11:52 I'm saying though

11:52 justin_smith: sicp is the better of the three

11:52 nboskovic: IF you had to pick one, which one would it be? I'm at the Uni and while I would love to print them all out, there's only so much time in one day

11:53 kungi: nboskovic: I would get SICP

11:53 nboskovic: Or save time and get a copy from Amazon

11:54 nboskovic: heh, well

11:54 It would take weeks to get here if it got here at all

11:54 kungi: nboskovic: Ok where is here?

11:54 nboskovic: Argentina

11:54 justin_smith: split the difference and get a semi-decent ebook reader and load up all those free books?

11:54 just a thought

11:54 nboskovic: Our customs agency is pretty terrible

11:54 I had a kindle once

11:55 justin_smith: how was it?

11:55 nboskovic: Small

11:55 I'd rather have technical books in paper

11:55 It's better for notes and stuff

12:00 I can print out 5k pages per month as long as I provide the paper, which is dirt cheap anyways, so I might as well take advantage of it

12:01 justin_smith: nboskovic: yeah, with my favorite books I can actually find frequently needed info based on marks or tears on the pages

12:01 nboskovic: maybe we need an ebook reader that adds entropy to frequently accessed pages to make them stand out in the TOC

12:01 nboskovic: lol

12:01 Nothing beats paper imo

12:02 justin_smith: paper is great

12:02 sometimes I print out code to go over it with a pencil away from a screen

12:02 nboskovic: The only thing that could surpass paper is some kind of virtual reality environment where it feels like you're reading paper anyways

12:02 justin_smith: I am doing a project where I am going to need to write TANDY basic, and I am going to do everything in paper first because basic sucks so much

12:02 nboskovic: yeah, that's how I solve my hardest problems usually; though I write it down by hand

12:02 Ouch

12:03 bja_: I hate paper. If I can't use regex search on it, I'm not interested

12:03 nboskovic: That's one advantage to digital media

12:03 justin_smith: bja_: clearly you don't have the pcre ocular implant

12:03 life changer

12:03 kungi: I would like to have both. Write on the paper and transfer the notes into the eBook

12:03 bja_: (inc justin_smith)

12:03 lazybot: ⇒ 157

12:03 kungi: This would be awsome

12:03 nboskovic: some day, that will be something

12:03 justin_smith: we can only hope!

12:04 nboskovic: Probably sooner than we think

12:04 kungi: nboskovic: There was a company creating pens which record what you wrote

12:04 justin_smith: we have wetware that greps for faces

12:04 kungi: But they destoryed themselves

12:04 bja_: in the meantime, I have interns who have OCR software and a scanner

12:04 nboskovic: I remember that.. shame, really

12:04 kungi: Livescribe was awsome

12:05 TEttinger: kungi, it would be awesome to have a live scribe, a dead scribe doesn't sound useful

12:05 nboskovic: Well, if the technology exists it could be rebuilt

12:05 justin_smith: TEttinger: leaving one around just sounds depressing!

12:05 kungi: TEttinger: is there an english word for the german carnival Tata tata ...

12:06 justin_smith: kungi: maybe Ba-Dum-Tish

12:06 TEttinger: kungi, as I understand it, there are lots of german words with no english equivalents (Weltschmerz)

12:06 Zeitgeist

12:07 kungi: nboskovic: It's called dot-paper or donane paper afaic. You have a nearly invisible dot pattern on the paper and your pencil has a camera recognizing the pattern.

12:07 nboskovic: Yeah, I'm looking it up

12:07 justin_smith: TEttinger: don't be silly, Zeitgeist is just timeghost

12:07 nboskovic: I was wondering

12:07 kungi: We only need to print books with pattern and have an appropriate ebook then -> BAM!!!

12:07 justin_smith: /s

12:07 TEttinger: though both of those are compounds, and "spirit of the times" is pretty close

12:07 nboskovic: you could probably have a pen with a small gyroscope on the tip

12:07 then record the movement when you're writing

12:07 kungi: nboskovic: then you dont't know where you are in the book

12:08 justin_smith: TEttinger: but timeghost sounds so much more awesome, like something from Adventure Time

12:08 nboskovic: looks like gyroscopes are too big atm

12:08 TEttinger: heh

12:08 nboskovic: you'd have to have a pen, a gyroscope and a recorder/transmitter

12:08 for the movement

12:08 justin_smith: nboskovic: accellerometers are pretty miniaturized though

12:09 TEttinger: swedish has the interesting word "lagom" (might be missing a mark)

12:09 justin_smith: nboskovic: and iirc they are mady with super tiny gyros + super sensitive pressure sensors

12:09 nboskovic: and more to the point, an accellerometer in a pen tip would basically do what you want I think

12:09 kungi: \o/ It is made of wörkings!

12:10 nboskovic: Good

12:10 time to patent it

12:10 justin_smith: http://en.wikipedia.org/wiki/Digital_pen too late

12:11 nboskovic: welp

12:11 kungi: Note to my future self: when you have a dev/user.clj file you should include it into tools.nrepl .... refresh. If not everything breaks.

12:11 justin_smith: kungi: so that was your reloaded issue?

12:11 makes sense I guess

12:11 kungi: justin_smith: yes

12:11 nboskovic: but wait, those seem to be more like wacom-style pens

12:11 justin_smith: nboskovic: it's all varieties

12:11 including wacom and standalone

12:11 it's wikipedia after all

12:11 nboskovic: true

12:12 the maxell penit looks good

12:12 kungi: justin_smith: this issue took me nearly the whole day. And I was starting to question my sanity.

12:12 justin_smith: kungi: that always sucks

12:12 nboskovic: doesn't seem to be on sale though

12:13 kungi: justin_smith: Yes especially if you start to minimize and minimize and then you have less than half a page of code and still can't see the error

12:45 ppppaul: when making macros in cljs, do i have to make them in a clj file?

12:50 edbond: ppppaul, yes

12:51 ppppaul: ok

12:53 Bronsa: dnolen_: do you have a testcase for MATCH-98? I'm curious to see if the patch for CLJ-979 fixes that

12:54 amalloy_: kinseapo is the daily spammer

12:54 dnolen_: Bronsa: ticket has a test case http://dev.clojure.org/jira/browse/MATCH-98

12:55 Bronsa: ah, should have looked at it, thanks

12:56 dnolen_: Bronsa: let me know if your patch fixes, this definitely a years old infuriating bug

12:57 Bronsa: if it fixes, might be worth mentioning that all the AOT bugs in core.match pretty much boiled down to multimethod + classes

12:57 Bronsa: dnolen_: yep it does

12:58 dnolen_: "worth mentioning to puredanger"

12:58 Bronsa: wow, thanks for verifying

12:59 Bronsa: dnolen_: uhm wait I might have spoken too soon. it fixes an issue but not 100% sure it's that one

12:59 dnolen_: heh ok

12:59 Bronsa: dnolen_: (compile 'clojure.core.match) w/o that patch throws java.lang.NoClassDefFoundError: clojure/core/match/protocols/IPatternCompile, w/ patch completes

13:06 seangrove: Bronsa: Looking at https://github.com/clojure/tools.analyzer, it references create-var, but I'm not clear on what that should be

13:07 Bronsa: Sorry, nevermind, just looked at the source

13:07 * seangrove smacks forehead

13:12 pandeiro: is it possible to do the clojure CA online now?

13:16 joegallo: pandeiro: i googled "clojure ca" and got to http://clojure.org/contributing

13:16 then searched in the page for 'online' and found https://secure.echosign.com/public/hostedForm?formid=95YMDL576B336E

13:16 so i believe the answer is yes

13:17 pandeiro: joegallo: yeah i'm there i just wanted to make sure this was actually valid in place of mailing it in

13:18 i did it already, so i hope so :)

13:23 EvanR: i did it, i overwhelmed vim clojure-static's ability to format my indentation with ==

13:23 too many levels of brackets i guess

13:26 Bronsa: dnolen_: still not sure, will investigate better the interaction between defmulti/class literals/AOT tomorrow and let you know if there's an obvious fix on the clj side. I remember investigating this months ago but I don't remember what I found out.

13:27 TEttinger: EvanR, split up some logic then? ouch...

13:27 Bronsa: seangrove: in case it helps, in t.a.jvm create-var is ~ intern, in t.a.js it just returns a "var" map

13:28 seangrove: in t.a when I write "var" (not capitalized) I don't mean a Var. it means some kind of object that the platform uses to hold a def init, in clj it's a Var in cljs it's a map in the compiler env

13:28 EvanR: TEttinger: well, its a big nested data structure, but yeah i plan to split it up

13:28 its easier for me to read sometimes if its all expanded into one big record (with proper indentation)

13:28 TEttinger: if a nested data structure gets too big it can't be read by the JVM

13:29 the example I found this in was https://dl.dropboxusercontent.com/u/11914692/weapons-map-too-large.clj

13:29 EvanR: ok but ... its an element of a map that ends with }}]]]

13:29 after that point the other elements dont indent

13:29 TEttinger: trying to parse one huge map didn't work

13:29 EvanR: so its 5 or 6 levesl deep

13:30 i think its an inefficiency in the implementation of the clojure static auto indenter

13:30 TEttinger: IIRC, that map is only 100 elements of 72-key maps

13:31 EvanR: whats the problem? that his weapons map *literal* has too many keys?

13:31 thats ridiculous

13:32 surely runtime maps and serializations can support more

13:32 TEttinger: yeah, it works if you split it up, but not as one literal

13:32 https://dl.dropboxusercontent.com/u/11914692/weapons-map.clj works

13:32 EvanR: ;_;

13:33 kinseapo is spamming

13:33 TEttinger: yep

13:33 EvanR: anyway, i have 4 keys, but like 5 levels of nesting

14:24 dmahanta: if we have two list listA and listB i want to do this map fn listA, but fn need listB everything whats the best way to do it, is global variable the only way

14:26 Gay-champion: anyone here is a programmer unity 3d? 9àè

14:28 TEttinger: dmahanta: you can use a let binding to make a local "variable"

14:37 kungi:

14:39 Gay-champion: Who is a transexual gay here ? 9à9

14:40 kungi: Gay-champion: I don't think sexuality is of interest in this channel

14:56 amalloy: EvanR: i don't see kinseapo in this channel at all. kicked already?

15:06 sg2002: Hey guys. What's the best tagging application for clojure src? It seems that neither ctags nor etags, nor gnu global support clojure out of box...

15:06 arrdem: puredanger: is "not trivially portable to cljs" a legitimate criticism of a feature at this point in time? Kicking around the numerics patch since it's something I've done worse before.

15:13 puredanger: it's a consideration, surely. I'm not too concerned with whether it's "trivial" or not. certainly we should be considering portability for anything like that.

15:16 I haven't talked to Rich about it, no idea what his opinion would be. I could see him going either way.

15:17 EvanR: is there a way to multi-line comment, such as a section of a map literal (in which case #_ does not work)

15:18 justin_smith: #_( ... ) works

15:18 just remember to remove the parens with the #_

15:18 amalloy: EvanR: there is no multi-line comment except those that work on single sexps

15:18 EvanR: trying that

15:19 justin_smith: &{:a 0 #_(:b 1 :c 2)}

15:19 lazybot: ⇒ {:a 0}

15:19 EvanR: works

15:20 puredanger: you could put " " around the whole thing :)

15:20 EvanR: not in a map literal

15:20 puredanger: well, then #_" "

15:20 amalloy: puredanger: also no good if there are any strings inside

15:20 puredanger: you people are too smart

15:21 amalloy: the parens are nice because it only requires N well-formed sexps

15:21 EvanR: as opposed to infinite?

15:22 amalloy: EvanR: infinite??? as opposed to needing sexps that don't have string, or aren't in a map literal, or...

15:22 EvanR: nevermind

15:30 TimMc: ,[1 2 #_#_#_#_ 3 4 5 6 7] ;; EvanR

15:30 clojurebot: [1 2 7]

15:31 EvanR: hmm

15:33 TimMc: Let me just trot out one of my favorite weird syntax things...

15:34 ,(#(+ 1 2 #_ %4) :a :b :c :d)

15:34 clojurebot: 3

15:38 hyPiRion: TimMc: That's a nice find

15:38 coffeeElf: Hello All

15:38 TimMc: Someone showed it to me a year or two ago.

15:39 coffeeElf: I am new to IRC and trying to learn Clojure

15:39 Know a bit of java

15:40 Can Clojure functions have names like 'str->int' ?

15:40 justin_smith: yes

15:40 coffeeElf: So it is just a name, no speacial meaning to that arrow !!

15:40 EvanR: but not int<:real

15:40 justin_smith: ,(defn str->int [s] (Integer/parseInt s))

15:40 clojurebot: #'sandbox/str->int

15:40 justin_smith: ,(str->int "1")

15:40 clojurebot: 1

15:40 justin_smith: right

15:41 coffeeElf: thanks guys

15:41 sandbox is the name space ?

15:42 justin_smith: yes, it is clojurebot's namespace

15:42 TimMc: hyPiRion: Clearly the solution to the problem of positional args in fn literals is to keep track in a monad.

15:42 justin_smith: and #' indicates a var

15:42 hyPiRion: TimMc: exactly that

15:43 TimMc: I still don't quite understand monads but at least I know when I could be using them!

15:44 amalloy: you can tell what issues i just love bringing up, because chrome autofills "d" to dev.clojure.org/jira/browse/CLJ-865

15:44 coffeeElf: (defn str->int [str] (Integer. str))

15:44 What does that function body do exactly ?

15:45 justin_smith: it calls the Integer constructor

15:45 coffeeElf: (Integer. str) ?

15:45 justin_smith: ,(Integer. "1")

15:45 clojurebot: 1

15:45 justin_smith: classname followed by . indicates that you are calling the constructor

15:45 $google clojure java interop

15:45 lazybot: [Clojure - java_interop] http://clojure.org/java_interop

15:45 coffeeElf: cool

15:45 EvanR: ,(number "1")

15:45 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: number in this context, compiling:(NO_SOURCE_PATH:0:0)>

15:45 EvanR: ,(int "1")

15:45 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Character>

15:46 justin_smith: coffeeElf: see the above link for the official intro

15:46 (to instantiating java classes in clojure code, and using their methods)

15:46 verma: ,(Integer/parseInt "11")

15:46 clojurebot: 11

15:46 andyf: EvanR: Emacs, vim, and most or all code editors can prefix or remove comments from contiguous range of lines with a few keystrokes. Good to learn those, and avoid fancy tricks, IMO

15:47 EvanR: andyf: well, the comments have to exist before that can be removed with a single keystroke, so i used #_( .... ), though i dont know how to remove this in vim at the moment

15:48 since the inside is not a single expr

15:48 coffeeElf: Thanks Justin

15:48 justin_smith: EvanR: he's referring to "comment region" - which I am sure fireplace can do

15:48 coffeeElf: np

15:50 coffeeElf: Looks like this this chat also works as a REPL :)

15:51 (println "Hello")

15:51 ,(println "Hello")

15:51 clojurebot: Hello\n

15:53 amalloy: coffeeElf: if you're going to use him as a repl, rather than to assist in demonstrating something or asking a question, please do so in /msg

15:53 justin_smith: I hear it is possible to run a repl locally too

15:54 crash_ep: Does anyone know if there is a way to get Midje to evaluate the `msg` parameter to `fact`?

15:54 coffeeElf: Will do, was just trying to check if this really is a REPL

15:54 EvanR: is Integer/parseInt a static method

15:54 crash_ep: In my case it is a symbol that points to a string, not a string literal…

15:54 * justin_smith has been guilty of abusing the channel bots in the past.

15:54 coffeeElf: have a REPL running on my PC

15:54 Thanks guys

15:54 justin_smith: EvanR: yes it is

15:55 EvanR: ,(Integer/parseInt "abc")

15:55 amalloy: coffeeElf: it's not a very good repl, really. if you try to print long or deep lists he'll balk, and he'll forget anything you've def'd within a few minutes

15:55 clojurebot: #<NumberFormatException java.lang.NumberFormatException: For input string: "abc">

15:55 EvanR: amalloy: a time limit just makes you better, like practicing basketball with a way smaller hoop, or training in the hyperbolic time chamber

15:56 or using dynamic types for everything

15:59 poushkar: could someone look at small function please? https://gist.github.com/vitaly-pushkar/efb19a69232f4cc1ba6d

15:59 I don’t get why it’s failing

15:59 TimMc: EvanR: oh snap

16:00 poushkar: Is this a CLJS thing? What call are you making? What do you expect to have happen?

16:01 poushkar: @TimMc yes, sorry, it’s cljs. I expect it to return all values from atom if it’s called without arguments, and filtered version of first case if called with argument

16:01 justin_smith: poushkar: it looks like you are providing get-entries where your code expects (get-entries x)

16:01 poushkar: that's my best guess at least

16:03 poushkar: @justin_smith well, I am expecting it to accept both zero or one agrument

16:03 justin_smith: poushkar: that's not what I am talking aout

16:03 *about

16:03 I mean that the error is saying get-entries, the function, is not a sequence

16:04 but it would return one

16:04 EvanR: i havent used joda time, is clj-time doing very much as a wrapper?

16:04 justin_smith: so likely something is getting get-entries where you meant to give it the return value of calling get-entries

16:04 if you want to provide no args, the syntax is (get-entries)

16:05 poushkar: oh, I see, let me try

16:05 yes, that works! thank you @justin_smith

16:06 justin_smith: np. Just remember that clojure doesn't implicitly evaluate very often, you almost always need () to make evaluation happen

16:06 sorry s/evaluation/invocation/g

16:08 poushkar: yeah, spent on it like 20 minutes, gonna remember that forever now :D

16:09 EvanR: and putting extra ( ) around stuff is usually bad

16:09 justin_smith: right, unless you want an extra invocation to happen of course

16:24 mikerod: I have been messing around with emacs-live and it has some "save hook" type of function that removes all trailing whitespace in a given file when I hit save - this is then not even undo-able.

16:24 Anyone have an idea what is causing this? This actually isn't great when we don't want git to show all these white space changes in big files.

16:24 I believe (haven't tested) it is specific to clj files

16:25 I'm not sure where this falls in the emacs structure

16:25 justin_smith: mikerod: try M-x describe-variabe after-save-hook

16:25 mikerod: I know this isn't strictly clj related, but emacs-live is mostly meant for clj dev with cider and some extra configs

16:26 justin_smith: mikerod: it may also be hooking into something clojure-mode specific, but I would check after-save-hook first

16:27 CaptainLex|2: I'm having trouble with splitting a pipe-delimited string. The regex for matching a pipe doesn't even seem to work escaped

16:27 sg2002: mikerod: Search for 'delete-trailing-whitespace

16:27 CaptainLex|2: ,(clojure.string/split "Hello!|World?" #"\\|")

16:27 clojurebot: ["" "H" "e" "l" "l" ...]

16:28 EvanR: ,(split "a|b|c|d" (re-pattern "|"))

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

16:28 EvanR: ,(clojure.string/split "a|b|c|d" (re-pattern "|"))

16:28 clojurebot: ["" "a" "|" "b" "|" ...]

16:28 EvanR: double fail

16:28 justin_smith: (= (re-pattern "|") #"|")

16:29 ,(= (re-pattern "|") #"|")

16:29 clojurebot: false

16:29 justin_smith: hm

16:29 that surprises me

16:29 EvanR: object equality

16:29 justin_smith: of course

16:29 dnolen_: getting excited about adding cata-matching to core.match a la Friedman et al

16:29 justin_smith: ,(clojure.string/split "a|b|c|d" #"|")

16:29 clojurebot: ["" "a" "|" "b" "|" ...]

16:29 justin_smith: ,(clojure.string/split "a|b|c|d" #"\|")

16:29 clojurebot: ["a" "b" "c" "d"]

16:30 CaptainLex|2: Gah!

16:30 justin_smith: EvanR: was the latter what you wanted?

16:30 or CaptainLex

16:30 CaptainLex|2: The latter was what I wanted, yes

16:30 mikerod: justin_smith: sg2002 both of these were helpful. I ended up finding it i think under the `before-save-hook` actulally though

16:30 CaptainLex|2: Why was I double-escaping it?

16:30 mikerod: emacs-live has this `live-cleanup-whitespace` there

16:30 I think it is the culprit

16:30 now to find the graceful way to disable that

16:30 justin_smith: CaptainLex: #"" is special, it makes it so you can use \ instead of \\

16:30 EvanR: you were trying to match literally a backslash followed by empty string

16:31 i mean, backslash OR empty string

16:31 justin_smith: (re-pattern "\\|") would have worked too

16:31 CaptainLex|2: Well, wow, thanks guys!

16:31 That's been driving me crazy for the better part of two days at work

16:31 Not two days straight of regexes

16:31 just two days of getting frustrated and doing something else

16:32 mikerod: Looks like `(remove-hook 'before-save-hook 'live-cleanup-whitespace)` worked nice :)

16:33 justin_smith: oh, of course it would have to be before-save-hook, because otherwise it would make the change after you save...

16:34 mikerod: justin_smith: that's sort of what I thought :P

16:41 amalloy: mikerod: if you commit files with trailing whitespace you're an infidel, though

16:42 huh. i just noticed the roots of "infidel". not believed? not believing? i guess it must just be nonbeliever

16:43 mikerod: amalloy: I don't like it either

16:43 I'm competeting with Eclipse CounterClockwise formatter

16:43 it likes to put a bunch of whitespace on empty lines

16:44 to align with the lines around them

16:44 this save hook for emacs-live destroys those too

16:44 And I don't think the CounterClockwise stuff is configurable at that level, but emacs is. So I lose since I can change it in emacs to match the ccw users :P

16:45 justin_smith: the answer is to switch to ed, and then everybody needs to switch what they do to be ed compatible

16:45 mikerod: hmm

16:46 TimMc: justin_smith: I don't think anyone needs to switch. ed is the standard text editor. It can handle anything other editors produce. Ed is the standard text editor.

16:46 mikerod: I thought it has been decided that Emacs is the best editor - siting my source of http://xkcd.com/378/

16:47 justin_smith: M-butterfly is gibberish :P

16:47 amalloy: you don't have a butterfly key, justin_smith?

16:48 justin_smith: hah - and here I thought that was the windows logo

16:48 amalloy: a common mistake

16:49 the apple logo looks a bit like a butterfly too. coincidence? i think not

16:50 mi6x3m: hey Clojure, any list of leiningen templates available?

16:51 amalloy: mi6x3m: https://clojars.org/search?q=lein-template

16:51 based on the lein docs, which say "All lein templates have an artifact-id of "lein-template", and are differentiated by their group-id, which always should match the project for which they provide a template."

16:52 (from https://github.com/technomancy/leiningen/blob/stable/doc/TEMPLATES.md)

16:52 mi6x3m: yes, this sounds reasonable :)

16:57 noncom|2: how do i make uberjar consider the projects in the checkouts dir ?

16:57 looks like it just ignores them...

16:57 am i obliged to lein install them ?

16:58 arohner: huh. test.check gen/pos-int includes zero as a positive number

16:58 hiredman: :(

16:59 are you sure?

16:59 arohner: user> (gen/sample gen/pos-int)

16:59 (0 0 0 3 4 5 5 6 5 2)

16:59 TimMc: heh

16:59 hiredman: :(

16:59 arohner: the bug is pos-int is an alias for gen/nat

16:59 hiredman: https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.clj#L344-L350

17:00 TimMc: I think test.check would have foudn that with some generative testing. :-P

17:00 hiredman: neg-int will also generate 0

17:00 arohner: oh, wiki "There is no universal agreement about whether to include zero in the set of natural numbers"

17:00 hiredman: there is s-pos-int

17:00 arohner: :(

17:01 TimMc: I feel like distinct-by should be a thing.

17:01 Does this feeling mean I am forgetting about some other fn?

17:03 EvanR: arohner: probably a good idea to include zero

17:03 unless you have a reason not to

17:03 arohner: EvanR: why?

17:03 mi6x3m: anyone around using lein oneoff by any chance?

17:03 arohner: we already have gen/int, gen/nat

17:03 amalloy: TimMc: (flatland.useful.seq/groupings f (fn [a b] a) nil xs) kinda does this

17:03 mi6x3m: I keep getting FileNotFoundException when I try to execute my script

17:03 amalloy: no, i guess it doesn't

17:04 EvanR: arohner: well, practically, youd need to have another type like "Nat or zero" for most programming cases where you would use this type

17:04 TimMc: &(map first (vals (group-by even? (range 10))))

17:04 lazybot: ⇒ (0 1)

17:04 arohner: EvanR: nat includes zero

17:05 EvanR: good

17:05 i was refudiating the wiki quote above

17:05 TimMc: ...but that accumulates values that should be tossed immediately, which could be unsuitable from some purposes.

17:06 EvanR: needs more lazy

17:06 amalloy: TimMc: i've certainly written distinct-by myself. http://amalloy.hubpages.com/hub/The-evolution-of-an-idea is a blog post i wrote ages ago, with a version of distinct-by that also allows you to keep up to N items in each bucket, instead of just 1

17:09 justin_smith: github formatting is still screwed https://github.com/clojure/data.csv/blob/master/src/main/clojure/clojure/data/csv.clj#L91

17:09 TimMc: ew

17:09 amalloy: that's actually a whole different problem, isn't it?

17:10 justin_smith: yeah, may be a new one

17:10 amalloy: the recent problems have just been styling the parsed language; this looks like a problem with parsing it

17:10 justin_smith: is there a place where we report those now?

17:11 amalloy: justin_smith: just drag complaints into the file labeled Recycling Bin

17:12 justin_smith: oh I've got to get me one of those - I assume a symlink to /dev/null would work?

17:15 andyf:

17:16 ppppaul: how do you spell cognitech? i'm doing google searches and only coming up with some forensic websites

17:17 zerokarmaleft: cognitect

17:17 ppppaul: thansk

17:19 EvanR: ,(sequential? {})

17:19 clojurebot: false

18:12 seangrove: ,(let [print str] (resolve 'print))

18:12 clojurebot: #'clojure.core/print

18:12 justin_smith: resolve wouldn't ever work on let bindings would it?

18:13 arohner: ,(doc resolve)

18:13 clojurebot: "([sym] [env sym]); same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)"

18:13 arohner: ,(doc ns-resolve)

18:13 clojurebot: "([ns sym] [ns env sym]); Returns the var or Class to which a symbol will be resolved in the namespace (unless found in the environment), else nil. Note that if the symbol is fully qualified, the var/Class to which it resolves need not be present in the namespace."

18:13 amalloy: justin_smith: indeed not

18:13 seangrove: I'm not clear on why though

18:14 amalloy: seangrove: because locals aren't vars

18:14 seangrove: amalloy: Ah, ok

18:14 amalloy: and resolve looks up vars

18:15 seangrove: amalloy: Let me check a few things and I'll have a follow up :)

18:31 nicferrier: dealing with OS processes in clojure looks hard.

18:32 justin_smith: (.run (ProcessBuilder. "ls" "-l"))

18:32 or you can just use clojure.java.shell of course

18:32 but that's not as flexible

18:32 nicferrier: justin_smith: yeah. we talked yesterday. I'm using conch.

18:32 justin_smith: got it. I decided pretty quickly using ProcessBuilder / Process was easier than using conch myself

18:33 nicferrier: my current problem is that I want to start a bunch of processes and do something when one of them finishes.

18:33 you can't future it because you can't do the equivalent of alt! with futures.

18:34 it looks like I have to allocate a thread just to run each process, or at least to collect it's exit.

18:34 justin_smith: sounds like you want a collection of processes, and a loop where you check .isAlive on each process? probably paring each process with the function to call when it finishes

18:34 then sleep and loop again, of course

18:35 nicferrier: yeah. that sucks. I might as well have used java.

18:35 justin_smith: well, this part is java. clojure has nothing nice beyond the java apis - but clojure has better tools for using those apis though

18:35 nicferrier: but not in this case.

18:35 hey ho.

18:36 amalloy: clojurebot: clojure |has| nothing nice beyond the java APIs

18:36 clojurebot: 'Sea, mhuise.

18:37 justin_smith: nicferrier: what I mean by better tools is the general lispy abstractions you can use. conch makes a decent attempt but doesn't really address your use case.

18:38 nicferrier: justin_smith: I think this shows a poor future api.

18:38 I can't see how the poor future api is compensated by the core.async stuff.

18:38 probably it is more than compensated normally, just the case of external processes is weak.

18:38 it is a bit odd I guess.

18:39 sorry, I'm just moaning really I guess.

18:39 justin_smith: nicferrier: I have the very early stages of a "process graph" lib that would create the equivalent of shell pipelines, but made out of a clojure datastructure so that individual parts can be reconnected / teed off / restarted as needed. It's really not near usable yet though.

18:40 nicferrier: sounds cool.

18:41 justin_smith: but I resigned myself that it needs a nanny thread that moves the data between the processes. Or even if it goes into parallel paths it would need one nanny per branch.

18:41 nicferrier: one thread per process?

18:41 justin_smith: but that's better than one extra thread per process at least

18:41 no

18:41 one per parallel path

18:41 remember I mentioned tees :)

18:41 nicferrier: not sure how you're going to tell when they finish.

18:41 justin_smith: so if it is linear, you only need one nanny

18:42 nicferrier: (.isAlive proc)

18:42 the api is really small file:///home/justin/java/doc/api/index.html

18:42 err, sorry, bad link

18:42 nicferrier: it's not like waiting on the exit status though.

18:42 justin_smith: https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html

18:42 nicferrier: no, this is for processes I expect to stay alive for a long time

18:43 nicferrier: isalive isn't in j7

18:44 justin_smith: wow, that is surprising, and also sad

18:44 nicferrier: it's a j8 thing?

18:44 justin_smith: yeah, that leaves you in a tough place if you don't want a nanny thread per process

18:44 I guess so

18:44 amalloy: is justin_smith running java 9 or something? i remember another suggestion recently for something that doesn't exist yet

18:45 justin_smith: haha - .isAlive does exist in java 8

18:45 nicferrier: guess your api won't work then.

18:45 :-)

18:45 amalloy: i'm on java 34 now

18:45 nicferrier: christ. I hope it's dead by then.

18:47 I guess I just need a thread per process.

18:47 justin_smith: what about checking if the output stream is closed? that's a hack I guess

18:48 nicferrier: yes. definitely.

18:48 unix is hard. doing anything but exit status makes it harder.

18:49 I wouldn't trust any polling particularly.

18:49 justin_smith: what does .exitValue return for a running Process?

18:49 nicferrier: it doesn't.

18:49 it excepts.

18:50 I should have said "Maybe" that would have been a nice haskell joke.

18:50 justin_smith: putting a try/catch on that would be yet another disappointing hack of a way to do it

18:51 nicferrier: don't see that's any better than (and @one @two @three) ?

18:51 justin_smith: less threads used. But yeah, just use futures unless you have hundreds of process I guess.

18:52 nicferrier: why less threads?

18:52 oic. right.

18:53 justin_smith: you could launch the process inside something that returns you the PID, then you could use a shell call to check if that PID is live

18:54 nicferrier: no. that would be terrible.

18:54 you've got the process handle from launching it! so wasteful not to use it.

18:54 justin_smith: but the information actually needed is obfuscated

18:54 ffwacom: does future pull from a thread pool or does it always create a new thread?

18:54 nicferrier: possibly using a thread to poll the exitValue and send a message to a channel.

18:54 sigh.

18:55 justin_smith: ffwacom: thread pool

18:55 nicferrier: ^^

18:55 but it's so annoying you can't resolve on a bunch of futures.

18:57 when a future is "promised" it's mapped to a thread, right?

18:57 the thread is taken all the time the future is extant.

18:58 justin_smith: yeah, futures don't jump between threads.

18:59 and they don't let go of them until fully completed

18:59 nicferrier: s'what I thought.

19:01 they complete though without specfically derefing them. right?

19:02 so my future could be (future (go (>! exit-channel (.waitFor proc))))

19:02 and I don't then have to block on all of them

19:02 amalloy: future (go ...) looks like a bad plan

19:03 nicferrier: ok. (future (>!! exit-channel (.waitFor proc)))

19:03 amalloy: yeah, i think you have to do like that

19:03 or even (thread (>! ...)) is probably fine, right?

19:03 nicferrier: don't think it matters.

19:04 idk. can't find the doc for fn thread :-)

19:04 amalloy: thread is supposed to be like go, except that it uses a thread from the future pool instead of the core.async pool

19:04 something like that anyway

19:05 nicferrier: future seems fine for what I did?

19:05 devn: im late to the party: could you use agents + add-watch?

19:06 nicferrier: possibly. idk enough about agents.

19:06 hiredman: https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async.clj#L392 not the future thread pool

19:06 nicferrier: central problem - how to wait on the process.

19:06 hiredman: (but pretty close)

19:07 nicferrier: agents sound like actors.

19:07 amalloy: nicferrier: they're not. rich even has a blog post or something, about how the main thing they have in common is names of professions that start with A

19:07 nicferrier: ha.

19:09 anyway. food for thought. thanks everyone!

19:09 it's a jolly interesting exercise. I have this already in scala and it's interesting to see what the strengths/weaknesses are.

19:09 Morgawr: is it possible to do nested structural matching with :keys ?

19:09 like if I have {:hello {:world 3}}

19:10 and I want to get the symbol world in a let

19:10 sg2002: Is there a reason why ob-clojure in the stable org is so obsolete and you have to install dev version of org to use it?

19:10 Morgawr: I have to do [{:keys [world]} (:hello data)]

19:10 can I move the :hello to the other side?

19:11 amalloy: Morgawr: you don't use :keys for that. are you aware that :keys is shorthand for a more flexible map destructuring?

19:11 hiredman: the people who make tools don't value stability of said tools as much as the people who use them

19:11 Morgawr: amalloy: what do you mean?

19:12 amalloy: Morgawr: (let [{:keys [x]} m] x) just expands to (let [{x :x} m] x)

19:13 Morgawr: so I can do (let [{{world :world} :hello} x] ...) ?

19:13 (where x is the map)

19:15 devn: ,(let [{{world :world} :hello} {:hello {:world 3}}] world)

19:15 clojurebot: 3

19:15 devn: Morgawr: yes. ;)

19:15 Morgawr: nice

19:15 is it the best way to do it?

19:15 if I want to abstract multiple keywords as symbols from maps within maps

19:15 or is there a more idiomatic way?

19:16 devn: ,(get-in {:hello {:world 3}} [:hello :world])

19:16 clojurebot: 3

19:16 Morgawr: yes but that doesn't look elegant in a let binding

19:16 devn: ,(get-in {:hello {:world [1 2 3]}} [:hello :world 1])

19:16 clojurebot: 2

19:16 devn: your choice, just sayin...

19:16 Morgawr: and I might want to get multiple symbols

19:16 like normal :keys destructuring but for inner maps :)

19:17 but yeah thanks for the examples

19:17 I love programming in clojure, it's all reasoning about data transformation

19:17 I've been using it for 2 years and my thought process is so different from most other languages I use every day, I start from two structures, the input and output I want, then I work twards turning the input into the output

19:17 I've never really done that before, it's cool

19:18 devn: Morgawr: it's kind of like this: https://www.youtube.com/watch?v=9CS7j5I6aOc

19:18 Morgawr: ahah yes :P

19:58 akkad: Morgawr: yeah it's a nice group compared to CL :P

20:46 hydo: Is there any way to change the class loader aside from loading from java or patching the source? I'm sure this hasn't changed, but I thought it was worth asking.

20:46 TEttinger: hydo, ask rritoch when he gets back, he's been working with classloader related things for OSGi for a while

20:46 hydo: I'm runing a (one character) change to the 1.7 source and I'm runing into weird issues with (instance?)

20:47 which probably means I should have grabbed the 1.6.x source instead. duh.

20:47 TEttinger: what's the one character change?

20:48 hydo: Flipping T to F in RT.java line 202 or thereabouts.

20:48 TEttinger: ah. what behavior does it change?

20:48 amalloy: defaults *use-context-classloader* to false, apparently

20:49 that sounds like a really scary switch to be flipping

20:49 hydo: *use-context-classloader* to False. Changes the default classloader, to... something. I know far too little about java's guts.

20:49 TEttinger: ah, https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L205

20:50 hydo: amalloy: I read a few threads and articles about others doing it before I did it. :)

20:50 research is best search

20:50 TEttinger: why the ops, amalloy?

20:50 hydo: The reason for it is that I'm loading clojure in a plugin to another huge java application.

20:51 amalloy: TEttinger: had someone to kick

20:51 the usual PM spam

20:51 hydo: TEttinger: Thanks! I'll watch for 'em.

20:53 kenrestivo: i'm going to create github project called solo hoy. not sure what it'll do, but i got the name picked out

20:54 TEttinger: hydo: he also forked clojure, you can see some of his code dealing with classloader-like stuff here https://github.com/rritoch/clojure/commit/0f4804bbf584049fd85ffa872f10522cc41eff9a

20:54 Morgawr: is there an equivalent to update-in but for singular key?

20:54 like assoc -> assoc-in

20:54 ???? -> update-in

20:54 TEttinger: Morgawr: update should be in 1.7

20:54 amalloy: kenrestivo: you might want to check whether that's offensive or obscene first

20:54 Morgawr: TEttinger: awesome!

20:54 TEttinger: amalloy: only today

20:54 hoy is now, solo is only

20:54 Morgawr: is there an estimated release date for clojure 1.7?

20:55 amalloy: TEttinger: i actually hadn't even been certain it was spanish, because it's always "hooy", rather than "hoy"

20:56 kenrestivo: heah it means "only today". i take it to mean "HURRY ACT NOW!" or some such spammy thing, given the context

20:56 or, given the spelling, "hurry act noooooooow!"

20:56 amalloy: yeah, apparently so

21:03 arrdem: oh right amalloy has ops now

21:03 amalloy: arrdem: indeed. tread lightly, lest you feel the back of my hand

21:04 * arrdem buttons top button, reaches for tie

21:27 andyf: Morgawr: No estimated release date for Clojure 1.7 that I have heard. Wouldn't be surprised if it were in the 2-5 months from now range.

21:28 You can use 1.7.0-alpha4 release if you like

21:28 hydo: anything amazing and awesome coming in 1.7?

21:28 arrdem: Transducers, feature expressions

21:28 hydo: I mean aside from *sparkle*a new release*sparkle*

21:28 oh yea, I need to watch that video.

21:29 arrdem: there were noises about lean clojure or profiles, but those noises seem headed in the direction of 1.8

21:29 Morgawr: andyf: alright, thanks :) I'll give a look at it but not using it yet for "real" work

21:35 justin_smith: nicferrier: hey! when you use ProcessBuilder, it should be returning a UnixProcess which has nice methods that Process does not

21:35 $javadoc java.lang.UnixProcess

21:46 arrdem: justin_smith: "nice methods" (.nice p)

21:47 justin_smith: hah

21:56 wildnux: hi

21:56 ,(map #(repeat 2 %) [1 2])

21:56 clojurebot: ((1 1) (2 2))

21:57 wildnux: ^^ that changed from my [1 2] (vector) to sequence/list

21:57 how can i preserve the type of collection when we use functions like this

21:58 how can i make it such that it gives me [[1 1] [2 2]]

22:00 arrdem: wildnux: is there a reason that you care about concrete type?

22:00 wildnux: arrdem: i am going though 4clojure

22:00 arrdem: wildnux: also why would you expect that behavior from those two functions which are documented to return seqs

22:00 wildnux: ah. oh. my b.

22:00 wildnux: arrdem: i want to use the same function which can return same type

22:01 arrdem: wildnux: ##(= [:a :b] (quote (:a :b)))

22:01 lazybot: ⇒ true

22:01 arrdem: ##(= [[1 1] [2 2]] '((1 1) (2 2)))

22:01 lazybot: ⇒ true

22:02 amalloy: wildnux: you mostly should not worry about preserving the types of your collections

22:02 wildnux: ,(flatten (map #(repeat 2 %) '([1 2] [3 4]))

22:02 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:02 amalloy: they will tend to be lazy seqs most of the time, and that will be fine

22:03 wildnux: ,(flatten (map #(repeat 2 %) '([1 2] [3 4])))

22:03 clojurebot: (1 2 1 2 3 ...)

22:07 wildnux: arrdem: found it ;)

22:07 ,(mapcat #(repeat 2 % ) [[1 2] [3 4]]

22:07 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

22:07 wildnux: ,(mapcat #(repeat 2 % ) [[1 2] [3 4]])

22:07 clojurebot: ([1 2] [1 2] [3 4] [3 4])

22:07 cursivecode: yogothosjaway: ping

22:11 arrdem: wildnux: sweet!

22:15 alright... core.logic patching time

22:21 hydo: transducers are interesting.

22:23 I'm at 30:45 of the strangeloop video and he hasn't mentioned monads yet, except for the image of a burrito.

22:31 sm0ke: cheshire should have a json to xml converter

22:37 arrdem: shouldn't be too hard to hack one up...

22:40 sm0ke: hurm jackson seems to have some support builtin

22:41 https://github.com/FasterXML/jackson-dataformat-xml

22:45 justin_smith: sm0ke: and jackson is what cheshire uses iirc

22:45 sm0ke: yes right

22:46 i am thinking of forking cheshire to hack xml support

22:47 i think the support for xml would make sense in cheshire i.e. to from json

23:03 seajames: Is there a way to destruct a vector and map? I'm trying this but it isn't working (let [[[foo bar] {:keys [other thing]}] ["Hello" "World"] {:other "Good" :thing "bye"}] (println foo))

23:03 crack_user: hello guys

23:05 justin_smith: seajames: ##(let [[foo bar {:keys [other thing]}] ["hello" "world" {:other "good" :thing "bye"}]] foo)

23:05 lazybot: ⇒ "hello"

23:06 justin_smith: seajames: your nesting was weird (and not even valid for a let block)

23:06 crack_user: some one knows a sql lib which a can write queries in more clojure way?

23:06 like (take 2 users) or (filter #(> :age 21) users)

23:07 arrdem: so I'm parsing XML by doing what amounts to a recursive reduce over the nodes in the tree carying forwards a state value.

23:07 ideas for how to implement progress tracking on the reduction?

23:07 seajames: justin_smith: thanks, first time trying this

23:08 arrdem: I figure it's probably easty to count leaf nodes and track the number of leaf nodes processed, but I'm not a great fan of doing IO from this otherwise pure parser.

23:08 justin_smith: arrdem: reductions and carry some updated progress state alongside the accumulator?

23:08 sm0ke: arrdem: isnt counting leaf node as expensive as paring it?

23:10 arrdem: sm0ke: shouldn't be.. I'm doing some relatively heavy lifting in the "parser". really I'm using data.xml to parse, then walking it with a slow importer that I refer to as a "parser".

23:10 * arrdem absuing terminology

23:10 arrdem: justin_smith: yeah.. that could work.

23:11 sm0ke: crack_user: strange idea

23:12 a nice one though

23:12 justin_smith: sm0ke: crack_user: there's datalog (including datomic), but it doesn't look like normal syntax

23:13 crack_user: justin_smith: I see datalog

23:13 sm0ke: crack_user: justin_smith i'd say korma would be closest to it

23:14 crack_user: I like the ideia to treat my database as clojure data structure

23:14 in some cases it can be useful

23:15 arrdem: bytemyapp and cbp's revise mongodb wrapper has an interesting query structure

23:15 it gets close to "normal" clojure code

23:15 s/mongodb/rethinkdb/

23:16 sm0ke: crack_user: what you want can be done simply via java.jdbc over the query-seq

23:16 but what one would ideally want is to to push the filters etc to db

23:17 e.g. (take 2 user) should translate to select * from user limit 2

23:18 crack_user: sm0ke: something like it

23:18 sm0ke: i am not sure how that can be implemented

23:18 warz: maybe something line LINQ-to-SQL can be an inspiration?

23:19 sm0ke: obviosly not everything will work, eg. (filter my-fancy-func user)

23:19 justin_smith: well, clojure.java.jdbc returns a lazy query seq over the transaction, so if you take 2 from the seq it gives you, only that much is grabbed from the db.

23:19 sm0ke: so i would say it would be very very hard to implement

23:19 justin_smith: what about filters?

23:19 justin_smith: sm0ke: that would have to happen on the clojure side unless you are willing to translate

23:20 sm0ke: i was just giving a small example

23:20 justin_smith: sure

23:20 just saying, lazy results and take N is doable now

23:20 sm0ke: justin_smith: alway finding holes in my comments :D

23:20 * arrdem ponders a transducer to query compiler

23:21 crack_user: justin_smith: yes, lazy query resolve the take example

23:23 hydo: Is there a known thing with (instance? thing Class) saying thing can't be cast to a java.lang.Class? I traced my code back just to make sure, but I don't see what I'm doing wrong. I got to where I opted for (= (class thing) (resolve (symbol "class.path"))) but that's just silly.

23:24 Though, while silly, it does work correctly... so it has that going for it.

23:24 justin_smith: hydo: you have the args in the wrong order I think

23:25 &(instance java.lang.String "hello")

23:25 lazybot: java.lang.RuntimeException: Unable to resolve symbol: instance in this context

23:25 sm0ke: ,(doc instance?)

23:25 clojurebot: "([c x]); Evaluates x and tests if it is an instance of the class c. Returns true or false"

23:25 hydo: ! no way. looking..

23:25 sm0ke: yep

23:25 justin_smith: &(instance? java.lang.String "hello")

23:25 lazybot: ⇒ true

23:25 hydo: oh my god.

23:25 I'm sorry :( I really try to ask intelligent questions. I'm just dumb.

23:25 heh

23:25 justin_smith: (instance? Newb hydo) => true but that's OK

23:26 hydo: totally

23:26 justin_smith: I make dumb mistakes all the time, and I don't even have an excuse

23:26 hydo: I make dumb mistakes and then tell everyone on the internet about them. hehe. but I do eventually learn, so I guess that's good.

23:27 like "Double check your assumptions before asking irc." Just learned that one today!

23:32 arrdem: $grim clojure.core/instance?

23:32 lazybot: http://grimoire.arrdem.com/1.6.0/clojure.core/instance_QMARK

23:32 munderwo: Hey all. I’ve got some interop code in clojurescript that has three levels of callbacks. I wrote some horrible core.async code to get it kinda working, but Im sure there is a better way to do it. this is what I have so far

23:32 https://www.refheap.com/94712

23:32 arrdem: justin_smith: I owe you a patch to make that conj.io...

23:33 munderwo: does anybody have any suggestions on how to make it better?

23:34 rritoch: In refrence to hydo's issue, I really need to get in the habbit of using the doc function instead of constantly googling to double-check argument order. clojure.string/split is usually the one I use backwards so I always need to double-check it. Some habbits are hard to break.

23:34 sm0ke: mumrah: get-commit makes no sense, as `c` is local

23:35 opps sorry ^ munderwo

23:35 unles (go..) returns a channel?

23:36 munderwo: sm0ke: yeah, when I said this was horrible it really is.. What the code is doing is passing a chan (is his case c) through the callbacks and then blocking until the last callback puts something on that chan. and then returns the output of that into blob.

23:37 im wondering if I can put this all in a go block with a let in it for each step?

23:40 sm0ke: munderwo: i would say its too much overhead to use a go block for every meta you are trying to fetch

23:41 it does not look very cpu intensive anyways

23:41 munderwo: ahh because I would need a seperate one for each?

23:42 Its not cpu intensive. Its just node.js so everything is async.

23:42 sm0ke: yea well there is a (go..) in every method

23:42 munderwo: have you dealt with callbacks by using core.async before?

23:43 sm0ke: well if its already asynchronus you done need to put another layer of asynchrony over it?

23:44 munderwo: core.async is not really about callbacks

23:44 its more like queues consumers and producers id say

23:45 munderwo: right, but I’ve seen that you can sometimes convert very call back intensive code into core.async and make it more readable.

23:45 not that im having much luck with the last part

23:45 :)

23:46 crack_user: I think I build a very limited scoped lib of this ideia

23:46 in the worst case it will be a complete waste of time

23:58 kenrestivo: is it weird that i have a preference for using futures for core.async loops instead of async/thread or async/go , and using future-cancel to stop them instead of using a kill channel?

23:58 i mean, is that bad?

Logging service provided by n01se.net