#clojure log - Apr 01 2013

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

0:07 technomancy: arg... four years of doing clojure and still get bit by that stupid stupid dashes-to-underscores nonsense

0:08 the things we put up with for no good reason =\

0:30 callenbot: technomancy: worth it to be using a language that isn't spoiled-milk stupid.

0:31 technomancy: callenbot: sure, but that doesn't mean we shouldn't be embarrassed when it is stupid

0:31 callenbot: Of course.

0:32 technomancy: honestly I'm just grateful for the graceful nil handling. I could do without the copious if-statements I have to write in Python.

0:32 technomancy: "graceful" nil handling?

0:32 spoken like someone who hasn't used an HM type system? =)

0:32 callenbot: technomancy: I have, but you know what I mean.

0:33 technomancy: compared with Python and Go which just let your shit fall apart every time...

0:33 MikeSeth: goddamn you, just by lurking in here I learn something new

0:33 technomancy: I dunno; clojure's handling of nil is also fairly embarrassing, but at least in this case we can blame the JVM

0:33 callenbot: bladeeblah I know Maybe/Either is better but it's still an improvement.

0:34 technomancy: if you *really* cared you'd use algo.monad

0:34 technomancy: I haven't written any nontrivial python... clojure's nil handling seems the same as ruby's

0:34 callenbot: technomancy: but deep down, you know that Haskell and Scala's type systems are the Gentoo Ricers of the modern age.

0:34 technomancy: callenbot: if I really cared I'd fork core.typed

0:34 callenbot: technomancy: you want a typed lisp?

0:34 technomancy: callenbot: no, I just want NPEs to go away

0:35 that accounts for 70-80% of type errors

0:35 callenbot: technomancy: this is why I implemented my own func call chain + maybe monad wrappers in python

0:35 NoneType errors were driving me up a wall.

0:35 I don't really need it in Clojure though, the Ruby-esque nil handling is (usually) enough for me.

0:36 Perhaps partly because I don't chuck shit at JVM libraries very often.

0:36 not directly, anyway.

0:37 technomancy: the unspoken assertion here is that one advantage Ruby has on Python is nil handling.

0:38 short-circuiting and kicking nils through the call chain is my preferred way of working.

0:38 technomancy: because nil can receive certain method calls?

0:38 like .nil?

0:40 callenbot: technomancy: no, more monadically in that functions can receive a nil argument and just spit back out

0:40 and a monadic wrapper can short-circuit before it gets to that if you have that available

0:40 but if you don't, the behavior is baked in.

0:41 technomancy: .nil? is pretty trivial and doesn't really fix anything, Python's problem wasn't that None makes every action except comparison fail, it was that some fairly common sense operations wouldn't just spit the None back out like Clojure tends to in similar circumstances.

0:42 technomancy: if Haskell and Scala type systems are the cost of wrapping and compile-time checking for nils properly, then I'd rather stay on the other side of the fence.

0:42 I like HM, but I don't like actually being forced to interact with the practical products of it (currently)

0:42 technomancy: eh; from what I gather scala doesn't really prevent NPEs properly anyway

0:43 OCaml does though, without all the hoops of Haskell

0:43 callenbot: their Option handles it.

0:43 technomancy: right, but only if you explicitly opt-in

0:43 callenbot: technomancy: gods, don't remind me of OCaml. That's a heartache like Common Lisp.

0:43 MikeSeth: holywar commenceth

0:43 technomancy: =\

0:43 callenbot: technomancy: I mean heartache like I wish it was more successful.

0:43 yearning :P

0:43 technomancy: yep, I hear you there

0:44 I had such a great time with the language and such a wretched time with the libraries/tooling

0:44 callenbot: MikeSeth: 'fraid not.

0:44 technomancy: well the system type sizes thing was annoying.

0:44 and the 31-bit integers

0:44 the tagging

0:44 technomancy: oh, for numerics?

0:45 callenbot: yeah it was janky.

0:45 technomancy: that there are multiple stdlib alternatives is disconcerting as well.

0:45 technomancy: I have a hard time getting bothered by numerics that are less horrible than JS I guess

0:45 callenbot: true.

0:45 technomancy: eh; are you sure you're not thinking of D?

0:46 callenbot: no I'm thinking of Jane Street + the batteries included ecosystem

0:46 it's really ghetto.

0:46 although D is too.

0:46 technomancy: oh, sure; it's a bit different

0:46 I mean with D there are literally two libraries claiming to be "the standard library" right?

0:46 callenbot: I don't know if I'd put it like that.

0:46 it's more that there's an old and a new

0:47 phobos was the new one i think?

0:47 technomancy: I thought it was one with a good license and one that was "official"

0:47 callenbot: oh, yeah.

0:47 I mean there's the GNU D compiler.

0:48 But really, if you want something with strict semantics and HM like Ocaml, what's your practical options?

0:48 technomancy: jane street seemed like just a bunch of guys tired of the slow evolution of the language

0:48 which I can empathise with

0:48 callenbot: of course, they had work to do.

0:48 unlike the french.

0:49 from the OCaml wiki page: "Influenced F#, Scala, ATS, Opa, Rust" - frick.

0:49 A list best summarized as: Microsoft, Insane, More insane, Weird and misguided, 20% done afters of dev.

0:49 after years*

0:50 technomancy: Opa =(

0:50 so much promise, and then they careened off the deep end

0:52 callenbot: technomancy: I think they saw Meteor and Derby and said, "WE SHOULD DO THAT"

0:52 technomancy: "you know how we could get funding or something? JAVASCIRPT"

0:53 callenbot: they weren't wrong.

0:53 technomancy: sad but true

0:53 callenbot: Rust is disturbingly gnarly though.

0:53 technomancy: statements, right?

0:53 callenbot: I'd call that one of the lesser sins.

0:54 the type system seems good, but the actual *experience* of writing code is Rust is generally fraught with fear, confusion, and hate.

0:54 technomancy: yes, but all the more damning due to the fact that you have to go out of your way to make it worse

0:54 callenbot: that might be due to the fact that it's 0.6 right now, but I can't really know for sure.

0:54 I'm not actually sure if the developers care if anybody other than the internal Mozilla Servo developers are able to use Rust

0:55 I don't think they actually care because they're too busy being ecstatic that they're getting paid to write a compiler on top of LLVM.

0:55 technomancy: clojurebot: creating a language with statements is a great way to broadcast your inexperience with languages to the world

0:55 clojurebot: You don't have to tell me twice.

0:56 callenbot: technomancy: unlike Go and OCaml, Rust is actually intended to go head to head with C++.

0:56 technomancy: so I'm less apt to question the statements.

0:56 technomancy: which means what, appealing to people with severe head trauma?

0:57 callenbot: technomancy: funny but I could imagine some edge cases where being able to decl a var is somehow helpful to the compiler.

0:57 the thin red line separating systems and applications programming is usually the dividing line at which the programmer services the compiler rather than the other way around.

0:59 technomancy: think about what it means that no one who understood scheme or forth or smalltalk was exposed to the design of the language before the point at which it was considered too costly to fix

1:00 callenbot: technomancy: I don't know, pcwalton seemed pretty intelligent to me. I don't know why they did it.

1:01 technomancy: they have random cherry-pickings of Ruby-esque syntax like implicit return

1:04 technomancy: case in point, if you need to declare a range of memory "volatile", how do you do that without statements?

1:08 huwt: HI

1:08 hi*

1:09 (list '(:a :b)) vs (list '(a b))

1:09 amalloy: callenbot: the same way you do anything without statements: make it an expression that returns nil or some analogue thereof. statements are just "expressions that are invalid in some contexts"

1:09 huwt: I don't get the difference... just started studying it 3hrs in but confused

1:10 one is a keyword, but what does this mean in implication...

1:10 callenbot: amalloy: you could do that, and that occurred to me, but it's a weird special case to have functions or expressions that act as pragmas.

1:11 I have no qualm with getting rid of statements, I just find the offensiveness of them to other people in non-Lisp languages to be a bit extreme.

1:11 it's not like anybody expected Rust to be a particularly powerful or elegant language.

1:12 it's an experiment in writing a highly concurrent and powerful web browser.

1:51 rplaca: huwt: one is a keyword and one is a symbol. They're just different things in clojure

1:51 'a is a symbol. If you use it without the quote, clojure will try to use it as a name

1:51 for a let-bound value or a var

1:52 :a is a keyword, it will evaluate to itself

1:52 so in most contexts, you can use it without quoting

1:59 Raynes: hyPiRion: Dude. Your Github contributions graph is going crazy.

2:01 hyPiRion: A friend on another network was admiring swearjure a moment ago. I told him of your awesomeness.

2:19 phatpenguin: #neo4j

2:24 amalloy: speaking of swearjure, hyPiRion, i think first/rest, and CPS are a universal solution to the large-number representation problem, as long as you have a way to get lambdas anywhere in an expression

2:24 like, i don't know how you manage lambdas, but for large expressions the transformation at https://www.refheap.com/paste/13171 generates a large number of small lambdas instead of one large lambda

2:25 tieTYT2: what's the point of defining something as dynamic when you don't need to define something as dynamic to with-redef it?

2:25 amalloy: instead it has stackoverflow issues, of course, but if you pass it through a trampoline or some other CPS transformer it will get you around the large-method problem

3:17 noonian: Hi, is there a standard way to get the name and version of my project from leiningen as defined in project.clj?

4:34 borkdude: so any nice clojure April fool jokes so far?

4:44 ivan: I believe the wise Clojurians have simply turned off their Internet for 48 hours

4:47 hyPiRion: Raynes: Well, I'm trying to do at least one commit per day, and one bugfix on Lein per week. It's not that much work really, but it looks nice on the contrib graph, yeah

4:49 tomoj: hyPiRion: seen gitminder?

4:50 hyPiRion: tomoj: nope, what is it?

4:50 tomoj: https://www.beeminder.com/gitminder

4:50 uh.. sign up to give someone money if you don't keep your commit rate goal

4:50 :/

4:50 borkdude: what is the best practice when doing multiple apps using a postgresql db? one database, multiple schemas? or one db per app? and one user per app, or just one user to rule all dbs?

4:52 yogthos I am trying postgresql - I noticed I have to change the sql to make it work from the guestbook example

4:52 yogthos for example, I have to convert java.util.Date to java.sql.Date

4:53 hyPiRion: tomoj: heh, well, if I suddenly get ill I don't want even more expenses

4:53 amalloy: "as long as you have a way to get lambdas anywhere in an expression

4:53 is probably the hardest part of Swearjure as of now

4:54 amalloy: i thought it might be, which is why i included the stipulation :P

4:54 but i thought you had solved it

4:55 hyPiRion: well, I can do it if I make a form and eval it

4:57 I'll have to revisit lambdas within lambdas soon I think

5:04 McTehranBurger: ,"Hallowed are the Ori"

5:04 clojurebot: "Hallowed are the Ori"

7:19 borkdude: lol, stackoverflow has "chat with an expert" as 1 april joke?

7:22 arcatan: my expert wasn't very fun :(

7:22 borkdude: arcatan who not

7:22 arcatan why

7:23 arcatan: she was like "Whatever you say" all the time

7:47 bhenry: what is the best java for clojure dev on ubuntu machine?

8:01 simsalibim: with compojure, how are most people doing RPC calls?

8:01 and clojurescript

8:02 ivan: bhenry: openjdk-7-jdk

8:03 bhenry: ivan: is that objective?

8:06 ivan: there may be reasons to use the Oracle build, or IBM's JVM, or Azul's JVM, but I bet you do not need them

8:06 hyPiRion: bhenry: If you don't notice any difference, either openjdk-6-jdk or 7 works fine

8:07 I alternate between both, and I haven't noticed any major differences for development purposes

8:07 bhenry: thanks guys

8:07 tomoj: use 7 to avoid having to get jsrwhatever to use reducers

8:07 or is it just fold now?

8:08 hyPiRion: tomoj: oh right, if you need core.reducers, then 7 is smart to have

8:08 I think it falls back to the normal reduce

8:36 sandbags: does anyone here use LightTable and know if there's ever any activity in #lighttable? I'm not sure if I've just been unlucky so far

8:52 si14: how do you "unzip" a sequence in Clojure, preferably in one pass?

8:52 I mean getting 2+ seqs from each element of one seq

8:55 bhenry: si14: partition and partition-all might be good starts

8:55 hyPiRion: bhenry: I think that does the opposite of what he wants

8:55 ,(partition 2 [1 2 3 4])

8:55 clojurebot: ((1 2) (3 4))

8:55 bhenry: i guess i need to see a sample in and desired out

8:56 hyPiRion: has [[1 2] [3 4]], want [1 3] [2 4]

8:56 si14: [[1 2] [3 4] [5 6]] -> [[1 3 5] [2 4 6]]

8:56 hyPiRion: yeah, thanks :)

8:56 hyPiRion: ,(apply map vector [[1 2] [3 4] [5 6]])

8:56 clojurebot: ([1 3 5] [2 4 6])

8:57 hyPiRion: I'm not entirely sure of performance on that one though. If you're in dire need of it, you may want to make something yourself

8:57 si14: it's kinda works, but not in general case.

8:58 I have something like [[a1 b1 [c1 d1]] [a2 b2 [c2 d2]] ...] and need to get 2 maps like {[a1 b1]: c1, [a2 b2]: c2} and {d1: c1, d2: c2}

8:59 it's can be done with reduce, but I wonder if there is an idiomatic approach.

9:00 bhenry: si14: i think whatever you're doing is not idiomatic.

9:00 si14: bhenry: why is it so?

9:00 hyPiRion: Well, that's not covered by the normal funcs at least

9:02 si14: ok, I need to compute 2 different metrics on one seq simultaneously. how would you do this? my current solution is r/map of fun that returns vectors of values for each element.

9:05 and, btw, am I wrong or clojure.core has a typo in a released version https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj#L321?

9:06 hyPiRion: si14: that may well be

9:07 $google jira clojure monoid

9:07 lazybot: [Overview - Clojure v1.6 API documentation] http://clojure.github.com/clojure/branch-master/

9:07 hyPiRion: damn you, google.

9:07 tomoj: hmm, I think you need a postreduce step to do that nicely

9:08 si14: tomoj: what do you mean?

9:08 tomoj: which reminds me of cgrand's suggested change to fold

9:09 well, see http://squing.blogspot.com/2008/11/beautiful-folding.html

9:09 I haven't tried to make sense of it in clojure yet, but I suspect reducers as is is not very well suited

9:10 data Fold b c = forall a. F (a -> b -> a) a (a -> c)

9:10 the (a -> c) seems to be missing?

9:14 (= [10 24] (r/reduce (__ + *) [1 2 3 4]))

9:16 si14: https://gist.github.com/si14/df5b9afe28835f8cc154 well, here is a pair of functions in questions

9:16 lines 10-15 are there only for rearranging the data. personally I don't like it.

9:18 tomoj: oh, I missed everything before "I need to compute 2 different metrics on one seq simultaneously"

9:18 * si14 I think that r/folds should really be folders

9:18 tomoj: I'm going to try to solve my problem instead of yours :)

9:19 si14: tomoj: :)

9:19 I would really appreciate any comments/suggestions on that snippet.

9:19 tomoj: hmm https://www.refheap.com/paste/44fb973a86835a8bc4d7ce9b5

9:19 that was too easy

9:22 si14: tomoj: yeah, that works for simple monoids like + or *. but for the general case it doesn't

9:24 tomoj: what is the problem for the general case?

9:24 I mean the combinef/reducef split in r/fold seems tricky

9:25 are there more problems?

9:28 si14: tomoj: no, that's the problem :)

9:29 tomoj: makes me kind of want one thing that can represent both the combine and reduce

9:31 https://www.refheap.com/paste/224956f9814740700a3e7f377 ? :(

9:32 (defprotocol IMonoid (-empty [this]) (-combine [this ret ret']) (-reduce [this ret v]))

9:32 ?

9:32 * si14 that's not a monoid :)

9:33 tomoj: yeah, bad name..

9:33 I'd say 'IFolder' but..

9:37 (defprotocol ICombine (-empty [this]) (-combine [this cret cret']) (-reduce [this ret v]) (-postreduce [this ret]))

9:38 (extend-type Fn ICombine (-empty [this] (this)) (-combine [this cret cret'] (this cret cret')) (-reduce [this ret v] (this ret v)) (-postreduce [this ret] ret)) ?

9:40 would allow cgrand's idea without breaking existing monoids

9:44 jcromartie: what *exactly* is print-dup

9:44 it's undocumented and not self explanator

9:44 y

9:44 but it pops up in various examples and discussions

9:44 tomoj: ,(doc *print-dup*)

9:45 clojurebot: "; When set to logical true, objects will be printed in a way that preserves their type when read in later. Defaults to false."

9:46 jcromartie: it specifically seems to rely on read eval

9:46 ,(print-dup {} *out*)

9:46 clojurebot: #=(clojure.lang.PersistentArrayMap/create {})

9:46 hyPiRion: ,(pr-str (doto (ArrayList.) (.add 1) (.add 2) (.add 3)))

9:46 clojurebot: "[1 2 3]"

9:47 hyPiRion: ,(binding [*print-dup* true] (pr-str (doto (ArrayList.) (.add 1) (.add 2) (.add 3))))

9:47 clojurebot: "#=(java.util.ArrayList. [1 2 3])"

9:48 hyPiRion: jcromartie: do you get its use now?

9:48 jcromartie: more or less

9:48 I don't quite understand why people advocate using the print-dup function directly in certain cases

9:49 it might just be the specific example I was looking at

9:49 bhenry: where can i find a walkthrough on the current best practice of a .emacs that works great for clj dev?

9:50 i have the standard emacs from apt-get install emacs

9:50 hyPiRion: bhenry: Bodil has a great .emacs.d at https://github.com/bodil/emacs.d, which you may want to look at

9:51 I have stolen that design for mine (https://github.com/hyPiRion/emacs.d)

9:51 Though they are more extensive than just Clojure though, so if you're new to emacs they are probably a bit overwhelming.

9:51 rkneufeld: For something a bit smaller you might try bit.ly/clj-ready.

9:52 stuartsierra: jcromartie: I don't think print-dup is meant to be called directly.

9:52 jcromartie: I didn't think so

9:52 hyPiRion: (inc rkneufeld)

9:52 lazybot: ⇒ 1

9:53 hyPiRion: That's a way better introduction for someone completely new. :)

9:56 rkneufeld: Once the Clojure/west videos are up you'll also be able to see my presentation on editing Clojure in Emacs. Until then there are my animated slides: https://www.dropbox.com/s/rwjer7p9mirbwfw/Editing%20Clojure%20with%20Emacs.mov

10:24 otfrom: afternoon all

10:35 borkdude: http://clochure.org/

10:43 gfrederi1ks: borkdude: wat

10:44 this must be date-related

10:46 nDuff: *snerk*

10:48 tbaldrid_: "A better Clojure" https://github.com/videlalvaro/clochure/

10:51 snowylike: at first I thought this was an April Fools joke

10:51 but then...

10:51 borkdude: tbaldrid_ clojure for the masses

10:52 hyPiRion: Has to be.

10:52 snowylike: quote: "So one the eve of April 1st we sat down in a brainstorm session with a team of PLT experts. Ideas starting flying around:"

10:52 with "April 1st" in bold

10:56 hyPiRion: Obvious is obvious

10:58 clochure.core looks rather blocky

11:01 gfredericks: great logo

11:02 otfrom: lovely

11:02 borkdude: untyped Haskell would be an alternative worth exploring

11:02 hyPiRion: gfredericks: We need one of those for Swearjure!

11:03 jcromartie: ooh, a new clojure project to poke at https://github.com/oakes/Nightweb/tree/master/server

11:04 wait a minute

11:04 hyPiRion: Well, it certainly is new.

11:05 jcromartie: here's the interesting stuff https://github.com/oakes/Nightweb/tree/master/common/clojure

11:06 pretty neat idea though

11:06 otfrom: Is there something in clojure core that lets you restructure a map based on the parameters to a function?

11:06 I found this: http://stackoverflow.com/questions/8999794/map-restructuring

11:06 but I'm wondering if I'm missing something core

11:07 gfredericks: hyPiRion: I'm terrible at logos

11:07 hyPiRion: gfredericks: Not you, we.

11:08 gfredericks: otfrom: not sure what you're asking. the top answer says "it's not provided" which is accurate. did you want something slightly different?

11:09 jcromartie: restructuring, huh, interesting idea

11:10 basically printf for data structures

11:10 bbloom: otfrom: not really workable with maps because the reader initializes them as real data structures

11:11 if you wanted to d something like obj = {a, b, c}, then you'd have an odd number of keys

11:11 you'd need to do something like {:keys [a b c]}

11:11 jcromartie: just like destructuring

11:11 bbloom: but then you have no way of differentiating between assignment and restructuring, you'd need some kind of marker

11:12 jcromartie: right, i'm just saying that it couldn't be baked into the syntax w/o creating ambiguity, you'd need to specifically request restructuring

11:12 otfrom: What I'd like to be able to do is (defn foo [bar baz] ...) call (foo 1 3) and have {:bar 1 :baz 3} available in the defn

11:12 gfredericks: that's defnk ain't it?

11:13 no wait

11:13 nevermind

11:13 otfrom: so you want a special extra local that has the arguments

11:14 otfrom: I'm not sure I *want* it, but if it existed, then I'd want to use it

11:14 and it seems like it doesn't exist

11:14 jcromartie: otfrom: it seems easy enough to make

11:14 clojurebot: Huh?

11:14 otfrom: and it is always so difficult to proves something doesn't exist ;-)

11:14 jcromartie: it does look simple to make, which is partly why I thought there might be something in core already

11:15 and I'd just feel silly for re-implementing it

11:15 gfredericks: (defmacro defn' [name arglist & body] `(defn ~name ~arglist (let [&args {~@(mapcat (juxt keyword identity) arglist)}] ~@body)))

11:15 ^ that has a 14% chance of working

11:15 otfrom: lol

11:15 gfredericks: wait no 0

11:15 hyPiRion: 14%? That's specific.

11:15 gfredericks: the splicing won't work

11:15 hyPiRion: ,(rationalize 0.14)

11:15 clojurebot: 7/50

11:15 hyPiRion: Works 7 out of 50 times, every time.

11:16 gfredericks: (defmacro defn' [name arglist & body] `(defn ~name ~arglist (let [&args ~(into {} (map (juxt keyword identity) arglist))] ~@body)))

11:16 hyPiRion: yeah, you need a ~@[] before the mapcat

11:16 boo

11:17 otfrom: I just hate re-implementing clojure.core badly. ;-) But at least it looks like I won't be doing that this time

11:17 loliveira: is there some way to implement "private" variables inside a defrecord?

11:17 jcromartie: (defmacro ?map [& names] `(into {} ~(mapv #(vector (keyword %) %) names)))

11:17 gfredericks: oh one more issue the fully qualified &args

11:17 jcromartie: I have no idea what to call it

11:17 gfredericks: (defmacro defn' [name arglist & body] `(defn ~name ~arglist (let [~'&args ~(into {} (map (juxt keyword identity) arglist))] ~@body)))

11:17 otfrom: ^ that seems to work in my repl

11:18 bbloom: loliveira: to what end?

11:20 hugod: I just found then when generating type hints on let bindings with a macro, you have to use class symbols, rather than classes themselves, or the type hints are silently ignored :(

11:20 jcromartie: loliveira: deftype's fields are public, deftype's fields are private

11:21 bbloom: jcromartie: huh?

11:21 jcromartie: bbloom?

11:21 clojurebot: bbloom: readability is not binary

11:21 bbloom: jcromartie: i assume you mean defrecord and deftype specifically

11:21 er respectively*

11:21 jcromartie: oops

11:21 yea

11:21 loliveira: bbloom: I have a record that holds database credentials. (defrecord DB [spec] …) spec is a map, it holds user, pass, driver, etc.. I'd like to store a pool into the record, but I think it should be private.

11:22 jcromartie: loliveira: why combine the DB spec and the pool?

11:22 bbloom: loliveira: why do you need a record at all?

11:22 jcromartie: ^^ that too

11:22 bbloom: records are an advanced feature

11:22 they are mostly a performance tool for when you need type dispatch

11:23 loliveira: bbloom: I need to work with 2 databases. it shoud

11:23 bbloom: so make two maps of credentials

11:23 and stick them in a vector or something

11:23 and stick that in a map with the pool

11:24 tjgillies: why do people use two semicolons for comments when one is fine? seems sort of redundant

11:24 bbloom: {:pool POOL :connections [{:username "foo" :url "xyz://..."} {:connection-string "asdfasdf"}]}

11:24 tjgillies: common-lisp-ism. one semicolon is a line comment for stuff to the left of the ;

11:24 jcromartie: tjgillies: https://github.com/bbatsov/clojure-style-guide#comments

11:25 tjgillies: think of it like headline levels

11:25 bbloom: yeah, what jcromartie said

11:25 loliveira: bbloom: thank ypu

11:25 i ll try.

11:25 tjgillies: ...

11:25 that websites just says "do this because i say so"

11:25 heh

11:25 AimHere: Well isn't that what all style guides are for

11:26 bbloom: i dunno anything about that particular styleguide

11:26 tjgillies: thats kinda my point

11:26 ;)

11:26 bbloom: but it's very common in lisps to have ; line comment, ;; block comment ;;; region comment ;;;; file comment

11:26 technomancy: riastradh' style guide says "do it this way because parens on their own line get lonely" which is pretty great

11:26 AimHere: Most of the content in most coding styles are arbitrary; but it's still good practice to follow one of them

11:27 hyPiRion: bbloom: there should be another one in project.clj, which has ;;;;; for project comments

11:27 technomancy: "do it this way because you'll sound funny if you don't" is basically the cornerstone of all human language though

11:27 hyPiRion: and then obviously ;;;;;; for system/application comments

11:28 enquora: anyone have experience with pedestal yet?

11:28 bbloom: hyPiRion: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; line separators == "comment on the universe below this point"

11:28 tjgillies: technomancy: yet here we are programming with parenthesis and such ;)

11:29 technomancy: tjgillies: all those crazy languages with curly brackets and semicolons just sound like gibberish to me

11:29 tjgillies: lol

11:30 technomancy: http://achewood.com/index.php?date=02212002

11:30 bbloom: i can't ever remember associativity rules anyway

11:30 tjgillies: i just realized putting a semicolon on the end of each line is valid clojure

11:30 hyPiRion: I suspect John McCarthy invented the emoticon and just wanted to be able to insert ;) at any place within his source code.

11:30 technomancy: heh

11:31 egghead: achewood rules

11:31 tjgillies: omg thats messed up if not funny

11:31 hyPiRion: tjgillies: Putting a semicolon at the start of each line is also valid Clojure

11:32 tjgillies: hyPiRion: it tends to make my programs less buggy as well

11:32 hyPiRion: yeh

11:34 stuartsierra: tjgillies: Emacs will automatically indent ; at right margin, ;; at current code indent level, and ;;; at left margin

11:35 tjgillies: (inc stuartsierra)

11:35 lazybot: ⇒ 3

11:35 ucb: stuartsierra: I rather enjoyed your post on scope

11:35 stuartsierra: ucb: Thank you.

11:35 ucb: no, thank you.

11:36 stuartsierra: You're welcome. :)

11:37 ucb: stuartsierra: sorry if this is a silly question, but I got to your blog via planet clojure and I couldn't find an RSS link on your blog. Is this by design?

11:38 stuartsierra: no

11:38 It uses feedburner.

11:38 bbloom: which is surely going to be killed soon.

11:38 ucb: hmm

11:38 heh

11:38 stuartsierra: I changed the theme recently: maybe the link is broken.

11:39 borkdude: what advantage has defhtml in hiccup over a normal function with html form?

11:39 ucb: I couldn't even find the link :)

11:40 stuartsierra: ucb: Yeah, I should fix that.

11:40 ucb: good to confirm it's not my tired eyes then

11:41 stuartsierra: Thanks for the heads-up. I'll try to fix that.

11:42 ucb: The link, by the way, is http://stuartsierra.com/feed

11:42 * ucb subscribes

11:43 borkdude: ANN: Untyped Strictly Evaluated S-Expression Haskell for the JVM http://t.co/kQoxHEcmeM

11:46 bbloom: borkdude: lol.

11:46 tjgillies: today is gonna suck

11:46 :)

11:49 stuartsierra: There, RSS links added.

11:49 TimMc: I've seen a defn+opts

11:50 whoops, I was in the scrollback

12:00 estebann: ls

12:00 lazybot: bin lib opt proc root sys

12:03 estebann: i'm trying to get an internal maven repo setup and I'm having a bit of trouble with leiningen

12:04 deploying works fine but the Authentication string is not sent when trying to download artifacts from the local mirror of central

12:04 has anybody setup leiningen to use mirrors with basic http authentication?

12:06 technomancy: estebann: are you able to pull from it if you treat it like a regular repo instead of a mirror?

12:07 estebann: technomancy: i have been testing against an artifact available in central and it seems to try central first if I don't setup a mirror

12:07 I could be wrong about that, let me check

12:10 technomancy: you can do :repositories ^:replace [["myrepo" {...}]]

12:10 to disable central/clojars

12:10 lyra77: http://xteensx.info/young-amateur-czech-couple-very-hot-sex-scene/

12:11 technomancy: ~guards

12:11 clojurebot: SEIZE HIM!

12:11 estebann: technomancy: cool, I didn't know that

12:13 hyPiRion: ~gourds

12:13 clojurebot: SQUEEZE HIM!

12:13 technomancy: clojurebot: botsnack

12:13 clojurebot: thanks; that was delicious. (nom nom nom)

12:15 estebann: technomancy: yeah, that works

12:15 hyPiRion: Ah, that's another plugin idea for lazybot/clojurebot: Say something whenever suspicious links appear here

12:15 estebann: i can pull the artifact from the proxy

12:16 jcromartie: bleh… mixing mutable thread-unsafe Java objects and Clojure concurrency

12:16 technomancy: estebann: so the problem there is that it might allow for transitive dependencies to skip the proxy

12:16 jcromartie: instant pain!

12:16 technomancy: I haven't really looked into it, but I think the advantage of :mirrors is that *all* references to central go through your repo instead

12:17 whereas with :repositories you can still have other repos sneak in through declarations of using central inside a dependency pom

12:17 estebann: ah, gotcha

12:17 technomancy: I was mostly asking that to see if lein could authenticate at all

12:18 that is, whether the auth issues were specific to the mirror functionality

12:18 estebann: makes sense

12:18 technomancy: unfortunately I've never actually used mirrors myself =\

12:18 borkdude: clojars april fools joke that didn't make it: for each jar you download, you have to contribute one library :P

12:19 wting: Hey guys, I'm trying to compile a hello world example via lein repl, but ('compile clojure.examples.hello) gives me a file not found in classpath. What the directory structure I should be using?

12:19 estebann: technomancy: should mirrors work like I am expecting them to? or have I misunderstood their capabilities

12:20 hyPiRion: wting: (compile 'clojure.examples.hello) instead, I suppose :)

12:20 wting: hyPiRion: oops, that's what I meant. :p

12:20 technomancy: estebann: I'm not quite sure what your expectations are, but you haven't said anything obviously incorrect yet =)

12:20 borkdude: wting probably don't want to name your namespaces starting with clojure

12:20 hyPiRion: wting: but are you using Leiningen, or just pure Clojure?

12:20 technomancy: TBH the mirrors stuff is kind of hand-wavy from my perspective; I just hand off to Aether and it does the rest

12:21 estebann: technomancy: ok, I guess I'll look into what's going on in aether, thanks for the help

12:22 wting: hyPiRion: Well I'm not using lein new to create the project, I'm just trying to compile it via `lein repl`. I just want to get a hello world compiled example working.

12:22 technomancy: estebann: how are you configuring mirror auth?

12:22 it might be that Leiningen just isn't honoring auth settings or something

12:22 estebann: :creds :gpg like everything else

12:22 technomancy: yeah, that could just be an oversight of Leiningen that it doesn't check there maybe?

12:23 if you put the creds inline does it work?

12:23 estebann: i'll check

12:25 hyPiRion: wting: Well, the docstring says "The source for the lib must be in a proper classpath-relative directory. The output files will go into the directory specified by *compile-path*, and that directory too must be in the classpath."

12:26 estebann: technomancy: yeah, that worked. should I submit a bug report?

12:26 hyPiRion: wting: So if have /some/dir in your classpath, then the file should be /some/dir/clojure/examples/hello.clj

12:26 technomancy: estebann: yeah, go for it

12:26 estebann: technomancy: thanks again

12:26 technomancy: no problem

12:33 augustl: are there any asset pipeline (name borrowed from Rails) systems around for Ring apps? For stuff like compiling non-JS to JS, only serving one minified file in production (from memory, probably), etc

12:37 scottj: augustl: maybe dieter, see pdf in clojurewest slides Biggar-cljv8_dieter_asset_pipeline.pdf

12:37 wting: hyPiRion: So I have a file in /tmp/hello/src/hello.clj with (ns hello (:gen-class)). In /tmp/hello I run `java -cp /usr/share/clojure/clojure.jar clojure.main`

12:38 However (compile 'hello) still fails. Should namespace be src.hello in hello.clj?

12:38 hyPiRion: wting: ugh, let me just find out what Leiningen does in a project :p

12:39 wting: I have lein installed if that's quicker

12:39 augustl: scottj: looking it up, thanks

12:40 hyPiRion: well, it's easier to make a project (`lein new app projectname`) and just use lein repl, then all classpaths and so forth are fixed for you

12:41 wting: hyPiRion: ahh ok, I see. I managed to compile the classes just fine, now I gotta figure out how to run them. :p

12:42 hyPiRion: I think that's the general consensus in the Clojuresphere.

12:42 wting: Leiningen can take care of that too :) `lein run` runs the project, `lein uberjar` creates a standalone jar

12:43 with uberjaring, the jar file lies within target/name-of-project-0.1.0-standalone.jar by default

12:43 (run by `java -jar name-of-jar`)

12:46 jaley: making extensive use of the closure library from clojurescript is just asking for typos

12:51 pl6306: I am processing a seq of strings. Is there something like a take while? So I can create maps after the first instance of say "--------------------------"?

12:53 hyPiRion: ,(take-while #(not= "---" %) ["a" "b" "hey" "---" "Not" "used"]) ; ?

12:53 clojurebot: ("a" "b" "hey")

12:54 pl6306: How about if only want the tail of the seq?

12:54 jaley: pl6306: drop-while?

12:54 pl6306: thanks

12:54 hyPiRion: yeah, (rest (drop-while instead

12:55 bbloom: ibdknox: i see you forked fipp. anything interesting in mind? (also, if you're using it, you should update as there was a major bug fix thanks to octagon)

13:05 wting: hyPiRion: managed to compile and run the jar, thanks!

13:05 tieTYT: http://stackoverflow.com/questions/15747774/whats-the-point-of-defining-something-as-dynamic-when-you-dont-need-to-define

13:08 hyPiRion: wting: you're welcome, enjoy :)

13:10 gfredericks: tieTYT: binding is thread-local, and with-redefs is not; thus the latter is not generally thread-safe

13:11 tieTYT: does that mean that with-redefs will have an affect outside of its scope if another thread tries to run the function?

13:12 finishingmove: hey guys, how would i do something like (int 2.6) but to get 3 instead of 2 ? (round up)

13:14 hyPiRion: ,(int (Math/round 2.6))

13:14 clojurebot: 3

13:14 joegallo: tieTYT: yes, it's a global thing, often useful for tests, probably not useful for normal code

13:15 ,(int (Math/round 2.1)) ;; though

13:15 clojurebot: 2

13:15 finishingmove: thanks guys

13:15 joegallo: ,(int (Math/ceil 2.1)) ;; perhaps you want this

13:15 clojurebot: 3

13:15 finishingmove: hm

13:16 so i guess there's a Math/floor too :)

13:16 joegallo: aye

13:16 tieTYT: ok but if you're single threaded, then the redef only occurs in the lexical scope of the with-redefs, right?

13:16 hyPiRion: yup

13:16 tieTYT: ok

13:16 joegallo: tieTYT: sure...

13:16 technomancy: tieTYT: no, with-redefs has dynamic extent

13:16 finishingmove: newbie question, but can i somehow add a 'use' statement somewhere and not have to write "Math/ ..." explicitly?

13:17 tieTYT: technomancy: i understand it redefines in a dynamic way

13:17 but once the scope of the with-redefs exits, the function goes back the way it was defined, right?

13:17 technomancy: yes

13:18 (which is not how lexical scope works)

13:18 tieTYT: right

13:18 hyPiRion: tieTYT: I think you flipped dynamic and lexical

13:19 tieTYT: what I was saying is that if the with-redefs is nested, its redef only takes effect under its scope and not outside of it

13:19 just like how if you nest a let, those symbols only have those values under the let's scope

13:20 technomancy: no, let is different

13:20 it doesn't extend inside the calls in the let body

13:20 tieTYT: i understand

13:20 i'm not talking about the functionality, i'm talking about the scope of their effect

13:20 hyPiRion: finishingmove: I don't think there is, actually.

13:20 tieTYT: anyway I think I get it :)

13:21 finishingmove: hyPiRion hm... maybe some 3rd party support?

13:22 hyPiRion: finishingmove: there was this thing called import-static, but I don't think it has been updated since Clojure 1.2

13:24 you could always try it out though

13:27 TimMc: finishingmove: May I offer a compromise? (.importClass *ns* 'M Math) then (M/abs -3)

13:27 finishingmove: TimMc yes that looks neat

13:30 Raynes: Sigh.

13:30 Looks like Charles Nutter is trying to 'fix' Lisp syntax as well.

13:31 technomancy: Raynes: I loled until I saw the "not an april fools joke" message at the top =\

13:31 Raynes: technomancy: Yeah, I'm arguing with him and he is being very trollish.

13:32 tomoj: where's this?

13:32 technomancy: he should know better, but yeah... nothing to be done

13:32 Raynes: Twitter, tomoj.

13:34 technomancy: Raynes: I linked to his gist on the lein-xml announcement though =D

13:34 callenbot: Raynes: dude implements a slow Ruby implementation (original, yes?) and now he has something to teach everybody :P

13:35 technomancy: "a slow Ruby implementation" is there another kind?

13:35 JRuby's fast for a ruby though

13:35 callenbot: kinda-sorta-not-really.

13:36 technomancy: MacRuby and Rubinius are neat.

13:36 bbloom: technomancy: yes, but they aren't really rubies so much as they are ruby look alikes :-P

13:36 MacRuby is just objective C with ruby syntax & statically resolved metaprogramming, which, to be fair, is a huge step up from no meta programming

13:37 callenbot: well I like Elixir too.

13:37 Raynes: technomancy: I just hate it when I respect people and then they do things like that and it smells so much like trolling that I'm baited in and I have to make them hate me with logic.

13:38 callenbot: Raynes: can you link what he's doing?

13:38 tomoj: https://gist.github.com/headius/5285216

13:39 callenbot: sigh.

13:39 amalloy: wait, Raynes, if it smells like trolling that should do the opposite of bait you in

13:40 callenbot: nobody that actually writes Lisp, cares.

13:40 this is a stupid gist.

13:40 tomoj: doesn't his "Immutable data structure example" call the data structures with no arguments?

13:41 I guess he thinks functions are these special things and you always know whether a symbol resolves to a function

13:41 bbloom: tomoj: yeah, that's the main problem with these indentation based approaches. they assume static type knowledge

13:41 Raynes: callenbot: https://twitter.com/headius/status/318780382348726272

13:42 This is part oft he thread.

13:42 But there is a lot more spread out.

13:42 Look at my or his twitter stream for more bitching.

13:42 callenbot: okay, so I admire Erlang

13:42 but I don't swoop into their community claiming to be able to solve what I think are their "problems"

13:42 why is he doing that to us?

13:43 Raynes: Because he can.

13:43 And he really thinks he is right.

13:44 callenbot: Raynes: must not work with macros on the regular.

13:44 Raynes: I'm more concerned that 5 people have told him he is utterly wrong and he just keeps repeating the same pointless things.

13:44 Make that 6.

13:44 People are still hopping in to tell him he is wrong.

13:44 callenbot: my mental bucket that says, "Ruby programmers are shallow" just had a few pebbles chucked into it.

13:44 technomancy: sorry!

13:44 true_droid: hey guys. I'm not very proficient with Clojure, but I'd like to find out how exactly existing Clojure collections reduce themselves with a given reducer

13:45 could someone point out places in Clojure source where to look?

13:45 Raynes: I don't think it has anything to do with what community he is from. It's more that he just hasn't even used Clojure and has decided it is broken and he is the messiah who can fix it.

13:45 bbloom: true_droid: grep for coll-reduce

13:45 technomancy: callenbot: more like "being good at compilers doesn't mean you won't suck at issues of crossing community divides" maybe?

13:46 true_droid: bbloom: thanks

13:46 callenbot: technomancy: I'll go with that, but usually people that have tackled seriously large projects are more humble.

13:46 technomancy: callenbot: I'm a bit sympathetic because the enormous amounts of shit he gets from ruby people who are like "eww yuck java" when they read about jruby

13:47 bbloom: i'm once again struck by how forcefully cond resists being formatted cleanly in ANY syntax/notation

13:47 callenbot: technomancy: if you need jruby's concurrency mechanisms, then you shouldn't be using Ruby anyway :P

13:48 amalloy: bbloom: i have a cute trick for that, if you like

13:48 technomancy: callenbot: not always an option. but anyway, this gist is stupid; no argument.

13:48 bbloom: amalloy: oh?

13:48 technomancy: and yeah, cond is super annoying

13:48 amalloy: the biggest problem is when the conditions are long enough that you need to wrap the then-clauses onto the next line, right?

13:49 bbloom: *shrug* when that happens i tend to just indent all of the then-clauses

13:49 amalloy: so you indent the then-clause with two commas, and emacs doesn't know it can delete them to "fix" your indentation

13:49 bbloom: amalloy: hmm interesting heh

13:49 i don't use emacs, so i don't fight with the indenter nearly as much

13:50 hyPiRion: Well, that's a limitation to clojure-mode though. I wouldn't be surprised if that can be fixed.

13:50 jcromartie: I didn't know people were so hung up on parens

13:50 on both sides

13:50 bbloom: jcromartie: it's just alien to people

13:50 amalloy: hyPiRion: it probably can, but nobody will. the indenter is hard to understand, and if it special-cases cond then your enhanced-cond macro will still be just as bad

13:52 hyPiRion: I'm not surprised.

13:52 technomancy: every time I have to write a cond where the body clauses need their own line it just makes me think I should be using core.match

13:52 bbloom: technomancy: but matching has a similar problem. the issue is more generally: 2D structures are hard to work with in text

13:52 TimMc: technomancy: core.match is still woefully undercooked.

13:53 bbloom: pattern matching adds some extra brackets and syntax that aleivates the problem :-P

13:53 alleviates* sheesh i can't spell and or type

13:53 technomancy: TimMc: yeah, we played with it at seajure and came to that conclusion

13:53 kind of bums me out that it's not under active development any more

13:54 bbloom: technomancy: on a totally random side note. have you ever seen jonathan edwards schematic tables?

13:54 super cool.

13:54 technomancy: bbloom: I think I saw some of that at his emerginglangs talk?

13:54 that was like 2009 though so I'm a bit fuzzy

13:54 bbloom: technomancy: http://subtextual.org/subtext2.html

13:55 technomancy: it's obviously just research/experimentation, but damn it's a cool demo

13:55 technomancy: flash =(

13:56 bbloom: *shrug* you have no way to view flash at all?

13:56 technomancy: I could get my wife's computer I guess?

13:56 bbloom: lol

13:56 ok, well if you ever get 40ish minutes to watch it, i recommend it

13:56 it's a really cool demo

13:57 technomancy: IIRC his emerginglangs talk was pretty FRP-heavy?

13:57 bbloom: didn't see it

13:57 this is an older demo about his idea of a GUI for visualizing decision trees & data flow

13:57 callenbot: Stuff like FRP makes functional programming look bad to the muggles, IMHO.

13:57 technomancy: I get the feeling if I try to find it I'll find a bunch of fire-and-brimstone 18th-century sermons

13:58 ztellman: callenbot: how so?

13:58 callenbot: ztellman: making things they thought they already understood more complicated.

13:58 amalloy: callenbot: doesn't all of FP do that?

13:58 callenbot: ztellman: speaking from what I saw of it in Haskell, anyway.

13:59 amalloy: "gosh dang, i already understand loops, why is this reduce stuff so friggin complicated"

13:59 technomancy: the FRP presentations I've seen aren't like that at all

13:59 callenbot: the lengths one had to go to to simply make a game was obscene.

13:59 technomancy: elm and Edwards' stuff

13:59 ztellman: callenbot: it's basically just the same conversation as callbacks vs promises, maybe you've just seen needlessly opaque presentations

13:59 bbloom: part of the problem with functional programming is that it makes complexity more apparent

14:00 it seems harder b/c it IS harder than it seemed before :-P

14:00 however, it's just as hard both ways lol

14:00 callenbot: ztellman: I don't really have a problem with it

14:00 seancorfield: that sounds like a positive, not a problem, bbloom

14:00 callenbot: ztellman: I have a problem with the impression it makes.

14:00 bbloom: seancorfield: you're right. let me qualify: the ADOPTION problem

14:00 ztellman: callenbot: write a letter to your haskell congressman, I dunno

14:01 callenbot: ztellman: I don't think anybody had serious trouble understanding promises

14:01 and promises offer a simplification of code that I think most can grasp.

14:01 I'm not sure the same is the case with FRP unless you've been deep down in the tarpit.

14:01 ztellman: callenbot: honestly, promises are only a hop, skip, and a jump away from FRP

14:02 bbloom: callenbot: 90% of the time, people just want to immediately resolve a promise, but lack of lightweight threads makes that a problem

14:02 ztellman: not in terms of complexity, I mean, but in terms of actual underlying concept

14:03 callenbot: ztellman: well if you put up a talk demonstrating as much, you'll probably solve some of the marketing problems.

14:03 ztellman: again, this might be a Haskell thing, but writing games with FRP was, "lets write a thesis!", not, "lets write a game!"

14:04 ztellman: callenbot: oh, in academia FRP is a big wanky black hole

14:04 bbloom: ztellman: you can say that again.

14:04 hyPiRion: callenbot: It's all the formal words, I think

14:05 monoid? catamorphism? zygohistomorphic prepromorphism?

14:05 It frightens people.

14:05 callenbot: I was speaking of the code.

14:06 I don't pay any attention to category theory.

14:06 bbloom: hyPiRion: i think it's different than frightening people. i think it's actually a cognitive burden to have such big words

14:06 gfredericks: monoid is six characters

14:06 monad is even shorter

14:07 bbloom: monoids are quite easy to understand :-P monads have a different problem

14:07 gfredericks: maybe we should rename monads something longer and scarier so people will stop being improperly interested

14:07 bbloom: lol

14:08 gfredericks: endofunctorial-monoid maybe

14:08 (EFM)

14:08 bbloom: it's like the word "blog"

14:09 there were news sites and personal home pages with regular updates long before the word "blog"

14:09 hyPiRion: Maybe we should just enterprisify it

14:09 bbloom: if you had called it a "automatic personal news publishing home page" it would have never caught on lol

14:09 hyPiRion: ConnectionListenerMonoid

14:09 There we go, now we can ship it.

14:10 ztellman: btw, since some people here have been down the FRP rabbit hole

14:10 anyone aware of something that deals with how FRP interacts with TCP backpressure?

14:10 I've searched in vain

14:11 bbloom: ztellman: huh?

14:11 ztellman: bbloom: FRP in a server context

14:11 amalloy: ztellman: the connection between those is hard to see, even knowing that you must mean in aleph/lamina. what's a more specific part of the problem?

14:12 ztellman: so I was looking at all the various versions of Rx

14:13 it's not clear to me if there's a story for when you can't reach the end of the FRP chain synchronously

14:13 i.e. there's a queue, or pending write over the network, etc.

14:14 the main problem here is that I'm not even sure what the right terminology here is, as maybe evidenced by my question

14:14 bbloom, amalloy does that make any more sense?

14:14 bbloom: ztellman: i know of many of the words & technologies you're talking about, but i have no clue what you're asking....

14:14 ztellman: rewind and simplify

14:15 ztellman: or maybe provide a concrete example

14:16 amalloy: i think so, but i'm definitely not qualified to answer it myself

14:16 ztellman: sure, trying to figure out the best way to unwind this

14:16 ok, simplest example:

14:16 you're a proxy between two different computers

14:16 you're taking messages from one, doing some sort of transformation, and forwarding it to the other

14:17 in general, these messages can be considered in isolation

14:18 but if the bandwidth of the producer outstrips the consumer, you start to run out of memory as the messages back up

14:18 callenbot: ztellman: wouldn't backpressure throttling mean the promises block longer?

14:18 bbloom: ztellman: aaah ok, i now think i get what you're asking

14:18 ztellman: callenbot: promises representing what, exactly?

14:19 callenbot: deliverable result of some sort.

14:19 ztellman: bbloom: my reading of FRP is that each value propagation is calculated in isolation

14:19 augustl: hmm, is it true that the routing module is what adds a "href" attribute to all "a" tags?

14:19 err, wrong channel

14:19 bbloom: ztellman: so FRP is a totally overloaded and completely useless acronym

14:19 ztellman: haha, ok

14:19 bbloom: ztellman: in this case, you're talking about Push Streams

14:19 push sequences

14:19 microsoft's Rx

14:19 etc

14:19 ztellman: correct

14:20 bbloom: what FRP originally meant and is most commonly discussed in the literature as is for dataflow systems basically

14:20 ztellman: so to greatly simplify my question: what happens with push streams when there's no more room to push?

14:20 bbloom: let's ignore ALL that and talk about push sequences

14:21 ztellman: so yeah, this is a distributed systems problem

14:21 you have to choose a policy

14:21 block the sender (how?), drop messages (which?), etc

14:21 push sequences are fundamentally no different than sockets in their design space

14:22 ztellman: sockets in the generic sense?

14:22 bbloom: yeah, like unix sockets, but more similar to zeromq sockets or message passing sockets

14:22 one problem IMO with Rx is that the pipeline is opaque

14:22 ztellman: yes, agreed

14:23 bbloom: you can't look inside each phase of the transformation & modify it

14:23 which is a problem w/ functions too, but it's not as big a problem cus functions rarely have internal state

14:23 if you add an atom to cache stuff in your function, then suddenly your function is harder to work with, debug, etc

14:24 push sequences inherently have some state/context and you can't see that easily

14:24 one school of thought is that you don't NEED to see it

14:24 that's the zeromq way

14:24 i highly recommend reading http://zguide.zeromq.org/page:all

14:25 it's long, but it has some reeeaaaally good explanations about common patterns for robust distributed communication designs

14:25 ztellman: I read it a ways back

14:25 but i'll take another look, thanks

14:25 borkdude: just checkin, this should be safe? db.config just contains a map with some settings (clojure.edn/read-string (slurp "resources/db.config"))

14:26 ztellman: specifically w.r.t. the policies you mentioned above, though

14:26 is there a first-class representation of that in Rx?

14:26 amalloy: borkdude: yes, that cannot execute any code as far as i know

14:26 bbloom: i dunno

14:26 zero mq has different types of sockets & the pairing of sockets dictates policy for things

14:27 ztellman: ok, cool

14:27 I'm looking for prior art in that space, I think I glossed over that part of it before

14:27 in zmq, that is

14:27 bbloom: in theory, you could create Rx components that essentially map to the buffering and blocking policies of zeromq

14:28 the tables on this page summarize: http://api.zeromq.org/3-2:zmq-socket

14:29 ztellman: perfect, thank you

14:30 on a tangential note, could you characterize the difference between push sequences and standard dataflow?

14:30 I think I've gotten them conflated in my head

14:31 bbloom: push sequences have a linear notion of time, dataflow as an instantaneous notion

14:31 jcromartie: any reason to use (Double. x) over (Double/parseDouble x) ?

14:31 technomancy: jcromartie: I think the former accepts things that are already doubles?

14:31 at least for Integer that's how it works

14:32 bbloom: ztellman: FRP dataflow systems tend to have concepts like signals, behaviors, etc. push sequences basically have subscribe/unsubscribe/push

14:32 ztellman: it's sorta like comparing lazy seqs to lazy evaluation

14:32 only it's push seqs to push evaluation

14:33 ztellman: bbloom: ok, so behaviors vs streams

14:33 bbloom: i guess so

14:33 like i said, FRP is an overloaded and muddled term

14:33 ztellman: and I've read a small subset of the literature, so I'm just trying to line things up to terminology I've already heard

14:33 TimMc: ~frp

14:33 clojurebot: FRP is Functional Reactive Programming, or maybe fiberglass reinforced plastic (and sometimes Functional *Relational* Programming, just to be confusing)

14:33 tomoj: a coworker decided he needed to make sure the internet (which was working) was going to work, so decided to fuck with the router. during an FRP discussion :(

14:34 ztellman: bbloom: anyway, thanks

14:34 TimMc: tomoj: We solved the whole thing. Sorry you missed it!

14:34 tomoj: the jonathan edwards stuff was "coherent reaction"?

14:35 true_droid: can one add fields to a record in runtime?

14:35 bbloom: ztellman: yeah, my pleasure. i hadn't made the zeromq analogy explicit in my head yet, so that was helpful to me too

14:36 TimMc: true_droid: Basis fields? Probably not.

14:36 true_droid: (assoc rec :newfield value)

14:36 tomoj: subscribe/unsubscribe/push seems like an unsound basis for push seqs to me

14:36 jcromartie: is there anything that does (f m {:foo g}) => {:foo (g (get m :foo))}

14:36 bbloom: tomoj: sure, i was far oversimplifying

14:37 tomoj: also, i really dislike the suscribe/unsubscribe thing in general, since it introduces a resource management concern

14:37 hyPiRion: jcromartie: update-in

14:37 ztellman: bbloom: what's the alternative?

14:37 hyPiRion: ,(update-in {:foo 1} [:foo] inc)

14:37 clojurebot: {:foo 2}

14:37 TimMc: true_droid: Sure. Try it.

14:38 bbloom: ztellman: i don't have a good one honestly. but it would look a lot more like the -> macro :-P

14:38 ztellman: so check out this file https://github.com/brandonbloom/fipp/blob/master/src/bbloom/fipp/transduce.clj

14:38 true_droid: TimMc: I'm curious how it works. If a record definition generates a Java class. Does associating new field creates a new subclass for it?

14:38 bbloom: ztellman: i'm basically leveraging the eagerness of reducers to emulate push sequences

14:39 ztellman: bbloom: transduce can't actually be a real verb, can it?

14:39 bbloom: map-state and mapcat-state enable reducers to have state

14:39 jcromartie: hyPiRion: no, I mean more like, {:foo 1 :bar "2"} {:foo str :bar #(Integer/parseInt %)} => {:foo "1" :bar 2}

14:39 bbloom: $define transduce

14:39 amalloy: $dict transduce

14:39 lazybot: amalloy: verb-transitive: To convert (energy) from one form to another.

14:39 bbloom: eh, lol

14:39 anyway

14:39 ztellman: the interesting bit is the state

14:40 it's encapsulated in that atom

14:40 but there isn't really an easy way to peek at it, which is problematic

14:40 TimMc: true_droid: It handles the basis keys specially and stores all the other key-val pairs in a regular map.

14:40 bbloom: ztellman: but look here: https://github.com/brandonbloom/fipp/blob/master/src/bbloom/fipp/printer.clj#L203-L208 you'll see how i stitch together the pipeline

14:40 true_droid: TimMc: I see, thanks!

14:40 hyPiRion: jcromartie: oh

14:40 bbloom: ztellman: it's brain dead simple lazyness, but the t/each sucks out of the pull sequence & then starts pushing into the reducers

14:41 ztellman: this is a dramatically simplified example b/c the push source is actually a pull source

14:41 i'm pushing to the console, but i'm pulling lazily from a document

14:41 ztellman: bbloom: right

14:41 bbloom: when you have a real push source, things get messy.

14:41 amalloy: jcromartie: if you're interested in a little type theory, then that's the basic operation of an applicative functor

14:41 hyPiRion: ,(merge-with #(%2 %) {:foo 1 :bar "2"} {:foo str :bar #(Integer/parseInt %)})

14:41 clojurebot: {:foo "1", :bar 2}

14:42 hyPiRion: But that's not exactly what you want, really.

14:42 ztellman: bbloom: my domain here is (broadly) network programming

14:42 amalloy: hyPiRion: it sure is clever, though

14:42 bbloom: ztellman: yeah, so i guess the idea that strikes me is that you don't have a resource management problem until you hook up your Rx chain to the source

14:42 ztellman: which means that data sources and sinks appear and disappear all the time

14:43 bbloom: if you define a chain inductively, you have to attach to the source immediately

14:43 jcromartie: amalloy: interesting

14:43 ztellman: bbloom: that assumes the chain's topology is not dependent on the messages themselves

14:43 hyPiRion: jcromartie: You could probably use reduce-kv here actually

14:43 jcromartie: hyPiRion: yeah, that's closer, I am just not sure if it already exists :P yeah

14:43 ztellman: or on other resources which you don't have control over, like client connections

14:44 I think that trying to avoid the resource management problem narrows the useful domain pretty drastically

14:44 tieTYT: oh man: (-> req :params :length)

14:44 bbloom: ztellman: if i were to take a design crack at this, i'd ban state inside each stage of the push sequence, but give those states an ID

14:44 tieTYT: I like that better than get-in

14:44 bbloom: ztellman: i'd also ban connecting to a source or sink until the end

14:44 and then the sources, sinks, and state would live OUTSIDE the chain

14:44 hyPiRion: ,(reduce-kv (fn [m k v] (if (m k) (update-in m [k] v) m)) {:foo 1 :bar "2"} {:foo str :bar #(Integer/parseInt %)}) ; jcromartie

14:44 clojurebot: {:foo "1", :bar 2}

14:44 tieTYT: i remember when I learned get-in, I didn't know what -> was, but nwo that I do, I think using it is easier to read

14:45 hyPiRion: It was way prettier when I thought it out in my head though.

14:45 jcromartie: :)

14:45 I'd say that's pretty close, technically I want to throw out keys missing from the key-fn map

14:45 bbloom: ztellman: i'll be back in a bit

14:45 ztellman: bbloom: ok, I've got a question relating to that design

14:46 but it can wait

14:46 hyPiRion: jcromartie: so a select-keys before or after

14:46 do*

14:49 borkdude: in a clojure project, a .clj is not loaded until needed… right?

14:49 technomancy: borkdude: user.clj is the only thing loaded implicitly

14:50 borkdude: I mean, is it safe to put a lobos script somewhere, without the risk it being run, when no other namespaces refers it?

14:50 technomancy: borkdude: `lein compile :all` could trigger it

14:50 don't put side-effects in the top-level

14:51 gfredericks: &foo should be a naming convention for anaphoric macros

14:51 lazybot: java.lang.RuntimeException: Unable to resolve symbol: foo in this context

14:51 borkdude: technomancy if I define some actions as functions, that would save me then

14:51 gfredericks: or for the locals they introduce rather

14:51 technomancy: borkdude: right

14:51 amalloy: gfredericks: that's an interesting proposal. i'm surprised to find i don't immediately hate it

14:51 gfredericks: amalloy: lol

14:52 technomancy: if lobos doesn't already tell you to put your changes in defns then that's worrisome

14:52 gfredericks: it came to me earlier when the fellah wanted an arguments map

14:52 Raynes: amalloy: April fools.

14:52 hyPiRion: Raynes: I was about to write that too

14:52 technomancy: gfredericks: I saw some anaphoric elisp macros that I totally didn't hate, but I think that was because elisp's lambdas are more verbose

14:53 gfredericks: someone told me elisp doesn't have closures

14:53 hyPiRion: technomancy: lambda-as-lambdas?

14:53 technomancy: gfredericks: it didn't until like two years ago?

14:53 amalloy: technomancy: has it really been two years?

14:53 borkdude: gfredericks there is a setting that you must have at the top of an elisp file to turn lexical closures on

14:53 gfredericks: technomancy: at least it beat java?

14:54 technomancy: amalloy: not sure; I've been running trunk for so long

14:54 gfredericks: ziiiiiiing!

14:54 hyPiRion: gfredericks: What are you saying, you have Clojure

14:54 JVM got it, that's enough for me

14:54 borkdude: technomancy it tells me to do that, but to activate the changes, I want to have some reference script for when I need to execute the db creation in the future or with other dbs

14:57 hyPiRion: borkdude: it's probably safer to leave it out of your clj and java source paths

15:04 bbloom: ztellman: i haven't thought deeply about that design, so i offer nothing more than a willingness to think through it with you :-P

15:05 ztellman: bbloom: understood

15:05 it's interesting, though, that your design is actually pretty 1:1 with how riemann is implemented, as I understand it

15:05 bbloom: haven't seen riemann. googled it. by aphyr on github?

15:06 ztellman: correct

15:06 http://riemann.io/

15:06 bbloom: looking at it now

15:06 ztellman: he's a coworker, we've had a few design discussions along these lines

15:07 bbloom: the interesting thing is that once you hook up to a source, you've got a resource management problem

15:07 ztellman: in this case, everything flows through the same topology, so it's just a question of how many sources are feeding into the same thing

15:07 it's a constrained use-case, so I'm not sure what works there would work elsewhere

15:08 the question I wanted to ask had to do with something I have in lamina, though

15:08 basically, it does split-apply-combine on streams of data

15:09 so every time a message comes in with a new facet, a whole new chain of transforms is built on the spot

15:10 I've spent a lot of effort on making the topology dynamic, thread-safe, able to do its own resource management, etc.

15:10 a question I sometimes explore is whether that was strictly necessary

15:10 bbloom: ztellman: does the topology itself really need to be dynamic? or can there be a static node w/ a dynamic subtopology?

15:10 ztellman: bbloom: in this case, the latter would probably suffice

15:10 bbloom: ie can i have source->transform->sink and then transform has some state which is a subtransform

15:11 yeah, i'd probably go with that :-P

15:11 ztellman: fair enough

15:11 bbloom: your state then just gets stored in a tree & you have a transform node that acts as a state machine which switches the underlying topology

15:12 analogous in some way to defunctionalization :-)

15:12 you have a higher order transform & you can realize it as a non-higher order one by inlining

15:14 ztellman: yeah, predefined chains of transforms can be useful

15:14 I've got some stuff which will split apart chains into distributable and non-distributable pieces, so you can process streams across multiple processes

15:14 bbloom: in theory, you can just make the root transform always be such a dynamic transform

15:15 so then you just always store the topology itself in the state atom

15:16 which i guess is what is happening with function composition. you're storing the topology in the Fn objects

15:16 ztellman: bbloom: yeah, but that's not introspectable in any sane way

15:16 bbloom: agreed

15:16 ztellman: have a first-class representation of the topology is really useful

15:16 bbloom: sure, and by the same token, i really wish i could introspect functions lol

15:17 ztellman: I wish I could introspect on how lazy-seqs are consumed, so I can tell if someone's holding onto the head

15:17 bbloom: the nice thing about function composition is that you get an evaluator for "free"

15:18 ztellman: I guess you could do something with weak refs, there, but I'm not masochistic enough to try

15:18 borkdude: argh, why does lobos want me to have the migrations in a namespace called lobos.migrations

15:19 tomoj: but do you want to say (i'm-consuming! some-lazy-seq) or whatever?

15:19 ztellman: tomoj: no, but if you have a topology representing where data's going, you don't need to

15:19 tomoj: but then you can't just do (first coll), right?

15:19 or can you have it both ways

15:20 bbloom: ztellman: even the haskell folks have no idea what to do about space leaks: http://www.haskell.org/haskellwiki/Memory_leak#Detection_of_memory_leaks

15:20 ztellman: tomoj: not with immutable data structures, as far as I can tell

15:21 if you forced each consumer to have its own queue, which it consumed at its own rate, you could tell how much data is "in flight"

15:22 tomoj: why is having a first-class topology representation valuable? not disagreeing, just curious about the details

15:22 obviously those beautiful dot graphs are great

15:22 ztellman: tomoj: I just like pretty pictures :)

15:22 bbloom: tomoj: two things

15:23 ztellman: tomoj: one is that the code isn't necessarily a direct representation of what's happening to the data

15:23 bbloom: it gives you somewhere to extract local state to

15:23 2) it enables debugging, etc

15:23 the topology EXISTS somewhere

15:24 it has to be reified in some way at some level

15:24 generally tho that level is just inside the functions as compiled

15:24 ztellman: bbloom: I defy you to infer the data topology of lazy-seqs via the object graph

15:24 bbloom: it's impossible

15:24 lol

15:24 but it exists

15:24 ztellman: oh, sure

15:24 bbloom: ok not impossible

15:24 tomoj: I was thinking the debugging benefit is primarily for operational issues

15:24 like lazy seq realization

15:24 bbloom: but you'd have to decompile bytecode lol

15:25 bdesham: I have a web app running with ring and jetty. what's the best way to run the server as a background process (so that I can log out of my shell with it still running)?

15:25 ztellman: tomoj: one is that it lets you understand what your code actually describes

15:25 tomoj: but you wouldn't need a topology graph for code working with only, say, vectors?

15:25 ztellman: function composition over lazy seqs can happen all over the place

15:25 bbloom: if i had my way, everything would be introspectable at all times :-P

15:25 ztellman: the net effect of that composition is very difficult to infer

15:25 tomoj: or maybe it'd still be helpful

15:26 ztellman: tomoj, if there's only a small number of transforms, and one source, and one destination, it's maybe not all that useful

15:26 because that can be described by a (->> s …) form

15:26 but there are some issues there, too

15:26 tomoj: transform/source/destination seems to imply some operational trickiness

15:27 ztellman: tomoj: don't pay too much attention to my terminology

15:27 tomoj: ah, right, if source is a vector, destination is a vector, and transforms are just functions. still could be nice to get a graph I suppose..

15:28 ztellman: tomoj: basically in the simple case it doesn't harm anything

15:28 in the complex case, it's invaluable

15:28 bbloom: aside: Rx has this concept of schedulers that is worth studying too

15:29 ztellman: it also lets you solve the resource management problem bbloom was mentioning, to an extent

15:29 bbloom: in theory, some intermediate step in the sequence can autonomously decide to emit an event w/o input from an upstream source

15:29 ztellman: since you know whether there are any remaining consumers for any given subset

15:29 bbloom: but in deeper theory, that's just getting an event from another source: a timer

15:30 ztellman: bbloom: yeah, in lamina all nodes can emit messages at any time

15:30 using pretty much the same mechanism you describe

15:32 anyway, tomoj, in general adding introspection capability is something you should design for

15:33 bbloom: ztellman: note however that introspection often (not always) incurs substantial runtime costs

15:33 mabes: speaking of Rx... has anyone here played around with netflix's RxJava (https://github.com/Netflix/RxJava)?

15:33 bbloom: however it is much much much harder to design OPTIONAL introspection :-)

15:33 true_droid: anyone knows of alternative clojure implementations in the works? I've heard of pyclojure

15:34 curious to know if there's anything else that fwould ree clojure from jvm

15:34 Raynes: Whoa

15:34 ztellman: bbloom: I think this particular domain is really friendly to introspection

15:34 Raynes: That f really ran off on you didn't it true_droid

15:34 true_droid: yeah

15:34 bbloom: ztellman: assuming you're writing server software & are likely IO bound, then yeah, for sure

15:35 ztellman: bbloom: I dunno, I've made a thread-safe dynamic topology that had to acquire locks, etc. and it take about 40ns per node

15:35 when propagating

15:35 bbloom: how many nodes do you typically have?

15:35 ztellman: well, depends on the application

15:36 bbloom: 10, 100, 1000, 10000?

15:36 ztellman: the server I was describing at clojure/west had about 500k, but not every node gets every message

15:36 bbloom: that's a shitload of nodes lol

15:36 i'm not even sure how i'd use that many nodes. is that like one per user?

15:36 ztellman: it's an extreme case, I was partially using it to stress test the mechanism

15:37 nah, it's a streaming analysis of structured data

15:37 tgoossens: I'm looking at rich hickey's ant demo. https://gist.github.com/spacemanaki/1093917#file-ants-clj-L45 . What is the reasoning behind the following documentation of the "move" function: "moves the ant in the direction it is heading. Must be called in a

15:37 transaction that has verified the way is clear"

15:37 ztellman: hierarchical code timings

15:37 tgoossens: Why not put the transaction in there it if it has to be put in a transaction anyway ?

15:37 bbloom: oh right i saw your talk

15:38 ztellman: so that's a distributed 500k nodes? or all in one process? or what?

15:38 nDuff: tgoossens: Because the check has to be inside the same transaction.

15:38 ztellman: so basically each timing is analyzed about half a dozen different ways, and within each it's getting quantiles, rolling sums, etc

15:38 one server

15:38 tgoossens: nduff: makes sense!

15:38 ztellman: it's distributable, but in my use case it's not necessary

15:38 bbloom: ok got it

15:38 that's a big number :-P

15:38 ztellman: they're lightweight nodes :)

15:39 tgoossens: nduff: stupid me. The documentation actually said that:p "Must be called in a

15:39 transaction that has verified the way is clear""

15:39 ztellman: but yeah, I'm looking at a constrained query language that will be distributable via storm, or something

15:39 bbloom: neat

15:39 ztellman: it's got promise, I think

15:40 I tried using it to measure a full map/reduce job without client-side sampling, got about 15gb/minute via UDP packets

15:40 which have a maximum size of 64k, btw

15:40 that made it fall over

15:40 tieTYT: how would you count the number of 0s in a vector? I used this: (reduce #(+ %1 (if (= %2 0) 1 0)) 0 vector)

15:40 ztellman: so there's definitely a threshold at which you want to distribute this sort of analysis

15:40 amalloy: (count (filter #{0} v))

15:41 tieTYT: ah yeah that's better

15:41 tomoj: how do you represent a dynamic topology (for e.g. the purpose of rendering to dot)?

15:41 bbloom: amalloy: tieTYT: might prefer zero?

15:41 (count (filter zero? v))

15:41 ztellman: tomoj: check out lamina.walk

15:41 amalloy: bbloom: doubtful

15:41 bbloom: heh ok then

15:41 tieTYT: so there you used a set as a function?

15:42 ztellman: tomoj: though that's just some sugar on top of the underlying data structure, no mechanism for making sense of a topology of 500k nodes

15:42 amalloy: &(zero? [])

15:42 lazybot: java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number

15:42 pl6306: What is an easy way of generating [[year quarter] ...] e.g. [[1993 1] [1993 2] [1993 3] [1993 4] [1994 1] [1994 2] ... ?

15:42 bbloom: amalloy: oh! wow. that's annoying

15:43 nDuff: pl6306: lazy? bounded? ...?

15:43 bbloom: surely the answer to that question is "false" lol

15:43 true_droid: what does reify return? can't find it mentioned in the reify doc string at all

15:43 nDuff: pl6306: ...well, if you really want it to be a vector on the outside, it can't be lazy...

15:43 pl6306: not lazy bounded just from 1993 to 2013

15:43 hyPiRion: ,(for [y (range 1993 2013) q (range 1 4)] [y q]) ;?

15:43 clojurebot: ([1993 1] [1993 2] [1993 3] [1994 1] [1994 2] ...)

15:44 amalloy: ,(map vector (mapcat #(repeat 4 %) (range 1993 2014)) (cycle [1 2 3 4]))

15:44 clojurebot: ([1993 1] [1993 2] [1993 3] [1993 4] [1994 1] ...)

15:44 amalloy: but hyPiRion's is better

15:44 pl6306: Nice thanks!

15:44 Starting to get the hang of this.

15:44 tomoj: ztellman: is the 'dynamic' part represented in there? or do you just call node-data at various times to see what the topology looks like at different times?

15:45 ztellman: tomoj: oh, I see, yeah, you're just sampling it

15:45 hyPiRion: pl6306: might want to replace 2013 with 2014 in my code, if you meant "up to and including 2013"

15:45 ztellman: tomoj: you can hook into callbacks for when nodes close, etc.

15:46 tomoj: if you want a fully consistent view you can recursively lock each node in the topology

15:47 but by default you're not getting one, because the topology doesn't change atomically

15:47 at the global level, anyway

15:48 borkdude: hmm, lobos uses an old version of java.jdbc (1.1)

15:48 (0.1.1)

15:49 tieTYT: i think one of the hardest things for me to take advantage of from a java/haskell background is that I can use non-booleans in an if statement

15:50 tomoj: would it be wrong to call that a bit less than first-class?

15:50 not really sure what 'first-class' means in this context

15:50 borkdude: tieTYT many dynamically typed languages have this, javascript, common lisp, etc

15:50 tomoj: though if that's less than first-class it may be impossible to do any better :(. damned 'dynamic'

15:50 ztellman: tomoj: it depends on what you're trying to do

15:51 tieTYT: borkdude: yeah, I don't usually use that feature though

15:51 borkdude: I guess C has it too?

15:51 tgoossens: Why was the name "agent" chosen for well.. clojure agents?

15:51 ztellman: one way to "sample" the topology is to send a message through it

15:52 the return value of (enqueue ch …) will give you the return value of each endpoint, or an async-result representing the eventual return value

15:52 but the topology may be changing around the message as it propagates

15:52 especially if it's queued anywhere

15:53 which topology matters? the one that was in place when the message was enqueued, or the one that's in place when it arrives at its various destinations?

15:53 Guest93639: ok I am confused. I printed out the value of my protocol var, apparently the :impls has a bunch of identical-looking class keys with different values. how does that happen? https://www.refheap.com/paste/13179

15:53 ztellman: or the frankenstein combination of the two that the message encountered as it was being propagated?

15:54 though again, if you want some guarantees of atomicity, those are possible if you want to lock down the topology yourself

15:54 I haven't encountered a production situation where that's useful, though

15:55 tieTYT: where/how can I find the documentation on using a set as a function?

15:55 tomoj: would be sweet though to make an animation of the topology changing while following a message

15:55 amalloy: jweiss_: you have redefined a defrecord or deftype multiple times at the repl

15:55 brehaut: tieTYT: clojure.org probably. (set key) is equivalient to (contains? set key)

15:55 amalloy: there are now multiple versions of that class, each with a registered implementation of the protocol

15:55 brehaut: almost equiv

15:56 jweiss_: amalloy: strange since there is no way to tell them apart that i can see

15:56 amalloy: jweiss_: they have different classloaders

15:57 tieTYT: brehaut: ok

15:57 brehaut: tieTYT: http://clojure.org/data_structures#Data%20Structures-Sets

15:57 tieTYT: very bottom

15:57 jweiss_: amalloy: do you have a recommendation to avoid this and/or fix it? just blow away the protocol var and re-compile?

15:57 amalloy: jweiss_: i recommend not caring

15:57 ztellman: tomoj: feel free to mess around with it a bit if you're curious

15:58 amalloy: it will not cause any problems whatsoever

15:58 jweiss_: amalloy: it seems to be causing problems.

15:58 ztellman: I'm probably going to extract the graphviz stuff into its own library

15:58 amalloy: jweiss_: really? what problems?

15:58 jweiss_: i'm getting an error that one of my records doesn't implement one of the protocol methods.

15:58 tieTYT: thanks

15:58 ztellman: maybe you'll build up some opinions on how to best do that

15:58 jweiss_: but it does, it's just choosing the wrong class

15:58 brehaut: tieTYT: contains? returns a bool, where as a set returns the object if its found. sets with nil or false can be funny if you use them for existence tests without using contains?

15:59 Raynes: brehaut: You. Hi.

15:59 brehaut: hi Raynes

15:59 amalloy: jweiss_: that happens if you re-evaluate the defprotocol form

15:59 tieTYT: i see

15:59 amalloy: you defined a new protocol with the same name, and the previously-existing records implement the old version, not the new one. if you re-evaluate the records, new classes will be produced that implement the new one

15:59 jweiss_: amalloy: yeah, that's why i wanted to know how to avoid/fix - so i guess i shouldn't have recompiled the namespace with that defprotocol?

16:00 amalloy: jweiss_: make sure to let technomancy know: he enjoys protocol schadenfreude

16:00 jweiss_: hm ok the defprotocol and defrecords are in the same ns, so i guess i should not eval forms, just recompile the whole ns.

16:00 Raynes: The shit.

16:01 amalloy: That's the second time I've heard that word in two days.

16:01 And yesterday was the first time I'd heard it in my life.

16:01 technomancy: amalloy: it's true

16:01 jweiss_: schadenfreude?

16:01 amalloy: Raynes: http://www.damninteresting.com/the-baader-meinhof-phenomenon/

16:01 Raynes: So either you're a callenbot copycat or that's a hell of a coincidence.

16:02 TimMc: ...or you're a young 'un.

16:02 amalloy: Raynes: it's a word, man. people using words you don't know is just a sign you're uneducated, not a sign from god

16:03 Raynes: Thanks guys.

16:03 TimMc: <3

16:04 jweiss_: oh man this sucks, why didn't anyone warn me about protocols

16:04 technomancy: I did!

16:04 amalloy: clojurebot: technomancy is <jweiss> oh man this sucks, why didn't anyone warn me about protocols

16:04 clojurebot: c'est bon!

16:04 technomancy: you just weren't listening

16:05 in your defense, you might not have been on IRC at the time

16:05 jweiss_: lol

16:05 i don't suppose i can save my fellow co-workers by somehow defonce'ing something

16:06 so that when they edit something else in this namespace they won't end up chasing their tail

16:06 TimMc: jweiss_: http://www.mspaintadventures.com/sweetbroandhellajeff/comoc.php?cid=001.jpg

16:06 pl6306: Why does (map #(load-sec-quarterly-master-idx (first %1) (last %1)) (vec (for [y (range 1993 2012) q (range 1 4)] [y q]))) in the REPL? But (defn load-historical-master-idx  (map #(load-sec-quarterly-master-idx (first %1) (last %1)) (vec (for [y (range 1993 2012) q (range 1 4)] [y q])))) throws an IllegalArgumentException Parameter declaration map

16:06 should be a vector  clojure.core/assert-valid-fdecl?

16:06 jweiss_: TimMc: lol

16:07 amalloy: pl6306: you forgot the args to defn

16:07 technomancy: TimMc: nice

16:07 pl6306: ok so I should put in []

16:08 amalloy: TimMc: what on earth

16:08 jweiss_: i don't know which one is hella jeff, but probably the one falling down the stairs since my name is also jeff

16:09 although the other guy does refer to him as "bro" so maybe not.

16:12 cdh473__: i just noticed: ".../comoc.php..."

16:18 TimMc: amalloy: Intentionally bad webcomic. I think it started as a joke in the MS Paint Adventures forums.

16:21 jweiss_: alright I am still baffled. when i recompile a namespace it seems like not everything gets redefined. i still have old versions of records still laying around.

16:27 TimMc: Yeah, they should have different classloaders.

16:29 jweiss_: TimMc: should, or that's why i'm having problems?

16:30 TimMc: The latter.

16:30 Not "this is a desirable scenario".

16:33 maacl: Considering a porting the GUI part of ants.clj to Clojurescript/canvas and back it by a Clojure backend. Would fetch (by Chris Granger) be my best choice for syncing the world from the backend to the frontend?

16:35 jweiss_: TimMc: the repl seems to be telling me that both the protocol impl key and the new record i just created, have teh same classloader. and the impl also has a definition for the :product method. yet when i try to call it, it doesn't work

16:35 https://www.refheap.com/paste/13184

16:36 i wonder if this has anything to do with using keywords as protocol method implementations?

16:36 i mean, they are functions, so i figured that should be fine.

16:36 sandbags: clojure newb here, is there a legitimate reason why (load-file "path/to/file.clj") might hang for minutes at a time?

16:36 brehaut: (while true) is a toplevel form

16:36 sandbags: oh, I googled up "load-file" so I could totally be doing this wrong... i'm in a lein reply btw

16:36 jweiss_: not legitimate, no

16:37 sandbags: jweiss_: okay, this perhaps explains why LightTable has stopped working for me

16:37 thanks

16:37 * jweiss_ never did get lighttable working

16:37 jweiss_: last i checked it wasn't compiled in a way that would run on my system

16:37 sandbags: is there any kind of logging that i can get clojure to do that might let me figure out why

16:38 i note in passing that, until about 7-8 hours ago, i wasn't having a problem

16:38 technomancy: sandbags: binary search is your best bet

16:38 sandbags: technomancy: you're thinking it's something about my source file?

16:38 technomancy: sandbags: if it's happening in lein repl, yeah. if it's in light table it could be something else.

16:38 jweiss_: eval forms one at a time in that file :)

16:39 technomancy: sandbags: also: load-file is very low-level; you should use require

16:39 sandbags: technomancy: LT was hanging on starting up a repl for the file, CG asked me to try in lein-repl

16:39 lein-repl starts

16:39 but then i figured that probably wasn't testing anything much

16:39 ah, ok

16:41 scottj: maacl: maybe look at pedestal

16:42 maacl: scottj: thanks, although looks heavy for just keeping a datastructure in sync

16:44 sandbags: IIReadC clojure returning 'nil' signifies success, right?

16:44 returning nil from a funciton such as 'require' i mean

16:45 amalloy: sandbags: more like "no meaningful return value"

16:45 generally it means nothing broke, though. certainly that's true for require and its friends

16:45 sandbags: thanks

16:49 Bronsa: sandbags: that's not always true though http://sprunge.us/EQVL

16:49 TimMc: sandbags: Clojure functions *have* to return something. (Or throw an exception, or call System/exit, I suppose...) If your function doesn't have anything useful to return, nil is the standard thing o use.

16:50 sandbags: thanks guys

16:55 okay so definitely something in the code hanging the repl, probably i have a bracket misplaced or something

16:55 although... i'd expect some kind of syntax error or something

16:56 amalloy: sandbags: well, as i think someone suggested earlier, you might have (while true) at the top-level or something like that. or light table could have a bug; it would hardly be the first

16:57 sandbags: https://gist.github.com/mmower/2fb5f8ba95382084b4e5

16:57 amalloy: it's not LT, i'm in pure lein repl now

16:57 without the comments, this is hanging my repl

16:58 nDuff: You're decrementing i, but testing n

16:58 so, yes, no surprise that that's hanging.

16:58 sandbags: ah, damn

16:58 amalloy: nDuff: he's not calling that function, allegedly

16:58 oh, but the println is there

16:58 nDuff: Exactly.

16:58 sandbags: yeah

16:58 the println

16:58 which is probably what i added that triggered this whole thing

16:59 amalloy: sandbags: i don't know what LT recommends, but in any other clojure setup it's a bad idea to do anything but define functions at the topmost level

16:59 sandbags: but is so seemingly innocuous an action that when LT started to ahng

16:59 amalloy: i was really just playing around but, yes, i can see why this is recommended :)

16:59 nDuff: I _am_ somewhat surprised that LT doesn't have an easy way to interrupt a runaway execution

16:59 (which, for instance, emacs+nrepl will do easily)

17:00 sandbags: well the thing is in LT it *looked* like it was still starting the repl

17:00 Glenjamin_: every time i try LT it seems to hang for an unclear reason

17:00 sandbags: Glenjamin_: well it is 0.3 :)

17:00 Glenjamin: yeah, i intend to keep coming back to it

17:01 sandbags: in this case I am not sure what LT could do, since the nREPL underneath it has hung

17:01 well, been hung

17:01 jweiss_: ok i seem to be making headway here, having one protocol function point to another doesn't seem to work

17:02 eg (defprotocol MyProto (foo [x]) (bar [x])) (extend My.Class {:foo identity :bar foo})

17:03 dsop: hmm sqlkorma doesnt convert types and retursn everything as strings?

17:03 jweiss_: (bar (MyClass. "baz")) -> IllegalArgumentException No implementation of method: :foo of protocol: #'MyProto found for class MyClass.

17:04 but (foo (MyClass. "baz")) works.

17:05 luisgabriel: I'm having some issues related to performance on a simple example that I'm writting in clojure. probably I'm doing something very wrong. If someone can help me, here is the code: https://gist.github.com/luisgabriel/5287722

17:07 I'm trying to implement a simple search engine for text files

17:07 jweiss_: doh... /me should have referred to the protocol function using the var. (extend My.Class MyProto {:foo identity :bar #'foo})

17:07 that works

17:08 amalloy: jweiss_: ah, now that sounds like a protocol behavior that i consider a bug. if you capture a protocol function's *value* at the top level (as opposed to its var), then that function doesn't get updated

17:09 dsop: hmm okay korma doe sconvert the types :)

17:10 callenbot: I've come to realize that scala and go represent two extremes of design principles.

17:10 jweiss_: amalloy: i'm not sure how it should work

17:11 in this case, foo is a protocol function and at the time it's being extended there was no implementation for that type.

17:23 dsop: whats the easierst way if i have two list of intergers to find the disjoint set?

17:24 TimMc: dsop: Use some clojure.set operations.

17:25 dsop: TimMc: ah clojure.set/difference, thx

17:52 inhortte: Does anyone here know how to properly include local jars in a project with leningen2?

17:54 amalloy: ~repeatability

17:54 clojurebot: repeatability is crucial for builds, see https://github.com/technomancy/leiningen/wiki/Repeatability

17:55 technomancy: inhortte: lein-localrepo or s3-wagon-private depending on whether you're doing real work or just playing around

18:01 inhortte: technomancy -> I'm just playing around for now. :)

18:02 technomancy: localrepo is prolly fine

18:02 inhortte: I'll try lein-localrepo

18:02 technomancy: but also submit a bug report to whoever is giving you a jar that's not in a repo

18:02 because that's crazy

18:04 inhortte: technomancy -> it's this: https://github.com/macourtney/clj-crypto ... I wanted to play around with 'masques' (https://github.com/macourtney/masques).

18:04 technomancy: oh, if it's a clojure project you can just do `lein install`

18:06 inhortte: technomancy -> I am not going to read a bit of lein documentation. :)

18:06 antares_: shipped Money 1.0, a tiny library for dealing with moneyz and currencies http://blog.clojurewerkz.org/blog/2013/04/02/introducing-clojurewerkz-money/

18:08 pmonks: Step 1: develop Money 1.0

18:08 Step 2: ??

18:08 lazybot: pmonks: What are you, crazy? Of course not!

18:08 pmonks: Step 3: PROFIT!!!1

18:09 * pmonks couldn't resist. He now apologises profusely.

18:09 antares_: pmonks: my last name is Gnome

18:20 hyPiRion: The leprechaun in action.

18:20 technomancy: money 1.0? I dunno man; everyone knows it's not a good idea to use floats for currency. =)

18:20 antares_: technomancy: there is a BigMoney type :)

18:20 technomancy: heh; nice

18:22 hyPiRion: Still doesn't fix the issue, does it?

18:22 ,(/ 1M 3M)

18:22 clojurebot: #<ArithmeticException java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.>

18:23 technomancy: well, dividing money by money doesn't make sense

18:23 antares_: hyPiRion: it's Java at the core and it uses rounding modes for division, if that answers your question

18:23 hyPiRion: ah

18:23 antares_: all potentially lossy operations require you to specify a rounding mode and scale

18:23 hyPiRion: technomancy: by people, perhaps?

18:23 technomancy: hyPiRion: surely an integer?

18:25 hyPiRion: technomancy: sure, but ##(/ 1M 3) would still not be representable

18:25 lazybot: java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

18:25 technomancy: oh, true

18:30 inhortte: technomancy -> thanks, by the way. it worked fine.

18:32 technomancy: cool

18:36 angusiguess: Is there any clear reason this wouldn't be displaying the image I load? It seems to get the dimensions right. https://gist.github.com/angusiguess/26ec9f33eaefcc2d9d8d

18:36 si14: what's the meaning of "NullPointerException [trace missing]"?

18:38 technomancy: si14: I think that's a bug in the JVM's tiered compiler

18:38 amalloy: si14: that is the clojure runtime letting you know you're going to be sad when you try to debug

18:38 * si14 :)

18:39 si14: https://gist.github.com/si14/6781aa479e696b5690b9 here is the code

18:39 technomancy: technomancy/leiningen#1025

18:39 lazybot: -XX:+TieredCompilation destroys tracebacks -- https://github.com/technomancy/leiningen/issues/1025 is closed

18:39 * si14 38th line causes NPE when uncommented

18:40 si14: it will be somewhat OK if I'll see that "Hello world" printout

18:40 but I do not

18:40 * si14 and now I'm really sad panda :)

18:41 technomancy: try disabling tiered compilation?

18:42 * si14 technomancy: just a moment

18:46 * si14 technomancy: thanks a lot, now I have a "clojure.lang.Numbers.ops" info

18:47 si14: but I still don't get why that printout is missing.

18:48 technomancy: si14: I guess it's not in the comments there, but someone traced it down to a bug in the JVM

18:49 si14: technomancy: "it" = ?

18:50 technomancy: the lack of a stack trace

18:50 si14: technomancy: can you take a look at that snippet please?

18:51 * si14 I'm talking about printout on line 2.

18:51 technomancy: hm; that's very strange

18:51 si14: when I uncomment line 38 I get NPE (thanks to your advice it's now somewhat traced), but no printout.

19:41 technomancy: thanks for the help, anyway :)

19:47 Oddman: what's everyone's preferred library for web, when dealing with clojure?

19:47 and fav mysql lib?

19:49 technomancy: Oddman: I don't know if anyone in here will admit to using mysql by choice =)

19:49 Oddman: clojure community is too elite for it?

19:50 what's the storage medium of choice here?

19:50 * technomancy uses postgres unless he has a reason not to

19:50 technomancy: but clojure.java.jdbc in theory connects you to any DB supported by JDBC

19:51 Oddman: gotcha. And is that an ORM solution, or a preferred solution to an ORM implementation?

19:51 new to java, clojure.etc. so starting from scratch :P

19:51 technomancy: it's not an ORM, but it's a good starting point

19:52 Oddman: doesn't need to be an ORM, just curious as to options available

19:52 and for web - what is the preferred framework?

19:52 been looking at compojure, seems quite light

19:52 technomancy: it's the best

19:53 Oddman: heh

19:55 scottj: Oddman: maybe look at korma, clojureql, and pedestal if you want something else.

20:00 Oddman: having a look at clojureql, this irks me:

20:00 SELECT * FROM (SELECT users.* FROM users ORDER BY users.id asc) ORDER BY users.id desc

20:00 when calling multiple sorts

20:01 =\

20:13 callenbot: http://gearon.blogspot.com/2013/03/clojurescript-and-nodejs.html

20:37 xeqi: Glenjamin: have you found any other bugs with peridot? considering releasing a new version once I merge the two pull requests

21:53 tomoj: hmm, if reifying vars in cljs (even just :dynamic ones) is unacceptable due to performance reasons, how about just adding a new metadata flag :reified or :var or something?

21:54 then if you want bound-fn to preserve your var you have to ask for it

21:55 guess it would be pretty shitty to have some vars reified and some not

21:56 brehaut: tomoj: that authentic javascript experience :/

21:56 tomoj: but is dnolen ever going to say something other than "can't reify vars, performance cost" or "can't keep binding frames for :dynamic vars, performance cost"

21:56 are those performance problems even solvable?

21:57 only other option I see is some weird hack to get bound-fn working, to which dnolen will probably still say "performance cost"

21:58 gfredericks: tomoj: when you're running on a crazy-high-level host like JS there's a limit to how much further you can pile abstractions

21:58 tomoj: are you suggesting we may never get bound-fn?

21:58 callenbot: maybe clojurescript should be ported to asm JS

21:58 for SPEEEEEEEEEEEEEEEEEEEEEEEEEEEED

21:59 Oddman: lol

21:59 tomoj: that seems unacceptable, though apparently dnolen disagrees, and he probably understands better than I..

21:59 gfredericks: tomoj: that wouldn't surprise me, but I definitely don't have my head in the relevant issues, nor know enough about JS

21:59 tomoj: cljs won't even get decent numerics

21:59 callenbot: there's already an llvm clojure project, just point, aim at emscripten, and fire!

21:59 brehaut: lets have a pool: how long will it take dnolen to write a fast generational collector in JS

22:00 callenbot: brehaut: I'll take Never for $1000 Trebek.

22:00 tomoj: gfredericks: decent numerics?

22:00 callenbot: tomoj: it's all 754

22:00 gfredericks: tomoj: anything besides floats

22:00 callenbot: technically 32-bit unsigned ints are allowed to fly past

22:01 but anything larger is gonna be a double.

22:01 tomoj: sure

22:01 but that seems irrelevant :)

22:01 callenbot: JUS SAYIN

22:01 gfredericks: tomoj: it's something you'd want in a language but can't get cuz speedz

22:01 tomoj: I mean, yeah, there are some nice things we will never get

22:02 but is bound-fn one of them?

22:02 if so,

22:02 I dunno. it seems like a big problem

22:02 gfredericks: Raynes: okay I got codez this time

22:03 callenbot: tomoj: cljs is just a house of pain built on an indian graveyard called JavaScript.

22:03 gfredericks: Raynes: https://www.refheap.com/paste/13189

22:03 callenbot: tomoj: the bedsheets are okay if you ignore the blood.

22:03 * gfredericks doesn't know how to use laser apparently

22:04 tomoj: often the only option will be to write manual bound-fns for specific vars of interest

22:04 gfredericks: tomoj: you do a lot of dynamic vars in cljs?

22:04 tomoj: not a lot

22:04 gfredericks: tomoj: also a macro could make that as easy as (bound-fn [*foo* *bar*] ...fn stuff...)

22:05 tomoj: right, I guess it's not that big of a problem

22:06 cljs.test and any async framework can manually do that for the vars they need

22:06 then the user just gets the pain of dealing with any other vars they need

22:06 gfredericks: could you do this without reified vars?

22:06 have binding log what it's doing somewhere?

22:06 so bound-fn knows what vars are active?

22:07 sounds like that wouldn't affect normal perf

22:08 I'm assuming you didn't want some kind of actual thread-local thing

22:08 tomoj: that's what I've been trying to figure out, I think it should be possible

22:08 but not at no perf cost

22:08 gfredericks: are there JS runtimes where that's meaningful?

22:08 tomoj: unless you have a :bindable flag or whatever like I suggested above

22:08 gfredericks: tomoj: what's the perf cost?

22:09 tomoj: anyone using :dynamic who doesn't need bound-fn will suffer needlessly

22:09 gfredericks: Raynes: oh apparently I need to pass the zipper to l/fragment for some reason

22:09 tomoj: if you do it for all :dynamic (dnolen has already pointed out that this is a concern)

22:10 gfredericks: tomoj: but only at the time they use binding, right?

22:10 tomoj: right, or if they set!

22:10 gfredericks: it just makes binding itself a little slower?

22:10 oh hm

22:10 set! is supposed to only affect the local frame isn't it

22:10 tomoj: theoretically, which is another wrinkle

22:10 gfredericks: okay screw it all I give up

22:11 tomoj: since you probably don't want to change cljs so that people set!'ing without binding get broken (though I'd be fine with it..)

22:13 I guess I can accept that users will have to manually handle their own vars

22:14 technomancy: you guys figure out that stuff before I find myself in the precarious position of needing to run code on a JS runtime, k?

22:14 tomoj: https://www.refheap.com/paste/1631777863115a2e1e8ea16c9

22:14 yeah, macro would be nice..

22:15 maybe you just tell your 'executor' which vars to carry

22:16 gfredericks: Raynes: I take it back again I have no idea what I'm doing

22:19 tomoj: actually, that would really suck

22:21 it would force knowledge about dynamic vars to all be complected together in places that shouldn't care at all?

22:23 any place you use bound-fn, you have to know about all the vars you're in the _dynamic extent_ of?

22:28 I'm gonna go for a var flag and no reification

22:29 howdynihao: whats a good / popular kata?

22:29 brehaut: 4clojure.org

22:31 brum: how long would it take one of you to do a problem like this.. http://www.4clojure.com/problem/77

22:32 howdynihao: that site is nice, but i was looking for something i could git clone

22:32 and run the tests and actually edit the code

22:32 instead of the 'fill in the blank'

22:33 gfredericks: brum: a few minutes?

22:33 brehaut: brum: that would probably depend on how familiar you are with the standard lib and the features of for

22:34 actually, you might not even need for for that one

22:34 howdynihao: https://github.com/gigasquid/yellow_belt_clojure_katas there is this, but its old, and it doesnt run as is, (probably simple to fix)

22:35 brum: i would take the first word and compare it to every other word, add the word to the array if it had all the same letters

22:35 brehaut: and gigasquid is a 4clojure contributor now

22:35 brum: remove the first word from the list and then do the same with the new first word

22:35 gfredericks: brehaut: brum: got it first try

22:36 howdynihao: i would like to note, catnip is very cool

22:36 gfredericks: seven lines

22:36 brum: let me see

22:36 gfredericks: https://www.refheap.com/paste/13193

22:37 brum: that's some fancy clojure knowledge

22:37 gfredericks: like brehaut said, familiarity with the standard lib

22:37 brehaut: my solution was apparently #(set (for [[_ s] (group-by frequencies %) :when (next s)] (set s)))

22:38 which is kinda awkward

22:38 brum: how long have you been programming for

22:38 gfredericks: brehaut

22:38 gfredericks: a decade or so

22:38 brehaut: i dont know

23:26 rocco65536: c-c , in emacs is giving me a compiler error

23:26 does anyone know what could be the matter?

23:26 jack_rabbit: What's the error?

23:27 rocco65536: class not found

23:27 am I supposed to run test via lein?

23:28 I tried adding clojure to classpath but it didn't work

23:28 maybe this test mode in emacs is outdated?

23:31 jhn: rocco65536: does it work from the command line when you do `lein test`?

23:32 fbernier: what's ->>

23:32 ?

23:32 rocco65536: yes lein completes the test

23:33 it just doesn't work in emacs

23:33 it can't find clojure.test.mode

23:35 jhn: rocco65536: did you install via marmalade or melpa?

23:36 rocco65536: the former

23:36 technomancy: rocco65536: clojure-test-mode 2.x needs nrepl.el; 1.x uses slime

23:37 rocco65536: I am using nrepl

23:37 technomancy: hm; weird

23:37 rocco65536: basically I just followed the tutorial here http://clojure-doc.org/articles/tutorials/emacs.html

23:37 technomancy: you can do (run-tests) in the repl as a workaround

23:38 rocco65536: unable to resolve run-tests

23:39 which namespace should I be in to run this

23:39 technomancy: rocco65536: your repl would need to be in your test namespace

23:40 rocco65536: ok now it works

Logging service provided by n01se.net