#clojure logs

2015-07-07

02:42tmtwdso, I can write an app in clojure , put it into a jar, and then it can be deployed on any machine with a jvm?
02:42justin_smithtmtwd: yes, "lein uberjar" makes it pretty easy
02:42tmtwdthat is sweet
02:43tmtwdso if I pass someone a jar to run, they needn't even know it was written in clojure?
02:44justin_smithtmtwd: not neccessarily, though it will contain clojure source code :)
02:44tmtwdthats really cool
02:44justin_smithtmtwd: I did have an issue with one client, where we couldn't use clojure any more because they discovered we were using clojure because they were trying to use static analysis tools, and those don't work on clojure.
02:45justin_smiththat's was a weird way to say that
02:45justin_smithanyway, we secretly shipped clojure, and it was fine until they cound't run their SA tool
02:45tmtwdbummer
02:45amalloyjustin_smith: their static analysis tools worked well enough to tell what language was being used. sounds good to me
02:46justin_smithamalloy: heh - they were source level analysis tools :P
02:46justin_smithbut it wasn't until trying to run the tools that they noticed we were shipping .clj
04:19J_A_Workquery about reagent and field focus: https://groups.google.com/forum/#!topic/reagent-project/RNk998XWxtw
04:24joschkaWhat am I doing wrong that I have to evaluate my functions `in the correct order` after I do (cider-jack-in). A simple (cider-eval-buffer) doesn't do it, I always end up with an "Unable to resolve symbol x" error because some later on positioned function wasn't evaluated yet. The functions don't need to be in 'some order' in the file right?
04:24joschkaI feel like such an idiot asking that question :D
04:27joschkaupon starting using (cider-jack-in), (ns-publics) retuns an empty map, shouldn't all functions be evaluated anyway right from the beginning?
05:29pyrhi clojure!
05:30pyris there a generally accepted way of using component when you need an arbitrary number of components for a specific functionality
05:30pyre.g: your app may open one to n "input sinks" which will adhere to a specific protocol, but you can't know in advance how many
05:31pyrdoes component cater to this ?
07:20magnarsjoschka: Clojure is evaluated top-down, so you should define functions before they are used.
08:03joschkamagnars: yes, thank you I already found (declare [&forms]) and all of the logic behind top down evaluation
08:50elvis4526hey, so i tried using H2 to mock a database, but my existing postgresql seem to not works right away with H2 :-()
08:50elvis4526I get this: "org.h2.jdbc.JdbcSQLException: Attempt to define a second primary key; SQL statement:"
08:51elvis4526Is there any specific way I need to handle references to other fields when using H2 compared to postgresql ?
08:53elvis4526uh, I think I just need to quote the identifiers
09:28elvis4526okay i just switched to sqlite instead lol
09:29justin_smithjoschka: yes, in clojure functions need to be defined in order
09:29justin_smithjoschka: amazing, but true
09:29justin_smithsorry, someone already said that
10:19dstockto1new videos seem to have been posted on clojuretv
10:21puredangeryeah, day 2 should be going up today
10:21oddcullywoohoo
10:22dstockto1cool, still waiting for the om next one
10:22puredangernot sure they'll get to all of them today
10:40noogaanyone using manifold? I'm looking for a decent way to model a stream "valve"
10:49Manaphy91I have a big hash map that cause a stack overflow... I use it like an advice for a dynamic programming algorithm... how can I evaluate memory size of a data structure?
10:57TimMcManaphy91: Three things.
10:57expez(ArrayList.) What is the .? I thought this was a reader macro?
10:58TimMcOne, do you mean an out of memory error? I'm not sure how a hash map would cause stack overflow.
10:58TimMcTwo, advice... is this like memoization? Not really important here, just curious.
10:59oddcullyexpez: ctor call
10:59oddcullyexpez: new ArrayList() in javanese
10:59TimMcThree, evaluating the size of a data structure in Clojure in particular and in the JVM in general is actually really difficult. Might be possible, but it basically isn't done.
10:59Manaphy91exactly memoization!!
10:59expezManaphy91: the jvm doesn't have tail call elimination. You're likely using a recursive algorithm without using loop/recur. If you were actually running out of memory you'd get OutOfMemoryError and not StackOverflowError
10:59TimMcOK, cool. :-)
11:02Manaphy91exactly I obtain 'Exception in thread "main" java.lang.StackOverflowError, compiling:(/tmp/form-init8694410201665152526.clj:1:72)`
11:02expezoddcully: yes, but what is the '.'? I thought this was a reader macro, which would be replaced by a constructor call at read time, but the reader returns "(ArrayList.)". I suppose I've answered my own question, and the "." is another token the compiler reads and replaces with a call to the constructor.
11:05expezManaphy91: You need to read about loop/recur. This might be an OK source if you don't have your favorite clojure book at hand: https://blog.8thlight.com/patrick-gombert/2015/03/23/tail-recursion-in-clojure.html
11:06oddcullyexpez: ah sorry, i took that for an less advanced question
11:07Manaphy91expez: I know what are loop and recur... I don't understand why I obtan stackoverflow and I think it is due to extreme memoization....
11:09expezManaphy91: That won't give you a StackOverflow error but a OutOfMemoryError. Allocate more memory to your jvm and you'll get the same result. Allocate a bigger stack and your program might start to run, depending on how deep the recursion is.
11:41justin_smithManaphy91: memoization does not cause StackOverflow
11:41justin_smithManaphy91: manual recursion (self call not using "recur") will
11:41justin_smithManaphy91: recur isn't just for loop, it is for functions too
11:42justin_smith,((fn [x] (if (> x 10) x (recur (+ x 3)))) 4)
11:42clojurebot13
11:44justin_smithManaphy91: oh, I just scrolled up - in order to use a hash map to drive a dynamic programming algo, I would use trampoline
11:44justin_smith(doc trampoline)
11:44clojurebot"([f] [f & args]); trampoline can be used to convert algorithms requiring mutual recursion without stack consumption. Calls f with supplied args, if any. If f returns a fn, calls that fn with no arguments, and continues to repeat, until the return value is not a fn, then returns that non-fn value. Note that if you want to return a fn as a final value, you must wrap it in some data structure and unpack it after trampoline returns."
11:44Manaphy91Yes, you are right!! I'm try to debug it! Any advice about debug in clojure? Usually i do a lein run and simply redirect output!!
11:45justin_smithManaphy91: there's a few options. A simple one is to define an atom (def debug (atom nil)) and somewhere in your code call (reset! debug x), then you can play with that data as captured at that point in your code
11:45justin_smithManaphy91: there's also tools.trace
11:45justin_smithManaphy91: depending on editor preference, there is good debugging support in cursive (intellij idea) and cider
11:48Manaphy91I use vim, sorry but i'm not in emacs church...
11:48Manaphy91I'm seeing tools.trace
11:50justin_smithManaphy91: the atom based things has other variants too like (def debug (atom [])) ... (swap! debug conj {:context ... :values {...}})
11:52Manaphy91justin_smith: thanks!!
11:55justin_smithManaphy91: my experience is that in a repl, if I can capture the values where the problem was happening, I can quickly sort out the answer (by rewriting interactively in the repl until I get the return value I want, or using those values as the basis for a unit test, or rewriting the code the generated those values...)
11:56justin_smithManaphy91: one of the main things I have learned with Clojure is how sane values are. Functions and macros and Objects are so opaque and weird, but values are very straightforward.
11:59justin_smithManaphy91: also, about the stack overflow / hashmap size thing - Clojure won't store a hash-map on the stack as far as I know
12:02amalloyit can't. objects are all on the heap, with only pointers on the stack
12:03justin_smithamalloy: I suspected that, but lacked proof / motivation to research right now :)
12:03amalloythe JIT may be able to move some stuff to the stack via escape analysis or something, i dunno
12:04justin_smithright, but the JIT is not about to "optimize" by blowing the stack
12:49br0tat0chiphi! i just started playing around with clojure and i got a little program working that updates some values in redis. does anyone have a good resource on websockets or how to get that to stream real time to a front end? ive done some research but not sure which is the simplest/straight forward way to go
12:58elvis4526I'm trying to understand clojure hiearchy system. I'm not sure I understand what you can use with (derive) ?
12:58elvis4526can you use something else than ::keyword ?
12:58justin_smithelvis4526: it creates heirarchies that will effect isa? and multimethod dispatch
12:59justin_smithelvis4526: you can use regular :keywords, or namespaced ::keywords, and use those keywords to mark more complex objects like records or maps
12:59justin_smith,::foo ; just a shorthand
12:59clojurebot:sandbox/foo
13:00justin_smithelvis4526: the idea is that it creates an abstract heirarchy, decomposed from any concept of implementation or datatype
13:01justin_smithyou can even create purely functional anonymous local heirarchies (though derive uses the mutable global heirarchy by default)
13:02elvis4526okay but then why something like (derive :user ::record) doesn't work ?
13:03justin_smithelvis4526: oh, right - you do need to use namespaced keywords
13:03justin_smithI forgot
13:03justin_smith,(derive :foo/bar :foo/baz)
13:03clojurebotnil
13:07elvis4526Oh okay - then i guess what I don't understand is namespaced keywords. What's the default namespace of :keyword ?
13:07justin_smithelvis4526: ##(namespace :foo)
13:07lazybot⇒ nil
13:07elvis4526yep that's what I get in a fn
13:07justin_smith,(namespace :foo/bar)
13:07clojurebot"foo"
13:07elvis4526why ?
13:07justin_smith,(namespace ::foo)
13:07clojurebot"sandbox"
13:08justin_smithelvis4526: because :foo has no namespace, ::foo has your current namespace, and :bar/foo has "bar" as a namespace
13:08justin_smithmaybe that doesn't really answer why though
13:53amalloyjustin_smith: since you're listing valid namespace forms: do you remember what the rarely-seen ::foo/bar does?
13:54justin_smithamalloy: expands the alias in the current namespace for foo
13:54justin_smitheg if you had (require '[clojure.string :as s]) ::s/bar would be :clojure.string/bar
13:54justin_smithiirc
13:54Bronsayup
13:54amalloydangit nobody ever remembers that. how am i ever gonna get to be the joker if everyone gets my riddles
13:55justin_smithamalloy: you might be conflating your batman villians
13:59elvis4526okay, I'm trying to imitate the concept of "parent constructor" in an OOP paradigm
13:59elvis4526maybe this will be more clear
14:00elvis4526but I'm really confused with what exactly is the relation with (derive) and the multimethods system
14:00justin_smithelvis4526: there is no relationship of functionality, only a relationship of identity
14:01justin_smithelvis4526: if there is no extension of a multimethod to ::foo, but ::foo is derived from ::bar and the multimethod is extented to ::bar, the method for ::bar will be called
14:01justin_smithif that helps
14:02puredangerit allows you to create an arbitrary hierarchy, that will be used to find method matches as with the Java OO hierarchy
14:03justin_smithyeah, I think that's a better way to put it, thanks
14:06puredangerI believe that there is a section covering multimethod hierarchies in Joy of Clojure, although I don't have the second edition to verify
14:07justin_smithI fleshed out some multimethod / heirarchy examples on http://conj.io too
14:09lvhIs it okay to read resource files in project.clj? I have a few SSL certs/keys for testing (pem files), I need them as strings in env (using weavejester's environ)
14:09lvhThe obvious way to add things to env is through project.clj
14:09justin_smithelvis4526: my examples here http://conj.io/store/v1/org.clojure/clojure/1.7.0-beta3/clj/clojure.core/defmulti/
14:11justin_smithelvis4526: specifically example 4 is all that is relevant here I guess
14:24chomwittwhy (str ["3"]) => "[\"3\"]" ? why do we quote? doublequotes?
14:26lvhCan I use the contents of a file in project.clj? I'd prefer to not have to copy-paste a big blob, but it seems like everything's quoted and I can't actually eval a thing.
14:31oddcullychomwitt: have you meant ,(apply str ["1"]) maybe?
14:32snowelllvh: You can wrap your `defproject` in a `let` and eval things up there to use inside
14:32snowellWhether or not that's a good idea in practice I'll leave up to the experts :)
14:32lvhsnowell: oh, I didn't realize that worked
14:32lvhI guess it makes sense that it would :)
14:44arrdemhyPiRion: can I make lein use a file other than project.clj for the same purpose as project.clj?
14:56chomwittoddcully: nop
14:58amalloyarrdem: `ln -s my-dumb-file.xml project.clj`
15:07arrdemamalloy: I thought not
15:08amalloyarrdem: there was that april fools joke lein-xml
15:08amalloybut it is not really what you want
15:09the-kennywell if lein-xml can read project.xml as xml we can at least represent the xml as sxml :)
15:29{blake}OK, I'm opening a DB connection like (def connection (up-connect)). But I want to put that in a function I can call at startup. Is possible? Or am I missing the boat/convention?
15:29TimMcsomething something component
15:30{blake}something something what? Is that what components are for? (Speaking of boats/conventions missed.)
15:31TimMc{blake}: https://github.com/stuartsierra/component might be appropriate for you
15:31TimMcI've not used it myself, mind.
15:32lodin_Is it recommended to prefix a library's core namespaces with libraryname.core, where the core namespaces would be those that define public protocols, functions using those protocols, etc, and non-core would be data structures that implement the interfaces in the core?
15:32{blake}TimMc: Yeah, I've stared at it more than once. I somehow didn't think of it in this context.
15:32{blake}But I guess that's "Database access: query and insert functions sharing a database connection" right there. :-/
15:34TimMclodin_: "core" is just a default that lein uses because it needs *something* -- you don't want single-segment namespaces.
15:35TimMcAs for the overall pattern (ignoring the actual name), that's not a pattern I've seen, I think. Maybe a good idea, though!
15:35lodin_TimMc: Yeah, I know. I want to distinguish between the necessary parts of the library, and the "batteries included" part.
15:36{blake}Are there local statics?
15:37lodin_TimMc: The alternative would be to just have the core namespace in the library, and have all actual implementations in other libraries, but that doesn't feel quite right. (At it would e.g. make testing harder.)
15:37amalloy{blake}: in...what? clojure? java? some weird library? certainly not in the first two cases
15:37amalloybut it's not 100% clear what you mean by local statics anyway. if you mean like in C, those are just sugar over a global static
15:38jknilodin_: there's mention of that sort of organization using something like an impl namespace in Joy of Clojure 2e p. 199 but you won't really see it a lot at large
15:39{blake}amalloy: In an OO context, I would have a function that referenced a property. Like a DB connection. When you said "myconn := DB connection", the DB class would go look at connection, and return the value if the connection had been made, or make it, then return it, if not.
15:39{blake}Even in a non OO context, I would have a function with a local static that did the same thing.
15:40{blake}But if I say in Clojure (def connection)...and then later try to put something in connection? That's not even a thing, is it?
15:40amalloy{blake}: so, that is kinda dangerous to do carelessly because of multithreading
15:40amalloybut you can easily enough define a delay that you deref every time, or a memoized function that you call or whatever
15:41lodin_TimMc, jkni: I'm going for this then. lib.core.X I mean.
15:41{blake}amalloy: Oh, a memoized function...yeah, that sounds right. That's what I'm trying to do, and I'd just forgotten how.
15:41justin_smith{blake}: an option I have done lately is to use an agent for things like that (agent instead of atom because atoms retry, and I wouldn't really want to retry db connection process)
15:41TimMcamalloy: Oho, C-M-SPC leaves the point where it is. This is better than my approach for copying sexps. :-P
15:42justin_smith{blake}: though if it won't be altered or redefined at runtime, a delay or memoize makes sense, yeah
15:42amalloyTimMc: it even lets you copy *multiple* sexps easily!!1!
15:42TimMcyeah
15:42{blake}justin_smith: I'll check it out. Yeah, I don't want to use delay.
15:43justin_smith{blake}: why not a delay? you would want to alter it later?
15:43{blake}I mean, the larger situation is that I have "(def connection (up-connect user pass))" and that gets called when I making the WAR, which upsets my dev-ops guys.
15:43{blake}er, no "I" there.
15:43justin_smith{blake}: right, and a delay prevents that
15:44justin_smiththough it requires a deref, but so would eg. an agent
15:44justin_smithand a deref vs. needing to call a memoized fn is like, 6 of one half dozen of hte other
15:45{blake}Oh, sorry. I think of delay as "delay(milliseconds)". =P
15:45justin_smith,(def d (delay (println "FORCED!")))
15:45clojurebot#'sandbox/d
15:45justin_smith,d
15:45clojurebot#object[clojure.lang.Delay 0x5d27ad7d {:status :pending, :val nil}]
15:45justin_smith,@d
15:45clojurebotFORCED!\n
15:45justin_smith,d
15:45clojurebot#object[clojure.lang.Delay 0x5d27ad7d {:status :ready, :val nil}]
15:45justin_smith,@d
15:45clojurebotnil
15:46{blake}justin_smith: Groovy. Thanks!
15:46{blake}(inc justin_smith)
15:46lazybot⇒ 271
15:46justin_smithI like delay for things that won't be rebound, it's simpler (weaker) than the other reference types
15:46justin_smithwhich means I can trust it more
15:46{blake}Well, I'm gonna make my own reference type. With blackjack and hookers. In fact, forget the referencing!
15:57amalloyjustin_smith: there was a fun bug in the error-handling for delay in versions earlier than like 1.4 or so
15:57justin_smithoh?
15:58amalloyeg, consider (let [s "whatever", t nil] (delay [(.length s) (.length t)]))
15:59amalloywell, actually, it is better like this: (let [s "whatever"] (delay [(.length s) (/ 1 0)]))
15:59amalloythe first time you dereference that delay, you get an aritmeticexception about divide by zero, as you'd expect
15:59amalloyif you dereference it a second time, you get a null pointer exception on s
16:00TimMchah, right
16:00amalloy(this isn't true anymore, but it was then)
16:00TimMcThis is the :once thing.
16:00amalloyyes
16:01amalloythe macroexpansion of delay promises to call the thunk only once, but if the thunk threw an exception it would actually be called multiple times
16:01Bronsaamalloy: how was it fixed? by caching the exception?
16:01amalloyyes
16:01amalloyyou could also imagine fixing it by throwing a BrokenPromiseException or whatever
16:02{blake}Why would there be a null pointer exception on s the second time?
16:02Bronsa:once can be really tricky
16:02Bronsa{blake}: the local is set to null after it's used
16:03Bronsa{blake}: a memory optimization that clojure uses to avoid blowing up the heap in certain situations
16:03{blake}Right, but--okay, so that's what gets cached, the null.
16:03justin_smithany votes for best kafka wrapper for clojure?
16:03{blake}samsa/core?
16:04{blake}(I'm kidding. Don't go looking for that.)
16:04justin_smith{blake}: if I ever make a kafka wrapper for clojure I will name it starvation-artist
16:05dnolenBronsa: on my work machine ~40ms for clojure.tools.reader to read cljs.core, ~70ms for cljs.tools.reader
16:05TimMcHey, can someone remind me of the common problem people encounter with protocols where they implement the wrong thing? Like, the interface or something?
16:05dnolenI believe my work here is done :D
16:05justin_smithTimMc: like they import the protocol as a class but don't require the ns?
16:06justin_smiththat's common enough an error
16:06amalloyTimMc: implementing the interface is fine. a problem is *using* the interface via (.m x) instead of the protocol function via (m x)
16:06TimMcNo, something that causes Foo != Foo errors.
16:06amalloyTimMc: reloading
16:06justin_smithTimMc: reloading
16:06TimMcamalloy: Hmm, maybe that was it.
16:06{blake}Nice. I think I would make one called "Gatekeeper" that didn't work but just lagged and lagged and lagged, and then finally said "This was assigned only to you".
16:06dnolenBronsa: nearing 2 orders of magnitude speed improvement over master
16:06TimMcI think this one wasn't about reloading.
16:07Bronsa(inc dnolen)
16:07lazybot⇒ 22
16:07Bronsadnolen: can't wait for a patch :)
16:07dnolenBronsa: question is when/how you want it
16:07dnolenit relies on *ns* being present, which requires ClojureScript master
16:07dnolenand resolve-ns, things like that
16:08Bronsadnolen: right. As I said a while ago, we need to release the new t.r at the same time as the new cljs
16:09Bronsadnolen: I'll take the patch whenever it's ready and you tell me when you're ready to release cljs, I'm in no hurry
16:09dnolenBronsa: OK it might be a while then - switching to analyzer/compiler perf work now
16:28expezIs cljs in cljs going to eliminate :refer-macros?
16:29Bronsaexpez: IUC there will be no changes to how ns/macros work
16:43nemelexi'm new to clojure, can anyone tell me why i'm being silly by expecting this to work? ... http://pastebin.com/xKvzLVNa
16:45justin_smithnemelex: where is the entry namespace? why is it referred to but not required?
16:46justin_smithwait, that's probably just a small mistake in simplifying the code
16:46nemelexsorry, i skipped that ns off, but it is there - it's my internal thing
16:46justin_smith"Wrong number of args (0) passed to: PersistentArrayMap" means "too many parens around a hashmap"
16:46justin_smith,({})
16:46clojurebot#error {\n :cause "Wrong number of args (0) passed to: PersistentArrayMap"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: PersistentArrayMap"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [sandbox$eval25 invoke "NO_SOURCE_FILE" 0]\n [cloju...
16:46justin_smithviz
16:47justin_smithyou'd have to look at the code for create to see where that is happening I guess
16:47nemelexah ok, i assumed it was happening when i was passing body to create
16:48nemelexi'll have another look -- thanks
16:57markmmIs there a emacs shortcut to sync the cider repl with a buffer you have changed
16:57markmm?
16:58arrdemmarkmm: with or without saving the buffer?
16:58arrdemmarkmm: C-c C-k will reload a file
16:58markmmarrdem: Ok thanks
16:59arrdemI think C-c C-l will evaluate the buffer whether it's saved or not but I'm not sure
17:04markmmarrdem: Yes it does do that, just tested it thanks
17:29cflemingamalloy: Sorry, I've been offline at a conference. The expiration is only for the beta, once it's stable upgrades will not be required.
19:35whodevilhello, I'm using lein ring uberwar then deploying it to tomcat which is running in debug mode, for some reason when I connect cursive to tomcat, it is not finding the namespaces. Is there something special I have to do to get cursive to pick up the bread crumbs?
19:40whodevilok, I'm dumb, nevermind nothing to see here.
20:00tolstoyWhen using datomic free in-memory, is there a way to remove all the AWS dependencies other than exclude each and every one of them?
20:04arrdemNope. Welcome to raw Maven.
20:04tolstoyOy. ;)
20:05arrdemThat'd actually be an interesting project, define logical groups of dependencies and write a Maven wrapper that can describe exclusions and replacements...
20:05tolstoySeems like of datomic-free doesn't support aws, etc, it ought not to depend on it.
21:20jefelante#/python
21:20jefelanteoops
22:37puredangerarrdem: you can do that in Maven with profiles
23:27gfrederickshas anybody implemented a clojure collection that can keep arbitrary updated aggregations about itself?
23:27gfredericksI think finger trees can do that, but might be too general?
23:28TEttingerupdated aggregations?
23:28TEttingerlike remembering history?
23:28gfredericksno
23:29gfrederickslike a map-reduce for arbitrary functions
23:29gfredericksI want to say just reduce but you wouldn't want it to be order sensitive
23:30gfredericksso the same kind of thing the hipster datastores use
23:30TEttingerI have no idea what you mean
23:30gfredericksword count!
23:30TEttingerdo you mean a storage for transducers or something?
23:30gfredericks[{:sentence "hello there"} {:sentence "some more words"}]
23:30gfredericks^ the collection would have precomputed the word count to be 5
23:30TEttingerahhhhh
23:31gfredericksand as you add/update items in the collection it efficiently updates the word count
23:31amalloyi think such a thing is too general to have an efficient implementation really, aside from one that says "you do all the work yourself"
23:31gfredericksreally? what about the hipster databases?
23:31amalloyyou need some constraints on what the function can do
23:32gfredericksyeah it'd have to be whatchamacallit
23:32gfrederickscommutative
23:32turbofailand associative
23:32gfredericksthe reduce part I mean
23:32gfredericksyeah
23:32gfredericksreducers already has this kind of logic does it not?
23:32amalloyit also has to be invertible, or something like it
23:32gfredericksI don't think so; maybe I didn't explain it well
23:33gfredericksif an item changes you just recompute the function for that item
23:33amalloygfredericks: but then you need some properties for the function "combining" all this stuff at the top level
23:34gfredericksjust the commutative/associative part, right?
23:34amalloyno
23:34gfredericksif you store a tree of values
23:34gfredericksthen you just walk up to the root
23:34gfredericksdoing your log(n) work
23:34ttt_fffare the slides from https://www.youtube.com/watch?v=ByNs9TG30E8& available anywhere? I want to know what om next isa bout without watching 46 minutes of video
23:35amalloygfredericks: that is basically what finger trees do, and the thing you're storing is the measure, as i recall
23:35amalloyif you make the measure be something or other, then finger trees can efficiently concat/split
23:35gfredericksamalloy: yeah I figured finger trees could, I just didn't know off the top of my head if they were so general that you'd have to do manual work to wire it up
23:35amalloybut you can make it be something else and then you can keep a running sum of (f x)
23:39ttt_fffWTF IS OMNEXT about ?