2016-05-02
| 02:16 | dysfun | justin_smith, asdf12z_: the binding for compojure can be a vector, symbol or map |
| 02:17 | dysfun | it treats them all differently with magic macro shit |
| 02:19 | amalloy | well, it treats the map and symbol the same |
| 02:19 | amalloy | ie, it just applies clojure's normal destructuring rules to both |
| 02:19 | amalloy | vectors are the special case; it destructures the :params key instead of the whole map |
| 02:22 | dysfun | yeah, that |
| 03:41 | jonathanj | are there any tools that output coverage data that i could use with codecov.io? |
| 03:44 | jonathanj | cloverage is... weird: |
| 03:44 | jonathanj | Caused by: java.lang.IllegalArgumentException: Can't call nil, form: (nil (nil #{map__14313}) (nil nil nil (nil #{map__14313})) #{map__14313}) |
| 03:45 | jonathanj | compiling:(aleph/http/client_middleware.clj:176:5) |
| 03:47 | TEttinger | that's a lot of nil there |
| 03:47 | jonathanj | haha, yeah |
| 03:47 | clojurebot | Cool story bro. |
| 03:48 | TEttinger | I don't think I even know what code coverage is |
| 03:48 | TEttinger | is it a test thing? |
| 03:48 | jonathanj | it's basically how many lines of your source your tests exercise |
| 03:48 | jonathanj | 100% coverage means every line (and possibly every branch condition) is exercised by your test suite |
| 03:49 | jonathanj | anyway, cloverage doesn't seem to work at all for me, it bails out with this bizarre error |
| 03:49 | jonathanj | i was kind of hoping someone else had encountered this |
| 03:50 | jonathanj | https://github.com/lshift/cloverage/issues/85 |
| 04:00 | jonathanj | is it possible to use a lein plugin from a local repo? |
| 04:17 | fikgol | TEttinger you are right. thanks |
| 04:18 | fikgol | TEttinger: you are right. thanks |
| 04:21 | TEttinger | ah glad i could help |
| 04:28 | tolstoy | jonathanj: One way to do it is add leiningen/whatever to your source, then make sure it's on the classpath in .lein-classpath. |
| 04:28 | tolstoy | ~/.lein-classpath (I think the name is). |
| 04:28 | clojurebot | excusez-moi |
| 04:28 | tolstoy | Then you can develop plugins within your existing project. |
| 04:37 | tolstoy | Oops, I mean <project>/.lein-classpath. |
| 06:25 | bikeshedr | asdf12z_: haha, I was just wondering this last week while going through the luminus-book |
| 06:59 | panor | does anyone know whether (set-agent-send-executor!) also increases the pool when futures are used? |
| 07:33 | Keksike | what are clojure function parameters in curly braces called and how do they work, for example (defn myFunction [{id :id}] ... |
| 07:34 | M-martinklepsch | Keksike (IRC): it's called destructuring http://blog.jayfields.com/2010/07/clojure-destructuring.html |
| 07:34 | Keksike | M-martinklepsch: thanks |
| 07:35 | M-martinklepsch | Keksike (IRC): essentially they allow you to bind certain keys in maps without an extra let |
| 07:35 | Keksike | ah ok |
| 07:36 | Keksike | M-martinklepsch: is there a way to define two sets of params for a function, one which has a map-parameter and takes the value from it that way, and one which just has the id as a normal parameter for example? |
| 07:36 | Keksike | I don't remember what thats called when defining many sets of params for a function |
| 07:36 | bsamorim | guys, how do I use a custom-made Java class to a clojure code? |
| 07:36 | bsamorim | via lein |
| 07:37 | luma | that's called multiple arity, but you need to have a different amount of parameters for each |
| 07:37 | M-martinklepsch | Keksike (IRC): variadic is the term used to describe functions taking a varying number of arguments (varying arities) |
| 07:37 | luma | you can't define two different implementations for the same amount of parameters |
| 07:37 | panor | does anyone know whether (set-agent-send-executor!) also increases the pool when futures are used? |
| 07:37 | Keksike | ty again M-martinklepsch |
| 07:38 | M-martinklepsch | Keksike (IRC): luma__ (IRC) right but he could do `(defn x ([map] ...) ([id data |
| 07:38 | M-martinklepsch | ]))` |
| 07:38 | Keksike | ok |
| 07:38 | M-martinklepsch | that might be a bit confusing to others but in theory it's possible |
| 07:39 | M-martinklepsch | Keksike (IRC): if you're looking for pattern matching there are a few libraries out there as well |
| 08:46 | panor | does anyone know whether (set-agent-send-executor!) also increases the pool when futures are used? |
| 09:19 | bsamorim | guys, how can I import a custom-made java class? |
| 09:19 | bsamorim | in clojure |
| 09:19 | bsamorim | all the way from the class's .class file |
| 09:25 | ridcully | just make sure it is in the right place of the directory structure (what it claims to be in the package) in your classpath and you should be good to go? |
| 09:28 | bsamorim | ridcully: but what would be the "right place"? i mean, suppose that i created my project with lein and put my java Foo class in src/java/Foo.class |
| 09:29 | bsamorim | ridcully: how should I import it? |
| 09:31 | ridcully | if it's in not package, then it's just Foo. also i am not sure, if src/java/*.class get picked up at all? |
| 09:32 | ridcully | does it actually turn up in your target-dir? |
| 09:40 | bsamorim | ridcully: how do I check that? |
| 09:44 | ridcully | bsamorim: on unix i'd use `find target|grep ...` - ymmv. but my advice here is just "java knowledge applied". i never had the need to deal with single pre compiled java.class files in lein yet |
| 09:44 | bsamorim | ridcully: hmmm....is it possible to create a java class via clojure? |
| 09:45 | bsamorim | ridcully: it would be a ridiculously simple class, just a List with some extensions |
| 09:45 | bsamorim | ridcully: i'd use it mainly for java's mutability |
| 09:49 | TimMc | bsamorim: You can use bytecode generation. :-) |
| 09:50 | bsamorim | TimMc: hmmm...interesting...how would I go about doing that ? |
| 09:50 | bsamorim | TimMc: is there a tutorial somewhere? |
| 09:50 | TimMc | Oh, I was kidding, you'd really want gen-class. |
| 09:50 | ridcully | bsamorim: https://github.com/technomancy/leiningen/blob/4a683b85eda2e0662120a12a1f0680e6ebc0c28c/doc/MIXED_PROJECTS.md |
| 09:50 | TimMc | I mean, "want" is a strong word, but for your purposes gen-class is probably the least worst. |
| 09:52 | bsamorim | ridcully: many thanks!!!!! |
| 09:52 | bsamorim | i'm checking it out |
| 10:22 | justin_smith | TimMc: why not deftype with some mutable fields? |
| 10:23 | sdegutis | Good morning one and all. |
| 10:26 | dysfun | you're perky this morning |
| 10:29 | sdegutis | dysfun: Until this day, I never knew perky meant "cheerful and lively." |
| 10:29 | sdegutis | I thought it was more like upbeat or something. |
| 10:29 | TimMc | justin_smith: Depends on what they need. |
| 10:30 | panor | does anyone know whether (set-agent-send-executor!) also increases the pool when futures are used? |
| 10:31 | justin_smith | panor: the pool futures use is auto-expanding, and is used by send-off |
| 10:31 | justin_smith | send uses a smaller pool |
| 10:31 | justin_smith | (that does not auto-expand) |
| 10:32 | panor | HMm not sure, i read in the docs: Clojure futures are evaluated in a fixed size thread pool that is also used by agents (updated via clojure.core/send). |
| 10:33 | justin_smith | panor: not fixed size, that is false |
| 10:33 | justin_smith | agents have two pools, you can read the code to verify that |
| 10:35 | justin_smith | panor: right here, it creates two pools, one fixed, the other cached (expandable), agents use both (send vs. send-off), futures use the expandable one https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Agent.java#L49 |
| 10:35 | justin_smith | panor: you might want to correct the person who told you futures were using a fixed pool |
| 10:36 | justin_smith | (this has been an issue in my own codebase in the past, someone was spawning futures like penny candy and crashed the vm by all the memory used in creating the new thread stacks) |
| 10:36 | panor2 | sorry dc'd :( |
| 10:37 | panor2 | the pooledExecutor is fixed? |
| 10:37 | justin_smith | panor2: yes, you can look up Executors.newFixedThreadPool - you saw the source link? |
| 10:37 | panor2 | ye i got that |
| 10:38 | panor2 | so how does it expand? |
| 10:38 | panor2 | a fixed one has at most n threads right? |
| 10:38 | justin_smith | the newCachedThreadPool creates that |
| 10:38 | justin_smith | it is not fixed |
| 10:38 | justin_smith | read down a couple of lines :) |
| 10:39 | justin_smith | as I mentioned before, two pools |
| 10:40 | justin_smith | panor2: here's the doc for newCachedThreadPool https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html#newCachedThreadPool(java.util.concurrent.ThreadFactory) |
| 10:41 | panor2 | ah yes i see |
| 10:41 | panor2 | i thought there was two times fixed, oops :D |
| 10:41 | justin_smith | panor2: this is why the docs mention you should use send-off (edpandable pool) for indefinite operations, and send (fixed pool) for quicker ones |
| 10:41 | panor2 | but i'm talking about futures atm :) so if i do (future ...) which pool will it use |
| 10:41 | panor2 | the docs say the fixed one |
| 10:41 | justin_smith | panor2: the expandable one |
| 10:42 | panor2 | hmm ok then :) |
| 10:42 | jonathanj | if you want to limit parallelism in an easier way, consider using claypoole |
| 10:43 | jonathanj | it has a (future) implementation that lets you provide a threadpool |
| 10:44 | justin_smith | panor2: relevant line of the future code (future uses future-call) https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6687 |
| 10:44 | panor2 | hmm indeed, it seems you are correct :D |
| 10:45 | justin_smith | that uses soloExecutor, which if you cross reference to the other link, is the one that expands |
| 10:45 | justin_smith | after an app crashing and burning because you have wrong assumptions about these things a couple of times, one has incentive to really know what's going on :) |
| 10:46 | panor2 | true, thanks for the effort :) |
| 10:47 | justin_smith | also, once you figure out which stuff is in java and which in clj, the clojure codebase is pretty straightforward to navigate to find answers |
| 10:50 | justin_smith | dysfun: OT - what's your take on Haskell From First Principles? As a perpetual Haskell n00b it looks good but I'd be interested in a more informed perspective. |
| 10:51 | sdegutis | Yes, Clojure is simple. |
| 10:51 | sdegutis | And easy. |
| 10:52 | dysfun | justin_smith: haven't read it. is that the bitemyapp one? |
| 10:52 | justin_smith | yeah, well him and a co-author (education expert) |
| 10:56 | dysfun | oh |
| 10:57 | mpenet | soloExec is an (unbounded) cached threadpool if I recall |
| 10:57 | justin_smith | it's kind of cool - Julie learned Haskell as part of the process of them writing the book, which informed the content... |
| 10:57 | justin_smith | mpenet: yup, that's what the source / javadoc I linked to above says as well |
| 10:57 | mpenet | rule of thumb is to avoid using any of the clojure.core stuff relying on threads unless it's for small stuff |
| 10:57 | dysfun | i can't comment on her and i'm going to refrain from commenting on him |
| 10:57 | justin_smith | dysfun: fair enough |
| 10:58 | mpenet | sadly some part of core.async suffer the same pb |
| 10:59 | mpenet | *parts |
| 11:01 | mpenet | ex: `thread` and I think the all callbacks for put/take (and all the functions that uses these), so a lot of stuff :( |
| 11:01 | beaky | helllo |
| 11:01 | beaky | how do you select the best steaks |
| 11:01 | beaky | oops wrong channel |
| 11:03 | TimMc | sort, then take n |
| 11:05 | justin_smith | TimMc: surely fmap with the juiciness monad - oops, wrong channel |
| 11:06 | dysfun | well if you're in a shop where you could walk out with bad steak, you're in the wrong shop |
| 11:06 | TimMc | Are you sure we should be sending steaks over channels in the first place? |
| 11:06 | justin_smith | TimMc: yeah, the buffers could lead to freshness issues |
| 11:07 | sdegutis | ,(count [""""""""""""""""""""""""]) |
| 11:07 | clojurebot | 12 |
| 11:25 | justin_smith | is there a standard idiom for repl foolishness that I don't want to impose on collaborators, but I do want loaded into user? maybe a small project that injects bindings into the user ns? |
| 11:28 | TimMc | justin_smith: .lein/profiles.clj, yeah? |
| 11:29 | justin_smith | TimMc: but I want functions for user |
| 11:29 | justin_smith | I guess I'll put those in a plugin |
| 11:30 | justin_smith | or maybe just (when (.exists (io/file "~/user.clj")) (load-file "~/user.clj")) or some such directly in profiles.clj |
| 11:30 | TimMc | If it's just local stuff, you can write code as nonrepeatable as you like. :-P |
| 11:31 | justin_smith | haha, right, I just wondered if there was something pre-rolled, seems like it would be a common enough thing |
| 11:31 | TimMc | The :repl map in projects has some useful stuff, as long as the project itself doesn't define anything. |
| 11:31 | TimMc | https://github.com/technomancy/leiningen/blob/stable/sample.project.clj#L346 |
| 11:32 | justin_smith | TimMc: right, of course, and I can put that in profiles.clj, thanks! |
| 11:33 | ridcully | there is also -i with a regular repl |
| 11:33 | Glenjamin | justin_smith: i've added "dev/" to src paths in a :dev profile, then added "dev/user.clj" to gitignore before |
| 11:33 | justin_smith | Glenjamin: yeah, I wanted global for all projects though |
| 11:34 | Glenjamin | I have vinysa set up to inject a bunch of stuff into a namespace called "." - that sort of thing? |
| 11:34 | justin_smith | Glenjamin: yeah, that's another approach - but I'm gonna see how far I can get with ~/user.clj and then consider vinyasa |
| 11:35 | Glenjamin | this is my user profiles.clj: https://www.refheap.com/118554 |
| 11:46 | justin_smith | Glenjamin: cool, that's helpful - now to stop shaving yaks and get some work done |
| 11:47 | binjured | is there any way to alias an import of a Google Closure class in CLJS? I need to import two classes with the same name from different namespaces. |
| 11:48 | justin_smith | binjured: you can use require to get google closure libs in cljs, right? |
| 11:49 | justin_smith | and you can use :rename with require |
| 11:49 | binjured | justin_smith: yeah, but i can't figure out how to construct via that. compiler always complains "foo.bar.Baz isn't a constructor" |
| 12:30 | panor | how do you get the internal state of an agent? |
| 12:32 | dysfun | you mean the current value? |
| 12:32 | dysfun | @ |
| 12:33 | panor | ah yeah im stupid lol |
| 13:18 | WorldsEndless | Selmer allows passing of variables into the rendered page (ie for Javascript use). But I'm using Hiccup; anyone know of a similar faculty without encoding them in the DOM? |
| 13:20 | ridcully | you mean like [:script {:type "text/javasript"} (str "var something='" (quoteproperly something) "'"] ? |
| 13:25 | _maddy | cool I just discovered something called defrecord, and it looks better suited for storing data than a hashmap... have to figure out how it works next |
| 13:29 | WorldsEndless | ridcully: Yeah, I suppose so. Looks lke it needs to be hand-made? |
| 13:30 | mloveless | and of course there's always defleopard |
| 13:31 | ridcully | WorldsEndless: i don't know if there is shortcut. i just wanted to understand the question |
| 13:31 | ridcully | leopard? |
| 13:31 | mloveless | the band.. sorry, bad joke |
| 13:32 | WorldsEndless | ridcully: Looks like there is a javascript-tag option, still requiring actual writing of javascript though |
| 13:32 | ridcully | thats def leppard ;) |
| 13:34 | mloveless | whoops! |
| 13:42 | TimMc | WorldsEndless, ridcully: It's surprisingly difficult to do that safely. |
| 13:43 | TimMc | My strong recommendation is to emit <input type="hidden" name="foo" value="json-goes-here"> because otherwise you can run into the most *exciting* security issues. |
| 13:44 | TimMc | Long story short, there's no general way to encode data safely in a <script> block because it's CDATA. |
| 13:53 | jonathanj | couldn't you emit something like <script id="app-config" type="application/json">...json data...</script> and parse it as JSON? as long as you're not eval()ing the contents, you should be fine? |
| 13:55 | jonathanj | you'd obviously need some JS code to run after that script tag: window.MyApplication.config = JSON.parse(document.getElementById('app-config')); // or such |
| 13:55 | jonathanj | seems a bit easier to manage (and a lot harder to mess up) than interpolating values into strings intended to be valid javascript code |
| 13:56 | ben_vulpes | anyone have experiences positive or negative to share with the clojure scheduling libraries, or the unadorned java versions thereof? |
| 13:57 | jonathanj | ben_vulpes: never used it before but i read about it in a post when the author announced his time library: http://docs.caudate.me/hara/hara-io-scheduler.html |
| 13:58 | ben_vulpes | testability is very important to me |
| 13:58 | jonathanj | hara.io.scheduler separates the what and the when, which i would imagine makes it a lot easier to test |
| 14:01 | ben_vulpes | man this hara dude has gone a wee bit nuts |
| 14:01 | ben_vulpes | i am an impress |
| 14:01 | TimMc | jonathanj: No, that's insecure for the exact same reason a text/javascript block would be. |
| 14:01 | TimMc | I'm going to make a blog post about this sooner or later. |
| 14:01 | jonathanj | although in my experience testing time-based things, you want some way to step the clock whenever you want and as much as you want |
| 14:02 | jonathanj | i don't see anything like this for hara |
| 14:02 | jonathanj | TimMc: how so? |
| 14:02 | TimMc | jonathanj: I don't have the time to get into it right now, but <script> is CDATA, so </script> ends a script block, always. |
| 14:02 | TimMc | and if that ends up in your data, you're hosed. |
| 14:03 | jonathanj | it does? |
| 14:03 | jonathanj | even if you wrap it in <![CDATA[...]]>? |
| 14:04 | jonathanj | how would "</script>" end up there anyway? |
| 14:05 | jonathanj | presumably when hiccup (or whatever) serializes your markup it escapes all the bad things, so you never end up with a literal <, >, &, etc. |
| 14:05 | TimMc | jonathanj: Give it a try. |
| 14:05 | TimMc | and remember that an attacker can supply ]]></script> if they want to. |
| 14:07 | TimMc | For the moment, just trust me when I say that the only viable options are: 1) Backslash-escaping forward slashes in the JSON; 2) Base-64-encoding the JSON (which is actually difficult due to character encoding issues); and 3) putting the JSON in an element attribute. |
| 14:07 | TimMc | The blog post will have more detail + a demo, I just need to reformat it. |
| 14:08 | jonathanj | hang on, an attacker where? |
| 14:09 | jonathanj | if someone happens to inject some JS into your config database on the server, that still won't matter because it'll all be quoted instead of literal when it's rendered |
| 14:09 | jonathanj | if there is some guy injecting code into the client's browser on their local machine you're basically screwed anyway |
| 14:15 | TimMc | Security needs to be general. |
| 14:36 | _maddy | is mapv more efficient than map, if I need to go through all the items in any case? |
| 14:37 | amalloy | jonathanj: the default behavior of hiccup (or whatever) is not to escape everything. you have to specifically say what needs to be escaped |
| 14:39 | will_sm | _maddy, map is lazy, so a new collection isn't created so the values are calculated as needed |
| 14:39 | will_sm | _maddy, a case where this may be detrimental is when you need the entire seq multiple times |
| 14:40 | amalloy | why would that be a problem? |
| 14:40 | will_sm | In the REPL, I did `(def a (map println (range 10)))`, which should be 10 nils |
| 14:41 | will_sm | outputing `a` calls the printlns each time |
| 14:41 | AimHere | Did you really want a list of ten nils? |
| 14:41 | will_sm | AimHere, didn't matter |
| 14:41 | AimHere | Otherwise, wouldn't doseq be the more idiomatic |
| 14:42 | amalloy | will_sm: no it doesn't |
| 14:42 | AimHere | Oh right, sorry, you're explaining stuff |
| 14:42 | will_sm | amolloy, nvm lol |
| 14:44 | _maddy | will_sm: like for example map-reduce, it will go over the whole seq anyway |
| 14:46 | will_sm | amalloy, does getting the first element calculate the whole thing? `(first (map println (range 10)))` printed out all of them in the REPL, but is this always the case? |
| 14:47 | amgarchIn9 | I think 32 element chunks are hardwired. Try (range 33). |
| 14:48 | will_sm | amgarchIn9, yup |
| 14:48 | AimHere | Doesn't (range 33) have 33 elements? |
| 14:49 | amgarchIn9 | yes, that's two chunks. |
| 14:49 | will_sm | AimHere, yeah, it printed 0-31 inclusive when I took the first |
| 14:53 | amalloy | _maddy: the main disadvantage of using mapv instead of map is that you get the entire collection in memory at once, whereas with (reduce f x (map f xs)) you can produce it only as needed, and throw away old items |
| 14:54 | amalloy | i don't know whether mapv or map is faster there, if the size of the collection is not an issue, but either way it is probably fairly close and not worth worrying about, so i'd use the safer map |
| 14:54 | amalloy | i wonder if mapv would exist, actually, if transducers had been invented first |
| 14:55 | amalloy | probably not |
| 15:12 | justin_smith | amalloy: agreed |
| 15:13 | justin_smith | _maddy: are you consuming the results, or doing some side effect as you go? |
| 15:21 | _maddy | justin_smith: consuming |
| 15:23 | justin_smith | aha, yeah. If it was just side effects you could use run!, but consuming you could check out using the map transducer if appropriate, or just use map as amalloy mentions |
| 15:29 | _maddy | ok, thanks |
| 16:14 | binjured | with CLJS/JS interop, am i missing something or is it normal to have to wrap just about everything in clj->js? |
| 16:15 | Glenjamin | binjured: you'd generally want to constrain interop to a small area, but then yes - you can't use lists/vectors/maps on JS funcs without converting |
| 16:16 | binjured | Glenjamin: seems like i can't even pass Closure class instances to other constructors without it. |
| 16:16 | Glenjamin | ah, i don't know much about that - I rarely use classes in JS-land |
| 16:18 | chemouna | I wanted to share this list for people who are learning clojure https://github.com/chemouna/ClojureResources (i've collected while learning clojure myself) |
| 16:21 | chemouna | if i'm missing some excellent other resources i would love to find them , please point them out |
| 17:48 | jrc | .. |
| 17:48 | jrc | .. |
| 17:49 | jrc | ............................................................................................. |
| 17:49 | jrc | .0. |
| 17:51 | jrc | sorry |
| 17:51 | amalloy | say hello to your cat for us |
| 17:52 | justin_smith | 😼 |
| 17:53 | jrc | I will haha |
| 18:06 | irctc | Hi there. I am wondering if anyone can tell me what has happened to conj.io? |
| 18:07 | irctc | Is it down temporarily, or has it been perma-deprecated? |
| 18:07 | justin_smith | irctc: I was wondering too, maybe arrdem can enlighten us |
| 18:51 | ZimaBlue | why is areduce a macro? |
| 19:19 | jrc | I installed vim-fireplace seems to be working, :%Eval etc works, but commands like cqq cqc do nothing, I wasn't instructed to add anything to .vimrc to make these work, has anyone had luck with this vim plugin? |
| 19:23 | ben_vulpes | what's literal syntax for a partial'd function? |
| 19:23 | ben_vulpes | i'd like to test that a function returns a particular function |
| 19:23 | ben_vulpes | ,(defn bens-funk [] :hi) |
| 19:23 | clojurebot | #'sandbox/bens-funk |
| 19:24 | ben_vulpes | ,(println (partial bens-funk)) |
| 19:24 | clojurebot | #object[sandbox$bens_funk 0xb8f8de4 sandbox$bens_funk@b8f8de4]\n |
| 19:24 | ben_vulpes | ,(println (partial sandbox/bens-funk)) |
| 19:24 | clojurebot | #object[sandbox$bens_funk 0xb8f8de4 sandbox$bens_funk@b8f8de4]\n |
| 19:24 | ben_vulpes | alternatively, what'd be the idiomatic approach to test that a particular function got returned from another function? |
| 19:25 | amalloy | ben_vulpes: don't test functions for equality |
| 19:25 | ben_vulpes | boo |
| 19:25 | amalloy | the only thing you can do is test their behavior by calling them with interesting arguments |
| 19:25 | ben_vulpes | cool nbd |
| 19:53 | EgyptPharaoh | Hi guys, im new to clojure |
| 20:23 | sdegutis | Aha! I hvzae data challeng.e Finally! |
| 20:24 | sdegutis | So you have data like this.. µany maps, list of them (or seq), and it has: each have a key :age, and you want to find the number of quantity of each. |
| 20:26 | sdegutis | (f [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}]) => 3 |
| 20:27 | sdegutis | It's kind of like, the opposite of distinct. |
| 20:27 | sdegutis | the intermediate of that (f ...) is {1 3, 2 2, 3 1} because that's the frequencies |
| 20:28 | sdegutis | Ag! Frequencies! |
| 20:28 | sdegutis | Map it to :age ahd then (frequndcies) it |
| 20:28 | sdegutis | ,(->> [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}] (map :age) (frequencies) (vals) (map dec) (reduce + 0)) |
| 20:29 | sdegutis | [SOLVED] |
| 20:29 | clojurebot | 3 |
| 20:29 | sdegutis | This was good challeng.e |
| 20:30 | justin_smith | ,transduce (map :age) (fn ([s] (count s)) ([s i] (conj s i))) #{} [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}]) ; sdegutis |
| 20:30 | clojurebot | #object[clojure.core$transduce 0x3c23ebbb "clojure.core$transduce@3c23ebbb"] |
| 20:31 | justin_smith | ergh |
| 20:31 | justin_smith | ,(transduce (map :age) (fn ([s] (count s)) ([s i] (conj s i))) #{} [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}]) ; sdegutis |
| 20:31 | clojurebot | 3 |
| 20:31 | sdegutis | BAH, FOILED AGAIN BY JUSTIN_MSITH |
| 20:31 | sdegutis | I will never understand transduers jsut. |
| 20:31 | sdegutis | justin_smith: . |
| 20:31 | sdegutis | Hmm let me prettyify that CLojure code. rst. |
| 20:32 | justin_smith | the key to understanding transduce is to use it to answer toy problems like this one, of course |
| 20:32 | sdegutis | Hmm. |
| 20:32 | sdegutis | Your solution confuses the **** out of me. |
| 20:32 | sdegutis | I don't undrstand what the (fnn) is doing or why there' a se.t |
| 20:32 | justin_smith | ,(transduce (map :age) (completing conj count) #{} [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}]) ; improveder |
| 20:32 | clojurebot | 3 |
| 20:33 | justin_smith | (completing conj count) is cool |
| 20:33 | sdegutis | improveder? |
| 20:33 | justin_smith | sdegutis: it was improved, now it's even improveder |
| 20:33 | sdegutis | earlier today i adjusted my work email signature in an email to an old colleague i used to work with to isnead of "Technical Support" to say "Code Typer In-er" |
| 20:33 | sdegutis | er, *Codes |
| 20:33 | justin_smith | sdegutis: set because I'm just counting how many ages (perhaps that answers the wrong question but is coincidentally right?) |
| 20:34 | sdegutis | Ahh yes it's coindidental. |
| 20:34 | justin_smith | oops! |
| 20:34 | sdegutis | It's number of "repeats". |
| 20:34 | sdegutis | So, age 1 is in there 3 times, so that's 2 repeats. |
| 20:34 | justin_smith | ahh |
| 20:34 | sdegutis | Sge 2 is in there twice, so 1 repeat. |
| 20:34 | sdegutis | 3 once, 0 repeats. |
| 20:34 | sdegutis | 2 + 1 + 0 = 3 |
| 20:35 | sdegutis | Also what the heck is completing? Is CLojure just untyped Haskell now? |
| 20:36 | TEttinger | ,(doc completing) |
| 20:36 | clojurebot | "([f] [f cf]); Takes a reducing function f of 2 args and returns a fn suitable for transduce by adding an arity-1 signature that calls cf (default - identity) on the result argument." |
| 20:36 | TEttinger | oh nice |
| 20:36 | justin_smith | ,(transduce (map :age) (completing #(update % %2 (fnil inc -1)) (comp (partial apply +) vals)) {} [{:age 1} {:age 1} {:age 1} {:age 2} {:age 2} {:age 3}]) |
| 20:36 | clojurebot | 3 |
| 20:36 | sdegutis | Yeah I sitll don't understand completing after reading htat. |
| 20:36 | sdegutis | justin_smith: fnil inc -1? Haha why not dec? |
| 20:36 | sdegutis | hmm |
| 20:36 | justin_smith | sdegutis: you know that pattern of (f (reduce g coll)) |
| 20:36 | sdegutis | My brain is mal functionling tonight. |
| 20:37 | sdegutis | justin_smith: No, |
| 20:37 | sdegutis | justin_smith: you say earlier "perpetual Hasskell newb" to refer to yosuelf as, yet here we see that you think in arity and function calls! |
| 20:37 | justin_smith | sdegutis: you never do (f (reduce g coll))? that is for when you want to accumulate one kind of data, and then process it before returning it |
| 20:37 | sdegutis | I seem to think in context-dependent transformations |
| 20:37 | justin_smith | sdegutis: haskell does not have arity |
| 20:38 | sdegutis | justin_smith: not that I can recall |
| 20:38 | justin_smith | well, mostly not |
| 20:38 | sdegutis | justin_smith: (it pretends to" |
| 20:38 | justin_smith | heh |
| 20:38 | sdegutis | Hmm. Only 17 matchs for "reduce" in our code. |
| 20:38 | sdegutis | Most of them are (reduce + 0) in an ->> |
| 20:38 | sdegutis | (at the end) |
| 20:38 | justin_smith | because you don't like (apply +) ? |
| 20:39 | sdegutis | Correct. I hate apply. |
| 20:39 | sdegutis | Most of my apply is apply str or apply max 0 |
| 20:39 | amalloy | "haskell does not have arity". a strange way to put it, but i guess not crazy |
| 20:40 | justin_smith | amalloy: maybe I meant "arity is not relevant to haskell in quite the way we are talking about here" |
| 20:40 | sdegutis | amalloy: justin_smith: you could almost say it has terminal and non-terminal transformations |
| 20:40 | justin_smith | because of course it does have arity |
| 20:40 | sdegutis | it almost has like, a function can take 0 args, like foo = "bar", now foo refers to "bar", or it takes 1 arg and returns a value, or it takes 1 arg and returns a function |
| 20:41 | sdegutis | so weird |
| 20:41 | sdegutis | hey wait a minute |
| 20:41 | amalloy | i mean, the way transducers use arity is pretty gross imo. it's a way to smuggle two totally distinct functions together as one "function" with two arities |
| 20:41 | sdegutis | you tricked me into thinking about haskell |
| 20:41 | jeaye | amalloy: Yup |
| 20:42 | justin_smith | well, the single arg function should take the same kind of thing as the first arg of the two arg function |
| 20:42 | justin_smith | so there's at least some relationship there |
| 20:43 | sdegutis | Crap. Out data ia ugly |
| 20:43 | sdegutis | crap |
| 20:43 | sdegutis | justin_smith: I will study your final exapl thanks |
| 20:44 | sdegutis | This i s oncufsong! |
| 20:46 | sdegutis | justin_smith: you will become world famous if you write a tutorial on transducers |
| 20:47 | sdegutis | Nobody understands them at all and there are no tutorials on them using simple data like this example. |
| 20:47 | sdegutis | holy crap that was remarkably typo roof |
| 20:47 | justin_smith | sdegutis: hmm |
| 20:47 | sdegutis | justin_smith: and It's very difficult to dissest your code |
| 20:48 | justin_smith | dissect? |
| 20:51 | Lewix | (cond-> {:first first :last last} |
| 20:52 | Lewix | what does cond-> do |
| 20:52 | amalloy | have you tried (doc cond->) |
| 20:54 | justin_smith | sdegutis: for starters, #(update % %2 (fnil inc -1)) is your frequencies but 0 indexed instead of 1 indexed to avoid the map dec |
| 20:54 | sdegutis | justin_smith: correct, dissoect |
| 20:54 | sdegutis | justin_smith: so it's an /alternative/ to map dec, rather than "avoiding" it |
| 20:55 | sdegutis | justin_smith: i feel like map dec would make more sense in the context semantically, and should work fine with transducers |
| 20:55 | justin_smith | sdegutis: what I mean, is it does the same amount of work that frequencies does, and avoids the extra work of map dec |
| 20:55 | sdegutis | hello eah another typo-less sentence! |
| 20:55 | sdegutis | justin_smith: but at the risk of more confusion for the sake of efficiency? |
| 20:55 | justin_smith | but sure, it could be a pointless optimization |
| 20:56 | justin_smith | sdegutis: why does everyone find fnil so weird? I think it's awesome and should be used a lot. |
| 20:56 | sdegutis | justin_smith: i like fnil sure, but update % %2 confuses my face off |
| 20:56 | sdegutis | extra level of indirection that makes my understanding more didfficult |
| 20:56 | justin_smith | OK |
| 21:00 | sdegutis | Hmm. This is hard problem. |
| 21:01 | sdegutis | Our database appears unhelpfully structured. |
| 21:02 | sdegutis | ,::find |
| 21:02 | sdegutis | Haha. |
| 21:02 | clojurebot | :sandbox/find |
| 23:48 | sdegutis | Wow. |
| 23:48 | sdegutis | I just realized, you can reduce with max instead of apply! |
| 23:48 | sdegutis | ,(->> [1 3 2] (reduce max)) |
| 23:48 | sdegutis | heck yeah! |
| 23:48 | clojurebot | 3 |