#clojure log - Aug 21 2015

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

3:02 Olajyd: Hi, TEttinger

3:02 Hi, all

3:03 TEttinger: hey Olajyd

3:03 how did the data parsing stuff work out yesterday?

3:03 *date not data

3:05 Olajyd: Hi, TEttinger :)

3:06 TEttinger: connection troubles?

3:06 Olajyd: sorry I got disconnected

3:06 yup

3:06 TEttinger: yeah, did the date parsing stuff work after the channel had the 3 people jumping in and out with suggestions? :D

3:07 Olajyd: I tried solving the datetime problem but somehow I couldnt resolve it

3:07 TEttinger: hm

3:07 did you encounter any errors that could be, say, posted on refheap?

3:08 Olajyd: the date parsing did work but had issues with number of days that is a non-integer

3:08 for example where the number of days is 0.5

3:10 TEttinger: right, so you needed also to parse decimal days?

3:10 this is where things get interesting

3:11 oddcully: Olajyd: have you tried the suggestions to work with hours or milliseconds?

3:12 Olajyd: oddcully, no :)

3:13 TEttinger: ,(let [date-str "2015-08-21"] (map #(Double/parseDouble %) (clojure.string/split date-str #"-")))

3:13 clojurebot: (2015.0 8.0 21.0)

3:14 Olajyd: I tried converting the non-integer days to hours or minutes and adding it to the given date string, dont know if that was a good approach though :)

3:15 TEttinger: ,(let [date-str "2015-08-21" part-of-day-str "0-0-0.4" parse-date (fn [s] (map #(Double/parseDouble %) (clojure.string/split s #"-")))] (map + (parse-date date-str) (parse-date part-of-day-str)))

3:15 clojurebot: (2015.0 8.0 21.4)

3:22 Olajyd: TEttinger, I have a problem for today :)

3:23 TEttinger: ,(def date-format (java.text.SimpleDateFormat. "yyyy-MM-dd-HH:mm:ss"))

3:23 clojurebot: #'sandbox/date-format

3:23 TEttinger: sure, go right ahead

3:23 Olajyd: TEttinger, problem is: Right-pads the associated string with the Pad Character until it contains Length total characters. If the column value is already longer than Length, then it is truncated to Length

3:24 What is the way to go with this,

3:25 TEttinger: this one is another thing that format is good for. and format is, if you recall, sorta a voodoo magic function... it has a description for this type of thing

3:25 but there happens to be another way hang on

3:28 Olajyd: really, lol I’m going to hang on to that voodoo function :)

3:29 TEttinger: ,(let [Length 20 Pad \- Name "TEttinger"] (apply str (map #(or (nth Name %1) %2) (range) (repeat Length Pad))))

3:29 clojurebot: #error {\n :cause "String index out of range: 9"\n :via\n [{:type java.lang.StringIndexOutOfBoundsException\n :message "String index out of range: 9"\n :at [java.lang.String charAt "String.java" 658]}]\n :trace\n [[java.lang.String charAt "String.java" 658]\n [clojure.lang.RT nthFrom "RT.java" 854]\n [clojure.lang.RT nth "RT.java" 847]\n [sandbox$eval27$fn__28 invoke "NO_SOURCE_FILE" 0]\n ...

3:29 TEttinger: oh right

3:29 ,(let [Length 20 Pad \- Name (vec "TEttinger")] (apply str (map #(or (get Name %1) %2) (range) (repeat Length Pad))))

3:29 clojurebot: "TEttinger-----------"

3:29 TEttinger: easier way actually

3:29 ,(let [Length 20 Pad \- Name (vec "TEttinger")] (apply str (map #(get Name %1 %2) (range) (repeat Length Pad))))

3:30 clojurebot: "TEttinger-----------"

3:30 TEttinger: ,(let [Length 20 Pad \- Name (vec "TEttingerLivesInCaliforniaSoItIsGettingLate")] (apply str (map #(get Name %1 %2) (range) (repeat Length Pad))))

3:30 clojurebot: "TEttingerLivesInCali"

3:30 TEttinger: there's some really neat clojure language stuff being used here

3:31 ,(doc nth)

3:31 clojurebot: "([coll index] [coll index not-found]); Returns the value at the index. get returns nil if index out of bounds, nth throws an exception unless not-found is supplied. nth also works for strings, Java arrays, regex Matchers and Lists, and, in O(n) time, for sequences."

3:31 Olajyd: wow

3:31 TEttinger: oh it can be even simpler

3:31 ,(let [Length 20 Pad \- Name "TEttingerLivesInCaliforniaSoItIsGettingLate"] (apply str (map #(nth Name %1 %2) (range) (repeat Length Pad))))

3:31 clojurebot: "TEttingerLivesInCali"

3:32 Olajyd: uhhmm nice

3:32 TEttinger: ok so quick going-over: Pad doesn't need to be a char but should be, probably.

3:32 Olajyd: ok

3:33 TEttinger: what it does is it maps over two collections, pair of elements by pair. one is an infinite range from 0, 1, 2... up to however many elements actually get used, which is limited by the other collection here.

3:34 (repeat Length Pad) will create a sequence of repeated pad chars here, exactly Length long

3:34 Olajyd: oh ok

3:34 TEttinger: the function we use on this uses the anonymous fn syntax, #() where %1 is an element from the first collection and %2 is an element from the second

3:35 it gets the nth char from Name at index given by an element from (range), so the first will be (nth Name 0 \-) when you resolve what the args are

3:35 the next is (nth Name 1 \-)

3:36 it will stop if it hits the end of either collection, doing the truncate because the repeated padding chars are exactly Length long

3:37 if the index from (range) is past the end of Name, it uses the not-found argument to nth in that doc I pulled up for nth

3:37 Olajyd: ok

3:37 TEttinger: and that's really all there is to it, other than needing to (apply str ...) on it to go from a sequence of chars to a string

3:38 Olajyd: so how about the voodoo function you suggested earlier

3:39 TEttinger, in what areas can we apply the formatting

3:40 TEttinger: that would be format. it I don't think can do the truncate part very easily

3:40 but it has built-in support for padding with certain characters

3:41 Olajyd: is it available in clojuredocs?

3:42 TEttinger: uh, sorta. clojuredocs refers to this: https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html

3:42 which is rather large.

3:42 Olajyd: oh nice

3:43 TEttinger: good things about format include:

3:43 ,(format "%04x" (int \Z))

3:44 clojurebot: "005a"

3:44 TEttinger: an easy way to get zero-padded numbers in decimal or hex

3:44 a lot of ways to format, though not parse, dates

3:45 Empperi: it is it's own mini language

3:45 a bit like destructuring in clojure

3:45 TEttinger: format can't handle arbitrary padding chars or truncation even with all that

3:45 yeah, or regular expressions

3:45 Empperi: yeah

3:46 TEttinger: we seem to be hitting a lot of those in these first few days with clojure :)

3:46 Empperi: and most of that stuff is not limited only to java/jvm

3:46 TEttinger: yep!

3:46 Empperi: the whole formatting syntax comes from C I think

3:47 TEttinger: I believe you're right unless C got it from somewhere else too

3:47 Empperi: and it's been adopted to whole plethora of languages

3:48 one of those strange looking mini languages which are actually worth learning since it'll carry on with you to the next language you're going to learn (most likely at least)

3:48 TEttinger: cl-format in clojure.pprint is a pretty crazy reimplementation of one of the most complex mini-languages in Common Lisp

3:48 http://clojuredocs.org/clojure.pprint/cl-format

3:53 Olajyd: TEttinger, thanks for making out time today, I hope to catch up with you tomorrow :)

3:53 TEttinger: no problem! glad to help

3:53 Olajyd: Thanks to y’all that contributed too

3:53 luxbock: (inc TEttinger)

3:54 TEttinger: lazybot is dead. long live lazybot

3:54 Olajyd: TEttinger, quick advice on how I can be like you :D

3:54 TEttinger: keep making little test projects and things in clojure

3:54 lots of little stuff in different areas

3:55 amalloy: TEttinger: i bet you never thought anyone would thank you for making out time

3:56 TEttinger: I'm happy my time is well-spent

3:56 amalloy: it's a joke, see. "taking time out" would be the usual idiom: "making-out time" sounds like a totally different thing

5:46 lazyseq: hi, I'm stuck with a java interop issue that I do not understand

5:46 I use gen-class to generate a class within a particular package to access its package private classes

5:47 however, I get the following exception java.lang.IllegalArgumentException: Can't call public method of non-public class

5:47 if I use an intermediate java class, that is not generated, this isn't an issue

5:48 the java class, part of the particular package, can access the public method of the non-public class with any issue

5:49 this drives me nuts, because I have a dependency between clj and java files that I cannot solve in leiningen because I do not know how to compile a single java file in the prep-tasks

5:51 that is, I have clj that depend on a java implemented class, and a different java implemented class that depends on a class generated with gen-class

6:38 Manaphy91: Hi, I've an atom useful to put items inside and a pmap with a procedure that try to add element to the aforementioned atom... The strange thing is that this procedure isn't deterministic and it seems to suffer sometimes of race condition.... (info Clojure version 1.6)

6:45 luxbock: say I have a processing pipeline that I'm implementing as a transducer, where I'm using an anonymous function as the reducing function

6:46 if my non-transducing version looks like (->> data (map foo) (filter bar?) ... (reduce post-processing {}))

6:47 with transducers it just occured to me that I can do the post-processing in the single-arity body of my reducing function

6:48 but I'm wondering if this is bad for readability, or if there are any other issues involved

6:49 because previously I had thought of the single-arity of the reducing function as a way to clean up state

7:24 drwin: @luxbock if post-processing is another transformation step which has nothing to do with transducing process (e.g. underlying data structure "data" in your case), you should do it as a transducer, this will allow your composed transducer (map filter post-process) to be composed with other transducers

7:26 luxbock: drwin: it's basically the difference between doing the post-processing in the single arity body of my reducing function, or wrapping the result of calling transduce in another function-call

7:27 I think I should just do the latter, it seems much clearer that way

7:28 drwin: luxbock: yes, the difference is subtle, just decide if post-processing is part of the process doing transduction (given transducers composite) or it is transducer on its own, which can be reused in other transduction processes

7:29 for example, if you decided to use channels instead of 'data, would post-process still make sense in that context?

7:32 luxbock: just to be clear, if the signature of transducer is (transduce xform f init coll), I'm talking about `f` and not `xform` here

7:34 drwin: well, f is transducing function, xform is transducer, you can put your post-processing in single-arity version of f, or have composed it as last transducer in xform, so you have to be talking about both, if I understand it well

7:37 your xform can look like this (comp map-xform filter-xform post-process-xform) or just (comp map-xform filter-xform) and do the post-processing in f

7:39 luxbock: post-process-xform would see items from coll one at a time, whereas I need to do things with the end result of the whole xform

7:40 so I think your example wouldn't work for my use case

7:42 like a silly example would be (transduce (filter pos?) (map (inc)) conj-and-calculate-avg)

7:42 which I know looks a bit silly, so I think (calculate-avg (transduce (filter pos?) (map (inc)) conj)) is the way to go

7:43 drwin: wait, I'm going to read the docs, I think xforms can do reduction and return single value if they want, mapcat can be xform

7:43 luxbock: hmm, yeah it's entirely possible I'm wrong, I'm still trying to wrap my head around these things :)

7:50 did you mean `reduced` instead of `reductions`?

7:51 drwin: luxbock: where exactly? :)

7:51 luxbock: err, the last thing you wrote, though I think you definitely didn't

7:51 drwin: luxbock: xforms can have also completion single-arity call, so post-process-xform could be implemented as stateful transducer, which collects all items and does reduction in its completion (flush), but I agree that would be a bit strange, because then the stream of values would have just one value

7:53 luxbock: hmm yeah that does sound right

7:54 drwin: luxbock: I wrote "I think xforms can do reduction and return single value if they want", that still makes sense to me, xform can decide to eat all items and do reduction to them and return single value to be further processed in transduction process

7:56 luxbock: I'm re-writing some old code to use transducers and re-factoring out some things at the same time, so doing both while trying to understand what the best way to use them is is taking its toll on me :)

7:57 but this is a pretty good way to get comfortable with them

7:58 drwin: luxbock: I'm also pretty new to transducers, I rewrote re-frame to use them

7:58 luxbock: think about partition-all https://clojuredocs.org/clojure.core/partition-all, it can give you stateful transducer

7:59 luxbock: your extreme post-processing-xform could work similar way, but collect all items in the stream

8:00 luxbock: but it is not usual, doing reduction in f is more natural

8:00 I think

8:01 luxbock: I hadn't even seen `unreduced` before

8:01 yeah thanks for the pointers, I need some food in my stomach before I continue this task

8:02 drwin: ok, enjoy your meal

8:09 zxc: hello, I'm learning clojure and love every aspect of it, but I'm worrying about performance, since everyone says clojure is slow. do I have reasons to worry?

8:10 oddcully: why do you believe what others say, when you can benchmark your usecase for yourself?

8:11 * wasamasa wonders who this enigmatic "everyone" is

8:11 zxc_: wasamasa: various blog posts and stuff

8:11 wasamasa: aha

8:11 got one to link to?

8:12 justin_smith: zxc_: slow to start up - yes. Slow at runtime - compared to what?

8:12 zxc_: wasamasa: first from google http://martinsprogrammingblog.blogspot.de/2012/02/why-is-clojure-so-slow.html

8:13 justin_smith: hmm, go?

8:13 wasamasa: a core2duo macbook?

8:14 zxc_: wasamasa: so I need a multicore monster to really feel it?

8:14 wasamasa: zxc_: keep in mind that python for example is 33x as slow as C

8:14 zxc_: and java around 2x as slow

8:14 zxc_: wasamasa: I know, python is sluggish, so is ruby

8:15 wasamasa: but I don't know about real-world clojure

8:15 justin_smith: zxc_: in the real world, most of us are not using clojure for things that have runtimes measured in seconds

8:15 zxc_: I wrote programs in clojure that run for months or years, 3 seconds startup time is nothing on that scale

8:15 zxc_: justin_smith: I mean - is speed problematic? or not at all?

8:16 justin_smith: zxc_: we have one graph algorithm that we wrote a 15 line java method for, because immutable data structures were slowing it down

8:16 zxc_: justin_smith: and what are these programs, if I can ask?

8:16 justin_smith: out of a ~3k line of code clojure codebase

8:17 zxc_: servers / backend processing for a webapp that does social analytics

8:17 zxc_: justin_smith: so most of the time it's good? that's what I came for

8:17 justin_smith: zxc_: in our experience, yeah

8:17 zxc_: justin_smith: okay, thanks

8:17 wasamasa: most of the time it doesn't matter

8:17 unless you're of course doing number crunching or who knows what

8:18 justin_smith: zxc_: but this is why I asked "compared to what" - if you were doing high frequency trading or video processing I would likely tell you to look for some other language (something faster than go as well :))

8:18 zxc_: bu-ut I'm not tied to web, right? since almost everything that was done with clojure was a web app or server stuff or something

8:18 justin_smith: zxc_: it's a niche that clojure is very good at

8:18 zxc_: justin_smith: nah, not really

8:19 justin_smith: zxc_: I would not personally (and do not in practice) use clojure for things that run for a few seconds at a time

8:19 zxc_: justin_smith: what about desktop apps?

8:19 justin_smith: zxc_: I don't have much experience with it, but we do have bindings to swing and javafx

8:19 zxc_: justin_smith: 'kay, thank you

8:19 justin_smith: I played with seesaw a little, but not enough to make anything substantial

8:20 (seesaw is a swing wrapper for clojure)

8:20 TEttinger2 did some stuff with seesaw I think? or was that gui stuff all with CLR?

8:21 zxc_: justin_smith: by the way, what language faster than go you were talking about? c?

8:21 wasamasa: seesaw is swing, so no clr there :P

8:21 justin_smith: zxc_: ocaml, haskell, java, c, c++, c#, f# there are a lot of options

8:21 wasamasa: what I remember is his screenshots, what I forget is how he made them

8:22 zxc_: but for me none of those are as nice to work with as clojure

8:22 wasamasa: if you're on clr, winforms works with mono or natively on windows

8:22 alternatively, gtk#

8:22 justin_smith: I wish more people were using clojure-clr

8:22 zxc_: justin_smith: hate every language from this list, kinda like haskell

8:22 justin_smith: it's the neglected cousin

8:22 zxc_: justin_smith: but I thought haskell was slower than go

8:22 * wasamasa is currently writing vanilla C#

8:23 wasamasa: once I've got something substantial going, I'll turn it into clojure for clojure-clr

8:26 justin_smith: zxc_: regarding speed, there's some screenshots from the benchmarks game here https://lispmachine.wordpress.com/tag/haskell-vs-google-go/ showing that typically go is slower than c++, c, ats, ocaml, sbcl, and ghc (haskell)

8:26 it was almost a close match with sbcl, but not with the others really

8:26 zxc_: justin_smith: from 2012

8:27 justin_smith: fair enough

8:27 zxc_: justin_smith: look now http://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=go&lang2=ghc

8:27 justin_smith: still slower than c in those benchmarks, but a lot better

8:28 justin_smith: zxc_: interesting, looks like they massively improved their benchmark code (or go itself) in the meantime

8:29 zxc_: justin_smith: yeah, go is a new language, a lot of new improvenments are in 1.5 now

8:29 justin_smith: those benchmarks are on 1.4 I believe

8:29 justin_smith: *checks* nope, 1.5

8:31 justin_smith: zxc_: the really sad thing is when you go to "all langs" for one benchmark, and then sort by memory usage - clojure is always so close to the bottom

8:31 zxc_: the other clojure weakspot

8:31 hyPiRion: Remember that the benchmarks game is, well, a game. May or (usually) may not be relevant to what you're developing.

8:31 justin_smith: hyPiRion: absolutely - last I checked most of the code was nothing like idiomatic code

8:32 but if we are trying to compare langs for performance I don't know of better comparisons

8:32 zxc__: justin_smith: so sad, since its syntax is so nice

8:33 hyPiRion: and these are numerical, short benchmarks

8:33 hyPiRion: that's why c shines

8:33 * justin_smith makes an alternative benchmark game for "implementing a new feature on a year old code base" so clojure can really shine.

8:50 zxc__: justin_smith: aand I went on benchmarks game, and clojure is at most just 6 times slower than c, it's not slow at all

8:50 justin_smith: it's comparable to haskell in performance

9:20 lodin_: Anyone knows a stringify function that can handle infinite (or very long) sequences, e.g. outputting something like "(0 1 2 3 4 5 6 ...)" for (range)?

9:26 dxlr8r: lodin_: (apply str (range 0 1000)) ?

9:27 lodin_: dxlr8r: (range 0 1000) is not infinite.

9:27 hyPiRion: lodin_: look up *print-length* and *print-level*

9:27 ,(doc *print-length*)

9:27 clojurebot: "; *print-length* controls how many items of each collection the printer will print. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum number of items of each collection to print. If a collection contains more items, the printer will print items up to the limit followed by '...' to represent the remaining items. The root binding is...

9:28 lodin_: hyPiRion: Excellent!

9:28 (inc hyPiRion)

9:28 Need comma?

9:28 jeaye: incf

9:29 lodin_: (incf hyPiRion)

9:29 hyPiRion: lodin_: I think lazybot is dead

9:29 lodin_: RIP :-/

9:29 hyPiRion: long live lazybot!

9:29 snowell: At least we have clojurebot

9:30 lodin_: hyPiRion: If lazybot comes back, will it be as zombiebot?

9:30 oddcully: i heard he also went over to slack ;P

9:30 snowell: clojurebot: We love you

9:30 clojurebot: excusez-moi

9:30 snowell: Well fine

10:13 Olajyd: Hi oddcully

10:14 justin_smith: $mail zxc__ note that the specific usages I mention (hft and video) are not just about being fast, but also about having low latency simultaneously with high throughput

10:14 lazybot has forsaken us

10:17 Olajyd: I tried using the clj-time library to do date functions and I’m getting #<DateTime 2015-08-21T22:56:38.400Z>, Do i need to format it to give something like `2015-08-21T22:56:38.400Z` :|

10:18 justin_smith: Olajyd: yes, clj-time has formatting methods - like most Object types the default print method isn't going to work in output that is meant for humans

10:20 Olajyd: Oh so if i’m using it somewhere else its passing it as an actual date value?

10:20 justin_smith :|

10:20 Manaphy91: Hi, I've an atom useful to put items inside and a pmap with a procedure that try to add element to the aforementioned atom... The strange thing is that this procedure isn't deterministic and it seems to suffer sometimes of race condition.... (info Clojure version 1.6)

10:21 akabander: (defn tick->string

10:21 "Converts a Java time scalar into a string using the specified format."

10:21 [fmt tick]

10:21 (let [jt (java.util.Date. tick)]

10:21 (.format (java.text.SimpleDateFormat. fmt) jt)))

10:21 justin_smith: Olajyd: right - you could look for the javadoc for that specific DateTime class, I am sure it has nice formatters

10:21 akabander: please don't paste code here

10:21 akabander: (tick->string "kk:mm:ss 'on' yyy-MMM-dd" tick)

10:21 Oh sorry

10:21 justin_smith: Manaphy91: atoms retry, don't do things to atoms that would cause errors if you retried (did them over, repeatedly)

10:22 Manaphy91: especially if you are using pmap and accessing the same atom in each parallel branch, you can expect many retries

10:23 Manaphy91: but sometimes it works and sometimes not... it isn't deterministic... it seems to overwrite prrvious data...

10:24 pmap is in a doall... if I try to substitute pmap with map it works....

10:24 justin_smith: are you using reset! at all? are you reading the atom contents and setting it in separate forms?

10:24 Manaphy91: can you share the code on eg. refheap.com?

10:25 Manaphy91: I use only (swap! atom-name function-to-update)

10:25 justin_smith: and your function doesn't drop data?

10:25 Manaphy91: I would like but it is too long...

10:25 justin_smith: Manaphy91: http://refheap.com

10:26 bja: anyone using undertow here know how I'd go about knowing whether .stop() is safe (i.e. the instance is actually started, otherwise this throws a NPE)?

10:28 justin_smith: bja: are you using the ring adapter?

10:29 lazy-seq: Is there any reason why I can't access package private classes from Clojure, even if I make the namespace equal to package containing the class I want to access?

10:29 justin_smith: lazy-seq: it isn't even supposed to work that way

10:29 bja: justin_smith: yes

10:30 I'm actually wondering if I should just move to org.immutant/web

10:30 justin_smith: bja: run-undertow should return the object that you would use to stop the server

10:30 lazy-seq: justin_smith: why not though, because clojure just creates a class in the same package

10:30 bja: yeah, it returns an undertow instance, but if you .stop it and it's not started it throws

10:30 was just wondering if there was some way I was missing to tell if it's started without trying to do and catching NPE

10:31 justin_smith: lazy-seq: just because you are in a package with the same name, doesn't mean you can access a private value

10:31 bja: oh, that's weird that you would end up with an unstarted instance of something you get by calling run-undertow

10:31 lazy-seq: it is not a private value, the class is package private, so only classes in the same package should be able to access it

10:32 justin_smith: lazy-seq: that's called protected, not private, and just having a package by the same name isn't the same as being the same package, this isn't java

10:32 lazy-seq: justin_smith: it works if I create a java class in the same package that accesses the methods I want and call the wrapper class from clojure

10:32 bja: justin_smith, it's started when you call (run-undertow), but I want to make sure my component's stop method is idempotent

10:32 so if someone accidentally calls (stop (stop http-component)) the world shouldn't blow up

10:34 justin_smith: Manaphy91: just a style not, (swap! pe update-in [conf-len] #(conj % ext-vec)) is equivalent to (swap! pe update-in [conf-len] conj ext-vec) but I think the latter is nicer to read

10:34 bja: or maybe I'm being silly and the world should blow up, idk. undertow just didn't seem to have any docs on knowing whether their instance was actually bound to ports right now or not.

10:34 Manaphy91: ok

10:35 justin_smith: bja: I typically have my system component dissoc the stateful thing after punching it in the state, so that next time it isn't there to punch again

10:35 lazy-seq: justin_smith: Given the decompiled class it is in the same package

10:35 bja: I guess that's a reasonable thing to do. Maybe more reasonable than trying to figure out how to avoid double stopping.

10:35 thanks

10:45 justin_smith: bja: I bet the undertow object has a method like .isRunning somewhere in the api, but I find the general practice of removing things from a component if they are no longer relevant to be quite re-usable :)

10:50 lazy-seq: justin_smith: I guess the only forward is to create a java wrapper then, still curious as to why that works, but clojure with the ns equal to the package or gen-class fails

10:53 justin_smith: lazy-seq: sadly I don't really get how package-scope works on a bytecode level - but I think this is one of the various ways that clojure's emitting of byte code and javac's are different

10:57 lazy-seq: I am following up to try to find more about this question. One clue I just found is that "protected" doesn't actually directly correspond to any protection in the jvm bytecode

10:58 arkh: I've been using clojure for a number of years now but I've never had to include java in a clojure project (leiningen). In broad strokes what are the steps a person needs to take to use this (1) from their clojure code: 1) https://github.com/ronniedong/Expect-for-Java

10:58 lazy-seq: justin_smith: I suspect it has to do with reflection, because the wrapper cannot have the package private class as a parameter. Rather I need to specify each parameter that has the type of the package private class as an Object and cast in the function to the package private class

10:58 justin_smith: lazy-seq: unless it really is private (which is not the same as package protected)

10:58 lazy-seq: there is no such thing as "package private"

10:58 arkh: Expect-for-Java is not in any public repository

10:59 lazy-seq: justing_smith: package private is synonymous to default access / protected

10:59 justin_smith: at least that is how I encountered it on several websites

11:00 wes_ellis: I've got a csv file that I want to parse and plot lat/lng on google maps. Can I do this with just clojurescript, or would I need compojure/ring?

11:01 justin_smith: lazy-seq: "protected" is a compiler restriction. "private" is a bytecode restriction. Clojure shouldn't be preventing access to package level protection at all, and reflection can easily get around the private stuff.

11:01 lazy-seq: justin_smith: that is what I expected, but somehow it throws IllegalAccess errors :/

11:02 arkh: You can include the java file in src/java, add the java-source-path to the project.clj and just import it into your clojure ns

11:03 oddcully: wes_ellis: there is a file api in javascript - i can not say, how well it's wrapped in goog libs (or if there is a nice cljs lib)

11:03 justin_smith: lazy-seq: this could have to do with the "final" flag too... hopefully someone else knows more, I'm rapidly out of my own depth here

11:03 m0wfo: final flag should have no effect

11:04 lazy-seq: justin_smith: the class is final btw

11:04 arkh: lazy-seq: thank you

11:04 justin_smith: it's not just classes that can be final

11:04 there's also fields and methods that are final (on a vm level)

11:05 and sometimes with reflection hacks you have to toggle final status to get at things

11:06 wes_ellis: oddcully Thanks. I'll look into a pure clojurescript application.

11:06 lazy-seq: justing_smith: I think I will spends some time to create a minimal example that invokes this behavior and see what is causing this

11:06 justing_smith: an other non-final protected class doesn't give an issue

11:07 justin_smith: so perhaps the final flag is influencing things

11:07 justin_smith: lazy-seq: I don't have it here (it is on my notes on my home computer) but there is a hack amalloy showed me where you can actually change the value of the number 5 to be 2... and ensuing hilarity of course. But it's a good demo of popping the hood and tweaking things you really shouldn't be touching.

11:09 arkh: depending on how ambitious you are feeling, it looks like clojure.data.csv is not huge, and porting it to cljs would be interesting if it hasn't been done yet (or even making a cljc version...)

11:10 lazy-seq: justin_smith: I try to dive more into the internals to figure this out, thanks for helping!

11:58 dxlr8r: hello, I know there is a project to compile clojure code to C. but is there a project where I can write clojure without compiling and running from shell?

12:05 justin_smith: dxlr8r: "a project to compile clojure code to C" this actually exists?

12:05 there are hooks to use llvm from clojure, but that's not the same thing at all

12:06 clojure relies really heavily on gc for starters...

12:06 jeaye: Not to mention java interop

12:07 justin_smith: jeaye: I could see system interop working for a cclojure - but yeah it provides a completely different level of abstraction

12:14 lvh: cljc would be cool

12:14 justin_smith: name's already taken

12:14 lvh: the reader logic is fairly different; ISTR clojure.data.csv uses a lot of Java APIs directly

12:15 justin_smith: ahh, that's what you mean, neverm ind :)

12:15 lvh: they are just io apis, you could swap them out

12:15 I have done more rediculous things in cljc

12:33 wes_ellis: js interop: I'm trying to get the .-result prop of a FileReader, but I think cljs is returning the result too quickly. How can I wait for .-readyState to be 2 ("finished")

12:40 lvh: justin_smith: Sure

12:40 justin_smith: My experience with cljc so far has been "rename file; magically be able to use it from both clj and cljs"

12:53 bourbon: what's the most proper way to differentiate behavior between lein profiles?

12:53 I want to use a local in-memory store for dev and a config file for everything else

13:00 wes_ellis: https://gist.github.com/hiredman/5167534

13:01 Nice example on reading files. Now if I can find a clojurescript equiv of clojure.data.csv

13:08 iwo: hey, quick concurrency question: I want to create N workers to do something in my clojure app, which I can do like: (dotimes [_ n] (future ...))

13:09 this kind of thing: http://stackoverflow.com/a/2622410/125825

13:09 however my first thought is: this isn't actually creating n threads of course, I'm still limited to the size of the thread pool used for futures (I'm just creating N tasks)

13:10 justin_smith: iwo: the future thread pool is not limited in size

13:10 iwo: It seems like what I want to do is send-off, but I have no need for agents

13:10 justin_smith: agents use the same thread pool futures do

13:10 iwo: so futures use the 'send-off' pool, not the 'send' pool?

13:10 justin_smith: in fact, canonically, the futures are using the agent thread pool

13:10 oh, wait

13:10 forgot those were two different pools

13:11 {blake}: Is one supposed to be able to "lein jar" a project newly created with "lein new app project-name"?

13:11 justin_smith: iwo: yeah, I think it's the expandable send-off pool futures use, but we should double check that

13:13 iwo: it's clojure.lang.Agent/soloExecutor

13:13 so it's the good one :D

13:14 thanks for pointing me in the right direction!

13:14 justin_smith: np, glad I could help

13:16 iwo: the point where it happens, for those following along at home https://github.com/clojure/clojure/blob/4bb1dbd596f032621c00a670b1609a94acfcfcab/src/clj/clojure/core.clj#L6670

13:21 dxlr8r: yes it is: https://github.com/schani/clojurec , but that was not important :)

13:26 I guess it could be done, but it would need to be compiled for every run. have a script start a repl with code from a file

13:27 might be better to have one repl up at all times and refresh it somehow, and then load new code

13:27 justin_smith: dxlr8r: what are you trying to do again?

13:28 dxlr8r: trying to replace clojure for small shell scripts

13:28 make it more like perl, python, etc.

13:28 justin_smith: that's what pixie aims to be

13:29 dxlr8r: nice :)

13:29 justin_smith: but you can totally run java -jar clojure-1.7.jar -e '(load "blah.clj")'

13:30 and the load time is actually decent with lein and nrepl out of the picture

13:30 or at least usable

13:30 {blake}: Huh. Pixie's VM is "small" at 10MB.

13:30 justin_smith: for a full system of a clj-like that's puny

13:30 dxlr8r: is it possible to have the jvm open, instead of opening and closing at everytime

13:30 would make it faster

13:31 and instead flush it between "scripts"

13:31 justin_smith: dxlr8r: there is grenchman for that kind of thing

13:31 but then all users need to share a vm and trust each other not to mess up the vm state of course

13:32 dxlr8r: true, might not be to smart :P

13:32 {blake}: Why is it all so big?

13:32 dxlr8r: is it possible to slim the jvm? :)

13:33 justin_smith: dxlr8r: it's not the jvm that needs slimming here, it's clojure itself

13:33 {blake}: Yeah, Pixie doesn't use the JVM.

13:33 justin_smith: {blake}: immutable data structures are relatively fast, but are not cheap

13:33 they trade size for speed

13:33 {blake}: And my understanding is it's not the JVM that's the startup time problem, either.

13:33 justin_smith: exactly

13:34 dxlr8r: ok

13:34 learning a lot today :)

13:34 will bookmark the projects

13:34 {blake}: Oh, I get that they're not cheap, but I guess I don't get how that translates to VM size. Unless the built-in stuff uses =and stores= a lot of IDSes.

13:34 justin_smith: {blake}: ever notice how much of clojure is written in clojure?

13:34 the immutable data goes pretty deep

13:35 {blake}: Huh. I thought we weren't supposed to bother with state. =P

13:37 dxlr8r: can I take code from pixie straight into clojure?

13:38 if it doesn't do any outside calls :)

13:38 fantazo: whats pixie?

13:38 dxlr8r: https://github.com/pixie-lang/pixie

13:38 justin_smith: dxlr8r: it's highly similar but not compatible, even things like require have different syntax

13:39 dxlr8r: well, that's not good :/

13:39 justin_smith: I'm sure in the brave future of arbitrary read-conditionals we will eventually see code that can be clojure or pixie code depending on which compiler you are using

13:39 {blake}: You can use hiccup from Pixie, apparently.

13:40 justin_smith: but pixie doesn't have clojure compatibility as a goal

13:41 {blake}: Right. Sort of a mindspace compatibility.

13:42 Bronsa: {blake}: in my system starting the jvm takes 1/5 of the time it takes for the repl to start

13:42 {blake}: Bronsa: Yikes.

13:42 How did you figure that out?

13:42 Bronsa: time java HelloWorld.java vs time java -jar clojure.jar < /dev/null :)

13:43 {blake}: Bronsa: Ha!

13:47 dxlr8r: time java -jar clojure-1.7.0.jar -e '(+ 1 2)', take 1 second here

13:47 so not that slow :)

13:47 Bronsa: 0.6s here

13:48 dxlr8r: 1.17 to be precise

13:48 justin_smith: yeah, when you take out the lein/nrepl overheads it's not super bad

13:48 Bronsa: i'm optimizing for startup time though, a bare java -jar take 0.8/0.9

13:49 dxlr8r: guess clojure can be used for scripting then :)

13:49 without having to make jars etc.

13:50 hiredman: I use clojure for scripting

13:50 Bronsa: I try to use bash when possible, when I fail I fallback to clojure

13:50 justin_smith: dxlr8r: especially considering you can do "lein cp > deps" and just slurp that deps file up from your script to get your runtime classpath (assuming that making sure maven has all those deps is part of your install for the script)

13:50 hiredman: https://gist.github.com/hiredman/a8fb63ec64704ecb967f is a script for deleting old backups of clojurebot's db from s3

13:51 rhg135: If you need many deps though, then it gets hairy, but for scripts it's unlikely

13:51 justin_smith: rhg135: lein cp generates a deps string, not too hairy

13:52 rhg135: That requires a project.clj and lein installed

13:52 justin_smith: during install, sure

13:52 but not during runtime

13:52 hiredman: https://gist.github.com/hiredman/05befd5b39eef89b86ca is a script

13:53 Bronsa: I'm guilty of doing java -cp `lein cp` clojure.main

13:53 hiredman: https://gist.github.com/hiredman/7670532

13:54 rhg135: Heh, as am I

13:54 dxlr8r: nice hiredman

13:54 Bronsa: hiredman: wasn't there a function to add a jar to the classpath at runtime in clojure.core?

13:54 hiredman: yep

13:54 Bronsa: ,(doc clojure.core/add-classpath)

13:55 clojurebot: "([url]); DEPRECATED Adds the url (String or URL object) to the classpath per URLClassLoader.addURL"

13:55 akabander: There's lein-bin which makes a binary from the uberjar

13:55 hiredman: the java method it called is still there on DynamicClassloader too

13:55 akabander: Or did I misunderstand the question? Load times are... not great... but okay on a fast system.

13:55 Bronsa: probably a better way to do that than using a using c.l.C/LOADER

13:56 dxlr8r: my scripts are going to use each other a lot, I'll take a look to see if I can make it work. or this might be a good time to refresh my python or perl

13:57 akabander: I wrote an API to Ambari REST in Python and a utility to use it, then re-wrote the API and tool in Clojure. Using lein-bin, the Clojure version takes 3x as long as the Python in user time.

13:59 dxlr8r: speed is really not to important for what I trying to do. but I want to share with a community, so a hackish approach would maybe not be the prefered way

14:00 akabander: Hm, I take it back. It's 0.12s user for the Python and 2.23s user for the Clojure. :(

14:01 It's all about the jvm overhead.

14:01 Skummet crashed on me, but I hear that can help.

14:01 dxlr8r: would be great with a clojure for scripting. easy refer to other scripts that are within your SHELL path etc

14:01 just as in perl/python/bash/sh etc. :)

14:02 akabander: Yeah I may have to dig into pixie and cljs.

14:02 dxlr8r: where the code is compatible with clojure. except for maybe the require etc. since it's based on shell path

14:03 akabander: This is one of those areas where I'm pretty sure smarter people than I am working.

14:03 dxlr8r: true dat :P

14:04 akabander: So I just saw a library anounced that works with both clj and cljs, not sure how difficult the technique is to use, but it could be something to consider.

14:07 dxlr8r: http://hugoduncan.org/post/shell_scripting_in_clojure_with_pallet/

14:08 not entirely what I wanted, but wanted to share while one the subject

14:09 akabander: Yeah, that's interesting, but it's sort of an inversion of what I want. :)

14:09 dxlr8r: https://koodo.wordpress.com/2013/11/09/shell-scripting-with-clojure/

14:10 fantazo: I wonder how someone could tune the jvm for a quick startup, like in shellscripts.

14:11 akabander: fantazo: There's a project called Skummet, which Switftkey is using to get decent startup times on Android

14:11 justin_smith: fantazo: considering that the jvm is 1/5 of the startup time, why would you optimize that first?

14:11 akabander: But I couldn't get Skummet to work

14:11 fantazo: is it?

14:11 justin_smith: fantazo: that or less

14:12 fantazo: I always wondered why jvm apps generally take longer to print something on the console than say C apps

14:13 justin_smith: fantazo: the jvm starts up slower than a program that isn't running on a vm. Clojure starts up much slower than the vm itself. We have a lot of optimizing we would have to do before the vm became the bottleneck.

14:13 dxlr8r: lein-exec looked interesting, but looks like you can include scripts from the shell path in an easy way.

14:13 akabander: http://blog.ndk.io/2014/02/11/jvm-slow-startup.html

14:13 dxlr8r: since it's still depended on lein to load deps

14:14 fantazo: justin_smith, that's bullshit a vm isn't the limiting factor for startup time. there are enough vm languages which start "instantly"

14:14 akabander: The part 2 of the article I linked above goes into detail

14:15 justin_smith: fantazo: OK looking at that link I was clearly wrong, more like 1/30th of the startup time is the vm

14:15 fantazo: did you read what I said? a vm is a factor, clojure is the bigger factor by far

14:15 fantazo: I did.

14:16 justin_smith: I don't know how you got "the vm is the slow part" out of my statement, which was the opposite

14:17 fantazo: " the jvm starts up slower than a program that isn't running on a vm."

14:17 first sentence.

14:17 justin_smith: which is a fact

14:17 followed by the more relevant concern: the app in question starts up much slower than the vm

14:18 fantazo: sure. but it highly depends on the language. not every vm language out there has a slower startup time

14:18 Bronsa: fantazo: he said jvm

14:18 the jvm startup time is the same regardless of language

14:18 fantazo: Bronsa, no vm.

14:18 justin_smith: fantazo: a program that isn't using a vm can be compiled such that literally the bytes that will be put into memory are in the same order and same position in the binary. This starts a lot faster than a vm that loads up bytecode. But this fact is not really relevant in the case of clojure.

14:19 Bronsa: fantazo: justin_smith said `jvm`

14:19 justin_smith: fantazo: there is no vm out there that will start up as fast as a program which literally has an mmap call as its startup sequence

14:19 akabander: Could we generate a binary that has already loaded core.clj into bytecode?

14:19 fantazo: Bronsa, I'm not arguing about a sentence which I quoted. sorry.

14:20 akabander: So instead of running on a JVM, the program would run on a CLJ-VM?

14:20 Bronsa: fantazo: you were replying to a comment he made about the jvm

14:20 akabander: That should let us trade seconds for bytes, which I'll happily do.

14:21 Bronsa: akabander: clojure.java is already distributed AOT compiled if that's what you're suggesting

14:21 fantazo: it really isn't important if a vm language has the same startup time. only a startup time for say -help or console like programs like java, cat, etc.

14:21 that's not a very big deal.

14:21 akabander: I guess so... I'm actually kind of naive when it comes to the JVM, so please feel free to kick me in the assumptions.

14:22 Bronsa: fantazo: i'm not sure you're reading or understanding what we're saying. the JVM startup time is a factor in the slow startup time of clojure but it's marginal. the real factor is clojure itself

14:23 akabander: clojure is loaded from class files, core.clj doesn't get recompiled each time you start clojure

14:23 fantazo: Bronsa, I'm understanding what you are writing.

14:24 akabander: Got it, but it does spend a lot of time creating vars and metadata and loading external functions. Can that be done once and "frozen" into a binary?

14:25 Bronsa: akabander: I don't think creating vars and metadata is the bottleneck, what's slow is loading the thousand of classes required to do that

14:26 hiredman: running the verifier

14:26 Bronsa: hiredman: I disable the verifier for my clj repl, startup time goes from 0.9 to 0.7

14:26 akabander: Bronsa: I'm just looking at the article about bootstrapping: http://blog.ndk.io/2014/02/25/clojure-bootstrapping.html

14:27 Bronsa: akabander: there is a branch in the clojure repo to delay var initialization until necessary, IIRC it resulted in some startup speedup at the cost of halved runtime performance

14:27 dxlr8r: guess btw I could use eval and read-string to load other clojure scripts from my path

14:27 justin_smith: dxlr8r: or even just load or load-file

14:28 dxlr8r: nice

14:28 hiredman: ,(doc load-file)

14:28 clojurebot: "([name]); Sequentially read and evaluate the set of forms contained in the file."

14:28 akabander: Bronsa: Yeah I'm looking deeper now; "functions like eval cannot know what classes are needed"

14:31 hiredman: there are a vast multitude of different techniques, and people have explored a number, and they all have different and in some cases complex trade-offs, and some of the techniques are proposed by people who barely use clojure so the interactions with other features of the language are not well understood

14:33 clojure could do very well for many different uses cases, and people of many ideas how to do it, but ideas are cheap

14:35 akabander: I have several use-cases just in this one project. I'm building an API first, then a set of utilities that will need the API, and then a modular long-running application that will also use the API.

14:35 hiredman: like, if someone *really* *really* wanted a highly optimized clojure they would take stalin (the optimized scheme compiler every cites) and port it/translate it for clojure and the jvm, but that is a lot harder and appeals less to thinking about things that might work and writing a blog post

14:35 everyone

14:36 akabander: you just need a socket and your utilities written in shell communicating with the socket via netcat

14:38 akabander: That approach actually has some interesting second-order benefits. Should be worth the experiment, at least.

14:38 hiredman: if someone actually finished an optimizing compiler for clojure, and people felt it was worth it to use, that would likely push clojure towards being "self hosted"

14:39 akabander: it is how every project that I know of that does something like that does it

14:39 (a whole program optimizing clojure compiler would do better when the datastructures are written in clojure too)

14:40 akabander: hiredman: And this is how we get the "fix the airplane in flight" behavior that all the "we're using Clojure" articles boast about. I see.

14:42 Bronsa: a whole program optimizing clojure compiler is impossible w/o sacrificing some features

14:42 hiredman: likely it would take someone like ambrose with core.typed (or Bronsa, who if I recall is also in academia, with all the tools analyzer work), because it is a huge chunk of work, hard to sustain as a fee time project, and most startups don't care that much

14:42 Bronsa: same for scheme

14:48 dxlr8r: I might make a small library to integrate the shell's path into load-file. so that you can simply just load the name of file and not know it's path

14:48 justin_smith: in my experience the biggest sacrifice with stalin is the hours of compilation time to generate toy level code - I lost patience before getting to anything close to usable

14:48 dxlr8r: and use pomegranate if the scripts need external jars

14:48 justin_smith: dxlr8r: maybe something like CLJ_TOOL_SCRIPT_PATH but using the name of your app or whatever

14:49 as an environment var that a user could add to or replace

14:50 dxlr8r: yeah, could seperate it from PATH ofcourse, have it contain the paths in PATH and the option to include clj only paths

14:50 if that makes sense, not the best to talk about coding in english

14:51 akabander: I would make it it's own variable, and if people want to put clj files in their actual PATH, then they can do CLJTOOL_PATH=$PATH:$HOME/lib/clj-stuff

14:51 dxlr8r: yeah

14:51 probably better

14:52 akabander: s/it's/its/

14:53 dxlr8r: will look at it. atm I am splitting up a lot of my clojure work to make them generic as libraries

14:53 and to put on github

14:54 a couple might end up ion clojars too. I have a small library that is actually quite handy and I haven't seen it for clojure before

14:54 so someone might want to use it too :)

14:54 s/ion/on

15:06 sdegutis: puredanger: i dunno man, getting word out to 642 people could mobilize quite a few people to protest cca/jira

15:07 I for one am rooting for these guys to win. Cognitect should make Clojure pure Github.

15:08 puredanger: This is not up for debate

15:08 It's not going to change

15:09 sdegutis: that's what they all say

15:09 just today gcc moved to git

15:10 change is possible

15:10 srsly tho if it doesnt change then rich and the team lose all my respect

15:11 and if that doesnt matter to them, then they deserve to lose all my respect even more

15:13 puredanger: I'm going to go put my energy into making Clojure things rather than into a conversation this dumb

15:14 hiredman: /ignore is really nice

15:22 snowell: I'd done that, but then I only get to see half of a conversation

15:25 sdegutis: puredanger: that may have been a bit harsh

15:26 i havent fully figured that out. but if it was, then you ahve my apologies.

15:26 hiredman: but the upside is you (sometimes) avoid saying harsh things to people on the internet, regardless of if they deserve it or not

15:28 sdegutis: I see what snowell said in an irc log but not in here, even though he isn't on /ignore -- wht givs

15:28 hiredman: but I also have my browser setup to replace certain words similar to https://xkcd.com/1288/, so I am used to my internet experience being heavily modified

15:28 sdegutis: hiredman: how?

15:28 chrome plugin?

15:28 hiredman: for me all the clojure documentation talks about namespaaaaaaaaaaaces

15:28 sdegutis: hiredman: how? clojure plugin?

15:29 i mean chrome

15:30 oh, i see. people are actually using /ignore.

15:30 so i guess justin_smith is the only one who doesnt have me on ignore

15:31 which works out well, because he's the only one here who knows what he's talking about.

15:31 prrt: hello beautiful clojuristas, is clojure suitable for indie games?

15:31 akabander: sdegutis: I don't have you on /ignore... yet.

15:31 sdegutis: :)

15:32 xemdetia: prrt, I think a better question is 'is java a viable platform for the sort of indie game you want to make?'

15:32 or rather the jvm/javascript

15:32 akabander: Someone should make clunity

15:32 hiredman: prrt: https://www.youtube.com/watch?v=0GzzFeS5cMc is a great presentation about games written in clojure

15:32 sdegutis: akabander: just you wait until I've said some reasonable and logical things that happen to upset the crowd who hold rich on a pedastal!

15:32 xemdetia: sure

15:32 prrt: xemedtia: java = clojure? or is something there I don't know

15:32 sdegutis: prrt: java is 3 things

15:32 akabander: Clojure = hosted on the JVM, but not Java

15:33 sdegutis: prrt: 1. a virtual machine that runs platform-independent bytecode

15:33 oddcully: akabander: there is arcadia

15:33 sdegutis: prrt: 2. a language (Java) that runs on that virtual machine (JVM)

15:33 prrt: 3. a set of libraries that the JVM inherently uses

15:33 prrt: Clojure is an alternative to #2

15:34 prrt: Clojure uses #1 and #3 tho

15:34 akabander: oddcully: I should have guessed. :)

15:34 prrt: sdegutils: but isn't it slower than java-language?

15:34 sdegutils: (which gamers still blame for slugishness)

15:35 sdegutis: prrt: yes clojure is slower than java

15:35 prrt: the trade-off is that clojure is more dynamic, which some people prefer over speed

15:36 sdegutils: prrt: there are optimizations that help clojure get close to java's speed in some circumstances, but they aren't common in the real world use cases

15:36 prrt: sdegutils: I just don't want to struggle with 15fps, like with python

15:36 sdegutils: prrt: generally speaking though clojure isn't used where speed of the program is a huge factor; usually bandwidth or io are the real bottlenecks

15:36 prrt: clojure is probably faster than python for games, yea

15:37 prrt: sdegutils: the real question is, is it fast *enough*

15:37 akabander: The GIL really hurts Python for games though; you can't multithread your renderer without causing hiccups everywhere.

15:38 prrt: umm, I'm sure I won't have advanced graphics

15:39 so roguelikes and platformers are a good spot?

15:39 zerokarmaleft: prrt: prrt: check out what the arcadia guys have done: http://arcadia-unity.tumblr.com/post/109708255688/building-flappy-bird-from-scratch-at-our-november

15:40 prrt: zerokarmaleft: thanks, I will watch it later

15:41 final question - is this speed issue improving with each release? like in go?

15:44 zerokarmaleft: prrt: there seems to always be something that improves performance with each major release

15:44 prrt: zerokarmaleft: significant changes, or cosmetic?

15:44 zerokarmaleft: I'll say that go has a lot more low-hanging fruit in that regard, e.g. GC

15:44 alexshendi: Is "The Joy of Clojure" still a recommended resource for learning Clojure?

15:45 akabander: prrt: There are no cosmetic changes, Clojure is beautiful as it is.

15:45 zerokarmaleft: how is performance improvemtn cosmetic?

15:45 * chouser waits with bated breath.

15:45 prrt: akabander: cosmetic changes in performance, like 0.001 secs

15:45 akabander: alexshendi: I'm halfway through the second edition now, I think it's excellent, but maybe the longtimers have more critical opinions?

15:45 prrt: small changes*, maybe it's a better word

15:46 zerokarmaleft: alexshendi: Joy of Clojure is awesome

15:46 akabander: Oh, maybe "incremental" is what you meant?

15:46 oddcully: prrt: have you done some gaming stuff on jvm. like with libgdx?

15:46 alexshendi: akabander: There is a *second* edition?

15:46 prrt: oddcully: nothing done with jvm before clojure

15:46 akabander: alexshendi: It's two feet from my left elbow, yeah.

15:47 prrt: akabander: I just wanted to know if there are big improvenments in performance

15:47 oddcully: prrt: there is play-clj, which wraps it for clojure

15:48 prrt: oddcully: bookmarked

15:50 alexshendi: akabander: I still have the 2011 edition, which I believe is the first edition.

15:50 oddcully: prrt: i mention libgdx because its quite popular and it has several android and steam releases (the galleray sadly shows "everything" so pointing something out, you might know is a bit hard)

15:50 zerokarmaleft: prrt: transducers in the last major release was a pretty big improvement, for some definition of big

15:51 prrt: the tuple stuff going into 1.8 looks interesting also

15:51 hiredman: tuples were reverted last I heard

15:52 zerokarmaleft: hiredman: haven't checked JIRA in several weeks on that point, so I may be mistaken about it being included in 1.8

15:52 hiredman: oh, maybe they are back? or maybe I imagined them being reverted

15:52 prrt: oddcully: o-kay, thank you

15:52 hiredman: looks like they are in master

15:53 Bronsa: they are reverted

15:53 zerokarmaleft: hiredman: wasn't that rich's own version of the patch?

15:53 hiredman: it is

15:53 ah

15:54 they are disabled, not reverted, so the code is there, just not used by default

15:54 zerokarmaleft: ah

16:01 weathered-tree: Hi, I"m new to Clojure and the JVM. I have a problem I could use some help with, though it involves jsvc . Anybody familiar with it and use it with Clojure?

16:02 akabander: alexshendi: This one is (c) 2014, so I suspect you are correct.

16:09 {blake}: weathered-tree: Well, maybe we can help even if we havne't used it. What's the nature of the problem?

16:11 weathered-tree: I have a program that writes using agents to a share (/mnt/cifs). When I run this program through -main it works fine. However, when I run it as a daemon using jsvc, I the agents fail to write to the share with permission denied.

16:12 I'm running with jsvc USER set to "root"

16:12 and root has permissions to read/write

16:13 justin_smith: weathered-tree: are you using map or for to do this?

16:13 weathered-tree: yes, map in this case.

16:13 justin_smith: weathered-tree: because these things are lazy, the repl has the side effect of realizing lazy seqs because it prints the result, -main has no such mechanism unless you add it by hand

16:13 weathered-tree: I use dorun

16:13 to evaluate the side effects, does that work?

16:14 justin_smith: weathered-tree: depends - dorun is not recursive for example

16:14 so a map inside a map or whatever would still be an issue

16:14 weathered-tree: I just noticed, but a call to -main works fine, even outside the repl.

16:15 justin_smith: ,(do (dorun (map #(map println (range %)) (range 10))))

16:15 clojurebot: nil

16:15 justin_smith: oops!

16:15 oh it worked anyway

16:16 ,(dorun (map #(map println (range %)) (range 10))) ; simpler

16:16 clojurebot: nil

16:17 justin_smith: ,(dorun (map #(dorun (map println (range %))) (range 10))) ; now with more doruns

16:17 clojurebot: 0\n0\n1\n0\n1\n2\n0\n1\n2\n3\n0\n1\n2\n3\n4\n0\n1\n2\n3\n4\n5\n0\n1\n2\n3\n4\n5\n6\n0\n1\n2\n3\n4\n5\n6\n7\n0\n1\n2\n3\n4\n5\n6\n7\n8\n

16:18 justin_smith: weathered-tree: of course I can't know whether anything like that is actually happening in your code

16:19 weathered-tree: I'm taking a look just to be sure :-) That said, when I run using "lein run -m" it works fine. Would that be the case if I had the problem you mentioned?

16:20 justin_smith: oh wait permission denied I clearly need a break here

16:21 I totally missed the part where you said "permission denied"

16:22 rhg135: Is jsvc doing any setuid type stuff?

16:22 stuartsierra: rhg135: I think it can drop privileges after startup.

16:23 weathered-tree: I think that is what is happening. I have -user option set to "root"

16:23 rhg135: Sounds like your code is not running as root

16:23 weathered-tree: yeah, though jsvc is, since I don't get any other permissions errors.

16:27 stuartsierra: I'm using component in this project, it's been very useful, thanks!

16:30 stuartsierra: weathered-tree: you're welcome!

16:33 oddcully: weathered-tree: it runs manually as root, but fails if you start it as root via jsvc? maybe your setuid config is wrong and it uses some default (like nobody)?

16:34 weathered-tree: oddcully: That could be the case, I didn't set up this machine, I'll take a look, thanks.

16:38 hante_monsta: How Clojure's release schedule works?

16:39 How long until the next major version?

16:39 weathered-tree: oddcully: no setuid on the /mnt or /mnt/cifs

16:41 Bronsa: hante_monsta: they aren't usually scheduled, a release happens when it's ready -- however 1.8 will be an exception, it's scheduled for release this november IIRC

16:42 oddcully: weathered-tree: no i meant you passing "root" there explicitly for suid? since you are already root and you want to run it as root, why pass that param - maybe it degrades to some unrelated used, which is not allowed to do things there

16:42 weathered-tree: disclaimer: i have not used jsvc, this is just asking "unix" stuff

16:44 justin_smith: hmm, on ubuntu you cannot su to root - could this effect jsvc? (probably not actually)

16:44 weathered-tree: oddcully: I think you may be right. I switched the -user option to a regular user instead of root, but still has write permissions and it works. I verified using htop that the user when using -user root was blank whereas now it shows the user specified.

16:44 justin_smith: ahh!

16:44 could be related to that anyway then

16:44 (inc oddcully)

16:44 weathered-tree: (inc oddcully)

16:45 oddcully: justin_smith: could you please inc me, when the darn bot is here again ;P

16:45 justin_smith: for sure

16:45 rhg135: He's not coming back man

16:46 oddcully: weathered-tree: if you are already root, it makes no sense to tell it to "drop" to root; this is "giving up power" makes most sense where you want to start a process for e.g. privileged ports and then drop root

16:47 yet jsvc could complain about it

16:47 amalloy: it's part of my plan to never let justin_smith surpass me

16:48 * justin_smith shakes his fist.

16:48 rhg135: Now it makes sense lol

16:48 weathered-tree: oddcully: good points. Thanks for the help, you and everyone.

16:49 justin_smith: (inc oddcully)

16:49 lazybot: ⇒ 16

16:49 weathered-tree: (inc oddcully)

16:49 lazybot: ⇒ 17

16:49 {blake}: (inc oddcully)

16:49 lazybot: ⇒ 18

16:49 oddcully: hooray!

16:49 rhg135: Yay!

16:50 justin_smith: weathered-tree: oh, I almost forgot to mention, just so our little garden-path detour wasn't a total waste of time, with 1.7 you can replace (dorun (map f ...)) with (run! f ...)

16:53 weathered-tree: I like that, I can replace a whole bunch of those. Can I inc two people in one day?

16:53 justin_smith: indeed

16:53 weathered-tree: (inc justin_smith)

16:53 lazybot: ⇒ 285

17:03 seako: anyone have experience with korma, honeysql or other clojure sql libraries and have preferences/recommendations?

17:07 justin_smith: seako: I don't think any of them are quite good enough that you don't end up needing to figure out how to use clojure.java.jdbc

17:10 seako: justin_smith: thanks, since the queries I need to write at the moment are pretty simple maybe I'll just start there before exploring other tools

17:12 justin_smith: seako: of the various tools I kind of like yesql (which generates a jdbc query function from what basically looks like a regular sql file)

17:13 futuro: seako: I've been using honeysql, which I've liked so far. I'm doing some pretty straightforward queries, and it's been easy so far

17:14 stuartsierra: Java JDBC isn't bad either.

17:15 seako: justin_smith: I saw that library. there is something that's appealing about just writing sql. but I often find myself needing to compose queries which is where I find sql rather cumbersome. I've enjoyed Sequel for Ruby in the past and both korma and honeysql seem like they would be just as pleasant if not more so.

17:16 futuro: thanks!

17:17 stuartsierra: thanks, I think I'll start there since it sounds like I should learn it no matter what since it's ultimately what's under the hood

17:44 skeuomorf: Hmm, what's a good static site generator to use?

17:47 Found Cryogen http://cryogenweb.org/index.html will give it a go

17:50 mfikes: skeuomorf: Cryogen is awesome IMHO. :)

17:52 skeuomorf: mfikes: Great. It doesn't appear to have il8n support though, right?

17:52 mfikes: skeuomorf: Let me test. (Or do you perhaps mean l14n?)

17:53 skeuomorf: (Do you want to localize to different languages, or just have UTF-8 properly rendered?)

17:53 skeuomorf: mfikes: I want niceties around having posts in different languages

17:53 mfikes: so that probably entails utf-8 properly rendered

17:53 mfikes: skeuomorf: Ahh... right. I have not clue with respect to that aspect.

17:53 skeuomorf: mfikes: And some kind of system to manage different versions of the same post

17:54 mfikes: No worries :)

17:56 justin_smith: skeuomorf: if nothing else, text output from clojure will be utf-8 if no other option is forced (though the internal representation is java native, basically utf-16)

17:57 ,(def ☃

17:57 err

17:57 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:57 justin_smith: ,(def ☃ 42)

17:57 clojurebot: #'sandbox/☃

17:57 justin_smith: ,☃

17:57 clojurebot: 42

18:02 sdegutis: Is there a way to set an environment variable from a Leiningen alias?

18:03 skeuomorf: justin_smith: oh, I see

18:06 sdegutis: How can you tell what Leiningen profile was used at runtime in your proram?

18:23 weathered-tree: seako: I've used korma and yesql in addition to jdbc.

18:26 sdegutis: I normally use environ and just add a {:dev true} or some such to each profile map.

18:27 seako: weathered-tree: that runs the gamut from low-level to dsl, do you have a personal preference based on those experiences?

18:31 weathered-tree: My first projects used korma, but I found it too heavy, plus it has some global state I wanted to not deal with. It's pretty useable though. I prefer yesql and jdbc though. Although it's more work, it is a lot easier to reuse what I write and easier to test.

18:34 seako: if you don't like writing SQL though, then korma is really your best option. I find with yesql I can keep the SQL out of my code which is good enough for me.

18:35 Clojure code*

18:42 sobel: can someone figure out how to pass a list or vector as the parameter to an IN clause in sql? (oracle)

18:51 dxlr8r: sobel: apply list

18:51 (apply sql [1 2 3])

18:54 sobel: no, i have a query with "...WHERE attr IN (?)" and i want to pass a list for the ?

18:56 really hoping i don't have to generate a piece of the query just because of this

19:00 AWizzArd: Today I updated my Emacs to use “Cider 0.9.1”. Now in the repl when I press <Enter> on some previous (“historic”) expression it no longer get’s copied down to the current prompt.

19:01 amalloy: sobel: you can't. there's no support in parameterized queries to parameterize the number of things in the IN clause

19:01 AWizzArd: Is this just me or is that a bug (or a new customizable setting)?

19:01 sobel: amalloy: thanks

19:01 amalloy: you just need to generate a string like "(?, ?, ?)" yourself

19:01 sobel: that was the best answer i could find on the web but it went back to 2013 so i thought i'd ask here

19:02 i guess i'll just fill a temporary table and join it. this query could get stupidly large anyway.

19:13 seako: weathered-tree: thanks so much!

19:37 domokato: I have a function that recursively traverses a tree, and I want to reuse the code to do one of two things: 1, perform some side effects for each leaf (easy), or 2, return a flat map containing leaf name to leaf data mappings. What's the best way to design the function to allow for both?

19:39 My initial thought is to pass a function in, but not sure how to get a map out of it (#2) without also passing the map through as a parameter

19:39 or something like that

19:42 i could use a map atom and populate that with each call to the passed in function, but there seems like there should be a better way

19:46 i could return a map from the traversal function, but that means i would also have to insert code to merge maps at the recursive calls, which seems like bad coupling

20:09 i'm thinking this may be a job for transducers...

20:12 TEttinger: or a job for zippers

20:13 http://www.exampler.com/blog/2010/09/01/editing-trees-in-clojure-with-clojurezip

20:28 justin_smith: domokato: you could use tree-seq, and filter for data that is leaves

20:28 ,(doc tree-seq)

20:28 clojurebot: "([branch? children root]); Returns a lazy sequence of the nodes in a tree, via a depth-first walk. branch? must be a fn of one arg that returns true if passed a node that can have children (but may not). children must be a fn of one arg that returns a sequence of the children. Will only be called on nodes for which branch? returns true. Root is the root node of the tree."

20:29 justin_smith: (tree-seq map? vals {:a {:b {:c 0} {:d 1}}})

20:29 ,(tree-seq map? vals {:a {:b {:c 0} {:d 1}}})

20:29 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

20:29 justin_smith: ,(tree-seq map? vals {:a {:b {:c 0} :d 1}})

20:29 clojurebot: ({:a {:b {:c 0}, :d 1}} {:b {:c 0}, :d 1} {:c 0} 0 1)

20:29 justin_smith: of course you would want to adjust the tree-seq arg for your trees, and ignore higher branches

20:30 aaelony: sobel: this is a reason why I prefer to write functions that emit SQL portions rather than use a library for this. If you write a function that contains a string of your sql query, it is simple to alter that string any way you please, including editing the IN clause. Then you can execute the new query string against a jdbc connection yourself. Just a thought.

20:31 for sql analytics, the level of granularity for sql composability is much higher than for normal apps that want crud functionality.

20:33 i.e. most often, not at the syntax level of sql, but the "what am I trying to do" level in sql...

20:43 domokato: justin_smith: hm, tree-seq might work with a little finagling, but the problem is it's not a simple tree - it's actually an acyclic digraph of objects of various types

20:43 justin_smith: thanks for the tip, i'll compare it to transducers and see which one works better

21:08 i think i'm gonna end up reducing the recursive call and passing a result value through, which will just continue to be nil in the case where I just want side effects. i think this seems reasonable

21:14 in this way i can do the map merging inside the passed in function

21:20 edtoast_46: please try joining #edtoast .I would greatly appreciate it

21:21 rhg135: tsk tsk

21:22 omarkj: Hey. Can I do multi arity in a defproto ?

22:41 weebz_: I'm currently making a website using compojure+http-kit, and I was wondering if anyone knew how to make debugging exceptions/errors easier?

22:41 when I get a message like: String index out of range: -42

22:41 it's a bit hard to figure out where it's coming from sometimes :\

23:37 Is it possible to call Clojurescript from JavaScript?

23:42 gfredericks: shouldbe, especially if you add ^:export metadata to the functions you want to call

23:42 weebz_: I haven't used clojurescript before, was curious because when I tried to search I didn't see any examples of how to do it

23:42 I want to use it in the context of a firefox extension

23:44 gfredericks: CLJS functions compile to JS functions, and the namespaces are all a bunch of nested objects

23:44 so you can figure it out pretty easily from a js console

23:51 weebz_: okay, thanks

23:52 do you know if it's possible to do require calls in this format? var fooBar = require("sdk/foo-bar")

23:53 because if that's the case I don't think I would even need to use javascript

Logging service provided by n01se.net