#clojure logs

2013-11-24

00:00technomancythat's the only reason nginx is needed at small scale
00:00swarthyOkay so, uberjar on my machine. Nginx to forward to port setup for uberjar. su myappuser - java -jar myapp_uberjar
00:00swarthythat is roughly the idea
00:00swarthywith nginx adding more security \ stability
00:01swarthyjustin_smith and technomancy thanks for the input
00:01justin_smithnp
00:01dsrxnginx is probably better for serving static files too
00:02justin_smithyeah, I usually set it up so the app never sees the requests for static files
00:02swarthyI think I came across that, you have to do something to allow the uberjar files to be served statically or something like that?
00:03justin_smithyeah, it is a pretty standard nginx config
00:03justin_smithso if you are running out of a jar, you would also want to unzip the jar in a predictable place
00:03justin_smithif you wanted that feature
00:03justin_smithwith tomcat, the jar gets unzipped automatically and you can just point to where it ends up
00:04swarthyjustin_smith: how much more cognitive overhead does getting tomcat and its ilk set up?
00:04swarthyI know zero about java stack for deployment.
00:04justin_smithswarthy: in my experience, just adjusting the default jvm opts
00:05justin_smiththen I copy the war for my app into /var/lib/tomcat7/webapps/ROOT.war
00:05justin_smithservice tomcat [start|restart|stop] as apropriate
00:05swarthywhat benefit does this yield over uberjar?
00:05justin_smiththough it has options to auto-restart when you upload an artifact
00:05justin_smiththe service abstraction
00:05justin_smithnot having to find the pid manually or do a killall or something
00:06justin_smithlogging in a default and reasonable way
00:06justin_smithwithout having to do anything other than println in my app if I don't want to do more
00:06justin_smithcomplete with zipping old logs renaming as apropriate etc.
00:07swarthyare there any good resources for learning this, anything that you used to get started or are you an old java hand?
00:07justin_smithit just takes care of a lot of the little nuiscance things that otherwise add up
00:07technomancyhuh; I didn't know tomcat did logrotate
00:07justin_smithI just learned from my coworkers
00:07justin_smithyeah, it gzips old logs, all that standard stuff
00:07swarthyjustin_smith: cool, I'll have to investigate
00:08justin_smithwell from my coworkers, plus googling
00:10justin_smithalso, using a war file in a tomcat container is probably the definitive way to run clojure webapps on elasticbeanstalk, which gives you a superset of tomcat's conveniences
00:11justin_smithwith beanstalk I rarely even need to ssh to the box
00:11justin_smith'lein beanstalk deploy', send out the messages to interested parties when I am informed the new version is up
00:11justin_smiththe rest is automated
00:14justin_smithsomething I am working on, regarding all this stuff, is a way to:
00:14justin_smitha) make it easy to deploy and access credentials
00:14justin_smithb) make development and usage of credentials easy
00:14justin_smithc) without ever having unencrypted credentials in git
00:15swarthyjustin_smith: I haven't used elasticbeanstalk, how does it compare price wise to VPS providers like linode and digital ocean?
00:15swarthyjustin_smith: does Pallet do that sort of stuff, I looked at it briefly today?
00:15justin_smithI don't know actually, I don't pay that bill :)
00:15swarthyjustin_smith: Ah, well DigitalOcean is dirt cheap if not a bit crappy from time to time.
00:16swarthybut they are getting better and better
00:16BAMbandaI don't think anyone has developed firefox extensions with cljs and I would like to be among the first
00:16justin_smithI think pallet is meant to abstract over various deployment and hosting options
00:16BAMbandai have some questions on packaging though:
00:17BAMbandawill lein be able to output the js to a folder outside of the root folder that contains project.clj?
00:17technomancyBAMbanda: I have never used cljs but I would love to do some 'zilla hacking with it
00:17technomancyBAMbanda: you can put .. in :target-path or whatever
00:17justin_smithswarthy: my guess would be that we go with amazon because they are reliable, large scale, and pretty standard as far as automated deployment goes
00:17BAMbandatechnomancy, yeah thats exactly what im trying to do!
00:17justin_smithswarthy: I've been meaning to check out various openstack alternatives though
00:18BAMbandatechnomancy, but even if that target path is a level above the lein project directory?
00:18technomancyBAMbanda: that probably has more to do with lein-cljsbuild though, which I haven't used
00:18technomancyI think so?
00:18BAMbandahmm
00:19swarthyjustin_smith: You guys are a dev shop too though, so you can pass cost on to clients perhaps.
00:19swarthyso stability > price
00:19swarthynot a bad thing if that is the case
00:20justin_smithswarthy: yeah, we bill clients for their hosting, but if we can save money on deployment, I can probably talk my boss into some fraction of that money saved landing in my pocket :)
00:21swarthyAhaha, well you guys having big name clients you will want that extra stability. DigitalOcean for example gives you a bare VPS fo $5 - $50 + per month. So you would need some sort of DevOps in place to get the same speed of deploy as AWS.
00:22justin_smithright
00:22swarthyand likely would not be anywhere near as stable or bandwidth limitations
00:22justin_smithand any downtime would translate into untold lost money
00:22swarthyyeah
00:22swarthyfor me, bootstrapping and mucking around I need cheap, lol.
00:22justin_smiththough the bigger clients have their own server farms and hosting facilities, and we just ship the code to run to them
00:23justin_smiththe biggest won't even let us use clojure :(
00:23justin_smiththough to our credit we keep trying
00:24swarthyWhat do they want instead?
00:25justin_smithgoogle has their python backend and weird google data backend
00:25justin_smithwe don't even touch that stuff, we just ship the frontend with them
00:26justin_smiththough sometimes we have to deal with some terrible spreadsheet to enter data the app needs
00:26swarthysounds about right. People love excel.
00:26swarthyIn a scary way.
00:26justin_smithnike has a java stack in house, and let us use clojure for a while, until the adopted automatic security audits, and couldn't find a tool that did that for clojure code
00:27bitemyappjustin_smith: that's really disappointing.
00:27justin_smithwe push back, really we do :)
00:27swarthyI wonder what the language landscape will be in ~5 years or so.
00:27swarthyJust in the short term.
00:27swarthyI wonder if it will change much.
00:27arrdemjustin_smith: what toolkit/program did they do said audits with?
00:28justin_smithour tech leads and producers love clojure for the productivity (and it attracts high quality devs and keeps them interested, in their experience)
00:28arrdemjustin_smith: I'm curious who peddles it.
00:28justin_smitharrdem: I'll need to look it up
00:28justin_smithwe contacted them, and they gave us a quote for how much it would cost for them to add a clojure analysis feature
00:29arrdemjustin_smith: kk. the pentest crowd is near and dear to my heart, which is why I'm curious
00:29arrdemjustin_smith: $(TOODAMNMUCH)
00:29justin_smithand actually, I should probably keep things at this level of vagueness, because this is client information after all
00:29arrdemyeah true that.
00:29bitemyappjustin_smith: what order of magnitude was the quote?
00:29arrdemI guess I'll just ask google...
00:30justin_smithbitemyapp: under a million :)
00:30justin_smitharrdem: oh, we never got clojure onto google, we just do frontend for them
00:31swarthyjustin_smith: what languages are most requested by your clients. Which is to say what languages do people most want contracted in your experience?
00:31justin_smithbitemyapp: could be a decent job, if you could get someone to pay you to write that static analysis tool
00:31arrdemjustin_smith: wha?... I meant google for the vendor...
00:31justin_smithahh
00:31justin_smiththey are also a client of ours, I got confused :)
00:32justin_smithalso, I think static analysis for blub languages is much easier
00:32bitemyappjustin_smith: I agree, but I could write a basic static analysis security tool for Clojure
00:33justin_smithI'm sure you could, and I would love it if that existed
00:33bitemyappthe only real problem would be a lack of a nice security problem corpus.
00:33justin_smithand I know my bosses would pay to use it
00:33arrdembitemyapp: what do you think such a thing would look like? a typechecker with information privilages type annotated?
00:33bitemyappjustin_smith: well I was looking at a nice Clojure code parser/dumper and it was particularly well suited to this kind of problem.
00:33justin_smithknown cut and paste boilerplate patterns are a boon to sa
00:34bitemyapparrdem: the types would be only marginally useful and probabilistic.
00:34arrdembitemyapp: then what kind of analysis would you be thinking to provide?
00:34bitemyappSQL injection would be the first and most obvious.
00:34bitemyappand is potentially a problem if somebody is doing something stupid with cjj in Clojure.
00:35justin_smithreally what you would want to look for is any interface of read or eval with data that comes from third parties
00:35arrdemjustin_smith: I think bitemyapp is on the right track.. there are more (read) and (eval) equivalent forms than just the obvious c.c.t ones.
00:35bitemyappanything that uses a non-edn reader really.
00:36bitemyappthe subject has been on my brain because my company is talking to a security vendor.
00:37bitemyappa tool vendor, offering "static analysis"
00:37bitemyappI was very disappointed with the tool and the price they were asking for what is frankly, snake oil.
00:37justin_smithyeah, SA stinks of that to me in many instances
00:37bitemyappIt's possible to produce very good static analysis tools
00:38bitemyappThe Microsoft SA tools for C++ and .NET are probably among the best, but they're constrained to type checking, undefined behavior, etc etc etc
00:38bitemyappthey're not really about "security" per se.
00:38justin_smithright, but it's also possible for a lot of money for bullshit if you call it static analysis
00:38dsrxwhat kind of type checking does a C++ static analysis tool do that the compiler does not?
00:38dsrx(or C#, for that matter)
00:39bitemyappdsrx: compilers aren't really allowed to use hueristics and probabilistic warnings to the degree an SA tool can
00:39bitemyappdsrx: SA tools will catch a lot more bugs than a vanilla C++ compiler because they'll warn on stuff that might be "valid" code or have undefined behavior that a compiler would let fly.
00:39bitemyapp-Wall isn't enough.
00:39justin_smithhell, one could probably extend kibit to give security warnings
00:40bitemyappI'm not doing that and I don't think it's a good idea.
00:40dsrxsure, I can definitely see how they could warn about undefined behavior
00:40bitemyappdsrx: http://www.altdevblogaday.com/2011/12/24/static-code-analysis/
00:40bitemyappimagine would a static analysis tool could do with something like Haskell?
00:40bitemyappwhat a*
00:40justin_smithor, what made me think of kibit: things that aren't guaranteed to be shitty security, but give enough reason to advise a second look at the surrounding code
00:40arrdemkibit is the wrong way to come at this sort of analysis...
00:41arrdemreally you want a theorem prover like c.c.t
00:41bitemyappseriously.
00:41justin_smithsure
00:41bitemyapparrdem: that's not what we're talking about
00:41bitemyapparrdem: we're talking about heuristic-based SA which can be a lot more comprehensive than c.c.t
00:41bitemyappyou can't cross function barriers with something like c.c.t, it's intentionally very conservative which is completely the opposite of what you want in this context.
00:43bitemyappyou want something that's acting on a probability and hueristics so it can track things across functions and namespaces and be paranoid.
00:44bitemyapparrdem: it's better to just make the paranoid tool happy.
00:44bitemyappand take the warnings seriously.
00:44justin_smithright, sa has a relatively low cost for false positives
02:00bitemyappSegFaultAX: he herped and he derped.
02:02TEttingerbitemyapp, herping is a useful skill, you never know when you will need to treat a snakebite.
02:03TEttinger... did someone fail the Almighty Employment Challenge?
02:04bitemyappTEttinger: no, just people being stupid about FP on Twitter.
02:04bitemyappTEttinger: I should take a census of white papers to make my point sometime.
02:05TEttingerheh. ironic that they're complaining on a site that has a fairly FP server-side (twitter uses scala I believe)
02:06TEttingeroh what's that? functional programming can't scale? well we have untold millions of users, minus 1. you.
02:06TEttingersomehow you were dropped from our DB, oh no...
02:08bitemyappHackerNewsOnion: Failed YC founder reluctantly taken back in by parents
02:08bitemyappTEttinger: it's not really about scale, they just don't understand the utility.
02:08bitemyappTEttinger: which is insane, if I kept a journal of bugs I wrote in Clojure 90-95% of them would be things languages like Haskell catch.
02:08bitemyappditto Java.
02:09bitemyappdoing the same "kind" of language over and over with a rebrand (Golang) is not progress.
02:09TEttingeryeah, there's a bad reputation that FP is useless for real-world tasks and is only used in academia
02:09bitemyappwell they keep slowly coming in our direction.
02:09TEttingerexactly.
02:09bitemyappGarbage collection, transparent reference types etc are now standard.
02:09bitemyappas is first class functions, lexical scoping
02:09TEttingerI forget how clojure is scoped
02:10bitemyappbut it amuses me that the only things that really improve the modern languages are things FP did first.
02:10bitemyappTEttinger: lexical, of course.
02:10bitemyappTEttinger: Clojure is the best bits of Scheme along with CL-style full macros.
02:10bitemyapponly thing it's really missing is TCO.
02:11TEttingerminus reader macros too, which isn't a huge loss for most tasks
02:11bitemyappwhich is mostly a non-issue due to loop-recur, unless you've got a mutually recursive algo that needs trampolined or rewritten.
02:11bitemyappI don't think reader macros was one of the better things Common Lisp had :P
02:16bitemyappokay, this guy on Twitter is a fuckin' prick.
02:16bitemyapp"when you're done confessing your faith" holy fucking shit what an asshole.
02:16bitemyapptbaldridge: feel like addressing the doubts of somebody that doesn't understand FP?
02:17TEttingerbitemyapp, leave him to stew in his misconceptions.
02:17TEttinger"don't feed the trolls"
02:18bitemyappTEttinger: I posted links to white papers so people could learn more anyway.
02:18TEttingergood plan
02:22bitemyappTEttinger: going to drink tea to ease out of the red haze now.
02:22bitemyappyogthos: hey
02:25john2xhmm since I can't require private fn's, how do I test them?
02:25john2xunit test*
02:26bitemyappjohn2x: #'
02:27john2xbitemyapp: sorry I don't understand?
02:27bitemyappI was trying to decide if I should do the google transcript answer or the technically correct but sufficiently baffling to force you to research and learn answer.
02:28bitemyappjohn2x: the above answer was an example of the latter. Do you want me to perform the requisite google query and explain to you the clicks and keyboard strokes required to get the answer in excruiciating detail?
02:28bitemyappjohn2x: because it's not like it's impossible that somebody else couldn't have possibly had the same question
02:28TEttinger$google clojure reader
02:28lazybot[Clojure - reader] http://clojure.org/reader
02:28bitemyappjohn2x: leading them to ask said question in a public forum or Q&A site, like perhaps Stack Overflow
02:28bitemyappjohn2x: where they would receive an answer their google'able query
02:28bitemyappjohn2x: enabling you to have an answer for your common question
02:29bitemyappjohn2x: and then you'd perhaps realize that you could google things faster than getting trolled on IRC
02:29TEttingerit's called a var-quote, which should be easier to google
02:29TEttingerit should also give you an idea what it does
02:29john2xmy bad. thanks both
02:29bitemyappI don't even mind answering questions, I mind answering googleable/boring questions.
02:31bitemyappnow if it's a question that requires reading code you can't understand, then we're in business.
02:31bitemyappsay, details of Clojure's compiler that aren't always easy to understand.
03:00bitemyapparrdem: http://i.imgur.com/0i2apZv.gif
03:00arrdembitemyapp: thank you for ridding me of my drowsyness.
03:01arrdembitemyapp: also with regards to the above, google doesn't deal nicely with special syntax like the arrows and var-quote. Those are reasonable IRC questions just because most search engines won't do the sort of full text indexing you really need to get answers there.
03:20echo-areas
03:20echo-areaSorry
03:20echo-areaBBL
03:21TEttingerarrdem: symbolhound
03:22TEttinger$google symbolhound
03:22lazybot[SymbolHound: Search Better. Code Better.] http://symbolhound.com/
03:22arrdemTEttinger: I have a new favorite website...
03:22TEttingerit's amazing isn't it. that no one has tried it before... the indexing isn't great so far
03:23TEttingerbut it seems to be rapidly improving
03:23TEttingerman I wonder if they have an API I can consume from lazybot
03:40bitemyapparrdem: he didn't know #' anyway.
03:40bitemyapparrdem: googling the original question "use a private function" would've gotten him the answer just fine
03:41bitemyapparrdem: not the #' syntax. I was intentionally being a pain by answering #'
03:41bitemyapparrdem: being asking trivially googleable questions is senseless.
03:41bitemyappbecause*
03:48echo-areabitemyapp: Or a systematical training
04:08zeebrahis contains? not the right way to check if a map contains a key?
04:08zeebrahit returns false for every key i know to be in the map so i'm surprised
04:11echo-areazeebrah: Use `find'
04:12bitemyappzeebrah: contains? is for keys in maps, yes.
04:12bitemyappzeebrah: could you please demonstrate an example.
04:12bitemyappecho-area: no.
04:13zeebrahuser> (contains? :a {:a 20 :b 10}) -> false
04:13echo-areabitemyapp: Why?
04:13bitemyapp,(doc contains?)
04:13clojurebot"([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."
04:14bitemyappzeebrah: you pass the collection first, the key second.
04:14bitemyappzeebrah: read the documentation.
04:14bitemyapp,(contains? {:a 20} :a)
04:14clojurebottrue
04:14zeebrahbitemyapp: just found that out
04:14zeebrahbitemyapp: it should throw an error or something.. but that makes a lot of sense now .. phew :)
04:14bitemyappzeebrah: should throw an error? Clojure is dynamically typed and abides by the GIGO principle.
04:15bitemyappzeebrah: if you want something that catches mistakes, you're thinking of Haskell or Scala.
04:15zeebrahnot at all
04:16bitemyappzeebrah: then be prepared to embrace GIGO
04:17echo-areabitemyapp: Care to tell me your reason?
04:17zeebrahno
04:17bitemyappecho-area: nope, I'm going to bed and reading an awesome book while sipping my lager.
04:18zeebrahif you pass in something that isn't a collection that's clearly an error
04:18bitemyapp"clearly" not really, no.
04:18zeebrahyou're wrong
04:18zeebrahmost dynamic languages do it that way
04:18bitemyappthere is no right or wrong, it's a design decision.
04:18bitemyappmost? no.
04:18bitemyappPerl and Ruby do the same thing.
04:19bitemyappGIGO is fundamentally part of those languages.
04:19zeebrahsmalltalk, common lisp, scheme
04:19echo-areabitemyapp: Okay. My guess is that `contains?' is more general than `find'. Not sure if it was your reason. Anyway, have a nice reading :)
04:19bitemyapponly Python is persnickety.
04:19bitemyappecho-area: it's not the reason, it's just the smarter function to use as long as you understand it, and since zeebrah expected contains? to act on the map key rather than value, I figured they understood it modulo arity.
04:20bitemyappecho-area: find has the same arity as contains? anyway, so it would've broken for zeebrah in the same exact way, not that you bothered to check why contains? wasn't working for them.
04:20bitemyappecho-area: avoid making blind suggestions without checking to see what the actual problem is.
04:21zeebrahi agree with bitemyapp find isn't the answer to the question
04:21echo-areabitemyapp: Noted. And thank you.
04:21bitemyappoff to my beer, bed, and book.
04:21echo-areaGood night.
04:21zeebrahnight!
04:30amalloy,(contains? :a {:a 1})
04:30clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.Keyword>
04:31amalloythat changed in 1.5, which i thought was worth mentioning since apparently there was a spirited debate in here about which is right
04:31zeebrahawesome good to hear that amalloy
04:31amalloywell, don't get too excited. get, find, and so on still silently return nil
04:32zeebrahand i really thought i was using 1.5
04:32zeebrahoh :/
04:37echo-area,(find :a {:a 1})
04:37clojurebot#<ClassCastException java.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map>
04:38echo-areaIt also applies to `find' :)
05:07amalloy&(find :a {:a 1})
05:07lazybotjava.lang.ClassCastException: clojure.lang.Keyword cannot be cast to java.util.Map
05:07amalloyi guess find was always that way
05:22dbushenkohi all!
05:27bamford_folks, quick question: in https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj#L75-L81 , is looks to me like a thread is spawned and then runs indefinitely, since it contains a (while true ...) -- correct? It will continue running in the background even after leaving the (let ...) scope?
05:30amalloyyes
05:32bamford_amalloy: ok, then I understand that it's not an ideal example for beginners, one should never use (while true) in a (thread) since that will bind one OS thread. I will use loop ... recur then, thanks!
06:47echo-areaamalloy: Are clojurebot and lazybot running different versions of Clojure?a
06:47echo-area,*clojure-version*
06:47clojurebot{:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"}
06:47echo-area&*clojure-version*
06:47lazybot⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil}
06:47echo-areaSorry, I should have evaluated these first
06:47echo-areaDidn't mean to bother you
07:25myguidingstarhi all, is there any test framework support mock file system io?
10:45tcrayfordanybody got any idea how to convince the clj compiler to specialize to one static method of http://twitter.github.io/commons/apidocs/com/twitter/common/quantity/Amount.html (the `of` method)? Everything I've tried so far results in `CompilerException java.lang.IllegalArgumentException: More than one matching method found: of,`
10:45tcrayfordthings I've tried:
10:45tcrayford(defn amount-of-seconds [^long n] (Amount/of n Time/SECONDS))
10:46tcrayfordcan't type-hint locals with a primitive initializer, so that's out
11:04justin_smithhttp://stackoverflow.com/questions/11919602/generating-clojure-code-with-type-hints tcrayford, this may help
11:08jehow (if?) is it possible to but the test-constant outside of the case: https://gist.github.com/jacobemcken/5778cb6a2caed2d2ebf2
11:08xcthulhuHow do I check what protocols LineNumberingPushbackReader instances?
11:08justin_smithxcthulhu: clojure.reflect/reflect
11:09justin_smithit returns that info (along with a whole bunch of other stuff)
11:09xcthulhuThanks :D
11:22justin_smithtcrayford: what about using (long n) (long Time/SECONDS)
11:22justin_smiththe second may be unneccisary
11:22tcrayfordjustin_smith: the second long isn't wanted even, that's an enum
11:23justin_smithoh
11:23justin_smithyeah, looking at Unit now
11:23tcrayfordthe (Amount/of (long n) Time/SECONDS) call fails though, same thing about more than one matching call :/
11:23justin_smithweird
11:24justin_smithwhat is the full class of Time/SECONDS?
11:27tcrayfordjustin_smith: http://twitter.github.io/commons/apidocs/com/twitter/common/quantity/Time.html
11:28tcrayford(this is for connecting to zookeeper via the twitter commons client: http://twitter.github.io/commons/apidocs/com/twitter/common/zookeeper/ZooKeeperClient.html)
11:28tcrayfordI might well just write a java shim around it that specializes to long
11:29justin_smithhave you tried using the double or float or int versions? on the off chance
11:30tcrayfordjustin_smith: yep ;)
11:30tcrayfordtried with (double n), (float n) and (int n)
11:36xcthulhuHey, I'm a clojure noob and I just read some code where someone wrote (def- ^{:const true} blah "blah")
11:36xcthulhuIs that idiomatic for private constants?
11:36justin_smithdef- is idiomatic for private things
11:36justin_smithI don't know if :const actually does anything though, maybe someone else does
11:37Bronsa:const actually does something
11:37justin_smithhttp://stackoverflow.com/questions/9162558/how-does-clojure-const-work
11:37Bronsait avoids the Var indirection when possible
11:37justin_smiththat's good to know
11:38justin_smithhow does it interact with redefinition?
11:38Bronsait breaks it
11:38justin_smithfigures
11:38hyPiRionwith pain
11:38justin_smiththanks, that's useful
11:38justin_smithso I should wait until my code is "done" before adding const hints I guess
11:39xcthulhuYeah, it's a premature optimization...
11:39Bronsajustin_smith: the rationale is that if you explicitely use ^:const you know what you're doing.
11:39justin_smithright
11:39justin_smithso basically, if I find something is getting looked up too often in a tight loop, use :const, otherwise just leave it be
11:40Bronsaif it's a constant, yeah
11:40justin_smithof course
11:40justin_smithbut most top level stuff in good clojure code should be constants
11:41TimMcAnd even then, shouldn't hotspot help out?
11:41TimMcand branch prediction
11:41justin_smithit would be interesting to see a comparison
11:42TimMcIt would be interesting to have everything be constants by default in production, but make everything rebindable during (say) lein test.
11:42TimMctest, repl... not sure what else
11:43BronsaTimMc: that's what (hopefully) will be possible to do with tools.* one day :P
11:43justin_smiththat would be cool
11:43TimMc(Not that I know it would definitely make a difference.)
11:44xcthulhuTimMc: Well, I was wondering because I have some parsing code and I want to use a gensym for an EOF symbol... in this case, dereferencing is the right thing to do, rather than inlining
11:44justin_smithxcthulhu: then you probably wouldn't want to use :const anyway
11:45xcthulhuYeah, that's why I came in here and asked :D
11:45xcthulhuAlso, which is better: (gensym) or (Object.) ?
11:45justin_smiththanks for asking, it's cool when I can learn something from someone else's question
11:46justin_smithdo you primarily care about a unique identity, or a binding that needs a unique symbol?
11:47xcthulhuUnique identity - clojure already has heigenic macros so it's hard for me to find a use-case for (gensym)
11:48TimMcxcthulhu: gensyms are a part of hygienic macros
11:48TimMcThat's what foo# does.
11:48TimMc&`foo#
11:48lazybot⇒ foo__38506__auto__
11:48justin_smithxcthulhu: you probably want Object.
11:48xcthulhuTimMc: Right. But explicitly writing (gensym) seems like a rare event
11:49TimMcIt happens from time to time. I've used it maybe a couple times a year.
11:49Bronsaxcthulhu: (let [x (gensym)] `(~x ~@(map (fn [a] `(~x ..)) something)))
11:51TimMcSpecifically, it useful when you run up against the limits of syntax-quote.
11:51xcthulhuI'm already there, actually.
11:53xcthulhuMy colleague wants to write the following, which I don't think is possible in clojure: (escape {"json": "is", "unnatural" : "in clojure" } ) => "{\"json\": \"is\", \"unnatural\" : \"in clojure\" }"
11:54xcthulhuI think I could do something like that with this: https://github.com/klutometis/reader-macros
11:54hyPiRionit's not possible.
11:55xcthulhuWhich is how I'd do it in Common Lisp
11:56xcthulhuBut I bet there's a "_ Considered Harmful" paper I'd be violating
11:56justin_smithyou could do it if the input was a string, but the embedded colons could lead to a map with an uneven number of symbols, for example
11:56justin_smithif it were not a string
11:56xcthulhujustin_smith: Yeah, that's why I'd do it with a read-macro
11:56hyPiRionIt would just break everything.
11:56justin_smithalso, I don't think : is valid input
11:57jtoyis it possible to write an interator for a db that can be used with inject like so: http://pastie.org/8505426
11:57jtoythat doesnt seem to work for me
11:57Bronsathere's no way it would work even with read-macros capabilities. : dispatches to read-keyword, you'd need to redefine that
11:57TimMcxcthulhu: You kind of want heredocs, which Clojure also doesn't have. Sort of.
11:57justin_smithhyPiRion: is that because you couldn't ensure your read macro ran before the built in {} read macro?
11:57justin_smithor whatever you call the thing that parses {}
11:58TimMcxcthulhu: I usually just write {:maps "are", :natural "in clojure"} and then tell Cheshire to convert it (taking keyword keys to string keys)
11:59hyPiRionjustin_smith: even if you could, you may env up breaking all clojure libraries you use
11:59justin_smithso something as finely grained as "parse this block if we can tell it is a json literal, otherwise hand down to the next parser" is not possible?
12:02hyPiRionWell, you could probably do some reflection on the reader, but I wouldn't bother go that far.
12:03xcthulhuhyPiRion: The common lisp way is to hijack the reader and parse the character stream yourself
12:03justin_smithalso, something like #json-literal [json map] -> "{\"json\" : \"map\"}" would work - but : would probably fuck it up
12:04justin_smith,:
12:04clojurebot#<RuntimeException java.lang.RuntimeException: Invalid token: :>
12:05justin_smith\: could be a workaround
12:05justin_smith,\:
12:05clojurebot\:
12:05hyPiRionxcthulhu: sure, been there, done that. Its usefullness in Clojure is debatable, though.
12:06TimMcxcthulhu: Anyway, what's wrong with just serializing a Clojure data structure to JSON?
12:06justin_smiththey probably want the convenience of seeing the real json form embedded in the clojure code
12:06TimMc{"key" ["val" "ues"], "numbers whee" 45}
12:06TimMc"Convenience", you can't even edit it structurally.
12:07justin_smithtrue!
12:07TimMcor template it
12:07xcthulhuTimMc: My crazy colleague wanted to do it the hard way, and as a n00b I'm honor bound to find a way to make his twisted dreams come true
12:08justin_smithif you want that kind of pervasive dsl paradigm, rebol is great for that
12:08justin_smithbut it does not have the performance you would get from clojure, and it is closed source
12:08justin_smithand the "pro" version costs money
12:09justin_smithie. in rebol an email address literal is somebody@example.com
12:09justin_smithand it just works
12:09xcthulhujustin_smith: Well my company pays us to program in clojure...
12:09justin_smithjust saying, that is not what clojure is designed for as an approach, but there are languages that are designed that way
12:13SegFaultAXxcthulhu: Where do you work?
12:13xcthulhuSegFaultAX: OpinionLab in Chicago
12:14xcthulhuThe company isn't very interesting, but I wanted a functional job and someone managed to convince management to go with Clojure
12:14SegFaultAXI think you told me that once before actually. :)
12:14SegFaultAXI recognize the site.
12:14SegFaultAX(Or perhaps one of your colleagues that also hang out in #clojure)
12:14xcthulhuTotally possible
12:15gunsxcthulhu: I had a recruiter approach me about OpinionLab; are you enjoying yourself?
12:24xenon75Hello
12:25gdeer81xcthulhu, is that the same opinionlab that you install on your website to get feedback about it?
12:27xenon75Are ClojureScript questions appropriate in this channel or should I go to #clojurescript (which seems quite dead) ?
12:27gdeer81xenon75, just fire away
12:27xcthulhugdeer81: Yeah
12:27xcthulhuIt's that opinionlab
12:29gdeer81xcthulhu, ha our business users want to put opinionlab on our current site. good to know we're using a company that uses Clojure =)
12:29xenon75ok, well I am learning Clojurescript by porting a javascript app I did some time ago. It is a little 3D demo which shows some effects - I basically update "scene data" 60 times per second doing some nice visuals while music is playing.
12:30xenon75now I was wondering that if I use persistent data structures and I "mutate" them 60 times per second
12:30xenon75I might choke the JS interpreter
12:30xenon75so maybe I should go with mutable stuff in clojurescript via (set!) or change the application I am learning with :)
12:31xenon75is it the case or the clojurescript runtime can cope with that?
12:33gdeer81xenon75, start with persistent data structures, if it chokes the interpreter, then go with mutable data structures with a facade of immutability, if that doesn't work...go dirty
12:35xenon75gdeer81: that was my intention as well - just wanted to know if my experiment was doomed from the start :)
12:35xenon75gdeer81: btw, what do you mean by "mutable data structure with a facade of immutability" ?
12:36gdeer81xenon75, lol yeah sorry
12:52justin_smithI think if changes happen anywhere near 60 times a second, you will need to stick with directly using the mutible structure
12:52justin_smiththough other things that are less frequently updated can stay immutible, most likely
12:56sritchiehey guys - has anyone seen this error on the new cljs version?
12:56sritchieAssert failed: :output-dir "/Users/sritchie/code/clojure/paddleguru/target/cljsbuild-compiler-3" must specify a directory in :output-to's parent "/Users/sritchie/code/clojure/paddleguru/resources/public/cljs" if optimization setting applied
12:57andyfBronsa: Thanks for the quick tools.analyzer.jvm fix
12:57sritchiethis happens with a custom :output-to, just as in the lein-cljsbuild example
12:58Bronsaandyf: np, if you encounter any more misbehavings please assume they are bug and report them
12:59andyfBronsa: So reading your reply to me on the dev mailing list, you would recommend I copy-and-paste t.a.j's analyze function, and remove some passes that do checking that currently breaks?
12:59andyfBronsa: I think you mentioned 'validate' as one pass that might be useful to remove.
13:01Bronsaandyf: depending on what you need to do, that may be a solution
13:01Bronsa(to avoid evaluating every form, that is)
13:02Bronsathe tradeoff is that you have no way of knowing if SomeClass/nonExistentField is valid or not
13:05sritchiednolen: any advice on how to handle this error about output-dir?
13:05sritchieor is that a cljsbuild thing
13:07Bronsaandyf: I'll take a look to see if I can help porting eastwood to tools.analyzer later
13:11Bronsaandyf: btw looks like ambrose's analyze does indeed eval the analyed expressions under the hood
13:19andyfBronsa: Sorry, was on a phone call there. Yes, ambrose's jvm.tools.analyzer's analyze does eval.
13:19danneuHow can you efficiently calculate `x^y modulo z` in one expression?
13:20andyfBronsa: I already have eastwood partially updated to use tools.analyzer.jvm now. I'm trying it out on various contrib libraries to see which ones it works on, and which it fails on. Right now still lots of failures. I will re-run those tests with validate step taken out and see what changes.
13:20Bronsaandyf: if your goal is simply detecting duplicate def's though, there is no need for eval'ing
13:21andyfBronsa: That was my thinking, too. Do as many checks that Eastwood does now, plus detecting duplicate def's, without doing eval, which probably means not doing validate, either.
13:22andyfBronsa: Would you recommend walking the analyzed expression trees for :def ops, so that it handles things like (let (defn foo ...)) that a few code bases use?
13:27danneuto answer my own question: BigInteger#modPow
13:27andyfdanneu: You beat me to it by a few seconds ... :)
13:28Bronsaandyf: depending on what you want to do you have different options -- if you want to support everything eastwood supports ATM, you'll need to use the bundled c.t.a.j/analyze or something really similar to that and eval every form, if you only want to do some static analysis e.g check for redefinition, unused functions etc, you can avoid evaluating everything and could probably use a custom analyze function with none of th
13:28Bronsapasses
13:28Bronsaandyf: yeah, you could use c.t.a.passes/walk to do that easly
13:28andyfdanneu: I'd recommend converting the answer back using (bigint result) before using it elsewhere in your code. Might want to wrap that up in a small Clojure function to do the BigInt <-> BigInteger conversions.
13:28danneuandyf: thanks. i only become a google-fu wizard once i've asked a question in irc
13:29danneuandyf: yeah, i've been extending https://github.com/clojure/math.numeric-tower this way
13:30andyfdanneu: Reason: BigInteger's do not obey hash consistency in Clojure, by choice. See http://dev.clojure.org/jira/browse/CLJ-1036
13:31andyfBronsa: Thanks. I'll experiment for a while and let you know if I hit any road blocks.
13:39bellkevHey I'm super new to Clojure, but I have a hopefully easy question. Does anybody know if deftype and defrecord are both equally likely to stick around, since the docs say both are "alpha"? I have a situation where I pretty much just need a struct-like map, but with a well-known set of fields. I definitely like the look defrecord, because it gives the map interface. Is that a popular way to go? Is deftype likely to be deprecated soon? Because
13:39bellkevseems similar to defrecord but with less features?
13:43Bronsabellkev: they're not in alpha anymore as of clojure-1.6.0-alpha3
13:44bellkevBronsa: Haha, nice, not in alpha as of the new alpha ;) Thanks!
13:45osnr_is there a shortcut to recur with the same values for the bindings? like, (loop [x 1 y 2 z 3] (recur x y z)) a shortcut for (recur x y z)
13:47justin_smithosnr_: you could put all the args in a destructured vector: (loop [[x y z :as in] [1 2 3]] ... (recur in))
13:47justin_smiththis would also requiring changing other calls to recur to put [] around the args
13:48justin_smithand you lose arg count checking
13:49justin_smithotherwise the code could stay the same
13:49osnr_justin_smith: would also make the initial binding harder to read, but thanks for the suggestion.. hmm. might end up doing that. would it be idiomatic to use a macro for this?
13:50justin_smith,(loop [[x y z :as in] [1 2 3]] (if (< (rand) 0.5) :done (do (println :tick) (recur in))))
13:50clojurebot:tick\n:tick\n:tick\n:done
13:50justin_smith,(loop [[x y z :as in] [1 2 3]] (if (< (rand) 0.5) :done (do (println :tick) (recur in))))
13:50clojurebot:tick\n:tick\n:tick\n:tick\n:tick\n:done
13:51justin_smith,(loop [[x y z :as in] [1 2 3]] (if (< (rand) 0.5) :done (do (println :tick) (recur in))))
13:51clojurebot:tick\n:tick\n:tick\n:tick\n:done
13:51justin_smithsorry
13:51justin_smiththat is a very small thing to be making a macro for
13:52justin_smithand I think the more you use destructuring, the more readable that form is
13:54justin_smithalso if you put the binding form directly under the destructuring form rather than on the same line, seeing what lines up with what can be pretty straightforward
13:55osnr_OK, cool -- I will go with some form of the destructuring then, thanks!
14:08bellkevI answered my own question from earlier about why there are both deftype and defrecord constructs by reading this: http://clojure.org/datatypes. However, as I start to play with records, I wonder: what do most people do for data validation? For example, if I create records with (map->RecordName {...}), it is okay if fields are missing or if there are extra keys not defined as fields on the record. Do people tend to perform validations separat
14:08bellkevlike this: http://blog.8thlight.com/myles-megyesi/2012/10/16/data-validation-in-clojure.html ?
14:11justin_smithbellkev: gigo is a really common design choice in clojure and in clojure libs
14:11justin_smithmy choice would be write a function that wraps map->RecordName with preconditions on the args
14:12justin_smith,((fn [x] {:pre [(number? x)]} (inc x)) 1)
14:12clojurebot2
14:12justin_smith,((fn [x] {:pre [(number? x)]} (inc x)) \a)
14:12clojurebot#<AssertionError java.lang.AssertionError: Assert failed: (number? x)>
14:13bellkevOkay, fair enough. I will be wrapping it anyway for other things, so that will be fine
14:14justin_smithor, if you prefer to return nil rather than throwing an error:
14:14justin_smith,((fn [x] (and (number? x) (< x 10) (inc x))) 1)
14:14clojurebot2
14:15justin_smiththanks to and, it will return nil if anything before the final term returns nil
14:15bellkevMaybe it's less necessary for me to even use the defrecord versus just a hashmap in the first place then, because it's doesn't need to do any protocol-ish stuff. Is it typical in clojure to use defrecords for field groupings only just to be explicit about what the record is, versus just using an anonymous map?
14:16justin_smithusually defrecord is for performance
14:16justin_smithor protocol stuff
14:16justin_smithbut then, protocols are often about performance too
14:16justin_smithit often works to use maps, then switch to a record if you find you need it eventually
14:17bellkevokay, that makes sense. Thanks!
14:17justin_smithrecords are not really used to ensure program correctness (since by design they really don't offer much for that), though I guess typed clojure could change that
14:26gfredericksdoes typed clojure have newtype? is there any reason it couldn't?
14:31hiredmangfredericks: it has some kind of type alias thing
14:31hiredmandef-alias
14:33gfredericksthat's a bit different from newtype I assume
14:33gfredericks(newtype Name String) would mean I can't substitute a string where I expect a name
14:35gfredericksthat would raise the question of how you'd obtain a Name in the first place I guess
14:38justin_smitha constructor that accepts a string of course
14:38justin_smithsounds like a monad
14:41TimMcWhen all you've got is a monad, everything looks like a burrito.
14:41justin_smithindeed
14:42TimMcjustin_smith: How can I solve the halting problem?
14:43BronsaTimMc: I lol'd
14:43tcrayfordjustin_smith: it's often used as a typelevel proof of something
14:44tcrayforde.g. if you have an invariant that all EncryptedPasswords are actually strings generated by bcrypt, then you hide the normal constructor, and have just the bcrypt encryption function be String -> EncryptedPassword, then you have a good way of ensuring that you won't accidentally check passwords against non bcrypted password strings
14:45justin_smithtcrayford: right
14:45tcrayfordbut newtypes in haskell are compile time only (99% of the time), so the code compiles/evals exactly the same as it would with String
14:46tcrayfordthey interact wonderfully with typeclasses (which are almost the same as procotols), as you can specialize say Eq for your custom strings without paying any performance penalty, which isn't true in many clojure lib designs that use protocols heavily
14:47gfredericksnewtype CaseUnawareString = String
14:48gfredericksnewtype EqualToItselfReversed = String
14:48gfredericksnewtype EqualToEverythingElse = String
14:48tcrayfordone of the things I love about newtyping EncryptedPassword is that you can make that thing not have a show instance, hide any way of getting it out, and suddenly you don't have to worry about accidentally logging passwords at all
14:49gfredericksclojurebot: haskell |means| you don't have to worry
14:49clojurebotIn Ordnung
14:52gfredericksI just realized you can print a newline with (println)
14:52tcrayford:///
14:53guns(newline)
14:53gunsSo people on windows don't yell
14:54justin_smithis println not guaranteed to generate a newline properly on windows?
14:54gunsoh, I suppose so
14:59dnolena sketch but here's a an idea I have for integrating mutable JS crap sanely w/o a perf hit and w/o paying for conversions clj->js js->clj conversions https://gist.github.com/swannodette/7631691
15:00dnolentldr; a transient that can't be made persistent that becomes unusable after an update operation
15:01gfredericksdnolen: is this for a lib, or language feature?
15:02dnolengfredericks: too half baked for language right now, but I plan on making it work for JS objects and we'll see what people think
15:02dnolengfredericks: if we can collectively make it less half baked maybe it's worth getting in - not sure yet
15:03bbloomseems like linear types
15:03bbloomimplemented dynamically
15:03bbloomhow do you deal with external modifications? ie if somebody gives you something that is already mutable
15:03bbloom(i believe the answer is: you don't)
15:04dnolenbbloom: yeah not a problem I want to solve :) but this does address how annoying it is to work w/ JS APIs
15:04dnolenbbloom: totally about the linear types bit
15:04bbloomseems like this will create a lot of gabage
15:05dnolenbbloom: see update!
15:05gfredericksso it only returns a new version if used = true?
15:06gfredericksI'm guessing at what check does
15:06dnolengfredericks: no ops allowed if used
15:06dnolengfredericks: if you ever get a new value, the old one dies
15:07bbloomyeah, i don't really understand how this helps either
15:07dnolenbbloom: no marshalling
15:07dnolenbbloom: no aliasing in your own code
15:10bbloomso is the entire goal that i get an exception if i use something mutable after i've released it?
15:10dnolengfredericks: bbloom: but it might not be worthwhile because you'd want it to work for nested values ... that seems tricky.
15:11bbloomyeah, i don't think this has any utility
15:11bbloomi'd rather deal w/ mutable things in normal mutable ways, wrap them up in a little machine, and then talk to those machines w/ async :-P
15:13dnolenbbloom: heh, like I said half-baked. But I'm not sure about the general idea not having utility - survey showed a lot of people complaining about js->clj clj->js
15:14bbloomdnolen: yeah, but i don't think the problem is related to correctness, it's about convenience
15:14dnolenthere are a couple things floating around out there - but few address the perf and good interaction on boths sides
15:14bbloomlots of js code use json or json-ish things for configuration, etc
15:14bbloompeople want js-obj to have {} syntax
15:14bbloomthat's basically it as far as i can tell
15:14dnolenbbloom: that's not my impression
15:14dnolenbbloom: they want immutable maps
15:15dnolenbbloom: what I'm suggesting here is having a mutable map and not being afraid to interact w/ it
15:15bbloomok let's rewind
15:15bbloomi'm going to look at the survey results again
15:16bbloomdo you have any particular comments you want to highlight? not your interpretation, source comments
15:16dnolenbbloom: yeah look at the individual responses on CLJS pain points
15:16dnolenbbloom: but also the fact that cljs-> js->cljs even exists, and stuff like mr-hyde
15:16dnolenanyways got a run for a bit - going to ponder the nested case
15:17bbloommrhyde is insane
15:20bbloomyeah, reading through these are confirming my suspicions
15:21bbloompeople want a way to call functions withArgs({like: "this"})
15:21bbloomthey want js data literals
15:22bbloomi wouldn't be surprised if a #js reader literal & printing made 90% of the complaints go away
15:28bbloomdnolen: another part of the problem is just that people need libraries & can't use jvm ones and wrapping sucks
15:28bbloomparticularly w/o feature expressions b/c it means if you write a date/time lib, for example, it's gonna be hard coded to JodaTime or moment.js or whatever
16:14{[^-^]},(reduce + (seq [1 2 3 4 5]))
16:14clojurebot15
16:14{[^-^]}is there any performance penalty to seq'ing that vector?
16:14justin_smiththat seq call is redundant
16:14justin_smithreduce does that already
16:14{[^-^]}it works around the subvec reduce problem
16:14{[^-^]},(reduce + (subvec [1 2 3 4 5] 1 4))
16:14clojurebot9
16:15{[^-^]}um
16:15justin_smiththe what problem?
16:15{[^-^]},(reduce + (subvec (into (vector-of :long) (range 1000)) 0 100))
16:15clojurebot#<ClassCastException java.lang.ClassCastException: clojure.core.Vec cannot be cast to clojure.lang.PersistentVector>
16:15{[^-^]},(reduce + (seq (subvec (into (vector-of :long) (range 1000)) 0 100)))
16:15clojurebot4950
16:16{[^-^]}yesterday someone told me to use vec instead of seq, and obviously that's slow
16:16{[^-^]},(reduce + (vec (subvec (into (vector-of :long) (range 1000)) 0 100)))
16:16clojurebot4950
16:17justin_smithso is the idea to get the subvec directly, rather than having to drop / take on the seq reduce would make?
16:18{[^-^]}I don't understand what you said
16:18justin_smithI guess I still don't understand why you would have to explicitly call seq on an arg to reduce
16:19{[^-^]}because you can't reduce over subvectors of primitive types
16:19{[^-^]}which is a bug
16:19justin_smithahh, ok
16:19justin_smithnot vector, but vector-of
16:19{[^-^]}yea
16:25sverihi, i have two clojure projects, where project A depends on project B, how do you handle this usually during develop time and during build time? i read about the checkouts folder and that makes sense, at least at dev time, but during build time? gradle handles multi projects really well, is there something similar with leining?
16:26justin_smithsveri: I typically put each project on clojars
16:26sverijustin_smith: ok, and what about private projects?
16:26justin_smithsveri: if something cannot be open source, I don't make it depend on other non-open-source things
16:26justin_smithwhich is a limitation, true
16:26sveriwell, both projects are private
16:26justin_smiththere is the option of a private maven repo
16:27justin_smithor, if you only build on one machine, lein install
16:27sveriah, i see, i have to setup a private maven repo, that sounds good
16:27justin_smithI have not really played with subprojects
16:27magnarssveri: we had this problem, and are in fact using gradle to handle the multi-project part of things, delegating to leining for each project. It's a hassle, tho. A private repo sounds better.
16:27justin_smiththey may very well work nicely, I just have no experience with them
16:28justin_smithcome to think of it, the only time I have heard gradle come up in the clojure world is multi-project stuff
16:28sveriso obv. thats where leiningen is missing something
16:28justin_smithyeah
16:30sveridoes anyone of you use jenkins or bamboo?
16:30magnarswe use teamcity for our multiproject gradle-leining frankenstein :)
16:31sveriany reason why you chose teamcity?
16:32magnarsI wasn't involved in the decision. I know they tried one of the free ones first, but had some issues that teamcity resolved handily. Can't remember any details tho, unfortunately. Sorry about that.
16:32sveriyea, no problem, thank you :-)
16:37BlueOrghello, i'm new to web development in Clojure. I want to parse the data entered into a form on a web page as a Clojure data structure. Can someone point me to specific examples that show how to parse form data into maps. I'm guessing Compojure can do that but i can't find specific examples.
16:40magnarsBlueOrg: that's what http://clojuredocs.org/ring/ring.middleware.params/wrap-params is for :) see :form-params
16:41coventry2sveri, magnars: Got to go, but the problem you're describing sounds like what lein checkout dependencies are for https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies
16:43magnarscoventry2: that's for development. The problem is building multiple private projects in the correct order for deployment.
16:45justin_smithsveri: we use jenkins
16:45justin_smithBlueOrg: compojure is actually pretty small, and just has to do with page routing. Ring is where most of the action is.
16:46justin_smithand the many ring middlewares
16:46BlueOrgjustin_smith where can i learn more about them?
16:46SegFaultAXCheck out Clojure Web Development for an in depth tutorial on building simple web applications in Clojure.
16:47SegFaultAXhttp://pragprog.com/book/dswdcloj/web-development-with-clojure
16:47justin_smithBlueOrg: the ones that come with ring are in ring.middleware.<etc> namespaces
16:58gfrederickshow many folk go out of their way to line up the values in multi-line map literals?
16:58dnolenpretty cool to see CLJS close to CLJ on this - https://github.com/kovasb/combinator
16:58justin_smithmy coworkers do it and it is annoying
16:58justin_smiththey never stay lined up
16:59gfredericksjustin_smith: I was thinking I would do it more if emacs knew how to do it
16:59justin_smith some kind of tabstop mode?
16:59gfredericksprobably? I don't know a lot about emacs wrt this
17:00justin_smithalso, one of the only things I miss about common lisp syntax is the auto-indent of let clauses would actually differentiate bindings from expressions that generate bindings
17:00justin_smith(on a related note)
17:01Bronsagfredericks: https://github.com/gstamp/align-cljlet does it
17:01gfredericksBronsa: oh man look at that
17:01justin_smithBronsa: nice, answers both of our gripes
17:02gfredericksI am going to try this with much haste
17:02BronsaI've beein using it all the time for tools.analyzer AST
17:02gfrederickselisp looks so alien to me
17:02justin_smithgfredericks: was clojure your first lisp?
17:03gfredericksjustin_smith: yeah
17:03justin_smithyeah, clojure is the outlier actually - now I like (most of) its differences though, after having to get over my familiarity based kneejerks
17:05arrdemdoes core.async have support for message passing over sockets?
17:06gfredericksBronsa: omg omg omg it worked
17:06gfredericks(inc Bronsa)
17:06lazybot⇒ 13
17:06gfredericksman this is going to make me hate everybody else's code
17:06Bronsahah
17:06arrdemgfredericks: what did I just M-x package-install?
17:07gfredericksarrdem: doesn't matter just use it
17:07arrdemTIL clojure is a drug...
17:08justin_smithman, can you hook me up? I've been settling for racket and need a hookup asap
17:10arrdemgfredericks: okay. yeah. this is pretty slick...
17:10gfredericksI just bound it to C-c C-a
17:12gfredericksI'm not looking forward to all the "align all the things" commits I have to make. why can't I just run gofmt
17:19BlueOrgany startup using luminus web framework in production? how was the experience?
17:41justin_smithBlueOrg: I work for a digital agency using Caribou (actually we wrote caribou), which is similar to Luminous in many ways. It works great in production for us so far.
17:42justin_smithbut we aren't a startup
17:42BlueOrgjustin_smith yeah. i looked into Caribou. i wish you guys could work on the documentation more and put out a few more sample apps. that would make it much more awesome. like a basic CRUD app.
17:43BlueOrgi'm new to Web development in Clojure.
17:43justin_smithif you just create and run the default config, that creates a crud app
17:43justin_smithalso, our documentation is really extensive, but if there are specific spots where it could use more, let us know
17:44brehautBlueOrg: if you are new to web dev in clojure, start by understanding Ring, and then probably look at compojure (because its a great example of how ring works, even if you dont use it later)
17:45BlueOrgbrehaut okay. thank you. :) i guess there's a section dedicated to it in the Clojure Programming book. i'll read it.
17:46dnolenless half-baked CLJS purgatory https://gist.github.com/swannodette/7631691
17:47dnolentimings at the bottom interesting
17:47dnolenhandles the nested case now
17:47dnolenyou can update something inside but it will invalidate the parent
18:02logic_proghttp://www.clojurescript.net/ <-- how does this clojurescript repl work? is it interperted in the client, or is there some server behind it?
18:03gfrederickslogic_prog: it's cljs-in-cljs, so presumably all in the client
18:04logic_progtaht is badass
18:04logic_proghttps://github.com/kanaka/clojurescript agrees with your analysis
18:13dabdI would like to implement a Tree abstract data type. Should I use protocols and deftype or is it overkill?
18:13bitemyappdabd: overkill.
18:13bitemyappdabd: do a first pass with vectors.
18:13dabdwhy?
18:13clojurebotwhy is the ram gone is <reply>I blame UTF-16. http://www.tumblr.com/tagged/but-why-is-the-ram-gone
18:13bitemyappdabd: [:parent [:child [:grandchild-one] [:grandchild-two]]]
18:13bitemyappdabd: it's simpler.
18:14bitemyappdabd: it's also what the tree based zipping libraries are based on.
18:14bitemyappdabd: also, you had your "why" when I said, "overkill"
18:14justin_smithprotocols and deftype get messy in the repl too
18:14bitemyappdabd: don't use protocols and deftype until you no longer need to ask questions in IRC. So long as you need to ask in here, you're going to get a no. At least from me.
18:15gfrederickso_O
18:16dabdlol
18:16arrdemdabd: the zen of Clojure is that for the most part you don't need to formalize your datastructures with types and protocols. Also protocols and deftypes get nasty in the repl and force restarting a lot :/
18:16gfredericks(inc arrdem)
18:16lazybot⇒ 6
18:16arrdemdabd: there's nothing more workflow disruptive than a repl restart
18:16bitemyapp(inc arrdem)
18:16lazybot⇒ 7
18:16arrdemYAY I DID SOMETHING RIGHT
18:17bitemyapparrdem: replus interruptus
18:17eggheadhm, in core.async how do I wait for multiple go blocks to close?
18:17eggheadsomething with alts! i'd imagine?
18:17arrdem$google replus interruptus
18:17lazybot[The TV Business Keeps Getting Stronger ! | blog maverick] http://blogmaverick.com/2012/01/14/the-tv-business-keeps-getting-stronger/
18:17bitemyappegghead: send nil yo.
18:17arrdemlazybot: you have failed me for the last time, commander
18:17bitemyappegghead: oh you want a "I died" event?
18:17gfredericksis anybody else getting SSL problems fetching from github?
18:17justin_smithegghead: (go (while ...) (this runs when the block closes))
18:18eggheadbitemyapp: I have two channels that close when completed, I just want to wait until they are both done
18:18bitemyappegghead: have them send "I died" signals to alternate channels using justin_smith's example.
18:18bitemyappegghead: when your "they-ded" vector has the count you want, proceed, until then, keep looking.
18:18bitemyapplooping*
18:18bitemyappbut it worked anyway.
18:19justin_smithalso, the other channel could have (or channel-a-open channel-b-open) as its while condition
18:19eggheadsounds reasonable, thanks
18:20bitemyappif I sound reasonable, the world has gone truly mad.
18:20dabdwhat is wrong about using the tree deftype as shown here: https://code.google.com/p/clojure-contrib/source/browse/trunk/src/clojure/contrib/types/examples.clj?r=527
18:21bitemyappdabd: it makes you an asshole and contrib is not an example of good code more often than not.
18:21bitemyappdabd: contrib is dead.
18:21gfredericksdabd: I think the answers you've already gotten still apply
18:21bitemyapp~contrib
18:21clojurebotMonolithic clojure.contrib has been split up in favor of smaller, actually-maintained libs. Transition notes here: http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go
18:22justin_smithdabd: if you are not going to redefine anything, nothing. If you are still working on the code for the definition, you have to restart the repl frequently, because changing a type definition does not change pre-existing instances
18:22bitemyappdabd: why do you ask people for advice and then argue with them?
18:23bitemyappdabd: if you're hell-bent on doing stupid shit, can you do that without wasting other peoples' time in the process?
18:23arrdem bitemyapp: because they're being caustic asshats themselves
18:23bitemyapparrdem: I'm the only caustic asshat allowed.
18:23dabdlol
18:23arrdemI'll leave that to tech's leniency
18:24gfredericksas long as you sound self aware about it it's totally fine!
18:24bitemyappgfredericks: it applies to companies too!
18:24arrdem1d2
18:24clojurebot1
18:24gfredericksdabd: some things you get for free with vectors but not deftype: equality, hashing, serialiation...
18:24dabdcan only laugh about your rudeness. Not arguing with anyone. I am reading on deftype and protocols and I find it hard to learn from docs only.
18:24arrdem(inc bitemyapp)
18:24lazybot⇒ 14
18:25bitemyapparrdem: http://i.imgur.com/OpxSJBf.gif
18:25dabdobviously trees can be implemented with simple lists or vectors. I already know that.
18:25bitemyappdabd: structural sharing, immutability.
18:25gfrederickswell deftype does give you immutability by default
19:02arrdemanyone know of a good dead tree book on the JVM bytecode standard?
19:05justin_smithI don't know of any, but I found a listmania on the subject on amazon after googling
19:07arrdemI'm amazon harder then. a cursory search didn't turn up a clear victor volume.
19:08arrdem*I'll
19:49ambrosebsgfredericks: newtype probably isn't possible with Typed Clojure. instead Typed Racket has refinement types that update a type to say it's passed a particular predicate. (Refinement Long clojure.core/even?)
19:49ambrosebsneed to copy that at some point
19:49bbloomgfredericks: oh yeah, i meant to comment on that earlier, but got distracted
19:49bbloomnewtype is basically (deftype Wrapper [whatever] ...)
19:50bbloomwhere ... delegates all operations on this to whatever
19:50bbloomthen the haskell compiler removes the delegation statically :-)
19:50bbloomso it wouldn't make sense to introduce newtype at the type checker level, you'd need a different aliasing mechanism
19:51ambrosebsbbloom: yea
19:51ambrosebswell put
19:52bbloomgfredericks: refinement types better match my intuitive notion of types, rather than the tag==type notion
20:07arrdemclojurebot: ping
20:07clojurebotPONG!
20:11coventry`,(let [recur (constantly nil)] (println recur) (loop [] (if 1 (recur)))) ; No locals shadowing special forms, I guess.
20:12clojurebotExecution Timed Out
20:16bbloom,(let [recur 5] recur)
20:16clojurebot5
20:16bbloomcoventry`: it's only in call position
20:16bbloombut yeah, it's a major wart of clojure that the specials are not namespaced
20:17bbloom(doc special-symbol?)
20:17clojurebot"([s]); Returns true if s names a special form"
20:18Bronsabbloom: except for import* :/
20:19bbloomweird.
20:33justin_smithis there a way to define a special form?
20:33justin_smithother than forking the core of the language
20:33brehautnot without hacking the compiler
20:33justin_smiththat was my suspicion, cool
20:33brehaut(which you might be able to do at run time but shouldnt)
20:34bbloomjustin_smith: dare i ask: why?
20:34justin_smithbbloom: curiosity
20:34justin_smithnot wanting to make one, but to understand their status
20:34bbloomjustin_smith: good answer :-P
21:02gfredericksbbloom: interesting; I might not have an intuitive notion of types :)
21:04bbloomgfredericks: nah, my intuition just differs from normal sane people 99% of the time
21:04gfredericksbbloom: you must be a fan of structural typing?
21:05gfredericksI feel like this approach is better at describing whether the program will crash, while haskell/tagging is better at describing what the programmer is imagining that things are
21:05bbloomgfredericks: in addition to (where appropriate), not instead of nominal typing
21:07gfredericksnominal typing must be a thing I don't know of
21:07gfredericksif it is neither structural nor tagging
21:07bbloomgfredericks: http://en.wikipedia.org/wiki/Nominative_type_system
21:07dsrxnominal typing just means "do the names of the types on their declarations match"
21:07bbloom== tags
21:08dsrxany usage i've seen (i am a noob) of 'tagging' in type systems refers to the notion of objects carrying type information at runtime
21:09gfredericksoh the nominative != nominal screwed up my googling
21:09gfredericksthese terms must be deemed equivalent via structural typing of english
21:09dsrxlol
21:09bbloomdsrx: no, you're understanding correctly. "tagged" for "tagless" generally refers to the execution strategy
21:11bbloomdsrx: i just don't draw as big a distinction has the PL community does b/c i'm firmly in the optional typing camp. i view tagless as an optimization (one which complects values with the context in which they are accessed)
21:13bbloom$define nominative
21:13bbloomdoesn't lazy or clojure bot do that?
21:13arrdembbloom: there's $google..
21:13bbloom$google define: nominative
21:13lazybot[Nominative case - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Nominative_case
21:13bbloomboo
21:13bbloomadj: relating to or denoting a case of nouns, pronouns, and adjectives (as in Latin and other inflected languages) used for the subject of a verb.
21:14bbloomnominal: (adj) existing in name only.
21:14bbloom*shrug* i guess thye are different
21:14bbloommy bad.
21:27jcromartieCIDER makes me lose my cookies
21:27justin_smithyour cookies?
21:28jcromartieSpecifically, C-c C-k in a Compojure app (with the server defonce'd) causes my in-memory session store to be lost
21:28jcromartieI just wanted to make a vomit joke.
21:28justin_smithhah
21:29justin_smithhttps://github.com/tovbinm/emacs-24-mac/blob/master/etc/COOKIES best result from the google search
21:29justin_smiththe best thing about installing emacs from source is probably all the weird shit they just pack into the source package just because
21:32TimMc$whatis nominative
21:32lazybotnominative does not exist in my database.
21:33jcromartieI guess it's because each time I load the file the top-level handler gets a new in-memory session store from compojure.handler/site
21:34justin_smithI wonder if there is a way to be sure changes to the handler are loaded, without forcing creation of a virgin session store
21:35justin_smithhttp://c2.com/cgi/wiki?NominativeAndStructuralTyping this is a good take on nominative vs. structural typing
21:36{[^-^]}why is clojure much faster than other dynamic languages like ruby and python even though they are imperative?
21:37justin_smithbecause they are too mutable, for starters
21:37justin_smiththere are certain optimizations that do not play nicely with mutation
21:38{[^-^]}even though haskell does lots of optimizations based on purity, it's still not faster than C
21:38justin_smithtoo much of the language depends on state, and preserving state semantics while speeding up code is hard
21:38justin_smithc has the advantage of low cache churn
21:38jcromartiejustin_smith: compiling to JVM bytecode goes a long way, too
21:38justin_smithbut ruby and python are just as shitty about cache usage as the jvm is, so they pay twice
21:39justin_smithonce for being imperative, and then again for type tags and heavy heap usage (non-locality of data)
21:39justin_smithactually the jvm is probably smarter about heap usage than their compilers are
21:40justin_smithbecause of how python and ruby objects are defined, you cannot use them without dereferencing their contained properties at each step
21:40justin_smithbecause there are no promises or limitations about when a mutation in an object could occur
21:41justin_smithI guess that java must be smarter about declaring things final? that part I am less sure of.
21:41jcromartie,(-> 123 #'str)
21:41clojurebot#<CompilerException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:0:0)>
21:41jcromartie,(-> 123 (#'str))
21:41clojurebot"123"
21:41jcromartieI know why, but it's weird
21:42jcromartie,(-> 123 ((var str)))
21:42clojurebot"123"
21:43justin_smithanother weird one:
21:43justin_smith,(-> '{a 0} 'a)
21:43clojurebot(quote {a 0})
21:43justin_smith,('a '{a 0})
21:43clojurebot0
21:45justin_smithanother factor is that python and ruby devs have put little priority on performance in their language design. Both the jvm and clojure are pretty aggressively optimized.
21:45justin_smithand some optimizations aren't just things you can tack on post-facto - they need to be factors in the base level design of the language
21:46justin_smiththat's the caveat to the whole "premature optimization" thing - there is such a thing as preemptive deoptimization through bad design
21:57jcromartiesimple solution: (defonce session-store (ring.middleware.session.memory/memory-store))
21:58jcromartiethen (handler/site app {:session {:store session-store}})
22:07{[^-^]}justin_smith: what about jruby and jython?
22:08{[^-^]}just bad deoptimization?
22:09jcromartie{[^-^]}: I don't think JRuby and Jython get the same JIT or AOT compilation treatment that Clojure do
22:09hiredman{[^-^]}: it is an uphill battle for them, I haven't heard anything performance wise for jython, but jruby has respectible performance due to heroic efforts
22:10jcromartieJRuby is worse than 1.9 as far as I know
22:10{[^-^]}slightly
22:10{[^-^]}ruby 1.8 was much slower than jruby
22:11{[^-^]}I'm starting to think clojure is the fastest dynamic language out there
22:12jcromartiewith enough macros, it can be insanely fast
22:15hiredmanhttp://clojure-log.n01se.net/date/2010-03-23.html#01:55
22:20justin_smith{[^-^]}: common lisps beat it still
22:21justin_smithbut only the ones that target a particular hardware, I think
22:28paomianhow to create 1000 agent by a function
22:31justin_smith,(dotimes [i 1000] (agent i))
22:31clojurebotnil
22:32justin_smithyou probably actually want to hold onto the values though, maybe a loop or a map + doall
22:35amalloy(repeatedly 1000 agent)
22:35paomianjustin_smith: it maybe do not word
22:35paomianjustin_smith: it maybe do not work
22:35amalloyalthough why you would want a thousand agents is beyond me. that almost can't help but be crazy
22:35amalloyoh, i guess i forgot to give the agent an initial value (repeatedly 1000 #(agent 0)), or (map agent (range 1000))
22:35hiredmanamalloy: agent needs an argument
22:36hiredman#(agent nil) or something
22:36amalloyhiredman: already fixed it
22:37hiredmanoh, so you did
22:57coventryThere's 1000 agents in the example at the bottom of http://clojure.org/agents
23:11justin_smithhah, so there is