#clojure logs

2012-10-27

01:16muhoowasn't the nyc the first ever clojure group?
01:16muhooi.e. didn't rhickey launch clojure to the nyc lisp group?
01:16muhooi thought he lived in nyc
01:23amalloyhe's presented at the nyc meetup a number of times
01:25amalloyeg cljs was announced there, and i think he gave a reducers talk not long after releasing them
01:27ambrosebsNow accepting contributions to Typed Clojure (Clojure CA only). Lots of small easy jobs I can give. https://github.com/frenchy64/typed-clojure
01:44Sgeoambrosebs, I assume you use some macro-expander. I trust it's not clojure.walk/macroexpand-all?
01:45ambrosebsSgeo: https://github.com/frenchy64/typed-clojure
01:45ambrosebswhoops!
01:46ambrosebshttps://github.com/frenchy64/analyze rather
01:46ambrosebsIt's an AST :)
01:48tomojwow
01:48tomojnice work
01:49ambrosebsnext best thing to Clojure-in-Clojure!
01:49ambrosebsclojure 1.5.0-beta1 only atm.
01:49Sgeo,(do (require '[clojure.walk :as walk]) (walk/macroexpand-all '(quote (let [a 1] a))))
01:49clojurebot(quote (let* [a 1] a))
01:50SgeoJust a demo of how utterly bad clojure.walk/macroexpand-all is
01:50ambrosebsSgeo: good thing the clojure compiler knows how. ;)
01:51ambrosebsg2g!
01:51SgeoBye
01:52SgeoI should learn how to praise and not just criticise
01:52clojurebotCool story bro.
01:52Sgeo(Not that I have criticism about ambrosebs's work, because I don't)
01:57andyfingerhutDoes anyone know how to modify a Clojure modular contrib module's pom.xml file (e.g. for data.xml) so that I can pass additional command line args to the java commands invoked to compile the code? Or is there a way to do it from the mvn command line?
02:46brainproxytrying to switch over to ritz-swank from swank-clojure but having some problems...
02:47brainproxyi've got a clean lein 2 project, and with the lein-ritz in my profile, I can fire up `lein ritz 4005` for example
02:47brainproxyand then I can use slime-connect to connect to it
02:47brainproxyfrom w/in emacs that is
02:47brainproxybut... I get a warning about slime and swank having different versions, *and* after choosing to continue past the warning, I never actually get a repl
02:48brainproxyi just get a notice the connection was made
03:37muhoonew i7 in the hizzy. now i can clojure it up with impunity.
03:59S11001001andyfingerhut: for scalar datatypes, there's usually a direct mapping between the XML options for each plugin and -D options you can give to maven
04:01S11001001andyfingerhut: I assume the javac options are in string settings, so those should suit
04:25scottjbrainproxy: well ritz does use a different version of slime than swank-clojure
04:43brainproxyscottj: yes, but I had swank-clojure uninstalled and was installed the version of slime rec'd by the ritz-swank readme
04:43brainproxyanyway, for now just using nREPL and nrepl.el
05:12wingyim making a SDK for an HTTP API .. i have some options for how to deal with the HTTP API endpoint: 1. pass the url to the functions 2. hardcode it in the functions 3. have it in the SDK's config.clj file
05:15wingyoption 3 seems to be a flexible one .. what is the best practice for this?
05:27andrewmcveighwingy: you can throw out #2 - that's crazy, #1 might get tedious, passing a URL to every function call.
05:27wingyso 3?
05:28andrewmcveighwell, out of those 3 options, I'd pick #3.
05:28wingyandrewmcveigh: are there more optons?
05:28wingyoptions
05:29wingyandrewmcveigh: i just thought about FP .. shouldn't all data be passed as params?
05:29andrewmcveighmany java/.net sdks use a singleton to store the current "binding" - not suggesting that this is a good option.
05:30andrewmcveighwingy: what do you do with other configurable options?
05:30wingyyeah
05:30wingyi guess i put them in config.clj
05:30wingybtw .. i think having a *service-url* is good
05:31wingymuch better than a config.clj
05:31andrewmcveighhow do you set *service-url*?
05:32wingyandrewmcveigh: does this mean that i have to wrap them inside (binding [*service-url*] (make-request))
05:32wingyyou said binding and i thought about dynamic binding
05:32andrewmcveighI quoted "binding", because it has nothing to do with clojure's binding...
05:32wingybut that is a good idea?
05:33wingykinda like *out*
05:33andrewmcveighPersonally, I don't think singletons are a good idea in clojure, but I'm no expert.
05:35andrewmcveighwingy: I think if you're doing something like (binding [*service-url* (:service-url (read-config))] (make-request)) - that's alright.
05:36wingyandrewmcveigh: is there a way to set *service-url* once so all SDK fns dont have to be wrapped?
05:37andrewmcveigh,(doc alter-var-root)
05:37andrewmcveigh&(doc alter-var-root)
05:37lazybotjava.lang.SecurityException: You tripped the alarm! alter-var-root is bad!
05:38Bronsa,alter-var-root
05:38Bronsa&alter-var-root
05:38lazybotjava.lang.SecurityException: You tripped the alarm! alter-var-root is bad!
05:38Bronsawoah :(
05:38andrewmcveighwingy: or you could use an atom/ref to hold it.
05:39andrewmcveighwingy: that's mutable territory though.
05:40wingy,(def *service-url* (atom "http://service.com/api"))
05:40wingyi'll try with it
05:41wingynot mutable, but switchable right?
05:41wingythe current state changes .. but the values don't
05:42andrewmcveighif state changes... is that not mutation?
05:45wingyis it?
05:45wingyok mutation in the identifier
05:46wingycorrect me if i am wrong
05:47andrewmcveighfrom http://clojure.org/atoms "Atoms provide a way to manage shared, synchronous, independent state. "
05:48andrewmcveighso if you (reset! atom1 5), you've changed it's state.
05:49andrewmcveighit's just been managed by clojure.
08:56wunkiI keep getting "method not found" for trying to call the static `of` method here: http://thumbnailator.googlecode.com/hg/javadoc/index.html
08:56wunkitrying to call it with `(Thumbnails/of ...)`
09:06keugaerg,(+ 2 3)
09:07keugaergret
09:08jonasachi, kinda new to clojure trying to get the examples repo form programming clojure2nd edition to work
09:08jonasacdid lein deps and it installed a bunch of stuff to .m2 folder
09:08jonasacbut when i run lein repl i cant import the example code like the book says
09:08jonasacbeing told examples is not in the classpath
09:09rod_what's the command you're using to import the example code into the repl jonasac?
09:09jonasac(require 'examples.introduction)
09:10rodnaphand the file is "src/examples/introduction.clj"
09:10jonasacyep
09:10rodnaphwith (ns examples.introdution) as the namespace?
09:10rodnaphand u start the repl from the folder that contains "src"
09:11jonasacyes and yes
09:11rodnaphwhat's the exact error? can you paste an example session to refheap.com (from cd'ing to the folder, ls'ing the contents and starting the repl)
09:12jonasaclein self-install helped
09:12jonasaci installed clojure via homebrew
09:12jonasacbut it works now
09:13rodnaphoh right (sorry if i got the wrong end of the stick, just joined channel)
09:14jonasacno, thanks for the help, just joined myself
09:15jonasacbeen mising lisp ever since SICP at uni
09:16rodnaphclojure is my first lisp, real eye opener though.
12:06erwagasoreI am doing clojure koans and I am stuck, need help: (= 25(__ ((fn[n] (* n n))))
12:06erwagasorewhat should I put in __ place?
12:08antares_erwagasore: do you have a link to the example?
12:10erwagasoreantares_ line 24 test https://github.com/functional-koans/clojure-koans/blob/master/src/koans/06_functions.clj
12:11antares_erwagasore: ok, that example makes sense
12:12erwagasoreantares_ maybe I need to understand what|how higher-order functions works after all.
12:13antares_http://clojure-doc.org/articles/language/functions.html#higher_order_functions
12:14antares_,((fn [f] (f 5)) (fn [n] (* n n)))
12:15antares_$ ((fn [f] (f 5)) (fn [n] (* n n)))
12:15antares_~((fn [f] (f 5)) (fn [n] (* n n)))
12:15antares_lazybot: help
12:15lazybotYou're going to need to tell me what you want help with.
12:16antares_erwagasore: well, here is your answer: a function that takes another funtion (the squaring one) and calls it with an argument of 5
12:30erwagasoreantares_ amazing thanks now I understand
12:39dnolenbbloom: thx for the core.logic patch
13:22tomojsitting here wondering whether I need to create a new datomic db or whether the changes I made to the schema are compatible with what's already there. I hadn't committed to git yet. I should have, but still, using git history for that would suck. a few lines of code lets me say "ok, pretend I committed this schema tx, then clojure.data/diff that with my current schema" :D
13:30TimMclazybot: help me with my homework
13:30lazybotTopic: "me" doesn't exist!
13:31TimMcOh good, it isn't self-aware yet.
13:38hyPiRionlazybot: What is the purpose of life?
13:46hyPiRionWell, it isn't even aware.
13:46hyPiRionAt least not fully aware.
13:46AdmiralBumbleBeemaybe it is aware, but it's too lazy to make it fully apparent
13:47tomojit seems aware of some of what I type
13:47AdmiralBumbleBeeit's aware of all of it, too lazy to respond to all of it
13:48AdmiralBumbleBeemaybe someone needs to kick it with a doall
13:58bbloomdnolen: my pleasure. thanks for posting that OZ link on the mailing list the other day. i found it really helpful for understanding how core logic works
14:00dnolenbbloom: Oz is pretty neat, the Prolog-like bits of core.logic are quite different from Oz, but I basically want to steal the Oz FD feature set wholesale
14:01bbloomdnolen: yup, i'm most interested in optimization
14:02bbloomas in minimization, not perf
14:02bbloomalthough perf is also important :-)
14:03bbloomdnolen: are there any examples of solver systems that include both a finite domain solver and some other category of solver? for example a linear programming solver that operates on floating point values?
14:03dnolenbbloom: as am I. core.logic needs a distribute functionality - it's pretty easy add.
14:04dnolenbbloom: core.logic already has multiple solvers, CLP(Tree) & CLP(FD), it's also a goal for both to be present in the same program.
14:05dnolenbbloom: and I would like to see CLP(R), floating point ops
14:05bbloomdnolen: same program == same top-level "run" form? i.e. the same constraint system?
14:06bbloomdnolen: seems like this CLP(X) form turns up some results in the literature. is there a survey of this terminology and the various types of solvers?
14:06dnolenbbloom: different constraint solvers in the same run yes
14:06bbloomdnolen: i may be interested in contributing a Simplex solver for linear inequalities -- I want to use it for UI layout
14:07dnolenbbloom: I'm not aware of a survey, but lots of various papers of course
14:07dnolenbbloom: that would be sweet
14:09bbloomdnolen: meanwhile, i have my CLJS CPS transform in pretty good shape… there's one small patch to analyze fn methods that would help me get it to a released state :-)
14:10dnolenbbloom: cool, yes I saw that will take closer look soon. related, your patch did break top level lets, do you have any thoughts about fixing that?
14:10bbloomtop level lets? hmmm
14:10bbloomlet me look
14:11dnolenbbloom: http://dev.clojure.org/jira/browse/CLJS-401
14:11dnolenbbloom: top level lets just drop JS vars at the top level, gensym protected overwriting, that's no longer the case
14:11bbloomdnolen: d'oh! makes sense
14:11gtrakerrr... someone must know the answer to this. I've been trying to create a clojure.test fixture that looks for exceptions in an agent, and I can't find a proper way to report the error. Throwing exceptions kills the main test-runner thread, using clojure.test/do-report seems to die on 'lein test', though it works on swank: https://gist.github.com/27cac036ef633a2b5cdd
14:11bbloomill see what i can come up with
14:12dnolenbbloom: thx much
14:12dnolenbbloom: I mention a possible fix, but I haven't had a chance to try it out. Might totally kill perf since if you have enough nested functions GClosure won't optimize.
14:13gtrakthe current approach: https://gist.github.com/562db53028a9a9a0218c
14:16bbloomdnolen: i know GClosure can optimize away top level self invocations … those (function() { … })(); forms
14:16bbloommaybe we should do that for every top-level?
14:18dnolenbbloom: hmm, I'd prefer a patch that only did for top-level lets.
14:19bbloomdnolen: sure. it may be generally value to include "is top level" in the AST somehow
14:19bbloomalthough, i guess you can infer that....
14:20dnolenbbloom: yeah I thinking you could tell this from env right, if so perhaps this is a simple fix.
14:22bbloomwell env is statement, expression, return
14:22bbloomthere isn't really top-level, since that is the same as statement
14:23gtrakI think it's because I'm not having proper bindings... grr.....
14:25bbloomdnolen: yeah, it's not sufficient to do only top level lets
14:25bbloomconsider:
14:25bbloom(do 1 (let [y 2] (js/alert y)) 3)
14:25bbloomthat exhibits the same issue
14:28dnolenbbloom: do doesn't introduce bindings so I'm not really concerned about that
14:29bbloomdnolen: no, the output of that is:
14:29bbloomvar y = 2; alert(y);
14:29dnolenbbloom: oh right
14:29bbloomstill happens
14:29bbloom:-/
14:29bbloomdnolen: i think i can just change compile-file to wrap each top-level & it will be all good
14:30dnolenbbloom: sure give it a shot.
14:36bbloomdnolen: hmm interesting… compiler.clj and closure.clj both have a compile-file method… but it seems like the one in compiler.clj is unused
14:37dnolenbbloom: it used, closure.clj line 356 calls compile-file in compiler.clj
14:37dnolenbbloom: also line 398
14:37dnolencomp/compile-file
14:38bbloomah comp/compile-file yes.. but the later case is a reference to line 349
14:42bbloomdnolen: ok, well this seems to work. let me cleanup & test a bunch of stuff & then i'll submit a patch
14:46dnolenbbloom: excellent
14:47wingywhat is the equivalent of setTimeout in clojure?
14:47bbloomdnolen: eh, never mind. doesn't play nice with def & especially with advanced optimizations
14:47wingy(with-timeout)
14:47wingyor hmm
14:48dnolenbbloom: darn. in what way is problematic w/ def?
14:49dnolenwingy: ScheduledThreadExecutor I think
14:49bbloomwell so you get globals by omitting the "var" keyword
14:50wingydnolen: can i use Thread/sleep
14:54dnolenwingy: that's not really equivalent to setTimeout as that will block execution of your program unlike in JS
14:54amalloyof his current thread, anyway
14:54bbloomdnolen: ok, so the issue is that in advanced mode, top-levels of the form x.y.z = w will get intelligently converted to namespace export things, where x and x.y will be initialized to {}
14:55bbloomdnolen: but if you wrap the func around that, then it won't do it
14:55dnolenbbloom: right
14:55bbloomdnolen: not sure if there's a way around that
14:57bbloomgoog.provide?
14:57dnolenbbloom: doubt it. I think we need to reify the notion of the top level in the AST, perhap a :scope field in env, it gets set to top
14:57dnolenbbloom: let will should modify the scope to be something other than :top
14:57bbloomdnolen: that won't help because you can have a def inside a let
14:58bbloom(let [x 1] (def y x))
14:58bbloomif you wrap that in (function(){…})();
14:58bbloomthen def breaks
15:00dnolenbbloom: I think the approach on the ticket is ok minus the hacky dynamic var bit. just gensym top level lets in the compiler.
15:00dnolenbbloom: on the existing patch on the ticket.
15:03dnolenbbloom: there lots of annoying edge cases to consider here. "the top level is hopeless" to quote Felleisen
15:04bbloomdnolen: goog.provide is what we want :-P
15:06dnolenbbloom: ah so you're suggesting wrapping everything, and emitting a provide for each top level? :)
15:06bbloomyes
15:06bbloomtrying that now
15:06dnolenbbloom: k
15:07bbloomdnolen: should also help with some dependency analysis stuff, since now goog closure will have publish export info for each def
15:08wingyis jetty creating a thread for each request?
15:09dnolenwingy: yes
15:09bbloomsurely it has a thread pool…
15:11dnolenbbloom: right, wingy: using a thread per request
15:13wingycool
15:14wingysoon you will see a good comparison between js/node.js/express and clojure/ring/compojure/hiccup
15:15Sgeoexpress?
15:15tomojgreat
15:16tomojI plan to argue that to my team shortly
15:16Sgeo:/ is that the thing my gf is raving about?
15:16tomojexcept .. hiccup
15:17bbloomdebugging advanced output is a pita.
15:18dnolenbbloom: yep
15:27brainproxyexpress is pretty nice, there's also restify and strata
15:28tomojI haven't thought about it enough yet, but I expect the choice connect made about middleware causes trouble for express
15:28brainproxythey all work similarly but have different goals, if you will, and so offer different bells and whistles
15:29tomojexpress 3.0 may have completely solved that trouble, but I doubt it
15:29brainproxytomoj: can you elaborate?
15:29brainproxyin any case, I now vastly prefer ring/compojure/liberator
15:30tomoja middleware in connect is like (fn [req res next])
15:30brainproxyhaven't had occasion yet to experiment w/ aleph
15:30tomojwhere ring has (fn [next] (fn [req] res))
15:30tomojI suspect this causes composability issues
15:31brainproxywell, passing the res object along is pretty important given the async nature of things
15:31tomojnot to mention that you side-effect a response out instead of returning one
15:31tomojthat's just because they didn't solve the async problem
15:32brainproxywell given that js doesn't have threads, then unless you're going to introduce a control flow mechanism along with the router
15:32brainproxythen you're stuck w/ the "async problem"
15:32brainproxyalthough some folks don't see it as a "problem" per se
15:32brainproxyit's just the nature of the beast
15:33tomojyeah, it could make sense to build something better over connect
15:33brainproxyi think the approach strata takes is to embrace the streams concept very deeply
15:33tomojif you can return a response stream, great
15:33brainproxyso as you pass control through the handlers, you're working with streams
15:34tomojor do you just write to the response stream they give you?
15:35brainproxytomoj: not sure, haven't really gotten into it, just know some folks using it, heard them talk about it, have looked at the website from time to time
15:35brainproxyhttp://stratajs.org/manual
15:38AntelopeSaladwhat is the standard way to run jetty in production mode if any?
15:38tomojlooks nicer
15:38tomojmiddleware has the right shape
15:40tomojit looks weird because you create a Response out of nowhere and then response.send(callback), but that's pretty much sugar for passing the response to the callback, which is the low-level async equivalent of returning it
15:43tomojhttp://news.ycombinator.com/item?id=3021564 "leaky abstraction" looks like a fully general counterargument
15:43tomoj""leaky abstraction" looks like a fully general counterargument" looks like a fully general counterargument :(
15:46brainproxyit's been over a year since that HN piece, and the project is still actively dev'd
15:47brainproxyso I guess something's working out for the users of it
15:51bbloomdnolen: sorry, had to step out
15:51bbloomdnolen: unfortunately, i don't think my idea works either… b/c then you have conflicts between top level vars and namespace names.
15:51bbloomdnolen: consider namespace foo with symbol bar and namespace foo.bar with symbol baz
15:53bbloomthis further solidifies my belief that, while cute, POJsO make poor namespaces
15:56bbloomhmm i guess the top-level vs namespace conflict already exists....
15:59dnolenbbloom: yeah I don't see how that's a problem.
16:04AntelopeSaladis there a ring setting i need to enable so it handles etags properly?
16:06tomojis there an entity binding syntax hidden in datomic already? something like :where [?p {:person/name ?name :person/age ?age}]
16:06tomojI mean besides :where [?p :person/name ?name] [?p :person/age ?age] ofc
16:08sritchiedoes anyone here have experience with monadic parsing in clojure?
16:08sritchieI'm writing a parser using clojure.algo.monads and working off of the numerous recursive descent parser blog posts out there,
16:09sritchiebut I haven't seen any project that pulls all of those combinators together into their own project
16:10gensymvhello, is there a particularly good way of defining pointfree functions in clojure?
16:10gensymvdefining them with def seems a whole lot slower then explicitly naming the arguments
16:14gensymvsee exhibit a https://www.refheap.com/paste/6185
16:15callengensymv: well you know what they say about points-free programming...
16:15callengensymv: it's pointless.
16:16gensymvcallen, that's really helpful.
16:16callenI was going for punny.
16:16jasonjcknsritchie: I don't, but have you tried asking for help within your near social network?
16:16sritchiejasonjckn: :)
16:16dnolengensymv: there's very little support for that style in Clojure
16:16sritchiejasonjckn: I'll use your clarsec
16:16jasonjcknSweet
16:16sritchiecan we get it updated to use clojure.algo.monads?
16:17bbloomgensymv: that's function call overhead of less than 0.0003 msecs
16:17jasonjckn i wrote my own monad
16:17bbloomseems pretty reasonable to me
16:17Sgeosritchie, clojure.algo.monads's maybe-m monad breaks the monad laws
16:17callensritchie: you should write a parser for C++
16:17gensymvbbloom, i see it as approx 30 times slower ^^
16:18sritchieC++ to clojure, that'd be a nice weekend
16:18callensritchie: my deeper point is that I'd be impressed if you simply wrote a passable C++ parser in using parser combinators.
16:18callen'simply'
16:18sritchiejasonjckn: writing your own parser monad's cool, but defining it using clojure.algo.monads lets you use the existing domonad, m-lift, etc
16:18sritchieSgeo: interesting
16:19bbloomgensymv: seems like premature optimization to me....
16:19dnolengensymv: you should look at the implementation of partial - it relies on rest args and apply, you're just not going to get super great perf out of partial.
16:19jasonjcknsritchie: I have those 2 ops
16:19jasonjcknsritchie: take it or leave it :)
16:19jasonjcknsritchie: an exercise to the reader is to port it yourself
16:20gensymvdnolen, so you essentially say that currying is not what clojure is built for.
16:20bbloomgensymv: no. you can do currying
16:20sritchiecallen: I'm working on a far more junior-level project
16:20bbloomgensymv: what dnolen is saying is that partial supports variadic functions
16:20sritchieparsing the thrift IDL
16:20gensymvah
16:20callensritchie: parsing C++ is demi-junior.
16:21bbloomgensymv: which haskell doesn't…. which makes optimizing currying and partial application easier
16:21gensymvso the two functions aren't semantically equivalent
16:21wingywe have a guy here wanting to switch back to node.js because he says jetty can't cache correctly
16:21bbloomgensymv: right. you can implement curry without var args & you'll get better perf
16:21wingyis this correct?
16:21callenwingy: that doesn't make any sense at all.
16:21callenwingy: cache what?
16:21gensymvbbloom, thanks that is helpful.
16:22jasonjcknsritchie: one disadvantage algo.monad is you need to wrap everything in with-monad, makes it hard to C-xC-e your parsers with interactive development
16:22sritchiesure, that's true
16:22callenwingy: jetty is a web server.
16:22Sgeosritchie, note protocol monads, a different implementation. Although it uses do as a macro name, which kind of sucks
16:22dnolenwingy: it's so sad that some of the thing they say about Node.js users is so true - http://www.youtube.com/watch?v=bzkRVzciAZg
16:22jasonjcknsritchie: also, because i'm using multi methods, you can derive monad's from other monads, although I haven't used that feature, limited value afaik.
16:22marcellu`how do I call extend-type for a type from a different namespace?
16:22callendnolen: <3
16:23sritchieSgeo: interesting, thanks for the tip
16:23Sgeoyw
16:23sritchiehttps://github.com/jduey/protocol-monads
16:23callensritchie: now go write a C++ parser
16:23sritchiewill do, sensei
16:23wingydnolen: im on your side
16:29antares_marcellu`: the same way but you make it qualified, e.g. otherns/MyType and you may have to import it in some cases
16:30tomojhmm, `:where [(fn-returning-integer ?x) [?int ...]]` gives "Don't know how to create ISeq from: java.lang.Integer" as expected, but `:where [(fn-returning-integer ?x) ?int]` gives "ArrayIndexOutOfBoundsException 2"
16:30tomojoh
16:30tomojwhoops
16:32antares_wingy: Jetty is an embeddable Web server. It almost certainly does not do caching automatically (not of its business) but you can set etags/last-modified in your app just like with anything else.
16:32jasonjcknsritchie: honestly, as cool as monadic parsers are, recursive decent parsers will never surpass LR/LL parsers afaik in performance
16:32jasonjcknsritchie: https://github.com/cgrand/parsley
16:32sritchieyeah, that lib is really cool
16:32jasonjcknsritchie: never used it, but that's probably the best clojure parser
16:32wingyAntelopeSalad: ^
16:32sritchiefor anything beyond thrift / learning experience, I'd go there
16:32sritchiemaybe I'll do it in both
16:35wingyhttp://www.youtube.com/watch?v=bzkRVzciAZg good one :)
16:39jasonjcknsritchie: so you're trying to build a parser with algo.monads and you're not sure how?
16:39sritchieno, I'm doing fine
16:40sritchieit works, it's great,
16:40sritchiejust wanted to know if someone else had built up these combinators in a lib I should use
16:40jasonjcknsritchie: never seen a lib that used algo.monads
16:40jasonjcknmost people rolled their own
16:40sritchiemidje
16:40jasonjcknfor parsing?
16:40sritchieno
16:41jasonjcknok I meant to add that qualifier
16:41sritchieI think you did parsing before algo.monads
16:41sritchieyeah
16:41jasonjcknyes
16:41jasonjcknexactly
16:44mklappstuhlI'm having trouble with namespaces here: https://github.com/mklappstuhl/computational-investing.clj
16:44mklappstuhltrying to load the core presents me this:
16:44mklappstuhluser=> (require 'mklappstuhl.stock-utils.core)
16:44mklappstuhlWARNING: extend already refers to: #'clojure.core/extend in namespace: mklappstuhl.stock-utils.util, being replaced by: #'clj-time.core/extend
16:44mklappstuhlCompilerException java.lang.IllegalArgumentException: Parameter declaration quote should be a vector, compiling:(mklappstuhl/stock_utils/metrics.clj:1)
16:45jasonjcknmklappstuhl: you don't nest defn's inside ns
16:45jasonjcknmklappstuhl: (ns foo) (defn …) etc
16:47mklappstuhljasonjckn, I which file am I doing this?
16:47jasonjcknsritchie: some languages need to be tokenized in order to parse successfully.
16:47antares_mklappstuhl: metrics.clj, see the exception?
16:47jasonjcknhttps://github.com/mklappstuhl/computational-investing.clj/blob/master/src/mklappstuhl/stock_utils/metrics.clj
16:48mklappstuhljasonjckn, wtf o.O I have this file open in vim and it looks completely different ?!
16:48jasonjcknmklappstuhl: save it
16:49mklappstuhljasonjckn, I just closed and reopened it and its still the correct version
16:49jasonjcknwell push your changes to git
16:49jasonjcknmaster
16:50mklappstuhljasonjckn, sure. I just did git add . and git commit 2 minutes ago...?! kind of confusing, haha
16:51mklappstuhljasonjckn, pushed
16:51jasonjcknok it's updated
16:52jasonjcknthat file looks fine
16:52jasonjckntry recompiling
16:52mklappstuhljasonjckn, seems to work now...
16:53mklappstuhljasonjckn, sorry this probably made a wierd impression :D
16:54jasonjcknsounds like you had some old cached files, not sure
16:56jasonjcknsritchie: consider if ( true ) {}; if = 2; if your parser is (<|> assignment-statement-pfn if-statement) then you'll incorrectly accept 'if' as a variable name
16:57jasonjcknsritchie: unless your assignment-statement-pfn is defined to exclude the parsing of keywords. which if expressed through combinator parsers would be super slow
16:58jasonjcknthe correct way to handle that is to tokenize first (with maximal munch)
16:59jasonjckn…so the assignment-statement-pfn will try to accept the token "symbol" and it'll encounter the token "if"
16:59jasonjcknand fail
17:00RoxxiHey, if I want to make a new record that is sortable, is there a Protocol or interface I can have it implement so that (clojure.core/compare rec1 rec2) automatically works?
17:00RoxxiI suppose analgous to Comparable?
17:01RoxxiOr is it just java.lang.Comparable o.O
17:04RoxxiLooks like it is..
17:05bbloomdnolen: see http://dev.clojure.org/jira/browse/CLJS-401?focusedCommentId=29830
17:06dnolenbbloom: so we don't need goog.provide?
17:07bbloomdnolen: nope! the issue was that i needed to not wrap the top level ns form
17:07dnolenbbloom: excellent! this looks good!
17:08dnolenbbloom: thx much
17:08bbloomdnolen: my pleasure! but while you're thanking me, you can also merge the patch at http://dev.clojure.org/jira/browse/CLJS-408 :-)
17:09Kneferilishello
17:10dnolenbbloom: will do will apply these in a little bit
17:11bbloomdnolen: one last one: a small cleanup i made while working on the top-levels patch: https://gist.github.com/3966254
17:11bbloomdnolen: if you want that too :-)
17:12dnolenbbloom: sure ticket+patch I'll apply it as well.
17:12bbloom*sigh* so much overhead :-/ but ok
17:13bbloomcan i sneak it in on the other ticket? heh
17:13dnolenbbloom: heh, nope
17:15bbloomhttp://dev.clojure.org/jira/browse/CLJS-409
17:15dnolenbbloom: thx
17:28mklappstuhlI have this little project here and I'd like to run simulations on collections of stock symbols... I have a rough draft of how I could structure this in simulate.clj but I'm pretty sure there are other more clojure-esque ways to do this
17:29mklappstuhlso I'd love to have some input :) 'm just starting with clojure btw
17:30gfredericksis simulate.clj a library? or just a file of yours?
17:30mklappstuhlhttps://github.com/mklappstuhl/computational-investing.clj
17:31mklappstuhlgfredericks, forgot the link somehow ... ^
17:31gfredericksrighto
17:32gfredericksI'm more prone to comment on low-level things first
17:32gfrederickslike your call to hash-map could be a map literal
17:32gfrederickse.g., (hash-map name trades) => {name trades}
17:33gfrederickshard to say much more about this without knowing how you're intending to use it
17:33mklappstuhlgfredericks, I know about the hash map thing... I just feel like its more readable
17:34mklappstuhlI'm happy about any input like this one too though
17:34gfredericksI almost never see clojure code like that; but it's a minor point, and even more minor if this code is just for yourself
17:36mklappstuhlgfredericks, I want to run simulations on historical data with fictional transactions at the beginning
17:36mklappstuhlkind of like:
17:36mklappstuhl10MM of AAPL shares
17:36mklappstuhl5MM of IBM shares
17:37mklappstuhlwith a date when the stocks were bought and an end date for the simulation
17:37mklappstuhlgfredericks, good to know about the hash-map convention
17:40gfredericksso you're simulating the value of a fictional portfolio given actual historical prices?
17:40mklappstuhlgfredericks, yes
18:00dnolenbbloom: patches applied
18:01bbloomdnolen: cool, thx
18:47RaynesHrm
18:47thearthur_strange Incanter problem,
18:47RaynesI wonder how targeting nodejs and writing libraries in it works.
18:47thearthur_yesterday incnater charts stopped displaying (i suspect they are displaying off screen)
18:48gensymvhello, in ubuntu 12.10 i installed the package clojure-contrib, but somehow cannot "use" it from clojure. i tried locating the libraries but had no lock with it. can anybody help me pls?
18:48gensymv*luck
18:52bbloomRaynes: you mean for cljs? it should work reasonably well, but won't really play super nice with the module system
18:53Raynesbbloom: I'm talking about how one would write a library in cljs they could distribute with npm and use in other nodejs-targeting cljs apps.
18:53RaynesThe whole namespace system for regular clojurescript makes no sense to me at all though.
18:53RaynesSo I don't really even understand how you'd do that there either.
18:54bbloomRaynes: well clojurescript piggybacks on Google Closure's module system. if you wanted to target node's module system, you could just refer to js/window.exports to bypass the symbol munging in both cljs and google closure
18:54RaynesThat easy, eh?
18:54Raynes;)
18:55bbloomRaynes: heh, yeah it is. just use bin/cljsc in the clojurescript source tree. when used with advanced compilations, it will compile your entire app to a single .js file
18:56RaynesHow does that help with library distribution?
18:56bbloomRaynes: in that file, you can do something like (set! js/window.exports somesym somesym) to export functions to the node ecosystem
18:56bbloomjust check in the .js output :-)
18:56bbloomi think package.json can run your build script pre-publish too
18:57RaynesThat's kinda convoluted though, isn't it? And it also includes all of Clojure as well.
18:57bbloomin theory, it should only include the bits of clojure that you depend on
18:57bbloombut we've got still some shortcomings for dead code removal
18:57bbloomyou just make sure the functions that you expose take plain javascript objects
18:57dnolenRaynes: someone could easily provide CLJS w/ simple optimizations + :static-fns as an npm module, and
18:57bbloomsimilar to how you'd stick a C interface on a C++ library
18:58bbloomjs/window.exports -> js/module.exports
18:58dnolenRaynes: then CLJS compiler would need a option to compile w/o core so you can provide your own libs w/ core as a npm dep
18:58bbloomsorry, been a while since i did some node.js
18:58dnolenbbloom: dead code elimination matters a whole lot less for node.js
18:59bbloomdnolen: i know, but Raynes said "it also includes all of Clojure as well" :-)
18:59dnolenbbloom: non-issue in my mind.
18:59bbloomagreed
18:59dnolen20,000 lines of JS is nothing to v8
19:00RaynesBut wouldn't there be issues with duplicated functions, or clashes, or something?
19:00dnolengiven that tools like emscripten generation hundreds of thousands of lines of JS and the modern engines handle it well
19:00dnolenwho cares on the server
19:00RaynesIt wasn't size I was worried about.
19:00bbloomRaynes: node's module system should protect you there
19:00dnolenRaynes: I mentioned ^ that you would need a way to compile your own lib w/o core.
19:01dnolenRaynes: we could add that feature to the compiler.
19:01RaynesBut didn't you just say that it didn't matter? :(
19:01dnolenRaynes: I said dead code elimination didn't matter.
19:01dnolendifferent thing altogether
19:01dnolenadvanced compilation is not relevant for server side JS
19:01bbloomheh, i think it doesn't matter… doesn't node's module system prevent globals without explicit references to `global`?
19:02bbloomdnolen: i mention using advanced compilation so that you can get a single js output w/o needing to muck with the stitching logic of that top level output js file… but there may be some other easy way to get a build step to concatenate those
19:02dnolenbbloom: yeah but I'd still be concerned w/ confusing v8 and deoptimization if multiple versions of cljs.core are getting loaded.
19:03bbloomdnolen: ah, good point. i forget that we muck w/ prototypes
19:06bbloomdnolen: in general, there is some ugliness in the compiler around the module system
19:06bbloomit might be nice to provide something like a namespace compilation protocol, to support pluggable module systems
19:06bbloomwould be nice to decouple us from the closure compiler, even tho it's super useful now
19:07dnolenbbloom: yes Node.js case in point
19:08bbloomdnolen: yup :-) also worth discussing at some point is the namespaces atom
19:08dnolenbbloom: though the Node.js module model simply sucks in a massive way.
19:08dnolenthe whole wrapping all libs in function making everything opaque is total shit.
19:08bbloomdnolen: yeah, common.js is the simplest possible realization of the brain dead objects == maps == namespaces world view
19:09bbloomdnolen: it's particularly great for thwarting interactive development. you want to "use" some symbol, so you do `var foo = pkg.foo` and then you later want to redefine pkg.foo, but that doesn't impact `var foo`!
19:10bbloomargh.
19:10bbloompython suffers from a similar issue
19:10dnolenbbloom: so it makes adopting the Node.js model in the compiler less compelling, but it means sharing libs w/ Node.js and vice versa kinda lame as it is today.
19:11bbloomeither way, protocol-izing the module system would help us better understand the requirements
19:11dnolenthough to be honest I just don't see Node.js folks using CLJS libs, the style of programming is just incredibly different.
19:12bbloomtangentially related: i'd also like to purify that ana/namespaces atom ;)
19:12dnolenbbloom: sure what do you have in mind?
19:12bbloomoh heh, i already said that…
19:12bbloomdidn't mean to repeat myself :-)
19:13bbloomsome kind of "compilation unit" AST node
19:13dnolenbbloom: ? in ana/namespaces ?
19:13bbloomno, instead of that atom
19:14dnolenbbloom: what for?
19:14bbloomi haven't fully thought it out, but i ran into some minor annoyances while debugging my CPS transform b/c that atom was stateful
19:15bbloomor at least b/c it is bound at the top-level, rather than within the scope of a compilation unit
19:15dnolenbbloom: this will require considerable thought since the utility of having it around for reflection is quite significant
19:16bbloomdnolen: yeah, it's just a gut reaction to "ugh, that thing annoys me".. i wonder if it could be made unbound and :dynamic, and then there could be a with-world type macro
19:17bbloomdnolen: definitely needs more thought. I'm just gonna let the thought bake for a while
19:17dnolenbbloom: it's worth investigating, would allow lein-cljsbuild to get parallel builds back too.
19:17bbloommmm parallel builds :-)
19:18bbloomoh, that brings up one other thought
19:19bbloomAST transformations seem to be inherently discrete. by that i mean you have to complete transform A before you can do transform B. if you wanted parallelize, you could only really do it by compilation unit
19:19bbloomi wonder if top-levels could be processed lazily… such that you could have A run on form 0, then while A is running on form 1, B is running on form 0
19:19bbloomdnolen: does that make any sense?
19:20bbloom(assuming you have two cores)
19:20bbloomi think i answered my own question: yes :-P
19:21bbloomexcept that the top level ana/namespaces prevents it...
19:21dnolenbbloom: heh lein-cljsbuild parallel-build was just a way to build multiple version of the script at the same time
19:21dnolenbbloom: you're thinking about something more ambitious
19:22dnolenbbloom: having the compiler be able to compile different files in parallel would probably be the source of the most win w/o adding too much complexity.
19:22frawrHaving some unexcpected behavior with lein run here. When I change something in the code and do lein run again, i get weird errors. I have to call lein clean first everytime.
19:22bbloomdnolen: yup
19:23amalloyfrawr: aot compilation makes things complicated. don't do it unless you absolutely have to
19:23frawrSo clear the aot list?
19:23frawrAnd when would I have to?
19:24frozenlockIs there a function like clojure.contrib.string/take available?
19:24amalloymainly when you want to expose a named class to a java program, or if you need really complicated gen-class stuff
19:24amalloy&(doc subs)
19:24lazybot⇒ "([s start] [s start end]); Returns the substring of s beginning at start inclusive, and ending at end (defaults to length of string), exclusive."
19:24frozenlockExcellent, thanks!
19:25amalloyfrawr: yes, clear :aot, and adjust your main entry -- :main ^:skip-aot myapp.main
19:27frawrthnx
19:28frawrthe errors are normal ones now, thnx. speeds up the proccess a whole lot.
19:29biscarchHow do I access a Java property? Equiv code in Java would be Environment.SANDBOX
19:30bbloomEnvironment/SANDBOX
19:30biscarch::facepalm:: thanks
19:30hyPiRion,(Integer/MAX_VALUE)
19:31hyPiRion&(Integer/MAX_VALUE)
19:31lazybot⇒ 2147483647
19:31hyPiRion&Integer/MAX_VALUE
19:31lazybot⇒ 2147483647
19:33bbloomdnolen: so let me know how i can help with distributions stuff in core.logic. I'd really love to general purpose minimization technique for prototyping a bunch of ideas i have :-)
19:34bbloomdnolen: i may ultimately need special purpose solvers, but general minimization would go a long way during the design phase
19:47dnolenbbloom: there's a key fn called map sum which tries each value of vars domain
19:48dnolenbbloom: a bunch of strategies could be added there, including possibly a custom cost function which knows how vars are entailed and which order to try which values.
19:49dnolenbbloom: currently it completely naive and just tries them in order and doesn't consider relationships between vars
19:49dnolengotta run
19:49bbloomk, i'll need to study it more. probably won't get to it for a while.
19:49bbloomcya
20:05callenI still say Clojure needs a mascot like go.
20:05callenClojure...Clown Fish?
20:06Iceland_jackThat sounds horrifying..
20:09hyPiRionhttp://www.flickr.com/photos/lndr/2648570113/
20:09hyPiRionIt's not the blue/green colour scheme though
20:15wingyis it possible to use something like (str) but strip all whitespace?
20:15wingysince i am using (str) in my code and the test and they are not the same since they contain different indentation whitespaces
20:16wingydue to their positioning in the source file
20:16callenhyPiRion: I'm sure that with some food dye, anything can be arranged.
20:16wingybut if i strip all whitespaces then they will be equal
20:19Somelauw,(clojure.string.replace "white spaced" #"\s+" "")
20:19Somelauw&(clojure.string.replace "white spaced" #"\s+" "")
20:19lazybotjava.lang.ClassNotFoundException: clojure.string.replace
20:19Somelauw&(clojure.string/replace "white spaced" #"\s+" "")
20:19lazybot⇒ "whitespaced"
20:20wingy&(clojure.string/replace "white spaced yes <input \>" #"\s+" "")
20:20lazybotjava.lang.RuntimeException: Unsupported escape character: \>
20:21wingy&(clojure.string/replace "<input \><a>some link</a>" #"\s+" "")
20:21lazybotjava.lang.RuntimeException: Unsupported escape character: \>
20:22wingydoesn't seem to be a good idea .. ill just stick with having the multi line string starting without indentation
20:30wingyi start to love xml :/
20:32callenwingy: YOU TAKE THAT BACK RIGHT NOW
20:34wingy*swallowing*
20:36hyPiRioncallen: colorizing the image is easier ;)
20:45Somelauwwingy: xml stands for everything that is wrong with this world :P
20:45wingyxml is more powerful than json!
20:46SomelauwMore powerful? Both can represent the same datastructures?
20:46wingyand we are quite used to it through html
20:46wingyhtml as json would be messy
20:48SomelauwMaybe I should make a tool that can convert back and forth between s-expressions and html.
20:49Somelauwxml is the reason i hate maven and ant
20:50SomelauwI think cmake is much more readable than ant
21:12akhudekTried eclipse for a day, and though I like CC, eclipse is just so slow compared to IntelliJ.
21:21hyPiRionOh, sweet
21:22hyPiRionDST is off here in Norway, so I can hack for one more hour
21:22hyPiRionturned off, or what you call it.
21:27akhudekhyPiRion: isn't it mostly dark in Norway this time of year?
21:30hyPiRionakhudek: It's "okay" right now - the sun shines from 8 am to 5 pm.
21:31akhudekoh that's not too bad
21:32hyPiRionIt's worse in December, then the sun rises 10 am, and it's pitch black around 2:30 pm
21:33akhudekwow! I visited Bergen once, but it was fortunately during the summer. Very nice then!
21:34hyPiRionheh :) Norway is a good place to live/be at summer, I think
21:35hyPiRionThough I suppose people living at hotter places may disagree
21:36akhudekI'm in Canada, but in the southern parts. In december it's dark by 5, but that's the worst that it gets
21:39hyPiRionIt's not easy, livin' in these countries far north.
21:46biscarchhas anyone used the java Braintree library? or can point me to a recent example for using third party java libs?
21:49akhudekbiscarch: http://clojure-doc.org/articles/language/interop.html
21:50biscarchakhudek: haven't seen that yet. Thanks.
21:50akhudekbiscarch: the only other trick is getting the library jars into the classpath
21:51akhudekif it's in maven, you can just get lein to pull them in like [groupid/artifactid "version"]
21:52biscarchakhudek: I set it up a :java-source-path in leiningen. I 'll check to see if the lib is in maven though
21:57akhudekbiscarch: as long as the jars in get into the classpath you'll be fine. I just find setting things up via lein deps to be the most convenient
22:06SgeoSomeone should write a Leiningen installer for Windows
22:07xeqiSgeo: do you mean something beyond the lein.bat ?
22:08Sgeoxeqi, putting wget or curl on the path, and putting lein.bat somewhere on the path
22:10AntelopeSaladwould it be a good idea to use require instead of use 99% of the time?
22:10xeqiAntelopeSalad: yes
22:10xeqiSgeo: ah, right. I forgot about that prereq
22:10akhudekAntelopeSalad: also, when using use, it's good practise to use :only
22:11akhudekhelps to know what the specific dependencies are
22:11AntelopeSaladakhudek: yeah, that seemed to be a common trend in some examples i've seen
22:11Sgeoxeqi, also, I didn't use emacs-starter-kit much, but I think there's more to getting emacs set up for Clojure than it. Clojure-mode too, I think?
22:12AntelopeSaladi need to get used to searching for different terms
22:12AntelopeSaladevery time i google for ring, it assumes i'm going to type ring worms
22:13akhudekprefixing with clojure always seems to work for me
22:13xeqiclojure-mode, clojure-test-mode, nrepl-mode, paredit-mode
22:13AntelopeSaladyeah or put github in there somewhere, i find myself looking at the api docs pretty often
22:14AntelopeSaladfor some reason i can't get wrap-file-info working properly though
22:15AntelopeSaladit never reports back what the docs say
22:17akhudekAntelopeSalad: if you are using it in conjunction with wrap-file, make sure that wrap-file comes first
22:18AntelopeSaladyep, i am
22:18AntelopeSaladi followed this to a T https://github.com/ring-clojure/ring/wiki/Static-Resources
22:19AntelopeSaladthe api docs say it should give me the content-type and last-modified but it doesn't seem to
22:19akhudekI take it you've restarted your jetty server since adding it?
22:19AntelopeSaladyep, it just omits reporting back those header fields every time
22:20AntelopeSaladi'm not sure of the idiomatic way to handle responses yet (this is basically day #1 of coding with clojure for me)
22:20AntelopeSaladi've been using ring responses with the default keynames, i figured the middleware would change the response as necessary
22:23akhudekI don't have any more guesses for you, but I've found it helpful to dump the actual responses or requests at various points to figure out what is going on.
22:23akhudekyou can use something like this: https://www.refheap.com/paste/6188
22:23akhudekoops, I had a bug
22:24akhudekit's fixed now
22:24AntelopeSaladi wouldn't have to manually setup the keyname for content-type and last-modified right?
22:24akhudekno
22:24AntelopeSaladexample: https://github.com/ring-clojure/ring/wiki/Creating-responses
22:25AntelopeSaladi've been using the -output- directly as my response
22:25AntelopeSaladexcept i didn't include the headers
22:25akhudekif you look at the code https://github.com/mmcgrana/ring/blob/master/ring-core/src/ring/middleware/file_info.clj
22:26AntelopeSaladthe only thing i really changed from the guide is i transformed those uses into requires
22:26akhudekthe only way I can see that it wouldn't add the right keys is if the body is not a File object
22:26AntelopeSaladbut i guess it would have crashed if i did something wrong
22:26AntelopeSaladall the other middleware works following the same require pattern
22:26SgeoIs the Joy of Clojure not available on Nook?
22:26AntelopeSaladhmm, the body in all cases so far has been either a string or a function to a hiccup function
22:27akhudekare the strings path names or something?
22:27AntelopeSaladnope, just random output
22:28AntelopeSaladi built up some examples without using templating, and then added templating after
22:28AntelopeSalad:body "foo" , etc. stuff like that
22:28akhudekOh. Then I'm confused why you are using file-info
22:28akhudekit's for augmenting file responses, not html responses
22:28AntelopeSaladthat could do it haha
22:29AntelopeSaladso far i've only been passing around hiccup functions to the response body
22:29AntelopeSaladi wasn't sure how else to do it (could probably figure it out with google)
22:29AntelopeSaladi had a layout clj file setup with a namespace, and then imported into my main app file, etc.
22:30AntelopeSaladhow would i let ring know to keep track of last-modified for non-file responses?
22:31akhudekwhat would the last-modified time of a generated file be?
22:31akhudekor do you mean the last modified time of the template?
22:32AntelopeSaladi'm honestly not sure, i only bring this up because another language puts an etag in the header for all responses
22:32AntelopeSaladand i was trying to get that to happen with ring too
22:32AntelopeSaladthis way it can return 200 or 304, etc.
22:33akhudekwell, in general, for all languages, you can only return a last modified time for static content
22:33AntelopeSaladthis was an etag in specific, not last-modified
22:33akhudekor effectively static content like a compiled template
22:33AntelopeSaladnot sure of the value, it looked like a negative unix time maybe
22:33AntelopeSaladi think it does compile templates for you
22:34AntelopeSaladis there a way to tell ring or hiccup to compile/cach templates automatically?
22:34AntelopeSalad*cache
22:35akhudeknot that I know of
22:35akhudekthough that doesn't mean such a thing doesn't exist
22:35akhudekI suppose you want some form have middleware that tracks if a response has changed since the last call
22:36AntelopeSaladso this would certainly lie on the shoulders of ring/ring's middleware not the template language?
22:36Sgeo"Purchase includes free PDF, ePub, and Kindle eBooks downloadable at manning.com."
22:36SgeoHow do I get those?
22:37akhudekAntelopeSalad: it could be handled by either, though probably doens't happen currently
22:38akhudekAntelopeSalad: a quick search turns up http://akoestler.blogspot.ca/2011/11/selective-browser-caching-with-etags-in.html\
22:38akhudekthen just change the etag every time you change your code
22:38akhudekif you are doing hiccup style outputs
22:38AntelopeSaladchecking
22:40AntelopeSaladwhat's that crazy +global-etag+ syntax mean?
22:40akhudeknothing
22:40AntelopeSaladi know + is ok to have as a variable name, but does it have context?
22:40akhudekauthor just likes plus signs I think
22:41SgeoIn Common Lisp, it's stylistic to have constants named with + on each side, I think
22:41akhudekit's not idiomatic to signify globals that way though
22:41AntelopeSaladah, he does mention his def is a constant (but should be changed later)
22:42AntelopeSaladthanks btw, this article seems pretty good -- i wonder why this isn't default functionality in ring, or at least a highly offically unofficial third party middleware
22:43akhudekprobably a combination of nobody looking into it enough to write something, and also that the problem isn't actually trivial to solve in a very generic way
22:43akhudekI mean, that solution requires you manually version your app, and make sure you don't apply the tag to dynamic responses.
22:45AntelopeSaladit seems to be solved in other libs
22:46AntelopeSaladi couldn't say if the solution is ideal/perfect but i haven't seen anyone complain yet
22:53akhudekAntelopeSalad: give me a bit and I will give a shot at a middleware
22:53AntelopeSaladif you know javascript i can point you to a very good lib which handles auto-etags
22:53AntelopeSaladthe code doesn't seem too hairy, might be able to get it even without js knowledge
22:57AntelopeSaladseems to be a 3 step problem: 1) a fn to generate the etag, 2) a value to store whether or not the request is fresh or not, 3) a fn to set fresh's value and the etag as well as trim out irrelevant headers when it's stale (content-type+length)
22:58callenhyPiRion: I prefer food dye.
23:02hyPiRioncallen: Well, each to their own, I suppose.
23:08SgeoWhat function does ` use to namespace a symbol?
23:10Sgeo,(let [foo 'bar] ``~foo)
23:10Sgeo..
23:10Sgeo&(let [foo 'bar] ``~foo)
23:10lazybot⇒ clojure.core/foo
23:10Sgeo&(let [foo 'bar] `~foo)
23:10lazybot⇒ bar
23:13ambrosebsSgeo: hard to tell exactly where this is done.
23:16ambrosebsSgeo: do you just want the semantics, or literally where the code is?
23:17SgeoThe semantics, although literally where the code is would be interesting
23:17ambrosebsSgeo: clojure.lang.LispReader$SyntaxQuoteReader/syntaxQuote I think
23:17ambrosebsin clojure/lang/LispReader.java
23:19SgeoWhy is that else way out there on L802?
23:19ambrosebsI think syntax quote just tries to resolve the symbol, and if it doesn't resolve to a var, just qualify it in the current namespace.
23:19Sgeo&`~@[1 2]
23:19lazybotjava.lang.IllegalStateException: splice not in list
23:19ambrosebsSgeo: Rich works in mysterious ways in Java :)
23:19ambrosebsSgeo: I assume it's Rich
23:20ambrosebsI've never seen Java quite like the Clojure compiler.
23:20ambrosebsBut I don't read much Java.
23:20arosequistI'm trying to learn core.logic fds. (+fd x y 5) works for x + y = 5, but what if I want x - y = 5? Is there a way to negate a domain?
23:21arosequist(that might be a really dumb question...brand new to core.logic in general)
23:21hyPiRionarosequist: x - y = 5 <==> x = 5 + y, ain't it?
23:21hyPiRionI don't know if it works for +fd though.
23:21hyPiRion(Not used core.logic, shoot me for that :( )
23:22arosequisthyPiRion: Ah, it works perfectly. Of course. Thanks.
23:26akhudekAntelopeSalad: you can try this https://www.refheap.com/paste/6189
23:27akhudekthere is probably a better way to implement it, but it seemed to do the right thing in light testing
23:27AntelopeSaladok
23:27AntelopeSaladi will experiment with it tomorrow, using it should be straight forward right?
23:27AntelopeSaladjust throw this into my app.clj file and then put it into the middleware stack?
23:27akhudekalso expect a performance hit to the server, though I don't know how much. Computing hash values certainly takes time
23:28akhudekyep
23:28AntelopeSaladjust so i'm 100% clear on this for later
23:28AntelopeSaladhttps://github.com/ring-clojure/ring/wiki/Static-Resources
23:29AntelopeSaladall i would have to do is replace: wrap-file-info with wrap-etag , right?
23:29akhudekright
23:29akhudekit computes the etag only on the body
23:29akhudekso as long as the body is set
23:29akhudekit should work
23:29AntelopeSaladi wonder how bad the performance hit would be
23:29akhudekno clue
23:30AntelopeSaladin the end it should save time i would think
23:30akhudekwell, for the client, not for the servers cpu
23:30xeqiI would expect it to save bandwidth, not really cpu time
23:30AntelopeSaladif it doesn't have to recompile a template and serve it, that's a pretty big win
23:31akhudekresponses will still be generated
23:31akhudekit only saves bandwidth
23:31AntelopeSaladyeah but as a slimmed down 304 right?
23:31akhudeknope, full responses are generated using this
23:31akhudekfor static files you can do much better
23:32AntelopeSaladhmm
23:32AntelopeSaladwhy couldn't we set the body to empty on 304?
23:32akhudekso for performance, you'd want to use this only on non-static but rarely changing responses
23:32AntelopeSaladthen send an empty body
23:32akhudekI think it does work that way
23:32akhudekso you do save bandwidth
23:33akhudekand your site will appear faster to clients
23:33AntelopeSaladso it is working in the way that is sends an empty body on 304s?
23:34AntelopeSalador would that doing something to "res" and then just wiping the body before returning it?
23:34AntelopeSalad*require doing
23:35akhudekwhen I tried it with curl, curl didn't download the body when setting the if-none-match
23:35akhudeknot sure if that is just curl doing that, or jetty doing it
23:35AntelopeSaladdid you curl it with verbose mode?
23:35akhudekyup
23:36AntelopeSaladwould it be a good idea to remove the content-type and length for 304s too?
23:36akhudekif you want, you can also modify the handler to additionally clear the :body
23:36akhudeknot, sure, I didn't read the specs that closely
23:36akhudekalso easy changes to make :)
23:36AntelopeSaladi ask because of this: https://github.com/visionmedia/express/blob/master/lib/response.js#L129
23:37AntelopeSaladhe strips out those 2 headers and clears the body on 204/304
23:39AntelopeSaladwe could probably use crc instead of hash too to eliminate some calculations?
23:40akhudeklooks like ring does have etag support https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/not_modified.clj
23:40akhudekoops, should have checked first
23:41akhudekthat still won't add etags to dynamic responses though
23:41AntelopeSaladbut it had nothing to write the etag
23:41AntelopeSaladyeah
23:42AntelopeSaladyour middleware handles both right?
23:42AntelopeSaladit clearly writes an etag and sends a 304 when it needs to
23:43akhudekyes, but it might be better to use this https://www.refheap.com/paste/6190
23:43akhudekand then not-modified on top
23:43AntelopeSaladon top as in, 1 function before this one in the middleware stack?
23:43akhudekIdeally you'd only use wrap-etag on non-static routes, since static files will have last-modified times.
23:44akhudeknot-modified must come after wrap-etag
23:44AntelopeSaladok, might as well use that then for sure?
23:45AntelopeSaladthe smaller wrap-etag + built in last-modified
23:45akhudekright, use this version as it fixes a capitalization issue: https://www.refheap.com/paste/6191
23:46AntelopeSaladthe built in one looks like it's doing so much more than your first version
23:46akhudekyeah, it checks last modified time too
23:46AntelopeSaladi guess that's necessary?
23:47akhudekno, but it's optimal for static resources
23:47akhudekyou don't really want to be computing hash values on big files like images for example
23:47AntelopeSaladso we would want last-modified to run on all requests
23:47AntelopeSaladand wrap-etag on just non-static requests?
23:48akhudekright, you want file-info on static requests, and wrap-etag on other requests
23:48AntelopeSaladthat will involve editing wrap-etag in some way to skip doing its thing?
23:49akhudekno, you can just group your dynamic routes and add wrap-etag only to that group
23:49akhudekcheck out compojure's defroutes
23:49AntelopeSaladi'm not really sure to "fork" 2 middlewares based on a condition
23:49AntelopeSalad*how to
23:50AntelopeSaladhmm that seems weird
23:51AntelopeSaladwhen i look at defroutes, i think it's to be used to associate a group of routes to a sub-route
23:51AntelopeSaladlike /user/foo , /user/bar
23:52akhudekit can group any handlers
23:52AntelopeSaladwhat happens if you have a bunch of dynamic routes with no pattern
23:52akhudeke.g. https://www.refheap.com/paste/6192
23:53AntelopeSaladlike /foo and /bar might be dynamic but aren't related
23:53akhudekthey are checked in order until the first non-nil response
23:53AntelopeSaladoh wow
23:53akhudekI think there are tutorials around for that too. I personally quite like compojure for url routing
23:53AntelopeSaladthe way you have this is nothing like what the docs say
23:54AntelopeSaladthis seems like arbitrary grouping (a very good thing)
23:54AntelopeSaladhttps://github.com/weavejester/compojure/wiki/Nesting-routes
23:54AntelopeSaladhow the heck are we supposed to know what you just did when we read that lol?
23:55akhudekthat page is talking about the context macro
23:55akhudekthere are better docs and tutorials around for compojure though
23:55akhudekif you dig
23:55AntelopeSaladyeah, that'll be tomorrow's project -- thanks for pointing me in the right direction
23:55AntelopeSaladi think this is a very good start to have a reasonable solution
23:56akhudekyour welcome, the clojure web libraries take a while to learn, but they are pretty great once you know them
23:56AntelopeSaladbtw what's your opinion on using a crc lib instead of hashing to save some cpu time, or do you think it's not even relevant?
23:56akhudekcrc is a form of hashing
23:57AntelopeSaladbrief googling (stackoverflow) seems to say it's less cpu intensive
23:57akhudekthere may be more performant hash routines than clojures built in function though