2015-02-26
| 00:07 | mercwithamouth | does anyone here prefer luminus to compojure? is luminus an alright choice or does it completely take over? |
| 00:08 | ddellacosta | mercwithamouth: I think that it's hard to compare them--luminus uses compojure as far as I know, just includes a lot more and acts as more of a comprehensive framework |
| 00:09 | ddellacosta | mercwithamouth: and I think you can see that it is opinionated about certain choices, but I can't speak to how hard it is to override certain things in luminus, sorry...maybe someone else can |
| 00:31 | mercwithamouth | ddellacosta: fair enough. i think i'm fine with just compojure. though i'm sure luminus isn't as overbearing as rails |
| 00:31 | l1x | ' (for [a [0 1] b (range 10)] [a b]) |
| 00:31 | ddellacosta | mercwithamouth: yeah, having been a Rails dev for a while I think it's probably safe to say that--luminus is much more a set of composed libs vs. how monolithic Rails seems |
| 00:35 | mercwithamouth | goos to know |
| 00:38 | niac | (walk (fn [[k v]] [k (* 10 v)]) identity {:a 1 :b 2 :c 3}) |
| 00:39 | niac | can it rewrite #() |
| 00:39 | niac | instead of fn |
| 00:43 | ddellacosta | niac: here's one way: |
| 00:43 | ddellacosta | &(clojure.walk/walk #(vector (key %) (* 10 (val %))) identity {:a 1 :b 2 :c 3}) |
| 00:43 | lazybot | ⇒ {:c 30, :b 20, :a 10} |
| 00:43 | ddellacosta | not sure that's much nicer |
| 00:44 | ddellacosta | or, |
| 00:44 | ddellacosta | &(clojure.walk/walk #(let [[k v] %] [k (* 10 v)]) identity {:a 1 :b 2 :c 3}) |
| 00:44 | lazybot | ⇒ {:c 30, :b 20, :a 10} |
| 00:45 | ddellacosta | but considering the fn version is less verbose than these, I wouldn't bother |
| 00:45 | l1x | &(for [a [0 1] b (range 4)] [a b]) |
| 00:45 | lazybot | ⇒ ([0 0] [0 1] [0 2] [0 3] [1 0] [1 1] [1 2] [1 3]) |
| 00:47 | niac | ddellacosta: maybe the fn is the best way |
| 00:48 | ddellacosta | niac: I mean, it all depends on context. What you're trying is obviously a toy example. Probably if it was a real implementation of something, you'd have that second arg be a named fn somewhere |
| 00:50 | niac | ddellacosta: thanks . i just try some code example on the web. |
| 01:27 | michaler` | going to implement users/roles/permissions system |
| 01:28 | michaler` | i wonder if there is anything out there which i can use instead of rolling my own |
| 02:41 | bashed | If I have a number of paths as vectors like [Home, Nav, Menu, Search] and [Home, Nav, Sign out], how do I merge them into a single tree. My current approach involves using 'assoc-in', since assoc-in creates hash-maps if any levels don't exist. |
| 02:42 | bashed | I want to store specific info for each of the vertices in the tree as well. Including their name, path, and additional information on them. |
| 02:45 | TEttinger | that's a good question, bashed, but I don't feel qualified to answer |
| 02:45 | TEttinger | it might be a clojure.zip thing |
| 02:45 | egli | michaler`: have you looked at friend? |
| 02:46 | TEttinger | https://www.refheap.com/97807 generating lots of old-testament-style names, I hilariously generate Eris and Vol right next to each other (goddess of discord and a god in a D&D setting) |
| 03:23 | michaler` | egli: hi |
| 03:24 | michaler` | egli: i've used friend a while back but i don't think it provides a full roles/permissions solution |
| 03:27 | egli | michaler`: what is a full roles/permissions solution? friend has roles (https://github.com/cemerick/friend#authorization) and even provides hierarchical roles (https://github.com/cemerick/friend#hierarchical-roles-ht-derive-isa-et-al) |
| 03:29 | sveri | I dropped friend in favour of buddy |
| 03:30 | egli | sveri: sure, buddy looks interesting |
| 03:32 | sveri | I don't want to say it is bad or something, however, I had one bad experience with it and the lack of documentation of proper integration was hard to when I wanted to use it |
| 03:35 | michaler` | egli: it provides some basic infrastructure maybe.. but i'm looking for a more full solution |
| 03:36 | sveri | michaler`: when having fun in the java world I always used shiro and if there wasn't buddy I would have thought about wrapping shiro in some clojure lib |
| 03:37 | sveri | michaler`: maybe this is something for you? |
| 03:41 | michaler` | sveri: i'm actually using buddy for this project too. also found some mention of wrapping shiro in clojure while searching google and the author wasn't sure whether the effort was indeed worth while. |
| 03:42 | michaler` | sveri: also it sounded like they invested a lot of time into that. I'm hoping to have some basic simple system done today :) |
| 04:12 | Eremox | Does clojure have separate namespaces for functions and vars like common lisp? |
| 04:12 | justin_smith | no |
| 04:13 | hiredman | no, and vars in clojure are a kind of reference type, where in common lisp "var" is just short for variable |
| 04:14 | hiredman | (which can be confusing when people trying to ask questions about "vars") |
| 04:16 | hiredman | (namespaces are also a thing in clojure, sort of analogous to packages in common lisp) |
| 04:17 | TEttinger | (inc hiredman) |
| 04:17 | lazybot | ⇒ 72 |
| 04:19 | Eremox | OK and functions are just like values in that vars reference anonymous functions? Which gives functions names right? |
| 04:20 | justin_smith | right, you can use (def foo (fn ...)) instead of (defn foo ...) except for the fact that defn adds some helpful metadata too |
| 04:20 | justin_smith | otherwise they are equivalent |
| 04:20 | hiredman | correct |
| 04:20 | hiredman | but vars are not the only way names are bound to values |
| 04:20 | Eremox | OK thanks. |
| 04:21 | hiredman | locals also bind names to values |
| 04:21 | hiredman | locals are function arguments or let bound names |
| 04:22 | ordnungswidrig | `fn` also can take a symbol for the name but I never understood it's purpose. defn macroexpands to fn without that. |
| 04:22 | hiredman | vars in clojure are the mutable cells that the top level bindings create with def create (def always defines a name at the top level, not like in scheme), locals are immutable |
| 04:22 | justin_smith | ordnungswidrig: the purpose is twofold: self calls that are not in tail position, and making stack traces readable |
| 04:23 | ordnungswidrig | justin_smith: I see. But why doesn't defn use the name argument to fn? |
| 04:24 | ordnungswidrig | Does the compiler do some extra work for the stacktraces if it finds a function in a var? |
| 04:24 | justin_smith | ordnungswidrig: because it doesn't need that for either of those reasons (the var / metadata suffice) |
| 04:24 | justin_smith | yeah, that's why it shows function names in stacktraces |
| 04:25 | ordnungswidrig | (def foo (fn bar [] (throw (Exception. "bogus")))) (foo) |
| 04:26 | ordnungswidrig | that shows "bar" in the stacktrace. evil :-) |
| 04:27 | TEttinger | I've taken to using variables named bogus and intentionally filled with impossible data when I need a value to indicate an invalid, non-nullable C# struct |
| 04:27 | TEttinger | I like nil better :( |
| 04:36 | Eremox | Does anyone have any good explanation of currying or a good article for it? I think I have been mixing closures and currying.. |
| 04:39 | tomjack | ,(let [plus (fn [x] (fn [y] (+ x y)))] (map (plus 3) [4 5 6])) |
| 04:39 | clojurebot | (7 8 9) |
| 04:40 | justin_smith | or you could just use partial, but neither that nor partial are currying |
| 04:40 | Glenjamin | Eremox: are you familiar with partial application? |
| 04:40 | Glenjamin | currying is related, but i think partial is easier to grok initially |
| 04:40 | justin_smith | ,(map (partial + 3) [4 5 6]) |
| 04:40 | clojurebot | (7 8 9) |
| 04:40 | tomjack | what is currying if not that? |
| 04:41 | Eremox | Yeah I think I get partial |
| 04:41 | justin_smith | tomjack: with currying the function returned will itself curry |
| 04:41 | tomjack | ah, just a different perspective. I think of 'currying' as some grunt work I have to do to my code |
| 04:41 | justin_smith | the point of currying is that it is implicit |
| 04:41 | tomjack | you think of it as something the function does for you, I guess |
| 04:42 | justin_smith | and clojure doesn't have currying - we opted for allowing varargs instead |
| 04:42 | tomjack | as a language feature, sure |
| 04:42 | justin_smith | tomjack: currying and partial evaluation both have definitions, and they are not the same |
| 04:43 | tomjack | I don't find dictionaries very useful |
| 04:43 | tomjack | but: http://en.wiktionary.org/wiki/currying |
| 04:43 | Eremox | In the source of clojure there is a macro called defcurried or similarly why isn't that part clojure? |
| 04:43 | tomjack | the definition there seems to describe exactly what I thought did above :) |
| 04:43 | tomjack | s/did/I did/ |
| 04:44 | justin_smith | tomjack: "Currying is converting a single function of n arguments into n functions with a single argument each." |
| 04:44 | justin_smith | clojure's + cannot be curried, because it takes 0 or more args |
| 04:44 | sveri | michaler`: Well, I guess you will, I found it easy to integrate, do you need an example? |
| 04:44 | tomjack | sure, I considered only the 2-arity of + |
| 04:44 | tomjack | :) |
| 04:45 | tomjack | conversely, I guess, when doing the transformation in a curried language, one must introduce explicit vectors |
| 04:46 | justin_smith | tomjack: well, I guess you did turn + into two functions with one argument each |
| 04:47 | justin_smith | in other words, clojure is annoying because you have to do explicit partial application because it isn't a currying language, and ML family languages are annoying because they don't provide convenient varargs |
| 04:47 | justin_smith | because varargs and currying mix very poorly |
| 04:48 | tomjack | I've been planning to attempt an experiment |
| 04:48 | tomjack | build a toy language with the Clojure reader, which fully embraces ambiguity |
| 04:49 | tomjack | try to write code and see which kinds of ambiguities make everything horrible |
| 04:50 | tomjack | e.g. (instance? (-> Nat Nat) (+ 3)) but also (instance? Nat (+ 3)) ? |
| 04:51 | justin_smith | that would lead to some seriously ambiguous bugs |
| 04:52 | justin_smith | transducer arities are a miniature versin of the problem |
| 04:52 | tomjack | the language should have a type system expressive enough to eliminate bugs, and there should be some elaboration procedure through which a program is only accepted if the ambiguity can be resolved |
| 04:53 | justin_smith | (they are useful, I am glad they are there, but we lose compile time errors for a class of mistakes) |
| 04:53 | tomjack | or, if you type an ambiguous program at the repl, I guess we can let you choose whether to run them all, look at them and pick, or whatever |
| 04:54 | tomjack | but I'm sure things will still be horrible if certain kinds of ambiguities are allowed... |
| 04:55 | justin_smith | tomjack: it would be a big change, right now clojure is not a "clever" compiler |
| 04:56 | tomjack | ah, uh, yeah.. the experiment would be a separate toy language with just some cosmetic similarity to clojure |
| 04:56 | justin_smith | yeah, just saying you wouldn't be able to leverage what exists very much is all |
| 04:58 | tomjack | right, except for (some) ideas and the reader, and Clojure in the non-meta-circular implementation |
| 04:59 | tomjack | I conjecture that a small subset of Clojure is a good fit for the operational semantics of such a language |
| 04:59 | tomjack | (if you can write a small clojure.core.logic{,.nominal}, I guess :( ) |
| 05:00 | tomjack | microkanren provides some hope |
| 05:00 | justin_smith | I've been awake for 22 hours, time for sleep |
| 05:00 | tomjack | ditto :( |
| 05:01 | justin_smith | I saw an excellent horror film with sleep deprivation themes today too |
| 05:01 | justin_smith | babadook |
| 05:01 | justin_smith | bye |
| 05:01 | ordnungswidrig | justin_smith: have a great nap. |
| 05:36 | tomphp | Hi |
| 05:40 | tomphp | I have a rather a couple simple interop (proxy) question which I can't find any references to |
| 05:40 | tomphp | 1) Can you set a constructor function? |
| 05:41 | tomphp | 2) how to you call other "methods" in the object - is proxy-super only for super or is there a this/self function? |
| 05:41 | tomphp | thanks ;-) |
| 06:22 | mnngfltg | In my REPL: OutOfMemoryError PermGen space java.lang.ClassLoader.defineClass1 |
| 06:22 | mnngfltg | what now? |
| 06:36 | hyPiRion | restart repl |
| 06:36 | hyPiRion | and/or run java 8 |
| 06:38 | mnngfltg | hyPiRion, installing java 8 now |
| 06:53 | martinklepsch | mnngfltg: hyPiRion or https://github.com/boot-clj/boot/wiki/JVM-Options#permgen-errors |
| 06:54 | martinklepsch | I'm trying to get some clj-webdriver stuff to work to test some reagent app. I constantly get errors like org.openqa.selenium.StaleElementReferenceException even though I don't hold any references to any elements myself |
| 06:56 | martinklepsch | my test looks like this: https://gist.github.com/martinklepsch/8c80e90fbd2ec332d0c6 |
| 07:27 | ggherdov | ,(cons :a [:b]) |
| 07:27 | clojurebot | (:a :b) |
| 07:27 | agarman | ,(conj [:b] :a) |
| 07:27 | clojurebot | [:b :a] |
| 07:27 | ggherdov | uhm. I'd like [:a :b] instead |
| 07:28 | agarman | ,(conj #{:b} :a) |
| 07:28 | clojurebot | #{:b :a} |
| 07:28 | agarman | ,(conj '(:b) :a) |
| 07:28 | clojurebot | (:a :b) |
| 07:28 | ggherdov | sure, but conj puts the elem wherever it pleases it. |
| 07:28 | ggherdov | i'd like to keep the collection type -and- prepend the new elem. |
| 07:29 | agarman | it puts it at the best place by the data structure |
| 07:29 | agarman | prepending to a vector is **slow** |
| 07:30 | agarman | it's designed for append |
| 07:30 | agarman | append is O(1) v O(n log n) |
| 07:30 | agarman | for prepend |
| 07:31 | ggherdov | base of the log? is it the log32 thing? |
| 07:31 | ggherdov | anyway I have small vectors, I was just ranting at cons changing the type. |
| 07:32 | agarman | cons operates on lists, just like it does in every other lisp ever |
| 07:32 | ggherdov | ok |
| 07:33 | agarman | far more people would bitch about that changing than having to use conj if you want to retain the collection type |
| 07:33 | ggherdov | I see |
| 07:35 | agarman | also, if you want to pull elements out of a vector without changing the collection type: |
| 07:36 | agarman | ,(rest [1 2 3]) (next [1 2 3) (pop [1 2 3]) |
| 07:36 | clojurebot | (2 3) |
| 07:36 | agarman | ,[(rest [1 2 3]) (next [1 2 3) (pop [1 2 3])] |
| 07:36 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )> |
| 07:36 | agarman | ,[(rest [1 2 3]) (next [1 2 3]) (pop [1 2 3])] |
| 07:36 | clojurebot | [(2 3) (2 3) [1 2]] |
| 07:36 | ggherdov | ok |
| 07:37 | agarman | ,[(first [1 2 3]) (peek [1 2 3])] |
| 07:37 | clojurebot | [1 3] |
| 07:38 | agarman | or just use cons, first et al because your vectors are small (ergo they'll likely work just fine as lists) |
| 07:39 | ggherdov | sure |
| 08:10 | hiteki | hi |
| 08:47 | mnngfltg | martinklepsch, figured out how to update to sun's java 8 on nixos, now hopefully fewer permgen problem (I get them in `lein` as well as in `boot`) |
| 08:48 | martinklepsch | mnngfltg: well, that JVM options thing should work for both :) |
| 08:49 | mnngfltg | martinklepsch, ... if you're willing to allocate 100s of MB or permgen space for every leiningen process, just to be safe |
| 11:26 | pepijndevos | What is the web stack du jour? |
| 11:27 | mbac | what are some fun clojure tutorials |
| 11:27 | mbac | rather, exercises to work through |
| 11:27 | shiranaihito | pepijndevos: ring? :) |
| 11:27 | mbac | i have some time coming up and i want something to keep my skills sharp on between sipping margaritas on the beach |
| 11:29 | sveri | mbac: 4clojure.com |
| 11:29 | mbac | whoa, that's awesome |
| 11:30 | pepijndevos | shiranaihito, yea, I just need some routing and misc utilities |
| 11:30 | csd_ | Suppose I have an effectful function, as well as a function that calls effectful function. How might I write something to compare whether the two functions are equal given similar arguments, which out executing effectful function? |
| 11:30 | csd_ | is it just a bad idea altogether? |
| 11:30 | Glenjamin | (doc with-redefs) |
| 11:30 | shiranaihito | pepijndevos: alrighty |
| 11:30 | clojurebot | "([bindings & body]); binding => var-symbol temp-value-expr Temporarily redefines Vars while executing the body. The temp-value-exprs will be evaluated and each resulting value will replace in parallel the root value of its Var. After the body is executed, the root values of all the Vars will be set back to their old values. These temporary changes will be visible in all threads. Useful for mocking out functions during testing." |
| 11:31 | sveri | pepijndevos: shameless self plug: https://github.com/sveri/closp |
| 11:32 | csd_ | Glenjamin: so use with-redefs to rebind effectful-fn to identity, for example, and then evaluate for equality? |
| 11:32 | Glenjamin | yeah, i wouldn't use it heavily - but that's the simplest way to do what you describe |
| 11:34 | chouser | what do you mean, "the two functions are equal"? |
| 11:34 | csd_ | Glenjamin: ok what if calls-effectul-fn is already defined and is the function I'm trying to test? |
| 11:34 | TimMc | ,(with-redefs [rand (constantly 100)] (rand-int 5)) |
| 11:34 | clojurebot | 100 |
| 11:34 | csd_ | I don't think with-redefs would work in that case |
| 11:35 | Glenjamin | with-redefs can only replace existing functions afaik |
| 11:36 | TimMc | csd_: Function A wraps function B, and you want to test that A passes its args unchanged to B and passes the return value back unchanged? |
| 11:36 | subhashgo | sveri: That's an interesting template, thanks |
| 11:36 | csd_ | I want to do a test like (= (effectful-fn immutable-arg mutable-arg) (call-effectful-fn immutable-arg mutable-arg)) |
| 11:36 | csd_ | so it needs to check that effectful-fn is the same function in either instance, and that the args are equal |
| 11:37 | mbac | this 4clojure.com thing is so good |
| 11:37 | sveri | subhashgo: np, your welcome |
| 11:37 | mbac | it should say achievement unlocked at milestones |
| 11:38 | csd_ | does what i'm saying make sense? |
| 11:38 | TimMc | Do you just want to test that B was called? |
| 11:38 | puredanger | mbac: tell amalloy_ |
| 11:38 | csd_ | yeah, basically. i'm testing a function that has a cond in it, and i want to check that under the right condition that it calls effectful-fn with the args i'm passing to the wrapper |
| 11:40 | csd_ | and i think the cleanest way to do that would be not to let effectful-fn execute |
| 11:40 | chouser | csd_: I suspect your code could be reorganized to be more testable, and might also then be more reusable and possibly easier to understand. That said, rebinding effectful-fn to capture its args and store them somewhere you can check later should work. |
| 11:41 | csd_ | rebinding in the test code or in the non-test code? |
| 11:42 | chouser | in the test code |
| 11:43 | hiteki | hi |
| 11:43 | Glenjamin | https://clojars.org/bond and https://clojars.org/q can wrap up some common patterns |
| 11:43 | Glenjamin | for rebinding functions in tests |
| 11:43 | TimMc | csd_: (let [calls (atom [])] (with-redefs [B #(do (swap! calls conj %&) :return)] (A :foo :bar))) and then test that @calls has one vector of the right vals. |
| 11:44 | chouser | csd_: (let [caught (atom [])] (binding [effectful-fn (fn [& args] (swap! caught conj args))] (effectful-fn ...) (call-effectful ...) (is (= (first caught) (second caught))))) ...or some such |
| 11:44 | Glenjamin | that's what https://github.com/glenjamin/q#with-stubs-fns--body does internally |
| 11:44 | TimMc | csd_: Or if you're using midje, (fact (A :foo :bar) => :return (provided (B :foo :bar) => :return)) |
| 11:46 | csd_ | ok but calls-effectful-fn is within the non-test code, and i would think that's where the binding would have to go |
| 11:46 | TimMc | csd_: This is too confusing, you should post an example. |
| 11:49 | csd_ | So here's the non-test function. https://www.refheap.com/97822 I want to be able to test the effectful functions without having to pass and test these large state maps |
| 11:49 | csd_ | i'm also experimenting with adding these keywords as an alternative method of testing |
| 11:50 | justin_smith | csd_: my usual approach to make things testable is split the logic from the actions |
| 11:51 | justin_smith | the function with the actions should be trivial, and then you test the result of the function with the logic |
| 11:52 | justin_smith | it's kind of like the "interpreter pattern" I think - the decision making function returns a data structure that tells the side effecting function what to do |
| 11:52 | csd_ | and so effectively you're testing the return value of the side effecting function when you test the decision making function? |
| 11:53 | justin_smith | csd_: well, you've refactored the problem, so you are testing that your logic is correct |
| 11:53 | justin_smith | and the side effecting function will be easier to test with no logic, and may be trivial enough to not really require testing (thinly wrapped library call) |
| 11:54 | csd_ | how are you testing the correctness of the logic without looking, indirectly, at the return values from the sideeffecting functions? |
| 11:54 | justin_smith | "no logic" is of course a relative exagerration - but the goal here is to limit the intermingling of decisions and side effects, so that each are easier to test |
| 11:54 | justin_smith | by testing their return values of course |
| 11:55 | justin_smith | which in the actual program will "drive" the side effecting functions |
| 11:55 | justin_smith | the logic half should take all the relevant args, and return a data structure, the side effecting half should take a data structure, perform an action, and return nil |
| 11:55 | csd_ | are you aware of any code samples that might demonstrate this? i'm somewhat confused |
| 11:56 | justin_smith | I use it in my own projects, let me find a decomplected example |
| 11:56 | TimMc | This is like the instruction decoder on a CPU. |
| 11:57 | justin_smith | TimMc: kind of, yeah |
| 11:57 | TimMc | taking a complex instruction and breaking it down into a smaller set of individual, sequenced actions to perform. |
| 11:58 | chouser | justin_smith: return values may not always be the best way to communicate what should be done. An alternative is to pass in the functions to be applies, so that you can pass in either effectful or pure fns. |
| 11:58 | chouser | You know, like you do to "reduce" :-) |
| 11:59 | justin_smith | chouser: it's true, that is also a good alternative |
| 12:00 | justin_smith | but regardless, the goal is to separate "what to do" from "doing the side effects" so that they can both be more easily verified correct |
| 12:00 | chouser | yes |
| 12:00 | chouser | because "what to do" is usually more complicated but easier to test. |
| 12:00 | csd_ | but when you test the has-logic-and-calls-isolated-side-effects, you still need to look at the its return value to judge correctness, and its return value is going to be a result of the side effecting functions |
| 12:01 | chouser | "doing the side effects" of course should be tested as well, but that usually requires more complex setups. VMs and such. |
| 12:01 | justin_smith | csd_: thare's also a very small function at the top that connects the decision maker and the side effector |
| 12:01 | justin_smith | what you test about the decision making function is the data structure it returns |
| 12:01 | justin_smith | or in chouser's version, you pass it a verifier function instead of a side effectful one |
| 12:02 | justin_smith | brb, shower and coffee |
| 12:03 | csd_ | ultimately i think you want, when test has-logic-and-calls-isolated-side-effects, is for the side effects not to occur. but they're still there in the function. so how can they not |
| 12:08 | justin_smith | csd_: it's not one function that does both of those |
| 12:08 | justin_smith | one function returns data representing the thing to be done |
| 12:08 | justin_smith | easy to test |
| 12:08 | justin_smith | the other takes data, and does an action |
| 12:08 | justin_smith | a third function connects them |
| 12:09 | justin_smith | csd_: a good example is in ring, with a well designed ring app |
| 12:09 | csd_ | ok conceptually i get what you're saying |
| 12:09 | justin_smith | all the request data is in an immutable data structure, each middleware returns a modified map representing some decision made, or some piece of data pulled in etc. |
| 12:10 | justin_smith | the handler function does not do anything with side effects usually - it returns a map that tells ring how to construct a response |
| 12:10 | justin_smith | you can easily test the handler by passing it a map, and then looking at the map it returns to you |
| 12:10 | csd_ | i see |
| 12:11 | justin_smith | it's the infrastructure of the ring server that ties this all together, and attaches the result of rendering that map to a response to the client |
| 12:11 | csd_ | and so the map contains the side effecting function that has to call it |
| 12:11 | csd_ | or rather, that the interpreter calls on it |
| 12:12 | justin_smith | no, in this case the ring server itself does the side effects, which are about reading from clients and writing back to client sockets |
| 12:12 | csd_ | oh i mean in general, not specifically for ring |
| 12:13 | justin_smith | OK, then that can be the way it is done, but there are other structurings available |
| 12:13 | justin_smith | and in practice the handler/app function is not perfectly side effect free |
| 12:13 | TimMc | Alternative to pprint that doesn't botch vars? |
| 12:14 | csd_ | justin_smith: where can i learn more about this? |
| 12:14 | stuartsierra | TimMc: dunno if it handles Vars, but bbloom's ffipp might be pluggable |
| 12:14 | justin_smith | csd_: hmm... you could look at how monads are used in Haskell I guess? |
| 12:15 | justin_smith | there are books that cover this stuff I am sure... |
| 12:15 | csd_ | whys that |
| 12:15 | justin_smith | csd_: this is exactly what monads do, they isolate side effecting code from program logic code |
| 12:16 | hiredman | http://dev.clojure.org/jira/browse/CLJ-1576 vote early and often |
| 12:16 | justin_smith | or maybe better to say they knit them together in a very specific way |
| 12:17 | TimMc | stuartsierra: Thanks! |
| 12:18 | profil | anybody who has used aleph with core.async? I am trying to connect aleph(manifold) streams to a core.async channel |
| 12:18 | csd_ | justin_smith: ok thank you for explaining all this to me |
| 12:21 | justin_smith | csd_: I think it makes a lot more sense when you try it. Start with chouser 's version of passing either a side effecting function or a verification function to the function that does the logic |
| 12:21 | justin_smith | that is probably the simplest way to try this general pattern |
| 12:23 | justin_smith | csd_: so, more concretely, with join-channel, you would probably pass a function representing what currently uses its return value in to the function, and you would probably also want to put some of the side effecting code from join-channel into that function you pass in (by returning a vector of data instead of one keyword) |
| 12:23 | justin_smith | s/returning/passing in |
| 12:23 | justin_smith | oops! |
| 12:30 | csd_ | justin_smith: yeah, now i'm just thinking about where in my code i want to put the interpretter exactly |
| 12:30 | crazydiamond | Hi. What tool may I use to effectively read large Clojure EDN file? Also, what format is better to store large piece of data? May be JSON or XML is better? |
| 12:37 | justin_smith | crazydiamond: I don't know if edn is apropriate for large files. Depending on how big "large" is of course. |
| 12:38 | crazydiamond | justin_smith, well, 42 megabyte of EDN |
| 12:38 | justin_smith | clojure.edn/read should handle that fine |
| 12:38 | justin_smith | but definitely pass in a buffered reader, don't slurp a string then read-string |
| 12:39 | crazydiamond | good to know |
| 12:40 | crazydiamond | my file contains sequence of things, and I have function that I'm applying to each item in sequence (and tweaking the function each time) |
| 12:42 | justin_smith | the most efficient way to do that general pattern may be one record per line of the file mixed with line-seq and either doseq or for |
| 12:42 | justin_smith | unless the input file is a given |
| 12:51 | crazydiamond | justin_smith, is this example of buffered reader? |
| 12:51 | crazydiamond | (with-open [rdr (clojure.java.io/reader "/tmp/foo.txt")] |
| 12:51 | crazydiamond | (reduce conj [] (line-seq rdr))) |
| 12:54 | l1x | morning |
| 12:54 | l1x | justin_smith: do you have a second? i was running into this very interesting problem and i was wondering if you could shed some light |
| 12:54 | clov3r | Hello #clojure. I have a question, trying to make a partially applied functions with java.lang.String's .contains |
| 12:55 | clov3r | but (partial .contains "a") gives a runtime exception, unable to resolve symbol |
| 12:55 | l1x | https://gist.github.com/l1x/836b23fe864dd0db1259 |
| 12:56 | l1x | i am trying to process N message streams lazily and I need to consume 1 (or few) message from each stream |
| 12:57 | l1x | but obviously if you do for [stream streams] it is trying to finish to process the first stream before moves on to the second one |
| 12:57 | l1x | i was wondering how could i process them taking 1 or N from each stream in each iteration |
| 12:58 | TimMc | clov3r: Yes, Java methods are not objects, so you can't pass them around like that. |
| 12:58 | TimMc | #(.contains "a" %) would be the equivalent |
| 12:58 | clov3r | TimMc: ok, well that;s good to know |
| 12:58 | clov3r | thanks :) |
| 13:01 | justin_smith | l1x: (doseq [stream-heads (apply map list streams) stream stream-heads] ...) |
| 13:01 | justin_smith | l1x: the problem with that is that it will stop when the shortest set of streams is done though... |
| 13:02 | l1x | hmm |
| 13:02 | l1x | i am thinking about creating a go-loop for each stream |
| 13:02 | l1x | and just send it to a channel |
| 13:02 | tomjack | yes! |
| 13:02 | tomjack | seqs don't seem right to me |
| 13:02 | l1x | doseq is no good though, because it holds the head afaik |
| 13:02 | l1x | and you are running out of memory |
| 13:03 | justin_smith | ,(for [stream-heads (map list [1 2 3] [4 5 6] [7 8 9]) stream stream-heads] stream) |
| 13:03 | clojurebot | (1 4 7 2 5 ...) |
| 13:03 | l1x | ,(for [stream-heads (map list [1 2 3] [4] [7 8 ]) stream stream-heads] stream) |
| 13:03 | clojurebot | (1 4 7) |
| 13:03 | l1x | :) |
| 13:03 | justin_smith | right |
| 13:03 | l1x | i was thinking about it a lot but it seems like channels are the best for this |
| 13:03 | justin_smith | doseq does not hold the head |
| 13:03 | l1x | no? |
| 13:04 | clojurebot | no is tufflax: there was a question somewhere in there, the answer |
| 13:04 | l1x | interesting, i got oom |
| 13:04 | l1x | and when i replaced it with loop it went away |
| 13:04 | l1x | maybe it is not realted |
| 13:04 | justin_smith | it could have to do with how the args to doseq are being generated |
| 13:04 | l1x | i see |
| 13:05 | crash_ep | Does anyone know the reason a buffer must be explicitly provided when a channel is created with a transducer? |
| 13:05 | justin_smith | like if you held onto the lazy thing that was passed to doseq |
| 13:05 | l1x | hmm i see |
| 13:05 | justin_smith | crash_ep: because arity overload is the only function overloading we have |
| 13:05 | l1x | alright justin thanks anyway, i going to rewrite it with channels |
| 13:06 | justin_smith | l1x: that probably makes sense, yeah |
| 13:06 | crash_ep | justin_smith: but passing `nil` does not seem to create an unbuffered channel, as it would normally |
| 13:06 | justin_smith | odd |
| 13:06 | crash_ep | (in CLJS) |
| 13:20 | dnolen | crash_ep: that's just how it works, you have to transduce on something, buffer size 1, true for Clojure too |
| 13:21 | crash_ep | dnolen: maybe I'm misunderstanding what a "buffer" is… I assumed `(chan)` creates a buffer of size 0. |
| 13:22 | dnolen | crash_ep: semantically unbuffered |
| 13:22 | crash_ep | dnolen: right. Why shouldn't a transducer operate on values put on a semantically unbuffered channel? |
| 13:22 | dnolen | crash_ep: no |
| 13:22 | dnolen | it has to transduce on *something* |
| 13:24 | crash_ep | dnolen: can you help me better understand what "transduce on" means? I thought transduction was an operation on values, but it sounds like something more nuanced than that. |
| 13:24 | dnolen | crash_ep: sorry, there are plenty of implementations you can read over now |
| 13:25 | crash_ep | dnolen: ok, i'll take another look |
| 13:25 | dnolen | the JS one provided by Cognitect that I wrote is particularly short |
| 13:25 | dnolen | crash_ep: https://github.com/cognitect-labs/transducers-js |
| 13:26 | crash_ep | I guess the part I'm not getting is the relationship to buffer size. |
| 13:26 | dnolen | crash_ep: just replace "buffer" with "empty list" |
| 13:26 | dnolen | doesn't make any sense |
| 13:31 | crazydiamond | Hi. Can I measure (say, in REPL) how long function takes to complete? |
| 13:31 | sritchie | ,(doc time) |
| 13:31 | crash_ep | dnolen: I thought transducers operated on the values as they pass through a channel, not a buffer. |
| 13:31 | clojurebot | "([expr]); Evaluates expr and prints the time it took. Returns the value of expr." |
| 13:31 | sritchie | crazydiamond: that should work |
| 13:31 | dnolen | crash_ep: nope |
| 13:31 | crash_ep | But it sounds like you're saying that a transducer is a property of a buffer, not a channel |
| 13:31 | justin_smith | crazydiamond: time for a semi-meaningful number, use criterium for proper micro-benchmarks |
| 13:31 | dnolen | crash_ep: transducers work on buffers yes |
| 13:31 | crazydiamond | sritchie, justin_smith great thanks! |
| 13:31 | crash_ep | then why don't we pass transducers to the `buffer` function instead of the `chan` function? |
| 13:32 | crazydiamond | I need to measure how long it takes to read file, so, it should be enough for me |
| 13:32 | justin_smith | crazydiamond: criterium makes sure that JIT gets warmed up and shows you mean / average / max time the function took over many calls |
| 13:33 | justin_smith | with the time function, you won't really see the influence of JIT, which can change things quite a bit |
| 13:33 | dnolen | crash_ep: that doesn't many any sense either |
| 13:33 | dnolen | crash_ep: the channel *uses* the buffer, it knows when and how to apply the transformer |
| 13:34 | dnolen | s/many/make |
| 13:34 | tbaldridge | dnolen: but the channel basically wraps the .add method of the buffer with the transducer, |
| 13:36 | tbaldridge | so you could technically do it in the buffer, but I don't know that it would be any better than putting it in the channel. |
| 13:36 | dnolen | tbaldridge: right which was my point, and less flexible if for some reason down the line something else needs to happen, encapsulation stinks blah blah blah :) |
| 13:38 | crash_ep | The relationship between these three things is not entirely clear to me, I'll have to study some more. Thanks dnolen tbaldridge |
| 13:46 | SegFaultAX | Any cyanite users around? The #cyanite channel is totally dead. |
| 13:46 | SegFaultAX | And no response yet from #graphite. #clojure, you're my only hope. |
| 14:26 | AeroNotix | SegFaultAX: yeah we use it, sup? |
| 14:26 | SegFaultAX | AeroNotix: Does it completely replace carbon-*? |
| 14:26 | AeroNotix | SegFaultAX: also, pyr is on #freenode |
| 14:26 | SegFaultAX | Except maybe carbon c relay. |
| 14:26 | AeroNotix | SegFaultAX: pretty much |
| 14:26 | SegFaultAX | AeroNotix: I know, but all the channels are dead. |
| 14:27 | AeroNotix | SegFaultAX: pm him directly. |
| 14:27 | AeroNotix | he's around |
| 14:27 | SegFaultAX | AeroNotix: Pretty much? Is there any need for carbon-cache or carbon-aggregate at all? |
| 14:27 | AeroNotix | SegFaultAX: I didn't set it up, I can ask |
| 14:28 | AeroNotix | SegFaultAX: nope, no need for either |
| 14:29 | _tim__ | hi, is there something similar to the async/dropping-buffer where i can tell when an item is discarded? or throw an exception if the queue is full? |
| 14:29 | AeroNotix | SegFaultAX: if you want features from carbon-aggregate, you'll need |
| 14:29 | AeroNotix | something like carbon-c-relay to do the aggs for you |
| 14:31 | SegFaultAX | AeroNotix: Ok, that's fair enough. |
| 14:31 | SegFaultAX | AeroNotix: Thanks so much for your time. |
| 14:31 | AeroNotix | SegFaultAX: think nothing of it |
| 14:31 | AeroNotix | yay |
| 14:31 | SegFaultAX | Anyone here use Cyanite? |
| 14:32 | AeroNotix | :) |
| 14:41 | ggherdov | ,(let [pair #((vector %1 %2))] (pair :a :b)) |
| 14:41 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector> |
| 14:41 | ggherdov | not sure I understand why |
| 14:41 | justin_smith | ggherdov: try expanding it |
| 14:41 | justin_smith | ,'#((vector %1 %2)) |
| 14:41 | clojurebot | (fn* [p1__53# p2__54#] ((vector p1__53# p2__54#))) |
| 14:41 | ggherdov | uh |
| 14:41 | justin_smith | notice the problem? |
| 14:41 | AeroNotix | ggherdov: you're calling the vector as a function |
| 14:41 | justin_smith | too many parens |
| 14:42 | ggherdov | thanks justin_smith AeroNotix |
| 14:42 | justin_smith | ,([1 2]) |
| 14:42 | AeroNotix | np |
| 14:42 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: PersistentVector> |
| 14:42 | justin_smith | that's what it did |
| 14:42 | ggherdov | i see |
| 14:42 | justin_smith | ,([1 2] 0) ; this works though |
| 14:42 | clojurebot | 1 |
| 14:42 | ggherdov | cool |
| 14:50 | puredanger | any time you see two ( ( together, you should pause and think about it to make sure that makes sense |
| 15:00 | AeroNotix | If you were on a 19hr flight. What clojure{,script} documentation would you take with you? |
| 15:03 | justin_smith | AeroNotix: does grimoire have a standalone version yet? maybe just if you clone the repo? |
| 15:03 | AeroNotix | justin_smith: good call |
| 15:04 | justin_smith | https://github.com/clojure-grimoire/grimoire |
| 15:04 | AeroNotix | thanks |
| 15:04 | justin_smith | also, name-apropriate question of the day |
| 15:04 | AeroNotix | :) |
| 15:05 | crack_user | hello guys |
| 15:05 | AeroNotix | crack_user: lo |
| 15:06 | crack_user | what is the best way I can check if all elements of collection A is in collection B |
| 15:08 | crazydiamond | Hi. Is there alternate version to println, that would be truncating big structure (like by adding '...')? |
| 15:08 | AeroNotix | ,(every? identity (map #{1 2 3 4} #{1 2 3 4})) |
| 15:08 | clojurebot | true |
| 15:08 | AeroNotix | crack_user: ^^ maybe? |
| 15:09 | AeroNotix | ,(every? #{1 2 3 4} #{1 2 3 4})) |
| 15:09 | clojurebot | true |
| 15:09 | AeroNotix | oh that's better^ |
| 15:10 | crack_user | that is it |
| 15:10 | crack_user | I just don't get the #{} syntax |
| 15:11 | AeroNotix | crack_user: sets |
| 15:11 | dnolen | crack_user: based on your description the following would also work (clojure.set/subset? (set A) (set B)) |
| 15:12 | crack_user | AeroNotix: but it also works with vectors and lists? |
| 15:12 | AeroNotix | crack_user: no |
| 15:12 | crack_user | :/ |
| 15:12 | dnolen | crack_user: you can re-read what I said |
| 15:13 | dnolen | ,(clojure.set/subset? (set [:bird :dog :cat]) (set [:bird :cat :dog])) |
| 15:13 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set> |
| 15:13 | dnolen | ,(require 'clojure.set) |
| 15:13 | clojurebot | nil |
| 15:13 | dnolen | ,(clojure.set/subset? (set [:bird :dog :cat]) (set [:bird :cat :dog])) |
| 15:13 | clojurebot | true |
| 15:14 | AeroNotix | I've always wondered why set is in its own namespace. |
| 15:15 | crack_user | dnolen: thx |
| 15:21 | pepijndevos | With compojure, how do you get both the request body and url parameters? |
| 15:22 | pepijndevos | {body :body} and [id] combined |
| 15:27 | puredanger | Pretty interesting new library from ye olde Nathan Marz https://github.com/nathanmarz/specter |
| 15:27 | AeroNotix | dude loves his macros |
| 15:28 | pepijndevos | {{id :id} :params body :body} |
| 15:29 | puredanger | AeroNotix: I don't think it uses macros? |
| 15:30 | AeroNotix | puredanger: oh I saw the ALL and assumed |
| 15:30 | AeroNotix | my bad |
| 15:33 | zerokarmaleft | a lot of interesting variations of lens cropping up in the clojure space |
| 15:33 | zerokarmaleft | lenses* |
| 15:34 | wink | it uses com.rpl.specter whereas http://rpl.com seems unrelated - I've never seen that. |
| 15:48 | puredanger | yeah, that's weird. plus why even bother with com in that case? |
| 15:49 | puredanger | unless he's in the process of acquiring it :) |
| 15:49 | clojurebot | No entiendo |
| 15:52 | amalloy | crazydiamond: you can bind *print-length* and *print-level* to change how println and prn handle large inputs |
| 15:52 | amalloy | maybe it's print-depth, i forget |
| 15:52 | amalloy | &(binding [*print-length* 5] (println (range 10))) |
| 15:52 | lazybot | java.lang.SecurityException: You tripped the alarm! push-thread-bindings is bad! |
| 15:52 | amalloy | ,(binding [*print-length* 5] (println (range 10))) |
| 15:52 | clojurebot | (0 1 2 3 4 ...)\n |
| 15:53 | crazydiamond | amalloy, thanks! |
| 16:36 | sdegutis | Hi nerds. Got any recommendations for a superlative ergonomic keyboard? Price is no object. (It's a value.) |
| 16:37 | amalloy | superlative, huh? you don't care if it's the best or the worst, as long as it's the most something? |
| 16:38 | sdegutis | amalloy: my dictionary says "of the highest quality or degree" |
| 16:38 | sdegutis | amalloy: so yes, the highest in quality |
| 16:38 | amalloy | that's a lame meaning. meaning 2 is the better one: expressing the highest or a very high degree of a quality |
| 16:39 | amalloy | ie, worst is a superlative, the highest degree of the quality of badness |
| 16:39 | sdegutis | amalloy: in grammar, yes |
| 16:39 | amalloy | grammar is superlatively important |
| 16:39 | sdegutis | amalloy: perhaps I meant exemplary |
| 16:40 | sdegutis | amalloy: or supergood |
| 16:40 | amalloy | double plus good |
| 16:40 | sdegutis | amalloy: now you're just making things up |
| 16:42 | amalloy | $google double plus good |
| 16:42 | lazybot | [Newspeak - Wikipedia, the free encyclopedia] http://en.wikipedia.org/wiki/Newspeak |
| 16:45 | sdegutis | So, ErgoDox? |
| 16:46 | TimMc | sdegutis: The DataHand is superlative along the axis of price. |
| 16:46 | TimMc | and unavailability, probably |
| 16:46 | sdegutis | ~guards |
| 16:46 | clojurebot | SEIZE HIM! |
| 16:48 | TimMc | The Maltron is the most UK one I know. |
| 16:49 | TimMc | sdegutis: And the Atreus is the most Clojure keyboard. |
| 16:49 | sdegutis | TimMc: says how? |
| 16:49 | TimMc | Well, technomancy makes it. |
| 16:50 | sdegutis | TimMc: so true |
| 16:52 | TimMc | I was going to get a fancy keyboard but I got physical therapy instead. |
| 17:12 | xemdetia | I got a $10 and grew a beard so I have less RSI from contemplative beard stroking |
| 17:15 | rpaulo | I have a beard and that didn't help |
| 17:31 | sdegutis | xemdetia: sounds reasonable alternative; thanks |
| 17:38 | bigs | TimMc, sdegutis: i have a pretty bad (diagnosed) case of carpal tunnel in both wrists. i've been using the kinesis advantage for about six months, now, and it's been absolutely astounding |
| 17:38 | bigs | could not recommend it highly enough |
| 17:39 | sdegutis | bigs: hmm, thanks for the testimony |
| 17:39 | sdegutis | bigs: it looks like it'd be painful on the wrist though cuz it rests on the flat surface |
| 17:39 | bigs | the key is getting a chair w/ elbow rests |
| 17:40 | bigs | that you can raise up highly enough so that your forearms are flush |
| 17:40 | sdegutis | bigs: clever |
| 17:40 | sdegutis | bigs: but im about to build a standing desk this weekend |
| 17:40 | bigs | i've also been in physical therapy for 4 months |
| 17:40 | sdegutis | bigs: so i dunno how thats gonna play into it |
| 17:40 | bigs | ah perfect |
| 17:40 | bigs | you can just adjust the height |
| 17:40 | sdegutis | oh good point, i should make the height adjustable |
| 17:40 | bigs | i actually just got my ergodox from the recent massdrop |
| 17:40 | bigs | but haven't put it together |
| 17:41 | sdegutis | massdrop? |
| 17:41 | bigs | i'm looking fwd to having it as my second keyboard |
| 17:41 | bigs | aye massdrop.com |
| 17:41 | bigs | afaik the only place selling ergodox kits |
| 17:41 | sdegutis | aww requires account |
| 17:41 | sdegutis | dang |
| 17:41 | bigs | haha |
| 17:41 | scottj | ?mode=guest_open might work |
| 17:42 | bigs | but yeah i seriously could never have imagined the impact the kinesis had |
| 17:42 | sdegutis | bigs: the tons of keys by the thumbs seems strange tho |
| 17:42 | bigs | that's the best part for me -- a lot of my CTS stems from overuse of the thumbs |
| 17:42 | sdegutis | bigs: i can understand ctrl+shift+alt+meta (two per thumb) but 10 total? wth? |
| 17:42 | bigs | i.e. bending them under the hand |
| 17:42 | bigs | to hit the modifier keys |
| 17:42 | sdegutis | bigs: oh yeah me too |
| 17:42 | bigs | w/ a layout like this, your hands remain open |
| 17:43 | sdegutis | bigs: i have apple kbd and reading left thumb to left Cmd key is big cause of pain |
| 17:43 | bigs | which reduces strain a lot. only takes maybe 5 days to get used to |
| 17:43 | sdegutis | sure |
| 17:43 | sdegutis | i liked atreus's idea of putting modifiers near thumbs, but atreus has too few keys 4me |
| 17:43 | bigs | aye |
| 17:45 | sdegutis | dang, no chance of getting ergodox soon cuz the drop ended |
| 17:45 | sdegutis | wsa hoping to get new kbd by monday |
| 17:45 | scottj | it takes 1-2 months after the drop ends anyway. they have a drop roughly once a month |
| 17:47 | bigs | yeah |
| 17:48 | bigs | that's why i got a kinesis :P |
| 17:48 | bigs | needed a solution immediately |
| 17:48 | scottj | bigs: do you use emacs btw? |
| 17:48 | bigs | i'm a vimmer |
| 17:48 | bigs | but i use emacs w/ evil mode |
| 17:48 | bigs | my cofounder is a full on emacs user w/ kinesis |
| 17:52 | sdegutis | bigs: it looks like the alt/ctrl keys on kinesis/adv would be hard to reach with thumb & require stretching |
| 17:53 | bigs | ah he maps the right ctrl to meta |
| 17:53 | bigs | to take care of that |
| 17:53 | bigs | ah -- also the kinesis is hardware programmable |
| 17:53 | bigs | which is awesome |
| 17:53 | sdegutis | whats that mean? |
| 17:53 | sdegutis | is that kind of like atreus's firmware? |
| 17:53 | bigs | can reprogram keys on the unit itself |
| 17:53 | bigs | no software |
| 17:53 | sdegutis | re https://github.com/sdegutis/atreus-firmware |
| 17:54 | sdegutis | bigs: you use querty or colemak? |
| 17:54 | sdegutis | lol @ phonic typo |
| 17:55 | sdegutis | i wondered why that felt strange to type |
| 17:55 | bigs | haha livin that qwerty life, but would love to go to colemak |
| 17:55 | sdegutis | ok |
| 17:55 | bigs | got a lotta c++ to write, tho haha |
| 17:55 | sdegutis | thx bigs 4 ur hlp |
| 17:55 | bigs | no time to relearn! |
| 17:55 | bigs | absolutley -- feel free to pm me whenever. this is something i've spent a lotta time on |
| 17:56 | bigs | when my CTS was at its worst, my hands were so swollen i couldn't form a fist |
| 17:56 | sdegutis | bigs: doesnt it hurt to have your wrists against the flat surface of it all the time? |
| 17:56 | sdegutis | re https://www.kinesis-ergo.com/shop/images/1466/advantage-side-hands.jpg |
| 17:56 | bigs | it comes w/ two adhesive wrist pads |
| 17:56 | sdegutis | oh nice |
| 17:56 | bigs | fitted for that plastic area -- quite comfortable and seem to age well |
| 17:57 | scottj | also they recommend not resting your palms on it or the pads all the time while typing |
| 17:57 | sdegutis | y4? |
| 17:57 | bigs | yeah |
| 17:57 | sdegutis | why for |
| 17:58 | bigs | definitely, scottj - the concavity makes it easier, too |
| 17:58 | bigs | releaves pressure on the carpal tunnel |
| 17:58 | scottj | sdegutis: presumably same reason you're not supposed to do it on a normal keyboard |
| 17:58 | sdegutis | bigs: where do your thumbs rest when not using those keys (ie ur just reading)? |
| 17:59 | bigs | space & backspace |
| 17:59 | sdegutis | bigs: in between the two thumb-key groups, or outside them,? |
| 17:59 | sdegutis | ooh |
| 17:59 | sdegutis | i guess if it has heavy keys then thats fine |
| 17:59 | scottj | probably quite convenient for reading, since I think lots of apps support those two keys for forward and back a page |
| 17:59 | sdegutis | ie requires pressing harder-ish |
| 17:59 | bigs | yeah it has mechanical switches |
| 17:59 | sdegutis | phew |
| 17:59 | bigs | and the springs are good |
| 17:59 | sdegutis | i wonder if my boss will buy it or if i have to buy it meself |
| 18:00 | bigs | should be an easy sell to the boss |
| 18:00 | sdegutis | but its like ~$250 |
| 18:00 | sdegutis | oh wait $300 |
| 18:01 | bigs | so like... 1.5-2 hrs of dev time hehe |
| 18:01 | sdegutis | oh nic, they sell foot pedals! |
| 18:01 | bigs | yep :) |
| 18:01 | scottj | $269 new w/ free ship off their ebay or amazon page. slightly less for a refurb that someone used for 10 minutes. |
| 18:03 | sdegutis | heh |
| 18:03 | bigs | i gotta get back to it, but good luck! |
| 18:03 | sdegutis | cya thx |
| 18:42 | vas | Hello |
| 18:45 | vas | This is more of a datomic-specific question -- is there a constantly running database process in another terminal? |
| 18:54 | justin_smith | vas: it may or may not run in a terminal. Usually there is at least one db process, yes. |
| 18:56 | gphilipp | hello |
| 18:56 | l1x | justin_smith: i rewrote the code that we talked about earlier with sync and channels, it does 30K req/s, the older version did 50K req/s. I am trying to dig into async and see if I could tune the code further |
| 18:57 | l1x | but now, i have a fully fledged idiomatic Kafka client in Clojure \o/ |
| 18:57 | l1x | the other project, is just ignoring these things so that codebase does not work with multiple Kafka streams |
| 18:57 | vas | justin_smith thanks. (= |
| 18:57 | justin_smith | l1x: one option if you really need max throughput is to directly use threads reading from native concurrent blocking queues |
| 18:58 | justin_smith | or one queue shared by the threads running the code, each one taking items off |
| 18:58 | justin_smith | whatever makes sense for your setup |
| 18:58 | l1x | justin_smith: right |
| 18:58 | l1x | justin_smith: https://gist.github.com/l1x/2a2b794379752199cd4b |
| 18:59 | justin_smith | core.async makes managing complex asynchronous stuff much less brittle, but perf wise sometimes a dedicated thread with a normal queue does the trick |
| 18:59 | l1x | it is using async/thread + go-loop |
| 18:59 | gphilipp | hi |
| 18:59 | l1x | it might not be ideal for this usecase |
| 18:59 | l1x | i might just use a normal loop + recur |
| 19:00 | l1x | but i am pretty happy that the out of the box performance is accetable |
| 19:01 | gphilipp | How can I set *print-right-margin* once and for all in my repl session w/o using (binding ...) macro. I've tried (set! ...) but it doesn't work (Can't change/establish root binding of: *print-right-margin* with set) ? |
| 19:10 | ToxicFrog | Is there a "dissoc-in"? |
| 19:10 | avshalom | ,(+ 2 2) |
| 19:10 | clojurebot | 4 |
| 19:11 | justin_smith | ToxicFrog: I think it exists in some util libs, but there is also update-in + dissoc |
| 19:12 | Bronsa | ToxicFrog: https://github.com/clojure/core.incubator/blob/master/src/main/clojure/clojure/core/incubator.clj#L62 |
| 19:12 | justin_smith | ,(update-in {:a {:b 1}} [:a] dissoc :b) |
| 19:12 | clojurebot | {:a {}} |
| 19:12 | justin_smith | ,(update-in {:a {}} [:a] dissoc :b) |
| 19:12 | clojurebot | {:a {}} |
| 19:13 | justin_smith | ,(update-in {} [:a] dissoc :b) |
| 19:13 | clojurebot | {:a nil} |
| 19:13 | justin_smith | that last one is where it gets tricky |
| 19:19 | gastove | This might be a terribly noob question, but: is it possible to have a defprotocol, implemented in a defrecord, that takes an additional argument that isn't part of the record's constructor? |
| 19:21 | amalloy | gastove: yes. protocol functions take one 'this argument, which is the record, and from which you can get all the record's fields, and any number of other arguments you want |
| 19:21 | gastove | Say... (defprotocol Foo (bar [x y])) (defrecord Baz [z] Foo (bar [x y] (println x y z))) |
| 19:21 | Bronsa | ,(defprotocol Foo (bar [x y])) |
| 19:21 | clojurebot | Foo |
| 19:21 | Bronsa | ,(defrecord Baz [z] Foo (bar [x y] (println x y z))) |
| 19:21 | clojurebot | sandbox.Baz |
| 19:21 | Bronsa | ,(bar (Baz. 1) 2) |
| 19:21 | clojurebot | #sandbox.Baz{:z 1} 2 1\n |
| 19:22 | gastove | amalloy: AH. Okay. |
| 19:22 | gastove | amalloy: somehow, I missed the part about `this` arguments, so all my arities are off. |
| 19:55 | ToxicFrog | Hmm. |
| 19:55 | ToxicFrog | So I want something similar to cond, that evaluates a sequence of (condition, value) pairs. |
| 19:56 | ToxicFrog | But I want it to return not only the value, but the corresponding condition as well. |
| 19:56 | ToxicFrog | Is there a thing for this? |
| 19:57 | ToxicFrog | Hmm. Condp looks like almost what I want. |
| 20:04 | amalloy | ToxicFrog: condp with the :=> keyword or whatever it is might suit, but it'll depend on what conditions you're testing |
| 20:28 | bashed | Has anyone noticed slow lein on linux? I'm developing in both OS X and linux using Oracle Java 8 but the linux system has a very slow compile time. The machine it is on is not even comparable to the mac (more powerful) |
| 20:28 | amalloy | bashed: SSD? |
| 20:29 | bashed | Yeah |
| 20:29 | mmitchell | ,(map byte "foo") |
| 20:29 | clojurebot | (102 111 111) |
| 20:30 | mmitchell | (map byte "foo∂") |
| 20:30 | bashed | amalloy: Hah, thanks I guess. I'm using an SSD but my 'Dev' folder is mapped to a HD. I guess I should have thought about that sooner |
| 20:30 | mmitchell | hmm yeah, anyone know how to map a string with unicode to an array of bytes? |
| 20:31 | amalloy | ,(.length "foo∂") |
| 20:31 | clojurebot | 4 |
| 20:31 | amalloy | ,(seq (.toBytes "foo∂")) |
| 20:31 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: No matching field found: toBytes for class java.lang.String> |
| 20:31 | amalloy | ,(seq (.getBytes "foo∂")) |
| 20:31 | clojurebot | (102 111 111 -30 -120 ...) |
| 20:32 | amalloy | gets you the bytes in UTF-8; you can ask for other encodings if you are a heathen |
| 20:32 | mmitchell | nice, thanks amalloy |
| 20:35 | mmitchell | amalloy: oh hmm, and then back to a string? (map char ..) => java.lang.IllegalArgumentException: Value out of range for char: -30 |
| 20:35 | amalloy | mmitchell: why are you converting a string into bytes and back into a string? |
| 20:35 | amalloy | i mean it is not an impossible thing to do but it is weird |
| 20:36 | mmitchell | just curious! :) |
| 20:36 | amalloy | ,(String. (.getBytes "foo∂")) |
| 20:36 | clojurebot | "foo∂" |
| 20:36 | mmitchell | good grief, that looks so obvious now. Thanks amalloy |
| 20:36 | amalloy | and if you already have the seq of bytes, produced by (seq (.getBytes "foo∂")), you can call (byte-array xs) |
| 20:37 | mmitchell | ok nice |
| 20:54 | Shayanjm | anyone know if there's a canned algorithm to determine the minimum number of circles with fixed radius R to fill the area of a larger circle of some arbitrary radius N > R? |
| 21:12 | Travisty | Shayanjm: That sounds like a hard problem |
| 21:12 | gfredericks | Shayanjm: tight minimum? cuz you can get a lower bound by just dividing the areas |
| 21:12 | Shayanjm | gfredericks: would like to maximize for coverage as well as # of circles necessary |
| 21:13 | Shayanjm | thinking overlapping doesn't really matter |
| 21:15 | gfredericks | what does "maximize for coverage" mean? you already required filling the area |
| 21:16 | Travisty | Shayanjm: It sounds related to the disk-covering problem: http://en.wikipedia.org/wiki/Disk_covering_problem |
| 21:16 | Shayanjm | gfredericks: given R is fixed, there's a very good chance that full coverage is impossible given non-overlapping circles |
| 21:16 | Shayanjm | in the case of overlapping, sure full coverage is totally possible |
| 21:17 | gfredericks | how is it possible at all without overlap?? |
| 21:17 | lazybot | gfredericks: Uh, no. Why would you even ask? |
| 21:17 | Travisty | Shayanjm: If you’re talking about packing the smaller circles into the bigger one without overlap, the problem is certainly hard |
| 21:18 | Travisty | Shayanjm: http://en.wikipedia.org/wiki/Circle_packing_in_a_circle |
| 21:19 | Shayanjm | gfredericks: impossible to get 100% coverage with non-overlapping circles |
| 21:20 | Shayanjm | but you can get fairly close depending on R |
| 21:20 | Shayanjm | Travisty: Looking, thanks |
| 21:20 | Shayanjm | going to rough out an implementation i think |
| 21:20 | Travisty | If you manage to solve either problem exactly, I think that would be quite an accomplishment |
| 21:21 | Shayanjm | Travisty: Probably won't be near exact, but hopefully "good enough" to get the data I need |
| 21:21 | Travisty | (i.e., finding the smallest number N of circles of radius r required to cover a circle of radius R, or finding the maximum number of non-overlapping circles of radius r that you can fit in a circle of radius R) |
| 21:22 | Travisty | you might be able to come up with some bounds that aren’t too bad |
| 21:23 | Shayanjm | Travisty: Yeah that's the idea. I want to figure out how "rough" my implementation can be and still have half-decent results |
| 21:24 | pdk | genetic algos give you a good amount of leeway to be "rough" |
| 21:24 | Travisty | pdk: Do you really think genetic algorithms are a good idea for this problem? |
| 21:25 | Travisty | There are very simple ideas that seem like they should be within a factor of 2 |
| 21:25 | Shayanjm | I think trying to implement genetic algos to fit this model would be more problematic than helpful at this point |
| 21:25 | Travisty | i.e., laying the circles down in grid that is just fine enough that there are no empty spaces |
| 21:27 | Travisty | You know that you need at least (R/r)^2 circles, and you could compute the number of circles you use in that grid, which amounts to working out how close the points in your grid need to be and how many of those points land in the circle of radius R |
| 21:27 | Travisty | Seems plausible that it will also be on the order of (R/r)^2 |
| 21:28 | Shayanjm | Travisty: I'm going to try throwing something into code and seeing what sticks. In the middle of a seminar right now so can't really sit down and REALLY think about the problem |
| 21:29 | Shayanjm | but in ~30 mins i'm going to see if I can implement a hexagonal layout for overlapping circles, and then trial-and-error non-overlapping and seeing what happens |
| 21:30 | Travisty | You might want to spend some time deciding what you want to optimize. If you don’t require that the larger circle be entirely covered, then you need to find some way to trade between the competing objectives of coverage and using only a few circles |
| 21:31 | Shayanjm | Travisty: that's probably where a genetic algorithm would come in handy |
| 21:32 | Travisty | You shouldn’t need a genetic algorithm to state the problem you want to solve |
| 21:59 | justin_smith | Shayanjm: what you want is a packing algorithm I think |
| 22:00 | justin_smith | packing algorithms are about successively placing items, with goals of taking up minimal space, reducing overlap, whatever. |
| 22:03 | justin_smith | or filling the space to a maximal covered percentage with a minimum number of items, sounds like your problem. |
| 22:05 | justin_smith | not directly related, but an algo with a really cool output http://cs.stackexchange.com/questions/12925/circle-packing-algorithm-used-by-percolator |
| 22:14 | Shayanjm | thanks justin_smith |
| 22:14 | Shayanjm | do you know of any clj circle-packing implementations? |
| 22:14 | justin_smith | Shayanjm: no, but I worked on one for rectangle packing (basically trying to do something like masonry.js in cljs) |
| 22:15 | Shayanjm | ooh, justin_smith do you have code samples offhand that you don't mind me looking at? |
| 22:15 | justin_smith | it's open source |
| 22:15 | justin_smith | https://github.com/prismofeverything/netnetnet |
| 22:16 | justin_smith | wait... this isn't looking like the finished project at all |
| 22:16 | justin_smith | one moment |
| 22:17 | justin_smith | Shayanjm: correction, this is the repo - https://github.com/prismofeverything/tesselax |
| 22:17 | Shayanjm | great, thanks justin_smith |
| 22:18 | justin_smith | it's designed with the intention that eventually layout algos would be swapped out |
| 22:18 | justin_smith | (I wanted to do packing starting in the center and building out instead of starting at top left and moving down/right) |
| 22:19 | Shayanjm | justin_smith: turns out that's exactly how I want to attack my own packing problem |
| 22:19 | justin_smith | the inside out? |
| 22:19 | justin_smith | the issue you will see with our code base (likely) is that all of it implies rectangular geometry |
| 22:20 | Shayanjm | Yeah that's fine, I just wanted to see how you've structured your implementation |
| 22:20 | justin_smith | but maybe you can salvage it and add non-rectangular overlap / positioning rules |
| 22:20 | justin_smith | OK |
| 22:20 | justin_smith | we did make it theoretically pluggable |
| 22:20 | justin_smith | it is just that we didn't try plugging anything yet :) |
| 22:20 | Shayanjm | I probably won't reuse any/much of your code, but do you want attribution if I do? |
| 22:20 | justin_smith | it's EPL |
| 22:20 | justin_smith | just follow the rules of the EPL if you use our code |
| 22:20 | Shayanjm | Ahh yeah totally didn't look @ the license |
| 22:23 | justin_smith | the EPL is very permissive about redistribution, and even combining with non-epl code |
| 22:35 | l1x | is there a way to override what happens when a java lib throws an exception in a different thread in Clojure? |
| 22:36 | justin_smith | l1x: like maybe wrap the code for that thread in a try/catch? |
| 22:36 | justin_smith | or is the java lib creating the other thread offering you no option to modify the code running the thread? |
| 22:38 | l1x | i can try the try/catch but if the exception is caught in the lib it does not make it to clojure |
| 22:38 | l1x | at least this is my understanding |
| 22:51 | bashed | How do I use pprint to print a nested map as compactly as possible? (less new lines) |
| 23:46 | l1x | Don't know how to create ISeq from: scala.collection.immutable.Stream |
| 23:46 | l1x | damn |
| 23:46 | l1x | not everything is sequable?? |
| 23:46 | lazybot | l1x: Definitely not. |
| 23:46 | l1x | i know bro, and it is sad |
| 23:47 | justin_smith | l1x: did you try calling seq on it? |
| 23:47 | l1x | yeah |
| 23:47 | justin_smith | hmm... |
| 23:47 | l1x | (seq (.toSeq iterator) |
| 23:47 | l1x | the problem is that the lazy-seq implementation is broken |
| 23:47 | l1x | it hold onto the head |
| 23:47 | justin_smith | whose? |
| 23:47 | l1x | holds* |
| 23:48 | l1x | i am shoving you |
| 23:48 | l1x | showing |
| 23:48 | l1x | jeez my english degrades like |
| 23:48 | l1x | https://gist.github.com/l1x/7dc6f42c43d191bcfe41 |
| 23:49 | l1x | i should use (rest iterator) |
| 23:49 | l1x | i guess, but it is not sequable and you cant do that |