#clojure log - Feb 26 2015

The Joy of Clojure
Main Clojure site
Google Group
IRC
List of all logged dates

0:07 mercwithamouth: does anyone here prefer luminus to compojure? is luminus an alright choice or does it completely take over?

0: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

0:09 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

0:31 mercwithamouth: ddellacosta: fair enough. i think i'm fine with just compojure. though i'm sure luminus isn't as overbearing as rails

0:31 l1x: ' (for [a [0 1] b (range 10)] [a b])

0: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

0:35 mercwithamouth: goos to know

0:38 niac: (walk (fn [[k v]] [k (* 10 v)]) identity {:a 1 :b 2 :c 3})

0:39 can it rewrite #()

0:39 instead of fn

0:43 ddellacosta: niac: here's one way:

0:43 &(clojure.walk/walk #(vector (key %) (* 10 (val %))) identity {:a 1 :b 2 :c 3})

0:43 lazybot: ⇒ {:c 30, :b 20, :a 10}

0:43 ddellacosta: not sure that's much nicer

0:44 or,

0:44 &(clojure.walk/walk #(let [[k v] %] [k (* 10 v)]) identity {:a 1 :b 2 :c 3})

0:44 lazybot: ⇒ {:c 30, :b 20, :a 10}

0:45 ddellacosta: but considering the fn version is less verbose than these, I wouldn't bother

0:45 l1x: &(for [a [0 1] b (range 4)] [a b])

0:45 lazybot: ⇒ ([0 0] [0 1] [0 2] [0 3] [1 0] [1 1] [1 2] [1 3])

0:47 niac: ddellacosta: maybe the fn is the best way

0: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

0:50 niac: ddellacosta: thanks . i just try some code example on the web.

1:27 michaler`: going to implement users/roles/permissions system

1:28 i wonder if there is anything out there which i can use instead of rolling my own

2: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.

2:42 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.

2:45 TEttinger: that's a good question, bashed, but I don't feel qualified to answer

2:45 it might be a clojure.zip thing

2:45 egli: michaler`: have you looked at friend?

2: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)

3:23 michaler`: egli: hi

3:24 egli: i've used friend a while back but i don't think it provides a full roles/permissions solution

3: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)

3:29 sveri: I dropped friend in favour of buddy

3:30 egli: sveri: sure, buddy looks interesting

3: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

3:35 michaler`: egli: it provides some basic infrastructure maybe.. but i'm looking for a more full solution

3: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

3:37 michaler`: maybe this is something for you?

3: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.

3:42 sveri: also it sounded like they invested a lot of time into that. I'm hoping to have some basic simple system done today :)

4:12 Eremox: Does clojure have separate namespaces for functions and vars like common lisp?

4:12 justin_smith: no

4:13 hiredman: no, and vars in clojure are a kind of reference type, where in common lisp "var" is just short for variable

4:14 (which can be confusing when people trying to ask questions about "vars")

4:16 (namespaces are also a thing in clojure, sort of analogous to packages in common lisp)

4:17 TEttinger: (inc hiredman)

4:17 lazybot: ⇒ 72

4:19 Eremox: OK and functions are just like values in that vars reference anonymous functions? Which gives functions names right?

4: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

4:20 otherwise they are equivalent

4:20 hiredman: correct

4:20 but vars are not the only way names are bound to values

4:20 Eremox: OK thanks.

4:21 hiredman: locals also bind names to values

4:21 locals are function arguments or let bound names

4:22 ordnungswidrig: `fn` also can take a symbol for the name but I never understood it's purpose. defn macroexpands to fn without that.

4: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

4:22 justin_smith: ordnungswidrig: the purpose is twofold: self calls that are not in tail position, and making stack traces readable

4:23 ordnungswidrig: justin_smith: I see. But why doesn't defn use the name argument to fn?

4:24 Does the compiler do some extra work for the stacktraces if it finds a function in a var?

4:24 justin_smith: ordnungswidrig: because it doesn't need that for either of those reasons (the var / metadata suffice)

4:24 yeah, that's why it shows function names in stacktraces

4:25 ordnungswidrig: (def foo (fn bar [] (throw (Exception. "bogus")))) (foo)

4:26 that shows "bar" in the stacktrace. evil :-)

4: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

4:27 I like nil better :(

4: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..

4:39 tomjack: ,(let [plus (fn [x] (fn [y] (+ x y)))] (map (plus 3) [4 5 6]))

4:39 clojurebot: (7 8 9)

4:40 justin_smith: or you could just use partial, but neither that nor partial are currying

4:40 Glenjamin: Eremox: are you familiar with partial application?

4:40 currying is related, but i think partial is easier to grok initially

4:40 justin_smith: ,(map (partial + 3) [4 5 6])

4:40 clojurebot: (7 8 9)

4:40 tomjack: what is currying if not that?

4:41 Eremox: Yeah I think I get partial

4:41 justin_smith: tomjack: with currying the function returned will itself curry

4:41 tomjack: ah, just a different perspective. I think of 'currying' as some grunt work I have to do to my code

4:41 justin_smith: the point of currying is that it is implicit

4:41 tomjack: you think of it as something the function does for you, I guess

4:42 justin_smith: and clojure doesn't have currying - we opted for allowing varargs instead

4:42 tomjack: as a language feature, sure

4:42 justin_smith: tomjack: currying and partial evaluation both have definitions, and they are not the same

4:43 tomjack: I don't find dictionaries very useful

4:43 but: http://en.wiktionary.org/wiki/currying

4:43 Eremox: In the source of clojure there is a macro called defcurried or similarly why isn't that part clojure?

4:43 tomjack: the definition there seems to describe exactly what I thought did above :)

4:43 s/did/I did/

4:44 justin_smith: tomjack: "Currying is converting a single function of n arguments into n functions with a single argument each."

4:44 clojure's + cannot be curried, because it takes 0 or more args

4:44 sveri: michaler`: Well, I guess you will, I found it easy to integrate, do you need an example?

4:44 tomjack: sure, I considered only the 2-arity of +

4:44 :)

4:45 conversely, I guess, when doing the transformation in a curried language, one must introduce explicit vectors

4:46 justin_smith: tomjack: well, I guess you did turn + into two functions with one argument each

4:47 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

4:47 because varargs and currying mix very poorly

4:48 tomjack: I've been planning to attempt an experiment

4:48 build a toy language with the Clojure reader, which fully embraces ambiguity

4:49 try to write code and see which kinds of ambiguities make everything horrible

4:50 e.g. (instance? (-> Nat Nat) (+ 3)) but also (instance? Nat (+ 3)) ?

4:51 justin_smith: that would lead to some seriously ambiguous bugs

4:52 transducer arities are a miniature versin of the problem

4: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

4:53 justin_smith: (they are useful, I am glad they are there, but we lose compile time errors for a class of mistakes)

4: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

4:54 but I'm sure things will still be horrible if certain kinds of ambiguities are allowed...

4:55 justin_smith: tomjack: it would be a big change, right now clojure is not a "clever" compiler

4:56 tomjack: ah, uh, yeah.. the experiment would be a separate toy language with just some cosmetic similarity to clojure

4:56 justin_smith: yeah, just saying you wouldn't be able to leverage what exists very much is all

4:58 tomjack: right, except for (some) ideas and the reader, and Clojure in the non-meta-circular implementation

4:59 I conjecture that a small subset of Clojure is a good fit for the operational semantics of such a language

4:59 (if you can write a small clojure.core.logic{,.nominal}, I guess :( )

5:00 microkanren provides some hope

5:00 justin_smith: I've been awake for 22 hours, time for sleep

5:00 * justin_smith waves.

5:00 tomjack: ditto :(

5:01 justin_smith: I saw an excellent horror film with sleep deprivation themes today too

5:01 babadook

5:01 bye

5:01 ordnungswidrig: justin_smith: have a great nap.

5:36 tomphp: Hi

5:40 I have a rather a couple simple interop (proxy) question which I can't find any references to

5:40 1) Can you set a constructor function?

5:41 2) how to you call other "methods" in the object - is proxy-super only for super or is there a this/self function?

5:41 thanks ;-)

6:22 mnngfltg: In my REPL: OutOfMemoryError PermGen space java.lang.ClassLoader.defineClass1

6:22 what now?

6:36 hyPiRion: restart repl

6:36 and/or run java 8

6:38 mnngfltg: hyPiRion, installing java 8 now

6:53 martinklepsch: mnngfltg: hyPiRion or https://github.com/boot-clj/boot/wiki/JVM-Options#permgen-errors

6:54 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

6:56 my test looks like this: https://gist.github.com/martinklepsch/8c80e90fbd2ec332d0c6

7:27 ggherdov: ,(cons :a [:b])

7:27 clojurebot: (:a :b)

7:27 agarman: ,(conj [:b] :a)

7:27 clojurebot: [:b :a]

7:27 ggherdov: uhm. I'd like [:a :b] instead

7:28 agarman: ,(conj #{:b} :a)

7:28 clojurebot: #{:b :a}

7:28 agarman: ,(conj '(:b) :a)

7:28 clojurebot: (:a :b)

7:28 ggherdov: sure, but conj puts the elem wherever it pleases it.

7:28 i'd like to keep the collection type -and- prepend the new elem.

7:29 agarman: it puts it at the best place by the data structure

7:29 prepending to a vector is **slow**

7:30 it's designed for append

7:30 append is O(1) v O(n log n)

7:30 for prepend

7:31 ggherdov: base of the log? is it the log32 thing?

7:31 anyway I have small vectors, I was just ranting at cons changing the type.

7:32 agarman: cons operates on lists, just like it does in every other lisp ever

7:32 ggherdov: ok

7:33 agarman: far more people would bitch about that changing than having to use conj if you want to retain the collection type

7:33 ggherdov: I see

7:35 agarman: also, if you want to pull elements out of a vector without changing the collection type:

7:36 ,(rest [1 2 3]) (next [1 2 3) (pop [1 2 3])

7:36 clojurebot: (2 3)

7:36 agarman: ,[(rest [1 2 3]) (next [1 2 3) (pop [1 2 3])]

7:36 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

7:36 agarman: ,[(rest [1 2 3]) (next [1 2 3]) (pop [1 2 3])]

7:36 clojurebot: [(2 3) (2 3) [1 2]]

7:36 ggherdov: ok

7:37 agarman: ,[(first [1 2 3]) (peek [1 2 3])]

7:37 clojurebot: [1 3]

7:38 agarman: or just use cons, first et al because your vectors are small (ergo they'll likely work just fine as lists)

7:39 ggherdov: sure

8:10 hiteki: hi

8: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`)

8:48 martinklepsch: mnngfltg: well, that JVM options thing should work for both :)

8: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 * TimMc hurries to create a web stack called "du-jour".

11:27 mbac: what are some fun clojure tutorials

11:27 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 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 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 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 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 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 the function with the actions should be trivial, and then you test the result of the function with the logic

11:52 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 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 by testing their return values of course

11:55 which in the actual program will "drive" the side effecting functions

11:55 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 You know, like you do to "reduce" :-)

11:59 justin_smith: chouser: it's true, that is also a good alternative

12:00 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 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 what you test about the decision making function is the data structure it returns

12:01 or in chouser's version, you pass it a verifier function instead of a side effectful one

12:02 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 one function returns data representing the thing to be done

12:08 easy to test

12:08 the other takes data, and does an action

12:08 a third function connects them

12:09 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 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 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 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 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 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 that is probably the simplest way to try this general pattern

12:23 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 s/returning/passing in

12:23 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 but definitely pass in a buffered reader, don't slurp a string then read-string

12:39 crazydiamond: good to know

12:40 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 unless the input file is a given

12:51 crazydiamond: justin_smith, is this example of buffered reader?

12:51 (with-open [rdr (clojure.java.io/reader "/tmp/foo.txt")]

12:51 (reduce conj [] (line-seq rdr)))

12:54 l1x: morning

12:54 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 but (partial .contains "a") gives a runtime exception, unable to resolve symbol

12:55 l1x: https://gist.github.com/l1x/836b23fe864dd0db1259

12:56 i am trying to process N message streams lazily and I need to consume 1 (or few) message from each stream

12:57 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 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 #(.contains "a" %) would be the equivalent

12:58 clov3r: TimMc: ok, well that;s good to know

12:58 thanks :)

13:01 justin_smith: l1x: (doseq [stream-heads (apply map list streams) stream stream-heads] ...)

13:01 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 i am thinking about creating a go-loop for each stream

13:02 and just send it to a channel

13:02 tomjack: yes!

13:02 seqs don't seem right to me

13:02 l1x: doseq is no good though, because it holds the head afaik

13:02 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 and when i replaced it with loop it went away

13:04 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 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 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 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 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 crash_ep: the channel *uses* the buffer, it knows when and how to apply the transformer

13:34 s/many/make

13:34 tbaldridge: dnolen: but the channel basically wraps the .add method of the buffer with the transducer,

13:36 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 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 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 asked

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 something like carbon-c-relay to do the aggs for you

14:31 SegFaultAX: AeroNotix: Ok, that's fair enough.

14:31 AeroNotix: Thanks so much for your time.

14:31 AeroNotix: SegFaultAX: think nothing of it

14:31 * SegFaultAX forgets everything he just learned.

14:31 AeroNotix: yay

14:31 SegFaultAX: Anyone here use Cyanite?

14:32 * SegFaultAX ducks

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 ,'#((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 ,(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 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 ,(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 {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 my bad

15:33 zerokarmaleft: a lot of interesting variations of lens cropping up in the clojure space

15:33 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 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 maybe it's print-depth, i forget

15:52 &(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 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 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 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 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 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 could not recommend it highly enough

17:39 sdegutis: bigs: hmm, thanks for the testimony

17:39 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 that you can raise up highly enough so that your forearms are flush

17:40 sdegutis: bigs: clever

17:40 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 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 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 aye massdrop.com

17:41 afaik the only place selling ergodox kits

17:41 sdegutis: aww requires account

17:41 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 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 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 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 that's why i got a kinesis :P

17:48 needed a solution immediately

17:48 scottj: bigs: do you use emacs btw?

17:48 bigs: i'm a vimmer

17:48 but i use emacs w/ evil mode

17:48 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 to take care of that

17:53 ah -- also the kinesis is hardware programmable

17:53 which is awesome

17:53 sdegutis: whats that mean?

17:53 is that kind of like atreus's firmware?

17:53 bigs: can reprogram keys on the unit itself

17:53 no software

17:53 sdegutis: re https://github.com/sdegutis/atreus-firmware

17:54 bigs: you use querty or colemak?

17:54 lol @ phonic typo

17:55 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 absolutley -- feel free to pm me whenever. this is something i've spent a lotta time on

17:56 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 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 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 ooh

17:59 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 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 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 but now, i have a fully fledged idiomatic Kafka client in Clojure \o/

18:57 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 or one queue shared by the threads running the code, each one taking items off

18:58 whatever makes sense for your setup

18:58 l1x: justin_smith: right

18:58 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 i might just use a normal loop + recur

19:00 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 amalloy: somehow, I missed the part about `this` arguments, so all my arities are off.

19:55 ToxicFrog: Hmm.

19:55 So I want something similar to cond, that evaluates a sequence of (condition, value) pairs.

19:56 But I want it to return not only the value, but the corresponding condition as well.

19:56 Is there a thing for this?

19:57 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 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 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 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 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 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 but you can get fairly close depending on R

21:20 Travisty: Looking, thanks

21:20 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 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 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 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 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 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 packing algorithms are about successively placing items, with goals of taking up minimal space, reducing overlap, whatever.

22:03 or filling the space to a maximal covered percentage with a minimum number of items, sounds like your problem.

22:05 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 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 https://github.com/prismofeverything/netnetnet

22:16 wait... this isn't looking like the finished project at all

22:16 one moment

22:17 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 (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 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 OK

22:20 we did make it theoretically pluggable

22:20 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 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 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 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 damn

23:46 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 the problem is that the lazy-seq implementation is broken

23:47 it hold onto the head

23:47 justin_smith: whose?

23:47 l1x: holds*

23:48 i am shoving you

23:48 showing

23:48 jeez my english degrades like

23:48 https://gist.github.com/l1x/7dc6f42c43d191bcfe41

23:49 i should use (rest iterator)

23:49 i guess, but it is not sequable and you cant do that

Logging service provided by n01se.net