#clojure logs

2014-03-17

00:00stcredzerobbloom: Since I started using pmap, I
00:00bbloomstcredzero: there's practically zero chance pmap is a good idea in a game ever
00:00stcredzeroI've started seeing strange errors
00:00l1xSegFaultAX: sorry to bother you, how could i filter with some in a nested structure where my collection is a vector of maps
00:00bbloommaybe clojurebot has something...
00:00dnolen_seangrove: your basic idea isn't completely off base in my opinion - I haven't considered the transformer/path thing in the yr particularly context
00:00bbloom~pmap
00:00clojurebotpmap is not what you want
00:00bbloomthere we go ^^ lol
00:00l1x:)
00:01stcredzerobbloom: even if you use (vec) to force evalutation in well defined stages?
00:01dnolen_seangrove: but I have considered how often the data you have is not in the form that a component needs yet you don't want to polluteyour app w/ logic about data transforms
00:01bbloomstcredzero: have you benchmarked pmap for your use case?
00:01stcredzerobbloom: I'm using pmap to handle execution in sub-grids.
00:01dnolen_seangrove: I was mostly thinking about :instrument + some transformer fn, but it seems like you're interested in this making less of a edge case and more central
00:02bbloomstcredzero: i'm willing to bet that pmap is making your game slower, try it and see
00:02stcredzerobbloom: the purpose is to be able to handle over 90% of the game loop in parallel, with only the leftovers that need global coordination in a normal serial game loop
00:02seangrovednolen_: It makes it highly amenable to static analysis + really fantastic tooling
00:02seangrovednolen_: You can get highly-functional apps with all the goodies going through this
00:03stcredzerobbloom: It's probably making it slower now, but I'm hoping to support 1000's of entities/players
00:03bbloomstcredzero: benchmark. benchmark. benchmark.
00:03seangroveThe danger is I might be going down the angular route and recreating basic concepts in a declarative way and introducing a bunch of complexity
00:03bbloomseangrove: that's my fear :-P
00:03seangrovebbloom: It's on my mind, certainly ;)
00:03bbloomseangrove: declarative UI doesn't work for programmers, it works for tools
00:04bbloomseangrove: which is OK if that's your goal, but you have to be clear about that
00:04stcredzerobbloom: the global world thing and the sub-grid thing are polymorphic, and except for boundary crossings, everything can execute with utter independence
00:04seangrovebbloom: The iterative bootstrapping process so far has been very promising in that regar
00:04stcredzerobbloom: I don't have to benchmark an architectural/algorithmic choice. The point is to have multi-core concurrency
00:05bbloomstcredzero: you're not hearing me.... or clojurebot :-P how many cores do you have? 2? 4? the overhead of communicating between them is likely to dwarf any benefit you get if you have thousands of game elements and they are small enough jobs to run every frame
00:05bbloomstcredzero: i've worked in games, if you want multi-core concurrency, you're much much better off parallelizing your stages: ie have rendering and gameplay running in parallel
00:05stcredzerobbloom: you're not hearing me. Except for boundary crossings, there *is no coordination* between subgrids.
00:06bbloomstcredzero: pmap has coordination
00:06bbloom(doc pmap)
00:06clojurebot"([f coll] [f coll & colls]); Like map, except f is applied in parallel. Semi-lazy in that the parallel computation stays ahead of the consumption, but doesn't realize the entire result unless required. Only useful for computationally intensive functions where the time of f dominates the coordination overhead."
00:06bbloomnote the "only useful for" message
00:06dnolen_seangrove: need to think about it some more - but it seems worth exploring.
00:06bbloomstcredzero: by definition, that's not true if you have thousands of entities
00:06seangrovednolen_: It's all PoC still, but pretty excited about it.
00:07stcredzerobbloom: also, the game loop comes in stages which are parallelized. You're leaving out a step somewhere. As far as I know, things are going to be CPU bound.
00:09stcredzerobbloom: http://www.reddit.com/r/roguelikes/comments/1xa9rj/i_have_been_writing_a_pseudoroguelike_mmorpg_with/ -- for one thing, all entities are going to have interpreted source code that other entities can fsck with in real-time. Will be CPU-bound.
00:09bbloomstcredzero: even if that were the case, you don't want pmap
00:10bbloomstcredzero: pmap will create a ton of garbage, incur significant synchronization costs, and generally cost you far more CPU time than it will save you
00:10stcredzerobbloom: sub-grid game loops are basically conventional serial game loops. Things are architected so that the sub-grid loops *are not coordinating* (as much as possible) pmap just fires off each independent serial game loop in parallel
00:11bbloomstcredzero: i understand why you think it will be faster, but unless you benchmark it and tell me i'm wrong (i'm not) then we're both wasting our time
00:11stcredzerobbloom: however, it does make sense that pmap is creating a ton of garbage.
00:12SegFaultAXstcredzero: You're not understanding bbloom's point. pmap itself has inherent coordination overhead irrespective of what you might be using it for.
00:12stcredzeroSegFaultAX: You can say the same for Erlang Actors. All of these things have inherent coordination overhead.
00:12bbloomstcredzero: except that that's a wildly different thing
00:13SegFaultAXstcredzero: That... has aboslutely nothing to do with what we're talking about.
00:13bbloomb/c erlang actors have independent GC heaps and run N-to-M threading
00:13SegFaultAXstcredzero: You can visualize a pmap as firing off a bunch of futures then joining on all of them.
00:14stcredzerobbloom: My understanding is that pmap is going to give me n to m threading. Yes, firing off a bunch of futures then joining. I don't have to have 100% utilization across time. If it looks like a sawtooth or square wave, that will be fine
00:14bbloomstcredzero: looking at your screenshots... is the game logic in cljs? or just the renderer?
00:14SegFaultAXstcredzero: Go measure, come back to us when you have a better sense of what's going on.
00:14stcredzeroJust the renderer.
00:15stcredzeroI can't really benchmark 1000's of entities until I have much more of the system built.
00:15SegFaultAXThen you're prematurely optimizing anyway.
00:15bbloomyes, that ^^
00:16bbloomstcredzero: you probably don't need the game entities to remain sorted, if that's the case you're paying significant overhead for the atomic operations done by the futures in the pmap impl
00:16stcredzeroI can just change all of those pmap to map.
00:16bbloomcore.async is likely to provide proper multi-threaded improvements
00:16stcredzerobbloom: remain sorted?
00:16SegFaultAXstcredzero: But you've got a bunch of things in your head that you're mixing together.
00:16bbloomstcredzero: pmap preserves the sequence's order
00:17stcredzerobbloom: why should that incur a significant overhead?
00:17bbloomgo to your repl and type (source pmap)
00:17stcredzeroSegfaultX: what things?
00:17bbloommaybe you'll understand then, if you don't you have a lot more to learn about multithreading performance
00:17bbloomand you're only going to learn that from BENCHMARKING
00:18devnfree idea: wiki-style editing of docstrings
00:18devncollaborative docstring writing, with a more wikipedia-like interface for editing what the code does
00:18SegFaultAXdevn: I wish that's what clojuredocs became.
00:19devnSegFaultAX: you know, i keep sitting around wondering how we ended up where we are
00:19SegFaultAXInstead it's a relic which high google ranking that hasn't been updated in years. :(
00:19bbloomstcredzero: sorry to be harsh, really just trying to help
00:19stcredzerobbloom: so you're saying it's the when that's the source of the overhead?
00:19devnclojuredoc is good, clojuredocs is ok
00:19devnbut it's sad no one has just sit down and replaced clojuredocs
00:19devni need to make that my mission.
00:19SegFaultAXI wonder if the maintainer would be willing to yield control of the domain.
00:20stcredzerobbloom: That pmap is polling over a bunch of things to see when they are all done?
00:20bbloomstcredzero: i'm saying that pmap is rarely appropriate and even if you custom-tailor a solution for your problem, you'll likely have a hard time getting a perf win
00:20devnapparently that was discussed at some point
00:20devni dont know the details
00:20bbloomstcredzero: no, it's not polling, it's blocking in order.
00:20bbloomstcredzero: also, since your game is going to have a server component, you're better off running GAMES in parallel
00:20bbloomstcredzero: ie different game world instances run on different cores
00:20devnSegFaultAX: do you want to remake clojuredocs?
00:20bbloomstcredzero: that will yield dramatically better CPU utilization and even more dramatically simpler code
00:21devnAKA do you have time to work on it?
00:21SegFaultAXdevn: Update it with 1.4 1.5 1.6
00:21stcredzerobbloom: so if I have 6 or so processors -- yes. I do plan on having different instances. That's part of the point I was making that you weren't paying attention to.
00:21devnSegFaultAX: forget the old site. let's just rewrite it and extract the content
00:22devnactually, you know what? i take back that idea. what we have is a rails application that could easily be updated
00:22bbloompmap is still not the answer
00:22stcredzerobbloom: everything you've said fits in with my expectations, so unless yo ucan give me some big-O figures that aren't n(log32(n)) I don't think you quite have a point.
00:22SegFaultAXbbloom: Not worth the effort, dude.
00:22bbloomSegFaultAX: agreed
00:22SegFaultAXstcredzero: Go measure.
00:23seangroveYeah, just benchmark, work from that
00:23SegFaultAXstcredzero: Show us that we're wrong with data.
00:23devncan someone catch me up on this conversation?
00:24SegFaultAXdevn: Just some deep misunderstandings about how threads work (and pmap in particular)
00:24trap_exitis there a version of for, which takes two lists, as their _zip_, but not a cross product, i.e. lst1 = [1 2 3] lst2 = [1 2 3], I want [1 1], [2 2], [3 3], rather than [[1 1], [1 2], [1 3], [2 1], [2 2] [2 3], [3 1] [3 2] [3 3]]
00:24stcredzeroif pmap is a good idea for independent CPU bound things, someone needs to give me a coordination cost that's worse than O(n*log32(n))
00:24stcredzerodevn: no, that's wrong. These guys don't understand what I'm proposing.
00:24devn,(zipmap [1 2 3] [1 2 3])
00:25clojurebot{3 3, 2 2, 1 1}
00:25stcredzerodevn: as evidenced by their bringing up separate instances. I will have separate instances.
00:25SegFaultAX(map vector [1 2 3] [:a :b :c])
00:25SegFaultAX,(map vector [1 2 3] [:a :b :c])
00:25clojurebot([1 :a] [2 :b] [3 :c])
00:25devnstcredzero: that too :)
00:25devn,(repeat 2 [1 2 3])
00:25clojurebot([1 2 3] [1 2 3])
00:25trap_exitso (for [ [a b] (map vector lst1 lst2)] ... ) ?
00:26trap_exitwell, [1 2 3], [1 2 3] were specific lists; I want it work with generic lst1, lst2
00:26SegFaultAXtrap_exit: (fn [a b] (map vector a b))
00:26stcredzerodevn: I'm not after 100% parallelism. I'm looking for limited parallelism that looks like a sawtooth or square wave over time. Then the OS can coordinate between different instances to get me near 100% CPU utilization.
00:26devnare the same length?
00:26trap_exitnot same length
00:26bbloomstcredzero: read the docstring again. you said thousands of items. the doc string literally explains that f needs to be expensive to justify it. if you are running f on thousands of items and you have less than tens of cores, and need real time responses, then pmap won't help you
00:26trap_exitbut I only want to take pairs up to the shorter of the two
00:27SegFaultAXtrap_exit: Then that's what you want.
00:27bbloomstcredzero: 100% CPU utilization isn't what you want...
00:27SegFaultAXtrap_exit: What I just typed, that is.
00:27stcredzerobbloom: you re not p[aying attention. I'm running f on dozens of items to support 1000's of entities.
00:27devnstcredzero: i know we're typing into this thing that is supposed to contain smart people
00:27devnbut i think we are just having a hard time communicating
00:28devnit sounds like there are reasons why you are choosing this approach
00:28devnbut we dont know everything about your problem
00:28SegFaultAX,((fn [a b] (map vector a b)) [1 2 3] [:a :b :c :d])
00:28clojurebot([1 :a] [2 :b] [3 :c])
00:28SegFaultAXtrap_exit: ^
00:29devn,(zipmap [1 2 3] [4 5 6 7])
00:29clojurebot{3 6, 2 5, 1 4}
00:29devnit might work... just saying...
00:29SegFaultAXdevn: I think he wants a list of pairs.
00:29stcredzerobbloom: f is expensive -- damn expensive in CPU. The parallelism isn't for each entity. It's for a much smaller number of chunks of the world that are independent. Each f is just a serial game loop running over many entities, which you seem all fired to tell me is going to be so efficient. I'm *counting on it*!
00:29bbloomstcredzero: i scrolled up and find no mention of you making that point :-P
00:29devnSegFaultAX: sure, but im just saying that's close enough for jazz
00:29stcredzerobbloom: search for where I talk about sub-grids.
00:30devnheh
00:30bbloomstcredzero: i'm looking at it, but i'm not a mindreader
00:30devn"ask me about the time i cured world hunger"
00:30bbloomstcredzero: still, even with dozens, i don't think you want pmap
00:30stcredzerobbloom: admit it, you were taling the whole time assuming I'm talking about paralleism per-entity.
00:30devnkidding of course, just sounded funny
00:31devnstcredzero: dude, this isn't a conspiracy
00:31bbloomstcredzero: i did think that, however, i still don't think pmap is what you want
00:31bbloomstcredzero: for every single reason i've listed
00:31SegFaultAXstcredzero: Why are you still not measuring?
00:31stcredzerobbloom: show me where pmap is costlier than O(n*log32(n)) and you win. Instantly
00:31stcredzerobbloom: I can't measure yet.
00:31devnalgorithm designs are meant to be tested
00:31bbloomstcredzero: if you can't measure yet, you can't optimize yet
00:31bbloomstcredzero: and constants matter
00:31bblooma lot
00:31stcredzerobbloom: I can design.
00:31bbloomespecially in threading
00:32devnstcredzero: see my previous comment
00:32bbloomstcredzero: i've been writing multithreaded web services AND games for years and i'd like to think i'm pretty good at it. not once has my first design been within many orders of magnitude of the winning design
00:32devnamen
00:33bbloomhell, i've fixed multithreading bugs in the tools for finding multithreading bugs in xbox games
00:33bbloomand even that took a few tries :-P
00:33stcredzerobbloom: I used to say that stuff to meetup audiences.
00:34bbloomstcredzero: i don't know why you think we're out to get you
00:34bbloomwe're trying to help
00:34stcredzerobbloom: also in your commentary, are you assuming there's any coordination between f's?
00:34bbloomnope
00:34stcredzerobbloom: so you're telling me that the coordination is O(n*log(n)) but that the constant factors are ungodly huge.
00:35bbloomstcredzero: i'm done arguing until you come back with numbers
00:35SegFaultAXstcredzero: No, he's telling you that it isn't worth it if the overhead of `f` applied to each chunk isn't greater than the coordination overhead of pmap.
00:35krasHI Again. Any recommendations for network/graph library in clojure? Something equivalent to networkx in python.
00:35seangrovestcredzero: bbloom is a good guy, worht listening to, even if he comes across as borderline crazy ;)
00:36bbloomseangrove: surely you know i'm full on crazy by now!
00:36stcredzeroI'm suspecting that no one knows what the ovehead of pmap is.
00:36trap_exitSegFaultAX: noted, thanks!
00:36SegFaultAXstcredzero: Well, that's because it depends on lots of stuff.
00:37bbloomstcredzero: no one is guessing b/c we're explicitly telling YOU not to guess
00:38SegFaultAXstcredzero: Mind it could be possible that pmap nets you a gain in performance (unlikely, but possible) but some very specific conditions have to be met before that's at all likely.
00:38SegFaultAXAnd even if those conditions are met, pmap is still probably not the tool you need for a tight game loop.
00:38SegFaultAX(It's too broad a hammer)
00:38stcredzeroSegFaultAX: That informatino would be much more useful than the catch-22 you're presenting me with. I'm trying to come up with a new architecture.
00:39SegFaultAXpmap is a sledge and you need a ball pene to have consistent processing time per frame.
00:39SegFaultAXstcredzero: How is "go measure and come back with data" a catch 22?
00:39stcredzeroSegFaultAX: So you guy's position is that I shouldn't even try/that I should benchmark something I don't have completed to benchmark, and that I'm damned because I'm prematurely optimizing. Of course I'm going to measure the thing!
00:40SegFaultAXstcredzero: Then why are we arguing? It's not like s/pmap/map/g is that hard to type.
00:41stcredzeroBut I'm ddamned for trying it in the first place as a premature optimizer. You're telling me you have a good a-priori guess that I should just have serial game loops. I'm arguing because I don't feel like you were inclined to listen and just wanted to play the "inform the noob" game and so overlayed a bunch of noob assumptions over what I was doing instead of actually listenting to my proposal.
00:42SegFaultAXstcredzero: Ok. Let us know when you have measurements. Good luck!
00:42stcredzeroAs evidenced by the assumptsions that f would be cheap, that parallelism was per-entity, etc.
00:44stcredzeroWhat would be actually helpful is to let me know what things pmap is not going to like in more detail.
00:50technomancystcredzero: answering questions on IRC is largely a matter of pattern matching
00:57krasHI Again. Any recommendations for network/graph library in clojure? Something equivalent to networkx in python.
00:58krasI don't require many algorithms, performance is the prime criterion
00:59krastitanium, loom???
00:59lazybotkras: Yes, 100% for sure.
00:59stcredzerotechnomancy: I have it when people keep insisting I'm saying something I'm not, especially in the face of my informing them I'm saying what I'm actually saying.
00:59stcredzero"have it" is mistyped v = t
01:00technomancystcredzero: haven't been paying attention to the discussion, just throwing that out there
01:00beamsokras: https://github.com/prismatic/plumbing ?
01:00technomancyI know my first instinct when I hear newcomers to Clojure ask about records is just to tell them not to use them
01:01stcredzerotechnomancy: I think your comment was very apt.
01:01technomancy(even if I have no idea what the actual answer is)
01:02stcredzerotechnomancy: because they were pattern matching, getting the details of my proposal wrong, then arguing from their pattern-match based assumptions
01:03technomancyhey, it's a 95%-effective approach
01:03stcredzerotechnomancy: then when I tried to inform them of their incorrect assumptions, they used that as evidence that I don't know what things are...like threading.
01:03stcredzeroMy esoteric projects are 5% ideas.
01:03technomancy(this is why we have bots)
01:06stcredzerotechnomancy: People are behaving more like bots, and the implicit assumptions is that everyone just mechanically falls into cubbyholes that are even more efficiently delineated for us through the information dissemination power of the INternet
01:08technomancyeveryone does it
01:08technomancythe real world is too complicated to function any other way
01:08technomancyyou see someone dress a certain way and you make assumptions about their personality
01:09technomancybecause it's far more efficient than finding out for yourself
01:09amalloytechnomancy: he left after cubbyholing everyone
01:09technomancyamalloy: well you know what they say about people who leave in the middle of IRC conversations
01:10amalloythey rarely get answers they're happy with?
01:10technomancythat they bloody well should learn how bouncers work
01:10zspencerZNC + irsssi
01:11technomancykind of annoyed that he ended up thinking I was just encouraging him
01:11beamsoor screen + irssi
01:12zspencerZNC allows multi-client so you can limechat in when you're afk
01:12technomancytmux allows mosh though
01:12technomancy
01:12zspencerBut yes, a screen/tmux terminal is good stuff
01:19bbloomtechnomancy: he just switched to defensive mode instantly and then demanded answers to questions that showed that we had correctly cubby holed him :-P
02:14stcredzeroWhat's the fastest way to go from a map that contains a bunch of defrecord objects as values to a collection that contains futures executing functions on those values?
02:53noidiif you want to retain the keys, then (into {} (for [[k v] m] [k (f v)]) is a common approach to mapping over a map's values
02:54noidiif you only need the values then (map f (vals m))
02:54noidiAFAIK that's fastest as in fastest to type in the editor :)
03:09antonvhi
03:09antonvany cider users here?
03:10winkeven if it's St. Patrick's Day, I'll wait a few hours with that :)
03:11antonvwhen I execute an expression with C-x C-e and the expression has error, then a stack trace buffer shows up
03:11antonvis there a shortcut to close it quickly, without havign to switch to that buffer by C-o first?
03:12antonvC-x o I mean
03:12antonvin SLIME I can just press q
03:12antonvand the debugger buffer closes
03:13antonvbut in cider I must switch to the buffer - tedious
03:15antonvOK, added (setq cider-auto-select-error-buffer t) to the .emacs
03:15antonvnot the error buffer is selected automatically, I just press q and it closes
05:43charedo you guys use intellij
05:43chareor use just cursive?
05:51winkLightTable for Clojure and Lua, IDEA for all other languages
05:58clgveclipse/counterclockwise
07:11Pate_how is Clojure's multimethod support implemented, specifically the dispatch function?
07:12nightflyprobably with a hashmap and lambdas
07:12Pate_found this: https://github.com/clojure/clojure/blob/0b73494c3c855e54b1da591eeb687f24f608f346/src/jvm/clojure/lang/MultiFn.java
07:13Pate_these is an IPersistentMap methodTable that caches the "preferred method" for a given dispatch.
07:14Pate_sorry, the methodTable has all the possible methods and preferTable caches the preferred method.
07:35clgvPate_: why do you ask for implementation details? just for learning and understanding?
07:35Pate_yes.
07:36Pate_I wanted to know how dispatch methods are implemented, because I felt they were functionally equivalent to an if...else on some type condition. And basically they are, but the result is cached.
07:43pepijndevosWhat is the relation between :gen-class, :aot and :main? Do I need all 3 to get a class with public static void main in it?
07:45sm0kepepijndevos: gen-class is one way for defining java classes in clojure, :aot and :main are leinigen specific
07:46clgvPate_: yeah in prinziple they are like a "cond" or "case" but open for dynamic extension
07:46pepijndevossm0ke, right, but if I want to do lein uberjar, I'll need both aot, and gen-class with a (def -main), right?
07:46sm0kepepijndevos: in clojure evrything is compiled to bytecode at the moment it is required, :aot is for doing it ahead of time
07:46pepijndevosrunnable uberjar that is
07:46clgvpepijndevos: yes. :gen-class in the namespace of the -main method and :main and :aot in project.clj
07:46sm0kepepijndevos: yes that is correct, if you want to invoke it like 'java -jar myjar.jar'
07:47pepijndevoscool. thanks
07:48pepijndevosWas unsure if gen-class was still needed with :aot. I guess ahead of time compilation does not nececerily mean generating classes.
08:00gfrederickswell it doesn't mean generating the particular class that gen-class generates
08:00gfredericksit does generate lots of other classes
08:02gfredericksusually the point of using gen-class is to make a class with a .main method
08:02gfredericksand you don't have one of those otherwise
08:38jespadaany hint/example on how to use log4j triggering-policy (SizeBasedTriggeringPolicy) trying to add that to https://github.com/aphyr/riemann/blob/master/src/riemann/logging.clj#L82
08:39jespadafailing..https://gist.github.com/jespada/729531b539ff6d556c1e
08:51AeroNotixw00t just bought my EuroClojure ticket!
08:52AeroNotixhttp://euroclojure.com/2014/
08:52AeroNotixanyone else going?
09:55wagjoAeroNotix: I'm going
09:55AeroNotixwagjo: in KRK already or ?
09:56wagjoAeroNotix: 3 hours by car from my place
09:56wagjoAeroNotix: It was an offer I could not refuse :)
09:57AeroNotixwagjo: indeed :) Our office is going (3 clojure people!) woot
09:57AeroNotixlooking forward to it
09:57hyPiRionI'm tempted, but money
09:58AeroNotixhyPiRion: where you at?
09:58mpenetgoing too, not sure from where yet though
09:58AeroNotixNorway iirc? hyPiRion
09:58hyPiRionOh hey I'm still a student at that moment I guess
09:58hyPiRionyeah
09:58mpenetppl going are staying where (hotel)?
09:58wagjoAeroNotix: Well you have it like 15 minutes, it would be shame not to go :)
09:58AeroNotixhyPiRion: dude, 70EUR
09:58AeroNotixwagjo: it's right down the road from my flat
09:58AeroNotix:D
09:58hyPiRionAeroNotix: that's not the costly part though. Planes and hotel is the main issue
09:59mpenetHotel are kind of cheap there
09:59AeroNotixbut yeah, places are cheap
10:00hyPiRionah, you guys
10:01mpenetplanes on the other hand... not sure a lot of low cost go to Krakow
10:03hyPiRiondang, I'm planning to move around that time too. hnggg
10:17AeroNotixn_b-:
10:17AeroNotixoops
10:17AeroNotixdepends where you're coming from in EU
10:17AeroNotixfrom the UK, really, reall cheap.
10:18hyPiRionYeah, it wasn't that expensive. I'm just scarred after the conj plane ticket I guess
10:19AeroNotixhyPiRion: where are you coming from?
10:19hyPiRionTRH
10:20hyPiRionTrondheim
10:20AeroNotixaha
10:21hyPiRionIt's like 160-180 € for a return ticket
10:24AeroNotixNot too bad, but still.
10:40devnticket prices were bad for me
10:40devnI think I paid 630USD
10:40AeroNotixdevn: you're coming from the US?
10:40devnand I'm in the US
10:40AeroNotixto KRK?
10:40devnno, to SFO
10:40AeroNotixah
10:40devnsorry, i caught the tail end of this conversation
10:40devni saw "conj plane ticket"
10:40devnand assumed you were talking about clojure/west
10:40AeroNotixwell, we were just talking generally :)
10:41AeroNotixprimarily about euroclojure
10:41devni realllllly want to go
10:41AeroNotixthen do!
10:41devnim going to have to submit a CFP
10:41devnwhen does the CFP end?
10:41devnpoland looks beautiful.
10:41AeroNotixI don't know what a CFP is
10:41devnCall For Proposals
10:41AeroNotixohh April 16th
10:41devnI'd need to give a talk if I want to go
10:41AeroNotixiirc
10:41devnmy company will pay if I go that route
10:42AeroNotixawesome, do eeet
10:42devnotherwise, I've spent too much on conferences this year already
10:42AeroNotix:
10:42devnyeah man, im thinking about giving a hoplon talk
10:42katratxocemerick: ping?
10:42BartAdvhoplon talk would be great
10:42clojurebotPardon?
10:43devnBartAdv: yeah, i've been getting into it. My friend Matt was working on this: https://github.com/mathias/gnar
10:43devnHe built that in like a day with no hoplon experience
10:43devn"Rapid Prototyping in Hoplon"
10:43devnsomething like that is kind of what I'm thinking
10:46devnso, now that we're talking about /that/ plane ticket... 1,622 USD
10:46AeroNotixyikes
10:46AeroNotixI just take a walk and boom I'm there :)
10:46devnnot a big surprise honestly
10:47devnhaha
10:47devntravel time is like 13hours
10:47AeroNotixouch ><
10:47devnprobably more like 16 including getting to the airport and all of that
10:48devnbut that's fine. i'd love to see poland
10:48AeroNotixluckily in KRK the airport is 10 minutes away from the centre
10:48devni think i'll probably go for an extra week
10:48AeroNotixand there's a train which comes directly from the terminal
10:48devnAeroNotix: are you in poland?
10:48AeroNotixI am, yeah.
10:48AeroNotixI'm not Polish, though.
10:48devnah, cool. hi! :)
10:48AeroNotixhi :)
10:49devni'd love to chat more, but i need to get some work done. slow morning for me so far.
10:49devnsee you poland! :)
10:49AeroNotixyou too, cya!
11:36katoxjust opened mwjs to see pete hunt citing rich hickey ;) http://mtnwestjs.org/live
11:37arrdemoh awesome, we got accepted for GSoC 14 :D
11:37mdrogalisarrdem: :)
11:38arrdemmdrogalis: :P it's internship applciation season so I'm not entirely neutral here
11:38arrdemhaxxing clojure for a summer would be pretty sweet.
11:40mdrogalisarrdem: Hah, nice
11:43ambrosebsarrdem: are you a student?
11:44arrdemambrosebs: yarp
11:44arrdemambrosebs: junior at U of Texas at Austin
11:45ambrosebsarrdem: about 4 days left until student applications close FYI
11:45arrdemambrosebs: I'm well aware.
11:45eric_normandambrosebs: how's the mentor search going?
11:45arrdemambrosebs: that's one of the reasons I'm mentioning it here :P
11:46ambrosebseric_normand: picked up a few helpers :)
11:46ambrosebseric_normand: thanks for the help
11:46seubertarrdem: congrats, you survived SXSW for another year
11:46seubert:P
11:46arrdemseubert: meh... two of my friends got hit in the "accident".
11:46seubertarrdem: :( :( :(
11:46arrdemare okay, but met.
11:46eric_normandambrosebs: you're welcome. that's what the gazette is for
11:46arrdem*meh
11:47seubertarrdem: i was really close to going down there that night, glad i didn't
11:47seubertglad your friends are ok
11:47seubertbrutal shit
11:48ambrosebsarrdem: are you applying this year?
11:48arrdemambrosebs: probably. just pinged deepbluelambda to chat about his lightweight clojure idea
11:49arrdemambrosebs: looking for an excuse to play with Clojure compilers over the summer tbh :P
11:49ambrosebsarrdem: great
11:58cemerickdnolen_: FYI, https://github.com/clojure/clojurescript/commit/0c7b31ada01237de33cef77b817ccef3f2b3576d changed closure/build so that it never returns a string containing the compilation output; (output-one-file ...) isn't in a return position.
12:00katratxocemerick: do yo think this friend change makes sense? https://gist.github.com/iperdomo/9596103
12:01cemerickkatratxo: I have it open in a tab, but haven't looked at it yet.
12:02katratxocemerick: ok, no problem it's not urgent ;)
12:03dnolen_cemerick: fixed in master now, thanks
12:04cemerickdnolen_: thanks; new patch on 656 coming your way right after I rebase and check against master again
12:18juxovecWhat you would do if function has too many args? http://stackoverflow.com/questions/22459629/what-to-do-when-function-has-too-many-arguments
12:21bbloomjuxovec: much more info needed about your problem
12:23dpritchett_i'm no clojure expert but my first thought is "write functions that don't need six parameters". I'm sure your actual problem is more complicated than that though
12:23juxovecbbloom: right now my controller gives to view results from model + actual data for form + data for grid orderby orderbydirection.
12:24juxovecIt goes slowly, in the beginning only one argument was needed but it grows over time.
12:26clgvjuxovec: do you need something like that? https://github.com/guv/clojure.options
12:28juxovecclgv: what would help can be named non-optional args which are checked on compile time
12:29dnolen_juxovec: #1 is the only acceptable solution in my opinion. If you really want compile time checking you should look at Typed Clojure
12:31juxovecdnolen_: I tried to add Typed Clojure to the project and my productivity went down maybe 60 %. Now I use only schema where I check most important dataflows. But thanks.
12:34S11001001“its called FAIL LOUD DESIGN... its designed to attract human admin attention if this fails”
12:35S11001001"200 lines of code and zero added features beats 100 lines of code and 5 features"
12:42shep-werkjuxovec: In OO world, we usually find collections of parameters can be wrapped into a cohesive object
12:42clojurebotGabh mo leithscéal?
12:43shep-werkso, stick them all into a map :-)
12:44Raynesjuxovec: You measure your productivity in actual percentages?
12:44RaynesAlso, https://stackoverflow.com/questions/22459629/what-to-do-when-function-has-too-many-arguments is you?
12:44dpritchett_Yeah as a Rubyist I was tempted to recommend using a closure to store a pre-configured object and manipulating it directly
12:44dpritchett_but I am not gonna contradict dnolen_
12:45juxovecRaynes: it just seems to me that with Typed Clojure I need three times more time to do anything
12:52bbloomjuxovec: when you have too many arguments, you have to first decide if you need to simplify your problem or simplify your solution (or both!)
12:52bbloomjuxovec: are the arguments related to the problem domain or the solution domain?
12:53juxovecas I wrote, I pass arguments from controller to view, its couple of results from models + some data for ordering and filtering data in datagrid (all are validated and modified query params)
13:16mdrogalisCan someone please help me write a little macro to do this? https://gist.github.com/MichaelDrogalis/9603819
13:16mdrogalisI'm stuck on figuring out how to be able to use x by name in the body.
13:17justin_smithmdrogalis: ~'arg iirc
13:17justin_smith~'x in your case
13:17clojurebotGabh mo leithscéal?
13:17justin_smithnow to actually try writing that macro
13:18mdrogalisThanks, justin_smith.
13:19danno1If strings are interned already aren't keywords irrelevant?
13:20llasramdanno1: Not all strings are interned, and interned string != identical object
13:21llasram,((juxt = identical?) '^:a foo '^:b foo)
13:21clojurebot[true false]
13:21danno1liasram: Oh so, so strings can be instantiated?
13:21technomancyplus strings are final
13:21llasramYeah, that too...
13:21technomancyso you can't make them ifn
13:21justin_smithmdrogalis: (defmacro guarded [val & body] `(when-let [~'x ~val] (when (not= ~'x ::poison-pill) ~@body)))
13:21justin_smithworks for me in my repl
13:22llasrammdrogalis, justin_smith: Why not just use an autogensym?
13:22justin_smithllasram: (guarded 2 (+ x 1))
13:22llasramOh, specifically for evil. Got it
13:22justin_smithshould return 3
13:22clojurebotExcuse me?
13:22justin_smiththat's what I assumed, at least :)
13:23mdrogalisHmm
13:25mdrogalisWorks great, thanks justin_smith!
13:25justin_smithnp, I made something similar for an ill-considered DSL ages ago
13:25justin_smithI reconsidered the technique, but will never forget how it was done
13:25justin_smithlol
13:26justin_smithnext time someone asks I should just be like "I know how to do that, but I'm a changed man general, I don't do that kind of work any more"
13:27justin_smiththe evils I have commited against hygeine will haunt me forever
13:27mdrogalisYeahhh.
13:27llasramMmm, context
13:27justin_smithheh
13:28mdrogalisI was stuck on trying to pass the entire bindings vector to the macro.
13:28mdrogalisObviously couldn't unroll it easily.
13:29justin_smithyeah, that's what I was doing, basically making a custom bindings vector
13:30mdrogalisAh
13:37dnolen_seangrove: ping
13:38seangrovednolen_: pong
13:39dnolen_seangrove: so read over your copy from yesterday a few more times - it is very close to some ideas I had floating around (I was getting thrown off the code since there are some types :)
13:39seangrovednolen_: It's all shambolic right now, I don't expect to keep much code from this phase, but the ideas are panning out really well for tooling.
13:39dnolen_seangrove: for higher level tooling your approach makes sense - breaking the relationship between the structure needed by a component and what actually appears in the app state. definitely something I allude to in my tutorials - but your taking it a bit further.
13:40dnolen_seangrove: in any case, I like how simple the idea is really - I would probably just write a couple more drafts to make the point clearer
13:41dnolen_seangrove: your org file made much more sense to me than the other materials
13:41seangrovednolen_: Cheers, appreciate it. I think if I remove serializable notes from the code, it can simplify it further (no need for the registry, etc.). I can introduce that later.
13:44upwardindexIs performance and java interop the two most important reasons for protocols?
13:44justin_smithupwardindex: they also help a lot with the fact that clojure namespaces cannot be recursive
13:45technomancyupwardindex: yeah
13:45justin_smithie. a.b cannot require a.c while a.c also requires a.b
13:45justin_smithwith a protocol that both can see, you can flatten out the cyclic dep
13:46technomancyeh; you can also do that with multimethods and resolve
13:46technomancys/and/or/
13:46justin_smithwhich brings us back to performance of course
13:46justin_smithfair enough :)
13:47llasramupwardindex: And the fact that protocols may be `reify`d
13:47upwardindextechnomancy: justin_smith: thanks! I'll keep using multimethods and not worry too much about not feeling the need for protocols :D
13:51gf3Is there cool pattern matching to match any item? e.g.:
13:51gf3(remove #{[:b _]} [[:a 1] [:b 2] [:c 3]])
13:52gf3for _
13:52rasmustogf3: https://github.com/clojure/core.match ?
13:52amalloygf3: (remove (comp #{:b} first))
13:52rasmustoamalloy: hah, or that
13:53gf3amalloy: Balls, was hoping for something a bit more declarative
13:53gf3amalloy: Thank you
13:54dnolen_gf3: you could write a little function sugar over core.match
13:54amalloymore declarative? i hereby declare that elements whose first item is :b shall not be permitted in this list!
13:54llasramheh
13:54gf3amalloy: haaah haaahahaha
13:54amalloyseriously though i don't see how #{[:b _]} would be any more "declarative"
13:55amalloyit's more...recognizable, in that the shape of the solution hints at the shape of the problem
13:55dnolen_(pat [:b _]) -> (fn [x] (match [x] [:b _] true :else false)) or whatever
13:56gf3dnolen_: Cool
13:57dnolen_gf3: you get all the fancy matching stuff for free o' course, maps etc.
13:57gf3dnolen_: Indeed, and it works ootb if I specify an exact match which is neat
14:02dbaschis there a tried-and-true way to do user/pass management in a compojure web app?
14:03justin_smithdbasch: basic auth, or setting a cookie, or?
14:03dbaschjustin_smith: mostly the db side of things
14:03RaynesI use environment variables for pretty much all configuration of my web apps.
14:04dbaschthe one thing I don't want to reinvent if possible is storing/looking up users and hashed passwords
14:04justin_smithdbasch: use a method that checks a hash, store the login and hash in the db
14:04justin_smiththere is not much to reinvent there
14:05justin_smithunless what you are really asking about is a db schema dsl / lib
14:05dbaschjustin_smith: that's what I'll do, I just wondered if there was a small library that did it already
14:05technomancy...and by hash he means bcrypt
14:05dbaschtechnomancy: or scrypt
14:05technomancyright; just not sha1 or md5
14:05technomancyjust so we're clear on that
14:06dbaschtechnomancy: exactly
14:06justin_smithtechnomancy: unless you mean basic auth, bcrypt is not appropriate for basic auth, it is good for log in once and store a "logged in" cookie
14:06technomancy~guards
14:06clojurebotSEIZE HIM!
14:06dbaschseangrove: retweeted
14:07seangrovedbasch: Looks like there might be something in lib-noir http://www.luminusweb.net/docs/security.md
14:07seangroveI don't think I'd bother with it too much, but who knows
14:07dbaschseangrove: I'll just do it myself, it's fun anyway
14:07justin_smithwe had a minor debacle where I set up what was supposed to be a "generic authentication field" for our modeling system, and someone decided to attach it to basic auth (which gets checked on every single request) and performance was really really bad.
14:08technomancyouch
14:08dbaschjustin_smith: I'm giving the user a token that lasts for a while, so that's not an issue for me. This is an api
14:09justin_smithgreat, then bcrypt is awesome for that
14:09firefauxdoes anybody know how I would go about making a "pointer" in a data structure node on disk to another node?
14:09firefauxI know I could use filenames, but those would vary in length
14:09justin_smithsounds like you want a synthetic identifier
14:10justin_smithhttp://en.wikipedia.org/wiki/Surrogate_key
14:10justin_smithuuid is good for that kind of thing, that can be portable across boxes / db engines if need be
14:11firefauxisn't UUID for identifying disc partitions?
14:11justin_smithit is for anything that needs to be universally unique
14:11firefauxok
14:11firefauxand java has an API for that?
14:11firefauxah yes
14:12firefauxjava.util.UUID
14:12justin_smithie. you know two different systems / components won't generate conflicting ones, so you can refer to them seamlessly on distributed setups
14:12justin_smithyeah, it has a method to create random ones
14:12justin_smithand they are big enough that conflicts are vanishingly unlikely
14:13justin_smith,(java.util.UUID/randomUUID)
14:13clojurebot#uuid "796d597c-3204-4854-b218-43ea2a710cd0"
14:13justin_smith,(str (java.util.UUID/randomUUID))
14:13clojurebot"d2e164c6-c08f-4756-84a1-9f25af3183eb"
14:14firefauxcool
14:14firefauxbut then how do I actually assign a UUID to a file?
14:15justin_smithprobably via a relational db?
14:16firefauxso doesn't that mean the relational db would have to store all of the filenames?
14:17firefauxalong with their associated UUID?
14:17justin_smithit sounds like it would be a good idea for you to step back and design the data schema / architecture before solidifying things though (not really knowing any of your details of course)
14:17justin_smithright
14:17firefauxokay
14:17justin_smithor you could have a function from filename to UUID - it really depends on your constraints
14:17justin_smithie. what kind of dir structure / naming convention limits you can / should impose etc. etc.
14:18firefauxwell this is for an assignment, creating a BTree which maps String keys to URLs
14:18firefauxand I can set a reasonable limit on the key size
14:19firefauxbut obviously URLs must be variable length
14:19firefauxof course, I could always use something like tinyurl...
14:19justin_smithalso a URL does not have to map directly to the directory structure (though that is of course simpler)
14:19firefauxI was thinking I would put URLs in their own files
14:20firefauxand have a "pointer" in the datastructure to those files
14:20justin_smithyou could also use a hashing system of some sort (which is what tinyurl is doing)
14:21justin_smithand of course their urls are not referring to a directory structure directly, there is a db in the middle, mapping hashes to strings
14:23amalloywhat are the cool kids using for oauth these days?
14:25TimMcamalloy: Clients, or providers?
14:26justin_smithclj-oauth here for clients, dunno if we are cool
14:26justin_smithhttps://github.com/caribou/twitter-api
14:26firefauxmaybe I'll just keep my whole database in one randomaccessfile, so I can just use offsets and not worry about files
14:26justin_smithfirefaux: do you have a reason not to use a real db?
14:27amalloyTimMc: client
14:27firefauxjustin_smith: well I have to implement everything myself, pretty much
14:27justin_smithfirefaux: oh, because it is an assignment?
14:27amalloygoes to show how clueless i am about oauth - don't even know how to ask my questions right :P
14:28firefauxjustin_smith: right. I can use whatever resources I want, but the whole assignment is basically making a database
14:35augustlwhat's a good way to get everyting in a file from after a blank line? I have a file with "header\nheader\nheader\n\nbody here\nhello, world", I want to extact the body
14:36augustlcurrently I do a line-seq and join afterwards, seems a bit wasteful..
14:36dpritchett_drop-while ?
14:36amalloyaugustl: maybe you don't want it all as one giant string anyway, if you're worried about the waste of using line-seq+join
14:36augustldpritchett_: yeah, that's what I use on the line-seq
14:36rasmustoI was going to say line-seq and drop-while +join
14:37augustlamalloy: hmm, good point. I'll look into not joining it at all
14:37augustlthe reason I make it into a single string is so I can put it into hiccup
14:37amalloyhiccup is happy to take lists
14:38augustlmakes sense :) I'll investigate.
14:39gf3dnolen_: Where can I find more info on undo managers and snapshottable UI w/ OM/React?
14:39gf3dnolen_: Finding mostly twitter threads :)
14:39gf3(Sorry if double post, my VPN died)
14:40dnolen_gf3: there's really not much to read - you get it for free
14:45mr-foobargf3: In github.com/sgrove/omchaya there is an example history player. The impln basically made every state change as an event, which could be acted on.
14:47gf3mr-foobar: Cool thx
14:50augustldoes it make sense to (doall (map fn an-io-seq)), to ensure that the map happens immediately, not lazily after the io stream object is closed?
14:50rasmustoaugustl: that works, but you may want to use doseq for side-effects
14:51augustlrasmusto: my map is pure, I just have to ensure it evaluates while the IO object is open
14:51amalloyaugustl: that is one of the few defensible uses of doall. there are other approaches worth considering too, though
14:51rasmustoer, s/side-effects/reading
14:51augustlamalloy: I'd love to hear about some of the other approaches :)
14:51rasmustoaugustl: ah, nm. Doall makes more sense. I had everything mixed up :p
14:52augustlrasmusto: ah :)
14:52amalloyeg, instead of returning a sequence from your function, pass a "continuation" sort of function *into* it: "here's what to do with the seq of things, please do it before you return [and thus close the iostream]"
14:53augustlamalloy: I see, that makes sense
14:53augustlthat also enables the memory usage benefits of lazy seqs
14:53amalloyit kinda turns things inside out, so it's a bit awkward. but at some point you'll have to realize the results of the map, and this lets you do it inside the resource's dynamic scope
14:54amalloythat's really how with-open works, in a way. (with-open [r (foo)] (f r)) is a macro, but it could have been a function: (with-open* f (foo))
14:55hiredmanaugustl: http://ce2144dc-f7c9-4f54-8fb6-7321a4c318db.s3.amazonaws.com/reducers.html
14:56augustlhiredman: thanks! I never use reducers, since I'm not familiar with them.. Will read.
15:00augustlhmm, I currently run a multi-line regex on my joined multi-line string. I don't suppose there are any ways to match a regexp over a seq as if it was one string..
15:00augustla seq of strings that represent lines
15:08augustlI'm screwed.. My syntax highlighter wants (multi-line) strings, so I can't just use the lines from line-seq directly.
15:15aaronj1335hey folks is (into {} ...) the fastest way to make a hash map from a long sequence?
15:16aaronj1335my quick little benchmarks suggest `into` and (apply hash-map ...) are the best
15:20Cr8into will do (persistent! (reduce conj! (transient orig-coll) input-coll)) on transientable types
15:21Cr8hash-map calls Persistent
15:21Cr8hash-map calls PersistentHashMap's create method
15:21Cr8which is basically the java equivalent of the above https://github.com/clojure/clojure/blob/1798b449b84c86a9b243bd79929a3a619194aa24/src/jvm/clojure/lang/PersistentHashMap.java#L52-L59
15:24Cr8so I'd just consider them equivalent.
15:26aaronj1335Cr8 cool thanks
15:27aaronj1335i'm trying to convert a python program that does some nlp stuff to clojure
15:27aaronj1335and the clojure version is 4-5x slower
15:27aaronj1335and i'm trying to figure out why
15:29bbloomaaronj1335: is the code small enough to gist?
15:29aaronj1335bbloom yea, it's a bit confusing tho because it's reading files from a weird format, so it may be a bit tough to understand. i'll gist it up, and see if it makes any sense
15:30bbloomaaronj1335: don't do that yet
15:30bbloomaaronj1335: first, decomplect the file loading and the logic
15:30aaronj1335ok
15:30bbloomso that you can benchmark apples against apples
15:30ptcekHow can I find what port the repl is running on?
15:30aaronj1335i've got that logic separated
15:30bbloomaaronj1335: the just post that part
15:30aaronj1335cool
15:30sdegutisptcek: what repl?
15:30clojurebotHuh?
15:31sdegutisptcek: there is usually an .nrepl-port file created in the dir you're in
15:31Pate_ptcek, are you running `lein repl` ?
15:31Pate_second sdegutis.
15:31Pate_also, `lein repl` will output the the host and port it is running on.
15:32ptceklein repl will... and .nrepl-port are good suggestions...
15:32ptcekI just opened datomic tutorial and started repl using the script there... but it does not necessarily listen on any port right? (i want to connect from emacs/vim)
15:33ptcekIt will be simpler to just create a new lein project I guess.
15:35seangrovednolen_ bbloom https://www.dropbox.com/s/8nroaf6dfa0a7ak/zenrise_barebones_app.mov wherein we make a barebones, unstyled, no-layout chat app. The next version of the tooling will replace the typing with a popup app-state inspector, so you can visually glue the transformer inputs to nodes in the tree. After that, there's no competition about building more maintainble UI's/client apps :)
15:35aaronj1335bbloom here's the code: https://gist.github.com/aaronj1335/9606615
15:36bbloomseangrove: is this not the same video as before? what's different?
15:36seangroveA developer hands the designer a snapshot of the app-state, and the designer can then glue that to the components independently
15:37bbloomseangrove: that's how it should work :-)
15:37bbloomaaronj1335: and you're saying that python is dramatically faster at this simple task?
15:37seangrovebbloom: Not enough yet, except that it's a functioning chat app with multiple components interacting and reading/updating the app state
15:37bbloomaaronj1335: even after warming up the jit by running it many times?
15:37aaronj1335bbloom 4-5 times yes
15:37seangroveBut of course doing it all in a closure to functionally-pure way
15:37aaronj1335yea, i basically paste the snippet into the repl several times
15:38bbloomaaronj1335: you can't get a realistic benchmark that way
15:38aaronj1335usually takes ~31 secs for clojure, only 4.5ish for python
15:38bbloomaaronj1335: use (time (dotimes [i n] ...
15:38seangroveThat's a pretty big difference
15:39aaronj1335(also i added the python snippet i'm using)
15:39bbloomaaronj1335: is "labeled tokens" a particularly big sequence?
15:39aaronj1335around a million items
15:39seangrove$seen noprompt
15:39lazybotnoprompt was last seen quitting 2 days and 20 hours ago.
15:40bbloomaaronj1335: then your problem is lines 4 and 5 vs python lines 4/5/6
15:40bbloomaaronj1335: you're walking the sequence twice in the clojure version
15:40aaronj1335bbloom that was faster than a (reduce) call where i incrementally built the sets
15:41aaronj1335only one loop in the reduce call
15:41bbloomaaronj1335: i'd have to see that code too
15:41aaronj1335one sec...
15:41bbloomfor a million items, memory access time is going to dominate the loop time for such simple transformations
15:42Morgawrhttp://i.imgur.com/J7hlC0t.png
15:42Morgawrsounds relevant
15:43bbloomseangrove: looking forward to seeing what UI you come up with for the transformer business
15:44seangrovebbloom: Probably going to be a bit small-talk-ish. Would be fantastic to have cljs-in-cljs at this point, heh. But ultimately, the transformer code (and probably controller code) should be written in javascript
15:45seangrovebbloom: Open up a small window (in terms of where they extend the app) for normal js developers to work in, tell them, "This function will receive these inputs, and must return the new state at the end. No side effects are allowed in this function." Let them write the javascript to handle that, and now they're plugging into a functionally-written cljs app
15:46seangroveBut that's all later. Going to try to get the UI for the transformer glue done tonight, and then go for a long walk.
15:49dbaschtechnomancy: do you see any obvious issues with my password validation? https://www.refheap.com/60118
15:50aaronj1335bbloom ok i replaced the double loop in the gist w/ a reduce call. now it's running at like ~39ish seconds
15:50Frozenlockcemerick: I'm trying your clojurescript.test, which seems to be exactly what I was looking for. However, I get a weird error... would you mind checking it out? https://www.refheap.com/60117 (and yes, I'm using (:require cemerick.cljs.test) like suggested)
15:51bbloomaaronj1335: need to see the code. also, you should benchmark simply no-op walking the file to see if you have an issue there
15:51cemerickFrozenlock: https://github.com/cemerick/clojurescript.test/issues/53
15:52aaronj1335bbloom i updated the gist w/ the reduce call if you'd like to look at it. walking the file alone is ~7 seconds.
15:52aaronj1335thnx for your help, btw, this is very kind of u
15:53dnolen_aaronj1335: also make sure you are running Clojure w/ adequate memory + JVM -server option
15:53Frozenlockcemerick: Ah! Thanks! Would you suggest to add the js file, or use SlimerJS?
15:53aaronj1335dnolen_ i'm giving it 2G
15:53dnolen_aaronj1335: and -server?
15:54cemerickFrozenlock: I'd follow @noprompt on this, I've not had to think about it
15:54bbloomaaronj1335: this is one of those rare situtations where you actually want transients
15:54aaronj1335dnolen_ one sec...
15:54aaronj1335dnolen_ that goes in the :jvm-opts array of my project.clj?
15:54Frozenlockcemerick: understood. Thank you very much.
15:55bbloomaaronj1335: also the code you pasted me is invalid
15:55bbloomyou're reducing over "tokens" which is not defined
15:55aaronj1335(in order to have the -server option for my repl)
15:55dnolen_aaronj1335: yes :jvm-opt ^:replace [...]
15:55dnolen_aaronj1335: lein has bad defaults for benchmarking
15:55aaronj1335cool thnx
15:56dnolen_aaronj1335: :jvm-opts ^:replace ["-Xmx512m" "-server"]
15:56dnolen_or something like that
15:56aaronj1335bbloom sorry, that was just a bad paste, i'll update it, but that should be labeled-tokens
15:57aaronj1335i'm running some unit tests before i bench mark to keep my sanity, but i can't do that on the gist stuff
15:58bbloomaaronj1335: try loop/recur with http://clojure.org/transients
15:58bbloomyou definitely want transients for that many objects
15:58bbloommemory access and GC are going to dominate the code as you have it now
15:58bbloomthe mutability in python actually spares you a ton of garbage overhead, doubly true when you do one loop instead of two
15:58bbloomthe reason the reduce is SLOWER is b/c into uses transients internally
15:58aaronj1335right on
15:59dnolen_bbloom: aaronj1335: even that said I would be surprised if you see a 4X boost from running w/ the right JVM settings
15:59aaronj1335yea i was wondering if there was a good way of using mutable stuff w/o having to make a bunch of java method calls
15:59bbloomdnolen_: wouldn't?
16:00dnolen_bbloom: oops yes
16:00dnolen_aaronj1335: I would first get the fastest idiomatic Clojure, should compete w/ Python
16:00dnolen_if you want to get much faster than that, it's definitely possibly but a bit fiddly / tedious
16:01bbloomdnolen_: even with a 4x improvement, he'd still not be competitive with python b/c the work each program is doing is so wildly different
16:01bbloomentertainingly, his code is a pathological case for the intersection of persistent data structures and lazy sequences :-)
16:02aaronj1335bbloom u think the lazy-seq's hurt perf here?
16:02bbloomaaronj1335: absolutely
16:02bbloomaaronj1335: again, increased allocation and garbage preasure
16:02dnolen_bbloom: the comparison is fair insofar as Clojure gives good performance for functional patterns compared to imperative approaches in imperative "scripting" languages
16:05aaronj1335well bummer... i was using lazy-seqs all over the place (esp. in the other code that reads the files) b/c i thought that similarly to python generators, they actually save memory pressure by never realizing the full array/list in memory
16:05bbloomaaronj1335: so generally lazy seqs are faster b/c you don't always do all the work
16:05bbloomespecially if you CAN'T do all the work (ie infinite lazy seqs)
16:05bbloombut when you're traversing an entire file and never backtracking, then you're paying for stuff you don't need, like all the intermediate values
16:06bbloompython generators don't capture past states in anyway
16:06bbloomthey are ephemeral
16:06aaronj1335but lazy seq's do?
16:07dnolen_aaronj1335: uh, I strongly suggest not getting lost in the performance assumption weeds just yet. Just make your code pretty and run it w/ the right JVM settings first.
16:07bbloomaaronj1335: you can hold on to a lazy seq and it won't change
16:08bbloomaaronj1335: reducers let you keep the pretty functional style and eliminate the overhead of the lazy seqs b/c you can only get at the final answer, not the intermediate results
16:08bbloomaaronj1335: you can get exceptionally good performance in both space and time for the same style of code
16:09bbloombut (sadly) i don't think that clojure exposes a reducable data type for files as lines
16:10TheMoonMasterI'm horrible with macros, I have a macro that defines an anonymous function that takes 1 argument, how can I make that argument available to the body passed to the macro?
16:10aaronj1335cool... i've got something to run to now, but i'll clean up the perf comparisons and jvm settings and may be back later tonight w/ more questions and fuller examples. thnx again dnolen_ and bbloom for your time
16:10gtrakTheMoonMaster: you should take the captured symbol as input
16:10TheMoonMasterI have no idea what that means.
16:11TheMoonMasterI have something like this in there right now, `(fn [msg#] ~@body)`
16:11TheMoonMasterI need msg# available in body, but I'm totally clueless.
16:11gtrakright, so msg# is a gensym, which is the opposite of what you want.
16:11TheMoonMasterAh
16:12mschuenedo ¯'msg if you want to call it msg inside the body
16:12gtrakguaranteed to be unique and not clash with what's in ~@body. but don't do 'msg instead, the client should pass into the macro the desired symbol.
16:12mschueneyes
16:13gtraklike (defmacro somemacro [sym & body] `(fn [~sym] ~@body))
16:13gtrak(somemacro msg (do-crap-to msg))
16:13TheMoonMasterIn this case it doesn't really make sense to have it passed in.
16:14gtraknot the value, just the name
16:14TheMoonMasterRight, still makes sense as just msg.
16:14mschuene~' is the quoting you want here
16:14clojurebotIk begrijp
16:14gtrakyea, it's just ill-advised to invisibly do stuff like that
16:14gtrakin general
16:14TheMoonMasterYeah, if it were a library or something more than what it is, I'd totally do that.
16:15gtrakjust so you know :-)
16:15mschueneit is OK if the client can specify how an anaphoric symbol will be named imo
16:15TheMoonMasterI appreciate the heads up and the help
16:15amalloymschuene: if the client says how to name it, that's the opposite of anaphoric
16:16seangrovednolen_: What's the state of meta in cljs? Is it readable at run-time (e.g. getting the metadata of a function at runtime)?
16:17gtrakseangrove: what's the use-case?
16:17gtrakI implemented something like that off analyzer data
16:17seangrovegtrak: Deciding on where to put the parameters for functions for introspection by a end-user tool
16:18gtrakhrm...
16:19gtrakso this is runtime-wiring or is the cljs compiler available?
16:20dnolen_seangrove: metadata on the function var you cannot get at runtime
16:20dnolen_seangrove: functions do support adding meta at runtime though
16:20seangrovegtrak: Right now run-time, could possibly push it into the compilation stage. Not the biggest deal for the time being
16:21gtrakmaybe a macro could bridge the gap
16:22gtrakthere's a dynamic var that stores the analyzer env, not sure about lifecycles and timing of these things.
16:23mdrogalisI've been looking for this forever. Stu Halloway on abstraction/encapculation Clojure's state perception model. http://vimeo.com/45136215
16:23mdrogalisNow I just wish I remembered who was asking for it D:
16:23mdrogalis4:50 - 8:00 ^
16:41shiranaihitois there an idiomatic approach to throwing exceptions from Clojure code? i'd like to produce some specific type of exception in a specific situation, but it feels a bit unwieldy so far
16:42amalloyclojure is pretty lax about exception types
16:43amalloypeople usually just throw any old garbage, and if you want to be specific you can use ex-info and ex-data to convey a lot more information than just a type
16:53shiranaihitoamalloy: do you think that common habit is.. alright?
16:53shiranaihitoi'm still new to clojure, but somehow i feel like trying to take care to produce clear, situational errors from clojure code is unwieldy
16:54shiranaihitomaybe i'm missing something.. or maybe that's why people just throw any old garbage, whatever that means exactly :p
16:55arohnerisn't there an official clojure 'contrib' lib w/ a better version of clojure.walk?
16:55amalloyit has its pluses and its minuses. i'd say there are more important things to figure out, for a new clojure programmer, than how to throw intricate exceptions
16:55shiranaihitoamalloy: what's your take on the unwieldiness though?
16:56amalloyi don't try to throw fancypants exceptions. i try to return data that indicates what went wrong
16:57technomancyex-info is a beautiful thing
16:57technomancyprobably my favourite new feature since 1.1
16:57shiranaihitotechnomancy: .. meaning? :p
16:58gtrakexceptions are annoying, but at least we have macros to deal with them better :-)
16:58shiranaihitoamalloy: well, i'm not trying to be fancy - just clear and informative, but do you have some kind of typical approach to returning data that indicates what went wrong?
16:58technomancyshiranaihito: dunno, I like it a lot? I find it adds a lot of expressivity.
16:59shiranaihitotechnomancy: well, i was wondering how you use it, but i guess that doesn't really matter because i'm not even familiar with the function itself :p
16:59technomancyif there's ever any reason a caller would need to make decisions based on what went wrong, ex-info is the way to go
16:59shiranaihitohmm
16:59technomancy(unless the caller is a java program or something)
16:59rasmusto,(ex-data (ex-info "blah" {:who 'what}))
17:00clojurebot{:who what}
17:00shiranaihitoohh alright
17:01zuzkinsHello guys. Does anybody know, if there is a protocol to extend on 3rd party type in clojurescript to alter the way prn-str prints it. I can't find it. Thanks
17:05dnolen_zuzkins: -pr-writer
17:10zuzkinsdnolen_: thank you
17:10dnolen_zuzkins: np
17:37NnelDoes Clojure support cyclical(?) definitions? E.g. A includes calls to B, B also includes a recursion into A.
17:37francis_wolkeNnel: no
17:37brehaut(doc declare)
17:37clojurebot"([& names]); defs the supplied var names with no bindings, useful for making forward declarations."
17:37amalloyNnel: it's possible with letfn or declare, but most of the time there's a better approach
17:37brehaut(doc letfn)
17:37clojurebot"([fnspecs & body]); fnspec ==> (fname [params*] exprs) or (fname ([params*] exprs)+) Takes a vector of function specs and a body, and generates a set of bindings of functions to their names. All of the names are available in all of the definitions of the functions, as well as the body."
17:38francis_wolkeI misspoke - you can use declare, but you can't do async loads of other namespaces.
17:39Nnelamalloy: brehaut , cheers, yeah there are better ways for sure.. just using clojure to lazily go through a scheme book :P
17:39amalloy,(letfn [(even? [x] (or (zero? x) (odd? (dec x)))) (odd? [x] (and (not (zero? x)) (even? (dec x))))] (even? 10))
17:39clojurebottrue
17:43Nnelamalloy: Thanks
17:45chareyou guys know how with ruby on rails it automatically compresses js files and puts them all into one big file
17:45charewhen using clojure with ring, compojure, etc... what is the equivalent
17:47justin_smithuse an asset minification step, this is built into clojurescript, but you can also use grunt or the closure compiler directly if it is plain js
17:47charejustin_smith so you're saying there is no framework already setup I gotta set it up myself
17:48justin_smiththere may be, none that I use
17:48justin_smithunless you are using clojurescript, there are setups for that
17:48seangroveThere's dieter, and I think there's also a successor
17:48seangrovetime to dance!
17:51charejustin_smith you also know how ruby on rails does more than minification it also does a kind of versioning by dealing with md5
17:51charedon't i need that too?
17:51justin_smithI don't know what you need
17:52justin_smithI think hlship is working on some kind of asset pipeline solution, but I don't know the details
17:52charejustin_smith so you're saying you're not familiar with rails asset pipeline?
17:52charedamn it
17:56bbjvahi all
17:57bbjvaI have a question about fucntions in Clojure, can someone pm me if you feel like helping
17:57rasmusto~anyone
17:57clojurebotanyone is anybody
17:57rasmusto~anybody
17:57clojurebotJust a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."
17:58amalloy~clojurebot is constantly polluting useful triggers like ~anyone by learning other irrelevant factoids to repeat instead
17:58clojurebotIn Ordnung
17:59rasmusto~anyone
17:59clojurebotJust a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."
17:59rasmustowait, hm?
18:00amalloyrasmusto: he has multiple hits and chooses one at random
18:00seangrovebotsnack
18:00rasmustoamalloy: ah, gotcha
18:00rasmusto~snotback
18:00seangroveclojurebot: botsnack
18:00clojurebotTitim gan éirí ort.
18:00clojurebotThanks, but I prefer chocolate
18:01amalloymakes it impossible to reliably use ~anyone or ~anybody
18:01seangroveIt's not clojurebot's fault
18:01amalloyi've tried un-teaching him the relation between those two, but it doesn't have any effect
18:01brehautamalloy: if only there was another bot you could program to reliably respond to a set of facts
18:02amalloydespite how unreliable clojurebot's factoid system is, it's still so much more convenient than lazybot's
18:03technomancyit's part of the deranged charm
18:03technomancylike how you have to smack the tardis control panel a few times before it goes
18:11justin_smithor blowing on the cartridge to make it work
18:12justin_smithtechnomancy: that's called percussive maintenance btw http://en.wiktionary.org/wiki/percussive_maintenance
18:12rasmustoi guess you were supposed to use IPA and a q-tip
18:13rasmustoi always blew the dust out (because my carts were in my tree fort)
18:13technomancyyou put beer on your NES carts?
18:13rasmustoisopropyl
18:13bbjvaI am trying to write a function that accepts keyboard input (which is then stored as a var) I surely need some pointers!
18:13technomancyoh that makes more sense
18:14justin_smithtechnomancy: the hops help mario jump higher, duh
18:14amalloy((juxt inc dec) justin_smith) ;; i wish this worked
18:14justin_smithhah
18:14technomancyheh
18:14amalloyi mean, i guess it does, right? i left his karma the same
18:15brehautjustin_smith: the blowing dust out of power / usb cables is mostly successfully a social engineering trick for help desk people: nobody wants to believe that they were stupid enoguh to not check something was plugged in before calling the help desk. 'blowing on it' is a good excuse for getting the user to actually check
18:15justin_smithI haven't heard of blowing on the cable
18:15justin_smith*hadn't
18:15technomancybrehaut: I heard it had more to do with the act of disconnecting and reconnecting
18:16rasmustoI like when people twist down harder on the VGA cable screws
18:16rasmustoif video doesn't work
18:16amalloyyeah, that's what i heard too, technomancy. something in the NES connectors didn't always click right, and just taking it out and putting it back was the real solution hidden behind blowing on it
18:16brehauttechnomancy: any excuse to get someone to check and have an excuse when it was just not plugged in properly ;)
18:16justin_smithbbjva: pretty much everything in the jvm is a pointer to something in the heap - perhaps you mean a reference type that can be updated (like an atom or ref or agent)?
18:17bbjvatyeah
18:17bbjvayeah
18:17dbaschhow do I redirect the output of clojure.tools.logging so that it appears in the slf4j output from "lein ring server"?
18:17bbjvasorry
18:17brehautamalloy, technomancy: and pulling it out might scrap off some of the rust accumulating on the pins due to blowing
18:17bbjvaI am coming from a java/c background
18:17amalloyhah
18:17bbjvatrying to figure it out
18:17justin_smithbbjva: also, most processes that require mutation in an imperative language can be translated to a functional form working on an immutible stream of input (lazy seqs or a reduction across some input)
18:17bbjvathanks
18:18bbjvano mutation in fp
18:18bbjvais taking me a bit of time to get used to
18:18justin_smithit is possible, but less often needed
18:18bbjvayeah
18:19bbjvapicking it up for work, loving the language lots so far, just changing my way of thinking is taking time
18:19bbjvai was an object head, but no longer
18:19justin_smiththe general pattern is to ask how the thing that was changing can be a parameter of a strict function (such that the "change" is a changed input, and the same input will always get the same result)
18:19bbjvaor at least not after 5 pm
18:19bbjvaokay
18:19justin_smithheh, it takes a while, but I think pretty much everyone here would agree it is worth it
18:20bbjvait seems like it
18:20gtrakbecause everyone else doesn't make it this far :-)
18:22justin_smithheh, like Douglas Adams' puddle
18:22gtrakthey stick to their comfy iterators and generics (hard to say with a straight face)
18:22justin_smithImagine a puddle waking up one morning and thinking, "This is an interesting world I find myself in — an interesting hole I find myself in — fits me rather neatly, doesn't it? In fact it fits me staggeringly well, must have been made to have me in it!"
18:24brehautgtrak: i have a hard time finding generics to be something detrimental
18:25brehautgtrak: its about the only part of contemporary big OO type systems that is nice :P
18:25gtrakthat's like saying I'd cut my arm off so I can get a prosthetic
18:26gtrakprosthetic nib
18:27gtrakmaybe it's not generics that are ugly but generics + classes/inheritance.
18:27gtrakI have rather painful memories.
18:27brehautyeah classes and inheritance are a pig
18:28brehautand yes they do make generics bleark
18:28brehautyou need to have good variance constraints (C#4+)
18:28amalloy$dict bleark
18:28lazybotamalloy: Word not found.
18:28amalloy:(
18:28brehautbut then you have to deal with variance constraints which are a mess
18:28brehautamalloy: onomatopoeia
18:28brehauta being sick noise
18:29amalloywell, i'm glad it's been a while since i had lunch. that's a pretty specific sound
18:30brehautsorry about that
18:31brehautgtrak: generics are also much more useful when used with discriminated unions than interfaces
18:34shriphanihi. I have a weird situation where java reflection confirms that a method exists but I can't seem to invoke it. Here's the trace I got from the repl. Can someone help? https://gist.github.com/shriphani/9609733
18:35gtrakdoesn't seem hard to improve on interfaces :-), we use a language that focuses on dynamic data, after all.
18:35amalloyshriphani: a method that takes varargs like f(String... xs) actually takes a String[], not multiple arguments
18:36shriphanio wow I am an idiot.
18:36martinklepschin clojure using = is a "referential equality" check right? could anyone explain how this works internally? (or explain what it means)
18:36brehauts/idiot/unfamiliar with the specifics of java compilation/
18:37gtrakmartinklepsch: referential equality means a pointer check, ie, identical?
18:37amalloyactually it looks like this one doesn't take varargs at all, it explicitly takes a String[]
18:37shriphaniyeah
18:37shriphaniyeah and I sent in a vector
18:37justin_smith,(doc =)
18:37clojurebot"([x] [x y] [x y & more]); Equality. Returns true if x equals y, false if not. Same as Java x.equals(y) except it also works for nil, and compares numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison."
18:37martinklepschgtrak, so it compares where the pointer points to in memory?
18:37amalloyso i'll give him "careless", which is between "idiot" and "java is crazy"
18:37justin_smithman, that doc string looked like it was using an emoticon for a moment
18:38shriphaniwell, that solves my problem.
18:38gtrakmartinklepsch: I think that's what he means, this is om, right?
18:38martinklepschyeah
18:38martinklepschgtrak, thanks, think I got it
18:38gtrakreferential as in 'reference', which really means pointer..
18:39technomancymartinklepsch: clojure's = sorta implements operational equivalence, with notable omissions
18:39justin_smithmartinklepsch: note the doc string I made clojurebot print above
18:39martinklepschjustin_smith, yeah read that
18:39martinklepsch= != identical?
18:39rasmusto~=
18:39clojurebotPardon?
18:40justin_smithspecial cases for numbers and collections (things where "same structure" could semantically mean "same" even if pointers do not match)
18:40rasmusto,(= [1 2 3] '(1 2 3))
18:40clojurebottrue
18:40justin_smith,(= ["a" "b" "c"] '("a" "b" "c"))
18:40clojurebottrue
18:41gtrakI think he probably also means in the 'general case'
18:41rasmusto,(= '(\a \b \c) (seq "abc"))
18:41clojurebottrue
18:42zer,(= '(\a \b \c) "abc")
18:42clojurebotfalse
18:42justin_smithstrings are not treated as sequential collections in general
18:42dbaschso, what's the right way to have configurable debug/info/error logging in compojure?
18:43gtrakdbasch: luminus chose to use timbre
18:43SegFaultAXdbasch: That's not really a compojure thing, but log4j is the standard Java logging utility. Timbre is the best wrapper around for it.
18:43technomancy"it's complicated"
18:44technomancywait, I thought timbre was independent of log4j
18:44dbaschSegFaultAX: jetty seems to be using slf4j
18:44technomancydbasch: it depends on whether you want unification with other libs. if not I would use println+binding
18:44SegFaultAXtechnomancy: Is it? I thought it was a wrapper for it!?
18:45gtrakis timbre actually on-par with java libs?
18:45gtrakseems like it's a dead horse, but they've been beating it for quite a while.
18:45chareok so making a webapp with clojure I use Ring, Compojure, Hiccup, and what else
18:45charewhat is the standard list of stuff to use?
18:46SegFaultAXtechnomancy: It appears to be using c.tools.logging which uses slf4j. TIL
18:46gtrakchare: luminus is a good starting point, batteries-included.
18:46SegFaultAXchare: Probably friend.
18:46technomancySegFaultAX: blargh. it started as its own thing. now I don't have anything to recommend for people who can get away with avoiding the java logging quagmire.
18:47technomancyapart from just println+binding of course, which is what I use
18:47SegFaultAXtechnomancy: Heh. Fortunately c.tools.logging provides a sane interface on top of most of the standard Java loggers.
18:47justin_smithjust wrap the process in nohup and you get logging?
18:47SegFaultAXtechnomancy: So whatever you have available on your CP will be selected by tools.logging and therefore timbre.
18:48SegFaultAXhttps://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging/impl.clj#L202
18:48technomancySegFaultAX: last I checked changing log level at runtime with log4j was a complete nightmare
18:48gtrakthe java stuff brings out the worst problems in dependency management
18:48hiredmantechnomancy: that is just not true
18:48justin_smithtechnomancy: the conclusion I came to was that they consider it a security thing so it is intentionally hard to modify dynamically? either that or they are totally out to lunch architecture astronaughts that recoil at the thought of anything simple
18:49technomancyhiredman: maybe it was commons logging. it's been a while.
18:49hiredmanyou call a static method with the name of the of log level you want
18:49justin_smithor maybe I was just doing it all wrong...
18:49amalloyhiredman: i think he means "changing whether INFO gets written to a file or just ignored, for package X"
18:50hiredmanok, that isn't write, you call a static method to get the level object, then you call a method on the logger to set its level
18:50technomancylol, at astronaughts
18:50justin_smithweird typo, glad it amused you
18:50justin_smithmy fingers seem to go by bizarre phonetic rules sometimes...
18:51hiredmannewer stuff like, uh, waht is logback? which is api compatible with log4j, acutally watches the config file and will reload it if there are changes, if I recall
18:51amalloyastronaughts are people in space who nobody cares about
18:51SegFaultAXWell you can always use something else if you don't want to deal with log4j directly... like slf4j
18:53technomancySegFaultAX: java logging is amazing because there are more abstract interfaces against libraries than actual implementation libraries.
18:53technomancywhere "amazing" here is not a good thing
18:53SegFaultAXHeh. Logging is a hard problem, clearly.
18:55hiredmanso let's throw fud at it
18:57SegFaultAXhiredman: I wasn't trying to spread FUD!
18:57lgs32aI have a strange problem with friend
18:57lgs32aIt simply does not authenticate
18:58hiredmanSegFaultAX: sure
18:58lgs32aI also noticed that there is an empty hash-map under the :session parameter in the request of the any handler
18:58SegFaultAXlgs32a: Well need more details than that. gist/refheap some code.
18:59lgs32aSegFaultAX: Would it be possible without?
18:59eric_normandshriphani: answered in the gist
19:00SegFaultAXlgs32a: "It doesn't work" isn't much to go on. ;)
19:00lgs32aI think somebody who knows the friend codebase well could help me significantly
19:00hiredmanpedestal service has some nice logback logging settings and some project.clj depednency wrangling to direct other logging frameworks you are likely to encounter to logback
19:00lgs32aSegFaultAX: As I said, the :session parameter is empty
19:00SegFaultAXlgs32a: Also, I'm pretty sure friend stores the authentication map under :session with a namespace qualified key.
19:01lgs32aYes it stores ::friend/unauthorized-uri
19:01lgs32aBut only if I visit a route directly, the redirect from login results in an empty session
19:02lgs32aI am using the interactive-form workflow
19:02lgs32aAlso, :credential-fn returns a valid login
19:05lgs32aEven though the login succeeds, current-authentication always returns nil
19:08seangroveUgh, damnit
19:09seangroveWhat do I want to check for to see if a value implements lookup, like hashmaps and vectors?
19:10amalloyILookup
19:10seangrove,(satisfies? ILookup {})
19:10clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ILookup in this context, compiling:(NO_SOURCE_PATH:0:0)>
19:10amalloyon the jvm it's an interface, not a protocol, of course
19:10SegFaultAXclojure.lang
19:10amalloyand it's in clojure.lang, right
19:10amalloy,(instance? clojure.lang.ILookup {})
19:11clojurebottrue
19:11seangroveHrm, struggling to get it to work in cljs
19:11seangroveLet me see if I can find the right name for it
19:12seangrovecljs.core/ILookup
19:12seangroveThat did it, thanks!
19:14gnandretta3
19:16Morgawrdoes anybody know Jamie's handle on irc (if he's even in here)? I wanted to talk to him about GSoC (I posted in the google group for clojure but got no reply)
19:23arohnerisn't there a library that is a better version of clojure.walk somewhere?
19:24justin_smithclojure.walk2 which got subsumed into clojure 1.6 iirc? https://github.com/stuartsierra/clojure.walk2
19:30Bronsajustin_smith: no it hasn't
19:32justin_smithhttp://dev.clojure.org/jira/browse/CLJ-1239 ah I see still open
19:33justin_smiththe only place lein search finds clojure.walk2 is currently the caribou/clojure.walk2 fork
19:33Bronsawhat's in 1.6 is support for records
19:33justin_smithahh OK
19:47gfrederickswhat am I ought to use to query the data structure that data.xml/parse returns?
19:49noonianaccording to the readme you should be able to use normal clojure fns
19:50noonian(-> parsed-xml :content println)
19:50hiredmangfredericks: you can do things with zippers, there was a contrib library for slicing it up in teh past
19:52hiredmangfredericks: https://github.com/clojure/data.zip/blob/master/src/main/clojure/clojure/data/zip/xml.clj
19:53gfredericksoh I knew zip had something to do with it
19:53gfrederickshiredman: thanks
20:48SegFaultAXPhilsophical question: in an utterly object oriented language like Java, what's the best way to build up objects compositionally vs. through inheritance? As a motivating example, assume we have a User class with all the essential methods for a User. Later, we want to add methods that are logically related to each other, but aren't really part of User itself despite needing a User to do their thing. What's the most common way to accomplish th
20:49seangroveSegFaultAX: I think there's an idea of service-layers for that
20:49beamsofor the situation you've mentioned, util classes usually
20:49SegFaultAXIn Objective-C world, for example, the answer is delegates all the way down. In Clojure, we can extend new methods over our types via protocols. Haskell has type classes which are functionally similar to protocols. But what about java?
20:49SegFaultAXbailon: So you're thinking the delegate pattern then? Or something similar?
20:50hyPiRionSegFaultAX: Interfaces with default methods I guess
20:50SegFaultAXhyPiRion: Not possible until Java 8.
20:50SegFaultAXSo how does modern Java work? Is it just inheritance all over the place?
20:50hyPiRionSegFaultAX: you said it was a philosophical question :p
20:50beamsoit's both util classes and service-layers, as seangrove mentioned
20:50hyPiRionBut yes, inheritance everywhere, or util classes
20:50SegFaultAXhyPiRion: Well, ok you got me there. :)
20:51amalloySegFaultAX: just a class that contains a User object, and in addition to the methods you're adding contains a getUser() method?
20:52SegFaultAXamalloy: That's basically what I was thinking. I wouldn't bother to proxy the object (eg forward messages to the delegator)
20:52amalloyindeed not
20:52beamsoi was going to say that the types/protocols thing made me curious
20:52amalloyif a thing is not a User, but needs a User to do its stuff, why should it act like a User?
20:53beamsoin all of my clojure programming i've used maps instead of types as i'm building up information in the type during computation
20:53SegFaultAXamalloy: It shouldn't. It just defines operations that require a user.
20:54amalloyright. i'm questioning why proxying the object is even under cnosideration. i don't know why you would do that even in a language that makes it easy, like the delegates you were mentioning earlier
20:55SegFaultAXamalloy: So when you start having more complex helper classes, that's where you start using DI. Eg if my helper class needs a User and a Foobar. How does DI work when I need a /specific/ User and a /specific/ Foobar. Like `new MyHelper(new User(2), new Foobar(42))`?
20:55amalloyif it's right in that case, you might as well do it in java, since eclipse makes it like ten keystrokes to generate all the delegators
20:56SegFaultAXUgh, irccloud keeps dying.
20:56amalloySegFaultAX: i don't understand that question at all. DI works by passing in the objects you depend on, as in your example
20:57amalloyso, your example seems fine, and i don't know what alternative you're asking for
20:58SegFaultAXI'm not asking for an alternative. I'm wondering what the typical pattern is for asking a DI harness for an instance of MyHelper with parameterized dependencies.
20:58beamsotypically for DI you're not relying on a specific instance of something from a database
20:58beamsoyou're using it to inject a database connection
20:59amalloyi have no idea what asking a DI harness for something is like, i'm afraid
20:59SegFaultAXbeamso: That's exactly what I'm asking about. I get DI for those types of things, what I don't get is DI for specific instances of things.
20:59beamsoi haven't seen people do DI for specific instances
20:59alewI don't think you should ask the DI harness for anything; the point of DI is that a component receives components without any of their implementation details
20:59beamsolike, in a webapp, you might choose to have a thread local or a session variable to hold those context sensitive items
21:00alewIf you want DI for specific instances, all you can do is do some sort of reflection/type checking in order to understand what you were given
21:00SegFaultAXamalloy seems to think it can inject specific instances of things.
21:00SegFaultAXAnd I'm wondering how that would even work, since you can't know until runtime what to inject.
21:00SegFaultAXWhereas a database connection (and all the configuration for it) can be specified ahead of time.
21:01amalloySegFaultAX: you talked about dependency inversion, which i understand to be a design pattern. i have no idea what a DI harness or framework looks like
21:01justin_smithSegFaultAX: as I understand it Java DI often uses a config file to specify the class that will be loaded at runtime
21:01SegFaultAXjustin_smith: Right.
21:01beamsoconfig files, annotations or hard coded java
21:02SegFaultAXamalloy: Um, when I gave the example above of `new MyHelper(new User(2), new Foobar(42))` you seemed to dismiss that as a trivial example.
21:02amalloyindeed, you can trivially write that code yourself, and get a functioning MyHelper
21:03SegFaultAXamalloy: I asked that in the context of DI, though.
21:03amalloyapparently you and i have no common conception of what DI is
21:03SegFaultAXamalloy: Dependency injection?
21:03amalloyso anything i have said in this conversation should be dismissed as meaningless
21:03SegFaultAXamalloy: Were you not talking about dependency injection?
21:04amalloywell, when you started getting confused, i clarified that i meant dependency inversion, the design pattern
21:04amalloyyou introduced "DI" without filling in the letters, but apparently you meant dependency injection
21:04beamsoinversion of control, you mean
21:05SegFaultAXDI is a relatively standard initialism given the context. My mistake for not clarifying.
21:05amalloylooking them both up, they seem pretty similar, except that you're talking about frameworks that do DI for you in some mystical way
21:06SegFaultAXamalloy: javax.inject is a good example.
21:06SegFaultAXAs is Dagger or Guice.
21:06amalloythose are what i know nothing about; DI the technique makes sense to me
21:06amalloylike i said, i have never used any of those, and can't help you with your current goal in getting them to do what you want
21:06beamsojavax.inject? oh noes.
21:07justin_smithI suspect much of what is meant by "dependency injection" is some hoops that inflexible languages must jump through to do dependency inversion - but I may be wrong about this
21:08SegFaultAXjustin_smith: Not really. Dependency injection is just a technique for constructing, well, dependencies to things.
21:08SegFaultAXAngularJS is a recent example of a framework that uses injection pervasively.
21:09beamsofor java it was a kind of way to remove the factory method, singleton and service locator patterns
21:10SegFaultAXJersey is actually a pretty cool example of DI "Done Right" in Java, imho.
21:10justin_smithhttp://martinfowler.com/articles/injection.html
21:11beamsoi like jersey but for some of the injection the resource classes get instantiated over and over again
21:11beamsoi can understand why angularjs has dependency injection but it almost goes too far
21:11SegFaultAXbeamso: That might be OK since they're tiny anyway.
21:15SegFaultAXamalloy: So going back to our previous discussion, you group helper methods inside a helper class, then construct that helper class with an instance of its dependency, is that right?
21:15hyPiRionWhat would you call a set of XML Schemas which defines a "standard"? Some people tends to call it a format, but I'm always confused because I consider XML to be the format, and the schemas to be the interpretation of the data.
21:15SegFaultAXSo User has core methods to user, and UserFoobarHelper has all the methods for doing Foobar-like operations on the User (horrible naming aside)
21:15dsrxangularjs dependency injection is hilarious
21:16dsrxbut it works
21:16amalloythat sounds right, SegFaultAX
21:16dsrx(modulo the build step you need for it to be minification safe)
21:16dsrx(unless you want to hand-annotate everything, blech)
21:16beamsofrom a code zealot point of view, your helper class shouldn't require dependency injection
21:16SegFaultAXamalloy: Would you provide methods on the User to construct instances of the helper classes?
21:16beamsorequiring dependency injection -> service layer
21:17amalloyi don't think so. why should User know anything about all the classes that need a User?
21:17SegFaultAXamalloy: Dunno, more to just reduce typing? I guess it doesn't matter that much.
21:18SegFaultAXIf I used UserFoobarHelper all the time, I wouldn't want to type `new UserFoobarHelper(user)` all over the place if I could avoid it :)
21:18amalloywhat, you'd rather type user.makeFooBarHelper()? what does that achieve?
21:19hyPiRionamalloy: just have the functions directly onto the User class I guess
21:19amalloybut this discussion started with "say you have a User class and it's great, and you want a new class that isn't a User but does things with Users"
21:19SegFaultAXamalloy: I'm just throwing out ideas.
21:19hyPiRionalthough if you need another object for the helper functionality, I'd guess that point is sort of moot
21:20SegFaultAXhyPiRion: The alternative is to make User do everything. Which can be quite a diverse set of concerns given the application. What's a better way to break the logic up?
21:20amalloySegFaultAX: i think if you want an object that uses a User, at some point you have to pass a User in. either at construction time, or perhaps as the first parameter to some static function
21:20hyPiRionI tend to use Clojure, and that seems to work quite well.
21:21hyPiRion(I tend to use Java for perf. reasons only these days)
21:22SegFaultAXhyPiRion: This whole discussion is a moot point in clj, really. At a minimum we have functions and namespaces, and protocols for when we care about types. (This part was discussed earlier)
21:22SegFaultAXSo I can trivially break up my logic into different namespaces.
21:22hyPiRionSegFaultAX: yeah, I know. I just said I used Clojure because I have no idea on how to do it "nicely" in Java, so I fall back to Clojure instead.
21:22SegFaultAXBut in a language like Java, how do I break up all the diverse logic for my User or other <insert central object here>?
21:23SegFaultAXI started this as a philosophical debate, anyway. :D
21:23hyPiRionhehe
21:28SegFaultAXBut I think this question applies equally to languages like Python and Ruby which are still heavily class-based.
21:28beamsobut i have first class functions in both languages
21:29beamsoa util class is attempting to paper over the crack that is no first class functions in java
21:37SegFaultAXbeamso: I'm not sure how that helps in this case.
21:39beamsoa util class is like 'i need to put some code somewhere'
21:39beamsofirst class function -> that code is already somewhere
21:39pdkat least java 8 is going halfway and giving us lambda!!!1
21:40SegFaultAXbeamso: Yes, I know what a util class is. I'm not sure how that helps in the situation we're discussing.
21:40beamsoyou asked about ruby and python
21:40beamsoruby does have first class functions
21:40beamsoi'm pretty sure that python does too
21:41anon_53k8it does
21:41SegFaultAXbeamso: But how do first-class functions ameliorate the problem I described?
21:41beamsoyou don't have to put logic into a class?
21:41beamsoit can live in a first class function just fine
21:42SegFaultAXbeamso: Well the first classness isn't really relevant here then. I could just as easily make a fully static class.
22:08gfredericksruby has 2nd class functions
22:08gfredericksruby aims a shotgun at first class functions and hits all around it
22:24AmandaCHow can I use lein to reference a jar? An API I wish to use isn’t on mavin or clojars
22:29BronsaAmandaC: I never used it but https://github.com/kumarshantanu/lein-localrepo might be what you need
22:29beamsoyou could also install the jar into your local repo using maven
22:29beamsohttp://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
22:30AmandaCHrm, thanks, beamso
22:35FrozenlockIs there a clojure/cljs way to handle internationalization in web apps? I've seen `tower', but this seems to be mostly for clojure.
22:35FrozenlockAt this point I think the best approach would be to use tower in the webserver and loading a single language in an atom on the client side.
22:39noonianyou could also use an existing js library
23:45vimuser21This is more of a general programming question, but lets say you wanted to create a bunch of hashs with key/value pairs, and the key is a unique id. how would you do this in a pure functional manner? seems like you would be mutating a counter which is stateful
23:46beamsois the key sequential or unique?
23:46amalloyvimuser21: reduce and recursion are both typical ways to immutably work with state
23:47vimuser21baemso: either would work =)
23:47amalloyfor example, ##(reduce (fn [m [id x]] (assoc m id x)) {} (map list (range) '(a b c d))))
23:47lazybot⇒ {3 d, 2 c, 1 b, 0 a}
23:48amalloywhich is really just a terrible way of writing (into {} (map-indexed vector '(a b c d))), to demonstrate how reduce can hold state
23:48ivanRaynes: if you are wondering why refheap is full of anonymous forks, it's the crawlers hitting /fork
23:48vimuser21amalloy: hm let me read the example for a second, i had the idea of passing in the last known value into a function so it can generate a new value
23:49ivanGET is a no-no for mutation
23:49beamsoif it was sequential a vector and remembering the offset could suffice
23:49amalloyvimuser21: here, (range) is my standin for an infinite lazy seq of IDs
23:49amalloyivan: hah. he could add a robots.txt too, right? "plz no fork"
23:53vimuser21amalloy: hm, well what about throwing in something like async? i had the idea of basically each id is pre-fixed with a number, and you can do async stuff by pre-pending id's with, for a back of a better term, the current "runner", ie runner "0" woild generate 0-1,0-2,0-3, runner "1" would generate 1-0,1-1, etc.
23:53vimuser21i guess it still fits in though
23:55vimuser21amalloy: to explain the project i'm working on a bit more, it's an auto flowchart program, so you can type s-expressions and it will flow chart it out
23:56vimuser21amalloy: so yeah recursion could work, i just would have to be carrying this counter around which is kind of annoying and whish there was a better way…technically a "generator" would work but thats statefull
23:56vimuser21not sure if i can have my cake and eat it too if you know what i mean =) lol
23:57amalloywell, you can carry around a lazy sequence instead of a counter, which is generally prettier. but you'll still have to manage it by calling first to get a new id, and saving the result of rest to make sure you never see that id again
23:57vimuser21yeah
23:58vimuser21the first time i wrote it i didn't need id's, i bascially did "everything at once", parsing, drawing nodes, and connecting..but that code was sloppy
23:58yuri_niyazovI need some help with doseq and transients. So, I have a fairly complicated doseq statement, with a few nested sequences, :let bindings, and :when filtering
23:58yuri_niyazovinside the body, I want to accumulate some values into a transient
23:59vimuser21was hard to read and wasn't good imo, was mixing side effect code with non side effect stuff