#clojure log - Oct 07 2015

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

0:34 Jaood: '

0:35 wmealing: '

0:35 i couldnt let that go unmatched

0:35 justin_smith: ' doesn't need a match in clojure

0:36 wmealing: oh NOW people talk

0:36 ;P

0:36 amalloy: justin_smith couldn't bear to see your correction go uncorrected

0:36 justin_smith: things have been getting quiet around here

0:36 amalloy: justin_smith: is everything in slack now, or what?

0:37 justin_smith: it's pretty active... but I can't use it like I do IRC

0:37 too much of an "app"

0:37 wmealing: what is slack ?

0:37 https://slack.com/?r=1 ?

0:37 justin_smith: it's an app that's a lot like IRC, and there's a clojurians channel there that a lot of people are using now

0:38 it even has an IRC gateway that I may eventually set up, my workplace uses slack

0:42 last I checked, having an archive / searchable log / on slack cost money, so clojurians doesn't have a searchable backlog

1:13 Frozenlock: Gotta love all those new shiny stuff. Remember when email was broken? Now we have Facebook messages. Wheeeeee

1:16 wmealing: i didnt think that any of it was broken

1:17 Frozenlock: It wasn't, nor is IRC.

1:18 TEttinger: being able to post snippets of code inline with a preview is pretty nice though, on slack

1:18 mungojelly: i think irc is still awesome but it could also be improved, like why don't we have any irc clients that understand richer text, we wouldn't have to change anything about the infrastructure just put <i> or w/e and parse it on the other side

1:18 TEttinger: I like Gitter better than Slack, less signing up :P

1:19 mungojelly: signing up prevents abuse which is why the internet has been such a sparlking fantastic positive place since we started having to sign up everywhere /s

1:19 amalloy: yeah, i use slack at work, but i am not willing to sign up for slack in order to try the clojure slack

1:42 devangshah: how can i use java functions inside the anonymous functions as part of map or filter?

1:42 justin_smith: devangshah: by using java methods inside anonymous functions

1:43 devangshah: i am trying to access them using (doall (filter #(.isDirectory) (file-seq (io/file dirpath))))

1:43 justin_smith: devangshah: you need % to indicate the argument

1:43 #(.isDirectory %)

1:44 devangshah: silly me…

1:44 thanks anyway..

1:44 newbie to clojure

1:45 justin_smith: devangshah: #(foo) is a function of no arguments that calls foo, the argument count expected is determined by the usage of %, %2, etc. you can also use %& for varargs

1:46 devangshah: yes.. i knew it.. even i used it in my project.. but somehow i missed here.. thanks anyway..

2:11 sm0ke: ,(clojure.java.shell/sh "pwd")

2:11 clojurebot: #error {\n :cause "clojure.java.shell"\n :via\n [{:type java.lang.ClassNotFoundException\n :message "clojure.java.shell"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java.net.URLClassLoader$1 run "URLClassLoader.java" 366]\n [java.net.URLClassLoader$1 run "URLClassLoader.java" 355]\n [java.security.AccessController doPrivileged "AccessController.java" -2]\n ...

2:11 justin_smith: ,(System/getenv "PWD")

2:11 clojurebot: #error {\n :cause "access denied (\"java.lang.RuntimePermission\" \"getenv.PWD\")"\n :via\n [{:type java.security.AccessControlException\n :message "access denied (\"java.lang.RuntimePermission\" \"getenv.PWD\")"\n :at [java.security.AccessControlContext checkPermission "AccessControlContext.java" 372]}]\n :trace\n [[java.security.AccessControlContext checkPermission "AccessControlContext.java...

2:11 justin_smith: :P

2:12 sm0ke: ,(do (require 'clojure.java.shell) (clojure.java.shell/sh "pwd"))

2:12 clojurebot: #error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__883 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__883 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkExec nil -1]\n [java.lang.ProcessBuilder start "Process...

2:12 sm0ke: ok but does (sh/sh "echo foo") works for anyone?

2:13 wmealing: ,(do (require 'clojure.java.shell) (clojure.java.shell/sh "echo $ENV"))

2:13 clojurebot: #error {\n :cause "denied"\n :via\n [{:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__883 invoke "sandbox.clj" 69]}]\n :trace\n [[clojurebot.sandbox$enable_security_manager$fn__883 invoke "sandbox.clj" 69]\n [clojurebot.sandbox.proxy$java.lang.SecurityManager$Door$f500ea40 checkExec nil -1]\n [java.lang.ProcessBuilder start "Process...

2:13 sm0ke: ah its supposed to be used like (sh/sh "echo" "foo")

2:13 weird

2:14 justin_smith: also it won't expand globs and doesn't really call sh

2:15 sm0ke: (sh "echo" "-n foo") (sh "echo" "-n" "foo") are different

2:16 interesting implementation

2:19 opqdonut: sm0ke: no, a very standard implementation

2:19 sm0ke: works just like the C exec

2:19 though I have to admit it's a bit weird to call it sh and not do sh-like command handling

2:21 sm0ke: there is a `sh` in C which is completely different

2:21 so you can compare it to `exec` and call it normal

2:21 opqdonut: do you mean `system` in C?

2:22 sm0ke: its like saying my cat is absolutely fine just that it looks like a elephant

2:22 opqdonut: yeah, I do agre that it is surprising

2:22 *agree

2:27 mungojelly: (clojure.java.shell/sh "clojure" :in "(clojure.java.shell/sh \"clojure\" :in \"(print \\\"hi\\\")\")")

3:05 nXqd: hi guys how can I pass the keys parameter in function call as a variable. For example : (def base-keys [username password]) (defn x [& {:keys base-keys} ())

3:08 sm0ke: ,( (fn [& {:keys [foo]}] (prn foo)) :foo 1)

3:08 clojurebot: 1\n

3:08 amalloy: ~mapply

3:08 clojurebot: You have to do something like (defn mapply [f & args] (apply f (apply concat (butlast args) (last args)))), which just goes to show why unrolled keyword args are a bad idea

3:08 sm0ke: is this what you meant?

3:08 amalloy: oh, that. ignore mapply

3:08 you can't do that at all

3:08 somewhere i ahve a stackoverflow answer that is semi-relevant

3:09 nXqd: sm0ke: if i understand correctly, the example you show does show the normal usage of parameter destructuring

3:10 amalloy: basically you don't want to do that: instead define the function as taking a map, and write a simple macro like (with-user user body) that destructures username and password out of the user map

3:10 nXqd: what I want is to pass the key as variable

3:10 sm0ke: ,(let [key :foo] ( (fn [& {:keys [foo]}] (prn foo)) key 1))

3:10 clojurebot: 1\n

3:10 nXqd: yeah it would be a better way :P

3:11 amalloy: you can't

3:12 nXqd: amalloy: and btw, how to insert multiple value to a record in datomic. For example : I have email, password, name in the function, then I can insert some how all of the dynamically

3:12 instead of specify each like :user/email email, :user/password password

3:12 amalloy: beats me. i can't even insert one anything into datomic

3:13 nXqd: hmm @(d/transact conn [{:db/id (d/tempid :db.part/user) :user/email email :user/password password}])

4:03 Fender: Hi guys, I want an async web server in clojure (such as httpkit or ring-async), however, most servers are not able to deal with an async channel for the *complete* response (instead, the only the body is an async channel). This means, I cannot set the HTTP status code of the response and I'll probably have to respond with 200 all the time. Then there's jet, that is able to do it but was obviously compiled against Java 8. So - is it usual to

4:05 TMA: Fender: your question was chopped off after "So - is it usual to"

4:06 Fender: thx - "So - is it usual to always respond in async servers with HTTP 200, am I missing something or is there no good server for my problem?"

4:41 nXqd: anyone here using component, please explain me what is map->ComponentName , is map-> a macro or something. how is it defined ? thanks

4:42 ianhedoesit: map->* is a constructor created by defrecord

4:44 I suppose factory functions might be easier to distinguish due to the OO hold on the term "constructor"

4:44 ->TypeName takes positional parameters to field values and map->TypeName takes a map of keywords to field values

5:02 tdammers: so I'm having a bit of trouble adjusting to clojure (coming from Haskell)

5:02 my main gripe is that every fn reads as something like "Anything -> Anything -> ... -> IO (Maybe Anything)

5:03 and the only strategy I've found so far for understanding what it does is reading the code

5:03 including all of its dependencies

5:03 but I can't help but think that there must be a better way

5:05 ianhedoesit: you mean you don't know how to understand functions in Clojure because there's no type hints or anything?

5:05 (I'm not trying to sound rhetorical or anything, I'm trying to understand your problem)

5:07 tdammers: pretty much, yes

5:07 sometimes, there's documentation, which helps a lot, but still

5:08 nXqd: ianhedoesit: hey thanks ! I didn't notice Clojure has bunch of -> factory function :)

5:08 tdammers: e.g., I'm working with kioo here, and there are all these macros that take an optional emit-opts argument

5:08 there is no documentation on that argument

5:09 ianhedoesit: nXqd: it actually (I think?) only has the two that are generated from defrecord (->TypeName and map->TypeName)

5:09 they're pretty handy.

5:09 tdammers: in order to figure out how to use it, I have to descend about 4 or 5 levels into the call chain

5:09 several paths, even, because each call dependency looks at a different key

5:10 this is really not a complaint, I just want to know where the "easy" button it

5:10 *is

5:12 ianhedoesit: tdammers: I think that's one of the common complaints (and something I worry about with dynamic languages) about all dynamic languages, no?

5:12 tdammers: ianhedoesit: yes

5:12 ianhedoesit: one of the huge niceties of Haskell, for example, is that you can just look at a function signature and know, at least, exactly what types you need to pass to a function to do _something_

5:13 tdammers: exactly

5:13 ianhedoesit: in dynamic languages you don't have that option. however, core.typed and Prismatic/Schema try to help with that.

5:13 tdammers: also, even with nothing but type signatures in place, the generated documentation is still useful in that you can easily click through to anything any function references

5:17 ianhedoesit: well to attempt an answer of your initial problem/question, you have to rely on good code, for the most part. also making assumptions like (defn foo [m k v] ,,,) probably takes a map, a key, and a value, etc.

5:17 or add type hints and whatnot.

5:17 tdammers: so it takes a map; but which keys does it expect, which values are allowed for them, etc.

5:21 ianhedoesit: that's typically where you need to look at the docstring

5:22 I don't know if that's all that different even for statically typed languages though? just because you have Map -> Key -> Anything -> Map doesn't mean you know what exactly to pass it either

5:23 you can have the same questions ("What key? What Anything? What's the Anything used for?" etc.)

5:25 tdammers: except that typically you wouldn't be using `Map Anything Anything -> Anything -> IO Anything`, but rather something like `Map UserID User -> UserID -> Maybe User`

5:26 ianhedoesit: true, but then you need to define all those things, no?

5:26 (I have virtually 0 experience with Haskell, so excuse my ignorance in this situation)

5:27 tdammers: you have to do that anyway, either explicitly (through data types) or implicitly (through the code that handles them)

5:27 can be as simple as newtype UserID = UserID Int, even

5:27 or even just type UserID = Int, which is less useful, but still acts as documentation at least

5:28 but yes, defining your data types upfront does form a bit of overhead

5:36 mungojelly: couldn't you also just type a program strongly enough that you don't need anything but types, that the whole flow of the program can only go one way b/c types, has anyone done that yet?

5:36 amalloy: yes, you can just run your entire program inside the compiler

5:37 but then it's no easier to analyze than a program that runs ar tunrime

5:37 tdammers: GHC's type checker itself is turing complete, so you can write anything in it, yes

5:37 mungojelly: like you'd have a function processed-some -> processed-more, and then processed-more -> processed-most, and processed-most -> done, and so it's just in the types how to compute the result

5:38 turing complete, everything's turing complete. :/ don't we have any better standards

5:39 tdammers: not everything is turing complete

5:39 most of the older SQL dialects aren't

5:39 many type checkers aren't either

5:39 mungojelly: but i mean people say something's turing complete like that proves you could do anything useful with it, but what did anyone make with a turing machine lately

5:40 tdammers: the thing about TC is that if you can implement an algorithm in one TC language, you can implement it in all of them

5:40 theoretically speaking at least; practical considerations often make the implementation unfeasible

5:41 (e.g., it'd require way more memory than we can provide, or it would take very long to run)

5:42 mungojelly: i want to bound my queues but i have unreasonable amounts of data coming into them, what's my problem called

5:42 opqdonut: see also "turing tarpit"

5:42 emauton: Or it'd be a nightmarish inverted tower of Babel spiralling down into the nine hells of computing. ;o)

5:42 mungojelly: "overload"

5:43 mungojelly: i know some strategies like (a) forget oldest unprocessed requests (b) drop new requests (perhaps applying backpressure)

5:44 emauton: Have a read of chapter 3 of "Erlang in Anger" by Fred Hebert (it's free online).

5:44 mungojelly: idk i just thought of (c) putting new things into random spots once the queue's full

5:44 emauton: ok thanks will do :)

5:44 opqdonut: dropping random stuff is good

5:44 has all sorts of nice theoretical properties

5:44 tdammers: "load shedding"

5:44 ^ useful google incantation

5:44 mungojelly: yeah i felt that as soon as i started running it in my mind, i was like huh well then at least it does its best like *statistically*

5:45 tdammers: yes

5:45 if you take great care to shed in "atomic" units, then that's probably the best you can get

5:45 mungojelly: ooh, "load shedding" is a good term for it. that's the opposite of the hell of naming i guess, the heaven of beautiful names.

5:54 ianhedoesit: tdammers: I stepped away for a minute, so this is backtracking a couple screens, but that is interesting. however, for complex types I fear the overhead would be much more significant, no? also, it's much less composable, is it not?

5:55 I don't know if I can make a point for the composability of either form, though

5:57 tdammers: I'd argue that it's *more* composable, because the mental overhead stays constant as your codebase grows

5:57 also, you usually use type variables and constraints rather than actual types in your signatures, so your code stays generic and composable

5:58 ianhedoesit: as in Int instead of UserID, but a UserID could still be passed?

5:58 or what do you mean by that?

5:58 tdammers: no, more like how, for example, fmap can map over any functor, not just lists

5:59 instead of writing :: (String -> String) -> [String] -> [String]

5:59 mungojelly: did y'all see that talk from strangeloop this year about chemical computing? that's like there's just types or just types and environments and the program makes the specific connections for you

5:59 tdammers: we write it as :: Functor f => (a -> b) -> f a -> f b

5:59 and with that, you can use fmap on lists, vectors, maps, maybes, eithers, etc.

6:00 amalloy: tdammers: it might be easier to start with map instead of fmap, and explain how the types for *that* work, because it's more familiar

6:00 tdammers: amalloy: yeah, probably

6:00 amalloy: was using fmap because that's more reusable and generic

6:01 map is kind of inbetween, in that it takes lists of a variable type, but they still have to be lists

6:01 :: (a -> b) -> [a] -> [b]

6:01 amalloy: well yes, but if you don't understand how map can be typed generically (i didn't, when i was starting to figure out functional programming) thenfmap is hopeless

6:02 tdammers: I'm assuming an audience that is familiar with generic functions here

6:08 dragon-irl: Is there a way to get intellij to resolve js calls when using cursive?

6:17 mungojelly: everything about backpressure and granting resources says to make a request queue of things that want the resource but what if you get too many *requests* to even handle those, how do i like pass out a finite number of request tickets

6:22 ianhedoesit: tdammers: is `map :: (a -> b) -> [a] -> [b] really more simple than `map ([f coll])`?

6:22 tdammers: not by itself

6:23 ianhedoesit: I realize that since I have very little understanding of Haskell, it's more difficult for me to parse it mentally, but seeing that my parameters are "f" and "coll", I assume it wants a function and a collection

6:23 amalloy: the point is that you can write (map 5 *) in clojure, and the compiler doesn't know that's wrong

6:23 tdammers: but checking whether String -> Text is a valid first argument for (a -> b) -> [a] -> [b] is much easier than judging whether (fn [x]) is a valid first argument for (fn [f c])

6:23 ianhedoesit: I know what a and b should be in Haskell's map, but if I didn't know what the map function does from an abstract point of view, I would have no idea

6:24 amalloy: with a static type the compiler can know enough to say "that's not how you use map"

6:24 tdammers: actually, there's not an awful lot the map function can do, given its type signature

6:24 ianhedoesit: amalloy: I know, and I agree that it's a valid complaint, and I worry about that too when thinking about committing time to a dynamic language

6:25 tdammers: it could reverse the list while processing it, or it could completely ignore the function argument and always produce an empty list, or it could stop mapping after reaching a hard-coded limit

6:25 but if you add the convention that the function does not add any hard-coded information, nor ignore any of its input, then map's behavior is pretty much completely described by its type signature

6:25 clojurebot: A nod, you know, is as good as a wink to a blind horse.

6:27 * TMA was a huge fan of dynamic typing in the past

6:27 ianhedoesit: I really should try to spend more time with Haskell. but I love my lisps the more I use them.

6:29 TMA: why only in the past?

6:29 TMA: but then I got to a point where I realized that it was not the static typing that made me uneasy, it was rather the unexpressiveness and burden thereof (C/C++/Java type systems)

6:30 tdammers: those languages have done a lot to set back statically typed languages

6:31 TMA: ianhedoesit: in a sense, dynamic typing is like global mutable state but applied to the metaprogram

6:31 ianhedoesit: I agree to some degree.

6:32 TMA: it can bite you if you do not pay attention (like passing a (fn [a b] ...) to first argument of map)

6:32 mungojelly: every paradigm has a mixture of typing strategies depending on where you look, you're always dynamically determining the meanings of some things

6:33 TMA: but it is hidden (not readily apparent)

6:34 I caught myself adding (declaim (ftype (function (...) ...) ...)) in my CL programs as a form of documentation

6:35 ianhedoesit: TMA: what are your feelings on things like core.typed, Schema, or Typed Racket, for example?

6:38 TMA: ianhedoesit: I think that gradual typing is somehow THE way; however, I have not yet managed to immerse myself in any of those

6:39 ianhedoesit: hm, thanks.

6:39 TMA: what would you say your language of choice is today?

6:39 TMA: like: bang together the prototype and then add the type annotations to hunt down some of the bugs

6:39 ianhedoesit: as far as static typing goes

6:40 TMA: ianhedoesit: it depends on the problem [and the environment]

6:41 but mostly I write my code in any language at hand, while designing (in my head) the thing in lisp code with haskell types

6:41 ianhedoesit: fair enough

6:42 TMA: unfortunately I forego most of the benefits of the compiler in this way :(

6:42 ianhedoesit: I suppose the answer I was hoping for was something like "try Haskell to feel the power of a proper statically typed language"

6:42 tdammers: "lisp code with haskell types" sounds like a great mode of operation

6:42 TMA: but the interoperability is much more importatnt to ship the result

6:43 sometimes prolog lends its hand in too :)

6:44 ianhedoesit: by all means, try it out

6:51 yesterday, I was hunting down a persistent NullPointerException in Java code, when I finally found the place that was causing it, I really missed my Maybe monad

6:55 spacepluk: hi, I need to build a very big JSON string incrementally by appending small pieces very quickly over a period of time. What would be an efficient clojureish solution for this?

6:55 should I just use interop with StringBuffer or is there a better way?

6:57 tdammers: you could write the JSON to a stream

6:58 that way you could avoid having it all in RAM at once

6:58 clojurebot: It's greek to me.

6:59 ianhedoesit: TMA: I do really like Maybe (from what I understand of it)

7:00 tdammers: it's really just null checks lifted to the type level

7:00 ianhedoesit: right, but that's powerful.

7:00 tdammers: although, because Maybe is also a Monad, you get a bunch of things for free

7:01 such as short-circuiting Maybe calculations as soon as one of the operands is Nothing

7:01 do { x <- Just 1; y <- Just 2; return (x + y) }

7:01 or, in applicative syntax, (+) <$> Just 1 <*> Just 2

7:02 ianhedoesit: Haskell's syntax also scares me every time I try to get involved with it.

7:02 I also find myself wanting to resort back to simple sexps

7:04 tdammers: Lisp syntax scares me... everything looks the same, even when it's something radically different

7:04 ;)

7:07 ianhedoesit: I have the opposite fear. having (according to you) `do { x <- Just 1; y <- Just 2; return (x + y) }` and `(+) <$> Just 1 <*> Just 2` (I assume the return statement was left out, but would be after `Just 2`) be the same confuses and upsets me.

7:11 TMA: tdammers: the pointless style scares me; and it even does not solve the problem of getting rid of the parentheses

7:11 ianhedoesit: I'd rather have everything look alike. I like that def, -> and + are three entirely different things, but (def a) (-> a) and (+ a) are all valid

7:12 TMA: pointless style?

7:12 TMA: ianhedoesit: pointfree

7:12 TEttinger: ianhedoesit: I think you missed a winky emoticon <tdammers> ;)

7:14 TMA: ianhedoesit: let's assume for a while an exotic clojure dialect where there are partial applications

7:14 ianhedoesit: TEttinger: I saw it but I'm not sure what inflection that's supposed to add

7:14 TEttinger: not serious?

7:15 that inflection

7:16 TMA: ianhedoesit: (f a b c) is just a shorthand for (((f a) b) c)

7:17 ianhedoesit: TEttinger: oh, I assumed he was serious. I figure it's actually pretty common that people don't like that everything looks the same.

7:19 TMA: ianhedoesit: so instead of (defn x [a b c] (f a a b c)) you write (def x (join f)), never mentioning the arguments at all

7:19 tdammers: ianhedoesit: there is no return statement in Haskell. return is a function that "wraps" a value in a monad. it's not a statement, it doesn't return from a function, it "returns a value into a monad"

7:20 re everything looks the same: I was half serious there, in that I do think having different things look different is good, and in case of doubt, I prefer sacrificing "same things look the same" for that

7:20 TMA: ianhedoesit: "return" is a haskelese for unit :: Monad m => a -> m a

7:21 tdammers: in haskell everything (but the type declarations) looks the same

7:21 tdammers: TMA: I would say in Haskell, you have a lot of room for making things look different

7:21 ianhedoesit: TMA: so then with x what do you do? how do you use it if it's defined as just (join f)?

7:22 tdammers: applicative syntax is done entirely in Haskell itself, no special cases in the compiler are needed

7:22 TMA: ianhedoesit: you call it as usual: (x a b c)

7:23 tdammers: re point-free style:

7:23 consider map

7:23 (map f items)

7:23 TMA: point-free style is awesome to write, but hell to read :-L

7:23 tdammers: now, "map f over something" is very common, it's basically a specialization of map

7:24 you could wrap that in a function like so:

7:24 (fn [x] (map f x))

7:24 the "x" in there is often called a "point" in Math textbooks

7:25 "point-free", then, just means that we write the function such that no points appear

7:26 which, if clojure functions were automatically curried, would just be (map f)

7:26 ianhedoesit: oh okay.

7:26 tdammers: and in Haskell, we can do exactly that: passing too few arguments produces a new function that takes the remaining arguments

7:27 ianhedoesit: so currying is key

7:27 tdammers: that's one way to look at it, yes

7:27 ianhedoesit: I was mostly just wondering what "(+)", "<$>" and "<*>" were.

7:27 tdammers: oh, that

7:28 (+) is just the + operator, but the parentheses allow us to use it in prefix notation

7:28 TMA: "(+) a b" is just another way to write "a + b"

7:28 tdammers: <$> and <*> are library-defined operators from applicative

7:28 <$> is an alias for fmap

7:29 TMA: tdammers: like (<$>) = fmap ?

7:29 tdammers: yes, that's exactly how it's defined

7:30 ianhedoesit: what is <*>?

7:31 TMA: holy whatever! why? why? why would you take a fine function with established name and rename it to a haphazardly named operator of unknown precedence and associativity?

7:32 tdammers: (<*>) :: f (a -> b) -> f a -> f b

7:33 i.e., it takes a pure function and converts it into a function that works on the same types wrapped in some applicative

7:33 hyPiRion: TMA: Because f <$> a <*> b is easier to read sometimes.

7:33 ianhedoesit: that's another question. so in the above example of `(+) <$> Just 1 <*> Just 2`, is `(+) fmap Just 1 <*> Just 2`?

7:33 equivalent*

7:33 TMA: ianhedoesit: no

7:34 tdammers: fmap (+) Just 1 <*> Just 2

7:34 ane: <$> is defined as an infix operator

7:34 TMA: you would need to wrap the fmap in `fmap` backticks

7:34 ane: if you did (+) `fmap` ... that would work

7:34 ianhedoesit: oh, I see.

7:34 ane: (backticks make anything act as infix)

7:34 ianhedoesit: yeah, I remember that now.

7:34 tdammers: the reason why applicative syntax is so popular is because of the similarity between pure function application and applicative function application:

7:34 f x y ==> f <$> x <*> y

7:35 the first calls f on two pure values; the second one calls the same function on two values in some applicative functor and returns the result back into it

7:35 the function itself is blissfully ignorant of the functor's plumbing

7:36 and you can write the whole thing almost like you would write pure code, except that the functor takes care of handling effects for you

7:36 e.g., I/O, failure, iteration, etc.

7:36 it's kind of like taking function application to a higher abstraction level

7:37 (hence the name "applicative functor")

7:37 TMA: and then you come across ((.) <*>) and you give up on haskell

7:37 tdammers: well, of course all of these features can be abused into academic obscurity

7:37 MasseR: TMA: you can always overdo stuff, but that syntax isn't really recommended :)

7:41 TMA: I have learned haskell in 2001 or 2002 IIRC; the simple typing rules have stuck in my head [the not so simple have gone]. I have tried to get back to Haskell since the last year, but I consistently hit the wall

7:42 most of the "new" stuff seems to be heavily fond of avoiding alphabetic characters and parentheses, except to turn the operators into their prefix form

7:44 MasseR: TMA: Ignore everything about lens and it will be much, much easier

7:44 mungojelly: yeah i like the ideas about typing but i don't quite understand or even believe that the perl syntax has anything to do with them

7:48 * TMA has not yet even heard of haskell lenses before today

7:49 MasseR: someString & allVersions %~ succ

7:49 as an example

7:50 But really, avoid them :)

7:56 ianhedoesit: well I've learned a lot about everything other than Clojure tonight.

7:56 so thanks everyone for that. :)

7:59 clgv: aleph question: My IdleStateHandler does not fire IdleStateEvents on the client side - but on the server side it does as expected. What might be wrong there? The pipeline is set up the same way on client and server.

8:01 $seen ztellman

8:11 tdammers: anyway

8:11 the thing I'm missing the most, I think, is the ability to step in at any point in the code and have the compiler figure out the shape of the data I can expect at that point

8:29 crocket: Does clojure enable mediocre programmers to maintain programs of 10k lines or even 100k lines?

8:29 opqdonut: no programming language enables that

8:30 development processed do

8:30 *processes

8:30 damethos: +1

8:31 muhuk: I'd expect 100 kloc programs written in blub to be 5~10k when written in Clojure

8:32 * clgv doubts that lines of code is a good metric for clojure code.

8:32 mavbozo: can clojure enable mediocre programmers to create programs of 10k lines before they give up?

8:32 clgv: mavbozo: yeah, copy & paste ;)

8:33 that's language agnostic

8:33 crocket: What is the economic tradeoff?

8:34 muhuk, If you're correct, would a C++ program of 140k lines can be written in 7-14k lines?

8:34 ouch

8:34 mavbozo: i assume mediocre programmers just sprinkle defs everywhere even inside function, or even using atoms as plain-old variables

8:34 crocket: If you're correct, would a C++ program of 140k lines be written in 7-14k lines?

8:34 mavbozo: effectively create imperative programs with clojure

8:35 crocket: mavbozo, That would be terribly programmers.

8:35 I am a mediocre programmer, and I don't write that kind of code.

8:35 terrible*

8:36 I couldn't have written such a beautiful snippet of code as https://github.com/crocket/clj-ddns-client/blob/master/src/clj_ddns_client/core.clj in java or javascript.

8:36 Even, a mediocre programmer can write such beautiful codes in clojure.

8:37 muhuk: crocket: I'm generalizing. But yes.

8:37 crocket: muhuk, If it includes test codes, wouldn't it double?

8:37 7-14k -> 14-28k

8:37 Or, does it include tests?

8:37 muhuk: possibly more than double

8:38 crocket: Test code is code

8:38 muhuk: sometimes my tests are 5 times LOC

8:38 I wouldn't included test code when I'm sizing up my codebase.

8:38 crocket: I could probably get less LOC in haskell or OCaml if you include tests.

8:39 You have to maintain tests as well

8:39 Since I'm a mediocre programmer, I don't know what functions I should test in clojure.

8:40 xcv: I think it's more a matter of the paradigms people are used to. Imperative + OO is pretty complex to wrap your head around, compared to FP.

8:40 crocket: Some of them just look like internal details

8:40 xcv: It's easy to forget what it was like to learn imperative programming.

8:40 Just my two cents.

8:40 crocket: Imperative programming is straightforward.

8:40 OO isn't.

8:41 xcv: Yeah, it is. And if the approach is "hack at it until it works" instead of writing something you basically understand, it can seem quite a bit easier.

8:43 crocket: 14*5 = 60k

8:43 YOu don't save much LOC

8:44 30k? maybe

8:44 tdammers: test code is code, period.

8:45 crocket: period

8:45 tdammers: in fact, I believe that to get a fair comparison, one should also include the necessary documentation

8:45 crocket: If a C++ program has 140k lines of code, how many LOC would a clojure equivalent including tests have?

8:45 oh, documentation

8:46 tdammers: which, granted, would be favorable for underdocumented codebases, so one would have to come up with a metric for "sufficient documentation"

8:46 but the reason I'd want to include documentation is similar to why I'd include tests

8:47 mavbozo: "everything is an expression" and immutability effectively forces clojure programmers to write code in less imperative style and more towards functional style

8:47 tdammers: mavbozo: it's very easy to opt out of either though

8:47 spacepluk: crocket: wild guess 1/10th of that if you don't need to call a lot of native code

8:48 tdammers: mavbozo: clojure has immutable values, but almost all the other side effects are completely uncontrolled

8:48 muhuk: remove the test code and your program works fine. Similar to generated code/files, test code is second class to actual code.

8:48 crocket: spacepluk, including tests?

8:48 spacepluk: crocket: and assuming it's written in a functional way not just copy the c++ code in clojure

8:49 crocket: do you need to mock a lot of things?

8:49 crocket: mock what kind of things?

8:49 spacepluk: crocket: servers, databases, etc.

8:49 crocket: I don't know

8:49 yet

8:50 jsabeaudry: Is there a way to not resolve a symbol in a backquote context?

8:50 spacepluk: either way pure functional code is easier to test

8:50 muhuk: oh, wait. I forgot to say "period".

8:50 period.

8:50 crocket: Someone wrote a set-theoretic database in C++ of 140k lines including tests. I was just wondering how many LOC I can save with clojure.

8:51 TMA: jsabeaudry: `(... ~'a ...)

8:51 crocket: It's like NoSQL.

8:51 jsabeaudry: TMA, oh sweet, thanks!

8:52 crocket: spacepluk, ^^

8:52 mavbozo: tdammers, what's the state of the art of controlling side effects? static typing?

8:52 TMA: crocket: it depends heavily on the style it is written in

8:52 spacepluk: crocket: I'm sure it will be shorter and be simpler if done right

8:53 crocket: hmm....

8:53 taylanub: mavbozo: usually just not using side-effecting operations, I believe. :-) and monads I guess.

8:53 spacepluk: crocket: at least you get rid of all the c++ boilerplate, build system etc.

8:53 crocket: His code is full of templates which he was proud of because templates fit his needs.

8:54 TMA: mavbozo: or a pure language like haskell

8:54 crocket: Is monad common in clojure?

8:56 muhuk: nope

8:56 tdammers: mavbozo: in clojure? I don't know; "discipline" and "naming conventions", I believe

8:56 mavbozo: Haskell uses the type system... the traditional approach is to use monads (or, as the case may be, functors or applicatives)

8:56 spacepluk: you don't really need monads as bad as in haskell

8:56 tdammers: spacepluk: you do, but you can keep them implicit

8:57 crocket: Since I don't know monads, I don't know if I need them.

8:57 tdammers: crocket: you are already using them, they're just not formalized

8:57 spacepluk: tdammers: yeah, I mean for side-effects and that kind of stuff

8:57 tdammers: spacepluk: monads and effects are somewhat orthogonal

8:58 spacepluk: tdammers: what I mean is that you don't need monads to wrap side-effects in clojure

8:58 tdammers: haskell doesn't have side effects at all

8:58 spacepluk: which makes your life easier if you're careful hehe

8:58 tdammers: just effects

8:59 but anyway

8:59 crocket: Has any of you used typed clojure? How was it?

8:59 tdammers: you don't need monads for that in haskell either

8:59 you do need types that encode effects, though

8:59 and those types almost always happen to be monads

9:00 mavbozo: tdammers, state of the art in programming world. In clojure, I resort to some patterns that is described here http://www.infoq.com/presentations/Clojure-Design-Patterns

9:00 crocket: Ok

9:00 tdammers: mavbozo: ah, ok... I'm not sure about that, but I believe most approaches treat effects individually, building separate features for each into their languages

9:01 spacepluk: crocket: are you familiar with other lisps?

9:01 tdammers: e.g., exception handling for failures, comprehensions for lists, "something" for I/O, const-ness checks for mutability, thread control for concurrent mutability

9:01 crocket: spacepluk, no

9:02 I know a little of emacs lisp, though

9:02 tdammers: but there are a few approaches that try to generalize effects into a uniform pattern

9:02 spacepluk: crocket: I would keep it simple and skip types at the beginning

9:02 crocket: Is there a better way to handle logging than mutating the global logging configuration in a namespaced var?

9:03 It is not pure

9:03 I tried to separate logging from business logic, but you can't attach hooks onto protocol methods and multimethods.

9:04 spacepluk: crocket: a macro might help there

9:05 crocket: how

9:05 https://github.com/technomancy/robert-hooke/ doesn't work on protocols

9:05 I tried to add logging as a post hook.

9:06 spacepluk, Can you show me how macro helps?

9:06 spacepluk: I'm not familiar with that library

9:07 but I guess you can make a macro that calls the logger to define the implementations

9:26 crocket: Oi

9:28 dstockton: Oi

9:42 clgv: io

9:45 jonathanj: is there something like readthedocs.org for Clojure projects?

9:45 muhuk: no. But RTD is language agnostic.

9:53 patrkris: hi there. is it possible somehow to make leiningen change the settings in logback.xml when building for production?

9:55 justin_smith: patrkris: for one thing, you could have a different :resources-paths setting for the build

10:02 patrkris: justin_smith: oh yeah, good idea. how come you always have the time to help? :D

10:08 visof: hi guys

10:12 justin_smith: patrkris: I'd probably find the answer to that question depressing

10:12 crocket: I realized there are only a few common types to go with in clojure.

10:12 Map, list, vector, and set

10:12 So, you don't worry much about types

10:12 visof: what is the best solution for this: i have a record Foo with :x and :y fields, and i want to apply function f on all elements in this Data structure, #Foo{:x (#Foo{:x (p1 p2 ...) :y (p1 p2 p3....)} ...) :y (#Foo{:x (p1 p2 p3...) :y (#Foo{...})})

10:13 ?

10:13 crocket: Types generated by defrecord are sort of treated like maps

10:13 If defrecord types are not treated like maps, they are type-checked during compile time.

10:14 How convenient.

10:14 visof: special_map function (special_map function datastructure) ?

10:14 crocket: Partially typed

10:14 justin_smith: crocket: they are maps, as much as any of the other clojure types implementing the interface

10:14 crocket: Dynamic typing is not as painful when all types are map, list, vector, and set.

10:14 sort of

10:16 taylanub: I find dynamic typing never painful. static typing on the other hand...

10:17 ToxicFrog: crocket: the problem there is that "map" covers infinity types. If you pass a map that is a lookup table of userIDs to user info structs to a function that expects a map that is a user info struct, you're going to have a bad time.

10:17 But they're both the same type!

10:18 Dynamic typing in and of itself isn't painful, but debugging type mismatch errors that only occur at runtime far from the point of error absolutely is, and if core.typed actually worked I'd be using it for all of my clojure work.

10:18 crocket: ToxicFrog, yes

10:18 I guess that's where haskell shines.

10:18 or Ocaml

10:23 tdammers: interesting... I find dynamic typing painful as soon as the codebase reaches a fairly benign complexity level

10:57 skeuomorf: Does core.match allow function applications when matching? e.g. execute `f` if the pattern is "x"?

10:57 s/applications/application

10:58 clgv: skeuomorf: on the selected branch? why not?

10:59 skeuomorf: clgv: Yeah, on the selected branch, skimming the examples and I didn't see similar usage, so was wondering

11:00 clgv: skeuomorf: just try it ;)

11:00 skeuomorf: clgv: can't afford to spawn a repl currently :)

11:00 clgv: lein try core.match x.y.z

11:19 spacepluk: is it just me or package management in java is completely broken? :(

11:20 every time I add a new dependency I need to track down incompatibilities with joda-time jackson or that kind of libraries

11:20 npm feels like alien technology compared to this

11:20 muhuk: spacepluk: package management in _ is completely broken

11:20 rhg135: It's pretty nice compared to say c

11:20 spacepluk: rhg135: that's true

11:22 muhuk: this wouldn't happen in node/npm because each module can depend on a different version of the same library

11:23 I don't think you can do that in the jvm

11:23 rhg135: As for npm, try upgrading/downgrading node and watch the native module build failures

11:23 muhuk: spacepluk: I don't think that's a good idea.

11:23 spacepluk: rhg135: yeah, you need to wipe the cache node_modules in that case, but you don't need to do package manager work yourself, tracking down versions, etc.

11:24 rhg135: Sometimes they just won't build

11:24 spacepluk: muhuk: why not? I'm having this problem because of implementation details of different libraries

11:25 rhg135: I guess you can't fix c package management hehe

11:25 rhg135: Sad but true

11:27 spacepluk: I'm trying to use storm/kinesis-storm-spout/amazonica/monger together, I looked great on paper

11:28 skeuomorf: spacepluk: oh npm is horrible, maybe not as horrible as Java though, I like nix and guix and in terms of languages, Cargo is great (Rust's de-facto package manager)

11:28 muhuk: spacepluk: because there's no guarantee the effects of having two versions of the same lib will be isolated like that.

11:28 spacepluk: muhuk: yeah, but that's a jvm limitation right?

11:28 skeuomorf: yeah, cargo is very nice

11:30 rhg135: Aren't classloaders meant to isolate classes?

11:31 spacepluk: rhg135: I thought about that, but in this case with storm/thrift's serialization I don't think I can

11:32 rhg135: I've never used either, please explain

11:32 spacepluk: so I'm trying to find a combination of versions that can work together, hence my frustration

11:33 storm is a distributed realtime computation framework

11:33 muhuk: spacepluk: why would you say that?

11:33 spacepluk: the computations must be serializable so that storm can send the code through the cluster

11:34 I don't think I can control how storm loads the classes

11:35 muhuk: what? sorry

11:35 rhg135: Doesn't it use Class/forName?

11:36 muhuk: spacepluk: why do you think it's a jvm limitation?

11:36 rhg135: Unless it does weird stuff with Unsafe

11:36 muhuk: spacepluk: suppose you call f & g in your code. Both of which in turn calls different versions of h

11:36 spacepluk: muhuk: yeah, you're right you can load the same thing in different classloaders, is a limitation of my usecase I guess

11:37 muhuk: spacepluk: how would you compare the results of h?

11:37 spacepluk: muhuk: I think that's ok if h-stuff is not exposed through f&g interfaces

11:37 muhuk: spacepluk: yeah, I was speaking in general terms. Having two versions of the same lib is a bad idea.

11:37 spacepluk: it's not OK though, if it's exposed.

11:38 spacepluk: muhuk: I feels like the simplest solution for this specific case though, I just don't think I can do it

11:38 muhuk: agreed

11:39 muhuk: spacepluk: I too wish maintainers would keep releasing with updated deps often. It would make it a lot easier to align such dependencies then. (more options to choose)

11:39 spacepluk: how do you deal with this situations? is there any tool I can use to find combinations of versions?

11:40 muhuk: yeah, I didn't expect so much pain, I've been away from jvm development for quite a long time, and had high expectations about maven and friends

11:40 muhuk: spacepluk: I exclude the older lib, sacrifice the goat and keep my hands inside the vehicle at all times.

11:40 spacepluk: hahaha

11:41 is there something like pactree for maven?

11:45 muhuk: spacepluk: lein deps :tree ?

11:45 rhg135: https://github.com/flatland/classlojure

11:46 spacepluk: muhuk: that's great thanks

11:46 muhuk: yw

11:51 spacepluk: rhg135: that sounds cool thanks, but first I'm gonna try to avoid messing with the class loaders

11:52 hopefully there's a combination that can work

11:52 rhg135: Old versions of software make me cry at night

11:53 It makes me feel if I have a bug people will not upgrade till much later

11:53 spacepluk: same here :(

11:54 I'm stuck with clojure 1.6 because of storm ¬¬

11:54 rhg135: It makes programming harder

11:55 Have to be loose in your input

11:55 Stableish api

11:56 spacepluk: there should be a very big "dependencies obsolete" flag in every package manager so that people feel guilty and upgrade

11:56 it's a lot easier when you do it often

11:56 rhg135: I agree, but sometimes you can't

11:57 muhuk: spacepluk: lein ancient

11:58 spacepluk: muhuk: I tried that with this libs it broke everything hehe

11:58 rhg135: But that's optional :-P

11:58 muhuk: spacepluk: define broke

11:58 spacepluk: the same problem I'm having now basically

11:59 it just breaks at different points

11:59 muhuk: spacepluk: I don't get it. It just reports libs that has newer versions.

11:59 spacepluk: I had a working combination, but then added amazonica and started to dance again

12:00 muhuk: yes, my problem is that the libs I'm using depend on different incompatible versions of the same thing joda-time, jackson, and utility stuff like that

12:02 muhuk: spacepluk: ok, you've probably already figured this out. But FWIW I set the latest versions, and downgrade one by one until I find a working combination.

12:02 spacepluk: in the end I might need to fork one, I'm not sure how to do that with lein/maven

12:03 muhuk: :_( yes

12:10 muhuk: rhg135: thanks for you help, at least now I don't feel stupid

12:10 rhg135: Np

13:05 mavbozo: i use mysql db and suppose I want to deliver this request "Give me a list of phone numbers of people who called in the last 4 days, whose call wasn’t answered and had never called us before"

13:05 usually, at first, I just create a function to wrap the query and parametrized the number of days

13:05 (defn phone_numbers_of_people_who_called_in_the_last_N_days_and_call_not_answered_and_never_called_before [db N] ...)

13:05 is it usual to wrap such query in a function with long name? or are there any other alternative?

13:09 sobel: tons of alternatives

13:09 use a shorter name

13:10 that is ridiculous. also, hyphenate not underscore, if you want to be fashionable.

13:10 that fn name seems to be the spec of the query

13:11 personally, if it's that important, i'll make a sql function/procedure and mirror it with a clj fcn of similar name.

13:15 mavbozo: oops, i still use old php, js function naming style. old habits die hard.

13:17 sobel: - is an operator in most languages. fortunately clojure has not operators.

13:17 so lisp(s) are gonna be the odd ones out, using -

13:20 mavbozo: still, i find it really hard to find shorter-meaningful names for query functions that satisfies many specific criteria

13:20 sobel: strict fn naming criteria sounds like like a self-injury to me

13:20 i don't seek meaning from fn names. just reference value.

13:27 mavbozo: sobel, how do you name your query functions then? do you have some rule of thumbs based on your experience?

13:28 oddcully: mavbozo: why don't you name it what biz calls them? these are just the where clauses put togehter. you could as well name it select_star_from_phonenumbers_where_...

13:39 spacepluk: mavbozo: you can also make a small dsl to build the queries via function composition

13:39 I'm sure somebody already did that

13:41 mavbozo: oddcully, in most cases the biz has these names, but when they don't have ones, i use long name for the functions

13:41 spacepluk: mavbozo: maybe name the function after the reason you need to make the query?

13:43 mavbozo: or use a shorter more general name and put filters as named parameters

13:43 I would hate running into a name like that hehe

13:48 sobel: mavbozo: i call them something short but related to their behavior

13:49 example: i had a recursive query that calculated and ordered script dependencies. it did a lot of different things but ultimately, it delivered ordered dependencies. it got named get-ordered-deps.

13:49 skeuomorf: ,(defprotocol MyProtocol (mutate [this]))

13:49 clojurebot: MyProtocol

13:49 sobel: it's a workhorse query. i deleted SO much procedural code after that query took over its job.

13:50 but it doesn't need a fancy name.

13:50 mungojelly: is this shortness fetish really appropriate, code is read a lot more than it's written, i'd rather read code written in whole words instead of using my actual brain guessing what "ch" and "prob" and stuff mean.

13:51 skeuomorf: ,(defrecord MyRecord [mymap] MyProtocol (mutate [this] (set! (. this mymap) (assoc mymap :hello 2))))

13:51 clojurebot: sandbox.MyRecord

13:51 sobel: fetish implies that it's an aesthetic (sexual!) preference. it's actually very practical.

13:51 skeuomorf: (def x (MyRecord-> {:nah 1}))

13:51 mungojelly: practical how? please don't say efficiency of typing :/

13:51 sobel: but it's optional, if you don't like it, go ahead and type those long names you love to read

13:51 skeuomorf: ,(def x (MyRecord-> {:nah 1}))

13:51 clojurebot: #error {\n :cause "Unable to resolve symbol: MyRecord-> in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: MyRecord-> in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: MyR...

13:51 sobel: it's quicker to read

13:52 skeuomorf: ,(def x (->MyRecord {:nah 1}))

13:52 clojurebot: #'sandbox/x

13:52 sobel: my editor can autocomplete them but i'll be damned if i want to LOOK at code with over-length identifiers

13:52 skeuomorf: ,(x)

13:52 clojurebot: #error {\n :cause "sandbox.MyRecord cannot be cast to clojure.lang.IFn"\n :via\n [{:type java.lang.ClassCastException\n :message "sandbox.MyRecord cannot be cast to clojure.lang.IFn"\n :at [sandbox$eval157 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval157 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval157 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java...

13:52 skeuomorf: ,(mutate x)

13:52 clojurebot: #error {\n :cause "sandbox.MyRecord cannot be cast to compile__stub.sandbox.MyRecord"\n :via\n [{:type java.lang.ClassCastException\n :message "sandbox.MyRecord cannot be cast to compile__stub.sandbox.MyRecord"\n :at [sandbox.MyRecord mutate "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox.MyRecord mutate "NO_SOURCE_FILE" -1]\n [sandbox$eval181 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval181 ...

13:52 mungojelly: it's quicker to read made up shorthand than actual words? hm kwl id, fn w/lgwg

13:52 skeuomorf: What's going on here? ^

13:52 spacepluk: I appreciate when code fits in 80chars

13:52 sobel: mungojelly: if you make up shorthand that lame, you deserve what you get

13:53 mungojelly: do you code?

13:53 spacepluk: names like that make that impossible

13:53 sobel: you're always here dumping on traditions evolved by years of practice and preference without any useful suggestions of what would actually be better

13:53 even less evidence of why you think these things

13:53 so i wonder

13:54 mungojelly: it seems to me a lot of these short names are "obvious" once you've simply steeped in this culture for a decade. i can usually guess them. but i use my brain doing that and it excludes newbies.

13:54 sobel: and making a ridiculous extreme out of a very reasonable idea, just so you can make fun of it, is pathetic and rude.

13:54 no one suggested unreadable or "made up" shorthand except you, for the purpose of belittling a reasonable idea of not making identifiers so long

13:55 so, i've been using clojure for commercial code less than 6 months, but the nomenclature was pretty obvious from day one. i'm not sure why you think it takes 10 years unless you're unfamiliar with coding.

13:56 which is ok, i'm just curious

13:56 this is a good place if you code and need a little support on the language or approaches. i come here for that. i don't understand why you're here, though.

13:56 mungojelly: obviously there's some balance between length and clarity somewhere. of course this level of shortness makes sense to people here, that's why it persists. but it's talking like this in a world of people who'd like to program with us but can't that feels rude to me.

13:56 hiredman: skeuomorf: a few things, but regardless of the other things, that will never work because mymap is not mutable so you cannot use set! to change it

13:57 sobel: mungojelly: it's not a big deal.

13:57 mungojelly: as matters of programming goes, this isn't. it's just a social question, unless you're trying to exceed the min or max bounds for identifier length.

13:58 skeuomorf: hiredman: hmm, I think? I should probably use an atom and swap its value

13:58 mungojelly: sure it's "just" a social question, just a question of how many and which kind of people are able to read the things we write.

13:58 sobel: mungojelly: bullshit.

13:58 skeuomorf: hiredman: An atom holding a map and swap that map with the new map

13:59 sobel: mungojelly: if you write something, you get to determine what the identifiers are. most people like their work product to be commonly acceptable.

13:59 mungojelly: let me know how those long ids work out for you when you code with an eye for passing review, peer acceptance, or maintenance by others.

14:00 until then you just don't get a say because you're proposing telling others how to do things you don't even yourself do

14:00 be done

14:00 hiredman: there is some syntax to mark fields as mutable

14:01 but an atom is going to be nicer to use so I would recomend using that

14:02 that compiler error isn't actually related to the mutable field thing, but if you solved the compiler error you would hit the mutable field thing, and atom would deal with both

14:04 kungi: I have the strangest of strange bugs. When I run my web application through the cider emacs repl I get each line of log output exactly once as it should be. When I run it through lein repl on the commandline I get each line exactly three times. The logger currently just uses println. O.o

14:05 hiredman: kungi: cider opens a few emacs buffers, and while some output gets directed to the repl buffer, other output can end up in other buffers

14:06 so you maybe printing 3 times in cider too, and the output just ends up in one of the other buffers

14:07 mavbozo: sobel, oddcully spacepluk, mungojelly thank you for the perspectives and insights

14:07 kungi: hiredman: just had a look in every buffer. It doesn't look like there is any stray debug output there.

14:11 oddcully: mavbozo: naming it get-missed-opportunities-phone-numbers makes it easier to compose it internally and don't have it's name beeing wrong after each change in the underbelly

14:14 justin_smith: ,(defmacro define-function [& body] `(defn ~(symbol (clojure.string/join \- (flatten body))) ~@body))

14:14 clojurebot: #'sandbox/define-function

14:14 justin_smith: ,(define-function [x] (+ x x))

14:14 clojurebot: #'sandbox/x-+-x-x

14:15 justin_smith: ,(x-+-x-x 2)

14:15 clojurebot: 4

14:15 kungi: hiredman: https://github.com/clojure-emacs/cider-nrepl/issues/266

14:18 mavbozo: oddcully, that's a good name

14:19 justin_smith, :-D

14:23 skeuomorf: hiredman: I see

14:37 ,(defrecord MyRecord [mymap] MyProtocol (mutate [this] (swap! mymap (assoc @mymap :hello 2))))

14:37 clojurebot: #error {\n :cause "Unable to resolve symbol: MyProtocol in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: MyProtocol in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6891]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: ...

14:38 hiredman: that call to swap is incorrect

14:43 skeuomorf: hiredman: Yeah, hastiness in editing the weechat buffer :)

15:30 zxc: Hello! How can I change this so it won't give me a lazy seq? I want just a string

15:30 http://lpaste.net/142497

15:32 oddcully: zxc: (apply str...) e.g.

15:32 zxc: oddcully: Thank you!

15:56 sagax: hi all!

15:57 i new be in clojure

15:57 but interesting,

15:57 skeuomorf: sagax: Hi!

15:57 sagax: Welcome :)

18:34 triss: when using ArrayMaps apparently "Subsequent assoc-ing will eventually cause it to 'become' a hash-map."

18:34 that kinda sucks doesn't it?

18:34 I really would like a nice array map...

18:35 and when i say something's an array-map i want it to stay that way

18:37 ianhedoesit: I'm confused.

18:38 triss: http://clojure.org/data_structures#Data Structures-ArrayMaps

18:40 ianhedoesit: right, but it won't actually change the type of whatever collection you have. if you need to ensure it's an ArrayMap you can just do (array-map (assoc initial-array-map :keys [values])), no?

18:41 triss: um... yeah i think i could. might have to jus for safeties sake in what I'm p to

18:41 thanks ianhedoesit

18:41 ianhedoesit: you certainly can.

18:42 (apologies for the long example to follow)

18:42 triss: maybe i should just use a vector of key value pairs though

18:42 ianhedoesit: ,(type (assoc {} :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9 :j 10))

18:42 clojurebot: clojure.lang.PersistentHashMap

18:42 ianhedoesit: ,(type (assoc {} :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9))

18:42 clojurebot: clojure.lang.PersistentArrayMap

18:42 ianhedoesit: ,(type (array-map (assoc {} :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9)))

18:42 clojurebot: clojure.lang.PersistentArrayMap

18:43 ianhedoesit: woops, the last one should add another kv pair, but either way, the explicit call to array-map will make it an ArrayMap.

18:43 a map with more than 10 key value pairs will be a HashMap because it's more efficient than an ArrayMap at that point.

18:44 triss: yup... i understand why HashMap might be implemented that way behind the scenes

18:45 but this is a bit bonkers if you ask me...

18:45 also if i cast the hash map i get given back by the assoc i'll have lost the ordering wont i?

18:45 which is what I'm after

18:52 rhg135: on a tangent, if I wanted to use this logic to build at runtime (ala (apply f ...)) is that possible?

18:53 ianhedoesit: triss: why do you want a sorted map in the first place?

18:54 triss: ah so I've got these maps... and I want to derive values from other values if they aren't specified...

18:55 i put functions in these maps to derive them...

18:57 and some of these values depend on other values that derived via funcions

18:57 clojurebot: It's greek to me.

18:57 ianhedoesit: that sounds complicated and I don't understand why a sorted map is required.

18:57 triss: it kind of is...

18:57 ianhedoesit: but I'm not going to be here long enough to help, unfortunately. good luck.

18:57 triss: thanks man

18:58 so am I the only one that thinks this behaviour is potentially confusing?

18:59 TEttinger: triss: would an ordered map be a better fit?

18:59 triss: the array-map becoming a hash-map thing?

18:59 TEttinger: no

18:59 https://github.com/flatland/ordered

19:00 triss: TEttinger: BOOM! thanks man

19:01 rhg135: It's rather nice to have optimized maps

19:01 TEttinger: triss: if you were relying on either array maps or hash maps having a consistent iteration order, that's probably a bug. I haven't used flatland/ordered yet, but I now strongly prefer using ordered collections in Java

19:02 (try iterating through a java.util.HashMap in Java 7, and in Java 8. different order just about every time. then try with a LinkedHashMap, same order. the latter is the behavior of ordered maps)

19:02 triss: no array-maps are documented as having consistent order.

19:02 TEttinger: yes, but they also have a maximum size, I think

19:02 triss: yup ten....

19:04 it seems quite an easy thing to get confused about... I homestly thought an array-map would just stay an array map when i first saw it...

19:04 And stuff changing type based on size seems nuts to me.

19:05 yes. do it behind scenes for performance....

19:05 but just tell me you're a HashMap...

19:06 do other types change like that in Clojure?

19:06 TEttinger: sorta. Integer can promote to BigInteger if you use the promoting math fns. * won't promote, but *' will

19:07 ,(reduce * (range 20 200))

19:07 clojurebot: #error {\n :cause "integer overflow"\n :via\n [{:type java.lang.ArithmeticException\n :message "integer overflow"\n :at [clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]}]\n :trace\n [[clojure.lang.Numbers throwIntOverflow "Numbers.java" 1501]\n [clojure.lang.Numbers multiply "Numbers.java" 1867]\n [clojure.lang.Numbers$LongOps multiply "Numbers.java" 467]\n [clojure.lang.Numbers ...

19:07 TEttinger: ,(reduce *' (range 20 200))

19:07 clojurebot: 32416343309932862480078063450197751286360345254602064903101245078980649624910495919277583333729267927978044287550245689991180639587939195917412832736019999345923394479196148258074227897996791388337336270220011364475288934580843359607845024722273008686295523615766901687120288519406781073348991324061273932221644800000000000000000000000000000000000000000000N

19:07 TEttinger: note the N, which is a BigInteger

19:07 ,(reduce *' 1.0 (range 20 200))

19:07 clojurebot: Infinity

19:07 TEttinger: ha

19:07 ,(reduce * 1N (range 20 200))

19:07 clojurebot: 32416343309932862480078063450197751286360345254602064903101245078980649624910495919277583333729267927978044287550245689991180639587939195917412832736019999345923394479196148258074227897996791388337336270220011364475288934580843359607845024722273008686295523615766901687120288519406781073348991324061273932221644800000000000000000000000000000000000000000000N

19:08 TEttinger: it doesn't need a promoting fn if it's already a BigInteger

19:08 ,(reduce * 1M (range 20 200))

19:08 clojurebot: 32416343309932862480078063450197751286360345254602064903101245078980649624910495919277583333729267927978044287550245689991180639587939195917412832736019999345923394479196148258074227897996791388337336270220011364475288934580843359607845024722273008686295523615766901687120288519406781073348991324061273932221644800000000000000000000000000000000000000000000M

19:08 TEttinger: M is BigDecimal

19:08 Frozenlo`: I'd prefer if * was automatically promoting. (Wasn't it like that before?)

19:08 TEttinger: it was. it caused performance problems

19:09 it was changed back in 1.1 or 1.2 or so?

19:09 there's also the unchecked-whatever fns, not sure when they were added

19:09 which do the standard java behavior of not throwing exceptions on arithmetic overflow

19:10 and just doing weird stuff to the bits

19:10 Frozenlo`: Screw perfomance :-p

19:12 TEttinger: Frozenlo`: just for you:

19:12 ,(alter-var-root #'* *')

19:12 clojurebot: #error {\n :cause "Cannot cast clojure.core$_STAR_ to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "Cannot cast clojure.core$_STAR_ to java.lang.Number"\n :at [java.lang.Class cast "Class.java" 3176]}]\n :trace\n [[java.lang.Class cast "Class.java" 3176]\n [clojure.core$cast invokeStatic "core.clj" 338]\n [clojure.core$_STAR__SINGLEQUOTE_ invokeStatic "core.clj"...

19:12 TEttinger: ,(alter-var-root #'* #'*')

19:12 clojurebot: #error {\n :cause "Cannot cast clojure.core$_STAR_ to java.lang.Number"\n :via\n [{:type java.lang.ClassCastException\n :message "Cannot cast clojure.core$_STAR_ to java.lang.Number"\n :at [java.lang.Class cast "Class.java" 3176]}]\n :trace\n [[java.lang.Class cast "Class.java" 3176]\n [clojure.core$cast invokeStatic "core.clj" 338]\n [clojure.core$_STAR__SINGLEQUOTE_ invokeStatic "core.clj"...

19:12 TEttinger: sigh

19:12 I don't remember how it works

19:14 Frozenlo`: For user-friendliness, I'd argue that * should do the 'obvious' layman stuff, while *' the more machine related perfomant stuff.

19:14 TEttinger: ,(alter-var-root #'* (constantly *'))

19:14 clojurebot: #object[clojure.core$_STAR__SINGLEQUOTE_ 0x291e9ae9 "clojure.core$_STAR__SINGLEQUOTE_@291e9ae9"]

19:14 justin_smith: TEttinger: alter-var-root is the same api as swap basically

19:14 TEttinger: ,(reduce * (range 20 200))

19:14 clojurebot: 32416343309932862480078063450197751286360345254602064903101245078980649624910495919277583333729267927978044287550245689991180639587939195917412832736019999345923394479196148258074227897996791388337336270220011364475288934580843359607845024722273008686295523615766901687120288519406781073348991324061273932221644800000000000000000000000000000000000000000000N

19:16 TEttinger: Frozenlo`: I think also anything that returns different types, with one of them being a primitive or boxed primitive, could be trouble. arraymap and hashmap both implement the same interface, you just return Map or whatever more specific variant they use. I don't think Integer and BigInteger share that?

19:17 there's some specialization on certain primitives in a gnarly chunk of clojure's internals

19:36 Frozenlo`: I have a webserver doing some task each time it receives a POST. Some of them might take some time, and I'd like to organize them in a queue and possibly do some monitoring. Any suggestion for a library?

19:58 To answer my own question (logs), https://github.com/Factual/durable-queue seems to do most of what I asked for.

21:33 crocket: If I rewrite a C++ program of 140k LOC, which language between haskell and clojure will result in the least LOC including tests?

21:33 Or OCaml

21:34 wmealing: this always depends on the task at hand

21:35 your C++ is likely heavy class oriented, and your clojure application will be data oriented.

21:36 if you're a competent C++ programmer, and a first time other language programmer you likely wont get the advantage of the language unless you know the domain you're writing from very well.

21:37 (trying not to be a downer, just from my personal experience, going from C -> (erlang | clojure | haskell)

21:37 )

21:39 crocket: what i found as a useful exercise is to find the core of your problem domain, and try to port part of that to your target language and do a comparison on it.

21:39 crocket: wmealing, Let's assume I have decent expertise in all languages involved.

21:39 wmealing: ok

21:39 crocket: Let's say I have coded with each of them for 2 years.

21:39 wmealing: including C++ right ?

21:39 crocket: yes

21:40 * wmealing thinks

21:43 wmealing: i haven't forgotten, just give m e a moment

21:45 ok, what i was -planning- to do was take an approach of LOC used in debians benchmark game

21:45 http://benchmarksgame.alioth.debian.org/play.html

21:46 i know that doesn't include test cases

21:46 but it will give an idea of how many LOC for similar problems

21:46 across multiple problems

21:57 annoyingly there is no single github of source.. they keep it in an issue tracker

21:57 https://alioth.debian.org/tracker/?func=browse&group_id=100815&atid=413122

22:22 crocket: How do I attach logging to protocol methods and multimethods?

22:39 neoncontrails: Say you're using Ring as the HTTP server for a figwheel app.

22:39 Do you boot in figwheel?

Logging service provided by n01se.net