#clojure logs

2013-04-24

00:01pppaulwalking is awesome
00:03pppauli have a walk that turns everything it touches into a set
00:03pppaul:)
00:03pppauli use walks for datomic stuff too
01:30beakyhello
01:32beakyhow do I learn the clojure language?
01:32callenbeaky: hello
01:32callenbeaky: buy a book
01:32callenbeaky: I recommend Cemerick's
01:32beakyah
01:32callenbeaky: SegFaultAX: something
01:32callenbeaky: http://www.clojurebook.com/
01:42tdignancallen: i bought a book
01:43tdignanbut I don't know clojure
01:43tdignanwhat do I do next?
01:43tdignanseriously, I bought the book. idled in the irc for a month, but not a lick of clojure.
01:43tdignando I have to actually read the book as well?
01:43tdignantbh, it intimidates me a lot.
01:44tdignanits so unlike anything else i've done.
01:44RaynesWell, you're never going to want to lick the Clojure.
01:45tdignanThat is a quite possible outcome.
01:45Oddmantdignan, that's functional programming for you
01:45Oddman:P
01:47beakyclojure looks like scheme
01:47callenClojure is relatively easy, as far as functional languages go.
01:47callenIt's not the "pull brain out of you through your asshole" experience that Haskell represents.
01:48tdignanoh, yeah. i looked at haskell once years ago.
01:48callenlooking doesn't really do anything
01:48callenwhich might explain why you haven't learned Clojure yet either.
01:49tdignanI haven't learned something just for the sake of learning it for a long time.
01:49tdignanusually i just learn the things I need to know to build things.
01:52tdignanI suppose I'm not the only one to give up here.
01:52callentdignan: why are you here?
01:53tdignancallen: um, I thought idling here and watching people talk about clojure would help to stoke my interest more
01:53tdignanI've been on autojoin for a month
01:58beakyso the bird book is the one to go for for beginners?
01:58Pupnik-ive been working with that one
01:58Pupnik-i think it is good
02:00tdignanlooks like there is also a free webcast by the author on may 1st
02:00tdignan...2012
02:00tdignannevermind
02:01beakywhat are the challenges to learning clojure?
02:06tdignanbeaky: i can tell you why I haven't learned it yet. it's unlike anything else I know, and I don't actually need to learn it.
02:07tdignani'm sure your challenges will be unique to your own mind.
02:07beakyah
02:08beakyI know c++
02:08beakyso I am probably going to have a tough time :D
02:08beakysince clojure is so different from those braces languages
02:10beakybut I want to use it to build a data processing app
02:11RaynesEvery single app ever is a data processing app.
02:11beakyheh
02:11beakyapps are just sequences of bits that flip other sequences of bits
02:13beakyclojure doesn't seem particularly object-oriented
02:13tdignanapps are programs that flip tons of redundant sequences of bits so the programmer can actually get done in a reasonable amount of time
02:13tdignannope. it's a functional language.
02:14beakyfunctional? like C?
02:14tdignanC is procedural
02:14beakyah
02:14tdignanthe main difference has to do with keeping state. a purely functional program doesn't have it.
02:15beakyso a language like clojure does away with flipping bits
02:15tdignanthe bits do flip. the code itself is data.
02:15beakyah
02:16tdignanso a clojure program, is actually data, that gets read by a parser, which then executes the code... which itself is actually flat text, data :)
02:16Chousukea purely functional program does have state. it's just explicit and individual states are generally immutable values
02:17ChousukeHaskell takes value-oriented programming to an extreme. even I/O is pure in haskell :P
02:17beakyah
02:17beakyso a functional programming language just views state as data/values, and functions are just maps between values?
02:18beaky(like mathematical functions)
02:18sparkjoyThat's a good way to think of it
02:18Chousukethat's maybe oversimplifying a bit, but yes
02:19Chousukewhen you work in a truly "pure" language you need some creativity to be able to do certain things that are "easy" in an impure language (I/O is the usual example)
02:20beakyis IO pure in clojure like haskell?
02:20Chousukenah, clojure is not a purely functional language
02:20beakyah, so clojure is more practical ^^
02:20sparkjoyvery much so
02:21Chousukeit's not more practical for that reason
02:21Chousukeit may be more practical because of JVM interop, but not because it's impure
02:21callentdignan: code being data has nothing to do with being functional, that's homoiconicity.
02:21RaynesIt's certainly more practical for people without the patience necessary to learn Haskell well enough to use it properly.
02:22callenRaynes: I don't think the purity is the confusing part with Haskell.
02:22Raynescallen: Wasn't saying it was.
02:22Chousukethe way haskell does IO is instead of "functions" that just do it, IO actions are represented as values that don't actually do anything until the *runtime* "interprets" them
02:22callenfair enough.
02:23Chousukeso you can store those values in data structures and copy them around, since without the runtime interpretation they don't actually have side-effects
02:24beakyso clojure is practical because it runs on the jvm and has seamless java interop and lisp metaprogramming facilities?
02:24ChousukeClojure is practical if you can use it to solve a problem you have
02:24beakyah
02:24Chousukeif you can't, it's not practical, in your case.
02:25Chousuke"practical" is very relative
02:25ChousukeSome people would consider Agda to be practical because they need to write formally verifiable software :P
02:25beakyright
02:26beakyI guess sometimes the functional style is very practical
02:26Chousukeit has many benefits
02:26Chousukethe main one, to me, is having fewer things interacting
02:26Chousukeso fewer things to worry about
02:27Chousukewhen working with mutable data, in theory anything could interact with anything else at any point during execution, so you have no guarantees, and have to code in a way that minimizes the likelihood of such interactions occurring when not intended
02:28Chousukeif you work with immutable data, you have a guarantee that nothing will affect it short of hardware failure
02:28matkomutability is adventurous, living on the edge
02:29matkothere's actually no such guarantees though, are there? Reflection lets you 'break in' at any time if you wish
02:29Chousukewell, that's true. but such violations would be easy to spot
02:30Chousukeyou can't do something like that by mistake
02:30beakyin rich hickey's talk about simplifying programs he did mention that immutable data simplifies things a ton; does clojure give lots of help in having immutable data? (C++ isn't really helping much in that area :( )
02:31ChousukeAll of clojure's basic data structures are immutable
02:31sparkjoyimmutability is the default in clojure
02:31Chousukethere's also a system for safely handling shared state, with well-defined concurrency semantics
02:32sparkjoyimmutable + persistent (e.g. efficient versioning) data structures are really handy and idiomatic
02:33sparkjoywe've been doing a lot of functional style work in an OO language, with somewhat persistent data structures, but it's not idiomatic and sometimes it can be painful
02:33Chousukepersonally I find it difficult to work with mutable data nowadays
02:33Chousukeit's frustrating to have to worry about making mistakes.
02:33sparkjoyyou find yourself fighting the language a lot - clojure makes these things much easier
02:35sparkjoyright I can't tell you how many times as a library developer I've been handed a mutable collection and wondered, "should I clone this, or is it gonna be stable"
02:35Chousukesay if in python you have a list full of dictionaries full of lists and want to transform it somehow. it ends up being rather painful.
02:36Chousukeespecially if you want to hold on to the non-transformed version
02:38Chousukefor example, what if one of the lists you're transforming is being shared with some other part of the code? you've just broken things.
02:38Chousukeit's not fun
02:39murtaza52(def primitive-conv {:I 1 :V 5 :X 10 :L 50 :C 100 :D 500 :M 1000})
02:39murtaza52(defn substraction-rule
02:39murtaza52 [coll]
02:39murtaza52 (map #(if (primitive-conv %1)
02:39murtaza52 (if (< (primitive-conv %1) (primitive-conv %2))
02:39murtaza52 (list '- %2 %1)
02:39murtaza52 %1)
02:39murtaza52 %1)
02:39murtaza52 coll
02:39murtaza52 (rest coll)))
02:39murtaza52(substraction-rule b) => (+ (- :L :X) :L :I)
02:39murtaza52expected => (+ (- :L :X) :I :I)
02:39brainproxymurtaza52: gist or refheap please
02:39brainproxydon't paste in chan
02:39murtaza52How do I correct the above fn ?
02:39murtaza52sorry let me do that
02:45murtaza52Can anyone help is getting this right - https://www.refheap.com/paste/13927
02:51matkoso why is 'ideomatic' so important? Like, I had a debate the other day about (seq collection) vs (not (empty? collection)), where the other guy argued that (seq collection) was the more ideomatic way to check for non-emptyness, and the documentation seems to concur. Why is 'one way' so important?
02:52antares_matko: it's not more idiomatic. Also, it's a matter of taste. Use (not (empty? …)) if you prefer that.
02:52matkook, so maybe I have the wrong definition of ideomatic in my head
02:52matkoI've really only ever heard this word in clojure context
02:52Chousukeactually using (seq foo) in a boolean context is a Clojure idiom
02:53matkoI prefer (not empty? ..) cause it gives true rather than a value
02:53matkoerr.. messed that up, but you get the idea
02:53Chousukeand (not (empty? foo)) is the same as (not (not (seq foo))
02:53Chousukesee the definition of empty?
02:53matkoreading it now..
02:54Chousukeidiomatic just means something that is commonly accepted as being good style
02:55Chousukeand an idiom is an instance of that. eg. it's a clojure idiom to use map/filter instead of explicit loops
02:55matkoso why does this matter? I mean, 'good style' of course matters, but is (seq foo) truly better style than (not (empty? foo))? I find that rather arbitrary
02:55antares_but it doesn't have to be the only style
02:55Chousukematko: it is arbitrary, but that's what makes it an idiom
02:56Chousukeit's the accepted choice among many.
02:56matko>Heh, but what is the purpose of having an accepted choice?
02:56Chousukewell, lots of Clojure functions deal with sequences
02:57rodnaph_can anyone tell me how to emit a "debugger;" statement via clojurescript?
02:57noidiwhen there's a Right Way (tm) to do something, it's easy to see what the code is doing just by its shape
02:57Chousukeso (seq foo) fell out from that
02:57Chousukeand it's shorter. and faster :P
02:57rodnaph_gah! got it, just as i had given up (http://stackoverflow.com/questions/11181752/clojurescript-breakpoints)
02:58noidiin C there's an idiom for iterating over a collection: for (i = 0; i < size; i++). everyone who sees that knows immediately what's going on
02:58noidiof course you could use a while loop there, but that would not be idiomatic, and it would require more thinking from the reader to see what the loop's about
02:58Chousukenoidi: it's also an idiom in C to treat integers as booleans, for whatever reason
02:59matkoChousuke: ah, that makes sense
02:59Chousukeit makes no sense if you start thinking about it but no-one considers it weird at all in the context of C
02:59matkonoidi: but I disagree with the idea that (seq foo) looks clearer than (not (empty? foo)) :p
03:00noidiseq vs. not empty? is not the best example of a clojure idiom, as it's one that many people disagree with
03:00matkoat least I know a rationale behind it now
03:00Chousukematko: it doesn't look clearer, but since you should know what seq does if you want to get anything done in Clojure, you learn that particular idiom quite quickly
03:00Chousukeand *then* it will look clearer
03:00Chousukebecause it's shorter
03:00noidia better example might be mapping over a map: (into {} (for [[k v]] m] [k (f v)]))
03:01matkowell I come from a common lisp background, so I'm very familiar with using value and nil as true and false.. it just striked me as odd that clojure would do it when it also has boolean values
03:01tieTYTwith gen-class, is it possible to pass the :methods in as a variable? I'm not sure how to do that because it needs a symbol in it (the name of the method without the prefix)
03:01noidiyou see "into {}" and "for [[k v]] m]" quite often in clojure code
03:01Chousukematko: booleans are there only for java interop
03:02matkohaha really? I thought they were there from scheme
03:03Chousukeit's a wart, but a necessary one
03:03Chousukeit would be difficult to use Java libraries without access to booleans
03:04matkoBut clojure propositions return true or false as well
03:04antares_Chousuke: I doubt that
03:04Chousukethat just helps when calling them from Java
03:04amalloyChousuke: i disagree that booleans are only for java interop
03:04Chousukemost clojure code doesn't really care.
03:05Chousukeamalloy: well, they are useful outside it too, but not required
03:06amalloylists and numbers aren't required either: we could just work with church encodings in the lambda calculus. but they're easier and more sensible to work with, and so are booleans. why should (= 1 2) return the empty list instead of false?
03:06Chousukenil is not the empty list
03:06Chousuke() is the empty list
03:07matkowait what.. nil is not '()?
03:07ChousukeI'm just saying that Clojure has no real need for explicit booleans because you could use nil and anything non-nil instead
03:07ChousukeRight. nil is not ()
03:07matkowow confused
03:08Chousukein Clojure nil means "nothing"
03:08matkoit also evaluates as true it seems
03:08matkoin an if
03:08Chousukeyeah, because it's a value
03:08beakydoes clojure have tail-call optimization?
03:08sparkjoynot automatically, beaky - need to use recur explicitly
03:08matkounfortunately it doesn't have tail-call optimization
03:09Chousukethe JVM doesn't guarantee tail-call elimination
03:09Chousukepeople get this stuff confused really easily
03:09Chousukethere's a difference between doing tail-call elimination and *guaranteeing* it
03:10Chousukethe latter is an issue of language semantics. the former is just an optimization.
03:10sparkjoygood point
03:10beakyah
03:11beakytoo bad :(
03:11matkoso, nil and false are false, everything else is true, and the seq trick works cause seq returns nil rather than the empty list when called on an empty collection
03:11matkothis feels.. hackish
03:11xxxyxxyxxoioiiiiiii9o99
03:11xxxyxxyxxmadar chod
03:13beakywhat is clojure's associative model for data?
03:13beakyis it like a map?
03:13sparkjoymaps and records
03:14beakyah neat
03:14sparkjoyrecords give you associative via a class, higher perf, easy to move to once you've figured out your model with a map
03:15Chousukematko: the way seq works is that if you have something in a collection, it will returns a seq representing the contents. if there is nothing, it returns nothing (nil)
03:15beakyrecords are like structs in C, or classes with no methods and all data fields public in java?
03:15beakyor ADTs like in haskell?
03:16Chousukerecords are an optimization of maps
03:16sparkjoypublic final fields on a gen'd java class
03:16matkoChousuke: I see that, but don't understand the reason for not returning an empty list instead, exept to return something that evaluates to false.. but in that case I don't get why empty list is not false in the first place.. eh, it doesn't matter much
03:17Chousukematko: it's not false because there are other empty things
03:17Chousukean empty list is distinct from an empty vector
03:17katratxomatko: only false and nil are "falsy"
03:17Chousukeand I think treating nil as an empty list is a mistake that CL made.
03:18sparkjoyoh interesting point about () and [] - never thought about it that way
03:18matkoit made recursing over lists easy
03:18matko(in common lisp)
03:19ChousukeI suppose seqs in clojure are sort of like CL lists in that regard
03:19Chousukeyou can recurse until (seq whatever) returns nil
03:20Chousukeand because you're calling seq in the recursion, the function works the same for all seqable data structures
03:20matkoyes, I like how clojure made vector and map as easy to use as lists
03:21sparkjoyone quick point about (seq foo) - if foo is a lazy seq, in my experiments this causes foo to materialize. Just tested it on an infinite seq and it materialized the first 32 items.
03:21sparkjoythat surprised me the first time I saw it
03:21Chousukesparkjoy: yeah it has to force one element to know if there are any
03:21sparkjoymakes me less confident that (seq foo) is faster than (not (empty? foo))
03:22sparkjoyif you weren't going to materialize it I suppose
03:22Chousukesparkjoy: it is faster because empty? is defined in terms of seq :P
03:22sparkjoyLOL nm then
03:22sparkjoythat's funny
03:22Chousuke32 elements getting realized is just an internal optimization (chunking)
03:22sparkjoyyea that's what I figured
03:23Chousukein general, having sequences with side-effects is a bad idea
03:23sparkjoyyea, I threw a println in a map to test it out
03:23sparkjoywas just curious
03:23mthvedtsequences with side-effects were a pretty fun paradigm for some computations
03:24mthvedtnow, you have to be careful about chunks
03:25Chousukelaziness and side-effects don't mix very well with dynamic typing :P
03:27mthvedtchousuke: i can think of a billion procedural languages with dynamic typing
03:27Chousukeactually, any time side-effects are involved you just need to be careful, regardless of the language or its laziness.
03:28Chousukemthvedt: sure, but lazy + effectful is already a bit of a problem. In Haskell's case, the type system at least helps a bit.
03:29mthvedtwell one reason haskell needs that, though, is because it enforces laziness
03:29Chousukefortunately laziness in Clojure is restricted to sequences so it's easier to control
03:29mthvedtclojure isn't a lazy language, it's an eager in-order language
03:29mthvedtbut a lot of lazy paradigms are used
03:30mthvedtbecause they are useful and convenient
03:30ChousukeI don't mind Haskell's laziness though. There are many useful things you can do only because it is lazy.
03:31beakyhaskell avoids success at all costs :D
03:31mthvedtidk, haskell reminds me of the guy who could be a successful manager but would rather be a senior engineer instead
03:32mthvedtwhere playing with neat ideas > practicality
03:32Chousukeit does make things harder for people trying to figure out how to make things efficient, but the haskell community is full of smart library writers solving that problem.
03:32Chousukemthvedt: the thing is, those neat ideas turn out to be practical once you get them fleshed out
03:33ChousukeFunctors and applicatives are something everyone uses. Monads too.
03:33mthvedtwell, monads are like
03:34mthvedtyou can do all these neat things with monads and monadic flow control, but that doesn't explain why you need them to write to stdout
03:34Chousukemthvedt: You don't need monads to write to stdout
03:34mthvedtchousuke: really? hacker news threads have lied to me
03:34Chousukemthvedt: the thing is, if you want to write to stdout, you have a monad
03:35Chousukeit's not that monad -> ability to write to stdout
03:35Chousukeit's that ability to write to stdout -> monad
03:36mthvedti have to confess that's not very eludicating
03:36Chousukemthvedt: I assume you already understand that haskell is pure? basically everything is an immutable, side-effect free value
03:37Chousukerepresenting side-effects in a system like this may seem difficult at first but it's really not
03:37Chousukeall you need is the ability to treat the "instructions" as values
03:37Chousukeand then the runtime will interpret those instructions
03:38Chousukeso when you say main = getLine in haskell, you're saying that the value of main is getLine
03:38Chousukeand when the program executes, it "sees" that the value of main is getLine, and does what it needs to do
03:38beakyhow does clojure compare to haskell in expressiveness? I guess clojure wins in that ballpark thanks to dynamic typing and metaprogramming facilities
03:38Chousukewhat monads accomplish is allow you to combine two values into one that represents both
03:39beakyor is haskell's magical type system surprisingly expressive?
03:39Chousukeso you can say main = getLine >>= putStrLn
03:40Chousukewhich just says "the value of main is the combination of getLine followed putStrLn with the result of getLine"
03:40Chousukefollowed by*
03:40Chousukeand that's it
03:40mthvedtyes, and that's what i'm getting at
03:41mthvedtit's dancing around an impedance mismatch, followed by bragging about how neat the dance was
03:41Chousukemthvedt: there is no impedance mismatch
03:41Chousukeint main() { x = getLine(); putStrLn(x) } says the *exact* same thing
03:42tcrayfordbeaky: I've never had a problem with expressiveness in either language. Clojure has macros, haskell makes it super easy to write a dsl with free monads/data types.
03:42beakyah
03:43Chousukemthvedt: the cool thing in haskell is that it recognises that the operation that combines the two substeps also applies to a lot of other things.
03:43Chousukefor example, callbacks-oriented control flow can be represented as promises
03:44Chousukeand the operations to combine promises... form a monad
03:44mthvedti know how monads work
03:44mthvedtif that wasn't clear before
03:47Chousukeat any rate, the point is that you don't need monads to do IO, callbacks, or short circuiting evaluation.
03:47Chousukebut since you do all of those things anyway
03:47Chousukeand all of them form monads
03:47Chousukewhy would you not use monads?
03:49Glenjaminwhat's the advantage of doing (do a b) to represent (a >>= b) instead of having the language allow a; b ?
03:50beakya >>= b is formally recognized by the type system
03:50Glenjaminor i guess, why do i need to know it's a monad
03:50mthvedtthat's a good question to ask anyone who's ever done unsafeperformio
03:50beakyonce you know that something forms a monad, you can do cool stuff that worked on other monads :D
03:51clgvGlenjamin: good question, e.g. I can use `for` and do not need to know that it is a monad in principle... ;)
03:51Glenjamini'm ok at basic haskell, but i never really grokked monads - so never done anything more complex than homework assignments
03:51Glenjaminthe list monad being some form of nondeterministic search really confused me
03:52mthvedtthe other thing is
03:52Glenjaminand then you get into arrows and functors, it often felt like abstraction for abstractions sake
03:52mthvedtshould a language really have a high barrier to entry for doing io
03:53noprompti think it largely depends on what the goals of the language are.
03:53Glenjaminjust because everything i do is equivalent to a mathematical model doesn't mean i want to deal with the model most of the time
03:54ChousukeGlenjamin: the nondeterminism is actually not that hard to understand
03:54ChousukeGlenjamin: you can think of a nondeterministic function as one that retuns a list of all its possible outputs
03:54mthvedtin practice, a lot of people don't understand it
03:55Glenjamini know, but *why* treating lists as monads make them deterministic was lost on me
03:55Glenjaminit was like discovering prolog hidden in the standard sequence container
03:55ChousukeGlenjamin: then combining a nondeterministic function with another means running the other function with every output from the first one
03:55Chousukeand concatenating the result
03:56Chousukeand that operation of combining them is what gives you a monad (along with a return operation)
03:57Chousukethe benefit from treating things as monads generically is that you can write functions that work across all monads
03:57Chousukeand if you have syntactic support for one monad, you have syntactic support for all monads
03:59Chousukeimagine if in C++ you could just do foo (Foo* x) {return x.doSomething()} and if x is null you just get a null.
04:00Glenjamini don't write in C++, but that seems like how all the high level languages without monads work in that scenario
04:00Glenjaminoh, sorry misread
04:01ChousukeGlenjamin: the thing is, people are adding these things into languages as special cases
04:01Chousukesome languages have .? for null propagation
04:02Glenjaminmm, because you often don't want null to make it further through the computation and blow up when you need a value to do something useful
04:02Chousukethen there are those coffeescript extensions with await and whatnot for less insane node.js programming
04:02Chousukewhereas if you just had a neat syntax for >>=, you'd get all that for free.
04:02nopromptless insane node.js programming?
04:02nopromptnot sure if that's saying much. :)
04:02Chousukenoprompt: avoiding nested callbacks
04:03nopromptChousuke: yeah, i know what you're refering too.
04:03Glenjaminmeh, i like node.js
04:04Chousukeif you coded node in haskell you could just write do { x <- someAsyncOp; y <- anotherAsyncOp; return x+y}
04:04Glenjaminthe module loading system and dependency management encourages really small, clean re-usable modules
04:05Glenjaminagain, i don't really see that as being leaps and bounds better than async.parallel([someAysncOp, anotherAsyncOp], callback)
04:05nopromptwell, there is type safety. which *is* a good thing.
04:05Chousukewhereas in javascript that's like someasyncOp(function(x, err) {if (!err) anotherAsyncOp(x, function...{})})
04:05Chousukewhich is a complete horror
04:05Glenjaminnoprompt: like in clojure?
04:06Chousukeglenjamin: oh, I forgot to add a dependency of anotherAsyncOp to x
04:06nopromptjavascript is just horrific in general. you have to be armed to the teeth with a body of knowledge before you can even consider writing serious code in the language.
04:07Glenjaminagain, i don't really see that as being leaps and bounds better than async.waterfall([someAysncOp, anotherAsyncOp], callback)
04:07ChousukeGlenjamin: yeah, and that's a monad
04:07Glenjaminnoprompt: i don't strongly disagree, but to do web work you have to know it pretty well
04:07nopromptit's probably the second or third worst language i've used (php being the first).
04:07GlenjaminChousuke: right, but does knowing its a monad change anything?
04:07ChousukeGlenjamin: you're just using a non-generic implementation of the exact same thing
04:07Glenjaminyes, i agree
04:07ChousukeGlenjamin: and you don't get syntactic benefits
04:08nopromptGlenjamin: well yes if you write raw javascript.
04:08Chousukedo notation is better than what you wrote.
04:08Glenjaminbut is it much better?
04:08Chousukeit is.
04:09Chousukebecause it's based on something generic, and thus extends to things you can't even imagine yet.
04:09Chousukelike, say, the Tardis monad :P
04:09Chousuke(which is a combination of state and reverse state)
04:09nopromptChousuke: you're making want to pick up haskell again. :)
04:10noprompt*making me
04:10Chousukeit's unfortunate that Monads are called monads
04:10Glenjaminthey should reall be Monoids!
04:11Chousukeif they were called "generic API for boilerplate" people might not be so scared
04:11Glenjaminwhat's that phrase now...
04:11Glenjaminmonads are just monoids in the category of endofunctors
04:11Chousukeyeah, heh
04:11mthvedti only program in the lambda calculus on categories
04:11mthvedteverything is a category
04:12Glenjamini'm not especially scared of them, it's just i'm unconvinced of the improvement - you still have to understand what the properties of the monad you're using are in order to compose them
04:12ChousukeGlenjamin: there are a lot of big words in that sentence but what is actually says is really simple :P
04:12ChousukeGlenjamin: sure, but you're doing that anyway when you're working with any kind of data
04:13Glenjaminyep, but more concrete abstractions designed for the particular problem can make the tasks you're likely to do easier
04:13ChousukeI've never seen an example of that
04:13nopromptGlenjamin: you know it's funny you mention that.
04:13Glenjaminand you could build them out of monads, or something less general - but when i'm using the specialised version it stops mattering
04:14ChousukeGlenjamin: I mean, you can do things with specialised versions and it's easy
04:14Chousukebut using the non-special versions is easy too
04:14Chousukeit's just two operators :|
04:14Chousukeand one of them is trivial
04:15nopromptpersonally, i think people tend to looking to apply general solutions or patterns when building software that they actually miss out on what they're actually trying to do.
04:15Chousukeit's like you'd rather have listSort() mapSort() vectorSort() all separate so that you know what you're sorting each time :P
04:16Chousukenoprompt: I don't think monads are like that
04:16Glenjaminthats why we have interfaces, or protocols / type classes
04:16nopromptChousuke: i don't necissarily either.
04:16Glenjaminthe monad stuff is at a level of abstraction I don't often need to deal with
04:17ChousukeGlenjamin: you're dealing with it all the time
04:17Glenjaminand yet I don't know I am!
04:17Glenjaminwhich is my entire point
04:17ChousukeGlenjamin: if you knew, you'd stop repeating yourself :)
04:17noprompti guess what i notice is that people learn about a X design pattern or X abstraction technique and try to make use of it when they really could have just solved their problem with a few lines of code.
04:18GlenjaminThat's a monad, I can use the monadic operators / That's some repetition, I can abstract that away
04:18Glenjamin^^ whats the difference?
04:19ejacksonnoprompt: i'm not seeing that in myself. As I learn higher level concepts, they dissolve the lower level ones. But its taking a long time.
04:19nopromptiow i can sympathize with what Glenjamin is saying.
04:19Chousukemonads are just a generic operator for the boilerplate in the following: A -> (operation) -> (boilerplate) -> B
04:19nopromptejackson: i wasn't refering to a large body of people, but some do approach software in this manner.
04:20ejacksonfancy composition operators :)
04:20Glenjaminso is A -> (high-level-operator) -> B
04:20ChousukeGlenjamin: that doesn't work if the operator doesn't actually return B
04:20noprompti worked with a guy a while back who was just so obsessed with "patterns" that it drove me to quit working with him.
04:20ejacksonnoprompt: oh, sorry, I thought you were making a general argument against higher level abstractions
04:20ejacksonnoprompt: hehe, I know what you mean now :)
04:20ChousukeGlenjamin: it's just so obvious to me.
04:21ChousukeGlenjamin: if you have functions that can return null, you can just go foo(bar(something(A))) to get B
04:21Chousukeyou have to do null checks after everything
04:21Chousukewhich is just boilerplate that you can't avoid
04:21Glenjamin(cond-> A something bar foo)
04:22Chousukethat's just one case
04:22nopromptejackson: i guess my point was that it's important to know when and where to apply abstraction.
04:22Glenjaminit's the case of hiding null
04:22ChousukeGlenjamin: if you have monads and syntactic support for it, you don't need any such special operators.
04:22nopromptof course, i still struggle with that too :)
04:23Glenjaminif you have macros and syntactic support for them, you don't need any such special monads?
04:23Chousukemacros don't compose
04:24Glenjaminmm, thats true
04:24Chousukewhat if you had async operations that could return nulls?
04:24Chousukeif you implemented these things as monads, you could still use do syntax
04:25Glenjaminbut what if i want to evaluate in parallel, or do something other than chain the calls?
04:25Glenjaminsurely i still need more notation
04:25ChousukeGlenjamin: do notation doesn't specify evaluation order
04:26Chousukeother than what is implied by the dependencies of each expression
04:27Glenjaminbut if two computations fail in parallel, what error value would i get back?
04:27Chousukeboth? it depends on the implementation of your bind
04:27Chousukethat's the point
04:27Chousukeyou get to decide what happens
04:27Chousukebut the syntax stays the same
04:28Chousukethere are of course limits to what monads can express
04:28Chousukebut sufficiently many things are monadic that having syntactic support for them is convenient
04:29nopromptthe day a language which marry's haskell and lisp comes a long will be a glorious day.
04:29ChousukeI think there is one already
04:29Glenjaminyou have convinced me there's an advantage when building composable operations
04:30nopromptChousuke: there are actually a few i've seen, but they're either no longer maintained or incomplete.
04:30ChousukeGlenjamin: if you think about it, composing things is the majority of what a programmer does nowadays
04:30ejacksonChousuke: so, which is it ? :)
04:31ChousukeLiskell is one I've seen mentioned somewhere
04:31ChousukeI haven't actually looked at it
04:32ejacksondo you use Clojure's monads at all ?
04:32nopromptthe last i checked liskell wasn't being maintained.
04:32nopromptthere's another one called shin.
04:33Chousukeejackson: I have some code that uses them, and I implemented monads once myself using protocols :P
04:33nopromptsorry, shen.
04:33GlenjaminChousuke: you've managed to pique my interest enough to try using some monads in my clojure :)
04:34Chousukeejackson: They're not as ubiquitous in Clojure since having a static type system really helps with monads (gives you safety and all) but you can still get some pretty elegant code
04:34Glenjaminand now I'd better go to work!
04:35ejacksonyeah, i hardly ever see them in the wild
04:39Chousukeejackson: https://gist.github.com/Chousuke/141085 here's some toy code I wrote ages ago to test out clojure monads. I don't think it'd be trivial to write without monads.
04:40Chousukeor rather, you'd just end up duplicating State :P
04:41Chousukeit's a functional parser that supports incomplete input and can be resumed arbitrarily many times.
04:41ejacksonthat's pretty cool
04:41ejacksonand short !
04:41ChousukeIIRC it has a bug though where the regexp sometimes fails if the input is split in a certain way
04:43ejacksonhaskell is like malaria: every few years I succumb to a relapse
04:44nopromptejackson: couldn't have said it better myself!
04:44ejacksoni *so* want to actually use it all the time, but haven't put enough block time aside to get it right
04:44noprompti'm debating picking up either erlang or prolog over the summer.
04:44ChousukeMy main problem with haskell is that it makes it more difficult for me to program in other languages
04:45ejacksonClojure has done that to me too
04:45Chousuke"gah why can't I just fmap this and be done"
04:45nopromptChousuke: yes, and it dooms you to see bugs.
04:45ejackson"what do you mean I can't use vectors as keys in a map, PYTHON ?"
04:45ejacksonwhat's haskells matrix story like ?
04:46nopromptejackson: clojure reduced ruby to my shell scripting language.
04:47nopromptactually, functional programming in general has ruin my experience in any language that isn't functional. :'(
04:47Chousukeejackson: I tried doing v = v.sort() in python and then wondered why it wasn't working (I didn't get NPEs because my template-engine silently converted nulls to nothing)
04:48nopromptdoomed to obscurity at the local developer meetups. it's a sad life. :)
04:48ejacksonyeah, exactly. Clojure teaches you to rely on certain things, and elsewhere they're just not there.
04:48nopromptChousuke: i had a fun conversation about the relevance of using negative indexes the other day with a python programmer.
04:49nopromptapparently python doesn't even have a last function.
04:52nopromptejackson: clojure is also a great lesson in thinking in terms of data and data transformation.
06:02ayiaHi guys, How can i "paste" name passed to macro like (defmacro def-name-var [name] ...) into name of the var in its definition, where name should be like -<name>-fields?
06:16clgvayia: please provide an example macro call and the desired expansion
06:29noidiayia, maybe you want `symbol`? it takes a string and returns a symbol, so you can do something like `(def ~(symbol (str name "-suffix")) ~value)
06:40ayiaclgv: =>(def-name-var jack) ;; should create a var with name -jack-fields
06:40clgvayia: ok
06:41clgvayia: (defmacro def-name-var [var-name] `(def ~(symbol (format "-%s-fields" (name var-name)))))
06:43ayiaclgv: noidi: thanks you guys, for this approaches... Just one more question, is there any other way to do this, maybe just with using quotes/unquotes? i.e. to make the code even more readable...
06:44clgvayia: no. you can define a separate function though
06:46ayiaclgv: what does this mean "define a separate function"?
06:49jaffe_ayia: you can define a function that adds the suffix to the symbol, and then have your macro call that function instead
06:51clgvayia: (defn derive-symbol [fmt s] (symbol (format fmt (name s)))) and then (defmacro def-name-var [var-name] `(def ~(derive-symbol "-%s-fields" svar-name)))
07:00ayiaclgv: jaffe_: got it! thanks!
07:56beakyhello
07:56knobHello!
07:56beakyRich Hickey often refers to "Polymorphism a la carte" in his speech; what does that mean?
07:56beakyis it like the single-dispatch polymorphism in C++?
08:00sparkjoyI'm not the expert, but my studies so far have revealed both single-dispatch polymorphism
08:00joegalloi think it's like, you can have a slice of cake, or a slice of pie, or also there's multimethods
08:00sparkjoybut also multi-methods
08:01sparkjoyprotocols use single dispatch, with a privileged first arg (like this in OO)
08:01hyPiRionbeaky: polymorphism as polymorphism itself. It's not bound to classes, only to functions.
08:02sparkjoymultimethods allow you to dispatch based on more than just the first arg
08:02sparkjoyalso a very cool thing about protocols
08:03sparkjoyis that you can extend them not only to types that you define
08:03sparkjoybut also to types that others have defined for which you do not control the source
08:04sparkjoyI'm just learning about protocols now (highly recommend _Clojure Programming_) but they sure seem powerful
08:08DerGuteMoritzsparkjoy: note that protocols are just a subset of multimethods
08:08beakyclojure has multimethods too?
08:08DerGuteMoritzyes
08:08sparkjoyyep beaky
08:08beaky(even though it isn't OO at all) :D
08:09DerGuteMoritzprotocol methods are just like multimethods which dispatch on the type of the first argument
08:09Bronsamh, I don't think protocols are exactly a subset of multimethods
08:09beakyso OOP has no monopoly over polymorphism?
08:09DerGuteMoritzwell, and with protocols you can also check whether they are implemented for a certain type, not sure if that's possible with multimethods
08:09Bronsawith protocols you can dispatch on the interface too, I don't think you can do that with multimethods
08:09DerGuteMoritzBronsa: how do you mean?
08:10DerGuteMoritzsurely you can use the same dispatch function that's used by protocols?
08:10Bronsa(extend-protocol proto clojure.lang.IPersistentMap (f [this] ..)))
08:10DerGuteMoritzexcept protocols will be more efficient
08:10Bronsawith a multimethod, you can't do that if you're dispatching on the first argument type
08:11DerGuteMoritzBronsa: ah, perhaps
08:12sparkjoybeaky: there's plenty of polymorphism in Clojure - you just have finer grained control
08:14sparkjoywatch Rich's "Simple made easy" talk - I think you'll get a feel for his goals of "decomplecting" systems
08:14beakyyeah that was an awesome lecture
08:23beakyso OOP is the enemy of simplicity?
08:24sparkjoyI wouldn't go that far, but I'm knee deep in an enterprise OO system now, using all the best practices, DDD, etc.
08:24sparkjoyand I can tell you that we are not as agile as we could be
08:24sparkjoyin large part because of the silos (classes) we've constructed around our data
08:25sparkjoywe program with immutable objects in C#, and we use immutable, persistent data structures, but this is not idiomatic so we find ourselves fighting against the current a lot
08:26sparkjoyand our persistent data structures suck compared to what's provided by default in Clojure
08:54cmajor7what would be the way to render protobuf from compojure? overrite "Renderable" with "byte-array" type?
09:18stuartsierraBy the way, Hudson releases are (mostly) working again.
09:18stuartsierraIn case anyone was waiting to release a library or something.
09:18stuartsierraSee my latest email to clojure-dev.
10:12dsabaninhey guys
10:13dsabaninhey guys
10:14silasdavisI'm getting a "don't know how to create ISeq error" which I've learnt usually means I've done somethign weird with '()'
10:14silasdaviscould anyone explain how the handler on line 52 could cause this error
10:14silasdaviswhen the alternative handler/site works fine
10:16dsabaninI wonder what is the right place to put a type hint for return value in defn? before arguments vector or before the name?
10:16ucbsilasdavis: paste code?
10:17silasdavisucb, oh I did paste it, I just didn't give you the link, how helpful of me: https://www.refheap.com/paste/13932
10:20ppppaulwhat should i use instead of walk to easily transform a nested data structure?
10:22stuartsierradsabanin: In the past, functions were type hinted with ^ClassName metadata before the function name.
10:23dsabaninah, I see. That explains why both ways work :)
10:23dsabaninthanks!
10:23stuartsierradsabanin: With the introduction of primitive function arguments & return values in Clojure 1.3, you could put return type hints on the argument vector.
10:24stuartsierrappppaul: If you know something about the structure of the thing you're walking, you can create your own recursive function that will be much more efficient than clojure.walk, e.g. using `update-in`.
10:25stuartsierraclojure.walk is a general, but not very efficient, solution to walking any arbitrary data structure.
10:25gfredericksclojurebot: clojure.walk is a general, but not very efficient, solution to walking any arbitrary data structure.
10:25clojurebotIn Ordnung
10:26stuartsierraclojure.walk also doesn't work on `defrecord` types
10:26stuartsierraif I recall
10:27tcrayfordalso you could try using a zipper. They are super good for walking nested structures and manipulating bits of them as you go
10:27ppppaulstuartsierra, i have found that when i attempt to do transformations with update-in it can get very hairy
10:27ppppaulmaybe i'm doing them wrong
10:27stuartsierraOh, it can get hairy. :)
10:27ppppauli find my walks to be very simple
10:27ppppaulthough, when i need a complicated walk it usually fails
10:28ppppaulso i stack a few simple ones together
10:28ppppaulcurrently i'm mostly using walks for testing
10:28stuartsierrappppaul: If it works and is fast enough for the use case, then there's no reason not to use clojure.walk.
10:29ppppauli think that i can probably get away with memorizing if i need performance
10:29ppppaulthanks stuartsierra, last night there was some talk about walk, and it made me feel like i may be going in the wrong direction with my style of clojure programming
10:30stuartsierra`walk` is certainly convenient - that's why I wrote it. :)
10:32ppppauli have found it very useful. i even ported it to javascript.
10:36ppppaulactually, since i'm on this topic... stuartsierra there have been occasions where i want to rip out some things from a tree and put them in a flattened array. like maybe all integers or something. i tried to do this a few times with walk but found it extremely hard. do you have any strategy for doing something like that (other than using an atom)?
10:36stuartsierraYeah `walk` isn't really designed for that.
10:37stuartsierraI do it with recursive functions and `mapcat` but it's not always easy.
10:37ppppauljust wondering if there was some clever way to deal with that with walk... like returning arrays and then doing a flatten or something
10:38VFeAnyone been using Riak via Clojure and have any recommendations for client libs?(i.e. any reason or problems I might encounter using Welle over Sumo or clj-riak, etc)
10:38tcrayfordwhat kinda items are you querying for? You might be able to use tree-seq
10:38antares_VFe: clj-riak and sumo are not really maintained, AFAIK
10:38tcrayfordVFe: I have been. I think welle's the only one of those that is regularly updated
10:38ppppaulhmm... something like #(= (type %) "whatever")
10:38tcrayford(sadly, I don't think welle is very well designed at all)
10:39VFeyeah, welle has been giving me some issues, and I was curious if people used one of the others more regularly
10:39antares_tcrayford: how many ways are there to design a K/V store API? :)
10:39antares_VFe: care to elaborate? I'm the author
10:39VFeOh, well hello :)
10:40ppppaulantares_, redis...
10:40tcrayfordantares_: when that store is eventually consistent, there are quite a few things welle does that I'm sad about (I'm a contributer, and using it)
10:40antares_ppppaul: I'm talking about client libraries
10:41ppppaulhmmm... there are probably a lot of ways to do so
10:41antares_tcrayford: well, I've seen only one issue from you, what else is missing?
10:41antares_ppppaul: really? for a key/value store?
10:41ppppaulbut the top level API shouldn't be so big
10:42VFeWell, first question, when I run it from repl, am I supposed to see like 3 pages of reflection warnings?
10:42antares_VFe: welle itself has next to no reflection warnings
10:43antares_some of its dependencies have them
10:43tcrayfordantares_: the api doesn't force people to use resolvers/retriers, and the docs sorta handwave over receiving conflicts.
10:43antares_tcrayford: and that's it?
10:43VFeyeah, I see nrepl, complete/core, etc, so that's expected behavior then?
10:44antares_tcrayford: retriers are now used by default. Forcing people to use resolvers sounds a bit too much.
10:44antares_tcrayford: man, at least we have some documentation. Most projects don't even explain what the hell R, W, DW and so on are.
10:44tcrayfordantares_: right. I'm glad about that ;)
10:45antares_VFe: the only way to solve it is to run after every dependency (and dependency dependency, and so on) and fix reflection warnings there
10:45antares_people did fix some in Cheshire and clj-http
10:46antares_sometimes they can't really be avoided, because in Clojure you only can overload on function arity, not types
10:46tcrayfordantares_: the fact that I've been wrapping welle in my own library so that the interface is nicer kinda makes me want to just go away and write my own clojure client lib on top of the basho java client.
10:47antares_tcrayford: well, it's your call :)
10:47tcrayfordantares_: I'm not sure, but I think modify might do the wrong thing with vclocks right now as well. Also, I have a rant about the *riak-client* and binding style of injecting the client, but that seems standard in clojure, sadly.
10:48antares_tcrayford: there is one thing that will change in 1.6 with vclock
10:48antares_apparently the value we need to propagate is the one from the response
10:48antares_and it's currently not preserved. So kv/fetch return value will have to change :(
10:49tcrayfordantares: is that with modify? That was my issue ;)
10:49antares_to {:vclock … :object …}
10:50antares_tcrayford: it affects modify but is also a problem of its own
10:50antares_unfortunately, the Java client itself has next to no docs
10:51antares_at least did not have them 2 years ago when Welle was started
10:51tcrayfordantares_: that'd cause sibling explosion, right? (assuming you have allow_mult on, which should nearly always be the case)
10:51antares_so it wasn't obvious which vclock value we have to use
10:51tcrayfordantares_: yeah. It's been rewritten completely since then from my perspective ;)
10:51antares_yes, that's what aphyr has observed
10:51antares_with his network splits simulation tool
10:52antares_tcrayford: I didn't see major changes, they just added and documented some stuff
10:52tcrayfordheh. It's a good thing the app I've written on top of welle isn't in production yet then ;)
10:52antares_with this change, I don't think there will be anything missing in Welle w.r.t. to the Java client
10:52antares_except that you don't have domain objects, of course
10:52tcrayfordwell, that's part of clojure
10:52tcrayford;)
10:53tcrayfordthe shit you store in riak should just be data, not domain objects ;)
10:53ieureSup tcrayford.
10:53tcrayfordieure: sup
10:54antares_tcrayford: what I often used Riak for, I often used LWW :) but I hear ya. I think 1.6 will be out in the next few days. We got a lot of tests to update, but the code change is minor.
10:55tcrayfordantares_: neat. Thanks. I don't wanna sound pissed off, welle is reasonably good as far as the riak clients I've used go.
10:55antares_tcrayford: but I totally welcome more clients
10:55antares_tcrayford: there is #clojurewerkz now if you want to suggest something or complain about welle more ;)
10:56tcrayfordantares_: it'll be a while if I do my own, I have an app to ship first
10:56antares_VFe: not sure if this answers your question, but with 1.6, Welle will likely be good enough even for demanding users. And it is maintained, including the docs.
10:57VFeMy main issue was the reflection things, pages of warnings tend to make me think I'm doing something wrong XD
10:57antares_tcrayford: understandable. If you want to see more changes in Welle, please file an issue.
10:57VFeBut the discussion was enlightening, I mainly asked cause I have to decide what we're going to be using in production
10:58antares_VFe: can you gist them?
10:58VFesure
10:59tcrayfordantares_: honestly most of the changes I'd want to see would be api changes (e.g. I don't think most of the options to fetch/store/etc should be options, they should be bundled up in a "bucket", along with a resolver/retrier. Those are more personal opinion things though. I have an internal namespace that does all of that for me right now).
11:00VFehttps://gist.github.com/VFe/5452786
11:01antares_tcrayford: Riak Java client kinda has two clients: "raw" and POJO-oriented. We can consider adding a "higher level" one in Welle.
11:01tcrayfordantares_: yeah. We should take this discussion to #clojurewerkz, not keep it in here
11:01antares_VFe: so, most of them are from complete/core. Is that an OSS library?
11:02antares_VFe: clojure.tools.nrepl I can't fix, I live in a country that has no reliable mail to US, so I won't be filing Clojure CA until it is electronic :(
11:05VFeI actually don't know what complete.core is, though in regards to the second part, couldn't you sign the document, email it to someone you trust in the US, have them print it and send for CA?
11:05VFei.e. have someone act as your legal proxy
11:06antares_VFe: it's not a Welle dependency, it's loaded by something else
11:06noidiVFe, if that was acceptable then Rich Hickey could just receive the e-mail directly and print it out himself if he ever needs a copy
11:07antares_VFe: possibly. I don't generally bother with core.* stuff, even trivial patches are accepted 3-12 months after you submit them.
11:07antares_that's not how OSS should work and I'm tired of trying to change the system. There are better ways to spend time.
11:08antares_nrepl developers are a bit better in this regard
11:08beakyhello
11:09antares_VFe: if you run lein deps :tree, it should show you what dependencies you have. Could you please gist that?
11:09beakyhow do I run clojure programs on my platform? I am using archlinux on x86/64
11:09nDuffantares_: Can you send faxes? Those are legally recognizable in the US in many cases (Relevance would have to talk to their lawyer, which I'm not, to determine if that's the case here).
11:09VFelol, I like how I I just googled for complete/core/clj and now that gist is on first page of results
11:10VFeI suddenly feel so alone
11:10VFeand yeah, lemme do that
11:10noidibeaky, do you want to get started with Clojure development, or run a program written by someone else in Clojure?
11:10beakyget started :D
11:11antares_beaky: there are tutorials at http://clojure-doc.org, take a look
11:11beakyah thanks
11:11beakyhmm clojure uses square brackets and braces too... thats new :D
11:12antares_nDuff: the policy is, you mail a piece of paper or sign it at one of the Relevance events. And then there are "screeners" and Clojure/core and months and months of waiting. I won't bother with that.
11:12nDuffantares_: Yes, I know -- I've done the "sign it at a conj" thing.
11:12VFehttps://gist.github.com/VFe/5452872
11:12nDuffantares_: ...but I'm saying that it should be possible to make a case for accepting faxes.
11:12beakybtw why does it use first/rest instead of car/cdr?
11:12technomancyheh; faxes
11:13antares_nDuff: the process is made intentionally hard. I'm not going to cooperate.
11:13nDufftechnomancy: They're used for sensitive medical documents all the bloody time.
11:13antares_beaky: because nobody knows what car/cdr mean
11:13technomancyhttp://achewood.com/index.php?date=11222006
11:13nDuffantares_: Ahh. If it's protest, that's a completely different matter.
11:13antares_beaky: besides CL and Scheme users, which are a tiny % of people who get into Clojure (33% Java, 33% Ruby/Python)
11:13beakyyeah I guess it's car/cdr are way too oldschool/archaic and first/rest are more communicative
11:14VFeTechnically, in the US, signature is an intent, which is why anything can be a signature, including digital. or why you can proxy your legal rights at will.
11:14antares_nDuff: not really a protest, I just don't think it's worth it
11:14VFeSo if they don't accept an email or fax, its a matter of personal policy, not of legality
11:14noidibesides, clojure's sequences are not linked lists made out of cons cells
11:14ieurebeaky, Clojure takes some inspiration from Scheme, which uses first/rest rather than car/cdr.
11:14noidiso car/cdr could lead old lisp programmers astray in thinking that
11:14tcrayfordantares_: I haven't signed one as well, for similar reasons. I've been to relevance events and not signed purposefully.
11:14beakyso the default clojure sequence is something from java?
11:15tcrayfordno
11:15ieureWell.
11:15ieureMuch of Clojure is implemented in Java, or at least has Java interfaces.
11:15noidibeaky, http://clojure.org/sequences
11:15beakyI am only familiar with C++ :D
11:15ieureSo clojure.lang.ISeq is the underlying type.
11:15beakyah thanks
11:16antares_beaky: please read a guide on sequences at http://clojure-doc.org, they are not implemented as cons cells and yes, they are implemented in Java. But most importantly they are immutable.
11:17antares_beaky: a slightly more approachable version http://clojure-doc.org/articles/language/collections_and_sequences.html
11:17beakyah, so clojure sequences are much like haskell's []
11:18beakybut more general
11:18tcrayfordwell, haskell
11:18lucianbeaky: or less general, depending how you look at it
11:18tcrayford's [] is implemented as cons cells iirc
11:18lucianbeaky: certainly more explicit
11:18beakyah
11:18beakythat's awesome
11:19beakyI like the idea of having a uniform interface for sequences
11:19maioI would like to serve result of write function from https://github.com/jkk/purty/blob/master/src/jkkramer/purty.clj as HTTP response. Any idea how to do that? It expects something that works with clojure.java.io/file
11:19beakye.g. in C++, the containers are unified under iterators
11:19beaky(but C++ containers are mutable by default) :(
11:19tcrayfordbeaky: haskell has uniform interfaces for sequences (see Traversable/etc). They're just not commonly used
11:21beakyhmm why not? :(
11:21beakymaybe the haskell crowd prefers pointfree or something else I guess
11:22tcrayfordfor one thing they're kinda complicated interfaces, and they're not exported by the Prelude. First/Rest is a much better design (imo)
11:22beakyah
11:23beakyseq is simple yet powerful :D
11:29tomojTraversable > Seq
11:29beakyis there a nice repl with autocomplete for clojure?
11:30vijaykiranbeaky: nrepl has autocomplete
11:30cmajor7answering my own question (serving protobuf from Compojure). no need to extend "Renderable", just wrap it into ByteArrayInputStream.
11:31nDuffbeaky: I'm very happy with emacs' nrepl.el
11:31cmajor7beaky: "lein repl"
11:31beakyah
11:32beakylein repl works :D
11:32beakyI think ill try nrepl
11:32beakyim a vim user... how long will it take me to ge tused to emacs? :D
11:34technomancydon't learn emacs and clojure at the same time
11:34antares_beaky: why not use Vim Fireplace?
11:35antares_beaky: http://clojure-doc.org/articles/tutorials/vim_fireplace.html
11:35TimMcIs clojure-jack-in still a thing?
11:35beakyah thans
11:35TimMcI installed clojure-mode from Marmalade, but that command is missing.
11:36tcrayfordbeaky: vim is fine with clojure. Not as fluid as emacs, but fine. Fireplace has some weird redrawing bugs on my system, but nothing super bad
11:37beaky:D
11:37blrmbeaky: vim fireplace is nice. I did wind up switching to emacs just for clojure, and it wasn't so bad. But yeah, learning clojure and a new editor at the same time is not going to be fun
11:37rbxbxtcrayford: beaky fwiw I've found vim/fireplace better in some regards than nrepl.el (if you'll pardon the heresy)
11:37beakyI always thought of emacs as the ultimate lisp ide
11:37kliphI seem to remember stumbling upon a MIT Scratch/Berkeley BYOB visual block-based programming implementation in Clojure, but now I can't find it. Am I off my rocker or can anyone point me in the right direction?
11:39tcrayfordrbxbx: it also has the bit in the readme about tim TPing your house
11:40blrmbeaky: you might check out emacs live if you decide you want to learn emacs. that helped me to get started with emacs+clojure: https://github.com/overtone/emacs-live
12:06beakyif clojure is not object-oriented at all, how does it do interop with java?
12:06beaky(which is pretty religious about OOP) :D
12:07danlarkinclojure lets you invoke methods on objects
12:07beakyah
12:07danlarkinand do other stuff too, like implement interfaces and inherit from classes, but that's generally not necessary
12:08mikerodI'm looking at the source for `reify` and I see that it is a macro. It uses a function `reify*`. Where is `reify*` defined at? I can't seem to find it.
12:09mikerodIn the clojure source that is.
12:09llasrammikerod: It's a special form, directly recognized by the compiler
12:09nDuffmikerod: clojure/lang/Compiler.java
12:10mikerodAh, ok. I didn't realize this. Thank you.
12:11joegallolo, in the beginning there were the special forms, and the special forms were with clojure, and the specials forms were clojure.
12:12mikerod:)
12:12antares_mikerod: special forms are listed on http://clojure-doc.org/articles/language/macros.html#special_forms :)
12:15mikerodantares_: Oh, I have not came across this one before. That's a great reference, thanks.
12:29jcromartieso here's a weird question
12:29jcromartiewhat's should I name a ref that holds the state of the data model
12:29jcromartiein a local scope
12:30jcromartie"ref" is already core/ref
12:30jcromartie"model" sounds more like a value
12:30jcromartiesame with "state"
12:31antares_jcromartie: state is fine (and pretty common). You can also use ref'.
12:31jcromartiebut then I use "state" to name the current value in the function arguments to alter, send, etc.
12:33jcromartieand Clojure calls the current value of an identity/ref "state"
12:33bbloomjcromartie: i've run into that naming conundrum before... where you have like the-state and a-state
12:33beakyhow does clojure achieve encapsulation without OOP?
12:33Ember-via several means but also encapsulation isn't as important as with OOP
12:33jcromartiebeaky: closures, records, datatypes
12:34jcromartiebeaky: you shouldn't worry about hiding things, but you should try to abstract things
12:34Ember-if you have no mutable state then a large part of why encapsulation is so crucial with OOP goes out of the window
12:34beakyah
12:35bbloomjcromartie: i've more or less just decided it's ok to shadow the ref's name
12:37bbloomjcromartie: (defmacro swapping! [name & body] `(swap! ~name (fn [~name] ~@body)))
12:37bbloomi've never actually used that, but it conveys a pattern :-P
12:37jcromartienice
12:37beakyso in clojure, all the OOP fluff is simply unnecessary? :D
12:37bbloombeaky: no one said that
12:37beakyah
12:38bbloombeaky: OOP is a deeply understood and well studied bag of tools
12:38bbloombeaky: clojure just embodies the opinion that OOP is the wrong default
12:41ToBeReplacedanyone have any tools for edn-based rpc they like?
12:41beakyit's not the default because it ties together a bunch of stuff in an unnatural way?
12:41technomancyToBeReplaced: sure: https://github.com/technomancy/die-roboter
12:41bbloombeaky: great talk by stuartsierra on thinking in data instead of objects: http://www.infoq.com/presentations/Thinking-in-Data
12:41beakyah thanks
12:43jcromartiebut at some point you might need something object-like (i.e. an identity that changes)
12:43jcromartiefor instance a cache of values that is updated in the background
12:43bbloomjcromartie: objects are useful even without identities sometimes
12:45bbloomjcromartie: like take a look at clojure/zip.clj, which rich wrote in the early days of clojure
12:45jcromartiebbloom: what would that be? isn't it just data at that point?
12:45jcromartieah
12:45bbloomjcromartie: it stores functions in the metadata of a vector....
12:45bbloomjcromartie: it would probably have been much better as a protocol & a reify
12:46bbloom(but i don't think those existed at the time)
12:46jcromartienope
12:46bbloomobjects are great when you have "co-data"... aka data that isn't printable/readable/immutable/acyclic/etc
12:46bbloomsee also seqs
12:47bbloomthey use objects to represent infinite data, not identities
12:49ToBeReplacedtechnomancy: cool, but not what i'm looking for; i'm looking for libraries to handle the equivalent of the json-rpc spec with edn
12:49technomancyToBeReplaced: hm. never used json-rpc, but if there are no libraries for it, it could be because it's just a trivial compojure handler
12:51ToBeReplacedyeah it's pretty straight forward / easy to roll -- you want the same kind of thing for client too
12:51beaky(alter-var-root #'*read-eval* (constantly false)) ;; What does this line do? It was generated by lein and it says it somehow prevents some kind of dangerous behavior
12:56no7hingit prevents the clojure reader from evaluating forms that were e.g. loaded via slurp
12:57antares_beaky: disables evaluation of arbitrary code by the reader (clojure.core/read-string, etc)
12:57antares_beaky: if you use Clojure 1.5.1, it is the default so that line can be removed
13:02andyfingerhutbeaky: antares_: *read-eval* still defaults to true in Clojure 1.5.1
13:03antares_andyfingerhut: oh
13:03beakyah
13:03andyfingerhutClojure 1.5.1 added the clojure.edn/read and read-string functions, that behave much like clojure.core/read and read-string, except have no ability to execute code as a side effect.
13:04andyfingerhuttools.reader contrib library also provides similar capability for edn reading with no side effects, and works with Clojure 1.3 and later.
13:04andyfingerhutclojure.core/read has its uses as it is still, but primarily when you want to pass around executable Clojure code as text.
13:16technomancybeaky: it was meant to be a workaround for the problem that read and read-string were unsafe on user-provided data, but they changed the tune and said that they now aren't intended for user data anyway
13:17technomancywhich IMO is unhelpful because they are still going to be used for it anyway, but that ship has sailed
13:22sritchiecemerick, any advice on how to get clj-http to provide a proper csrf header in a post request?
13:30mynomotoHow do I require a project namespace in a lein plugin?
13:31technomancymynomoto: eval-in-project
13:31technomancythat is, leiningen.core.eval/eval-in-project
13:31mynomototechnomancy: I tried that, but not sure how to use it. Do you have an example?
13:33technomancymynomoto: sure; see the source for the "check" task in leniingen
13:33mynomotoOk, thanks.
13:34technomancybasically it's like eval except it takes a project argument first
13:34technomancyproject map
13:37cemericksritchie: you mean something like X-Requested-With?
13:37sritchiecemerick: figured it out -- I just needed to use the :cookie-store option
13:37cemerickah
13:38cemericksritchie: yeah, X-Request-With isn't right, anyway.
13:39silasdavishow should I convert ':foo' to 'foo'?
13:39llasramDo you want ##(name :foo) ?
13:39lazybot⇒ "foo"
13:40silasdavisthanks
13:43Glenjaminwhen the 'check' task warns about reflection, what is it actually warning about?
13:45technomancy...is this a trick question?
13:55beakydoes a dynamically-typed programming language need polymorphism?
13:56technomancybeaky: you need polymorphism for clojure's built-in types. genuine need for polymorphism for user-defined types is fairly rare.
13:57technomancyit's completely orthogonal to the static/dynamic divide though
13:57beakyah
13:58patchworkTrying to wean myself off swank for nrepl
13:59patchworkCan you embed nrepl inside a running process?
13:59beakywhat are clojure's builtins? I guess it has strings, symbols, singly-linked lists, vectors, hashmaps, and sets?
13:59technomancypatchwork: yeah, it's in the nrepl readme
14:00patchworktechnomancy: I read through it, I just see it being able to start from the command line or from within emacs, but nothing about starting it from inside my app then connecting to it
14:01technomancypatchwork: are you sure you have the right readme?
14:01patchworkThat is the main draw for swank, I can start it up inside my app then control my running app process from emacs
14:01patchworkhttps://github.com/kingtim/nrepl.el ?
14:01technomancyhttps://github.com/clojure/tools.nrepl
14:01technomancyyou're reading the client's readme, not the server
14:01patchworktechnomancy: Aha, thanks!
14:01technomancysure
14:03jcromartieI really need to get out of this one-big-ref thing
14:03jcromartieI have one ref for the configuration of the app
14:03patchworkjcromartie: I just went through that
14:04jcromartiebut then the runtime data should have its own references
14:04jcromartieatoms, agents, whatever
14:04jcromartieI have an API that is used by a JS front-end for making changes to the config.
14:04patchworkI think it is better to have a dynamic var actually, then you can rebind it at will, but not affect other processes
14:04patchworkyou bind it when the app boots
14:04jcromartieI think I might just do that
14:04jcromartiebecause I don't realyl need to create instances of the system
14:05jcromartieI went down this route thinking it was cool
14:05patchworkI ran into trouble with the ref because all threads saw the same thing!
14:05patchworkIt is helpful if that is what you want
14:05beakycan you program in an imperative style in clojure? (like in scala)
14:05patchworkbut for config I needed to change some options
14:05jcromartiebeaky: sure why not?
14:05patchworkbeaky: If you insist!
14:05patchwork(do (op! …) (op! …) ...)
14:06beakyah :D
14:06jcromartiepatchwork: someone gave me the idea of having a function that creates a "system" ref that can be held in the REPL or whatever and then pass that to functions that create compojure handlers etc
14:06jcromartiebut it would just be simpler to have a var
14:06patchworkjcromartie: I found the var to be more flexible for config specifically
14:07jcromartieand you can add watches to save it etc
14:07patchworkbut I'm sure others have other opinions!
14:07jcromartieI dunno
14:07jcromartieI'd just have a ref in a var
14:07jcromartieI have a good system in place for persistence
14:07patchworkDo you know about the #'var-name idiom?
14:07jcromartieyes
14:08patchworkit returns a reference to the var, not the value
14:08patchworkvery useful
14:08jcromartieit just returns the var itself
14:09patchworkYeah. I avoid dynamic vars everywhere (it couples code too heavily and fns can't be reused elsewhere), but config needs user specified values somehow
14:12Glenjaminis there a quick way to grab the first non-empty string in a sequence?
14:12tcrayford(first (filter empty? seq))
14:12tcrayfordoh
14:12tcrayfordnon empty
14:12patchworkGlenjamin: (first (filter identity seq))
14:13patchworkOr more clearly (first (remove empty? seq))
14:13tcrayford,(first (filter (complement empty?) ["a" ""])
14:13clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
14:13patchworkremove/filter are lazy so it will only calculate up to the first non-empty string
14:13tcrayford,(first (filter (complement empty?) ["a" ""]))
14:13clojurebot"a"
14:14kawpatchwork: Isn't "" trueish?
14:14Glenjaminpresumably that identity one doesn't work, or i could just use (or)
14:14tcrayfordyeah, identity doesn't work
14:14tcrayfordfilter is fine because of laziness though
14:14patchworkAh, yeah I was thinking nil, not ""
14:15tieTYT2http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class
14:15Glenjaminit's a shame clojure doesn't have a haskell style function composition operator
14:15tcrayfordcomp is ok
14:15tcrayfordclojure doesn't have operators!
14:16Glenjaminhah, true
14:16Glenjaminreader macro then :p
14:16tcrayfordlike arc?
14:16tcrayford(a:b thing)
14:16Glenjaminthat could work
14:18bbloomblargh. just what i need. yet another thing that breaks * and # in vim
14:18Glenjamin,((comp first remove) empty? ["" "a"])
14:18clojurebot"a"
14:18Glenjaminvs
14:18Glenjamin,(first (remove empty? ["" "a"]))
14:18clojurebot"a"
14:19Glenjaminor i guess (-> ["" "a"] (remove empty?) first)
14:19Glenjamin,(-> ["" "a"] (remove empty?) first)
14:19clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.core$empty_QMARK_>
14:19Glenjaminbah, ->>
14:19Glenjaminanyway, it all seems to be roughly the same size-wise
14:26gfrederickswoah that money library has functions called `plus` and `minus` o_O
14:27antares_gfredericks: yes, what about it?
14:28antares_we used the same names as Joda Money. Also, asking people to :refer-clojure :except [+ -] is a bit too much
14:29gfredericksantares_: I'd rather do :as m with m/+ and m/-
14:30antares_gfredericks: then our + would be non-variadic
14:30Raynesantares_: Please, please expect that people are going to :require :as your libraries.
14:30antares_at least if we change the signature
14:30antares_Raynes: I am not recommending :use or :refer :all
14:31RaynesI'd so much rather have then called + and - and have to qualify them.
14:31Raynesthem*
14:31tcrayford(money/+ a b) reads worse than (money/plus a b) to me
14:32antares_I followed joda money names, it doesn't matter to me if it is + or plus
14:32RaynesI mean, it isn't a huge deal, but clj-time is super inconsistent because it's horrified of shadowing clojure.core names.
14:32antares_plus does not behave like clojure.core/+ if you take a close look
14:32antares_it is not variadic, it can accept Java objects or doubles
14:32llasramI'd like it to be `+` please (Unicode "PLUS SIGN" character)
14:33RaynesShadowing doesn't imply behaving the same.
14:33antares_Raynes: may also be because it is really old and has dozens of functions in a single namespace
14:33trinaryuse the emoji fat plus
14:33gfrederickstcrayford: because of the '/' and the '+' next to each other?
14:33antares_trinary: ha
14:33Raynesplus and minus are perfectly acceptable in any case.
14:33tcrayfordgfredricks: yep
14:33tcrayfordalso
14:33tcrayforddoes money// even work?
14:33tcrayfordfor division?
14:34antares_good point, amounts// would at least look terrible
14:34antares_tcrayford: it should
14:34Raynes&(clojure.core// 10 2)
14:34lazybot⇒ 5
14:34tcrayfordthere's something new about clojure's syntax
14:34tcrayford(to me)
14:34gfredericksis that // bug fixed?
14:34antares_lets call division // to confuse people!
14:35antares_I still roll my eyes when I have to use =:= and =/= in Erlang
14:36RaynesI roll my eyes when I have to use ports in Erlang.
14:37gfredericksin any case, I think most would agree that the idiomatic clojure practice is to give things the most straightforward name and use namespaces to distinguish
14:38gfredericksthen the user can decide if they want naked symbols to refer to the core version or the library version or whatever
14:38RaynesWe should put it in that monstrous style guide!
14:38antares_gfredericks: I thought the most idiomatic is to be all anal about consistency?
14:39gfredericksantares_: I'm not sure what you mean by that
14:39RaynesYeah, that's a horrible thing to be.
14:39antares_when a minor difference in behavior with clojure.core/+ means you have to pick a different name :)
14:39gfredericksoh I see
14:39RaynesAfter you've used clj-time for more than five seconds and ended up in secs seconds second minutes mins minute hell...
14:40gfredericksno, I agree with raynes that using the same name doesn't imply any particular similarity; also is there some reason it can't be variadic?
14:40RaynesFWIW, I'm totally fine with plus and minus.
14:40RaynesI was just making a case for not avoiding shadowing in other scenarios.
14:41antares_Raynes: I think clj-time is a case where the domain is very nuanced, less so with money. There are "hours" and "hours of day", for example, the former is a period of time
14:41Raynesantares_: Not what I mean though.
14:41Raynesantares_: IIRC, there is at least one case where it names something 'sec' instead of 'second' because of clojure.core/second, while the minute analogue is called 'minute'.
14:41RaynesThat is *horrifying*.
14:42RaynesAnd I've nearly broken things over it in the past. :P
14:42antares_Raynes: maybe I focused to much on seconds vs second vs secs :)
14:42callenwhy isn't it days/hours/minutes/seconds
14:42gtrak&min
14:42lazybot⇒ #<core$min clojure.core$min@11cdd43>
14:42antares_Raynes: please file an issue, I think seancorfield would consider changing that to "second"
14:43RaynesI doubt it. It'd be a breaking change.
14:43antares_I doubt clojure.core/second gets much use
14:43gfredericksI use it all the time
14:43gfredericksbut the shadowing wouldn't bother me, obviously
14:43antares_callen: there are functions that return a period of N seconds and # of seconds on a date/time
14:43antares_Raynes: it's OK to have a breaking change once in a few years
14:43antares_I'm going to break a few key functions in Welle tomorrow :)
14:44Raynesantares_: So, you do some Erlang?
14:44antares_because it's the right thing to do
14:44antares_gfredericks: fortunately, it's not Ruby, people will get a warning
14:44gtrakmake a new lib called clj-time+ or clj-time-plus
14:44gfredericksantares_: oh sure
14:44antares_Raynes: yes, mostly on and around RabbitMQ. Also have an Elixir library :)
14:44VFethe real question I have, is how do I actually use emoji in clojure?! (defn 🍉 [🐉 🐪 💀](+ (* 🐪 🐉) 💀))
14:44antares_gtrak: noooooo
14:44Raynesantares_: https://www.refheap.com/paste/13920 I'll pay you $10 to send Erlang a patch for this.
14:45RaynesOf course I'm pretty sure that involves C.
14:45antares_VFe: like so twitter.com/michaelklishin/status/270072723751960576? ;)
14:45antares_Raynes: I don't hack on OTP, I use Erlang
14:45Raynesantares_: But you should.
14:46gfredericksusing words for numeric operations bothered the hell out of me every time I wanted to do alternative arithmetic in java or JS; clojure allows that to be much nicer in my opinion
14:46gfredericksbut I don't mind being a minority on that. I can always creating locals for + - * / etc :)
14:46antares_Raynes: right after clojurewerkz passes 100 projects, I promise
14:46gfredericks(defmacro with-money-math ...)
14:46technomancygfredericks: CL's use of -p for predicates drives me nuts for the same reason
14:46VFeantares_: this changes everything
14:47gfrederickstechnomancy: it's a required thing?
14:47technomancygfredericks: no, a cultural thing
14:47Raynesantares_: I'll hold you to it.
14:47technomancygfredericks: well, it might be required in CL; not sure if the standard allows for ?
14:47tcrayfordI really wish haskell allowed ? as part of a variable name :/
14:47Raynes'variable'
14:48technomancyI bet all widely-used implementations do, and elisp certainly does
14:48RaynesEVIL ONE
14:48antares_Raynes: I know you are serious business
14:48gfrederickstechnomancy: oh right question marks
14:48tcrayfordRaynes: im troll
14:48Apage43it's pretty hairy though
14:48RaynesApage43: You can have my $10 as well.
14:48RaynesIt's bounty.
14:48RaynesI'll even tack on $1 for pain and suffering for having to use C. ;)
14:49technomancyhazard pay
14:49antares_do C programmers get to retire earlier, too?
14:49mynomotoI'm still trying to use eval-in-project for a lein plugin. I got this code https://www.refheap.com/paste/13938
14:50SegFaultAXApage43: Y u no nif?
14:50Apage43SegFaultAX: I've done NIFs too
14:50mynomotoAnd this error: Exception in thread "main" java.lang.ClassNotFoundException: squiggle.core, compiling:(NO_SOURCE_PATH:1:37)
14:50Apage43I've built the VM for Android and iOS before and that required getting into the guts though
14:50technomancymynomoto: it's best to use fully-qualified var names for referring to things not in core
14:50SegFaultAXApage43: Then I /really/ feel your pain.
14:50technomancyat least for starters
14:50Apage43also had to debug the VM on numerous occasions
14:51SegFaultAXApage43: Eheh, Erlang on Android. Wut?
14:51Apage43*and* iphone
14:51Apage43it was for a product that packaged CouchDB
14:51SegFaultAXApage43: But.. why?
14:51SegFaultAXAh.
14:51mynomototechnomancy: my bad. Will do.
14:51SegFaultAXStill, pleasae no.
14:52technomancymynomoto: but it sounds like the init form might be the culprit here
14:52technomancyconfirm it's on the classpath, etc
14:52cemerickdnolen: any ideas re: a StackOverflow compiling a match form in one environment, not another (on the same commit in the same project)?
14:52Apage43indeed, it was a silly idea, and we've luckily scrapped it in favor of just writing a CouchDB-compatible lightweight db for that stuff
14:52RaynesI'd do the port stuff myself, but goodness, I value my life more than that.
14:52Apage43compatible meaning it syncs with it, not necessarily exposes the same API
14:53dnolencemerick: hmm not really
14:55SegFaultAXApage43: Why would you want such a thing to begin with?
14:55mynomototechnomancy: I'm running the plugin in that project folder. It should be in the classpath right?
14:55cemerickyeah, figured it'd be a longshot
14:56Apage43SegFaultAX: sync. CouchDB replication is really nice for that.
14:56technomancymynomoto: maybe print out (leiningen.core.classpath/get-classpath project) before calling eval-in-project so you can verify?
14:56dnolencemerick: feel free to open a ticket w/ stack trace, it might be obvious or it might not.
14:57dnolencemerick: does heroku AOT?
14:57SegFaultAXApage43: But couch on a mobile device? Ugh. It doesn't seem like you have the CPU nor the memory to do anything more than the most trivial work.
14:57Apage43that is: work offline for a bit, edit your local db, then connect up for a short time and sync it with some remote db.
14:57cemerickdnolen: good question, I don't recall....(goes to look)
14:58Apage43SegFaultAX: that's why it was silly. The new thing is a much less silly, being a layer over SQLite that implements some of the couchdb functionality.
14:58ppppaultry-let sounds sexy
14:58ppppaulgist gist gist!
14:59Raynesrefheap refheap refheap!
14:59cemerickdnolen: heh, yeah, it does :-P
14:59SegFaultAXApage43: We built something like that at my last job (mobile games). But were actually storing transformations in the database which would be streamed to the server in blocks when they regained connectivity.
14:59owengalenjonesanyone using :creds :gpg ever see an EOF error when trying to pull lein deps from an archiva repository?
14:59SegFaultAXApage43: I'm curious, is your implementation open source?
15:00amalloygfredericks: try-let sounds like toilet
15:00gfredericksamalloy: phew!
15:00Apage43the new one isn't by me, but it's here https://github.com/couchbase/couchbase-lite-ios
15:00gfredericksamalloy: for several seconds I thought you were using "toilet" as a generic adjectivish thing to describe something you don't like
15:00gfredericksI can imagine tcrayford using the word that way
15:00amalloyhaha
15:01amalloythat name is *pants*, sir
15:01Apage43formerly called TouchDB
15:01dnolencemerick: that's probably the issue
15:01Apage43we had to slap branding on it
15:01SegFaultAXApage43: Neat! Thanks.
15:01dnolencemerick: there's a ticket for the AOT problem, would love some help on that one.
15:02ppppauli used to couchdb
15:02ppppaulbut not couchbase
15:02ppppaulthey are a bit different
15:03mynomototechnomancy: It's in the classpath.
15:06SegFaultAXIs it just me or does github /feel/ very different when you're not logged in?
15:07gideonitehi i have a noob ring question: i can't seem to get form parameters from a request.
15:07gideonitewhen (:form-params req) i get a map with strange keys
15:07gideonitewhich are not symbols
15:07gideonitesomething like (user foobar) instead of (:user foobar)
15:08gideoniteany advice?
15:08SegFaultAXgideonite: What middlewares are you using?
15:08weavejestergideonite: By default, parameters are strings
15:08gideoniteshould i being using wrap-params?
15:08weavejesterParameter keys, I mean, because a parameter name doesn't necessarily conform to what is allowed in a keyword
15:09weavejesterFor example, foo%20bar=baz translates to {"foo bar" "baz"}
15:09SegFaultAXgideonite: Are you using Compojure?
15:09weavejesterThe wrap-keyword-params middleware turns the parameter keys into keywords
15:09gideonitei'm actually using pedestal.io
15:10SegFaultAXDoes pedestal use Compojure?
15:10weavejesterBut wrap-keyword-params only applies to (:params req)
15:10weavejesterPedestal doesn't use Compojure
15:10SegFaultAXBummer.
15:10weavejester(:form-params req) will always have strings for keys
15:10SegFaultAXgideonite: https://github.com/weavejester/compojure/blob/master/src/compojure/handler.clj <- good example of some reasonable default middlewares.
15:11weavejesterPresumably gideonite wants to do a lot of async work, which pedestal is designed for
15:11gideoniteweavejester: right, but it does use ring. right now i'm just trying to set up something simple. ah, so i need to figure out how to get from a map where keys are string
15:11gideoniteweavejester: eventually, yes.
15:11weavejestergideonite: Try accessing (:params req)
15:12SegFaultAXIs it safe to assume that pedestal sets up the common middlewares for you by default?
15:13gideoniteweavejester: that does work. i now see that my question is really how to get from a map with strings as keys. that's already helpful
15:13weavejestergideonite: It's the same as getting from a map with keywords
15:13weavejestergideonite: Well, except that you can't use strings as functions
15:13SegFaultAXgideonite: Maps are functions of their keys.
15:14weavejestergideonite: So (params "foo") or (get params "foo")
15:14SegFaultAXgideonite: Keywords are functions, too. They try and get themselves from their argument.
15:14gfredericksdangit try-let is hard to write
15:15gideoniteboom -- obviously it's get. noob questions! thanks so much
15:15SegFaultAXgideonite: Or using the map itself in function position, ##({"foo" 1 "bar" 2} "foo")
15:15lazybot⇒ 1
15:15gideonitethere's also a function keyword fyi, if you're committed to having keywords
15:17gideoniteSegFaultAX: haha, that seems complicated
15:18SegFaultAXgideonite: Why?
15:18SegFaultAXgideonite: As I said, maps are functions of their keys. That turns out to be really useful.
15:19jcromartieI am OK with putting important runtime state in a var.
15:19jcromartiethere. I said it
15:19gfredericks"keys are functions of their maps" would be a fun terrible feature for a language
15:19gfredericksjcromartie: with alter-var-root? or with an atom?
15:20jcromartienot quite
15:20jcromartieI mean refs in vars
15:20jcromartieetc.
15:20gfredericksrefs in vars in atoms in agents in actors in scala
15:20jcromartieyes
15:20SegFaultAXgfredericks: That's concurrency done right.
15:20TimMcgfredericks: I look forward (with some trepidation) to ##(format "lib-%04d" (rand-int 1e4))
15:20lazybot⇒ "lib-3236"
15:20TimMc(regarding keys and maps)
15:21jcromartieI think that a core namespace is the right place to bolt down some important things in place and put all the important parts together.
15:21gfredericksTimMc: mutable numbers first
15:22gfredericksTimMc: I resisted that naming pattern recently
15:25[tab][tab][tab]Oh my god this is the best nick.
15:25SegFaultAX[tab][tab][tab]: Hah
15:26TimMc...and registered.
15:27gideoniteSegFaultAX: sorry, you are absolutely right. that's the best thing to do. i guess strings don't evaluate to themselves?
15:27gfredericksthey do
15:27gfredericks(eval "foo") => "foo"
15:28SegFaultAXgideonite: Strings always evaluate to themselves.
15:29TimMcStrings, keywords, vectors, maps, sets...
15:29amalloythey just aren't functions
15:29gideonitethen why can't i go ("foo" {"foo" "bar"})
15:29SegFaultAXgideonite: But they aren't functions. Keywords are and all they do is `get` themselves from their argument.
15:29amalloyTimMc: minus vectors, maps, and sets...
15:29TimMcamalloy: Eh?
15:29gideoniteSegFaultAX: got it
15:29amalloythe vector [x] clearly does not evaluate to [x]
15:29gfredericksbeing evaluated and being called are different
15:30gtrak&(eval 'x)
15:30lazybotjava.lang.SecurityException: You tripped the alarm! eval is bad!
15:30TimMcamalloy: Hmm... fair.
15:30gtrakCompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:1)
15:30SegFaultAXgideonite: I think most people like to use keywords as functions if the maps their dealing with have keyword keys.
15:31SegFaultAXgideonite: Eg (:foo {...}) vs. ({...} :foo)
15:31SegFaultAXDespite them being equivalent
15:31gtrakthe first will never give an NPE
15:31SegFaultAXgideonite: For all other types of keys, you pretty much have to use the map in function position.
15:31amalloymeh, i rarely use maps in function position. i usually just use get
15:31TimMc,('foo {'foo 4})
15:31clojurebot4
15:31TimMc^ almost never used
15:32SegFaultAXTimMc: Literally never used.
15:32clojurebotTimMc: There is a Clojure patch on CLJ-1168 that seems like it should allow Leiningen to work with 1.5.0 and :jvm-opts ["-Dclojure.read.eval=unknown"] http://dev.clojure.org/jira/browse/CLJ-1168
15:32TimMcThanks, bot. Thanks... for nothing.
15:32nzwhat is difference between with-redefs and binding? other than binding works only with vars that are marked ^:dynamic?
15:32SegFaultAXTimMc: But it is interesting that keywords are effectively just symbols.
15:32nz,(doc binding)
15:32clojurebot"([bindings & body]); binding => var-symbol init-expr Creates new bindings for the (already-existing) vars, with the supplied initial values, executes the exprs in an implicit do, then re-establishes the bindings that existed before. The new bindings are made in parallel (unlike let); all init-exprs are evaluated before the vars are bound to their new values."
15:32nz,(doc with-redefs)
15:32callensometimes I think the bot was coded to be unreliable/weird on purpose.
15:32clojurebot"([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 mockin...
15:33TimMcnz: The difference is that with-redefs is not thread-safe, alters the root, and should only be found in your test/ directory.
15:33gfrederickswoah java is getting "default methods" for interfaces
15:34TimMcoh what
15:34SegFaultAXgfredericks: Oh? How does that make them different from abstracts?
15:34gfredericksthey're on the interfaces instead of superclasses
15:34nzgfredericks: yep, it is so that List etc interfaces can work nicely with lambdas
15:35SegFaultAXSoo, Java is getting mixins via default interface methods?
15:35gideoniteSegFaultAX: so in some sense :a evaluates to #(get % :a). i agree, it's a very nice concept
15:35gfredericksI am sitting 15 feet in front of Brian Goetz describing this
15:35nzyou can add default implementation to interface. that impl is used if the implementing class doesn't implement the metod
15:36TimMcThe slow slide into multiple inheritance.
15:36SegFaultAXTimMc: That's what I was thinking.
15:36gfrederickshe said "java has always had multiple inheritance for types" and I'm not sure what that meant
15:36SegFaultAXTimMc: Very Ruby-esque.
15:36gfredericksis that what interfaces are?
15:36nzhttp://www.lambdafaq.org/do-default-methods-introduce-multiple-inheritance-to-java/
15:37SegFaultAXgfredericks: Maybe that classes can implement an infinite number of interfaces?
15:37tieTYT2can someone help me with this question? http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class
15:38SegFaultAXnz: Yup
15:38tieTYT2I think i'm asking a fundamental clojure question here, not something specific to gen-class
15:38nzlist.forEach(System.out::println)
15:39SegFaultAXnz: Although I never really would have called that multiple inheritance because it carries a slightly different connotation for me than simply implementing any number of interfaces.
15:39nzmultiple inheritance of behavior
15:40SegFaultAXnz: That's what I usually associate with MI, the behavior part. But it's easy to adjust that mental model to include types.
15:41SegFaultAXStill, default methods means that Java can now properly implement the mixin pattern. I guess that's ok?
15:44tieTYT2why does this return nil? (macroexpand-1 '(gen-class
15:44tieTYT2 :name com.sandbox.GeneratedClass
15:44tieTYT2 :methods [[hello [] String]]))
15:44gfredericksI think gen-class always expands to nil
15:45nDuff*nod*.
15:45tieTYT2how's that possible?
15:45gfredericksit's a side-effecting macro
15:45tieTYT2oh so I can't see what it's doing?
15:45gfredericksyou can read the implementation
15:45nDufftieTYT: It doesn't do anything at all except during ahead-of-time compilation.
15:45gfredericksthe 7th rule of macro club is don't write side-effecting macros
15:45tieTYT2oh right
15:45tieTYT2ok well I really am stuck with this then
15:46tieTYT2http://stackoverflow.com/questions/16199258/how-can-i-pass-in-the-list-of-methods-to-gen-class
15:46amalloytieTYT2: that is not a thing it is possible to do
15:46amalloynor would it be terribly useful if you could
15:46gfredericksand java's getting this streaming interface
15:46tieTYT2amalloy: ok thanks, at least now I know that.
15:47SegFaultAXWow, gen-class is exceedingly complicated.
15:47jcromartieoh snap
15:47jcromartiecyclical dependency
15:47tieTYT2amalloy: the reason I want to do that is because I want to make a function you use like this: (GET "url" [url] some-body) that will generate a jersey class
15:47tieTYT2but I want each of those function calls to add a method to the gen-class
15:48tieTYT2and I can't figure out how to do that a method at a time
15:48TimMcjcromartie: Having everything in core?
15:49TimMc*too much
15:49jcromartiehad something important in a web.core, that was used by web.core.routes.foo
15:49jcromartieand vice versa
15:53gfredericksI think java just invented reducers?
15:53jcromartiefoo.bar.baz should not use vars in foo.bar, as a general principal
15:55beakyare there progrmaming languages that are better than clojure?
15:55ppppaulno
15:56ppppaulclojure is best
15:56SegFaultAXbeaky: Better than Clojure /for what/?
15:56ppppauleven for micro computing
15:56AimHerebeaky > INTERCAL is better than clojure.
15:56ppppaulor, micro-codeing
15:56beakyah
15:56gfredericksyes: it has been proven that either J or Dart is better than Clojure, but also that it is impossible to determine which one
15:56gfredericksthis has been called the "J-Dart Indeterminacy Problem"
15:56ppppaulJ <3
15:57ivanif clojure doesn't do what you want, just write a sufficiently smart clojurescript emitter
15:57beakyhmm I should look into J
15:57SegFaultAXppppaul: Have you seen Conway's GoL in APL?
15:57ppppauli have
15:57ppppauli was impressed
15:58callenbeaky: fortran is way better than clojure
15:58SegFaultAXSuch an excellent video: http://www.youtube.com/watch?v=a9xAKttWgP4
15:58beakybut fortran isn't as general-purpose as clojure afaik
15:58Chousukewith a sufficiently smart compiler, (can-have? 'pony) returns true and a pony will be delivered shortly
15:59beakyit's just a dinosaur language for dinosaur numerical computing libs that have over 6 decades of optimization
15:59amalloyChousuke: i would expect more like a piece of paper with the word pony to arrive
15:59amalloy(can-have? pony) might give you an actual pony
15:59Chousukethat may be
15:59Chousukeor maybe the compiler is feeling generous and gives you a pony sticker instead
15:59ppppauli want pony
16:00AimHereI think if something has 60 years of optimization, then it's going to be pretty damn optimized, and quite likely to be the best at what it does. Therefore Fortran is Best Language
16:00AimHereQED
16:00patchworkI do all my computations on abacus
16:00ppppaulabacus is best language
16:00gfredericksthe first language to be invented is necessarily the best
16:00callenAimHere: Fortran used to have a performance advantage on C due to design that has since been overcome with vectorization and compiler flags.
16:01callenAimHere: advantages that weren't entirely due to "time", keeping in mind that C has had quite a lot of industry dollars dumped into it.
16:01SegFaultAXAimHere: Also, quite a lot of math library code is still written in Fortran even today.
16:01beakyah
16:02TimMcEnglish is a pretty nifty programming language. Very expressive. However, a sufficiently powerful runtime can be quite expensive.
16:02callenTimMc: I hear grad students make good interpreters.
16:03callenbeaky: is somebody commissioning you to ask questions for a dictionary with definitions composed entirely of IRC logs?
16:03AimHereEnglish is just Cobol++
16:03Apage43English interpreters tend to be pretty slow, comparatively.
16:04Apage43You can sometimes get one to translate your English to something more computer usable though :)
16:06TimMcEnglish is very prone to non-deterministic bugs. For instance, if you issue the same command multiple times, it is likely to stop working.
16:06gunsDoes lazy-seq guarantee safe concurrent access to the next value?
16:06beakyI guess all programming languages have a raison d'etre; hence there is no best one
16:06TimMcThe result is that the more you test a program, the less likely it is to work!
16:06gunsI found what I thought was an unsynchronized mutation in a deftype on (next)
16:07Chousukeenglish is not a very good programming language
16:07gunsbut the object was wrapped in a lazy-seq and survived hammering from 1000 threads!
16:07Chousukecompilation takes months or years, might not terminate, and the end result might or might not correspond to what you mean
16:07gunssorry for interleaving the conversation.
16:08TimMcguns: You're not the one who should be apologizing. :-P
16:08TimMcIs the code somewhere where we can see it?
16:08gunsTimMc: If you're interested, I could gist it
16:09Raynes&(interleave '[Chousuke TimMc] '[guns Raynes])
16:09lazybot⇒ (Chousuke guns TimMc Raynes)
16:09RaynesSorry for interleaving guys!
16:10ChousukeYou made me gun TimMc, Raynes
16:10Chousukethat is not nice
16:10RaynesNice.
16:12tbaldridgeguns: yes it does: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LazySeq.java
16:12tbaldridgenotice how sval and seq anre synchronized, thus only one thread can be running those methods on the same object at a time.
16:12gunstbaldridge: I took a look at that file, but didn't immediately see an answer to my inquiry
16:13gunsI guess I should have read closer
16:13tbaldridgeguns: yeah it's a nasty bit of code.
16:13gunstbaldridge: Ah, I see it now. Brilliant
16:14tbaldridgethat's actually the cool thing about Seqs as opposed to interators or .NET's IEnumerable. running over the same seq 100 times will only actually calculate the seq once.
16:15gunsI was using a Random and BitSet in my deftype; I thought I would have to lock and clone, but lazy-seq took care of all the details
16:16tieTYT2amalloy: i don't understand why you're saying that would not be very useful
16:19tieTYT2I'm getting the sense clojure is a bad language to build a java-code generator
16:19Apage43i once used clojure to generate C. I wish I could stop remembering.
16:20Rayness/clojure/any language/
16:24tieTYT2I'm trying to write a clojure DSL to generate Jersey code, but it doesn't seem possible to me since gen-class won't let you pass in a dynamic list of method names
16:26TimMcMacros to the "rescue"...
16:26tieTYT2a macro that generates a gen-class ?
16:27tieTYT2I didn't know that was an option
16:27raek*sigh* why is the syntax highlighting suddenly gone for me in clojure-mode...
16:29Raynesraek: Holy shit. I haven't seen you speak in like a year.
16:29RaynesHow are you? Besides your emacs being broken?
16:33andrew__this might be a ridiculous question, but what is the difference in terms of java interop between using . and /? for example, I sometimes see ServerSocketChannel/open but on the next line I'll see (InetSocketAddress. "localhost" 5000)
16:33raekRaynes: things are good...
16:34andrew__are only certain things able to use the / for interop, whereas others must use the . ?
16:34raekhave been playing with Haskell for some time (and I also have a job nowadays)
16:35dnolenandrew__: / for static methods
16:35raekandrew__: (Foo/bar) means bar method of Foo class, but (Foo.) means Foo constructor
16:35andrew__much appreciated dnolen and raek
16:41iamdrwgreetings. is there a profiler for clojure? because profiling via time makes me go mad
16:42tcrayfordiamdrw: all the jvm profilers work
16:42tcrayfordso jvisualvm works (and you prolly already have it installed), yourkit is free if you're open source and mention it on your page, and much better than jvisualvm
16:43nightfly__profiling results might be dissapointingly vague if using higher-order functions though
16:43amalloytechnomancy: how do i force refetching of snapshot dependencies?
16:44technomancyamalloy: lein -U deps
16:44TimMciamdrw: If you just want benchmarking of different algorithms, criterium is excellent.
16:44amalloythanks
16:45iamdrwcriterium seems what I was looking for. Thanx
16:47amalloycriterium is great if you want to know how long a particular thing takes; yourkit is more work, but is better if you want to know what is taking so long
16:47tcrayfordthey do different jobs for you ;)
16:49weavejesterHmmm… there might be a bug in core.memoize… either that or I'm misreading this stacktrace
16:49amalloyweavejester: core.memoize and core.cache both do a big pile of reflection for no particular reason. i'd consider that a bug, in libraries designed to improve performance
16:51weavejesterI get this interesting stacktrace, which looks like a race condition: https://gist.github.com/weavejester/60a0a0bf334af85ffdfe
16:53amalloy,@nil
16:53clojurebot#<NullPointerException java.lang.NullPointerException>
16:53amalloyfunny that it thinks that's a Future, but whatever
16:54weavejesterI think that's the last type of deref it tries...
16:54hiredmanbecause deref now works on non-clojure created java futures
16:54hiredmanyet another hand rolled protocol
16:55cemerickdnolen_: yeah, it was AOT. I'll see if I can track it down. Hopefully I can be 1/3 with core.match issues. :-P
16:55dnolen_cemerick: :)
16:57weavejesterIt would seem to imply that (swap! cache through* f args) is returning nil for some reason
16:58weavejesterWhich implies clojure.core.cache/through is...
16:58weavejesterI'm not seeing how that's possible, however...
16:59dnolen_iamdrw: I recommend YourKit, criterium appears nice for only high level benchmarking
16:59dnolen_er profiling
16:59amalloyweavejester: of course it's possible: cache is a protocol, and you can implement it so that every function returns nil
17:00weavejesteramalloy: Yeah, but all the functions in the TTLCache seem to return not-nil
17:03mikerodWhen someone was learning Clojure the other day, they posted the question "so what's the "right" thing to do other than the giant, procedural let block?" I didn't have a good answer or a good reference. However, I feel there is much more to programming in Clojure than a "big procedural let block." Hmm.
17:04mikerodI've been puzzling over what to say to this.
17:04bbloomdepends on the problem at hand
17:04bbloombut generally the answer is more functions....
17:05mikerodYeah, I think it was a question directed at what does the functional paradigm offer over the "big procedural let block" perhaps.
17:05mikerodMore functions is appropriate I'd say. :P
17:05bbloomit's very common to see a (-> pipeline of step functions like this) where you thread a {:map "of" :keys "like" :this "through"}
17:05technomancywhat does being in a let block have to do with being procedural?
17:06bbloomtechnomancy: i assume he means that he is shadowing names for each incremental "change"
17:06mikerodI don't think of them as coupled.
17:06technomancybbloom: hm; that's a strange use of the word procedural
17:07bbloomtechnomancy: i agree, but i've seen quite a few people new to functional programming use single static assignment in a way that feels like a throwback to some C code
17:07mikerodI agree it was an open ended question and over generalized. I think bbloom had the right description with "shadowing names for each incremental change".
17:07technomancyI don't think there's anything wrong with shadowing names for each change if it's a case where -> is not suitable for argument order reasons
17:08technomancythat pattern alone does not make code procedural
17:08bbloomi agree with technomancy, but i'll add that after a small handful of let bindings & your function gets too big, it is a code smell
17:09technomancyright; but function size is orthogonal to let-rebinding
17:09technomancywell, they may be correlated, I guess
17:09pjstadigcorrelation is orthogonal!
17:09bbloomtechnomancy: forgive me for jumping to conclusions, but mikerod seems to have suggested that i read his & his colleagues' minds... :-)
17:10mikerodSo more functions obviously gives you more abstraction, modularity, reuse, comprehensibility, etc.
17:10bbloommikerod: it's also just easier to work with if you stick some stuff in a map b/c you can print it out
17:10mikerodbbloom: I don't agree with the question I posted, I just have had a hard time formulating an appropriate response.
17:11bbloommikerod: yeah, it's hard to teach someone a new way of thinking
17:11mikerodbbloom: Indeed. I appreciate your feedback on it too.
17:14Raynesguns: Oh, you're the vim-clojure-static guy.
17:14Raynesguns: I commend you on your efforts good sir.
17:17seancorfieldjust saw the discussion about clj-time... i inherited it and am not particularly attached to the names in it... that said, introducing 'second' would cause many users of clj-time to see the ugly "warning ... name already bound to ..." message on :use or :refer :all ... which is how most code uses it i suspect
17:17gfredericksseancorfield: I think most of our usages of clj-time are :as or :refer [...]
17:18seancorfieldbut it wouldn't be the only library that shadows a core function and folks know how to get around it...
17:18gfredericksmostly on principle of avoiding :use/:all
17:18seancorfieldgfredericks: you could well be right
17:18seancorfieldand the docs could make it clear too
17:18gfredericksseancorfield: just piping up with a data point
17:18seancorfieldclojure.java.jdbc has shadowed resultset-seq for a long time, for example
17:19TimMcseancorfield: Maybe that's a good reason to call it "second" -- fewer people using :use.
17:19seancorfield(but core/resultset-seq is a silly place for that function!)
17:19seancorfieldTimMc: heh, yeah, strong encouragement to change their ways :)
17:20seancorfieldfeel free to create an issue https://github.com/clj-time/clj-time/issues (when github comes back up :)
17:21Raynesseancorfield: If that's how most code uses it then that code is wrong and needs to be changed anyways.
17:27seancorfield"most code is wrong" -- Raynes, April 2013 :)
17:27seancorfieldi agree, btw
17:28Raynesseancorfield: I'm writing an issue.
17:29Rayneshttps://github.com/clj-time/clj-time/issues/70
17:32seancorfieldthank you sir!
17:41Raynesseancorfield: https://twitter.com/mikeflynn_/status/327175064644628481
17:43patchworkIs *worst* a dynamic var there?
17:45patchworkAnyone use morph for modeling global state? https://github.com/blancas/morph/wiki/Modeling-Global-Data
17:45patchworkI am looking at it as an alternative to having a dynamic var for configuration
17:45patchworkmight be more trouble than it's worth
17:46patchworkI like the idea of having pure functions access global values without passing config vars everywhere though
17:47TimMcRaynes: I wonder how much of that is just "time is hard" and the guy thinks it is clj-time's fault.
17:47RaynesTimMc: All of it I'd wager.
17:51seancorfieldi replied on twitter suggesting he open issues with improvement ideas
17:51seancorfielda lot of ppl are quick to criticize but slow to actually suggest concrete improvements
17:52joegallowell, it's easy to take potshots from the peanut gallery, much harder to climb down and start working ;)
17:54TimMcYou can't really file a proper (design) bug report in 140 characters, but if you file a github issue you don't get to be ranty in front of your friends, and we can't have *that*.
17:58rasmustowhy does this behave differently at the repl and when doing 'lein run'?: (map (comp #(.exists %) as-file) ["." "target" "/tmp" "fjoewifj"]) ; (I only get false when doing lein run)
17:58callenRaynes: I +1'd your issue.
17:59callenRaynes: WITH RUV
17:59Raynescallen: Good on ye, sir.
18:01seancorfieldcallen: changing everything to plurals would be kinda disruptive to existing users... and i think there are already some singular and plural versions of the same thing?
18:01seancorfieldi'll have to go dig into the API when i get to that
18:02Raynestpope: It'd be cool if I could pass a commit message to :Gcommit somehow.
18:03callenseancorfield: I'm open to superior alternatives that don't rest on "don't fix things"
18:03Raynestpope: It'd be useful for quick commits with short messages.
18:03callenseancorfield: you could have a migration period where using the old names pukes a warning and lets them know the next semver compliant version will get rid of the old names.
18:04SegFaultAXRaynes: But if you're already in the editor, what does that actually buy you?
18:05RaynesSegFaultAX: About 4 keystrokes.
18:05rasmustohey Raynes, can I bounce a fugitive+fireplace idea/pull req off of you?
18:05SegFaultAXi:wq is too much?
18:05RaynesSegFaultAX: Yes.
18:05SegFaultAXI guess i<esc>:wq
18:05Raynesrasmusto: Sure, but I have nothing to do with either of those projects.
18:05rasmustoI'm wondering if I should submit a pull request for this: https://github.com/rasmusto/vim-fireplace/commit/f8ae7c429aaa4a6375dbbade239b5f1b82538506
18:06rasmustoRaynes: I'm just curious if anyone would use it
18:06RaynesI don't think I use fugitive nearly well enough for this to be useful to me in particular, but that doesn't mean it isn't good.
18:07rasmustoIt lets you use cpp when inside of a :Gdiff window, so you can throw old code at the REPL
18:07RaynesThat sounds totally useful.
18:07RaynesYou should run it by tpope.
18:07rasmustoI've pinged him a few times, which is why I was wondering about just making an issue/preq
18:07RaynesYeah, that's best. He isn't around particularly often.
18:08rasmustokk
18:19rocco`can someone help me with something
18:19TimMcrocco`: Just go ahead and ask your question; if someone can help they will answer.
18:20rocco`I'm running a repl in emacs and I'd like for a function running in a different thread to print into the repl
18:21rocco`right now I have no idea where it prints because I don't understand the *in* and *out* streams
18:23TimMcOh, that can be tricky. I remember something about nREPL binding a new *out* for each new entry, too.
18:24rocco`what would be the preferred way to do it?
18:27technomancyuse bound-fn for your thread maybe
18:29TimMcrocco`: Oh right, how are you starting that thread?
18:30rocco`using the java Thread start
18:30rocco`should I use clojure abstractions instead?
18:31rocco`I'm just learning this
18:31rocco`I'm trying to run a socket server with server-socket from the old contrib
18:31rocco`and I want it to speak to me :)
18:37whinubHey guys, I'm pretty new to clojure but I was wondering if anyone could recommend a decent sized program / project with good documentation that I could read through and learn from.
18:38rocco`whinub: how about the clojure implementation itself?
18:40TimMcThe Clojure implementation breaks all the Clojure dev rules. :-/
18:40technomancythat's not a very good way to learn
18:40TimMcLeiningen is pretty nice.
18:40technomancyTimMc: as long as you skip the profile merge stuff =)
18:41beppurocco`: this one is relatively small and is well documented. https://github.com/Engelberg/instaparse
18:42beppu(that last one was for whinhub)
18:42rocco`:)
18:43whinubThanks for the suggestions guys, will definitely be checking them out.
18:43rocco`I'm also going to check it out
18:44TimMcrocco`: clojure.core/future and other multi-threaded constructs generally convey bindings such as *out* to the new thread.
18:46rocco`makes sense
18:46rocco`will try
18:55rocco`there's something about lein I don't understand
18:56rocco`is running a lein repl the same as doing a jack-in
18:56callenwhinub: web app?
18:56rocco`no just ordinary app
18:56callenrocco`: I wasn't talking to you.
18:57callenwhinub: do you want to see what a clojure web app looks like?
19:01technomancyrocco`: jack-in is just `lein repl :headless` plus connecting an elisp client to it
19:02SegFaultAXwhinub: If so, refheap and 4clojure are both open source.
19:02technomancyas is clojars
19:03tpopeRaynes: :Gcommit -m works
19:04Raynestpope: Of course it does. Because you're tpope. I should have just known.
19:23bingoAny one has experience installing with brew install leiningen 2.1.3 in mac osx?
19:23RaynesMeh, don't bother.
19:23amalloydon't use brew
19:23RaynesJust install via the shell script.
19:23technomancyhomebrew is kind of silly
19:23RaynesDon't use a package manager for anything related to Clojure ever.
19:23bingooh i see.
19:23Raynestechnomancy: It's perfectly fine for other things, but it's silly for this and Clojure in general.
19:23technomancyRaynes: I disagree
19:24Raynesamalloy: OS X comes with a JVM iirc.
19:24Raynestechnomancy: What package manager would you propose I use?
19:24RaynesNone at all?
19:24whinubcallen: Hey sorry about delay went to cook some dinner. Taking a look at a web app would be awesome. What do you recommend?
19:24RaynesI kind of need one.
19:24technomancyRaynes: apt-get or nix
19:24amalloytechnomancy: brew is silly, but it's better than the alternatives on osx
19:24RaynesAnd this is the least shitty of all of them.
19:24technomancyI don't know of any other good ones
19:24Raynestechnomancy: I need one that's actually useful.
19:24technomancyamalloy: I don't dispute that
19:25RaynesNix is great and all, but I have things to do besides making packages for everything I ever use.
19:25bbloombrew has been 1) fast 2) (generally) up-to-date and 3) not-horribly-broken... which is not something that can be said for any other OSX package manager
19:25RaynesMy only problem with brew is that at least 70% of the packages I've ever tried to install would break while installing in one way or another.
19:25RaynesFortunately they fix these problems relatively fast.
19:26bingoWell any way, I have been struggle of trying to run lein but it is complaining of depencies. I was running lein deps, and i still havin ghte same issue.
19:26Raynes(70% is an exaggeration)
19:26bbloomRaynes: clearly.
19:26technomancystockholm syndrome much?
19:26bbloommeanwhile, plan 9 namespaces would dramatically simplify every package manager ever.
19:27pjstadigmy only problem with driving on the road is that 70% if the time i die on the way to my destination
19:27technomancypjstadig: other than that, the weinermobile is a great form of transportation
19:28RaynesBut fortunately the paramedics resuscitate you relatively fast?
19:28technomancyit's aerodynamic and stuff
19:28RaynesNot sure if that metaphor goes all the way here.
19:29pjstadig(it was an exaggeration)
19:29RaynesTouché.
19:31patchwork70% of all exaggerations result in developer death
19:31bbloomi myself has died literally thousands of times
19:37weavejesterI think I've figured out why core.memoize/memo-ttl occassionally excepts
19:37weavejesterUnfortunately I'll need to use JIRA to report it *sigh*
19:40amalloyweavejester: send fogus an email, and maybe he'll fix it for you in secret
19:40rationalrevolt,(let [o '+] (o 1 2))
19:40clojurebot2
19:40weavejesteramalloy: I think I might raise it on clojure-dev first. I'd like a second opinion or two
19:40rationalrevoltam i not doing this right?
19:40BronsaI still don't understand what's preventing contrib libraries from using github issues
19:41amalloyrationalrevolt: '+ is a symbol, not the addition function
19:41amalloy+ is the addition function
19:41patchwork,(let [o +] (o 1 2))
19:41clojurebot3
19:41weavejesterDo symbols act as functions to maps, the same as keywords?
19:41amalloyyesz
19:42weavejester,('+ {'+ 2})
19:42clojurebot2
19:42weavejester,('+ {'+ 2} :not-found)
19:42clojurebot2
19:42weavejester,('+ {'+ 3} :not-found)
19:42clojurebot3
19:42weavejester,('+ 3 :not-found)
19:42clojurebot:not-found
19:42weavejesterJust checking :)
19:43weavejesterrationalrevolt: So yep, ('+ 1 2) is the same as (get 1 '+ 2)
19:44weavejesterrationalrevolt: It tries to lookup a key '+ on 1, but since 1 isn't a map it fails and returns the failure result, which has been set to 2.
19:44amalloyi thought that was supposed to throw an exception in 1.5 now
19:44amalloylooking things up in a non-map
19:44weavejester,*clojure-version*
19:44clojurebot{:major 1, :minor 5, :incremental 0, :qualifier "RC6"}
19:44amalloy,(contains? 4 3)
19:44clojurebot#<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: java.lang.Long>
19:44amalloy,(get 4 3)
19:44clojurebotnil
19:44amalloyapparently it's just the contains? check, not get
19:45Bronsaamalloy: the get patch didn't get into 1.5 afaik
19:47rationalrevoltthanks weavejester
20:01bingoHi Anyone, I would like to get someone who has experience install leiningen on mac osx 10.8.2
20:02amalloyhttps://github.com/technomancy/leiningen/blob/master/README.md#installation
20:02bingolet me try again.
20:16bttfwhy can't i :use two different namespaces that have the same method defined ?
20:16bttfall calls to that method are explicity dereferenced to their respective namespace
20:17amalloybttf: you want require, not use. use is explicitly for non-aliased names
20:18bttfamalloy: but can i require without aliasing ?
20:19bttfwait what is the aliasing part ... (require foo.bar as bar) or (require foo) so that i only have to type bar
20:19bttf(require foo.bar :as bar)
20:20Bronsa(require '[foo.bar :as bar])
20:20Bronsaor (ns .. (:require [foo.bar :as bar]))
20:20bttfoh right
20:22bttfok seems i was confused about require
20:24mynomototechnomancy: I did the fun project of find repetitions in code. But still no luck turning it into a lein plugin. And it was not that fun :) https://github.com/mynomoto/lein-repetition
20:26mynomotoIf someone knows how to make this works as a lein plugin I'd be glad. Can't require the project namespace.
20:26technomancyhuh, why do you need it to be a lein plugin
20:26technomancy?
20:28technomancyerr--why do you need to cross the boundary between leiningen and the project?
20:28technomancycan't you do it exclusively through static analysis?
20:29mynomototechnomancy: Doesn't need, just trying to learn something new.
20:30technomancysure
20:30mynomotoIt needs to know if a var is bounded in the ns or it will make it generic.
20:30technomancyoh, ok
20:31technomancyI guess you can't assume all vars are created by def or defn because of macroexpansion
20:31technomancyit looks like you're trying to require plugin namespaces from inside eval-in-project though; that's probably where it's breaking
20:32technomancyyou can only require things from :dependencies
20:32mynomototechnomancy: But I can change the project dependencies right?
20:33mynomotoOr could put everything in one file...
20:33technomancymynomoto: you could add to :dependencies but that can get hairy when profiles come into play
20:34technomancyif you can run everything inside the project process it's simpler
20:34technomancyjust say "add this to :dependencies and then run lein run -m repetition.finder" or something
20:34technomancyor if the code to be run in the project isn't that big you could build it up as one big form like `lein test` does
20:35technomancybut that gets unmanageable once you have more than a page or so
20:36mynomotoOk, I will try the lein run way. Thanks.
21:01rocco``is there a way to access a thread if you deleted the reference to it
21:01rocco``I mean a function that's running in that thread