#clojure log - May 08 2014

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

0:51 PigDude: is #inst reader macro documented somewhere?

0:52 *data reader

2:53 dhruvasagar: Hey guys, I am learning clojure and having fun, I am a little confused with the syntax of this function (.toUpperCase), it looks like most string functions are like this, I am unable to get (doc .toUpperCase) and (macroexpand) also doesn't do anything for this so I am not sure what to make of this '.' methods

2:53 beamso: ,(.toUpperCase "foo")

2:53 clojurebot: "FOO"

2:53 beamso: if it starts with a ., it's most likely java interop

2:53 dhruvasagar: beamso: I know how to use it, I just don't understand the significance of the '.'

2:54 dbasch: it’s java interop, .toUpperCase is a method of java String

2:54 dhruvasagar: dbasch: why the '.' ?

2:54 beamso: then it looks like a method call?

2:54 dbasch: dhruvasagar: see http://clojure.org/java_interop

2:54 dhruvasagar: dbasch: thanks, reading

2:54 beamso: (toUppercase "asd") also looks like a method call

2:54 babilen: reading the interop docs

2:55 beamso: *

2:55 servo: isn't like everything in clojure java interop?

2:55 dhruvasagar: servo: I don't think so, libraries written in clojure are different from the ones borrowed / imported from java

2:56 servo: I suppose this is the way to differentiate

2:56 servo: i guess im conflating java/jvm

2:56 dbasch: servo: there’s clojure for other platforms, most notably clojurescript on javascript

2:57 servo: (not= clojure clojurescipt) (== clojure clojurescript)

3:01 dhruvasagar: I am considering building a small webapp this weekend using clojure, I am considering using something like Noir / Luminus, however I've been recommended to use compojure / rain directly, what are your thoughts ?

3:01 servo: noir is deprecated

3:01 dhruvasagar: s/rain/ring

3:02 servo: why so >

3:02 servo: use httpkit + compojure

3:02 beamso: i thought noir was deprecated but lib-noir wasn't

3:02 servo: i never said lib-noir was deprecated ;)

3:02 beamso: ah

3:03 dhruvasagar: servo: checking out httpkit

3:03 servo: httpkit is the shiz

3:03 dhruvasagar: servo: interesting, my familiarity to nodejs might come in handy

3:04 clgv: dhruvasagar: ring+compojure is pretty standard

3:04 dhruvasagar: clgv: hey :)

3:04 dbasch: dhruvasagar: start with compojure and see if that’s enough for what you want to build

3:05 dhruvasagar: dbasch: what about templating?

3:06 servo: i use hiccup

3:06 but i hear good things about enlive

3:06 dbasch: dhruvasagar: whatever you like, really

3:06 hiccup is ok

3:06 clgv: servo: yeah well, hiccup is not really templating, you'll force you designers to learn the EDN part of Clojure ;)

3:07 servo: i consider that a win

3:07 dbasch: or you could go the api / client-side app route

3:07 * beamso uses selmer for templating

3:09 servo: im kinda of the opinion that only static data should be spit out as html

3:09 and data should be used to update dom using reactjs et al

3:09 dhruvasagar: servo: I agree

3:09 servo: reactjs / angular / knockout ?

3:09 beamso: sometimes my html output isn't for browsers :/

3:09 servo: what reads html besides browsers?

3:10 beamso: wkhtmltopdf

3:10 dhruvasagar: servo: he didn't mention html

3:10 servo: oops my bad

3:10 servo: ok

3:11 so for the other 99% of use cases id say my opinion still stands

3:12 dhruvasagar: servo: whatever you said is pretty much http standard...

3:12 servo: I can't output dynamic data as html...unless I am thinking wrong

3:13 servo: dynamic on the server side

3:13 before render

3:14 dhruvasagar: is :use deprecated ?

3:14 beamso: i take it that it's easy to use reactjs with REST resources?

3:14 dhruvasagar: beamso: I think so

3:14 clgv: yes you shoud only use "use" on the repl

3:14 dhruvasagar: beamso: but I think either angular or knockout or even backbone would do good too

3:15 clgv: thanks

3:15 servo: im a big fan of react

3:15 beamso: i didn't like what i saw of angular

3:15 dhruvasagar: servo: tbh I haven't used it much

3:15 servo: learning curve with angular is too steep

3:15 clgv: (:require [my.awesome.namespace :as an]) with (an/my-fn ...) makes it clear where the function is defined

3:15 dhruvasagar: so far the most that i've liked is knockout

3:16 knockoutjs is pretty good, have started disliking backbonejs since I used knockoutjs

3:16 servo: theres a cool clojurescript lib for react called om

3:16 although personally i like to write native javascript

3:16 dhruvasagar: servo: me too

3:17 * clgv runs away scared ;)

3:17 dhruvasagar: servo: I did like Coffeescript for a bit, but then I guess I just didn't groke js well enough then

3:18 servo: coffee script is ok. one good thing is that it's guaranteed to pass lint in script mode everytime

3:18 strict mode*

3:18 sjy: i still like coffeescript. are you saying there comes a level of js zen where you actually want to mess around with prototypes?

3:18 dhruvasagar: sjy: well sort of, I think it's more to do with the ease of debugging

3:20 servo: not everyone likes coffeescript and when you're on a team you force people to maintain code. vanilla javascript is standard. its mostly a political thing

3:20 sjy: fair point, i don't use coffeescript at work. tbh 90% of the benefit for me is not having to write out "function"

3:21 servo: function is only one more character than (defn )

3:23 although most editors will autocomplete the trailing )

3:24 dhruvasagar: sjy: you can always use snippets

3:24 servo: snippets?

3:25 dhruvasagar: servo: what editor do you use ?

3:25 servo: I guess you could call them templates too ?

3:25 servo: sublime

3:25 dhruvasagar: servo: or bundles /

3:25 servo: ah

3:25 i know what you're talkign about now

3:27 bengillies: you have the same last name as me

3:28 dhruvasagar: servo: and that would be ?

3:29 servo: gillies

3:29 obviously

3:30 :)

3:30 dhruvasagar: servo: k :)

3:31 servo: almost have 1000 messages logged from #ubuntu into datomic woo

3:32 dhruvasagar: servo: interesting datomic

3:33 servo: wonder how they manage the queries since they maintain all versions / changes of a record (document?)

3:33 servo: datomic is to databases as jesus is to sinners

3:34 dhruvasagar: queries happen in the application

3:34 dhruvasagar: servo: I meant resolving queries

3:34 servo: the data store is just a binary blob key value covering index

3:34 dhruvasagar: servo: I suppose they just get the latest version

3:35 servo: its the datom with newest transaction id

3:36 theres an index that groups transaction ids

3:39 dhruvasagar: servo: cool

3:39 servo: sounds interesting although might force a lot of horizontal scaling and backups etc will be slower etc

3:39 servo: write performance would also be compromised a little

3:40 servo: still an interesting idea especially considering read is the most frequent operation

3:45 servo: writes are slower only in theory

3:46 with dynamodb cranked up you will have to try really hard for transactor to get away from you

3:49 dhruvasagar: servo: k

5:40 jcidaho: Anyone tried https://github.com/sunng87/hbs?

5:40 handlebars for Clojure?

6:13 clgv: jcidaho: sparse docs. syntax for variables looks similar to selmer but no idea what the collection syntax looks like

6:24 jcidaho: clgv: Have you used Selmer? We are analyzing templating options

6:25 we have a mixed team of Clojurians and front end ppl who want to hack on the HTML templates

6:25 Something mustache related is the current favourite option, but the logic-less side isn't so appealing

6:26 clgv: jcidaho: one of our students is using it for his project. so we'll see how it performs...

6:26 Glenjamin: i'm not clear why you'd use mustache if you don't go logic-less?

6:26 the main selling point was portability, i thought

6:27 jcidaho: Glenjamin - it's an easy templating language for UX devs + Clojure server-side devs to converge, plus the template can be used client-side, the door is open to that possibility

6:28 Glenjamin: jcidaho: as soon as you add logic, the server-client stuff gets much harder. unless you're using a language that runs both sides i guess

6:28 raw mustache gets is client/server portability by having very few features

6:29 jcidaho: Glenjamin - Yeah. Handlebars is an option, so long as both server-side and client-side use the same extensions

6:29 I'm tempted by Antlers too

6:29 Glenjamin: mm, whenever i've used mustache i've done an explicit "presenter" layer

6:30 jcidaho: Glenjamin - makes sense - I've seen a large project where we didn't do that, and wish we had

6:32 Glenjamin: yeah, mustache trades off power for portability - so you have to put the power somewhere else or its just a mess

6:33 but if you want UX people to be able to make significant changes to rendering logic it probably isn't a good fit

6:34 jcidaho: I wonder what are the other options? Hiccup would be too hard core for them, as would Enlive..

6:34 Glenjamin: something derived from the django/jinga/twig family i guess

6:36 jcidaho: Selma

6:36 martintrojer: can you render selmer templates in the client?

6:38 jcidaho: I guess if you need to, you can just use pure mustache, which is a subset of Selma.. (haven't used Selma, so making an educated guess)

6:41 locks: selma?

6:41 ssideris: jcidaho: with this scenario there is the added complexity of staying within mustache syntax in some cases and not staying within it in some others

6:42 jcidaho: yup - templates living in a special directory that swing both ways, and are restricted to normal mustache

6:42 a price must be paid somewhere..

6:42 https://github.com/yogthos/Selmer

6:44 locks: thanks jcidaho, that was proving tricky to search for

6:47 jcidaho: Sorry, I typoed

7:37 CookedGr1phon: Rather than the error message "nth not supported on this type", for the sake of clojure beginners, would it not make more sense to say something like "Was expecting a value which supports nth, e.g. a vector"

7:38 and while we're at it, what about printing the value that's at fault, rather than just its type

7:39 it really bugs me that error messages almost never show you what you passed in to make it complain, just make cryptic comments about how it was wrong

7:57 clgv: CookedGr1phon: yeah would be awesome if the clojure compiler would throw ExceptionInfo instances with additional context data

7:58 CookedGr1phon: well ideally we could browse all the values at every stage in the stack frame, but I'd settle for up to 30 characters of the pr-str'd value that's caused the issue in the message

7:59 (any more than that you might make the error message stupidly large

7:59 but a snippet is usually enough to give you an idea where to look for your error

7:59 clgv: well if it used ExceptionInfo the REPL frontends could implement functions to investigate that

8:01 CookedGr1phon: guess so

8:02 getting more information (specifically locals from stack frames) into exceptions would make working with clojure 100x smoother

8:03 Glenjamin: there's a suggestion in the clojure wiki about being able to run in different modes

8:03 you generally don't want locals-capture if you're in production or benchmarking, for example

8:03 but you would want that in dev

8:03 CookedGr1phon: sounds promising

8:25 borkdude: I got this in my profiles.clj: https://www.refheap.com/85253 - and this in my project.clj: :profiles {:ring-server {:dependencies [[org.immutant/immutant-jobs "1.1.1"]]}}

8:26 yet when I start my project like this: lein with-profile ring-server ring server

8:26 I get this: Exception in thread "main" java.lang.RuntimeException: No reader function for tag spy/p, compiling:(fuod/report.clj:206:72)

8:26 help.

8:27 clgv: borkdude: you specify dependencies in your profile.clj? that's very likely a really bad idea

8:27 borkdude: oh wait. missread "lein-ring" as "ring" sorry

8:28 agarman: clgv it's not a bad idea, just one that you need to be careful with as you can accidentally use something in a project and forget to add it to the project

8:29 borkdude: it is an idea I got from http://dev.solita.fi/2014/03/18/pimp-my-repl.html

8:29 Glenjamin: that sounds like it makes it a bad idea to me :)

8:29 borkdude: only deps for debugging purposes

8:29 Glenjamin: oh right, debugging / tooling dependencies

8:29 agarman: I use it for alembic, fresh, criterium, sigmund, better stack trace etc.

8:29 Glenjamin: i see now

8:29 agarman: lots of stuff that just doesn't belong in a project.clj

8:30 Glenjamin: borkdude: try lein with-profile ring-server classpath

8:31 clgv: agarman: yeah tools are fine, but not something like "ring" ;)

8:32 agarman: I do keep separate profiles for when I want to launch and incanter, datomic or postgresql repl

8:32 AWizzArd: Does Jetty, Ring or Compojure have an intelligent way on how to treat gzipped files? I could easily add a with-gzip middleware, but this would cost cpu on each request. Instead I want to pre-gzip my static files and have them delivered.

8:32 clgv: borkdude: but it is possible that the :user profile is not used for ring-server you should check that

8:33 borkdude: ah, the problem might be that I first have to load the program, then add the #spy/p thing, because of some dynamism

8:35 justin_smith: /join #caribou

8:35 err

8:39 borkdude: and that it fails when I load it at firstah wait. if I start with lein with-profile ring-server,user ring server

8:40 sorry. if I start with lein with-profile ring-server,user ring server I get this error msg: Exception in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'spyscope.core/print-log, compiling:(fuod/report.clj:206:72)

8:42 justin_smith: AWizzArd: I think hlship is working on a ring content middleware that would cover issues like that - he is also the guy behind the tapestry java lib

8:44 https://github.com/hlship/dieter

8:44 oh, never mind, that doesn't do gzip (yet?)

8:47 clgv: borkdude: huh. how about adding spyscope to the dev dependencies or dependencies of the project and see whether that works first? then you can move it farther away incrementally and see when it fails

8:47 borkdude: clgv good idea

8:49 AWizzArd: justin_smith: yeah, a middleware that checks when "game.html" is requested if there is also a "game.html.gzip" and deliver that, along with the right response headers.

8:49 justin_smith: AWizzArd: and also maybe generate game.html.gzip if that does not exist yet - for static files at least

8:49 this would be tricky with templates

8:50 AWizzArd: I would be happy enough if it didn’t try to gzip explicitly, just serving the corresponding files if they should exist, or just serve what was requested in the first place.

8:52 justin_smith: now that I think about it - why not a wrapper for wrap-resource, where it first looks for foo.bar.gzip (returning if found) and otherwise for foo.bar

8:52 that should be like a 5 line middleware

8:52 clgv: AWizzArd: with-gzip middleware using core.cache?

8:53 AWizzArd: clgv: intriguing

8:54 Glenjamin: is there a load balancer / reverse proxy between your app and the internet?

8:54 i'd normally just have my app return proper mime types and put this sort of thing there

8:54 AWizzArd: Glenjamin: not yet, but I guess nginx is just a question of time.

8:55 justin_smith: (inc Glenjamin)

8:55 lazybot: ⇒ 3

8:55 justin_smith: yeah, let nginx or varnish handle that actually

8:55 Glenjamin: in that case with-gzip + proper cache headers will probably be fine

8:56 AWizzArd: Glenjamin: so nginx would not forward requests of "game.js" to my Jetty anymore, but instead cache&deliver game.js.gzip itself?

8:56 Glenjamin: yeah, i'd maybe have a deploy step that created assets and gzipped versions

8:56 justin_smith: AWizzArd: yeah, you can configure nginx to do that

8:56 Glenjamin: although ideally you want to put a hash in the URL, the cache forever

8:56 borkdude: argh, context switch from another project to this clojure project. why is this false? (== 0M 0.000M)

8:56 justin_smith: and that is better than serving static resources from ring

8:57 AWizzArd: Okay, sounds fine then, thx guys.

8:57 justin_smith: borkdude: == respects float vs. integral distinction iirc

8:57 borkdude: what is your version? this stuff has been in flux a little lately

8:58 ,(== 0M 0.000M)

8:58 clojurebot: true

8:58 justin_smith: maybe update your version

8:58 borkdude: 1.5.1 still

8:58 justin_smith: ,*clojure-version*

8:58 clojurebot: {:major 1, :minor 6, :incremental 0, :qualifier nil}

8:58 borkdude: ok I'll upgrade

8:59 ah this could also explain why I'm seeing different results locally compared to on the server. if I use immutant, does it respect the clojure version of the project?

8:59 justin_smith: I don't know immutant

8:59 tcrawley: borkdude: yes, Immutant will use the clojure dep in your project.clj

8:59 borkdude: ok, then it doesn't explain it :)

9:00 what is the latest clojure, 1.6.0? or 1.6.1? ?

9:00 tcrawley: 1.6.0

9:00 borkdude: k

9:00 martinklepsch: I'm processing lots of data and my JVM just crashed because there was no more memory available (on a 512mb machine ;D) — is there anything that I can do to make that work or should I just go for more ram?

9:01 borkdude: martinklepsch you can increase the default heap space

9:01 justin_smith: borkdude: when the machine has 512 max that won't go too far

9:01 borkdude: justin_smith true, but mayb it's not even using all of that

9:03 hyPiRion: martinklepsch: would you expect it to crash? If possible, stream the data instead of reading it all in at once

9:03 I have no idea if that's your issue, of course

9:04 martinklepsch: hyPiRion, it doesn't surprise me to much. I want to bulk insert stuff into elasticsearch so not sure if streaming would work in that context

9:04 hyPiRion: ah

9:05 martinklepsch: borkdude, just reading up on heap space a bit. can I do that with leiningen? I'm just running stuff from the repl on that server

9:05 borkdude: martinklepsch yeah, you can define jvm-opts

9:05 Glenjamin: if the machine only has 512, you'll just have to rely on lazy sequences

9:06 borkdude: martinklepsch but I'd have to look it up also

9:06 Glenjamin: steer clear of big vectors or maps

9:06 martinklepsch: borkdude

9:06 http://stackoverflow.com/questions/3757223/jvm-options-using-leiningen

9:06 borkdude: martinklepsch the answer from 2010, I would also check in the leiningen docs

9:07 martinklepsch: borkdude, that still seems valid: https://github.com/technomancy/leiningen/blob/master/sample.project.clj

9:07 hyPiRion: martinklepsch: `:jvm-opts [your-jvm-opts]`. Eventually try to uberjar and run

9:07 justin_smith: you need ^:replace for some jvm-opts to really apply

9:07 otherwise they get overridden by some defaults

9:07 -server is one of those

9:08 martinklepsch: justin_smith, what does server do?

9:08 Glenjamin: -server is default, or -server doesn't get added?

9:08 hyPiRion: justin_smith: That was changed, I think it only applies to lein pre 2.0.x

9:08 Glenjamin: ah, right

9:08 justin_smith: hyPiRion: definitely applies to some 2.x

9:08 Glenjamin: i added -server recently and it seemed to work

9:08 on latest

9:08 justin_smith: martinklepsch: changes the hotspot optimization strategy, and affects startup time

9:09 Glenjamin: good to know, thanks

9:09 hyPiRion: justin_smith: technomancy/leiningen#1230

9:09 lazybot: Set default :jvm-opts in :base profile to :displace -- https://github.com/technomancy/leiningen/pull/1230 is closed

9:10 hyPiRion: So uh, pre 2.3

9:10 * hyPiRion thought lein was on 2.1 for some reason

9:10 justin_smith: cool, good to know that changed

9:11 hyPiRion: still an iffy problem though. Wish we could please everyone with some good defaults

9:11 rolfb: any mnemonics for remember which book is which of "Programming Clojure" and "Clojure Programming" ?

9:12 martinklepsch: so with 512mb ram I would go for something like :jvm-opts ["-Xmx265m"] or is it safe to use 512m as well?

9:13 justin_smith: depends, does your OS use memory?

9:14 martinklepsch: justin_smith, uh, yeah?

9:15 I guess 512 mb is just not enough to run riemann, elasticsearch + my data intensive program. :D

9:15 (which is fine :))

10:04 is there something about running lein as root that will absolutely ruin my life?

10:06 justin_smith: well, lein is a dev and build tool...

10:06 why do you want to run lein as root?

10:08 clgv: martinklepsch: except from the usual reasons not to run any application programs as root if not necessary?

10:08 martinklepsch: justin_smith, clgv, I'm just toying around and am to lazy to setup non-root for that :P

10:09 switching to a 2GB machine seemed to fix the problem btw

10:09 justin_smith: you are on a system that has no non-root user?

10:09 clgv: martinklepsch: too lazy for a "useradd ..." ?

10:09 justin_smith: making a user account takes about 1 minute tops

10:10 martinklepsch: yeah, but than I need to switch to do certain like running docker and stuff

10:10 but yeah, maybe I should just do it

10:11 justin_smith: martinklepsch: consider making an uberjar on the dev machine, and just running java -jar on prod also

10:11 martinklepsch: justin_smith, would that allow me to jump into a repl?

10:11 I just wondered — when I do a lot of data processing and print all that data to the repl because the function I'm calling just returns that data, could that be the reason for memory issues?

10:12 probably yes right?

10:12 because that 2gig machine just crashed too haha

10:12 justin_smith: martinklepsch: if you use tools.nrepl.server you can connect to the app with a repl

10:12 martinklepsch: REMOTELY AS WELL?!!

10:12 that would be crazy cool

10:13 justin_smith: make an ssh tunnel

10:13 martinklepsch: yeah

10:13 justin_smith: don't open nrepl to the whole world :)

10:13 yes, works remotely

10:13 also, use an ssh tunnel to connect a local visualvm (or other profiler) process to the server

10:13 to see what is really happening, where resources are actually going, etc

10:13 martinklepsch: haha, I mean, I run my stuff as root so I can open the nrepl to the world as well right ;)

10:13 justin_smith: visualvm comes with the jdk

10:16 borkdude: can I ask a question about cursive clojure here?

10:17 justin_smith: martinklepsch: http://java.dzone.com/articles/how-debug-remote-java-applicat this shows how to start the java process with a debug port open

10:18 you can add the args to the lein :jvm-opts if you still don't want to uberjar (though I still recommend making uberjars and not running lein on prod)

10:18 borkdude: my question is: how can I debug while starting lein ring server in cursive clojure

10:18 martinklepsch: justin_smith, eclipse?! ;P

10:18 justin_smith: hah, stop at the jvm setup step

10:18 and connect a real profiler

10:19 martinklepsch: justin_smith, yeah will probably do that in the future. seems saner and I wanted to understand that whole uberjar stuff better anyway

10:19 justin_smith: it's not super hard, just means you need a compiled -main for the app

10:20 there is a way to specify the jar, then the class, then the args so you don't need a compiled main as well

10:20 martinklepsch: justin_smith, yeah got so far the last time but ran into other issues and then stopped

10:20 Glenjamin: if you uberjar, presumably there's no way for it to pick up the :jvm_opts from your project.clj anymore?

10:20 borkdude: or lein immutant run for that matter

10:21 justin_smith: Glenjamin: right, I typically make a short startup scripts with my prod jvm opts

10:21 Glenjamin: makes sense

10:22 justin_smith: it just eliminates a few moving parts

10:22 and makes restarts on the server much faster

10:22 martinklepsch: justin_smith, just for the interim — could it be that printing all that stuff to the repl actually causes the memory to get full because it's stored until the fn returns?

10:23 justin_smith: martinklepsch: depends on whether you are holding on to the head of lazy sequences

10:23 martinklepsch: holding on to the head?

10:23 justin_smith: lazy sequences reduce memory usage if you iterate over them but don't have abinding to the head (the first element)

10:23 if the head is bound, then all of the lazy sequence must be stored

10:24 because it is accessible via the head

10:24 if you print the lazy sequence in its entirety, then the whole thing will be realized

10:25 if you instead print as you process, and don't hold onto the head, then lazy sequences can actually help you reduce memory usage

10:25 this means not binding the entire sequence, instead using it as it is generated

10:25 martinklepsch: justin_smith, the printing just happens as a consequence of the called function returning all the data

10:26 justin_smith: (let [r (range)] (map f r)) <- this eats up heap

10:26 (map f (range)) <- this doesn't neccessarily eat up heap

10:26 in the second case, clojure knows that nobody can actually access the previous elements of (range) so it can let them be collected

10:27 martinklepsch: and the repl does what you just described I think, i.e. it waits until the function is done and then attempts to print it all

10:27 justin_smith: it does the first thing, holding onto the entire lazy-seq

10:27 you should print element by element

10:28 martinklepsch: yeah

10:28 justin_smith: (if you want to conserve mem)

10:28 martinklepsch: think I understood how to fix it, thank you!

10:28 (inc justin_smith)

10:28 lazybot: ⇒ 42

10:28 martinklepsch: hah!

10:29 justin_smith: np

10:29 martinklepsch: I always saw people doing that, hope it's fine that I just did it :)

10:29 justin_smith: yeah, it's a meaningless number, but it's all good

10:32 mikerod: Non-dynamic vars still are deref'ed every time they are accessed (as long as their value is not inlined) correct?

10:32 So I write: (defn my-test [x] (some-other-fn x))

10:33 And call: (my-test 5) ;= `some-other-fn` is deref'ed during evaluation right? This is true for the AOT-compiled version of this `my-test` fn as well right?

10:33 I have done some digging and I believe this is accurate.

10:34 And it also is the only way I could see something like `alter-var-root` or `with-redefs` to work to change the behavior of vars referenced in the BodyExpr of other fn's

10:34 Glenjamin: you are correct

10:36 agarman: it's a bit more subtle though

10:37 clgv: mikerod: correct but there is a slight problem if the first function was a primitive one (i.e. primitive long or double in its signature)

10:37 agarman: ,(def *name* "world")

10:37 clojurebot: #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)>

10:37 clgv: ,(def a 1)

10:37 clojurebot: #'sandbox/a

10:37 clgv: interesting

10:38 agarman: if you are in a repl and redefine a var as dynamic

10:38 Glenjamin: ,(do (def a) (identical? a (deref (var a)))

10:38 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

10:38 agarman: any existing references to the var will continue to lookup the original var

10:39 that is, non-dynamic vars get cached

10:39 static vars get cached

10:39 dynamic vars do not

10:39 mikerod: Hmm, interesting.

10:40 So a static var really shouldn't be attempted to be redefined in "production" code it would seem.

10:40 Since it seems a bit risky on the scenarios where it may not be re-looked-up

10:41 I have heard it is "bad practice", but I'm just trying to think if this relates to some reasons why.

10:41 agarman: you can re-point an existing var

10:42 you just can't put a new var the the same symbol in the namespace and expect to have occurring usages of that symbol to point to your new var...unless you're var started out as ^:dynamic

10:43 there is a nice clojure/west video that describes how all this works much better than I could in IRC :-)

10:44 mikerod: agarman: Yeah, that makes sense. I can dig for the video and see if I've watched it before. If it is pretty new, chances are I haven't.

10:45 agarman: I'll pass the link, just looking for it right now

10:45 https://www.youtube.com/watch?v=8NUI07y1SlQ

10:46 https://www.youtube.com/watch?feature=player_detailpage&v=8NUI07y1SlQ#t=443

10:46 that's roughly where he starts talking about static vs dynamic

10:46 if you're impatient :-)

10:46 mikerod: hah, thanks for the insight.

10:47 agarman: yw

10:47 mikerod: This looks good and I haven't seen it before. I'll check it out.

10:52 martinklepsch: justin_smith, this nrepl server stuff gets me really excited

10:52 makes me understand this whole "modify running programs" thing

10:53 justin_smith: martinklepsch: yeah, it is handy - I typically have a conditional block that starts up an nrepl server based on an env var in pretty much every top level project

10:54 martinklepsch: justin_smith, yeah, makes perfect sense

10:56 that would pretty much be my main function I guess ;D

10:57 justin_smith: next step after that: once a function misbehaves in a way you don't understand, go into its namespace at runtime and (def debug (atom {})) and then add apropriate calls to (swap! debug assoc (java.util.Date.) ["description of place" some values at this place])

10:57 and then use your repl foo to investigate the values going on :)

11:05 AWizzArd: core.async: put! / take! vs. >! / <! — what are the differences?

11:06 Is (put! my-chan 15) the same as (go (>! my-chan 15))?

11:06 teslanick: put! and take! can be used outside goblocks

11:06 And don't park

11:07 note that take! takes a callback function to avoid parking for information.

11:08 AWizzArd: How can put! *not* park if there is nobody reading from the chan?

11:08 teslanick: It also takes a callback if you care about when something is removed from the channel

11:09 put! and take! are (at least from the examples I've seen) used on the edges of your core.async machine in parts of your system that need to operate asynchronously

11:10 Note that if you want to park, you can use >!! and <!! outside a goblock. Probably not a good idea, but...

11:10 AWizzArd: I’m not sure if it is otherwise equivalent to (go (>! my-chan 15)).

11:11 teslanick: put! and (go (>! ...)) aren't equivalent. They do different things, which is why they have different names/idioms. ;)

11:12 ttallman: quit

11:38 technomancy: I ... uh http://i.imgur.com/zfqbtYL.png

11:38 agarman: lmao

11:42 clgv: awesome :P

11:42 bbloom: heh

11:50 tbaldridge: I actually heard someone use an argument once that "OOP may be more verbose than FP, but if all programmers moved to FP, then we'd have an overpopulation software engineers, and I'd have to fight harder for a job".

11:52 teslanick: Because less code would need to be written to solve the same problems?

11:53 Glenjamin: i'm not sure that's possible

11:54 the overpopulation bit

11:54 we'd just make more things

11:54 tbaldridge: agreed. but I pretty much gave up at that part of the argument.

12:01 technomancy: there's actually a really interesting paradox around that

12:01 https://en.wikipedia.org/wiki/Jevons_paradox

12:01 tbaldridge: next time you see him, you can point him to wikipedia and 19th-century coal consumption

12:02 Glenjamin: seems to apply to computer gui apps too

12:03 joegallo: ugh, it's the old "if everyone has fast-pass/ez-pass, then the traffic will be on the streets rather than at the toll lanes" argument

12:03 barf

12:05 bbloom: technomancy: that's an interesting article. thanks

12:06 joegallo: now if you'll excuse me, i'm going to go stimulate the economy by burning down a bunch of buildings

12:07 hiredman: maybe start a few wars

12:07 mikerod: I launch the REPL with some AOT-compiled clj record types on the classpath. When attempt to reload this record, I am able to create new instances of the same class that are loaded with a DynamicClassLoader. However, when I do (.getClassLoader some.class.Name) in the REPL, it is still resolving to the original class loaded on the AppClassLoader.

12:08 *by "same class" I meant the redefinition of the same class name.

12:09 bbloom: tis same sort of stupid broken thinking is what causes massively successful companies to fail to innovate

12:09 mikerod: The consequence of this is that in my REPL, I construct (new some.class.Name) and (some.class/->Name) and get instances of 2 different classes.

12:10 bbloom: they hold on to their initial successes and think the world won't change around them, assuming that b/c their inventions produced wealth in the past, that they will always be their primary sources of wealth... which becomes a self-fulfilling prophecy by being their ONLY source of wealth

12:11 technomancy: bbloom: yeah, I figure Jevon's paradox is also relevant to code.org naysayers

12:11 bbloom: technomancy: very.

12:11 cbp: java.lang.ThreadDeath

12:12 bbloom: cbp: argh. i hate that ThreadDeath exception

12:12 cbp: such description, very understandable

12:12 bbloom: if you catch Throwable, you actually need to remember to RETHROW ThreadDeath, otherwise you may never get out of an infinite loop

12:13 cbp: =/

12:13 mikerod: tbaldridge: that argument made me laugh; but in a bad way

12:15 tbaldridge: I think the world would be a better place if everyone knew at least some coding. And no, we wouldn't have a problem with demand, because just like some people who write hate writing (me), we'd have people who knew how to code, but don't understand enough theory to do it as a profession.

12:15 That is to say, anyone can code, but learning how to apply it properly takes time, like any profession.

12:17 mikerod: tbaldridge: agreed

12:18 angusiguess: @tbaldridge I guess one part of it is people's expectation that it be professional. Something not shared with, say, musical or artistic aptitude.

12:22 mikerod: So, does anyone know why the REPL doesn't eval Class literals as the newest definition of dynamically loaded types when the class was loaded initially by the AppClassLoader?

12:22 To re-phrase my questions/observation on this.

12:22 borkdude: is it possible to find usages of a function in cider?

12:25 Bronsa: mikerod: http://dev.clojure.org/jira/browse/CLJ-979 probably related

12:27 mikerod: Bronsa: nice, this does seem to be on-topic

12:27 thanks!

12:27 It's a bit annoying. I just noticed it because I get test failures from reloading the defrecord

12:28 because of an instance? check failing after that, but it is in the same ns as the defrecord, so I was expecting them to stay in sync.

12:28 Fun

12:29 seangrove: I wonder how much bootstrapped cljs would help people get on the cljs wagon

12:30 Bronsa: mikerod: me & ambrosebs looked into this a bit a while ago while he was porting core.typed to tools.analyzer

12:30 bbloom: seangrove: probably not at all... why do you think it would?

12:30 bhauman: seangrove: do you have something particular in mind?

12:30 Bronsa: mikerod: another relevant ticket is probably http://dev.clojure.org/jira/browse/CLJ-371 which unfortunately got declined

12:31 mikerod: Bronsa: cool, it is all making sense now

12:32 Glenjamin: so the general theme seems to be you can AOT, or repl - but not really both

12:32 Bronsa: Glenjamin: yeah

12:32 mikerod: AOT is full of surprises

12:32 Glenjamin: which means you can't patch a protocol definition in a live app

12:32 seangrove: bbloom: A node.js developer is going to be pretty unnerved by the amount of jvm tooling to get start with cljs

12:33 bbloom: Just removing that initial barrier, making it easier to get up and running

12:33 cbp: Is it possible to have a cljs repl when opening a file:// from a browser?

12:33 Glenjamin: jvm peeps probably underestimate how foreign all the jvm stuff is if you don't have a java background

12:33 nullptr: seangrove: as is a jquery developer

12:33 cbp: I mean I guess I know it's possible since Lighttable does it but is it possible with austin?

12:34 bbloom: seangrove: meanwhile, node.js requires a lot of C++ tooling to get started.... this is a presentation/readme problem and maybe automation problem, not a justification for self-hosting

12:34 nullptr: i'm very savvy with jvm stuff, have a reasonable amount of clojure experience, and am an expert in g closure, and i still found getting started with cljs maddening

12:34 Glenjamin: bbloom: not to run the JS

12:34 bbloom: ... and this is coming from a guy wants that :-P

12:34 Glenjamin: it's a single binary

12:35 bbloom: Glenjamin: not if you actually want to do anything useful it isn't... you also need the package manager: npm

12:35 seangrove: bbloom: Not a justification, of course not. Just a nice side-effect that it becomes far more portable for other envs

12:35 Glenjamin: ok, 2 binaries

12:35 bbloom: Glenjamin: bottom line: you need an installer

12:35 Glenjamin: there's not that many libs that need to c++ build

12:35 bbloom: what it installs is moot

12:35 seangrove: I know almost nothing about node.js personally, and I'm frustrated that I have to use npm sometimes

12:35 bbloom: npm is atrocious

12:35 expez: seangrove: any plans on adding a bit more documentation to your om-draggable component, it wasn't as easy as I'd hoped to put it to use.

12:35 Glenjamin: npm is the best :(

12:35 bbloom: Glenjamin: no, it really isn't

12:35 cbp: but npm solved dependency management

12:36 bbloom: lol

12:36 Glenjamin: no dependncy conflicts is great

12:36 seangrove: But it's the same frustration that node devs would experience on the cljs side. If you gave them the foundation, they'd hack cljs up in their own npm way and run with it

12:36 expez: No, I'll probably just remove it. Been working on a much more all-encompassing approach to this stuff

12:36 expez: seangrove: aight, good to know!

12:36 seangrove: expez: I could probably change it a bit though so normal Om apps could use it, on reflection

12:36 Glenjamin: bbloom: what problems do you have with npm? i've generally found using it to be great

12:37 cbp: Is there a tool thingy that takes an html file as input and serves it through whatever web server?

12:37 stompyj: Glenjamin: it’s *always*[0] down and/slow [0] always meaning at least 2x a month

12:38 and when you’re pushing to production 10x a day

12:38 and deploys hang and/or outright fail

12:38 Glenjamin: then you use a caching proxy :s

12:38 don't rely on a free external service for production deploys :)

12:38 i got the impression bbloom had issues with the tool itself

12:38 stompyj: the fact it could have learned from rubygems.org and bundler

12:38 bbloom: even ignoring the downtime, i've had massive problems actually *using* it

12:38 Glenjamin: i assume people deploying clojure a lot use nexus instead of maven central

12:39 stompyj: and seemingly didn’t, isn’t encouraging

12:39 oh, i’ve had tons of issues with it as well

12:39 bbloom: the node_modules thing is attrocious. there is nothing like bundler's lock files, which is also a complaint i have about lein

12:39 stompyj: one of my devs couldn’t create an account for weeks

12:39 with no error returned

12:39 Glenjamin: bbloom: `npm shrinkwrap` does exactly what lock files do

12:40 the local node_modules thing is my favourite bit :s

12:40 bbloom: Glenjamin: never head of shrinkwrap, looks like it isn't standard

12:40 Glenjamin: it's in the core package, but doesn't run unless you ask it to

12:41 bbloom: the package.json format, being json, can't have comments in it... which is insane

12:41 technomancy: bbloom: aren't lockfiles just there to work around the fact that everyone uses version ranges in bundler?

12:41 bbloom: technomancy: i dunno. i don't like version numbers, i like sha1s

12:41 i like refspecs

12:41 technomancy: what's a refspec?

12:41 bbloom: https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html

12:41 technomancy: oh, sure

12:41 bbloom: see my rant on semver: http://www.brandonbloom.name/blog/2013/06/19/semver/

12:41 Glenjamin: not having comments i can see, but it's more of a manifest rather than a config file - there shouldn't really be anything complex in there

12:42 bbloom: Glenjamin: it doesn't need to be complex to say "TODO: remove this dep"

12:42 technomancy: bbloom: are you ranting about publishers who use semver or people/tools who assume others use semver?

12:42 Glenjamin: i can see that

12:42 bbloom: technomancy: tools that assume semver

12:43 technomancy: right

12:43 Glenjamin: although echo "TODO: remove dep x" >> README.md is roughly as useful

12:43 bbloom: the node_modules directory is terrible b/c it confuses every damn tool i have... i have to add ignore rules to so many configs

12:43 technomancy: bbloom: version numbers are like ^:private imo; they contribute intent, but relying on their mechanism is madness.

12:43 bbloom: technomancy: indeed

12:43 technomancy: s/contribute/communicate/

12:44 Glenjamin: my personal approach is ranges for libs that trust/assume semver - but lock down numbers in applications and check it works

12:44 technomancy: seems silly to be "against semver" for that reason though

12:44 martinklepsch: just trying to setup that repl server I found the following to launch it in main: https://groups.google.com/forum/#!topic/clojure/wWunRvmX5Co — but I wonder why that let binding & Thread/sleep is used?

12:46 bbloom: technomancy: you'll see my rant is balanced :-P

12:46 stompyj: Glenjamin: although, in all seriousness, “don’t like the package manager endorsed by the language? then don’t use it!” is a very dangerous stance for a community to take

12:46 technomancy: bbloom: I can see it there because I know what I'm looking for, but I think it would be easy to miss

12:46 stompyj: especially when go exists

12:47 Glenjamin: stompyj: i don't follow? if you don't like rubygems, you probably should use ruby

12:47 etc

12:49 stompyj: In general, the JS/node community has had flippant responses to real concerns by people trying to use the technology stack

12:49 the net result of that is going to be an exodus to Go, or a similar language

12:49 bbloom: i also generally hate tools that have interactive defaults & no obvious master flag for "I AM SCRIPTING THIS THING"

12:50 Glenjamin: go's dependency management story appears to be "you always get master, better hope no-one breaks you"

12:50 justin_smith: martinklepsch: I think the sleep is just for keeping the process going

12:50 technomancy: Glenjamin: no one would ever do such a horrible thing as break backwards-compatibility

12:50 Glenjamin: "If a library creator doesn't have the discipline to follow proper release practices and the idioms in the Go community, I think it can be argued that you probably don't want to be using their code in production either."

12:50 bbloom: yeah, which is why go-get is terrible, by why go is awesome for big company wide code bases (which i'm not a believer in, but understand it)

12:50 Glenjamin: thats a quote from the go community

12:50 justin_smith: martinklepsch: the let block is likely the trace of an incomplete refactoring

12:51 technomancy: Glenjamin: http://p.hagelb.org/oh-yeah.gif

12:51 high-larious

12:51 Glenjamin: anyway, dependency management is hard

12:51 martinklepsch: justin_smith, would you mind pasting me some code how you did that?

12:51 justin_smith: martinklepsch: I think both can be eliminated, since the l in repl is for loop

12:51 technomancy: Glenjamin: "Life is hard. But it's a lot harder if you're stupid."

12:51 Glenjamin: heh

12:51 technomancy: I forget who said that.

12:51 martinklepsch: justin_smith, I tried it earlier without the sleep and I think it didn't work

12:52 justin_smith: (start-server :port 42042) should suffice - though you can add the sleep if it is exiting too soon on you

12:52 or a while loop that sleeps etc.

12:52 martinklepsch: deploying an uberjar is very cool btw :)

12:52 justin_smith: martinklepsch: yeah, definitely the RIGHT WAY™

12:53 technomancy: bbloom: because at a company you can literally beat a path down to the offender's cubicle with pitchforks and torches?

12:53 martinklepsch: justin_smith, it's so crazy simple... I'm coming from ruby/rails and that's quite different :D

12:53 Glenjamin: are uberjars always AOTed, will you run into the dynamic reload of Record issue described above?

12:54 technomancy: Glenjamin: you can use uberjars without AOT

12:54 Glenjamin: ah neat

12:54 technomancy: you just have to use clojure.main as your entry point

12:54 justin_smith: martinklepsch: yeah... their deployment story is crazy - but look how many startups it created :P

12:54 technomancy: I don't know that I'd recommend it though; afaik the pitfalls of AOT don't apply in production

12:55 Glenjamin: unless you want to mess around in a repl on production i guess

12:55 technomancy: justin_smith: /me whistles innocently

12:55 Glenjamin: unsure if i do yet :)

12:55 justin_smith: martinklepsch: it is harder to make a business model out of "send us a jar and we will execute it"

12:55 technomancy: Glenjamin: true, you do have to be more careful with a repl

12:55 martinklepsch: justin_smith, looks like my previous try was just fine :)

12:57 rasmusto: just made this typo: lein eastwoord

12:57 justin_smith: haha, sounds dutch

12:58 rasmusto: was thinking of http://en.wikipedia.org/wiki/Die_antwoord maybe

12:58 dunno why I'd have muscle memory for that

12:58 justin_smith: or like an insane white south african hiphop performance art project

12:58 jynx

12:58 rasmusto: ,(range 10)

12:58 clojurebot: (0 1 2 3 4 ...)

12:58 bbloom: technomancy: if you "always ship master" and have a giant perforce tree, then everything is effectively defacto vendored anyway

12:59 technomancy: and also pitchforks + cubicles

13:00 technomancy: bbloom: pretty soon the pitchfork thing will be possible in the OSS world with drone attacks though

13:00 seangrove: Necks to throttle.

13:01 * bbloom registers droneforks.com

13:01 * seangrove imagines a drone that cooks and feeds me

13:01 TimMc: to whom?

13:01 rasmusto: seangrove: look in the mirror

13:01 seangrove: Wonderful mixing of third and first person there...

13:02 rasmusto: seangrove: jokes :)

13:02 seangrove: rasmusto: I need to delegate!

13:02 Ordering food is easy, it's the last mile problem that hasn't been solved: take out box to mouth.

13:02 But now we have... DroneForks!

13:02 rasmusto: I always picture that wallace and grommit morning routine

13:03 machine thing

13:07 martinklepsch: justin_smith, how do you access this nrepl in your prod env then? do you use ssh tunneling?

13:07 (sorry if you mentioned that earlier)

13:08 justin_smith: martinklepsch: yeah, but usually I don't end up needing a repl in prod

13:09 martinklepsch: justin_smith, currently my whole programm does nothing on it's own (which is intended) so having a repl seems like the best way to control that remotely

13:10 technomancy: martinklepsch: you could use something like xmpp too if you want easier control from a mobile

13:10 that's what I do with the bot in my lab

13:10 martinklepsch: technomancy, that sounds pretty cool but also a lot more complex

13:11 technomancy, what do you send via xmpp then actually?

13:11 technomancy: martinklepsch: yeah, it means you have to decide up front which commands you want to expose over chat

13:11 in my case it's just temperature querying and setting

13:12 (also this is erlang rather than clojure, but whatever)

13:12 martinklepsch: technomancy yeah ok, thought so

13:12 technomancy: martinklepsch: actually... you could easily do a full repl over xmpp

13:12 or you could do a repl that's restricted to only call functions in a given namespace

13:13 justin_smith: oh yeah, xmpp has the security layer taken care of

13:13 technomancy: https://github.com/technomancy/mire/blob/master/src/mire/commands.clj <- this does something like that

13:13 justin_smith: is there an easy xmpp lib for clojure?

13:14 martinklepsch: I'm fine with the repl and tunneling

13:15 although I'm having trouble fguring out how to map a port on a remote machine that only listens on localhost to a local port on my machine :/

13:15 justin_smith: ssh -L handles that pretty easily

13:18 ssh -L local-port:127.0.0.1:remote-port <host>

13:18 martinklepsch: justin_smith, yeah I have something like this but doesn't seem to access the port through localhost on the remote machine: ssh -L root@host -L 4242:host:42042 -N

13:18 justin_smith: no, 127.0.0.1

13:18 is manditory - means local

13:19 host means treat it as a remote access, which is denied which is the reason for the tunnel

13:19 martinklepsch: ah !

13:19 thank you!

13:19 works now

13:19 justin_smith: I guess you can also specify localhost instead of 127.0.0.1 but 127.0.0.1 may work in some circumstances where the host is misconfigured

13:20 martinklepsch: justin_smith, yeah was thinking in that direction just wasn't aware that I can put in 127.0.0.1 in that place

13:21 justin_smith, you've helped me tons today! thanks so much!

13:22 justin_smith: np

13:25 martinklepsch: sometimes when I run java -jar my-thing.jar I can't cancel it with ctrl-c anymore, anyone an idea why that is?

13:26 justin_smith: martinklepsch: are you running agents? are you catching Throwable?

13:26 anyway, kill -9 is the brutal way, which almost always works

13:27 martinklepsch: yeah, having some (catch) statements in there

13:27 justin_smith, yeah that was what I did the first time. just wondered why that sometimes happens and sometimes not

13:27 justin_smith: if your catch is Throwable, you should rethrow if you get the interrupt signal

13:32 martinklepsch: cheers everyone for being so incredibly helpful today! you made my day (really!) have a good day/evening!

13:45 guns: ambrosebs: I was able to build that Closeable linter with tools.analyzer; it was just as easy as you said. thanks again for the tip

13:45 ambrosebs: guns: very nice

13:56 nillkill: hmm is there an easy way to load a var from a .clj file and get the name of the var? So something like (load-file https://github.com/Parsely/streamparse/blob/master/streamparse/bootstrap/project/topologies/wordcount.clj) then pull the name of the var (“wordcount” in this case) as well as the evaluated form?

13:57 or a better question perhaps, should we be doing this w/ something other than (var-get (load-file …))

14:00 i was hoping I could get (:name (meta (var-get (load-file …)))) but that doesn’t seem to work

14:04 Glenjamin: nillkill: are you expecting the var to be the last form in the loaded file?

14:05 nillkill: yeah, should only ever be one var in the file. looks like (meta (load-file “file..clj”)) will work

14:05 Glenjamin: i feel like that should work if you leave out the var-get

14:05 yeah

14:07 technomancy: http://www.clojure.tn/images/stk-trc.png <- whoa, is this what you get with cider out of the box now?

14:07 ucb: technomancy: yes

14:07 hiredman: :(

14:07 ucb: technomancy: latest which is 0.7.0-alpha I believe

14:07 hiredman: hiding frames

14:07 technomancy: fancy ultra fresh

14:07 mstang: Best Java decompiler?

14:08 technomancy: I assume those are hyperlinks?

14:08 nillkill: Glenjamin: how would I still evaluate that var after the load-file?

14:08 i guess do a get-var later on

14:08 Glenjamin: if you have name and ns, you should be able to fish it back out

14:09 or (let [var (load-file)] { :name (:name (meta var)) :var var })

14:09 something like that

14:09 ucb: technomancy: which ones? the headings? Yes, they hide/show different sections of the stacktrace

14:11 technomancy: ucb: yay, interactivity.

14:11 stompyj: checking out that new podcast that dnolen_ did, dude is a beast

14:11 ucb: technomancy: yayayayayaya indeed

14:11 technomancy: ucb: do you know if that's happening server-side or client-side?

14:12 ucb: technomancy: I haven't a clue. I'm just a user :)

14:12 mstang: stompyj: was that the interview or does he have something new?

14:13 stompyj: mstang: the interview at javascript jabber

14:13 mstang: stompyj: I am about 1/3 of the way through, he is a beast!

14:15 stompyj: the best part about the clojure community is the ability with which the stewards of different parts of the ecosystem can articulate why X thing is important

14:15 feels like the early rails days

14:18 SegFaultAX: What would you call group-by where the keying function returns multiple groups for a given element?

14:18 group-many is the best I can do.

14:19 teslanick: 'categorize' ?

14:21 SegFaultAX: teslanick: I like it! Thanks.

14:26 amalloy: SegFaultAX: i'm curious what your implementation of that looks like. seems like there are a number of plausible approaches

14:28 SegFaultAX: amalloy: I can show you the sauce if you want.

14:28 amalloy: https://gist.github.com/SegFaultAX/3f2657c6c338691d812c (Python)

14:29 amalloy: ah. i just sketched it out in clojure, SegFaultAX: https://www.refheap.com/649f9d50c4f7df0bd835dd7ca

14:33 teslanick: til about fnil

14:33 nullptr: ,(doc fnil)

14:33 clojurebot: "([f x] [f x y] [f x y z]); Takes a function f, and returns a function that calls f, replacing a nil first argument to f with the supplied value x. Higher arity versions can replace arguments in the second and third positions (y, z). Note that the function f can take any number of arguments, not just the one(s) being nil-patched."

14:34 teslanick: So (fnil conj []) returns a version of conj that will use an empty vector if the first argument to it is nil.

14:35 Frozenlock: In compojure, do I need to specify a 'not-found' route everytime I use `context'?

14:36 amalloy: Frozenlock: i can't think why you would do so

14:37 Frozenlock: I ask because when I use (context "/some-url" ....), if a page doesn't exists under "/some-url/..." I just get a blank page. :-/

14:37 amalloy: Frozenlock: you want a single not-found route after all of your routes, probably

14:38 Frozenlock: amalloy: Yes, that's how things are for now. A single not-found route at the end of my app-routes

14:38 amalloy: (routes (context "/foo" ...) (context "/bar" ...) not-found)

14:38 i don't think context surreptitiously inserts a blank page. if you're getting one, you put it there

14:39 Frozenlock: hmm...

14:40 dbasch: Frozenlock: what does the response look like? A blank page could mean many things

14:44 Frozenlock: dbasch: http 200

14:44 Glenjamin: anyone familiar with test.check who knows how i can run a (defspec) in isolation at the repl?

14:45 reiddraper: Glenjamin: run the test as a function: (test-ns/my-test)

14:45 Glenjamin: hah, d'oh

14:45 thanks

14:45 reiddraper: np

14:46 Glenjamin: is there a neat way to feed a failure case back in to the body, without extracting to a function?

14:46 my sequence is something like: check => fail, add-watch, run-once

14:47 reiddraper: Glenjamin: no way that i'm aware of, without extracting to a function

14:48 Glenjamin: ok, thanks

14:50 reiddraper: Glenjamin: i think you'll find that extracting it into a function is a good idea anyway

14:51 Glenjamin: mm, i started like that, but then folded them into the defspec as it was only 3 lines

14:52 being able to do something like (check-case (:smallest result)) might be quite nice

14:57 Frozenlock: amalloy: You were right, I added a allow-cross-origin middleware and it was messing with the headers

15:00 roppongininja: Guys I'm really commited to JVM and I want to learn my first functional language - should I start with clojure or scala?

15:02 ystael: roppongininja: Learn enough of each to make an educated choice!

15:02 bbloom: roppongininja: yes.

15:02 but you're in #clojure, so the answer should be clear

15:02 amalloy: roppongininja: you're asking here instead of in #scala. you know what you want in your heart of hearts

15:03 llasram: It might have been a loyalty test

15:03 bbloom: llasram: here we are only loyal to shit that works

15:03 technomancy: amalloy: he could be asking in both

15:03 dbasch: I agree that you should try both and decide for yourself

15:03 amalloy: technomancy: yeah, but i'm not in #scala so i think it probably doesn't exist

15:04 * technomancy nods

15:05 dbasch: having a mixed Scala / Java codebase is not fun, for example

15:05 technomancy: that said, the jvm seems like a weird thing to be committed to

15:05 just kind of going forward assuming you'll never have requirements for low-memory or tight C integration

15:06 mstang: Scala seems a bit on the complicated side of things

15:06 I took a two day class ;-)

15:06 dbasch: technomancy: it depends on where you work. Some companies require that you give their devops a jar / war that they can toss into production, and they don’t care how it was created

15:07 technomancy: dbasch: sure, if you've decided to specialize solely in long-running server software

15:07 roppongininja: dbasch: I don't need to learn this for work (maybe for a future one) I just want to try functional programming by writing a simple bitcoin trading bot :)

15:07 dbasch: I dont care how long it takes its just for fun

15:08 technomancy: dbasch: it makes more sense for a company to be committed to a platform than for an individual, anyway

15:08 bbloom: roppongininja: if you just want to learn, and you've never done a lisp before, clojure will be a bigger and more rewarding learning experience

15:08 roppongininja: technomancy: I've never done any other programming than Java/c/python/js

15:08 and c#

15:08 technomancy: and loyalty to a company is pretty old-fashioned these days

15:09 roppongininja: so I've never done any functional programming

15:09 dbasch: roppongininja: in Scala you always have the temptation to code as if it were Java, you have to be more disciplined to stay functional

15:09 Scala is an easier sell to organizations where most developers have a Java background for that reason

15:10 * dbasch has seen some atrocious Scala code

15:10 roppongininja: dbasch: I know that scala is better when looking for a job but I'm not looking for a new one

15:10 bbloom: dbasch: s/Scala //

15:12 dbasch: bbloom: ok, atrocious in a very specific way :P

15:12 bbloom: dbasch: that's for sure

15:12 dbasch: e.g. people transforming a collection by iterating over every item and copying the result of a function into a new collection

15:13 fowlslegs: What is the correct syntax for recur when I want to assign the value of one var to another. Say I have (loop [x 1 y 2] (if (= x 2) [x y] (let [u 4] (recur (inc x) (y u)))))

15:13 cbp`: why can't cljs get a repl to a browser-opened html file?

15:13 fowlslegs: Except the (y u) is incorrect syntax. What if I want 4 bound to y for the next loop?

15:14 amalloy: just...(recur (inc x) 4)

15:14 you just put values there. no names

15:14 fowlslegs: purrrfect

15:14 bbloom: cbp: has to do with same domain policy

15:14 dbasch: roppongininja: a bitcoin trading bot in clojure would be a fun project

15:14 roppongininja: are there any beginners here?

15:14 amalloy: yes

15:15 roppongininja: I don't know anything about clojure but if someone's a total no-life like me we could team up and write a free open source btc trading bot:)

15:16 I guess that if you want to learn that's the fastest way - learning by doing :)

15:16 dbasch: roppongininja: I don’t know about #scala, but if you start something and share your code here you’ll get tons of good feedback

15:19 nullptr: roppongininja: you can get from a->b down either path, but i do think you'll have more fun with clojure

15:21 roppongininja: Should I use emacs for clojure? I've been a intellij idea user so far

15:21 nullptr: have you used emacs before?

15:22 it's a nice clojure environment, but the learning curve is, well ... http://ergoemacs.org/emacs/i/emacs_learning_curves.png

15:22 roppongininja: nullptr: yes for a max of 24h total, so I know close to nothing about it, I've been using vim for a long time though

15:22 nullptr: I know that picture

15:22 bbloom: ~fireplace

15:22 clojurebot: Huh?

15:23 nullptr: https://github.com/tpope/vim-fireplace

15:23 bbloom: clojurebot: fireplace is github.com/tpope/vim-fireplace

15:23 clojurebot: 'Sea, mhuise.

15:24 dbasch: roppongininja: by now there are some decent choices besides emacs, including LightTable and Cursive (IntelliJ)

15:24 roppongininja: dbasch: and which one are you using

15:24 dbasch: roppongininja: I use Emacs personally

15:25 technomancy: roppongininja: don't learn emacs and clojure at the same time

15:25 zerokarmaleft: roppongininja: Cursive is quite capable

15:25 cbp: Once you go into the emacs rabbit hole you never come back

15:25 roppongininja: there's this thing called evil-mode

15:25 technomancy: emacs will be there waiting for you once you get decent at clojure

15:25 zerokarmaleft: evil-mode is terrible

15:25 bbloom: roppongininja: just use what you know

15:26 and if you don't know anything else, just use light table, since it's so easy to get started

15:26 nullptr: i agree with bbloom, LT is a great low hassle startup env

15:27 and as technomancy says, emacs will be there waiting for you ... probably even if you wait a couple of decades

15:27 cbp: you probably will only need lein repl for a good while anyway

15:27 roppongininja: Ok I will give LT a try then!

15:28 dbasch: roppongininja: btw, I’ve written some bits of bitcoin-related code in clojure, let me know when you have specific questions

15:28 kenrestivo: Raynes: would it be an abuse of irclj to use it as a gateway from irc to another chat system, which i think would require multiple connections from ircj (one for each user on the other system)?

15:29 Glenjamin: i've been fairly happy with the latest LT - it now seems to have most of the "proper editor" bits

15:30 roppongininja: dbasch: do you mind adding me on skype?

15:30 dbasch: roppongininja: I don’t use skype much, but you can mention me here or on Twitter (same handle)

15:31 mstang_: LT isn't a great editor, but I like it's interactivity better than Emacs or Vim

15:31 roppongininja: mstang_: I've got sublime text 2 by the way is that any good

15:32 or shall I ask is it better than LT

15:32 mstang_: roppongininja:I have heard that people like it, the nice thing about LT is that you can edit, CTRL-ENTER and see the result inline

15:33 Cursive is looking interesting, haven't tried it yet

15:35 roppongininja: I don't think sublime is as interactive from what I have heard, never used it

15:35 {blake}: LT's not bad. The inline has some use but limited (to me so far).

15:35 mstang_: roppongininja: If I have some fancy editing, I open Vim or gedit depending on what kind of editing...

15:36 roppongininja: but then I go back to LT

15:36 SegFaultAX: amalloy: Reasonable implementation?

15:36 amalloy: I don't really know how much python you do. :D

15:36 But you get the idea, right?

15:36 mstang_: roppongininja: btw, I keep the Emacs cheat sheet open on my desk ;-)

15:38 Glenjamin: the watch feature in LT is quite neat

15:39 nullptr: Glenjamin: is that like cider-tracing?

15:39 Glenjamin: highlight form, add watch, see values passing through on eval?

15:44 amalloy: SegFaultAX: i don't do any python. implementation seems fine, although the problem is pretty bland if you can just mutate things

15:45 i wouldn't have created the variable `keys` at all: just write `for key in fn(e): ...`

15:48 you can also use setdefault instead of get, to simulate fnil and remove some more nonsense

15:48 ie, replace lines 8-10 with acc.setdefault(key, []).append(e)

15:49 Glenjamin: setdefault is a weird function

15:51 amalloy: what. is gist broken? when i click the Fork button on SegFaultAX's gist, i get a 422 Unprocessable Entity

15:51 dinduks: Hi folks. Can some please share some piece of code that shows how are operations on collections usually nested in Clojure? It's hard to find this with a search engine.

15:52 amalloy: "The change you wanted was rejected. Maybe you tried to change something you didn't have access to."

15:52 Glenjamin: amalloy: works for me :s

15:52 dinduks: what do you mean by nested?

15:52 tbaldridge: dinduks: operations are nested?

15:53 dinduks: Glenjamin: like a map on a filter on another map, etc.

15:53 tbaldridge: (->> [1 2 3] (map inc) (filter pos?) (filter even?) (map dec))

15:53 Bronsa: gist

15:53 Glenjamin: generally you just nest them, you can improve readability with intermediary variables using let, or via ->>

15:53 tbaldridge: , (->> [1 2 3] (map inc) (filter pos?) (filter even?) (map dec))

15:53 clojurebot: (1 3)

15:54 dinduks: How is "->>" called, so I can search it? :)

15:54 Glenjamin: threading macro

15:54 dinduks: Cool thanks.

15:55 I thought about using many `let` but then I wondered if it was a good idea to have 10 let that are simple temp variables

15:55 amalloy: i always call it the Arrow of Awesome

15:55 dbasch: dinduks: technically it’s thread-last, there’s also -> or thread-first http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E

15:56 amalloy: dbasch: "technically" it's ->>. thread-last and thread-first are two colloquial names that some people use

15:56 dbasch: amalloy: I mean as opposed to threading macro

15:57 no nitpicking, just trying to clear the confusion because dinduks would encounter -> when searching for threading macro

15:57 Glenjamin: some subjective combination of nesting, threading and let usually produces something readable

15:57 amalloy: but how sad would he be to find information on ->? not sad at all

15:59 dinduks: :)

15:59 Thanks everyone. I think ->> with some line breaks if my (fn …) are long will do the trick.

15:59 amalloy: sounds about right, Glenjamin

16:00 llasram: + splitting into multiple functions

16:00 + our fanatical devotion to the Pope

16:00 ystael: llasram: but everyone expects the threading macro

16:00 amalloy: llasram: nobody must know our secret nickname for rich hickey

16:01 llasram: heh

16:03 stompyj: If theres any “The State” fans here: HEEYYYYY, ITS A DA POPAAAA

16:25 Glenjamin: i seem to have a complete mental block here, i'm wanting to return a reverse lazy sequence from a java.util.ArrayList - but i can't seem to think what to use

16:25 i assumed that lazy-seq was the right thing, but that doesn't fit at all

16:26 oh wait, i think i got it

16:35 haywood: Om question. I have a nested component structure, think table -> row -> cell. The cell needs a bit of 'global state but it feels wrong to pass that down in a cursor when the components above don't need it at all

16:38 seancorfield: haywood: perhaps a better Q for the #clojurescript channel?

16:39 haywood: seancorfield: will do! thanks

16:40 microamp: curious, how often do you guys use loop/recur?

16:41 Glenjamin: probably too often

16:41 technomancy: microamp: very rarely

16:41 AimHere: When I can't think of a way of using 'reduce'

16:42 Glenjamin: i think the only one i didn't factor away was reducing a huge collection into two big collections

16:42 microamp: thanks, just got back to learning clojure again, tempted to use loop/recur probably more often than i should've

16:43 technomancy: microamp: it's usually a sign either 0) you're a schemer or 1) you haven't fully internalized the seq API

16:43 or both!

16:43 amalloy: Glenjamin: that sounds like a group-by,not a loop/recur

16:44 or a reduce in the worst case

16:44 microamp: technomancy: hah, coming from python background, i guess it's more like 1 :)

16:44 Glenjamin: ~7 million records into two maps, one with ~1 mil the other with ~6 mil

16:44 clojurebot: excusez-moi

16:44 * microamp likes how technomancy labelled it as 0/1 as opposed to 1/2

16:44 seancorfield: microamp: I have a handle of loop/recurs in tight code that manipulates text (it's horribly non-functional in style but it's fast!) but otherwise I hardly have any in about 20kloc

16:44 AimHere: I'm just wondering if a third option would be 2) or 10)

16:44 Glenjamin: even with reduce, i'd have to create something to hold the two intermediaries at each step

16:45 seancorfield: 15 of them total in just over 20kloc... see, you made me go count them!

16:46 Glenjamin: two in this file :s

16:46 seancorfield: a few of those are in go loops

16:47 amalloy: Glenjamin: huh? the two intermediaries are held in the map you're reducing over

16:47 i'm curious to see this process of splitting up a collection into two that you think requires loop/recur

16:47 Glenjamin: i end up with two distinct maps

16:48 although i do ultimately return a map

16:48 hrm, let me time it

16:48 https://www.refheap.com/85264 is my other example

16:49 amalloy: this is the splitting one - https://www.refheap.com/85265

16:51 amalloy: what is with all these transients?

16:51 Glenjamin: well a) it's a large collection and b) i'd just read up on transients when i started

16:52 amalloy: anyway, this is just a reduce over (result-set-seq rs)

16:52 Glenjamin: yes, but it's faster

16:52 i did start with that

16:53 i've changed a lot of other stuff since the last slow version, i should try the seq again though

16:54 amalloy: but, really, this isn't a terrible candidate for loop/recur. squeezing it into a reduce over a pair doesn't increase readability by much, and what you have isn't already a seq

16:58 dans: evening all - so i was thinking is there a name for a composition pattern as so: (defn comp-i-dont-know? [g h] (fn [inst val] (g inst (h val)))) I'm thinking of this as composing transformations over a value before it is passed for example to a java setter.

17:01 amalloy: doesn't ring any bells for me, dans

17:05 dans: hmm, thats cool was wondering whether I was just being thick amalloy - its pretty specific, I can't think of any general use cases for such a function - useful for setters as I said, as I tend to create lots of setters via composition etc when building up java interop layers.

17:05 amalloy: i don't really understand the comparison to setters

17:06 is doto not suitable for this? doto and -> are often useful for interop

17:06 mercwithamouth: newb dev question. so i created a post route to collect data to be used in a function. i can see the post data in firebug...what would be a good way to see if it's actually touching my server code? I start the server from the repl...

17:06 dans: yes - but I like to have the power of the various map/data transformation options that are available if I generalise setters as functions

17:08 noonian: mercwithamouth: i usually write a simple ring middleware function that just prints the request and response to stdout

17:08 dans: so I use something like https://github.com/danstone/getteretta to create maps of getters setters I can then do some interesting things in my interop layers.

17:10 noonian: mercwithamouth: https://www.refheap.com/85266, then wrap your handler with that before passing it you run-jetty or w/e

17:10 mercwithamouth: noonian: hrmm... ehh hmm how can i about doing that when right now my posts are coming from client side only. i could see how that would be possible...i guess i should just add some persistence now

17:10 noonian: ok, taking a look

17:11 noonian: that will print out the data that the server receives in the request, and also what it will return to the client with the response

17:11 mercwithamouth: hmm even using the repl in light table?

17:12 noonian: yes, if you are running your server from within light table, it will print to the console so you may have to open light tables console in a tab (ctrl+space type console and the fuzzy search should find it)

17:12 mercwithamouth: ahh! gotcha!

17:12 ty!

17:13 noonian: np

17:13 Glenjamin: you can also do it with the "watch" feature

17:14 mercwithamouth: Glenjamin: watch? do tell...

17:14 Glenjamin: instead of the print statements, select the form and "add watch" - it's alt+w on my LT

17:15 then the value will be displayed inline when you make a request

17:16 mercwithamouth: nice! ok i'll try that out...be back in a few

17:16 whodidthis: whoa, i also had no idea

17:38 mercwithamouth: hmm one issue... after (start-server) in a repl...when I try to call anything on the next line it just starts opening up new tabs like crazy going to my server

17:38 is this avoidable?

17:42 ahh oops...dur

17:43 *cuts live off* -_-

17:44 PigDude: if you ever wanted to know how clojure prints dates, you didn't :P

17:45 but long story short it's simpler to parse the string out of `pr-str' than to try to do this any other way, as far as i can tell

17:46 amalloy: PigDude: simpledateformat in java is a hassle to deal with, but flexible enough to do whatever you need

17:47 &(.format (java.text.SimpleDateFormat. "kk:mm:ss") (java.util.Date.))

17:47 lazybot: ⇒ "14:44:40"

17:49 mordocai: amalloy: If there isn't a wrapper/native way to do that, there should be...

17:49 justin_smith: PigDude: clj-time helps a lot

17:50 amalloy: mordocai: that's silly. if things in java work, there's no need for a wrapper in them in clojure.core

17:50 justin_smith: the native java time code has issues, joda-time (which clj-time wraps) improves

17:50 nullptr: (inc clj-time)

17:50 lazybot: ⇒ 1

17:50 amalloy: as justin_smith says, the native java time stuff *is* pretty garbage, but wrapping garbage just gets you wrapped garbage

17:51 mordocai: amalloy: I don't know, right now I'm very new to clojure (about 1/7th through "The Joy of Clojure" as my intro) but I am all for abstracting away java as much as possible. My attitude may change.

17:52 noonian: wrapped gargabe doesn't stink as much :P having said that, clj-time is the way to go

17:53 justin_smith: mordocai: given that by using interop you can already be more concise than native java would be, and lose very little functionality, you'll be happier just learning how to do interop and being comfortable with it. It's good to fight library bloat where you can anyway.

17:57 PigDude: justin_smith: yea, but this is for the glue between clj-time :_)

18:00 justin_smith: PigDude: ahh, I had remembered clj-time having its own formatters

18:02 noonian: it does iirc

18:22 martinklepsch: with an ns statement like this I'm getting "No value supplied for key: true": https://www.refheap.com/85271

18:22 if I remove the lighttable.nrepl part it just works fine

18:22 amalloy: martinklepsch: (:gen-class :main true) doesn't make any sense to me. don't you just want (:gen-class)?

18:23 martinklepsch: amalloy, hm good question. I probably just copied that from somewhere else ô.O

18:24 funnily that doesn't change anything

18:25 ah, wait a sec

18:26 amalloy: oh, your require is wrong

18:26 martinklepsch: omg, that was stupid

18:26 :D

18:26 should probably go to bed

18:29 Glenjamin: this may be a dumb question - but would RandomAccess & List be considered sufficient to implement clojure.lang.Reversible?

18:30 i noticed that seq works on ArrayList, but rseq does not

18:32 amalloy: Glenjamin: yes, but that's an uncommon enough use case that it's not really exciting to put into core

18:33 Glenjamin: would it be considered better practice for me to extend the protocol in my application, or just implement arraylist-rseq?

18:33 amalloy: and like, you can write it yourself: (defn list-rseq [xs] (let [n (count xs)] (for [i (range n)] (nth xs (- n i 1)))))

18:33 Glenjamin: in fact, this is a library, so it would have to be the latter

18:33 amalloy: it's not a protocol, so you can't do that; but if you could you shouldn't anyway

18:34 Glenjamin: i've done a lazy version with recursive and lazy-seq, but basically the same thing

18:35 unless for is lazy? that'd be far neater

18:35 amalloy: of course for is lazy

18:35 Glenjamin: whoops

18:35 thats so much neater than what i had

18:36 doall is the non-lazy for, so ofc for is lazy

18:36 amalloy: s/doall/doseq

18:36 Glenjamin: erm

18:36 yes

18:36 so obvious now

18:36 amalloy: you could also use List/listIterator, and ListIterator/prev to walk backwards over the list

18:36 insetad of using nth

18:37 Glenjamin: i had .get, no idea what the differences are really :)

18:37 amalloy: eh, nth goes through some dispatching logic in c.l.RT and then calls .get

18:38 Glenjamin: i suppose the iterator enforces the blow-up-if-mutated constraint

18:39 amalloy: &(let [a (java.util.ArrayList. '(a b c d e)), iter (.listIterator a (count a))] ((fn step [] (lazy-seq (when (.hasPrevious iter) (cons (.previous iter) (step)))))))

18:39 lazybot: ⇒ (e d c b a)

18:40 kil3n: hey

18:41 anyone using emacs-live vanilla setup?

18:41 Glenjamin: oh, now we've swapped

18:42 justin_smith: kil3n: there are many emacs users here, we may be able to answer a question even if we aren't using the emacs-live setup

18:42 Glenjamin: (defn arraylist-rseq [al] (let [n (count al) it (.listIterator al n)] (for [i (range n)] (.previous it))))

18:42 &((fn [al] (let [n (count al) it (.listIterator al n)] (for [i (range n)] (.previous it)))) java.util.ArrayList. '(a b c d e))

18:42 lazybot: java.lang.ClassNotFoundException: java.util.ArrayList.

18:43 kil3n: justin_smith: thanks, it’s just that I can’t seem to make changing the font size stick, it auto-resets after a second on startup (when “zoning…” is done or something)

18:43 setting the new font size in live-packs

18:43 Glenjamin: &((fn [al] (let [n (count al) it (.listIterator al n)] (for [i (range n)] (.previous it)))) (java.util.ArrayList. '(a b c d e)))

18:43 lazybot: ⇒ (e d c b a)

18:44 justin_smith: kil3n: what method are you using to set the font? is it actually saving it for future sessions via customize?

18:44 amalloy: urgh. you shouldn't really use the side-effecting .previous inside a for-loop

18:44 i can't think of any way it could go wrong here, but it makes me queasy

18:45 kil3n: justin_smith: in `init.el` in my live-packs folder

18:45 `(set-face-attribute 'default nil :font "Menlo 15")`

18:45 justin_smith: kil3n: try m-x customize-group basic-faces and check out what is under the Default face: entry

18:45 Glenjamin: is it particularly different from a side-effecting lazy-seq?

18:45 kil3n: justin_smith: checking…

18:46 justin_smith:

18:46 amalloy: well, Glenjamin, chunked sequences make it a bit different

18:46 kil3n: justin_smith: state: STANDARD, “inherit”: INS DEL Face: (sample)

18:47 amalloy: eg, you could imagine writing (take n (for [i (range)] (.previous iter))) instead

18:47 Glenjamin: ah, i see - lazy-seq is unchunked?

18:47 kil3n: justin_smith: sorry that was button face

18:47 justin_smith: Height is 120

18:47 amalloy: which looks okay, but will probably call .previous too many times because you're not explicitly guarding it with .hasPrevious

18:47 kil3n: justin_smith: font is menlo, correct

18:48 justin_smith: I’ve tried changing the :height before in the init.el file as well, like this “(set-face-attribute 'default nil :height 180)”

18:48 PigDude: OK! How do I compare sets?

18:48 kil3n: justin_smith: but still resets after a sec

18:48 amalloy: Glenjamin: there are only a couple things in clojure.core that produce chunked sequences. range, seq on a vector, seq on a map...maybe something else i can't think of at the moment

18:48 justin_smith: kil3n: odd - maybe try opening ielm and checking the current face attributes?

18:48 PigDude: justin_smith: yea, this is for part of the program before i can guarantee clj-time (a cljs part)

18:48 Glenjamin: interesting, i wouldn't have expected range to be chunked

18:48 justin_smith: ahh

18:48 amalloy: some things *preserve* chunked sequences, like: for, map, filter, remove

18:48 technomancy: kil3n: starter kits like emacs live often do weird things that make them really difficult to debug

18:48 PigDude: justin_smith: for pulling (pr-str) formatted date when reading json, as value-fn

18:48 kil3n: justin_smith: tried changing the height directly, but how do I actually save this?

18:49 technomancy: it's difficult to recommend their use for new users

18:49 kil3n: technomancy: yeah :)

18:49 PigDude: ,(compare #{1} #{1 2})

18:49 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentHashSet cannot be cast to java.lang.Comparable>

18:49 kil3n: technomancy: honored to speak to you btw, love leiningen

18:49 PigDude: ,(compare #{} #{})

18:49 clojurebot: 0

18:49 technomancy: kil3n: glad you like it =)

18:50 kil3n: please recommend another start if you have one, semi-n00b in emacs, used to be die-hard vim user before discovering the epicness of emacs when starting doing lots of clojure

18:50 PigDude: ,(superset? #{1 2} #{1})

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

18:50 PigDude: ah it's not in core

18:50 justin_smith: kil3n: not only is emacs epic, it has lots of great fan fiction available too (melpa...)

18:51 amalloy: that's pretty weird, PigDude. why does it work for two empty collections?

18:51 justin_smith: ,(do (require 'clojure.set) (clojure.set/superset? #{1 2} #{1}))

18:51 clojurebot: true

18:51 kil3n: justin_smith: fan fiction..? metaphor?

18:51 amalloy: &(identical? #{} #{})

18:51 lazybot: ⇒ true

18:52 amalloy: i guess that's why. i didn't realize those read to indentical objects

18:52 justin_smith: kil3n: expanding on the "epic" metaphor

18:52 technomancy: kil3n: it's best to just pick individual packages that do things you like instead of finding one huge package that does everything

18:52 amalloy: &(identical? [] [])

18:52 lazybot: ⇒ true

18:52 amalloy: &(identical? {} {})

18:52 lazybot: ⇒ true

18:52 amalloy: well, today i learned something

18:52 kil3n: technomancy: yeah but that seems like something to do when you actually know what you need, after you’ve used the stuff productively for a while… ;)

18:52 Bronsa: amalloy: they get compiled to PHS/EMPTY PHM/EMPTY PV/EMPTY

18:53 technomancy: kil3n: but if you feel the need to start somewhere, I can at least promise that https://github.com/technomancy/better-defaults won't mislead you in weird/confusing ways

18:53 kil3n: hehe thx

18:53 amalloy: Bronsa: yeah, i gathered as much: there's not really any other explanation

18:53 Glenjamin: PigDude: i dunno about how well it works with cljs, but http://momentjs.com is my go-to for JS date/time handling

18:53 Bronsa: amalloy: yeah, that should also be true for (). see Compiler$EmptyExpr or however it's called

18:53 amalloy: technomancy: isn't that the same thing people with starter kits say?

18:54 coventry: ,(identical? (pop [1]) [])

18:54 clojurebot: false

18:54 technomancy: amalloy: the difference is I'm not (anymore) filled with lies

18:54 PigDude: amalloy: interesting

18:55 justin_smith: ,(identical? (empty #{}) (empty #{}))

18:55 clojurebot: false

18:55 PigDude: Glenjamin: in this case i have some common code handling dates in cljs and clj

18:55 Glenjamin: so am going to use common JS/Java Date API as much as possible but probably end up shipping the object to clj-time immediately in clj and to date.js (or your moment.js) in cljs

18:56 Glenjamin: ah, that's likely to be tricky - i think java.util.Date and js Date are pretty similar - the latter being modelled on the former

18:56 Bronsa: justin_smith: looks like empty preserves meta

18:56 PigDude: Glenjamin: yea, in the end i just need to get consistent dates that can be compared in the host environment

18:56 Glenjamin: which isn't so bad. the fanciest arithmetic is adding a minute to a date

18:56 justin_smith: PigDude: what about just using .getTime?

18:57 ,(.getTime (java.util.Date.))

18:57 clojurebot: 1399589548663

18:57 justin_smith: it's trivial to parse at least

18:57 PigDude: justin_smith: my designs originally all used unix timestamps, yes

18:57 justin_smith: however that's a last resort :)

18:57 justin_smith: why last resort? do you need to carry something like tz info too?

18:58 PigDude: nope, and w/ timestamps comparison and basic arithmetic are pretty simple ... now i'm thinking if i should go back to that design. i wrote a lot of code for it ..

18:59 dbasch: ,(System/currentTimeMillis)

18:59 clojurebot: 1399589681249

18:59 justin_smith: it just seems that serialization / parsing is simpler with a timestamp number, and there are fewer weird things to go wrong (not to say there are none...)

18:59 PigDude: justin_smith: either way i want library users to be able to provide date objects, so i can't justuse timestamps. originally the library required calling w/ timestamps but i think this is unfriendly

19:00 justin_smith: then your wrapper layer is the getTime method of the Date object :)

19:00 PigDude: yea .. ok, thanks for talking w/ me about this, it's easy to doubt myself :P

19:01 maybe better to go w/ timestamp

19:01 justin_smith: this is not flawless - sometimes a time has to be specific to a timezone, so then you need that metadata

19:01 but mostly it is the path of least complexity I think

19:02 Glenjamin: amalloy: cheers for the tips - am I ok to use your last sample pretty-much verbatim?

19:02 justin_smith: dbasch: nice, for some reason I missed that one :)

19:03 amalloy: it should work, yeah. although i'd really just use the version with for/range/nth

19:03 PigDude: justin_smith: yea, and lets me filter w/ (partial > t) rather than #((complement neg?) (compare t %))

19:03 justin_smith: so i'll tak that :)

19:03 (don't expect those to be identical coimparisons, point being comparing Dates is harder)

19:03 Glenjamin: oh right, i forgot to try that one

19:03 amalloy: well, i guess the version with a ListIterator works even for non-RandomAccess lists like a LinkedList

19:04 Glenjamin: in this case its a concrete ArrayList, but that version is much neater anyway

19:08 martinklepsch: if my uberjar saves files to certain directories (like resources/ in dev) etc, how would I intergrate that into the deployment?

19:08 (I guess resources wasn't really the right place for this in the first place)

19:09 justin_smith: martinklepsch: io/resource finds resources in the classpath

19:09 martinklepsch: or are you concerned about data stored to the fs at runtime?

19:09 martinklepsch: the latter

19:10 justin_smith: you could modify your code to take a path as an env var or config

19:10 or use a CDN

19:18 swarthy: anyone every experience clojure.java.shell/sh causing segfault when trying to run a ruby script?

19:18 ever*

19:19 justin_smith: causing the jvm to segfault? or just the shell?

19:19 noonian: i've experienced segfaults when trying to run ruby scripts myself :P

19:21 if you have ruby configured using rvm or rbenv it might not behave the same way from clojure.java.shell because afaik those tools monkey with your bash environment and it may be different from the jvm

19:25 swarthy: noonian: that is likely what is happening then

19:25 justin_smith: causing ruby to segfault

19:25 noonian: is there anything I might try to force an env/user? anything that worked for you?

19:25 justin_smith: with ProcessBuilder you can construct the specific env you want to pass to the child process

19:26 noonian: i haven't tried this with clojure.java.shell, but i had a similar problem in the past calling ruby from a pallet script and i had to first source a script for rvm that setup some variables for the correct version

19:27 i'm not sure where those scripts lived though

19:28 https://rvm.io/integration/cron#environment

19:29 so in bash before running the ruby script you do something like: source /usr/local/rvm/environments/ruby-1.9.2-p290

19:29 swarthy: so would it be possible to use (sh <source env> <call script>) ?

19:29 i suppose I can try

19:30 justin_smith: with a ; in between, should work

19:30 swarthy: justin_smith: will do

19:30 I smell a blog post.

19:31 amalloy: justin_smith: i don't think you can just put a ; in there, can you? sh doesn't actually call your shell, it invokes a process. you'll need (sh "bash" "-c" "source env; call script") or something

19:32 justin_smith: oh, ok - I thought by the name sh that it would be invoking a shell - in that case you wouldn't be able to use source either

19:33 yeah, clojure.java.shell/sh just spawns the program, so you would need to call /bin/sh explicitly (or bash if you really feel the need)

19:34 noonian: my bash-fu isn't where it should be without even calling out from java

19:34 justin_smith: (verified via (clojure.java.shell/sh "pstree"))

19:35 noonian: (clojure.java.shell/sh "sh" "-c" "source <file>; script")

19:35 noonian: justin_smith: nice

19:36 justin_smith: the whole command can be in one string arg to sh, after the "-c"

19:37 https://www.refheap.com/85278 <- example

19:38 noonian: later folks

19:40 swarthy: justin_smith: thanks for this, I'm working on it now

19:40 so far no luck

19:45 justin_smith: how is the ruby in question installed?

19:45 perhaps it needs libs that are in /usr/local/lib/ instead of /usr/lib/ for example

20:05 TimMc: Given a var, is there an *easy* way to tell whether it could accept a given arglist?

20:05 I'd rather not parse the arglists myself...

20:06 technomancy: TimMc: (some #{'&} (apply concat (:arglists (meta #'myvar)))) is a thing

20:06 oh, a given arglist

20:06 that's harder

20:06 we do basically that in leiningen though

20:07 TimMc: For detecting bad CLI args?

20:07 technomancy: it ain't purty

20:07 TimMc: because that's exactly what I'm up to right now.

20:07 technomancy: https://github.com/technomancy/leiningen/blob/master/leiningen-core/src/leiningen/core/main.clj#L226

20:08 TimMc: ,((fn [& &] &) 1 2 3)

20:08 clojurebot: #<CompilerException java.lang.RuntimeException: Invalid parameter list, compiling:(NO_SOURCE_PATH:0:0)>

20:08 TimMc: Just checking. :-P

20:09 technomancy: http://p.hagelb.org/smart.gif

20:11 amalloy: is & the only symbol that backquote treats specially that isn't a special form?

20:12 that is, look at ##`(foo, def, &, let*, bar)

20:12 lazybot: java.lang.SecurityException: You tripped the alarm! def is bad!

20:12 amalloy: die in a fire, bro

20:12 ,`(foo, def, &, let*, bar)

20:12 clojurebot: (sandbox/foo def & let* sandbox/bar)

20:13 TimMc: hah

20:13 technomancy: imma steal that, k?

20:13 and relicense it under the WTFPL

20:13 technomancy: ~guards

20:13 clojurebot: SEIZE HIM!

20:15 TimMc: Seriously though, I might copy that into org.timmc/handy.

20:16 I just realized I don't actually know how to do attribution in such a case other than adding a comment about the source...

20:16 technomancy: as long as it's EPL you're fine

20:59 zeroem: ,(get-in {} [])

20:59 clojurebot: {}

20:59 zeroem: ,(update-in {} [] identity)

20:59 clojurebot: {nil nil}

21:00 zeroem: is that inconsistency expected?

21:06 amalloy: zeroem: it's not totally clear what it would mean to update-in with an empty keyseq. {nil nil} is a stupid result, but nothing else is super-appealing

21:07 do you want (update-in {} [] (constantly 5)) to return 5? then update-in doesn't even always return a map!

21:07 zeroem: amalloy: well, get-in with an empty keyseq returns the map itself, it would make sense if update-in provided the map itself to the fn

21:08 if you println instead of identity, it's just given nil

21:08 amalloy: that's "reasonable", but as i said it leads to some unpleasant consequences

21:09 hyPiRion: I think it would be more sane to just throw if it's an empty keyseq, but perhaps that's just me.

21:10 coventry: ,`~'` ; <- Is there any way to get a backtick inside a backtick?

21:10 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

21:11 amalloy: hyPiRion: that'd be my preference too

21:11 coventry: no, it doesn't really make sense to do so given that backquote is read-time

21:11 coventry: Right.

21:15 lemonodor: is there a mocking library that I can use with clojure.test?

21:15 danlamanna: any immediate thoughts on mist/peer/freepastry?

21:36 justin_smith: newb jvm question: is onEnable a standard java method, or a convention of some plugin system?

21:36 jeremyheiler: in what context?

21:37 justin_smith: as a method on a class, in examples I see it contains initialization code

21:37 which I would usually assume goes in the constructor

21:37 googling is not giving me much

21:38 jeremyheiler: onEnable is surely a valid java method name. otherwise i don't understand your question.

21:39 justin_smith: I just wondered if it was a convention of some plugin system or framework, or something that the jvm would call

21:39 jeremyheiler: i mean, wht class are you talking about?

21:39 justin_smith: like I said, a newb question

21:39 jeremyheiler: where do you see it?

21:40 justin_smith: it's something I saw in a random paste of java code, and I got curious

21:40 sorry, I guess it's a stupid question

21:40 jeremyheiler: oh, ok. it doesn't ring a bel for me.

21:41 not a stupid question. i get it. seeing code out of context in an unfamiliar language begs lots of questions.

21:42 cbp: standard java method as in a method of Object?

21:42 then nope

21:58 justin_smith: PigDude: btw, it looks like there is a "Calendar" class for doing math on date / time. No idea if it is worth using though

22:00 ,(doto (java.util.Calendar/getInstance) (.add java.util.Calendar/HOUR_OF_DAY 10))

22:00 clojurebot: #inst "2014-05-09T11:56:01.005+00:00"

22:00 zeroem: amalloy_: yeah I definitely would have preferred an exception rather than blowing hours on assumed functionality :F

22:11 justin_smith: amalloy_: I remember a little while back we were talking about setting up default java versions on debian. I just upgraded to jdk 1.8 and instead of messing with update-alternatives it sufficed to rm /etc/alternatives/java and replace it with a symlink to the jdk1.8 bin/java file

22:11 oh, and this worked

22:17 AWizzArd: dnolen_: In core.match, can I express: match x if it is (:or 1 2 3) or if it is `:guard even?`? If it is one bind its actual value to `n` so that I can `n` in the result.

22:19 (if (or (= x 1) (= x 2) (= x 3) (even? x)) (let [n x] ...then...) else)

22:39 philc: from a repl, is it possible to run just a single (testing ...) context within a deftest?

22:45 servo: anyone know if theres a ruby fressian library?

Logging service provided by n01se.net