2013-07-29
| 00:26 | sinistersnare | hey, i was just wondering if java8 means anything to the clojure community. mostly just JVM improvements. Like java7 brough invokeDynamic, does java8 bring anything special to the JVM? |
| 00:34 | seangrove | dnolen: Would you be cool if I add in an emit-fn-params method? Right now there's a problem with fn params being repeated in the output js source, and the closure compiler refusing to compile it |
| 00:34 | seangrove | e.g. (defmulti apply-multi-test (fn ([_] 0) ([_ _] 0) ([_ _ _] 0))) |
| 00:35 | bbloom | seangrove: i'm not dnolen, but i can help unblock you should he not reply |
| 00:35 | bbloom | seangrove: make that change in isolation |
| 00:36 | bbloom | create a separate patch for just that bug and/or refactoring. write a good commit message that motivates it |
| 00:36 | bbloom | then dnolen is more likely to be able to understand & accept |
| 00:36 | seangrove | bbloom: and just note that the source-map-columns patch relies on having this emit-fn-param patch? |
| 00:37 | bbloom | yeah |
| 00:37 | bbloom | i only sorta understand what you're saying, but it sounds like it might be a good patch on it's own |
| 00:37 | bbloom | especially if it fixes a bug |
| 00:37 | bbloom | i've had failed larger patches that have yielded a handful of useful fixes / cleanups that dnolen has accepted |
| 00:37 | seangrove | It fixes a problem that I've introduced |
| 00:38 | bbloom | lol well that's slightly different |
| 00:38 | seangrove | Yeah :P |
| 00:38 | bbloom | but still, if it cleans the code up and enables something, you can certainly motivate it |
| 00:38 | seangrove | By having fn params get emitted as vars, the current method of making sure param-names don't get reused in a single fn declaration doesn't work anymore |
| 00:38 | seangrove | Ok, will do |
| 00:38 | seangrove | Sounds reasonable enough anyway |
| 00:39 | seangrove | Makes it easier to reason about |
| 00:39 | bbloom | yup |
| 00:39 | bbloom | this is why i always say: git is more than a version control tool. it's a tool for thinking about software development as an orderly sequence of incremental improvements |
| 00:40 | bbloom | it's a tool for slicing and dicing patches, just as much as vim and emacs are tools for slicing and dicing code |
| 00:40 | bbloom | so slice and dice! |
| 00:40 | seangrove | That's an interesting point |
| 00:49 | dnolen | seangrove: this sort of thing is easier to understand in a source maps design page |
| 00:49 | bbloom | ah, design pages. where implementation progress goes to die :-P |
| 00:50 | dnolen | seangrove: I do understand the basic issue - but I can't offer much about solution approach until I understand what approach you are considering |
| 00:50 | dnolen | bbloom: haha |
| 01:24 | Raynes | rkneufeld: ping |
| 01:25 | sinistersnare | pong! |
| 01:25 | Raynes | o.o |
| 01:26 | Raynes | You can't pong someone else's ping! |
| 01:26 | Raynes | That's just rude. |
| 01:26 | sinistersnare | too bad, i did it |
| 01:26 | xeqi | mitm attack |
| 01:26 | callen | Raynes: hai |
| 01:27 | Raynes | rkneufeld: Anyways, just wanted to say thanks for lein try. I just did `lein try [me.raynes/fs "1.4.5"]` to get a little shell scripting repo. This is amazingly powerful because of aliases. I can make an alias, `lein shell`, and have this awesome whenever I like. |
| 01:27 | callen | Raynes: what does lein try do? |
| 01:27 | Raynes | $google lein-try |
| 01:27 | lazybot | [rkneufeld/lein-try · GitHub] https://github.com/rkneufeld/lein-try |
| 01:28 | Raynes | callen: It's "start up a repl with these dependencies added, please" |
| 01:28 | callen | Raynes: how nifty and compact. |
| 01:28 | callen | that's freakin' sweet. |
| 01:28 | callen | no more dumb placeholder projects. |
| 01:30 | Raynes | callen: It's be cooler if you could give it a bit of code to execute at startup as well. |
| 01:30 | callen | Raynes: repl init code is kinda of a long-running annoyance for me. |
| 01:30 | callen | lein task combinators would contribute to solving that I guess. |
| 01:30 | Raynes | callen: lein try [me.raynes/fs "1.4.5"] '(require \'[me.raynes.fs :as fs])' = winning |
| 01:30 | Raynes | Cause I could alias that and truly have a shell repl waiting for me. |
| 02:14 | egghead | heh, I was playing with websockets and core.async, accidentally made an echo server that sent everything it received back on both ends |
| 02:16 | certainty | moin |
| 02:18 | callen | certainty: moin moin |
| 02:20 | sinistersnare | the fish? |
| 02:22 | mmarczyk | first cut at transients support coming to a cljs rrb tree implementation near you |
| 02:22 | bbloom | mmarczyk: bad ass |
| 02:22 | callen | mmarczyk: nifty. :) |
| 02:23 | mmarczyk | I hasten to add (sheepishly) that that's along with a failing test case |
| 02:23 | mmarczyk | needless to say I fully expect it not to stay failing for long :-P |
| 02:24 | bbloom | mmarczyk: is there a good citation for how transients work? is it in Purely Functional Data Structures ? |
| 02:24 | mmarczyk | bbloom: afaik they're original to Clojure |
| 02:24 | mmarczyk | dnolen: ^ |
| 02:25 | bbloom | mmarczyk: really? rich did it as original research? he's a smart dude, but that doesn't seem like his MO |
| 02:25 | mmarczyk | dnolen: that was supposed to read "^ right?" |
| 02:26 | mmarczyk | bbloom: I've come across two acknowledgements of vectors being his original idea |
| 02:26 | mmarczyk | bbloom: it is based on Phil Bagwell's earlier work, but with substantial new insight |
| 02:26 | mmarczyk | bbloom: also Clojure's persistent HAMT is, well, persistent, which the original HAMT as described in the paper wasn't |
| 02:27 | mmarczyk | bbloom: "Ideal Hash Trees" is all mutable |
| 02:27 | bbloom | heh well ok |
| 02:28 | bbloom | i honestly don't know how to program any more without the set of data structures that clojure provides |
| 02:28 | mmarczyk | bbloom: neither do I |
| 02:28 | bbloom | https://github.com/harukizaemon/hamster <- saved my ass TWICE now on ruby projects for clients :-) |
| 02:28 | bbloom | made me look like a fucking hero when i was able to make things magically work that people couldn't do before, heh |
| 02:28 | tomjack | I've just been trying to make a PHM wrapper for java :( |
| 02:29 | mmarczyk | bbloom: wow, interesting |
| 02:29 | bbloom | mmarczyk: both cases involved speculative operations (ie backtracking) |
| 02:30 | mmarczyk | bbloom: original impl not based on Clojure? |
| 02:30 | bbloom | in one, the client wanted to try a dozen or so different operations and choose maximize the result |
| 02:30 | mmarczyk | bbloom: (hamster, I mean) |
| 02:30 | bbloom | hamster has citations in the readme |
| 02:31 | mmarczyk | bbloom: it cites ideal hash trees, but the way I remember it there's not a word about anything being persistent in tehre |
| 02:31 | mmarczyk | there. |
| 02:31 | mmarczyk | certainly the word isn't used |
| 02:31 | mmarczyk | neither is immutable |
| 02:31 | mmarczyk | anyway |
| 02:32 | bbloom | in the other ruby project where it helped me out, there was some crazy bug that nobody could figure out. i just changed the program to use immutable structures & then changed a loop into an inject (aka reduce) then changed that into a "reductions" then did some analysis over basically partition 2 with a step 1 (ie diffs) and poof isolated the bug |
| 02:32 | mmarczyk | yeah, kind of cool to be able to keep old versions around given this use case :-) |
| 02:32 | mmarczyk | magic ;-) |
| 02:32 | bbloom | same client, both times he was like "bwha!?!?!" and now he's learning clojure, heh |
| 02:33 | mmarczyk | sharing your book of spells then? :-) |
| 02:33 | bbloom | that's what they pay me fore |
| 02:33 | mmarczyk | heh, right |
| 02:34 | bbloom | mmarczyk: ok one other related thing you might know about |
| 02:34 | bbloom | consider dynamic bindings |
| 02:35 | bbloom | oleg describes 3 possible implementations: 1) "deep binding" which is just a stack that provides constant push and linear walk for reads |
| 02:35 | bbloom | 2) "shallow binding" which is basically try/let/set/finally/set-back |
| 02:36 | bbloom | and 3) some name i forget that is basically what clojure does, where you just keep a running set of bindings and merge them each time |
| 02:36 | bbloom | anyway, #1 is linear reads and constant writes |
| 02:36 | bbloom | #2 is constant reads & writes, but not thread safe |
| 02:37 | bbloom | #3 has constant reads & writes, but has bigger issues analyzing the stack of bindings |
| 02:37 | bbloom | so the question is this: |
| 02:37 | bbloom | is there a way to "slice" bindings effectively, just like an rrb vector |
| 02:37 | bbloom | but that gives you a "map" view of such a slice that has log lookups |
| 02:38 | bbloom | basically, i want the "newest" binding all the time on read, but want log lookup instead of linear |
| 02:38 | bbloom | and i want to slice and concat the stack of bindings efficiently too |
| 02:38 | bbloom | mmarczyk: does that make sense? |
| 02:39 | mmarczyk | bbloom: do you have the Oleg link on hand? |
| 02:39 | bbloom | http://okmij.org/ftp/Computation/dynamic-binding.html#DDBinding |
| 02:39 | bbloom | DDBinding.pdf |
| 02:39 | mmarczyk | oh ok, that's what I'm looking at |
| 02:40 | bbloom | i'm building a CESK-style interpreter, but i want to support delimited continuations |
| 02:40 | bbloom | right now, i just do the standard linear search and recurisve linked list copy/concat/whatever, but i was hoping for something better |
| 02:42 | mmarczyk | well, this is interesting |
| 02:42 | mmarczyk | I'll need to think about this, but it does make sense |
| 02:43 | bbloom | the real issue is that reads from deep dynamic vars will involve walking the entire stack |
| 02:43 | bbloom | so like if you have a deep recursive function that is 1000 levels deep and you want to look up the hostname or something practically global, you need to walk 1000 levels up |
| 02:43 | bbloom | which probably isn't too bad, but would be terrible in an inner loop |
| 02:44 | bbloom | granted, tail call elimination could dramatically shallow (verb) the stack, so it might be OK in practice |
| 02:44 | bbloom | i'm just curious |
| 02:46 | bbloom | btw, it's section 7 of that pdf |
| 02:46 | mmarczyk | yeah, just read that |
| 02:47 | mmarczyk | so in deep binding something like (binding [*foo* bar] ...) installs a new frame at the front of a list |
| 02:47 | bbloom | yeah, basically a parent pointer in each continuation |
| 02:48 | bbloom | (defrecord Machine [continuation control environment store]) |
| 02:48 | bbloom | (defrecord Continuation [value environment control continuation]) |
| 02:48 | bbloom | that's what i have in my notes |
| 02:48 | tomjack | maybe in each node keep a map from key to highest index containing an entry with that key? then concat is an extra O(n) in the number of distinct keys per node (hopefully effectively constant)? and slice...? |
| 02:50 | tomjack | what's the problem with option 3? |
| 02:50 | bbloom | so the idea in that delimited bindings pdf is that when you capture a delimited continuation, you only capture the dynamic bindings within that continuation |
| 02:50 | bbloom | the problem with #3 is that it is undelimited |
| 02:50 | bbloom | the example in the paper that made the most sense to me was "mobile code" |
| 02:51 | mmarczyk | how about a map of var -> list of values |
| 02:51 | bbloom | say you have a continuation based web server & it pauses execution and then another request comes in on a different box and the continuation is saved in memcache or something |
| 02:51 | mmarczyk | if empty, use global value |
| 02:51 | mmarczyk | (empty list = unbound var) |
| 02:51 | bbloom | so when the continuation resumes on a different machine, you want to keep any dynamic bindings in the processesing of the request, like *user-time-zone* but replace the *host-name* binding |
| 02:51 | bbloom | tomjack: make sense? |
| 02:52 | tomjack | somewhat |
| 02:52 | bbloom | mmarczyk: that's what clojure does. see what i just said to tomjack |
| 02:52 | mmarczyk | right |
| 02:52 | tomjack | I don't think I've ever understood delimited continuations, but I think I sorta get it |
| 02:53 | tomjack | in my idea above you do one PHM lookup on the root, then an RRB lookup :/ |
| 02:53 | bbloom | (binding [*host-name* …] (process-request (fn [request] (binding [*user-time-zone* …] …)))) |
| 02:53 | bbloom | tomjack: assume that the function passed to process-request can be paused and resumed later on a different web server |
| 02:54 | tomjack | I've been kind of curious before about attaching finger-tree like metadata on RRB nodes |
| 02:55 | tomjack | in this case basically an index over vars? |
| 02:55 | bbloom | yeah, but your index is invalidated when you splice the stack |
| 02:55 | mmarczyk | bbloom: wait, so does Clojure keep a list of map-like binding frames |
| 02:55 | mmarczyk | bbloom: or a map of lists |
| 02:55 | bbloom | i can conceive of sensible caching approach to the "deep binding" strategy, but i can't conceive of a persistent structure that is inherently efficient |
| 02:55 | tomjack | sure, you're going to have to rebuild the indices of all the new nodes? |
| 02:56 | bbloom | mmarczyk: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java |
| 02:56 | bbloom | see pushTheadBindings |
| 02:56 | mmarczyk | yeah, looking at this :-) |
| 02:57 | bbloom | each frame has a parent frame pointer and a bindings map |
| 02:57 | bbloom | the for loop basically does merge |
| 02:57 | bbloom | that's the "acquaintance vector" strategy #3 in the literature |
| 02:58 | mmarczyk | bbloom: ok, got that |
| 02:58 | mmarczyk | bbloom: and you want to be able to throw away bindings installed before a marker |
| 02:58 | bbloom | tomjack: i'm trying to figure out a way to do it w/o having to cache b/c the cache will be invalidated A LOT if you make use of control structures for normal code (like if you wanted to implement core.logic in terms of continuations) |
| 02:58 | bbloom | mmarczyk: right |
| 02:59 | tomjack | cache? var -> rrb index ? |
| 03:00 | tomjack | are there reasonable cases where the set of distinct vars isn't effectively O(1) |
| 03:00 | bbloom | tomjack: but you need to splice the indexes (slice and concat) |
| 03:00 | mmarczyk | and you'd like to be able to serialize the delimited continuation with the pre-marker stuff left out, I suppose? |
| 03:00 | bbloom | tomjack: you need to find A PARTICULAR key |
| 03:00 | tomjack | if that were the case, it would seem that the overhead of the measures would be some constant factor over a bare RRB |
| 03:00 | bbloom | it's a sorted multi-map |
| 03:00 | mmarczyk | actually, more importantly |
| 03:01 | mmarczyk | would you be ok with early bindings hanging around until the whole thing is serialized? |
| 03:01 | bbloom | mmarczyk: serialization is a whole nother thing, just illustrates one use case |
| 03:01 | mmarczyk | in that case you could use an index-based approach to cutting off early bindings and then during serialization actually use it to prune stuff |
| 03:01 | bbloom | mmarczyk: would be better if the continuations were correctly pruned, such that no garbage was unintentionally retained |
| 03:02 | tomjack | I don't understand your point about cache invalidation |
| 03:03 | bbloom | tomjack: i'm trying to find a solution w/o any mutable caches b/c slicing and concatenating stack subsequences is extremely common |
| 03:03 | bbloom | so the caches would likely never have time to get warm |
| 03:03 | tomjack | hmm.. mutable cache? |
| 03:04 | tomjack | I was suggesting putting a normal PHM in each node |
| 03:04 | bbloom | that won't work b/c you need to capture only a SUBSET of the bindings |
| 03:04 | bbloom | and that subset is specified by where you splice the stack |
| 03:05 | tomjack | yeah, when you splice the RRB, you need to recompute the measures up to the new root. is that what you mean by "mutable"? |
| 03:05 | bbloom | by mutable i meant like a memo atom cache |
| 03:05 | bbloom | i guess in theory you could keep a PHM per frame and recompute that PHM during slicing |
| 03:06 | bbloom | so what you're saying about a small number of dynamic vars means that it's "effectively constant" |
| 03:06 | bbloom | slicing and concatenating would still be linear, but with a higher constant for merging vars as you go |
| 03:06 | bbloom | and then you'd get log(vars) lookup |
| 03:07 | bbloom | instead of linear(stack) |
| 03:07 | tomjack | hmm |
| 03:07 | bbloom | not sure that would pay off tho |
| 03:07 | tomjack | RRB should give you log everywhere, no? |
| 03:07 | bbloom | the issue is that there is a "filter" for a particular stack frame that you're gonna splice at |
| 03:08 | bbloom | you don't splice at "position 5" or at "key > 123" |
| 03:08 | bbloom | or rather on lookup i mean |
| 03:09 | bbloom | hmmm… thinking... |
| 03:09 | egghead | https://gist.github.com/eggsby/6102537 :) borrowed some of dnolens code to implement a websocket as a cljs core.async chan |
| 03:09 | tomjack | I'm imagining that whatever is pushing/popping bindings will know the indices at which to splice (i.e. it will keep track of the stack depth) |
| 03:09 | bbloom | tomjack: nah, it can't. there needs to be a level of indirection for the "name" of the place to splice |
| 03:10 | bbloom | tomjack: b/c it can hold on to that name and a variety of changes can happen to the stack in between |
| 03:10 | bbloom | i'm a little too tired to be thinking about this now tho |
| 03:10 | mmarczyk | very cool problem |
| 03:10 | tomjack | hmm, so I've just been thinking of an RRB vector of MapEntry, but there needs to be some extra markers that say "a frame named XYZ starts here" or something? |
| 03:11 | bbloom | soooo i'm gonna go to sleep. mmarczyk is gonna continue being awesome w/ rrb. and you can read oleg & try to make sense of delimited continuations :-) |
| 03:11 | bbloom | tomjack: yeah something like that |
| 03:11 | bbloom | you need to lookup "most recent stack frame labeled X" |
| 03:11 | bbloom | and then slice there |
| 03:11 | mmarczyk | now I'll be thinking about the perfect data structure for this |
| 03:11 | bbloom | and then concat it back somewhere else |
| 03:13 | mmarczyk | bbloom: does reinstating the continuation automatically install the marker? |
| 03:13 | mmarczyk | at point of splicing |
| 03:14 | bbloom | mmarczyk: there are a variety of operators that do a bunch of subtly different things |
| 03:14 | bbloom | shift/reset has kinda "won" |
| 03:14 | bbloom | but there are also named prompts + capture/restore which has won in practice |
| 03:14 | bbloom | i still don't understant the precise details |
| 03:14 | bbloom | it's all in the mountain of stuff on oleg's site :-P |
| 03:15 | mmarczyk | in practice? who implements that? |
| 03:16 | bbloom | heh. well racket has a variety of operators w/ a hacky patched up pile of craziness at the bottom on top of ye old call/cc of yore |
| 03:16 | bbloom | then oleg et al have done delimc libraries for ocaml, some scheme, and haskell |
| 03:17 | bbloom | in ocaml via hacking with the byte code machine, in scheme via a call/cc+state hack, and in haskell as translation to a monad :-P |
| 03:18 | sontek | So are people still using noir for web development or has eveyrone switched to using ring and rolling their own? |
| 03:19 | mmarczyk | bbloom: thinking about this gives me this euphoric feeling... :-) |
| 03:20 | bbloom | mmarczyk: heh |
| 03:20 | mmarczyk | nothing like a story of a fabulous hack in the morning :-) |
| 03:20 | bbloom | mmarczyk: in theory tho, it's actually a pretty "simple" set of semantics |
| 03:20 | bbloom | reading the math is hard for a simpleton like me |
| 03:20 | bbloom | but i'm almost there |
| 03:22 | mmarczyk | bbloom: have you looked into http://www.cs.indiana.edu/~dyb/pubs/monadicDC.pdf ? |
| 03:22 | bbloom | not yet, but it's on my queue |
| 03:23 | mmarczyk | mostly asking because I've been wondering if there's a usable implementation |
| 03:23 | bbloom | in my experience, monads are about types and types alone |
| 03:24 | bbloom | i'm a believe in optional/pluggable type systems & so i feel that you need to understand the dynamic primitives before you can talk about the types |
| 03:24 | bbloom | moands seems like cart before the horse to me in haskell land |
| 03:25 | bbloom | i'm a big believer in "strategy" systems |
| 03:26 | bbloom | ie systems that let you combine operations by adding & removing groups of sub operations, such that you can tune the system to the problem at hand |
| 03:26 | bbloom | but i'm getting really abstract now & certainly making ZERO sense |
| 03:26 | bbloom | so i'm going to bed |
| 03:26 | bbloom | cya guys |
| 03:26 | mmarczyk | good night |
| 03:26 | noonian | night |
| 03:26 | mmarczyk | disagree about zero sense, but we can continue next time ;-) |
| 04:35 | llasram | It is that time of the day |
| 04:35 | ddellacosta | yep. heh. |
| 04:39 | hyPiRion | too early for Europeans on vacation, too late for Americans |
| 04:39 | Raynes | callen: ping perchance |
| 04:40 | Raynes | callen: http://erlang.org/pipermail/erlang-questions/2013-July/074906.html I |
| 04:41 | Raynes | I'm currently being told that being able to send EOF to an external process's stdin and then read data over EOF is a bad thing you should never do and that's why you can't do it in Erlang. This is a feature of every single modern programming language in existence. I give up. Seriously, man. I'm beyond cynical at this point. |
| 04:41 | Raynes | I'm at blown away level throw-shit-out-the-window. |
| 04:42 | hyPiRion | Raynes: and we all love unicode too! |
| 04:43 | hyPiRion | But yeah man, IO is really hard. Even the JVM has serious design flaws there |
| 04:44 | hyPiRion | IO, character sets and dates are like the bane of most programs. |
| 04:45 | xybre | Whats wrong with sockets? |
| 04:45 | xybre | That seems like the best tool for the job. |
| 04:46 | Raynes | xybre: Sure, go hack in socket support for all the fundamental unix programs which rely on you being able to read data from them after you've sent them EOF. |
| 04:46 | xybre | Which are you using? |
| 04:47 | Raynes | What difference does it make? |
| 04:47 | Raynes | All of them. |
| 04:47 | Raynes | This is a problem with Erlang. |
| 04:49 | llasram | Maybe it's a communication issue. I mean, there isn't a libc function to do what you're describing. Instead you pipe, fork, dup2, exec, right? Maybe can do same thing in Erlang? |
| 04:49 | xybre | It makes a lot of difference. |
| 04:50 | Raynes | llasram: I think it is a communication issue. If not, then I'm entirely blown away. |
| 04:50 | xybre | Especially in Unix, a lot of commands are just wrappers around kernel functions. So often you should invoke them yourself instead of shelling out. Unless you're writing Bash scripts. |
| 04:51 | Raynes | There are other programs, for example pygmentize, that waits for EOF as well. |
| 04:52 | xybre | I'm guessing Erlang wasn't designed for scripting. |
| 04:52 | Raynes | Don't think Java was either. |
| 04:53 | xybre | Java tries to do everything, its a mass of feature creep. |
| 04:55 | xybre | Like perl. If perl had multimilion dollar companies backing its development. |
| 05:02 | Raynes | xybre: Name a language where you can't do this. |
| 05:06 | xybre | Befunge. |
| 05:07 | Raynes | lol |
| 05:07 | xybre | You can't do it in C unless you do it by hand, it looks like you just have to do it by hand in Erlang too. |
| 05:08 | Raynes | You can't do it by hand in Erlang. |
| 05:08 | Raynes | You can write C code to do it and then try to talk to that C code in Erlang. |
| 05:08 | Raynes | This should be abstracted. |
| 05:08 | Raynes | Ports are already an abstraction for reading and writing, the missing piece is just telling it that you're done writing. |
| 05:09 | Raynes | I think Richard misunderstood me, because it doesn't seem to make a lot of sense. |
| 05:09 | xybre | Providing detailed use cases tends to help visualize solutions. Perhaps an example could better explain to him. |
| 05:09 | Raynes | I sent an example a few minutes ago. |
| 05:10 | Raynes | Hopefully that clear things up. |
| 05:10 | xybre | Hopefully! |
| 05:11 | Raynes | I'm just frustrated, because ROK is a bit of a God in the Erlang community, and if he dismisses this because he misunderstands me or something then it's likely going to get buried. I've got a pal who knows Joe Armstrong and says he'll bring it up with him and get his opinion on it in any case, so I can stop caring so much about responses on the mailing list I suppose. |
| 05:11 | Raynes | Joe Armstrong is kinda the last stop down the "will this happen" line. |
| 05:12 | xybre | Some people have off days too, things get overlooked, sometimes pride or shortsightedness gets the best of us. If there's not a solution right now, there likely will be in the near future. |
| 06:06 | jonasen | bbloom: fipp (mostly) ported to cljs: https://github.com/jonase/fipp/compare/cljs |
| 06:07 | dotemacs | hello |
| 06:08 | dotemacs | Just stumbled upon this exchange on Twitter: https://twitter.com/artagnon/status/361784625716133889 Troll? |
| 06:10 | hyPiRion | dotemacs: Just tells you that the core doesn't have a need for many changes, and that those changes are considered thoroughly |
| 06:11 | hyPiRion | See e.g. core.async, which isn't built into the Clojure repo, but is nevertheless a "core" feature in some sense |
| 06:11 | hyPiRion | That being said, yeah, bug additions to core happens slowly. |
| 06:12 | hyPiRion | bug fixes I mean |
| 06:12 | jonasen | hyPiRion: but bug *additions* happens slowly too :) |
| 06:12 | hyPiRion | jonasen: yeah, true that :) |
| 06:14 | learner_ | Hi, I am trying to understand a puzzle solution listed @ https://gist.github.com/swannodette/5127150 . But I am not able to figure out where "clojure.logic.set" reference is coming from. Any idea which library this namespace is part of? Thanks for your help in advance |
| 06:15 | dotemacs | hyPiRion: thanks for the reply :) |
| 06:37 | noncom | hi! is there any good example of building a TCP client with Aleph? |
| 06:38 | noncom | the one at the official github page is not well-described |
| 06:50 | opqdonut | weird: proxy works when in a file, but not in the repl (user namespace) |
| 06:50 | opqdonut | NPE in clojure.core$name |
| 06:55 | arcatan | o hai opqdonut |
| 06:55 | opqdonut | cheerio |
| 06:57 | arcatan | certainly this works in repl: (def foo (proxy [Closeable] [] (close [] (prn "foo")))) (.close foo) |
| 06:58 | opqdonut | that's almost exactly what I did: (def p (proxy [java.io.Closeable] [] (close [this] (prn :CLOSE)))) |
| 06:58 | opqdonut | oh, right, the this is bogus. well it fails even without it: (def p (proxy [java.io.Closeable] [] (close [] (prn :CLOSE)))) |
| 06:59 | arcatan | opqdonut: when i copy-pasted that to repl, there was a weird space characters. once i removed them, the NPE went away |
| 07:00 | opqdonut | hah |
| 07:00 | opqdonut | yep, that was it |
| 07:00 | opqdonut | seems like my xmodmap has rotted |
| 07:04 | learner_ | learner_: Answering my own question. There is no namespace called "clojure.core.logic.set". But that is something "swannodette" hoping to have. Ref: http://swannodette.github.io/2013/03/09/logic-programming-is-underrated/ |
| 07:06 | snake-john | I am wondering why the reader macro #' for (var symbol) was introduced. even in clojure.core I see it only used 6 times. is it really used that heavily in clojure programming? |
| 07:07 | learner_ | ,(println "test") |
| 07:07 | clojurebot | test\n |
| 07:08 | arcatan | snake-john: i use it quite often to refer private variables from repl |
| 07:10 | snake-john | arcatan: so it is more used when you are interactively checking your code. i see. thanks |
| 07:10 | hyPiRion | or if you alter the var itself |
| 07:11 | opqdonut | I'm not sure it needs to be a reader macro, it could be a normal macro (/ special form) |
| 07:12 | hyPiRion | Sure, but what are the downsides of having it as a reader macro? |
| 07:12 | opqdonut | I for one would prefer (deref (var foo.bar/quux)) to @#'foo.bar/quux |
| 07:12 | opqdonut | :) |
| 07:34 | noncom | is anyone here well-aware of Aleph? |
| 07:52 | learner_ | How to exclude certain functions from clojure.core package when on REPL ? |
| 07:57 | snake-john | maybe (ns your-name-space (:refer-clojure :exclude [+])) |
| 07:57 | kmicu | $google clojure exclude |
| 07:57 | lazybot | [ClojureDocs - clojure.core/refer-clojure] http://clojuredocs.org/clojure_core/1.2.0/clojure.core/refer-clojure |
| 08:05 | schmir | is there a way to require some packages without polluting the current namespace? i.e. I like to load a package but I don't need a name for it |
| 08:05 | schmir | :refer with an empty list probably |
| 08:06 | hyPiRion | schmir: you don't need to refer at all |
| 08:06 | hyPiRion | ,(require '[clojure.string]) |
| 08:06 | clojurebot | nil |
| 08:06 | hyPiRion | ,(clojure.string/join ", " ["A" "B" "C"]) |
| 08:06 | clojurebot | "A, B, C" |
| 08:07 | schmir | hyPiRion: but that put's clojure.string in the current namespace |
| 08:08 | hyPiRion | schmir: hm, but why would you load the package in the first place then? |
| 08:08 | hyPiRion | side effects? |
| 08:09 | schmir | (require ... :refer ()) does what I want |
| 08:09 | schmir | hyPiRion: I'm registering a function in another module |
| 08:10 | schmir | hyPiRion: should probably load the code dynamically...somehow.. |
| 08:10 | schmir | hyPiRion: yes, side effects |
| 08:12 | arcatan | doesn't even (require '[foo :refer ()]) add foo to the current namespace? |
| 08:13 | schmir | arcatan: yes, it does..damn |
| 08:20 | bja | nvm, ritz takes a port |
| 08:25 | learner_ | snake-john: Thanks for your answer about excluding certain functions from clojure.core when on REPL. It works! |
| 08:26 | hyPiRion | schmir: to be fair, I wouldn't worry too much about that |
| 08:26 | learner_ | kmicu: Yes, the first thing I do is googling before I trouble anybody on IRC. But I couldn't understand how to do on REPL. snake-john: helpmed me. Thanks |
| 08:26 | hyPiRion | unless you'd explicitly want to load it AND keep it out, it's not that dangerous if it's possible to refer to it from the current ns |
| 08:27 | schmir | hyPiRion: yes, probably doesn't matter |
| 09:05 | fmw | hello, I'm having an issue when trying to use a checkouts directory in my Leiningen 2.2 project directory. When I run lein classpath, the classpath seems fine, but when I compile I'm getting a FileNotFoundException |
| 09:06 | ro_st | have you lein install ed the checkout-ed project? |
| 09:07 | fmw | ro_st: no, that might be the proble, |
| 09:07 | ro_st | that catches me every time :-) |
| 09:07 | Anderkent | eh, why do you need to lein install it? |
| 09:07 | ro_st | to put the .pom into your .m2 |
| 09:09 | Anderkent | Hm, I can see how you'd need that to package your stuff, but needing to do it to get a compile going is strange |
| 09:10 | ro_st | checkouts leverage the deps system, and the deps system is built on top of maven, and maven needs it to be in your local repository before it can continue |
| 09:10 | jonasen | ro_st: I think the point of checkouts is to *not* have to "lein install" on every change |
| 09:11 | fmw | ro_st: yes, that fixes it |
| 09:11 | ro_st | you don't have to do it on every change |
| 09:11 | ro_st | just the first time, so that there's a stub in place |
| 09:11 | Anderkent | I'm also surprised that was a file not found exception rather than something sonatype related |
| 09:11 | Anderkent | ro_st: actually if it works as you say it does, you have to install after every dependency change in the checkouts project |
| 09:12 | jonasen | https://github.com/technomancy/leiningen/blob/master/doc/TUTORIAL.md#checkout-dependencies |
| 09:12 | Anderkent | I can see how that's the simplest implementation for lein, I guess |
| 09:12 | jonasen | first sentence |
| 09:12 | fmw | Anderkent: that was because I removed the dependency from my project.clj |
| 09:12 | ro_st | Anderkent: what jonasen just said :-) |
| 09:12 | Anderkent | ro_st: jonasen: huh? It's not the first sentence (it's the third) |
| 09:13 | ro_st | pedant! |
| 09:13 | Anderkent | first one is about not having to install, so I think that was adressed to you :) |
| 09:13 | fmw | a follow-up question: I currently need to have all the dependencies of the project I'm checking out in the project.clj of the current project as well |
| 09:13 | Anderkent | (third of the second paragraph, at that! :P) |
| 09:13 | ro_st | -waves hands in the air- whatevs :P |
| 09:13 | Anderkent | fmw: that shouldnt be necessary |
| 09:13 | fmw | why is it not picking up the dependencies of the checked out project automatically? |
| 09:13 | ro_st | it is, unfortunately. |
| 09:14 | Anderkent | huh! |
| 09:14 | ro_st | despite that annoyance, it's still too useful to not use |
| 09:14 | ro_st | nice article, stuartsierra. it's another arrow in the quiver |
| 09:14 | fmw | thanks for your help :) |
| 09:14 | Anderkent | how come it doesnt recognize them while fetching the checked-out project from m2? |
| 09:14 | stuartsierra | ro_st: Thanks. |
| 09:15 | ro_st | Anderkent[away: it runs the code in checkouts as though it were in src |
| 09:15 | maleghast | stuartsierra: what article..? |
| 09:15 | ro_st | i don't know. i'm a user of this stuff. i haven't read the code |
| 09:15 | maleghast | (I'd like to read it) |
| 09:15 | ro_st | http://stuartsierra.com/2013/07/28/the-amateur-problem |
| 09:16 | supersym | can someone give me a use-case for :inline / definline? I must not be getting 'it' :) |
| 09:17 | supersym | ro_st: which article? |
| 09:17 | ro_st | ^^ link |
| 09:17 | supersym | oh |
| 09:17 | supersym | :S |
| 09:17 | supersym | lol nvm then |
| 09:18 | tgoossens | is there a function that does (reduce f (map g col)) already in the core libs? |
| 09:18 | maleghast | stuartsierra: Yep, ro_st is quite right, nice article - thanks. |
| 09:19 | stuartsierra | maleghast: Thanks. |
| 09:22 | supersym | frameworks can be highly dynamic, with a pluggable architecture and can allow for RAD... one may argue RAD doesn't belong in corporate software environments and might just facilitate the 'amateurs' but tbh, I would have never learned half the technologies/languages I know today without on occassion the jumping board of a framework to introduce entirely new concepts |
| 09:22 | supersym | I think here we talk about rather static frameworks though, as a one size fits all solution? |
| 09:23 | stuartsierra | I don't say frameworks are ALWAYS bad. Just mostly. :) |
| 09:26 | hyPiRion | I feel that many frameworks complect stuff. It's usually rather hard to switch some components of the framework. |
| 09:27 | hyPiRion | At least those frameworks I've worked with. |
| 09:28 | supersym | oh definitly... the thing is everything takes a learning curve, and it takes interest, pashion, desire for knowledge to dive in. Stuart is completely right on the whole 'dead simple' thing being a things that just obfuscates complexity |
| 09:28 | supersym | but for me, everything in clojure is dead-easy compared to say: JS |
| 09:29 | supersym | hand-crafting compiled/optimized stuff was just too much of a pain,... most advanced 'frameworks' in clojure solve problems I will probably never have to tackle :D |
| 09:30 | supersym | as long as people are aware it should be fine though, and if someone would only pay me $300 for a web site, I'd gladly use a framework for 1 hour job :P |
| 09:31 | ro_st | clojure's concision does lend itself to composing things as needed rather than importing framework.*. we use ring, compojure, hiccup for our website. don't need anything else |
| 09:31 | supersym | "these days of rapidly-changing technological capabilities" and maybe because you guys are in the US, but people (especially the web community) is slow to catch up |
| 09:32 | supersym | here anyway... people still use PHP for petes sake |
| 09:32 | ro_st | 'here' ? |
| 09:32 | supersym | ro_st: right... just like when I switched from Windows -> Linux, I found I didn't need much of those old things, as I thought I did |
| 09:33 | supersym | thats why I like Arch probably |
| 09:33 | supersym | Netherlands... but I guess more places |
| 09:33 | supersym | I'd be surprised if we had more than 200 people of 16mil. that would actively use Clojure >< |
| 09:34 | ro_st | i'm in South Africa |
| 09:34 | edw | supersym: In so many areas of my life, I've found that's true: we worry that we need all sorts of things to be happy/successful and so we never clear everything off and start over, but the reality is that we don't need a whole lot. |
| 09:34 | ro_st | i'm doing my damndest to jam Clojure in any place i can get it |
| 09:38 | ro_st | edw: that's why getting rid of junk is so liberating :-) |
| 09:39 | supersym | wholeheartedly agree |
| 09:39 | edw | ro_st: I know! But then that just creates more room for books, and each apartment move becomes more painful! |
| 09:40 | hyPiRion | The trick is to learn concepts, not languages, frameworks or libraries. |
| 09:40 | ro_st | edw: -grin- books are special |
| 09:40 | supersym | so in principle I agree with the post, it gives food for thought, but on the other hand, I've seen crappy professional IT folks and extremely proficient 'end-users' |
| 09:41 | ro_st | hyPiRion nails it, basically |
| 09:41 | supersym | hyPiRion: probably true yes, Clojure opened up a whole can of math/philosophy/CS subjects I would have never else touched, but are *highly* rewarding |
| 09:42 | ro_st | concepts win. i use Clojure because it values the concepts/principles that it does |
| 09:43 | ro_st | and it makes them easy to employ. yes, easy -grin= |
| 09:43 | supersym | those are all expressions, the results of concepts, ideas, scientific discovery.. so reading the source can learn you a lot or provide hints of the underlying principles applied in other peoples work |
| 09:45 | supersym | ro_st: agreed... and rich hickey makes a very compelling case imho |
| 09:46 | supersym | so how much amateur is someone who realized that and ended up with clojure? I'd probably judge them as seasoned professionals :) |
| 09:46 | supersym | although in reality of course, if they dont do it for a living, they are not |
| 09:47 | ro_st | i'm a professional-not-using-OOP-any-more-er |
| 09:48 | ro_st | but an amateur Clojurist |
| 09:48 | ro_st | happy to say i've not attempted to build a framework though :-) |
| 09:50 | supersym | hehe yeah.. my point is this perhaps, how much framework is a tiny core that allows for easy extension? |
| 09:51 | ro_st | the problem is the framework assumes that it knows the entire problem phasespace |
| 09:51 | supersym | it wouldn't constitute a framework until someone deliberately names it that was... and has gathered an ecosphere of plugins/extensions around itself, and targets a specific problem? |
| 09:51 | supersym | right |
| 09:51 | ro_st | the best framework in Clojure so far, is Clojure itself |
| 09:51 | supersym | :) |
| 09:54 | mmarczyk | stuartsierra: could we turn off jdk 1.5 tests for core.rrb-vector for now? (pulls in reducers unconditionally; I suppose this could change in the future) pinging you since I'm not sure if I'm supposed to just tweak build.ci myself |
| 09:57 | stuartsierra | mmarczyk: Go ahead and change it in build.ci, then ping me to rebuild the Hudson configs. |
| 09:57 | mmarczyk | stuartsierra: ok, thanks |
| 10:00 | mmarczyk | stuartsierra: done |
| 10:01 | stuartsierra | mmarczyk: reloading Hudson... |
| 10:02 | mmarczyk | stuartsierra: cool, thanks! |
| 10:27 | noncom | when i load all files into a repl, *ns* in each file is not bound to the ns of that file. instead, it is bound to user ns or clojure.core.... How do I, when evaling a whole namespace, get the symbol or string of the name of that namespace? |
| 10:28 | noncom | like (ns my-ns) (defn that-ns [] ...) where (that-ns) returns 'my-ns or "my-ns" |
| 10:29 | Bronsa | noncom: (let [curr-ns *ns*] (defn that-ns [] curr-ns)) should do it |
| 10:33 | mmarczyk | stuartsierra: hm, somehow Hudson still seems to run the jdk 1.5 tests |
| 10:33 | stuartsierra | yeah, I saw that |
| 10:34 | stuartsierra | oh, 'cause I'm dumb |
| 10:34 | stuartsierra | Forgot to rebuild the configs before restarting Hudson. |
| 10:34 | mmarczyk | :-) |
| 10:35 | stuartsierra | mmarczyk: OK, restarting again with new configs. |
| 10:36 | mmarczyk | stuartsierra: thanks! |
| 11:07 | learner_ | Newbie question here, any idea why this call fails |
| 11:07 | learner_ | (let [rands (partition 4 (repeatedly 20 #(rand-int 100))) _ (println (map vector [:age :name :pos :cos] rands)) ] (map #(into {} %) (map vector [:age :name :pos :cos] rands))) |
| 11:07 | learner_ | ,(let [rands (partition 4 (repeatedly 20 #(rand-int 100))) _ (println (map vector [:age :name :pos :cos] rands)) ] (map #(into {} %) (map vector [:age :name :pos :cos] rands))) |
| 11:07 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Keyword> |
| 11:10 | seangrove | Bronsa: Out of curiosity, why are lines in tools.reader 1-indexed? |
| 11:10 | hyPiRion | ,(let [rands (partition 4 (repeatedly 20 #(rand-int 100)))] (into {} (map vector [:age :name :pos :cos] rands))) ; Probably not what you had in mind, right? |
| 11:10 | clojurebot | {:age (80 45 64 68), :name (19 75 35 40), :pos (44 48 42 63), :cos (90 22 91 92)} |
| 11:10 | Anderkent[away | learner_: into expects a list of map entries, you give it a single map entry. Try #(into {} [%]) |
| 11:11 | Anderkent[away | (or (apply hash-map %) ) |
| 11:12 | justin_smith | learner_: ,(map (fn [numbers] (into {} (map vector [:age :name :pos :cos] numbers))) (partition 4 (repeatedly 20 #(rand-int 100)))) |
| 11:12 | justin_smith | I think that is what you actually wanted |
| 11:12 | justin_smith | ,(map (fn [numbers] (into {} (map vector [:age :name :pos :cos] numbers))) (partition 4 (repeatedly 20 #(rand-int 100)))) |
| 11:12 | clojurebot | ({:age 25, :name 55, :pos 19, :cos 63} {:age 77, :name 85, :pos 61, :cos 95} {:age 18, :name 92, :pos 5, :cos 50} {:age 28, :name 69, :pos 71, :cos 29} {:age 8, :name 13, :pos 3, :cos 22}) |
| 11:14 | Bronsa | seangrove: i mimicked LineNumberingPushbackReader's behaviour |
| 11:25 | learner_ | Thanks justin_smith: & Anderkent[away: |
| 11:25 | justin_smith | learner_: out of curiosity, what was the actual behavior you wanted? |
| 11:27 | learner_ | justin_smith: You guessed what I wanted exactly. I was trying to learn from clojure.logic example https://gist.github.com/swannodette/5127144 |
| 11:35 | egghead | is there anything you can do with core.async you couldn't do with futures/promises or is it just a different set of semantics for managing the same stuff |
| 11:36 | tbaldridge | egghead: how do you express a async stream of values with futures/promises? |
| 11:36 | tbaldridge | To quote Rich: "promises are the one-night-stand of async programming" |
| 11:36 | tbaldridge | "we're looking for more long-term relationships" |
| 11:37 | egghead | for some reason I was thinking a promise could be fulfilled multiple times |
| 11:37 | egghead | d'oh |
| 11:37 | egghead | thanks tbaldridge that's a good way to look at it |
| 11:37 | egghead | but then it seems to have much in common with something like FRP |
| 11:38 | piranha | well not exactly |
| 11:38 | piranha | a bit maybe, a channel is a bit like event stream |
| 11:38 | tbaldridge | egghead: it does, but the way it's all wired up is quite a bit different. |
| 11:38 | piranha | but then behaviours always have a value and you don't have similar notion in core.async |
| 11:39 | egghead | except event streams usually don't have that sort of 'rendevouz' semantics like core.async |
| 11:39 | piranha | I guess you could build FRP lib on top of core.async... |
| 11:40 | seangrove | Alright, good stuff. Got the tests passing for source-map fn-param column info. Most of the work was undoing damage I had caused by not understanding how shadowing was handled |
| 11:40 | egghead | ya, you can easily build weird little map/reduce/filter for the chans |
| 11:40 | tbaldridge | IMO, core.async is less functional than FRP, but it's also easier to understand |
| 11:40 | alandipert | need to add coordination, but then you're not getting much benefit from buffering |
| 11:40 | alandipert | (if any) |
| 11:40 | functionform | assuming you have a collection in form of ((col1) (col2) (col3) (col4)), how do you get it to be ((col1 + col2) (col3 + col4)) ? |
| 11:40 | egghead | Last night I wrote a websocket wrapper as a core.async channel |
| 11:40 | tbaldridge | Some FRP stuff is all about "let's take this normal function, and re-compile it to work with streams instead of values", that's some complex compiler magic |
| 11:41 | egghead | seemed kind of voodoo to be able to read from it and have it read from the remote server and write to send |
| 11:42 | egghead | it seems like you should be able to write something like Rx on top of core.async |
| 11:42 | nDuff | egghead: someone's done pretty much that. |
| 11:42 | bbloom | tbaldridge: i agree. FRP is oversold by the academic community |
| 11:42 | tbaldridge | egghead: https://groups.google.com/forum/#!msg/clojure/L4nEVho555k/HqeDHeWbWmUJ |
| 11:42 | Anderkent[away | functionform: (map (partial apply concat) (partition 2 [[1 2 3] [4 5 6] [7 8 9] [0]])) |
| 11:42 | egghead | well, well, well |
| 11:43 | bbloom | tbaldridge: it was invented for dealing with data that represents continuous things, but discrete is always preferable to work with when you can choose |
| 11:43 | functionform | hm thats awesome |
| 11:43 | egghead | neat |
| 11:43 | functionform | i'm having trouble leaving behind the world of loop |
| 11:43 | alandipert | bbloom: that depends heavily on your use case, as it's really easy to go from continuous => discrete, but very hard to go the other direction |
| 11:43 | functionform | and for |
| 11:44 | tbaldridge | bbloom: agreed. Now what does have me thinking, is Sussman's work on propagators http://dspace.mit.edu/handle/1721.1/44215 |
| 11:44 | bbloom | alandipert: i know you're a big FRP fan :-) you'll just have to wait and see what i'm working on, but it's gonna be a while |
| 11:44 | alandipert | i think FRP blows but i'm in love with continuous propagation |
| 11:44 | bbloom | tbaldridge: oh yeah, propegators are awesome too |
| 11:45 | tbaldridge | bbloom: I havent' put any thought into it at all, but it seems that propagators on top of core.async may be possible. |
| 11:45 | functionform | thanks anderkent. |
| 11:45 | bbloom | tbaldridge: you mean building a distributed propagators evaluator? yeah, should be |
| 11:45 | bbloom | s/distributed/concurrent/ i guess |
| 11:45 | tbaldridge | yeah |
| 11:46 | bbloom | that'd be cool |
| 11:46 | bbloom | go for it :-) |
| 11:47 | bbloom | alandipert: by continuous propagation, you mean like you have your single atom source data & rerender the view from that like you guys do with hlisp, right? |
| 11:47 | bbloom | alandipert: in that case, i agree, but it's got nothing to do w/ FRP really :-P |
| 11:49 | squidz | what are the negatives to FRP besides it seemingly steep learning curve? |
| 11:51 | bbloom | nothing is wrong with FRP in general, it's just that it's the wrong tool for the job for UI, which is where everybody seems to want to apply it |
| 11:51 | bbloom | UI, outside of animation (which is a good domain for FRP) is inherently discrete |
| 11:51 | bbloom | your undo/redo menu has a LIST of items in it, not some flowing signal there :-P |
| 11:52 | piranha | bbloom: so you have an idea of something better? |
| 11:52 | Chousuke | I don't think FRP has any trouble with discrete things |
| 11:52 | piranha | i.e. still not having events, but skipping FRP? |
| 11:53 | tbaldridge | piranha: core.async? |
| 11:53 | bbloom | piranha: i do & i've discussed it a bit here in this channel w/ a few folks, but it's gonna take some time to bake |
| 11:53 | bbloom | Chousuke: see turing tarpits :-P |
| 11:54 | Chousuke | how is that relevant |
| 11:54 | squidz | or wrapping frp with clojure using core.async etc. to make it very simple/intuitive |
| 11:54 | Chousuke | I mean, if your UI has a list, then a signal of its contents is just its state. |
| 11:54 | bbloom | Chousuke: electricity is continuous, yet we need to introduce a clock to discrete the operation of our CPUs so us mortals can understand it |
| 11:55 | bbloom | descretize* |
| 11:55 | arrdem | gah where's aperiodic... his blog's down and I need a screen cheat sheet :P |
| 11:55 | piranha | tbaldridge: well core.async as it is right now won't give you continuous propagation, won't give you a proper source of information, just events to consume; I've tried doing UI with Go and I don't think that this level of abstraction is right |
| 11:55 | bbloom | Chousuke: sure, i understand the idea, i'm just not convinced that it's a useful way to think about the problem |
| 11:55 | dnolen | egghead: core.async is flexible enough to handle both what FRP libs and promise libs JS folks use for, w/ on one abstraction |
| 11:55 | dnolen | piranha: I disagree |
| 11:55 | piranha | bbloom: but changes of state in FRP could be discrete (and usually are, it's not like your string 'hello' slowly changes to 'world') |
| 11:56 | dnolen | piranha: and I think know sources and destinations is an anti pattern in UI programming. |
| 11:56 | piranha | dnolen: I would love to see UI written in core.async :) |
| 11:56 | dnolen | s/know/knowing |
| 11:56 | Chousuke | bbloom: then applying a transformation to the list is just a transformation to the signal, and any updates are reflected automatically |
| 11:56 | dnolen | piranha: yeah I've been working on this a bit, I wouldn't go back to plain JS or JS w/ just promises or just the reactive style. |
| 11:56 | bbloom | then you introduce databinding & suddenly your signal graph is cyclical |
| 11:57 | bbloom | so you have to introduce dampeners, to eliminate feedback loops |
| 11:57 | bbloom | and now time is central to everything you do all the time |
| 11:57 | bbloom | it's callback speghetti just the same |
| 11:58 | Chousuke | bbloom: note that list signal should be separate from the actual listview UI element "signal" that gets drawn |
| 11:59 | bbloom | any design that relies on heroic programmer effort to enforce a particular decomposition means that the primitives don't compose usefully (for the problem domain) |
| 11:59 | bbloom | this is the same issue w/ callbacks |
| 11:59 | egghead | but aren't UIs a continuous stream of events |
| 11:59 | egghead | usually user input and network events? |
| 12:00 | tbaldridge | egghead: That's pretty much the way the Pedestal UI models things |
| 12:00 | Chousuke | bbloom: I suppose the issue is that FRP is a very general technique. you can use it for data flow that involves no UI whatsoever. |
| 12:01 | bbloom | Chousuke: that's why i mentioned turing tarpits: it's a very general technique that is not well suited to a large number of problems people are trying to solve with it. that's not to say there arent' areas where it's super useful |
| 12:01 | bbloom | tbaldridge: my primary complaint about pedestal is that it requires the programmer to manually compose the dataflow graph, which seems laborious and error prone |
| 12:01 | bbloom | the externalization of state, however, greatly helps by enabling the replay & other debugging tools |
| 12:02 | bbloom | so it may very well still be a step up from everything else that is out there now |
| 12:02 | tbaldridge | bbloom: to rephrase "it's not easy enough" :-P |
| 12:02 | Chousuke | then if you have a program written using FRP, you will need to be careful not to confuse the flow of your data with the flow of user interactions. |
| 12:03 | bbloom | tbaldridge: that's not it. i just think that the dataflow graph is an implementation detail that a compiler should be generating :-) |
| 12:03 | Chousuke | I suppose I see your point. that can be tough to do right |
| 12:04 | egghead | I still don't know what problem pedestal is the solution to :p |
| 12:04 | tbaldridge | bbloom: I'm half serious there. IMO such compiler/macro magic should be left until the underlying concepts are proven to work. Build with data, optimize with macros. |
| 12:04 | egghead | tbaldridge: and what would YOU know about macros? :p |
| 12:04 | bbloom | tbaldridge: sure, i'd agree with that |
| 12:05 | egghead | maybe one day I'll understand what's going on in https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/ioc_macros.clj |
| 12:05 | tbaldridge | bbloom: I've build several dataflow engines in the past, and IMO, text is just a horrible way to describe dataflow. IMO, we need something like LabView's GUI to do dataflow well. |
| 12:06 | bbloom | tbaldridge: heh, oh yeah, anything that's two dimensional kinda blows in text. i note how people struggle to correctly format cond forms :-) |
| 12:10 | Chousuke | I suppose the ideal with frp is that UI is stateless. |
| 12:11 | bbloom | Chousuke: state ABOUT the UI is fine, state INSIDE the UI is the problem |
| 12:11 | Chousuke | which would actually make animations explicitly dependent on a time signal |
| 12:14 | dnolen | tbaldridge: huh, interesting never heard of LabView, though I've seen lots of folks use MaxMSP to build interactive programs. |
| 12:15 | gfredericks | (inc lein-try) |
| 12:15 | lazybot | ⇒ 1 |
| 12:15 | Chousuke | efficient updates to a stateless UI might be a problem though, since if you for example update your list input data, the UI could be more efficient if it knew that an item was added to the end (instead of just "the list changed") which creates an unfortunate dependency between the UI and the data format. |
| 12:15 | Wild_Cat` | we used Labview to automate some of the QA process at my old job. Very pointy-clicky, but it worked. |
| 12:16 | Chousuke | so you would have to model an "item enters" event and then pipe that to list append and listview redraw behaviours |
| 12:16 | Chousuke | and then your data is no longer connected to the UI directly :/ |
| 12:28 | dnolen | CLJS switched to tools reader (thx again seangrove & Bronsa) |
| 12:29 | seangrove | dnolen: Thanks |
| 12:29 | alandipert | is there a way to generate an inner class in clojure? |
| 12:31 | hiredman | there are no inner classes outside of javac, as far as I understand the jvm |
| 12:31 | dnolen | seangrove: how are the other source map bits going? |
| 12:31 | jonasen | bbloom: transduce is ready to be pulled I think. Or is there something more to be done? |
| 12:32 | seangrove | dnolen: I'm working on them now, though I shouldn't be, really. Made a lot of progress and the diff is still pretty small, but have a few failing tests. |
| 12:32 | bbloom | jonasen: just waiting for me to pull it down, test it, etc. i'm doing some client work now, so it'll have to wait a tad |
| 12:32 | seangrove | Working on the foo.ns_shadow_test tests now |
| 12:32 | bbloom | jonasen: thanks! |
| 12:33 | dnolen | seangrove: ha! k cool |
| 12:33 | jonasen | bbloom: ok, no problem. The fipp work was pretty easy. But I think I found a cljs bug |
| 12:33 | bbloom | jonasen: nice. what's the bug? |
| 12:34 | jonasen | (r/reduce + (map inc [1 2 3])) throws. LazySeq does not implement IReduce |
| 12:35 | bbloom | jonasen: gah. dnolen will surely accept a patch for that :-) |
| 12:35 | dnolen | bbloom: jonasen: fixing right now |
| 12:36 | jonasen | dnolen: cool! |
| 12:43 | seangrove | dnolen: would appreciate a heads up here https://gist.github.com/sgrove/6105574 looks like ns_shadow_test/bar in the cljs -> js compile goes fine, but it gets mangled on the second (simple/advanced) compile |
| 12:43 | seangrove | Is there some obvious disambiguation that happens that I've missed? |
| 12:45 | seangrove | Ah, nevermind |
| 12:46 | dnolen | seangrove: that output looks wrong to me even for no optimizations |
| 12:46 | seangrove | I assume the function param has to be munged to avoid the collision with the ns |
| 12:46 | dnolen | seangrove: yes absolutely |
| 12:46 | seangrove | That's what I was missing, shadowing the ns properly |
| 12:46 | seangrove | Need to get more clojure-language hackers here in SF so this is easier to do in person |
| 12:48 | bbloom | seangrove: do you have a github account? |
| 12:48 | seangrove | bbloom: sgrove |
| 12:49 | bbloom | seangrove: you should update your email addresses or fix your gitconfig |
| 12:49 | bbloom | github can't match the patch's metadata to your account |
| 12:50 | seangrove | bbloom: I'll take a look at it later tonight, thanks for the heads up. Probably set it 4 or 5 years ago, haven't thought about it since. |
| 12:51 | bbloom | s@bushi.do |
| 12:51 | bbloom | is what's on the patch :-) |
| 12:54 | dnolen | seangrove: the ns collision stuff is present in the munge fn |
| 12:54 | gfredericks | does anybody know how to test a specific namespace in the clojure repo? |
| 12:55 | gfredericks | mvn test <something>? |
| 12:55 | hiredman | hah! |
| 12:55 | dnolen | jonasen: lazy seq issue fixed in master |
| 12:56 | seangrove | bbloom: Ok, added the email to my github account, thanks |
| 12:57 | babilen | cemerick: Thanks for closing the drawbridge licensing issue that promptly -- It would also be nice if every source file could mention its license and include a header (for the EPL) such as https://www.refheap.com/17010 - Merci! |
| 12:58 | cemerick | babilen: Sure thing. I won't add headers like that though, I find them pretty irritating. |
| 13:00 | babilen | cemerick: Alright, your call. The important bit (actually shipping the license text as required by the license) has been taken care of. I wonder why so many projects opt to ship the html text though. Thought it would be more common to find a plain text version in LICENSE :) |
| 13:00 | babilen | cemerick: thanks again |
| 13:03 | bbloom | cemerick: +1 for fuck those annoying top of file license comment blocks |
| 13:03 | clgv | bbloom: actually only in 50% of the drawbridge files ;) |
| 13:04 | pjstadig | they can be useful if someone wants to use a file or two from your project |
| 13:04 | babilen | bbloom: They make it *much* easier to figure out the license if somebody decides to copy an entire file from once project to another. |
| 13:04 | pjstadig | makes it clear what is license how |
| 13:04 | alandipert | license meta, for licensing on a per-form basis |
| 13:05 | cemerick | clgv: shit, that's what I get for copy/pasting! :-P |
| 13:05 | bbloom | alandipert: nah, licensing has dynamic extent, not lexical :-) |
| 13:05 | babilen | I don't think that licensing should be treated as that unimportant and it is easy to hide/fold those license headers away so they don't really bug you |
| 13:05 | alandipert | lexical is better because then we can have license combinators |
| 13:05 | pjstadig | bbloom: clojure.core/*license* |
| 13:06 | pjstadig | alandipert: but then you'd have to take the license as an argument to every function? |
| 13:06 | hiredman | babilen: the first step there is not putting the headers in all caps |
| 13:06 | bbloom | alandipert: we were just discussing delimited dynamic extent here last night. you can have combinators then |
| 13:06 | Chousuke | The solution is a license monad |
| 13:06 | babilen | I mean I just found a *bunch* of Clojure projects that do not comply with the EPL in that they don't ship the license text in source copies |
| 13:06 | pjstadig | i like where this is going |
| 13:06 | cemerick | babilen: In general, if I publish code publicly, I really don't care what people do with it. :-) |
| 13:06 | hiredman | pjstadig: obviously we'll need letrec for that |
| 13:06 | babilen | hiredman: I simply copied that part from the EPL |
| 13:06 | pjstadig | hiredman: lol |
| 13:06 | bbloom | monads are macro expressible in terms of delimited continuations! :-) |
| 13:07 | Chousuke | Or if you implement it as an indexed monad, you can implement bind so that you can only compose compatibly licensed functions |
| 13:07 | bbloom | babilen: yup, i'm totally non-compliant |
| 13:07 | babilen | cemerick: Well, then use an appropriate license for that (MIT might suit you, EPL unfortunately has certain requirements (but you know that)) |
| 13:07 | Chousuke | and produce correctly-licenced result functions |
| 13:07 | babilen | bbloom: I fail to see how that is a good thing |
| 13:08 | babilen | (let alone something to be proud of) |
| 13:08 | bbloom | babilen: i didn't say it was a good thing or that i'm proud of it |
| 13:08 | bbloom | i blame technomancy & lein! defaulting to the EPL and not including the license in the template |
| 13:08 | pjstadig | guys if we're going to fight about something can we fight about the CA instead? |
| 13:08 | cemerick | babilen: yeah, I started using MIT in a lot of stuff lately. The "EPL, just like Clojure" somehow became a meme some years ago, and a lot of people unfortunately freak out when they see a Clojure library that isn't EPL. |
| 13:08 | pjstadig | i guess i just lost the CA game |
| 13:09 | bbloom | i've been meaning to just switch (almost) everything to MIT |
| 13:09 | babilen | cemerick: I saw that, makes perfect sense! |
| 13:10 | bbloom | i wish github helped w/ licensing, but i can assume they are worried about the legal implications there |
| 13:10 | pjstadig | the problem is software patents, and MIT is silent about them |
| 13:10 | bbloom | ^^ what pjstadig said |
| 13:10 | pjstadig | EPL is nice because it deals with patents |
| 13:12 | bbloom | http://www.scala-lang.org/node/146 <- what license is that? |
| 13:12 | bbloom | looks like 3 clause bsd |
| 13:16 | babilen | bbloom: Good point about the lein default, I might ask them to include it :) |
| 13:16 | cemerick | bbloom: they forgot to edit "THE REGENTS" out of the last block :-P |
| 13:16 | bbloom | lol |
| 13:16 | bbloom | nice. |
| 13:17 | hiredman | the scala regents |
| 13:20 | pjstadig | i wanna be a clojure regent |
| 13:20 | pjstadig | can i be a clojure regent? |
| 13:21 | stuartsierra | Clojure has no regents, only agents. |
| 13:24 | llasram | You could always create a library named `alchemy` which included reagents |
| 13:28 | Bronsa | seangrove: dnolen I just noticed that clojure and clojurescript returned different things for (namespace 'foo/bar/baz) so it was a bad idea to have that test anyway |
| 13:28 | dnolen | Bronsa: agreed |
| 13:29 | bbloom | Bronsa: i don't know if it was that specific test, but the namespace & name functions in cljs were bugged w/ respect to symbols named '/ |
| 13:30 | bbloom | there was a search for / from the wrong side, so you got something like namespace "foo/" and name "" instead of "foo" and "/" |
| 13:32 | paraseba | can somebody help me understand why lazy-seq behaves like this? https://gist.github.com/paraseba/6105728 |
| 13:32 | bbloom | paraseba: move the cons outside the lazy-seq |
| 13:32 | bbloom | (cons n (lazy-seq …)) |
| 13:33 | bbloom | i think that would fix it |
| 13:33 | hiredman | no |
| 13:33 | bbloom | ok or no, i didn't look at it too carefully. trust hiredman :-) |
| 13:33 | hiredman | the issue is because of the map identity, you have something like O(n) more stack frames to realized the nth element |
| 13:34 | paraseba | bbloom: that still stack overflows |
| 13:34 | bbloom | hiredman: as yes, that makes sense |
| 13:35 | hiredman | so the first "rest" has one call to identity to realize the value, the next "rest" has 2, etc, etc, etc |
| 13:36 | paraseba | but are all those calls nested? |
| 13:36 | hiredman | (cons x (cons (identity x) (cons (identity (indentity x)) ...))) |
| 13:37 | hiredman | paraseba: map creates a lazy-seq, so the result of a call to map is effectively a promise to give you each value of the input with the function applied to it, when you ask for it |
| 13:39 | paraseba | hiredman: I don't fully understand how it coud be nested identity applications. If instead of nested it were inc, would I get a number incremented many times? |
| 13:40 | hiredman | you have a recursive function |
| 13:40 | hiredman | follow it through with the substitution model |
| 13:41 | paraseba | I'll try that |
| 13:41 | paraseba | thanks |
| 13:41 | Chousuke | map is lazy so the 5000 identity calls all happen at once to get the first value of the seq. |
| 13:41 | Chousuke | or maybe last, I might be inverting the logic in my head |
| 13:41 | hiredman | you basically end up with (map identity (map identity (map identity ...))) |
| 13:42 | paraseba | yes, that's how I imagine it hiredman , but I don't see why that would overflow the stack, since each one of those map calls returns a promise without nesting the stack |
| 13:43 | paraseba | Chousuke: to get the first element of the seq there is nothing to be done, it's just n |
| 13:43 | hiredman | paraseba: yeah, but as soon as you try to realize it (for say, printing, or getting the 5000th element) the promises all come due |
| 13:44 | paraseba | that makes sense hiredman I think I get it now, thanks |
| 14:33 | seangrove | tbaldridge going after trolls on twitter with some admirable patience |
| 14:33 | tbaldridge | seangrove: rofl, I shouldn't, but it's so hard not too. |
| 14:35 | tbaldridge | well guys, it's been real, but according to Twitter, Clojure is dead, so I'm moving to Ruby now... |
| 14:35 | bbloom | lol |
| 14:36 | rkneufeld | Raynes: glad you like lein-try |
| 14:36 | bbloom | it's so funny to me that people 1) don't think lisp can evolve and 2) think that internal beauty is the #1 priority |
| 14:36 | Raynes | rkneufeld: <3 |
| 14:37 | alandipert | Raynes, rkneufeld: group hug you guys, bring it in |
| 14:37 | rkneufeld | some kind of "exec this too" would be awesome |
| 14:37 | Raynes | hugs* |
| 14:37 | Raynes | In my accent it sounds the same. |
| 14:37 | Raynes | :3 |
| 14:39 | gfredericks | tbaldridge: that list of languages he posted for comparison does not include any lisps, which I think is relevant to your libraries claim -- i.e., macros specifically take the pressure off of innovating the language |
| 14:39 | gfredericks | some of the pressure* |
| 14:39 | tbaldridge | as does most of the rest of lisp. No need to improve the syntax of a language when you have sexprs and macros. |
| 14:40 | bbloom | tbaldridge: so it's interesting. racket & most lisps have "syntactical sugar" for cons cells |
| 14:40 | bbloom | (x y z), (x . (y z)), etc |
| 14:40 | bbloom | they have syntax support for a particular concrete data structure |
| 14:41 | bbloom | and clojure added support for data structures of parameterized types |
| 14:41 | bbloom | that just seems like a no brainer to me, even in theory |
| 14:41 | tbaldridge | yeah, as well as racket being a "everything included" language. They have a ton more to support with a custom GC, typesystem, packages, etc. |
| 14:41 | tbaldridge | Last I checked, even their FRP implementation is in the main language source tree |
| 14:42 | bbloom | racket is a great project w/ some amazing work done on it, but the goals are just so different |
| 14:42 | bbloom | those guys are studying languages (and we need them!) we're trying to build real things (and they need us!) |
| 14:42 | bbloom | :-) |
| 14:42 | seangrove | Is there a way to see what form (fn* nil (apply bug rest__5789#)) will take when it's expanded/parsed all the way out? It seems like there's at the very least a (do) form that gets wrapped around the body |
| 14:43 | tbaldridge | fn* is a builtin |
| 14:43 | seangrove | This is causing me some trouble with some source-maps and lower-level js-forms like js-obj |
| 14:43 | tbaldridge | so it's all in the compiler parsing |
| 14:44 | seangrove | hrm.... |
| 14:44 | tbaldridge | the parsing code is here: https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj#L379 |
| 14:44 | tbaldridge | that probably doesn't help |
| 14:44 | Bronsa` | seangrove: and here's your do https://github.com/clojure/clojurescript/blob/master/src/clj/cljs/analyzer.clj#L375 |
| 14:44 | seangrove | tbaldridge: Yeah, looking at that right now already ;) |
| 14:45 | seangrove | Bronsa: ah! |
| 14:45 | seangrove | Thank you, I had skipped over that looking for (do ... |
| 14:55 | bosie | anyone know industries in germany using clojure? |
| 15:06 | koderde | Whats a good logging framework regarding: concurrency, production, logrotation, performance? |
| 15:07 | hiredman | any of them? I think logback is supposed to be the new java logging hotness |
| 15:08 | koderde | hiredman: thanks for the tip I will have a look ... |
| 15:08 | pjstadig | hiredman: no. it's log4j2 |
| 15:08 | justin_smith | log4j2 updated to use disruptor and is blazingly fast, or so I hazily recall |
| 15:09 | hiredman | logback is what pedestal uses, which isn't so much of an endorsement, just a place to steal config files from |
| 15:09 | pjstadig | justin_smith: inc |
| 15:09 | justin_smith | http://logging.apache.org/log4j/2.x/manual/async.html it actually scales in performance with more processor for example |
| 15:09 | justin_smith | we should get more clojure stuff using disruptor |
| 15:10 | hiredman | *shrug* yet another silver bullet that people can use on nails |
| 15:10 | tbaldridge | what are you using that requires so much throughput that disruptor would help? |
| 15:10 | clojurebot | excusez-moi |
| 15:11 | hiredman | tbaldridge: some people aren't using datomic so in order to have a history they have to dump everything to logs? I guess? |
| 15:11 | tbaldridge | notice that the use case for which disruptor was designed had a unique problem. Their CPU bottleneck was dominated by the performance of their queues |
| 15:12 | tbaldridge | hiredman: lol, perhaps |
| 15:12 | tbaldridge | "I don't need DB history, that's what I have flat files for...." |
| 15:13 | jkj | Raynes: laser man? |
| 15:13 | Raynes | ? |
| 15:14 | jkj | Raynes: is the laser library yours? |
| 15:14 | Raynes | Yes. |
| 15:15 | jkj | i'm having the dumb today. cannot fragment to html |
| 15:15 | Raynes | I've been afflicted with the dumb from time to time. |
| 15:15 | Raynes | Do you have a failing example I can look at? |
| 15:15 | jkj | just a moment |
| 15:16 | jkj | Raynes: https://gist.github.com/jkjuopperi/34f79db2832a43c79dd4 |
| 15:17 | jkj | there is the fragment... and the code |
| 15:17 | jkj | moment |
| 15:18 | Raynes | jkj: Can you also show me the calling code that causes the exception as well as the exception itself? |
| 15:19 | jkj | Raynes: thank you for your help. the dumb passed the moment I asked for help :P |
| 15:19 | Raynes | :p |
| 15:19 | Raynes | That's how the dumb usually works. It's a serious disease. |
| 15:19 | jkj | Raynes: the problem was that laser/fragment returns a vector with the node map inside |
| 15:20 | jkj | Raynes: and i ofcourse concatenated the vectors and not the nodes inside them |
| 15:20 | Raynes | fragment-to-html is meant to work on exactly what fragment returns. You shouldn't have to concatenate things. |
| 15:38 | jkj | Raynes: laser is working splendidly btw. migrated from enlive. just need to learn to read the apidocs it seems |
| 15:39 | Raynes | Good to hear it. :) |
| 15:39 | Raynes | The API is changing quite a bit in 2.0.0 |
| 15:39 | jkj | Raynes: i misused to-html and missed fragment-to-html :P |
| 15:39 | Raynes | Feel free to play around with 2.0.0-SNAPSHOT if you aren't worried about a few bugs and things changing on you. |
| 15:39 | clojurebot | but I don't feel using a map or set is neat |
| 15:39 | Raynes | I agree clojurebot. Very observant of you. |
| 15:40 | tbaldridge | clojurebot: scatterbrained much? |
| 15:40 | clojurebot | Huh? |
| 15:41 | tbaldridge | as I thought |
| 15:44 | troydl | Greetings; Opinion/convention question: I'm writing a function that takes a collection of maps and a key and returns a collection of maps with duplicates of that key removed. I'm wondering what I should do with the maps in the collection in which the given key doesn't exist. Should I filter them all out or leave them all in? |
| 15:45 | noonian | what do you mean duplicates of that key removed? you can't have duplicate keys in a single map |
| 15:46 | troydl | Sorry, I mean if two maps both have a key and their value is equal, return only one of them |
| 15:46 | troydl | one of the maps* not the values |
| 15:48 | noonian | and if they are not the same value would you leave both maps there? |
| 15:49 | noonian | it depends on the assumptions you want to be able to make about the value that is returned from the function imo |
| 15:51 | troydl | Basically I want a function like (distinct [coll]) that takes a keyword name and returns only those in the collection with distinct values on that key |
| 15:54 | troydl | So '({:a 1 :b 2} {:a 2 :b 2} {:a 1 :b 3}) passed in with [:a] would return ({:a 1 :b 2} {:a 2 :b 2}) or ({:a 2 :b 2} {:a 1 :b 3}) but not all 3 |
| 15:56 | ucb | troydl: how would it decide which ones to return? |
| 15:58 | troydl | Whichever comes first I think. The other keys and values aren't important. |
| 16:01 | troydl | As long as the values were distinct on the :a key |
| 16:04 | noonian | troydl: I would either not return any maps that were missing the key, or return all of them |
| 16:04 | troydl | Right that's what I was thinking, I just couldn't decide between those two options :P |
| 16:06 | troydl | I guess I'll go with not returning them if they don't have the key for now and if a situation pops up where it makes sense the other way I'll change it. Thanks. |
| 16:06 | noonian | np |
| 16:08 | gfredericks | easiest way to canonically pretty-print some standard edn data? |
| 16:08 | rhg135 | prn-str? |
| 16:08 | bbloom | define "canonically" |
| 16:08 | gfredericks | bbloom: I don't have to worry about ordering on unordered collections |
| 16:08 | gfredericks | rhg135: not very pretty |
| 16:08 | rhg135 | true lol |
| 16:09 | rhg135 | but humanly pareable ;) |
| 16:09 | gfredericks | rhg135: also not canonical I don't think |
| 16:09 | rhg135 | hmm |
| 16:09 | rhg135 | multimethods? |
| 16:09 | clojurebot | multimethods is what separates the boy from the man. |
| 16:10 | rhg135 | nice bot |
| 16:10 | gfredericks | my use case is I'm checking some data into my git repo and I want git to be able to give me useful info about changes |
| 16:10 | llasram | mmm... robot sexism |
| 16:10 | gfredericks | clojurebot: forget multimethods is what separates the boy from the man. |
| 16:10 | clojurebot | Ok. |
| 16:10 | rhg135 | protocols? |
| 16:10 | clojurebot | http://whiley.org/2012/02/29/a-problem-of-decoupling/ describes a problem solvable by protocols |
| 16:10 | gfredericks | it's not really even a worthwhile thing to say apart from the gender aspects |
| 16:15 | gfredericks | maybe I don't need records so I could just manually combine sorted-map with clojure.pprint |
| 16:20 | duck11231 | multimethods are what separates the boys from the men at runtime by comparing the results of a dispatch function against a set of values |
| 16:20 | gfredericks | (defmulti foo age) |
| 16:20 | gfredericks | no wait |
| 16:21 | gfredericks | (defmulti foo (partial < age-of-majority)) |
| 16:22 | duck11231 | Yeah, I felt myself reaching a bit far for that one |
| 16:23 | gfredericks | are multimethods faster than protocols implemented with extend? |
| 16:23 | tbaldridge | gfredericks: no |
| 16:23 | gfredericks | tbaldridge: that's good to know |
| 16:24 | tbaldridge | gfredericks: there's some other stuff in here, but here's some relative numbers: https://github.com/mikera/matrix-api/blob/master/src/test/clojure/clojure/core/matrix/calling_benchmark.clj |
| 16:25 | clj_newb_2345 | is there a way to do a non-blocking read in core.async ? |
| 16:25 | gfredericks | tbaldridge: wait I think I stated my question backwards |
| 16:25 | clj_newb_2345 | i.e. a function that immediately returns either [:ok value] or [:nothing] ? |
| 16:25 | gfredericks | and these benchmarks say the opposite of what I misinterpreted you to mean |
| 16:26 | tbaldridge | gfredericks: multimethods are slower than any other Clojure polymorphic system. Granted you won't notice most of the time, but they are quite slow |
| 16:27 | gfredericks | tbaldridge: so I'm curious why the extended-call is faster -- are they not both hash lookups? |
| 16:27 | gfredericks | I guess protocols don't have to muck with the global hierarchy |
| 16:27 | duck11231 | IIRC, it's because the multimethod has an extra fn call |
| 16:27 | gfredericks | duck11231: you mean because the dispatch function isn't inlined? |
| 16:28 | duck11231 | well, yeah |
| 16:28 | gfredericks | that makes sense |
| 16:28 | gfredericks | well this is good to know. I kept hearing "protocols are faster" and nobody seemed to think it worth clarifying that they're faster even with extend |
| 16:28 | gfredericks | which seems an obvious question to me |
| 16:29 | tbaldridge | gfredericks: protocols also use a form of inline caching, |
| 16:29 | gfredericks | what does that cache? the inheritance details? |
| 16:30 | duck11231 | I think it's very interesting this note about using a custom class with an optimized hashCode being faster than vector comparison |
| 16:30 | gfredericks | since it's not a direct map from (class x) to impl? |
| 16:30 | duck11231 | I'm going to have to play with that |
| 16:30 | tbaldridge | no, the first time a callsite is hit, it caches the function it will execute, after that it's mostly a case of "is the object we're handed an int? if so use the cached fn, otherwise hit the extension map to find the fn to execute" |
| 16:31 | tbaldridge | http://en.wikipedia.org/wiki/Inline_caching |
| 16:31 | gfredericks | oh okay -- so only works on repeated calls of the same type |
| 16:31 | tbaldridge | yes |
| 16:31 | tbaldridge | but also like "repeated calls of the same time in the same call site" |
| 16:32 | tbaldridge | there's a ton of black magic involved here, and last time I talked to Rich about it, I realized that I knew very little about how it worked. :-| |
| 16:32 | gfredericks | oh I missed the "callsite" detail -- I get it now. |
| 16:34 | pcarrier | where am I stupid here? |
| 16:34 | pcarrier | ,(map key [{:a 1 :b 2} 3 {:a 4 :b 5} 6]) |
| 16:34 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry> |
| 16:34 | gfredericks | pcarrier: what do you want it to do? |
| 16:34 | pcarrier | gfredericks: |
| 16:34 | gfredericks | key doesn't work on maps or numbers |
| 16:34 | tbaldridge | you probably want keys |
| 16:34 | gfredericks | even so |
| 16:34 | gfredericks | would fail on numbers |
| 16:34 | pcarrier | => '({:a 1 :b 2} {:a 4 :b 5}) |
| 16:35 | gfredericks | pcarrier: you want to filter out the non-maps? |
| 16:35 | pcarrier | no no no |
| 16:35 | pcarrier | oooh wait nevermind. |
| 16:35 | pcarrier | brainfart. |
| 16:35 | pcarrier | ,(map key {{:a 1 :b 2} 3 {:a 4 :b 5} 6}) <--- actually work fine :) |
| 16:35 | clojurebot | ({:a 1, :b 2} {:a 4, :b 5}) |
| 16:36 | gfredericks | ah ha |
| 16:36 | pcarrier | I'm not such a huge fan of all those literals (but I love the destructuring let) |
| 16:37 | pcarrier | ,(map #({:val (val %)}) {{:a 1 :b 2} 3 {:a 4 :b 5} 6}) |
| 16:37 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentArrayMap> |
| 16:38 | pcarrier | what am I missing here? |
| 16:39 | pcarrier | it's a stupid example, but I expect => '({:val 3} {:val 6}) |
| 16:39 | tbaldridge | pcarrier: don't use the #() when returning a map |
| 16:40 | tbaldridge | pcarrier: what you're saying is "create this hashmap, and now call it. instead use (fn [v] {:val (val v)}) |
| 16:40 | tbaldridge | pcarrier: or better yet, use (fn [[_ v]] {:val v}) |
| 16:40 | rhg135 | or #hash-map :val ...) |
| 16:40 | rhg135 | #(hash-map...)* |
| 16:41 | gfredericks | I prefer not using tricks like that to return literals from #() |
| 16:41 | gfredericks | seems like it can only be confusing |
| 16:41 | pcarrier | hmmm. that didn't feel very tricky to me. but thanks :) |
| 16:41 | tbaldridge | that works, but the but the destructuring method is cleaner. and somewhat avoids the smurf problem. |
| 16:41 | pcarrier | well it doesn't work. |
| 16:42 | justin_smith | #(identity {:val (val %)}) |
| 16:42 | tbaldridge | ick |
| 16:42 | pcarrier | yuck |
| 16:42 | Bronsa | #(or {:val (val %)}) :) |
| 16:42 | justin_smith | heh |
| 16:42 | pcarrier | yuckier |
| 16:42 | gfredericks | #(do {:val (val %)}) |
| 16:42 | tbaldridge | *grumbles how people want to use crazy syntax instead of using (fn [x]) * |
| 16:42 | justin_smith | I often do (def id identity) because something that useful should not be verbose |
| 16:42 | pcarrier | ok, let's stop here please. |
| 16:43 | gfredericks | there's actually a funny set of clojure things that act like identity on one arg |
| 16:43 | tbaldridge | just use fn people, it's not a dirty word. |
| 16:43 | gfredericks | $findfn 42 42 |
| 16:43 | lazybot | [clojure.set/union clojure.set/intersection clojure.set/difference clojure.core/time clojure.core/dosync clojure.core/long clojure.core/short clojure.core/+ clojure.core/* clojure.core/doto clojure.core/unchecked-long clojure.core/+' clojure.core/unchecked-short cloj... https://www.refheap.com/17018 |
| 16:43 | Bronsa | tbaldridge: nobody actually uses those tricks, it's just for fun :) |
| 16:43 | pcarrier | omg omg how can I run findfn locally? |
| 16:43 | gfredericks | well swearjure has to use tricks |
| 16:43 | gfredericks | pcarrier: pm the bot |
| 16:43 | pcarrier | gfredericks: no I meant on my machine :) |
| 16:44 | gfredericks | or clone lazybot and try to find that code somewhere |
| 16:44 | tbaldridge | oh crap....that means I can do this |
| 16:44 | tbaldridge | ,(+ {:foo :bar}) |
| 16:44 | clojurebot | #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentArrayMap to java.lang.Number> |
| 16:44 | tbaldridge | oh good |
| 16:44 | gfredericks | tbaldridge: I shoulda use a non number |
| 16:44 | tbaldridge | I was hoping that wasn't the case |
| 16:44 | gfredericks | $findfn :foo :foo |
| 16:44 | lazybot | [clojure.set/union clojure.set/intersection clojure.set/difference clojure.core/time clojure.core/dosync clojure.core/doto clojure.core/macroexpand-1 clojure.core/or clojure.core/comp clojure.core/-> clojure.core/macroexpand clojure.core/max clojure.core/identity clo... https://www.refheap.com/17020 |
| 16:44 | pcarrier | $findfn {:a 1} {:a 1} |
| 16:44 | Bronsa | pcarrier: tbaldridge Raynes released findfn as a library if I'm not mistaken |
| 16:44 | lazybot | [clojure.set/union clojure.set/intersection clojure.set/difference clojure.core/time clojure.core/dosync clojure.core/doto clojure.core/destructure clojure.core/doall clojure.core/macroexpand-1 clojure.core/or clojure.core/comp clojure.core/-> clojure.core/macroexpan... https://www.refheap.com/17021 |
| 16:44 | pcarrier | he he he. |
| 16:45 | Bronsa | yep -- https://github.com/Raynes/findfn |
| 16:45 | tbaldridge | lol, I like this method best, it's soooo clear on what's happening |
| 16:45 | pcarrier | ,(io! {:a 1}) |
| 16:45 | clojurebot | {:a 1} |
| 16:45 | gfredericks | ,(-> :foo max min clojure.set/difference comp) |
| 16:45 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set> |
| 16:45 | tbaldridge | ,(macroexpand {:foo :bar}) |
| 16:45 | clojurebot | {:foo :bar} |
| 16:45 | gfredericks | tbaldridge: unfortunately that has weird behavior on some inputs :P |
| 16:46 | tbaldridge | nah, we'll just put a warning in the readme "don't use seqs as inputs to this fn" |
| 16:46 | gfredericks | unless you are an expert |
| 16:46 | Bronsa | #(-> {:foo %}) looks quite nice actually |
| 16:46 | tbaldridge | lol |
| 16:46 | duck11231 | "... because I hate typing fn" |
| 16:46 | tbaldridge | +1 duck11231 |
| 16:46 | tbaldridge | (inc duck11231) |
| 16:46 | lazybot | ⇒ 2 |
| 16:47 | gfredericks | (def fn-is-a-long-word identity) |
| 16:47 | pcarrier | Bronsa: good catch, it totally does |
| 16:47 | pcarrier | #(-> ) does look really nice |
| 16:48 | gfredericks | there's basically nothing you can put there that doesn't look like a mistake |
| 16:48 | tbaldridge | pcarrier: just to be clear, if I saw that in a code review, I would not be happy. |
| 16:49 | tbaldridge | It's an abuse of both #() and -> |
| 16:49 | pcarrier | tbaldridge: yup. |
| 16:49 | Raynes | I'd punch you in the face. |
| 16:49 | Raynes | I don't mess around with unhappiness. |
| 16:49 | tbaldridge | rofl |
| 16:52 | duck11231 | Of course, there's always (partial hash-map :foo) |
| 16:53 | tbaldridge | to really get what he wants though, it's actually (comp (partial hash-map :foo) val) |
| 16:56 | solus | Any help with this clojurescript code would be greatly appreciated:https://gist.github.com/anonymous/803534eb6496ffd7c36d |
| 16:57 | bpburns777 | anyone one know what causes these exceptions Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath: Trying to call a clojure generated class from java from a nexus plugin. |
| 16:58 | solus | basically I want to find all the items that have data set on the server and set some checkbox elements to checked. However I get back DocumentFragments which dont have a setAttribute method |
| 16:59 | duck11231 | solus: Are you sure you want reduce here and not just map? |
| 16:59 | solus | no I actually got that as a suggestion from someone else earlier this morning |
| 17:00 | solus | but I don't see any reason why it couldn't be map |
| 17:00 | tbaldridge | solus: if you use reduce you'll need two arguments to your fn |
| 17:01 | tbaldridge | solus: if you use map, it'll be lazy, so be sure to wrap in doall or something |
| 17:02 | solus | (doall (map (fn) collection) right |
| 17:04 | tbaldridge | solus: your problem is probably that reduce is handing you two args, and you're expecting one. This doesn't always result in an error in CLJS |
| 17:04 | tbaldridge | *three cheers for the crappy JS VM* |
| 17:05 | solus | I tried (doall (map (fn) collection)) and the error is gone but the dom isn't updated |
| 17:06 | duck11231 | solus: does something like this work? https://gist.github.com/duck1123/2b69f37c621d8cfe03c5 |
| 17:07 | Bronsa | solus: if you don't care for return type, just use a doseq btw |
| 17:08 | solus | duck1123: one second |
| 17:11 | solus | duck1123: no joy |
| 17:12 | duck1123 | and did it log the elements you expected? |
| 17:14 | solus | I got a persistenthashset back |
| 17:14 | zerokarmaleft | in core.async, is there way to do something like alts!/alts!! on output? |
| 17:15 | bbloom | zerokarmaleft: yeah, that works. check the doc strings |
| 17:15 | bbloom | you can mix and match too |
| 17:18 | duck1123 | solus: Do you happen to have a copy of colors and t you could provide? try logging element inside the doseq to make sure it's getting the items you want. |
| 17:21 | solus | I think its actually a problem with my php code |
| 17:21 | solus | apparently it doesnt want to set a class for my checkboxes |
| 17:21 | solus | .... |
| 17:21 | solus | wth |
| 17:23 | duck1123 | I have a sign here at my desk that says "Did you clear your cache?" I can't hold it up for you. |
| 17:23 | zerokarmaleft | bbloom: should selecting from multiple output flows be external to the state machine? |
| 17:24 | bbloom | zerokarmaleft: the various multiplexing forms will build the correct state machine for you with arbitrary mixing and nesting of input and output |
| 17:24 | bbloom | that's kinda the whole point :-) |
| 17:26 | zerokarmaleft | hmm, ok |
| 17:27 | snake-john | is there a easy way of printing the state-machine emited code (the result of fn emit-state-machine). |
| 17:27 | snake-john | I tried something like putting (map #(clojure.pprint/pprint %) (ioc/state-machine body 1 &env ioc/async-custom-terminators)) in the go macro. is there an easier way? |
| 17:27 | hiredman | ,(doc macroexpand) |
| 17:27 | clojurebot | "([form]); Repeatedly calls macroexpand-1 on form until it no longer represents a macro form, then returns it. Note neither macroexpand-1 nor macroexpand expand macros in subforms." |
| 17:29 | snake-john | I tried macroexpand-1 but could not get a result with it. but maybe I did something wrong?! |
| 17:30 | hiredman | ,(doc macroexpand) |
| 17:30 | clojurebot | "([form]); Repeatedly calls macroexpand-1 on form until it no longer represents a macro form, then returns it. Note neither macroexpand-1 nor macroexpand expand macros in subforms." |
| 17:30 | hiredman | ,(doc macroexpand-1) |
| 17:30 | clojurebot | "([form]); If form represents a macro form, returns its expansion, else returns form." |
| 17:34 | solus | ok I was editing the wrong file |
| 17:35 | solus | thats what I get for not looking at this code for a month and a half |
| 17:36 | snake-john | hiredman: macroxpand-1 shows me the code now. thanks a lot! |
| 18:43 | mthvedt | for handling authentication in ring, is there anything out there besides friend worth looking at |
| 18:56 | justin_smith | is there a way to test if some value implements a specific protocol? |
| 18:58 | justin_smith | (comp (extends my/Protocol) class) |
| 18:58 | justin_smith | (answering my own question) |
| 19:12 | dward | there is a health/process monitor for network clusters and cloud vm networks written with lamina and aleph |
| 19:12 | dward | and I can't remeber it's name |
| 19:13 | ztellman | there is? |
| 19:14 | dward | zach, perfect person. I thought there was... I may be mistaken. I'm trying to persuade my boss to use lamina on a new service, and I wanted a case study to point to. |
| 19:14 | dward | if you don't know, then i'm probably mistaken |
| 19:14 | ztellman | haha, ok |
| 19:14 | dward | keep up the good work, lamina is awesome |
| 19:14 | ztellman | at Factual we're using it to ingest 25k qps, fwiw |
| 19:15 | ztellman | it's a really trivial service, but solid |
| 19:15 | bbloom | ztellman: nice! |
| 19:15 | Raynes | https://github.com/flatland/telemetry is a service that gets the crap beat out of it a lot, I think. |
| 19:16 | clj_newb_2345 | has anyone used clojure or clojurescript for nexus 7 (or android more generally) apps ? |
| 19:16 | ztellman | oh, and geni's using it for a websocket broadcast medium, I think they have several thousand live connections at any given time |
| 19:17 | Raynes | Yeah, telemetry and https://github.com/flatland/hermes |
| 19:17 | Raynes | I think hermes is also an example of a very simple service that gets the crap beat out of it, similar to what ztellman described a moment ago. |
| 19:18 | Raynes | Lamina and turtles all the way down. |
| 19:18 | dward | hmmm I will check it out, I still have a lot of reading up to do. |
| 19:19 | ztellman | well, let me know if you have any questions |
| 19:22 | ztellman | huh, apparently a bit more than 25k lately: https://dl.dropboxusercontent.com/u/174179/various/diurnal.png |
| 19:24 | dward | ztellman well now I knwo where to find you, you'll never have a peaceful moment again. |
| 19:24 | dward | good stuff thanks for the figure |
| 19:25 | dward | i'm trying to build a deduplication engine that's basically a very simple bayesian inference tree that processes records from a stream comparing against a lucene index. It's been done but not well. |
| 19:25 | dward | With an aleph and lamina base, I think it would be fast as hell and could easily be written to scale to clusters |
| 19:25 | ztellman | so it's just a filter that's moderately expensive? |
| 19:26 | ztellman | or are you doing complicated things with the topology of the streams? |
| 19:28 | dward | ztellman: for now that's what it is, but my eventual goal is to turn it into a state machine. I want to use it to do an anlysis called markov chain monte carlo. |
| 19:28 | dward | so the topology could evolve to be very complicated, with possible recursion |
| 19:28 | ztellman | hmm |
| 19:28 | ztellman | well, you can do that, though to the extent that you can decouple the FSM and the topology, you should |
| 19:29 | ztellman | I've also got a simple performance-oriented FSM library incubating right now |
| 19:29 | ztellman | maybe that will be ready around when you need it |
| 19:31 | dward | hmm, i'll check it out, but my primary reason for using lamina would be to organize the dataflow, so i can extend my decision tree later on |
| 19:32 | ztellman | ok, that makes sense |
| 19:32 | ztellman | well, let me know if you end up doing that, it sounds interesting |
| 19:34 | dward | yes i will, if he picks it up, hopefully i can persuade my boss to opensource it. can you point me to your FSM library? |
| 19:34 | dward | have you released it yet? |
| 19:35 | ztellman | oh, not yet |
| 19:36 | dward | okay, i'll check back later, thanks for the input |
| 20:03 | scape | not sure what this is called,but I want to pass a type of a class in clojure into a function in a java library. so like this in java: assets = new AssetManager(); assets.load("data/ship.obj", Model.class); I have something like this in clojure: (doto (new AssetManager) (.load "data/ship.obj" whatdoiputhere?)) |
| 20:04 | scape | to basically pass Model.class as an arg |
| 20:04 | justin_smith | (.load "data/ship.obj" (.class Model)) ? |
| 20:04 | scape | let me try that thanks :) |
| 20:05 | justin_smith | maybe just (class Model) |
| 20:05 | justin_smith | if .class literally returns its class |
| 20:06 | scape | it does return that class in java |
| 20:06 | justin_smith | so it may be that you want class rather than .class |
| 20:06 | justin_smith | because class works on anything, .class only if it explicitly has that method |
| 20:08 | justin_smith | ,(class java.lang.Class) |
| 20:08 | clojurebot | java.lang.Class |
| 20:08 | justin_smith | (.class java.lang.Class) |
| 20:09 | justin_smith | ,(.class java.lang.Class) |
| 20:09 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: class for class java.lang.Class> |
| 20:09 | scape | (doto (new AssetManager) (.load "hex.obj" Model)) seemed to work, while (doto (new AssetManager) (.load "hex.obj" (class Model))) returned GdxRuntimeException No loader for type: Class com.badlogic.gdx.assets.AssetManager.load |
| 20:10 | scape | thanks for the help |
| 20:10 | justin_smith | glad you got it sorted out |
| 20:11 | scape | is there a good resource for java interop? |
| 20:11 | justin_smith | The Joy Of Clojure and Clojure Programming both have extensive info |
| 20:11 | scape | ok thanks! |
| 20:12 | justin_smith | (probably other books too, those are the ones I have) |
| 20:12 | scape | i have clojure prog. with emerick, i'll have to reread it |
| 20:12 | justin_smith | also, reading the source to clojure wrappers of java libs is very informative |
| 20:13 | justin_smith | page 357 in the emerick book |
| 20:14 | justin_smith | oh yeah, on that page it shows ClassName.class translates to ClassName |
| 20:14 | justin_smith | as we discovered |
| 20:29 | bbloom | you know you've been writing lisp for a while when you create a variable named "else" and stare at it funny, unsure if you are spelling that correctly b/c it looks odd |
| 20:32 | scape | nice, thanks for the page detail. rumaging bookcase :D |
| 21:30 | cmatheson | i'm trying to update a ref in a go block (maybe that's a bad idea), but it doesn't work (No such var: clojure.core/runInTransaction). should i be using the blocking core/async stuff instead? or is core.async incompatible with the other clojure concurrency features? |
| 21:39 | aje | Hello |
| 21:41 | aje | I am trying to install clojure on Debian wheezy |
| 21:41 | aje | I aodwnloaded the 1.5.1 stable zip from the clojure web site |
| 21:42 | SegFaultAX | aje: Easiest way to get Clojure is via Leiningen. |
| 21:44 | aje | And run: ant ... the compile dies with FileNotFoundEception could not locate clojure/test/generative/runner__init.class or clojure/test/generative/runner.clj on classpath |
| 21:54 | aje | Any ideas? |
| 21:57 | uris77 | use Leiningen |
| 22:02 | xeqi | aje: run ./antsetup.sh |
| 22:03 | llasram | xeqi: They're trying to "install Clojure," which I think means they really do want Leiningen |
| 22:04 | xeqi | heh, true |
| 22:06 | llasram | aje: You know how e.g. for Python you install a program named "python" you use to do stuff with the Python language? For historical reasons, the Clojure equivalent of that program is named "lein" (for Leiningen) |
| 22:07 | gfredericks | let's just rename the language "leiningen" to clear up the confusion |
| 22:07 | llasram | aje: http://leiningen.org/ Unless you're a Debian package maintainer, you should download and install straight from there |
| 22:07 | llasram | (inc gfredericks) |
| 22:07 | lazybot | ⇒ 29 |
| 22:08 | llasram | That plan is so beautiful |
| 22:09 | aje | llasram: Thanks... |
| 22:09 | gfredericks | "Leiningen is a dialect of lisp designed to not set your hair on fire." |
| 22:09 | brehaut | lol |
| 22:09 | aje | Downloaded leiningen. Weird name for a piece of software ;) |
| 22:09 | brehaut | its an ant joke |
| 22:09 | aje | how? |
| 22:09 | clojurebot | with style and grace |
| 22:09 | gfredericks | $leiningen ants |
| 22:09 | gfredericks | $google leiningen ants |
| 22:09 | lazybot | [Leiningen Versus the Ants - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Leiningen_Versus_the_Ants |
| 22:10 | gfredericks | philgelburg has been naming projects after literary characters since before I knew how to read |
| 22:11 | aje | I see ... |
| 22:14 | xeqi | gfredericks: is your swearjure talk published? |
| 22:29 | gfredericks | xeqi: it's like the last one on the schedule |
| 22:29 | gfredericks | a couple more months I think |
| 22:35 | xeqi | blah |
| 22:41 | onr | ToxicFrog: just use java lol |
| 22:43 | ToxicFrog | onr: if I were reduced to that I'd rather solve it by hand |
| 22:47 | akurilin | If I do group-by with an object like a joda DateTime, will it internally use something like the hashcode to determine the value of the key to use for the resulting map? |
| 22:48 | bbloom | akurilin: it will use hash codes & equals. you have to give it objects that behave sensible under equality, which should include pretty much everything in joda |
| 22:49 | akurilin | bbloom, if I'm understanding the source for group-by correctly, it does an assoc on the map, which I believe uses whatever implementation of hash code and equals, as you suggested? |
| 22:49 | akurilin | *the result map |
| 22:49 | bbloom | yup |
| 22:50 | akurilin | that's one terse-ass function btw. |
| 22:50 | akurilin | oh Rich. |
| 22:50 | akurilin | bbloom, ok thank you, that clarifies it. |
| 22:56 | akurilin | Do a lot of clojure functions operating on collections intentionally place the collection argument at the end to avoid having to switch between -> and ->>? |
| 22:57 | tbaldridge | akurilin: seq functions use the seq at the end (see map and reduce) |
| 22:57 | tbaldridge | akurilin: collection functions use the collection as the first argument (see conj, assoc, dissoc, etc). |
| 22:58 | akurilin | tbaldridge, would sort fall in the first category? |
| 22:58 | john2x | test |
| 23:02 | tbaldridge | .(doc sort) |
| 23:02 | tbaldridge | ,(doc sort) |
| 23:02 | clojurebot | "([coll] [comp coll]); Returns a sorted sequence of the items in coll. If no comparator is supplied, uses compare. comparator must implement java.util.Comparator. If coll is a Java array, it will be modified. To avoid this, sort a copy of the array." |
| 23:02 | tbaldridge | akurilin: "returns a sorted seq" so the collection goes last |
| 23:09 | akurilin | tbaldridge, is the idea that most of the time I won't be intermixing the two categories of functions with a threading operator? |
| 23:11 | tbaldridge | akurilin: yeah, its normally a bad idea to switch between the two. |
| 23:11 | tbaldridge | akurilin: to tell you the truth though, I don't normally find myself wanting to mix them. map/reduce/filter/remove are all seq functions so I use those together |
| 23:12 | tbaldridge | assoc/dissoc/merge are used together, etc. |
| 23:12 | akurilin | tbaldridge, got it, pefect. thank you. |
| 23:15 | akurilin | Heh, I like how sorting a map by value is frequent enough of a scenario that clojuredocs had to fully write it out. |
| 23:18 | babilen | hyPiRion: thanks a lot for fixing the license issue that promptly. rock on! :) |
| 23:58 | clj_newb_2345 | looking at http://docs.datomic.com/tutorial.html , I have one simple quesiton: where is the clojure example code? |
| 23:59 | clj_newb_2345 | it seems like there is plenty of code examples for typing into the datomic shell |
| 23:59 | clj_newb_2345 | but no actual clojure code |