2016-02-26
| 00:15 | seanirby | is there a way i can associate an nrepl server with a clojure app |
| 00:18 | seanirby | wait nvm, i may be confused |
| 03:44 | akonring | \list |
| 07:48 | freddy_ | hi friends |
| 09:04 | kungi | Can I limit the number of threads to 1 while running my tests on the JVM? |
| 09:58 | nicola1 | did cider-refresh stop working for anyone else here in the past couple of days? |
| 09:59 | nicola1 | i can't seem to load any module in the repl anymore more than once |
| 10:11 | kwladyka | nicola1 maybe you need a licence? |
| 10:11 | kwladyka | nicola1 trial end? |
| 10:13 | kwladyka | nicola1 restart intellij? update? |
| 10:14 | nicola1 | this cider https://github.com/clojure-emacs/cider |
| 10:17 | nicola1 | i think upgrading the package broke something, but pinning (from cask) the git version of cider won't work at all (cider fails to load some "cider-test" file, even if i specify cider's latest commit on which melpa's version is based on) |
| 10:20 | hexa | anyone ever tried to cider-jack-in with a lein-exec script ? |
| 10:37 | kwladyka | nicola1 i use cider with intellij, so i don't know situation in eamcs |
| 10:55 | sdegutis | Isn't this sufficient for turning Clojure rows into a CSV string? https://gist.github.com/sdegutis/55febb1065df0a85208e |
| 10:56 | sdegutis | Of course, the two "," instances could be replaced with an optional variable as well as the "\n" instance. But even then, it's, like, complete. Right? |
| 11:00 | TimMc | kungi: You mean limit the total number of threads in the JVM, or change whether your tests are multi-threaded? |
| 11:05 | kungi | TimMc: I was asking the wrong question |
| 11:05 | kungi | TimMc: I found my bug an d have to think about it for the weekend |
| 11:11 | TimMc | :-) |
| 11:18 | justin_smith | nicola1: CIDER emacs upgrading in place *always* breaks |
| 11:19 | justin_smith | nicola1: the two things that typically fix it are deleting all .elc files related to clojure stuff (including things like clojure mode that aren't strictly CIDER), and deleting everything clojure related entirely then installing the version you want |
| 11:20 | justin_smith | personally I opted out of using a tool that breaks when upgraded, but that's a personal decision of course |
| 11:24 | nicola1 | justin_smith: i've had it break a few times but it's usually resolved quickly; i'd be happy using an older version (that's why in my cask setup i specify the git commit to pull from) but in that case it fails to even start |
| 11:24 | justin_smith | nicola1: no it's not about using an older version |
| 11:24 | nicola1 | btw i'm erasing the whole .cask directory when reinstalling, no success though |
| 11:25 | justin_smith | it's that updating without deleting first breaks it |
| 11:25 | sdegutis | justin_smith: I have not had problems upgrading CIDER |
| 11:25 | justin_smith | oh |
| 11:25 | justin_smith | sdegutis: congratulations |
| 11:25 | sdegutis | justin_smith: I've had to find the right version numbers but that's about it |
| 11:25 | justin_smith | how often do you upgrade? |
| 11:25 | sdegutis | Like twice a year at this rate |
| 11:25 | sdegutis | That's about how often Cider comes out with new versions tho |
| 11:25 | justin_smith | sdegutis: that's why it is OK, it breaks when you upgrade |
| 11:25 | sdegutis | what breaks? |
| 11:25 | justin_smith | CIDER |
| 11:25 | justin_smith | random crap |
| 11:25 | justin_smith | everywhere |
| 11:26 | justin_smith | sdegutis: normally, in emacs, when a package has a new version you can just pull it in |
| 11:26 | sdegutis | ok |
| 11:26 | sdegutis | justin_smith: sorry you've had bad experiences with it :( |
| 11:26 | sdegutis | justin_smith: i normally delete the old version and pull in the new version for upgrades |
| 11:27 | justin_smith | sdegutis: I had a coworker who would turn .cljc files into clj / cljs files because he did not have a CIDER new enough to work with cljc properly and refused to update because it would break :( |
| 11:27 | sdegutis | justin_smith: that would be frustrating indeed |
| 11:29 | TimMc | justin_smith: o_o |
| 11:29 | TimMc | I feel like as long as you have paredit, further editor support is not really all that necessary. |
| 11:30 | sdegutis | so, unrelated: i'm getting closer this week to finally using component in our whole app! |
| 11:30 | sdegutis | I'm still trying to figure out how to make the router be able to be a component. |
| 11:30 | justin_smith | TimMc: that's my take as well - though auto-indent that behaves properly is also very nice |
| 11:30 | sdegutis | I like the idea of the router and the route-handler being separate components. That's how duct does it right? |
| 11:31 | justin_smith | sdegutis: the way I would do that next time is passing a hash-map containing all the handlers in the system (each component adding to it as needed) and then finally having the router pull out the functions and middlewares it uses from that map |
| 11:32 | justin_smith | I don't know duct though |
| 11:32 | sdegutis | justin_smith: hmmm interesting to have each component have its own handlers |
| 11:32 | justin_smith | or middlewares |
| 11:33 | justin_smith | each stateful thing probably has the ability to offer its state to another handler, or a handler that accesses its state (if not both) |
| 11:33 | sdegutis | justin_smith: ignore the duct comment, I just meant that's how weavejester's ring-component lib works, it allows the ring-jetty-adapter to be wrapped in a component which can take another component as the handler |
| 11:33 | justin_smith | got it |
| 11:34 | justin_smith | yeah, you could make one component that contains the http-adaptor and another that constructs the handler, or combine them. The former would be a small thing without the handler / middlware definitions. |
| 11:37 | sdegutis | hmm |
| 11:37 | sdegutis | man, so many options |
| 11:37 | sdegutis | arg |
| 11:38 | justin_smith | sdegutis: clearly we need to get 1250 people to try each option, and then tabulate the total complexity and error rate of each resulting codebase and then we can calculate the objective best choice |
| 11:39 | sdegutis | agreed |
| 11:40 | justin_smith | sdegutis: my analog watch only allows setting in the forward direction, and is 15 seconds fast, and this makes me angy |
| 11:40 | justin_smith | *angry |
| 11:40 | sdegutis | *hangry? |
| 11:40 | justin_smith | I need to spin it almost 12 whole times to get it right and even then what are the chances I get it perfect that time |
| 11:41 | justin_smith | sdegutis: also I am permanently hangry, because I decided to lose weight. This is a seperate topic and completely off topic. |
| 11:42 | sdegutis | justin_smith: why does your time need to be so accurate? are you a train conductor for a living? |
| 11:43 | justin_smith | sdegutis: wait I thought I was an engineer |
| 11:43 | sdegutis | hahahaha i get your joke |
| 11:43 | justin_smith | OK different kind of engineer my bad and maybe I should not even use that term because we are not certified and I did not go to engineering school |
| 11:43 | justin_smith | well, that's a load of my mind, thanks |
| 11:44 | justin_smith | sdegutis: realistically my watch could be 10 minutes off and nobody at work would never notice |
| 11:45 | sdegutis | justin_smith: all the clocks in our house are off from each other by many minutes and seconds |
| 11:45 | justin_smith | I'm gonna get a watch that just blinks 12:00 all the time |
| 11:46 | sdegutis | well its always 12:00 somewhere! |
| 11:48 | justin_smith | sdegutis: blinking 12:00 is a totem, capturing the spiritual energy of all misconfigured devices and software everywhere. |
| 11:53 | sdegutis | :D |
| 11:53 | sdegutis | hi |
| 11:55 | sdegutis | TIL you shouldn't use anonymous functions for things so much because they don't have metadata |
| 11:55 | sdegutis | ,(meta (fn [])) |
| 11:55 | clojurebot | nil |
| 11:55 | sdegutis | Literally impossible to determine its arglists. |
| 11:55 | justin_smith | but hey you could put meta on it |
| 11:55 | sdegutis | Oh right lol |
| 11:59 | justin_smith | ,(defn has-arity [f n] (try (apply f (repeat n nil)) true (catch clojure.lang.ArityException _ nil) (catch Throwable t true))) |
| 11:59 | clojurebot | justin_smith: Excuse me? |
| 11:59 | justin_smith | haha |
| 11:59 | justin_smith | sdegutis: the above thing is an abomination, but it correctly tells you whether a function has a given arity |
| 11:59 | justin_smith | I probably should have named it has-arity?-lol-don't-use-this |
| 12:00 | sdegutis | Actually |
| 12:00 | sdegutis | got an idea brb |
| 12:00 | justin_smith | oh no I gave sdegutis an idea I'm scared |
| 12:01 | sdegutis | you will regret it |
| 12:03 | Bronsa | sdegutis: no function has arglist metadata |
| 12:03 | Bronsa | it's been that way since 1.3.0 |
| 12:04 | sdegutis | IT WORKS |
| 12:05 | justin_smith | sdegutis: how about a fn-with-arglists macro? |
| 12:05 | sdegutis | https://gist.github.com/sdegutis/62f0b4177f01cf331218 |
| 12:05 | sdegutis | justin_smith: even better |
| 12:05 | justin_smith | oh, man... |
| 12:06 | sdegutis | it's like pretty legit kinda! |
| 12:06 | Bronsa | there's with-local-vars for that |
| 12:06 | justin_smith | sdegutis: instead of the let / gensym you could just do (let [v# (defn x# ~@stuff ...)] ...) |
| 12:06 | justin_smith | Bronsa: with-local-vars attaches the kind of metadata defn would? |
| 12:06 | sdegutis | justin_smith: oh right! |
| 12:07 | sdegutis | I forgot x# does gensym for me |
| 12:07 | Bronsa | justin_smith: no, right |
| 12:07 | justin_smith | sdegutis: I MEAN YOU WERE USING IT RIGHT THERE ALREADY COME ON |
| 12:07 | justin_smith | get it together, man |
| 12:08 | sdegutis | updated |
| 12:08 | sdegutis | https://gist.github.com/sdegutis/62f0b4177f01cf331218 |
| 12:09 | sdegutis | this is probably the cleverst thing ill ever accomplish in clojure |
| 12:10 | justin_smith | sdegutis: (defmacro fn+ [& stuff] `(doto (defn n# ~@stuff) (partial ns-unmap *ns*))) |
| 12:10 | justin_smith | sdegutis: tested in my repl, works |
| 12:10 | sdegutis | oh man |
| 12:10 | sdegutis | I was just about to type "i kinda wanna find out how to use doto on this thing) |
| 12:10 | justin_smith | now you know! |
| 12:11 | TimMc | That partial doesn't need an extra set of parens? |
| 12:11 | justin_smith | TimMc: nope |
| 12:11 | justin_smith | err... |
| 12:11 | TimMc | you sure? |
| 12:11 | justin_smith | TimMc: you are correct! |
| 12:12 | justin_smith | TimMc: the ns-unmap silently misbehaved |
| 12:12 | sdegutis | justin_smith: wait doesnt that require comp meta :name too? |
| 12:12 | sdegutis | or are you able to just give that a var? |
| 12:12 | sdegutis | cuz it says 'sym' in the docstring |
| 12:12 | sdegutis | (doc ns-unmap) |
| 12:12 | clojurebot | "([ns sym]); Removes the mappings for the symbol from the namespace." |
| 12:12 | justin_smith | sdegutis: I think it does |
| 12:12 | justin_smith | sdegutis: yes, fixing |
| 12:12 | sdegutis | yeah so that shuldnt work and doesnt work here |
| 12:13 | sdegutis | i trieda comp version but i think i got it wrong cuz it no worky |
| 12:14 | sdegutis | dang this tricky |
| 12:15 | justin_smith | defmacro fn+ [& stuff] `(doto (defn n# ~@stuff) (->> meta :name (ns-unmap *ns*)))) ; TimMc sdegutis fixed |
| 12:16 | justin_smith | thanks for the quality QA |
| 12:16 | sdegutis | oh man so smart |
| 12:16 | sdegutis | justin_smith: wins |
| 12:18 | sdegutis | justin_smith: https://gist.github.com/sdegutis/62f0b4177f01cf331218 |
| 12:18 | sdegutis | this is just terrible |
| 12:18 | sdegutis | why would you contribute to such a terrible invention justin_smith |
| 12:18 | sdegutis | and TimMc |
| 12:18 | sdegutis | how terrible of a macro |
| 12:18 | sdegutis | my goodness |
| 12:19 | sdegutis | so awesome |
| 12:21 | justin_smith | sdegutis: it would be nice if instead the thing that attached metadata was a separate composible function |
| 12:21 | justin_smith | so instead of making a var just for the side effect of getting the metadata we want, we could pull that metadata-generator in |
| 12:21 | justin_smith | kind of like how destructure is just a function you can call in your macro if you want it |
| 12:22 | sdegutis | justin_smith: that would be impossible tho unless your fn was quoted |
| 12:22 | sdegutis | unless.. |
| 12:23 | justin_smith | sdegutis: look at the source to defn, most of the code is just building the metadata map |
| 12:23 | justin_smith | sdegutis: if that happened in a separate function, we could use it |
| 12:23 | TimMc | open a jira ;-) |
| 12:23 | justin_smith | TimMc: seriously considering it! |
| 12:24 | sdegutis | justin_smith: i feel 100% confident everyone will be against the idea |
| 12:24 | justin_smith | sdegutis: oh I know it, but it's the principle of the thing! |
| 12:25 | sdegutis | justin_smith: ok well if you post it then link me ill +1 it |
| 12:25 | sdegutis | although itll probably be canceled out by amalloy's -1'ing it |
| 12:26 | justin_smith | sdegutis: he has a bot that just -1s anything you +1 |
| 12:29 | Bronsa | caveat is that it'll only do that on bad ideas |
| 12:32 | sdegutis | Bronsa: like he said |
| 12:39 | sdegutis | I like how nicely assoc works with defrecord. |
| 12:39 | sdegutis | Nice job guys. |
| 12:47 | sdegutis | Why is this? |
| 12:47 | sdegutis | ,(do (definterface Bar) (defrecord Foo [quux] Bar) ((juxt identity type) (dissoc (Foo. 2) :quux))) |
| 12:47 | clojurebot | [{} clojure.lang.PersistentArrayMap] |
| 12:47 | sdegutis | That's unexpected to me. I'd assume it would try to retain the type. |
| 12:48 | sdegutis | Even this: |
| 12:48 | sdegutis | ,(do (definterface Bar) (defrecord Foo [quux zappa] Bar) ((juxt identity type) (dissoc (Foo. 2 3) :quux))) |
| 12:48 | clojurebot | [{:zappa 3} clojure.lang.PersistentArrayMap] |
| 12:48 | TimMc | When you remove a basis key on a record, it stops being a record. |
| 12:49 | justin_smith | sdegutis: yeah, that's been the expected behavior for a while now - I'm thinking at least since 1.5? maybe before that even? |
| 12:49 | sdegutis | Is that desired behavior? |
| 12:49 | TimMc | "expected" |
| 12:49 | justin_smith | definitely explicit - I remember it changing |
| 12:49 | Bronsa | Bar is completely useless to your example |
| 12:49 | sdegutis | Yeah I carefully avoided using the word "expected" in my last question. |
| 12:49 | sdegutis | It has disparity with assoc: |
| 12:50 | Bronsa | justin_smith: I think that's actually always been the case, not a 1.5 change |
| 12:50 | sdegutis | ,(do (definterface Bar) (defrecord Foo [quux] Bar) ((juxt identity type) (assoc (Foo. 2) :quux nil))) |
| 12:50 | clojurebot | [#sandbox.Foo{:quux nil} sandbox.Foo] |
| 12:50 | Bronsa | sdegutis: rationale is that by being X + something else you're still X, by being X - parts of X you're no longer X |
| 12:50 | sdegutis | Bronsa: hmm I can see that |
| 12:51 | sdegutis | still, it feels wrong |
| 12:51 | Bronsa | some would argue not behaving this way feels wrong |
| 12:51 | TimMc | Where it gets gross is when you want to break apart a map and reconstruct it. |
| 12:51 | TimMc | (into (empty m) (for [[k v] m] ...)) works great to preserve type for most maps, but not for records |
| 12:51 | Bronsa | where it gets gross is when (empty some-record) throws but (dissoc some-record record-key) doesn't |
| 12:52 | justin_smith | (assoc instance :field :temporarily/removed) |
| 12:52 | justin_smith | haha |
| 12:52 | TimMc | Aw man, empty throws on records? Didn't know that. |
| 12:52 | Bronsa | yeah |
| 12:52 | TimMc | yuck yuck yuck |
| 12:52 | Bronsa | it feels really wrong that empty doesn't behave like reduce dissoc (keys record) |
| 12:52 | sdegutis | TimMc: that makes more sense though, because you're reconstructing a map from only the fields of a record, without "re-attaching" the metadata |
| 12:53 | sdegutis | TimMc: whereas dissoc seems more like removing a field while preserving the rest of the thing |
| 12:53 | Bronsa | I'd rather have either both dissoc/empty throw or have them both fallback on normal maps |
| 12:53 | Bronsa | there's no good reason why (defrecord X []) (empty (X.)) shouldn't work |
| 12:53 | sdegutis | naturally its far too late to make any changes like that since it would break every clojure app ever |
| 12:54 | Bronsa | Don't think so |
| 12:54 | Bronsa | if something hasn't worked, making it work shouldn't break anything |
| 12:55 | Bronsa | and if you're depending on (f x) throwing an UnsupportedOperationException, your code deserves to be broken |
| 12:55 | justin_smith | Bronsa: unless someone was intentionally throwing errors as flow control, and if they did that, they deserve broken code. |
| 12:55 | justin_smith | right, right |
| 12:55 | Bronsa | justin_smith: they deserve more than that |
| 12:55 | Bronsa | unless they're doing that as an optimization :P |
| 12:56 | Bronsa | but in that case, you're still not going to throw an UOE |
| 12:56 | Bronsa | justin_smith: IIRC core.match uses exceptions as flow control for non-local returns |
| 12:57 | justin_smith | ick |
| 12:57 | sdegutis | Bronsa: you planning to file a jira ticket? |
| 12:57 | Bronsa | no |
| 12:57 | sdegutis | ok i might then |
| 12:57 | Bronsa | justin_smith: it's surprisingly fast |
| 12:57 | justin_smith | Bronsa: I'm sure it was a perf improvement over the sane option, but still, ick |
| 12:58 | Bronsa | justin_smith: you're either going to use recursion or exceptions if you want to backtrack in clojure |
| 12:58 | Bronsa | since there's no goto |
| 12:58 | Bronsa | or explicit return |
| 12:58 | Bronsa | (both or which exist in java) |
| 12:59 | Bronsa | (both of which are incredibly useful for this kind of stuff) |
| 12:59 | justin_smith | that's true |
| 13:00 | justin_smith | and also sad, it would be nice to have a cleaner thing like continuations |
| 13:00 | Bronsa | ¯_(ツ)_/¯ |
| 13:00 | Bronsa | I honestly don't think continuations are much cleaner thatn gotos |
| 13:00 | Bronsa | than* |
| 13:01 | justin_smith | well, they are first class, but I guess it's not so hard to make a goto first class and juggle lexical environments to go with them... |
| 13:03 | sdegutis | Bronsa: what about the continuation monad? |
| 13:19 | gfredericks | if you were using test.check's recursive generator |
| 13:20 | gfredericks | (gen/recursive-gen some-collection-generator-fn some-scalar-generator) |
| 13:20 | gfredericks | would you expect it to ever generate pure scalars, or only collections of varying depths? |
| 13:23 | gfredericks | also does anybody use freenode from erc and how can I get past that weird auth thing it does now. |
| 13:25 | hiredman | gfredericks: well, only generating collections of various depths would make it weird that you passed in a scalar generator |
| 13:25 | gfredericks | hiredman: I mean for (gen/recursive-gen gen/vector gen/boolean), it could generate [true [false false]] but never true or false |
| 13:25 | hiredman | right |
| 13:25 | gfredericks | so the scalar generator does get used either way |
| 13:26 | hiredman | if you are have a tree generator, would you ever generate just a leaf |
| 13:26 | gfredericks | yeah, same question |
| 13:27 | gfredericks | I'm hoping there'll be a compelling example of some sort :) |
| 13:27 | gfredericks | I think it's relatively easier to get one from the other |
| 13:27 | gfredericks | s/easier/easy/ |
| 13:28 | gfredericks | http://dev.clojure.org/jira/browse/TCHECK-83 |
| 13:28 | gfredericks | I think I created this when I was making a json generator and got surprised when it didn't generate any scalars; but on the other hand in some json contexts pure scalars are considered invalid I think |
| 13:29 | hiredman | if you where testing some kind of recursive tree traversal, depending on the traversal code, you might want to test hitting a leaf |
| 13:32 | hiredman | although, if you are thinking of it as a tree kind of data structure, a lot of those have lots of rules associated with their structure, so you can't just generate them recursively willy nilly |
| 13:33 | gfredericks | rules that are only valid at the root in particular? |
| 13:34 | gfredericks | it might make sense to restrict this to use cases where you can generate things recursively willy nilly |
| 13:34 | gfredericks | given the signature of the function |
| 13:36 | hiredman | a tree structure I might want to test would be, I dunno, a red black tree, but those have rules about what nodes can be children of other nodes, and are restricture to two children per node |
| 13:36 | hiredman | yeah, only things willy nilly |
| 13:36 | gfredericks | yeah, I think that would require something more general/customizable |
| 13:36 | hiredman | so like json or edn |
| 13:36 | gfredericks | right |
| 13:37 | gfredericks | speaking of trees it is Bronsa |
| 13:37 | hiredman | an edn generator I would definitely expect to hit leaves |
| 13:38 | gfredericks | you could also argue that including leaves is better for test.check uses in particular to avoid accidentally undertesting |
| 13:38 | gfredericks | I think adapting it to not do leaves is as simple as calling (collection-gen-fn (gen/recursive-gen collection-gen-fn scalar-gen)) |
| 13:42 | gfredericks | okay I'm convinced |
| 13:42 | gfredericks | everybody brace for minor breaking changes |
| 13:42 | hiredman | a clojure code generator that did included generating type hints would be nice |
| 13:42 | gfredericks | is that related? |
| 13:43 | hiredman | not really |
| 13:43 | gfredericks | okay cool just checking |
| 13:43 | gfredericks | thought I was missing something |
| 13:43 | gfredericks | has somebody written a general code generator somewhere? |
| 13:47 | amalloy | justin_smith: never fear, your has-arity? is in fact not correct |
| 13:47 | justin_smith | amalloy: awesome, what's the mistake? |
| 13:48 | amalloy | try it on (fn [] (inc 1 2 3 4)) |
| 13:48 | amalloy | it'll claim not to have arity 0, but of course the problem is that in lacks arity 4 |
| 13:48 | justin_smith | oh, of course |
| 13:48 | justin_smith | cool, I feel much better now |
| 13:49 | sdegutis | Some aspects of Component really confuse me. Is this normal? |
| 13:49 | amalloy | it's the same reason you get bogus errors for stuff like (defmacro fo [] (inc 1 2 3 4)) |
| 13:49 | amalloy | ,(defmacro foo [] (inc 1 2 3 4)) |
| 13:49 | clojurebot | #error {\n :cause "Wrong number of args (4) passed to: core/inc--inliner--4489"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "clojure.lang.ArityException: Wrong number of args (4) passed to: core/inc--inliner--4489, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type clojure.lang.ArityException\n :message "Wrong numb... |
| 13:50 | amalloy | well, apparently inc is smarter now |
| 13:50 | amalloy | ,(defmacro foo [] (seq 1 2 3 4)) |
| 13:50 | clojurebot | #'sandbox/foo |
| 13:50 | amalloy | ,(foo) |
| 13:50 | clojurebot | #error {\n :cause "Wrong number of args (2) passed to: core/seq--4357"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (2) passed to: core/seq--4357"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6781]}]\n :trace\n [[clojure.lang.Compiler macroexpand1 "Compiler.java" 6781]\n [clojure.lang.Compiler macroexpand "Compiler.java" 6837]\n [clojure.lang.Com... |
| 13:50 | justin_smith | haha |
| 13:50 | amalloy | ,(defmacro foo [] (seq)) |
| 13:50 | clojurebot | #'sandbox/foo |
| 13:50 | amalloy | ,(foo) |
| 13:50 | clojurebot | #error {\n :cause "Wrong number of args (-2) passed to: core/seq--4357"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (-2) passed to: core/seq--4357"\n :at [clojure.lang.Compiler macroexpand1 "Compiler.java" 6781]}]\n :trace\n [[clojure.lang.Compiler macroexpand1 "Compiler.java" 6781]\n [clojure.lang.Compiler macroexpand "Compiler.java" 6837]\n [clojure.lang.C... |
| 13:52 | gfredericks | I got to write a function called random-psuedofactoring: https://www.refheap.com/115236 |
| 13:53 | cfleming | {blake} TEttinger3: Sorry for the problems. I haven't had time to reproduce with that project.clj yet, but generally you have to add the deps to the project.clj, and then use the Refresh Leiningen Projects action, which you can either search for or use the lein toolwindow. |
| 13:54 | amalloy | gfredericks: returns, not generates? that makes it sound to me like it just keeps one collection lying around forever, and always gives that one |
| 13:54 | {blake} | cfleming: I did not know there was a lein toolwindow! Cool! |
| 13:54 | gfredericks | amalloy: well it's in the context of test.check generators, so hopefully that means the more natural interpretation is that it doesn't return a generator |
| 13:54 | gfredericks | but that there might be a better wording |
| 13:55 | gfredericks | I think a lot of docstrings for functions that return generators just say "Generates ..." |
| 13:55 | amalloy | it seems like this could be a generator if you wanted it to, right? am i wrong, or is there a reason not to do that? |
| 13:56 | gfredericks | amalloy: yeah it could be one that's just not what I needed it for |
| 13:57 | sdegutis | im back |
| 13:57 | amalloy | i understand you owe me a link to something so i can downvote it, sdegutis |
| 13:57 | sdegutis | amalloy: oh yeah hold on |
| 13:57 | sdegutis | amalloy: https://gist.github.com/sdegutis/62f0b4177f01cf331218 |
| 13:58 | sdegutis | amalloy: its not yet turned into a mailing list discussion but justin_smith had toyed around with the idea of extracting the metadata-generating code from defn and turning it into a stand-alone function (which defn then uses) so it can be used independently similar to how 'destructure' works |
| 13:58 | sdegutis | amalloy: anyway please downvote my gist |
| 13:59 | amalloy | oh. you mean like clojure.tools.macro.name)with-attributes? |
| 13:59 | sdegutis | amalloy: justin_smith /cc |
| 13:59 | sdegutis | amalloy: not quite, cuz fn+ here generates :arglists for you |
| 14:00 | sdegutis | amalloy: that was the main reason i invented fn+ today |
| 14:01 | amalloy | well, it's a cute trick anyway |
| 14:02 | sdegutis | thanks! |
| 14:02 | amalloy | github doesn't have downvotes, so i forked and deleted it |
| 14:02 | sdegutis | amalloy: haha or yu could comment with -1 |
| 14:02 | sdegutis | :-1: technically |
| 14:03 | sdegutis | wow u wasnt kiddin https://gist.github.com/amalloy/05b64a9418fd318b7916/revisions |
| 14:04 | sdegutis | amalloy: actually your revision should just contain `(meta (fn [x] (inc x)))` so its made clear that your fork results in less functionality than the thing you forked |
| 14:04 | sdegutis | :D |
| 14:06 | justin_smith | amalloy: my thought was that it would be nice to be able to generate the same metadata properties that defn would, or that def would, without having to call def/defn, so the specific metadata generation could be refactored into a function - name-with-attributes is nice but doesn't do all the metadata defn does, and would need to be manually updated for each change to core's defn |
| 14:08 | sdegutis | justin_smith: what would such an api look like in action? |
| 14:09 | sdegutis | justin_smith: (let [f (fn [])] (generate-metadata f)) ? |
| 14:09 | sdegutis | justin_smith: or (generate-metadata (fn [])) ? |
| 14:11 | justin_smith | sdegutis: maybe something like (defmacro fn+ [& body] `(with-meta (fn ~@body) ~(gen-meta body))) |
| 14:11 | justin_smith | sdegutis: but I realized the annoying thing about making a function that defn would use to generate its macro - you can't use defn to define that helper :) |
| 14:13 | amalloy | or syntax-quote |
| 14:13 | justin_smith | amalloy: oh yes, of course |
| 14:14 | justin_smith | that would also be an annoyance |
| 14:16 | {blake} | I have a vector of vectors I'm using to make my web-page, and now (using React) I have to update a value in that vector of vectors. |
| 14:17 | {blake} | [[{stuff}{stuff}{stuff :control {:cell-name "target" :value "changethis"}}][next row...]] |
| 14:18 | justin_smith | {blake}: are you using react directly or with some clojurescript wrapper? |
| 14:18 | {blake} | justin_smith: reagent |
| 14:18 | amalloy | don't use vectors to store stuff you want to look up indexed by some key |
| 14:18 | justin_smith | {blake}: don't change the vector, use a function call to generate the vector |
| 14:18 | {blake} | amalloy: Well, I didn't know I was going to have to. |
| 14:18 | amalloy | instead of searching through a bunch of vectors, wouldn't it be lovely to have a map? {"target" ...} |
| 14:19 | justin_smith | amalloy: this is hiccup |
| 14:19 | justin_smith | so generate the hiccup, instead of using a literal |
| 14:19 | amalloy | if it were hiccup you would have a seq of vectors, perhaps. never a vector of vectors |
| 14:19 | justin_smith | {blake}: or do you mean some source data? if so, yeah do what amalloy says |
| 14:19 | {blake} | OK, so, yeah, I've thought of "change it to a map" and "regenerate the vector". Just seems like a lot of work. |
| 14:20 | justin_smith | {blake}: less work than arbitrary updates in a vector I'd think |
| 14:21 | {blake} | So, the deal is, my server sends me data that I used to make an entry page for the user, including pre-populating some of those values. |
| 14:21 | {blake} | (At the user's request.) |
| 14:21 | {blake} | I'd been putting those in "defaultValue". |
| 14:21 | {blake} | Only to discover that reagent only uses defaultValue first time out. |
| 14:21 | {blake} | When the component is first rendered. So I put it in value. |
| 14:22 | {blake} | But if I put it in value, all my components gotta be "controlled". |
| 14:22 | {blake} | And to make them "controlled", I gotta be able to update that structure the server sends. |
| 14:22 | {blake} | So. |
| 14:22 | {blake} | Crap. |
| 14:24 | justin_smith | {blake}: send the data from the server in a form you can easily access, and generate the structure you need on the frontend from that |
| 14:25 | justin_smith | so yeah, a map instead of vector, like amalloy said |
| 14:25 | {blake} | Or... |
| 14:25 | {blake} | Maybe send two structures. Since the only thing that's going to change is a small subset of controls->values, keep one for the structure of the whole page, and a little part for the react stuff. |
| 14:26 | justin_smith | but it's easier to generate the right vector from a map than it is to update a vector correctly |
| 14:26 | justin_smith | if you need a vector, make it out of maps |
| 14:28 | rhg135 | Juxt is useful for that |
| 14:28 | justin_smith | indeed! |
| 14:31 | gfredericks | ~juxt |
| 14:31 | clojurebot | juxt is usually the right answer |
| 14:31 | gfredericks | ~juxt |
| 14:31 | clojurebot | juxt is a little hard to grok but it's the best thing ever |
| 14:31 | gfredericks | ~juxt |
| 14:31 | clojurebot | juxt is usually the right answer |
| 14:32 | {blake} | Lotta juxt propaganda goin' on. |
| 14:32 | tcrayford_____ | juxt shut up already |
| 14:34 | {blake} | I have a nice thing on the server where it's going through the cells of the spreadsheet and creating a vector. |
| 14:35 | {blake} | A vector of vectors. Rows and columns. Then I just go through this on the client side, same way. |
| 14:35 | {blake} | I guess I could key it as [col row] and make a flat map. |
| 14:35 | sdegutis | just and comp are cool |
| 14:36 | sdegutis | just don't expect them to notice rebound vars unless you explicitly pass vars |
| 14:36 | sdegutis | (comp foo/bar foo/quux) ;; redefine #'foo/bar or #'foo/quux and it will never notice |
| 14:36 | sdegutis | (comp #'foo/bar #'foo/quux) ;; this will though |
| 14:36 | sdegutis | This works because you can call vars as functions if you try hard enough. |
| 15:04 | sdegutis | Hello. |
| 15:04 | sdegutis | What's your recommended way of sharing many common immutable parameters between a group of functions? |
| 15:05 | sdegutis | The way I'm currently using is to have each of them take a map as its first parameter with each of these values at common keys. |
| 15:50 | rhg135 | But then you can't compose them elegantly, I guess it's not as bad |
| 16:25 | justin_smith | clearly what we need is some crazy hack using metadata to imitate monads |
| 16:25 | justin_smith | (that was in response to rhg135 but it's universally true as well, of course) |
| 16:56 | {blake} | Who doesn't love crazy hacks? |
| 16:56 | justin_smith | in fact I sometimes suspect I *am* a crazy hack |
| 16:58 | amalloy | isn't using metadata to imitate monads like using...noodle soup to imitate 4chan? they are just totally disjoint separate things |
| 16:59 | CaptainLex_ | Well that's what makes the hack /crazy/ |
| 17:00 | justin_smith | amalloy: in the sense that a monad can track a separate immutable value implicitly carried forward in each call, which could hackily be a metadata passed along on values |
| 17:00 | justin_smith | or maybe I'm just talking nonsense again |
| 17:15 | rhg135 | justin_smith: I just pass everything in one mega map, maybe a magic monad is better |
| 17:21 | gfredericks | oh man; I have a memory perf test in test.check that runs fine on the jvm but blows the stack (?) in cljs |
| 17:21 | gfredericks | #object[RangeError RangeError: Maximum call stack size exceeded] |
| 17:22 | gfredericks | I guess either nodejs has a smaller default stack than the jvm or cljs uses more stack frames than clj or both? |
| 17:27 | CaptainLex_ | gfredericks: The former wouldn't surprise me one bit |
| 17:28 | gfredericks | this shouldn't even be a particularly stacky usage :/ |
| 17:28 | gfredericks | still trying to get a proper stack trace |
| 17:30 | gfredericks | the internet says that e.stack is something useful but for me it's undefined :/ |
| 17:30 | gfredericks | so I'm not sure how to figure out what's so stacky about this |
| 18:04 | rhg135 | that would be the reader monad now that I think it |
| 18:45 | srruby | I want to do something like: lein ring server -env=testing To indicate that the server is running in a testing environment. Thanks, John |
| 18:46 | CaptainLex_ | srruby: I don't know about any special ring stuff, but can't you just pass environment variables to the JVM like normal? |
| 18:46 | CaptainLex_ | Which I don't have any real experience with either |
| 18:53 | srruby | CaptainLex_ : I guess I'll use (export FOO=bar; lein ring server) |
| 18:54 | CaptainLex_ | Or you could ($FOO=bar lein ring server) if you didn't want to mess with your normal environment |
| 18:54 | CaptainLex_ | Or you could even write a shell script to launch lein with the variables set according to arguments, if the syntax annoyed you |
| 19:17 | srruby | How can I change a string into a "reader" object ? |
| 19:19 | CaptainLex_ | srruby: What are you trying to do? |
| 19:20 | srruby | CaptainLex: I have some code that reads from a file and processes the data. I want to test the code with a string. |
| 19:21 | amalloy | with-in-str |
| 19:21 | srruby | Something like new Reader(new stringBuffer("test data") |
| 19:21 | srruby | amalloy: Thanks |
| 19:25 | srruby | O |
| 19:44 | srruby | OK. This is what I came up with. |
| 19:44 | srruby | (defn reader-from-string[s] |
| 19:44 | srruby | (new java.io.BufferedReader (new java.io.InputStreamReader (new java.io.ByteArrayInputStream (.getBytes s))))) |
| 19:44 | srruby | (slurp (reader-from-string "a,b,c,d")) |
| 19:45 | srruby | seems clumsy |
| 19:46 | rhg135 | StringReader exists |
| 19:50 | srruby | OK. This works. (with-in-str "hello" (parse-data (clojure.java.io/reader *in*))) |
| 19:50 | srruby | That is what I was looking for. |
| 19:53 | srruby | (parse-data (new java.io.StringReader "a,b,c,d"))) |
| 19:54 | srruby | rhg135: Thanks. (new java.io.StringReader "foo") was what I was looking for. |
| 19:54 | rhg135 | np |
| 19:55 | amalloy | was there something wrong with (with-in-str "a,b,c,d" (parse-data *in*))? |
| 19:56 | rhg135 | ,(class *in*) |
| 19:56 | clojurebot | clojure.lang.LineNumberingPushbackReader |
| 19:56 | rhg135 | oh |
| 19:57 | amalloy | ,(with-in-str "a,b,c,d" (class *in*)) |
| 19:57 | clojurebot | clojure.lang.LineNumberingPushbackReader |
| 19:58 | rhg135 | I assumed it'd be a inputstream given his code |
| 20:01 | amalloy | ,(class System/in) |
| 20:01 | clojurebot | java.io.BufferedInputStream |
| 20:01 | rhg135 | hmm |
| 20:45 | n0n3such | hey |
| 22:22 | hodwik | Are LISPs hard to read because I'm not used to them, or are they just harder to read? |
| 22:23 | tolstoy | I find them easier to read, but I suspect Clojure's use of brackets, and syntax highlighting improve that significantly. |
| 22:25 | hodwik | I guess I find it easier to get a sense of what the code is doing at a fine-grained level |
| 22:25 | hodwik | but I'm having a hard time stepping back and seeing the big picture |
| 22:25 | hodwik | because all of the pieces are so low-level logically |
| 22:26 | tolstoy | Coming from Java? |
| 22:26 | hodwik | Python & Java |
| 22:28 | tolstoy | A friend just went through a similar thing. For him, realizing that the functions were verbs seems to have helped a lot (his words not mine). |
| 22:30 | hodwik | Hmm, I'm not sure I follow. |
| 22:31 | tolstoy | Clojure functions, generally, take data as parameters and transform it into another form of data. |
| 22:31 | tolstoy | So, map, reduce, filter, etc. |
| 22:31 | tolstoy | So, just read the function names and get a sense of what they're doing. |
| 22:33 | hodwik | I've gotten that far |
| 22:33 | hodwik | I'm just not sure how to skim code, so to speak |
| 22:33 | hodwik | to get the big ideas |
| 22:33 | hodwik | Everything looks equally important, in a way |
| 22:34 | TEttinger | ah, yeah. an interesting thing is that what would be a few lines in java, with a for loop for instance, is typically a one-line call in clojure to a collection-based fn |
| 22:35 | hodwik | So then maybe skimming code is not the right strategy to read code in clojure? |
| 22:35 | TEttinger | like map vs. creating a new ArrayList and appending to it in a for(Thing thing : myList) {} way |
| 22:35 | tolstoy | That's what I do. |
| 22:35 | TEttinger | clojure code tends to be slightly wider and much less vertically stretched |
| 22:35 | tolstoy | But I skim by first reading the names and then maybe glancing at the function body to see if there's filter, reduce, map, or something. |
| 22:36 | TEttinger | yeah, similar here |
| 22:36 | tolstoy | Like this: https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/middleware/params.clj |
| 22:36 | tolstoy | I start at the bottom and go up. |
| 22:37 | hodwik | Interesting, why read from the bottom? |
| 22:37 | tolstoy | That's usually where the "main" function is, with all the ones above it in support position. |
| 22:38 | TEttinger | it is a big benefit to know if you're dealing with a many-to-many fn (map and mapcat are commonly used like this, filter usually), a many-to-one (usually reduce, not always), a one-to-many (iterate, certain uses of loop, for can be used something like this), etc. |
| 22:38 | tolstoy | Then I quickly scan up and see, assoc-query-params, where I can see he's parsing the querystring from the request (:query-string this or that). |
| 22:39 | tolstoy | I can see that he's parsing the query string into a key/value and associating it to the request as two keys. The rest the functions: *shrug*. |
| 22:40 | tolstoy | Keywords are pretty nice because you can kinda trace the transformation of data by scanning for them. |
| 22:40 | hodwik | Oh, that |
| 22:41 | hodwik | 's an interesting strategy. |
| 22:41 | tolstoy | I didn't know I had that strategy until looking at that code. ;) |
| 22:44 | hodwik | Do you find yourself using other people |
| 22:44 | hodwik | 's code/libs less when writing in Clojure? |
| 22:45 | tolstoy | Sort of. |
| 22:45 | tolstoy | For me, the biggest difference between Clojure and your avg Java/Python/C# approaches is the separation of data from functions. |
| 22:46 | tolstoy | For instance, with that "ring" web stuff, you realize that it's just a wide variety of functions that take a "request" map and produce a "response" map (mainly). |
| 22:47 | tolstoy | Once you get that, you can skim the code if, say, you wonder how it handles cookies, or query strings, or a response with a body of type "stream". |
| 22:47 | tolstoy | So, the "big idea" you mentioned is getting that main idea, the request map. |
| 22:49 | tolstoy | And given that the vast bulk of Clojure code is just maps and lists, you don't need to look for type names (like domain objects). |
| 22:50 | tolstoy | So, you don't look for things like User, but, instead, for functions that seem to operate on users, like, (auth? user) or (valid? db-conn email password) and so on. |
| 22:50 | tolstoy | So, yeah, from the point of view of OO, it can seem like undifferentiated soup. ;) |
| 22:53 | hodwik | So with Python and Java, I find Python much more expressive. However, I also find it much more difficult to read my code 6 months later than with Java. As if, all that boilerplate just acts as a visual cue. |
| 22:53 | hodwik | My concern is that Clojure is going to go farther in that direction. |
| 22:54 | hodwik | I take it that you do not experience that relationship between expressiveness and readibility, if you find clojure to be more readable? |
| 22:56 | tolstoy | Clojure's the first language where, when I didn't understand a docstring, I clicked the "show source" link and that actually helped. |
| 22:57 | tolstoy | I do find it more readable, I think, because everything's in one place. With Java, I have to use Intellij so I can bop around because any given thing seems to involve dozens of objects. |
| 23:02 | hodwik | I was thinking it'd be pretty cool to have syntax highlighting that does every pair of parens a different color. Does such a thing exist? |
| 23:03 | tolstoy | rainbox delimiters |
| 23:03 | tolstoy | rainbow, sorry. |
| 23:03 | hodwik | Awesome. Is it useful/popular? |
| 23:04 | tolstoy | I think it's reasonably popular. What's your editor? |
| 23:05 | hodwik | Well, I've got Emacs setup, but I wouldn't call it my editor, but that's where I'm working on Clojure right now. |
| 23:06 | tolstoy | https://github.com/Fanael/rainbow-delimiters |
| 23:06 | tolstoy | Alas, no pictures on that page. |
| 23:07 | hodwik | Thanks |
| 23:07 | hodwik | I'm checking out some screenshots, it looks a bit more distracting than I thought it would |
| 23:08 | tolstoy | I find it so. |
| 23:08 | amalloy | hodwik: ideally you should be paying attention to the indentation, not the parens |
| 23:08 | hodwik | Is focusing on the parens the wrong way to go about it. That is, do you read the "verbs" more than the parens? |
| 23:08 | tolstoy | Yeah, I dim my parens, actually. |
| 23:08 | tolstoy | And use paredit to manage them. |
| 23:08 | amalloy | parens are for the computer |
| 23:09 | tolstoy | Anyone happen to know how to query specific network adapters via command line on windows? |
| 23:09 | hodwik | Ah, I think stanislav datskovskiy told me that |
| 23:09 | hodwik | I had forgotten |
| 23:24 | macrolicious | I'm getting a FileNotFoundException: Could not locate seesaw/core__init.class or seesaw/core.clj on classpath in spite of having :dependencies [[org.clojure/clojure "1.5.1"] |
| 23:25 | hiredman | seesaw is not part of clojure |
| 23:25 | hiredman | so saying you depend on clojure doesn't mean you get seesaw |
| 23:51 | totalnes` | hiredman: oops, I meant to say I had: :dependencies [[org.clojure/clojure "1.5.1"] [seesaw "1.4.4"]]) |
| 23:51 | totalnes` | last line didn't paste |
| 23:51 | totalnes` | in my src directory I have seesaw. |
| 23:58 | hiredman | totalnes`: what do you mean by "in my src directory I have seesaw." ? |
| 23:59 | hiredman | in the interest of short circuiting this, you likely added the dep to project.clj and didn't restart your repl |