#clojure log - Feb 06 2014

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

11:48 silasdavis: Anyone have any advice for database migration/schema libraries

11:48 I am interested in clojure ones

11:48 but I am also considering using ActiveRecord from rails

11:48 or indeed anything else

11:48 technomancy: ~clojars migrations

11:48 clojurebot: clojars migrations are just a namespace with functions: https://github.com/ato/clojars-web/blob/master/src/clojars/db/migrate.clj

11:49 Anderkent: silasdavis: do you already use a sql abstraction library?

11:49 technomancy: silasdavis: I would recommend against something big like lobos or drift

11:49 migratus or ragtime are fine, but IMO you're better off with something like the link above

11:49 rkneufeld: Stickers! Get em while they're hot: https://twitter.com/rkneufeld/status/431468188715343872

11:50 `cbp: Does north america include mexico

11:50 :-)

11:50 amro: aw, only NA

11:51 silasdavis: Anderkent, thinking about it, I have a high throughput front end which is largely go, I'm also looking at which abstraction library to use there. I thought clojure or rails might provide more flexible migrations and administrative manipulation of the database

11:51 joegallo: https://github.com/pjstadig/migratus

11:51 locks: does north america include portugal?

11:52 silasdavis: technomancy, could you expand on your resasoning?

11:52 locks: what's an ocean, really.

11:52 muhoo: `cbp: last i heard, north america is canada, usa, and mexico.

11:53 rkneufeld: `cbp: Yeah totally

11:54 `cbp: Usually american sites count only canada alaska and us as north america

11:54 rkneufeld: `cbp: Yeah, it's not a big grand thing, so I'll totally send you some stickers.

11:55 Anderkent: silasdavis: I can't remember exactly, and I've moved on from the project since so I can't change, but I think I've used drift before without any issues. The only thing I remember doing that was slightly uncommon was writing a defmigration macro that disabled down migrations

11:55 `cbp: =)

11:55 AimHere: What about Cuba, Jamaica, Bermuda, Barbados, Grenada and so forth? Don't they get to be North America too?

11:56 `cbp: can you send anything to cuba from the usa

11:56 technomancy: silasdavis: I feel like the code mostly speaks for itself =) it's quite short

11:56 Anderkent: silasdavis: the general approach of a migration being just a function is sound I thikn

11:56 coventry: How do you say (.-value (.getElementById js/document id)) in dommy?

11:56 technomancy: silasdavis: also, IMO down migrations usually sound like a good idea but don't actually work well in practice because they never get tested

11:57 same with DB-agnosticism; there are too many quirks in DDL across various SQL implementations to make a DB-agnostic lib really reliable unless it has thousands of users a la activerecord

11:57 muhoo: migrations are very clean in datomic, and seem to come from a similar approach as technomancy's.

11:57 Anderkent: technomancy: silasdavis: ah, actually, I think we moved on to a similar approach later on; except we'd also ensure that the list of already executed migrations are a prefix of the list that we want

11:58 technomancy: silasdavis: so I guess that's another vote against drift and for a simple approach like clojars-web

11:58 rkneufeld: AimHere: I don't know about those ones (esp. Cuba). If the postage is reasonable I'd do it.

12:01 silasdavis: so going to the other extreme, would you consider just writing a schema in a sql file?

12:02 technomancy: silasdavis: definitely

12:02 that's a great place to start; the question is how you deal with changes

12:03 silasdavis: presumably through a in-language abstraction layer or dsl

12:04 Anderkent: technomancy: silasdavis: so we had a very simple schema (two or three tables) initally, so our first migration just adds that

12:04 x^2: hey, i am a little bit confused about what a piece of code is doing

12:04 Anderkent: if you have something more sophisticated you might just write it down in a sql file and run that

12:04 x^2: could someone help me understand?

12:04 silasdavis: Ideally i'd like a declarative schema and have some library mostly sort out creating me database and dealing with tables already existing etc

12:04 Anderkent: x^2: sure, upload it somewhere and we can take a look

12:04 x^2: it's really jut a line or 2

12:04 sec

12:05 (let [[_ from priv chan cmd] (re-find #":(.*)!~.* (PRIVMSG) (.*) :(.*)" msg)]

12:05 so you don't have to explain the regex

12:05 but

12:05 is that command just basically setting each thing returned from re-find, to one of the things in the binding vector?

12:05 and if so, what is the significance of the _

12:05 Anderkent: silasdavis: the thing with declarative schemas is that you lose so much control of your database, and sooner or later you'll need a feature thats not in the dsl

12:05 teslanick: The first thing that re-find returns is the whole string, I believe.

12:05 Anderkent: x^2: _ doesn't mean anything special, but it's often use as a variable name for something that won't be used

12:06 x^2: ohhh

12:06 coventry: x^2: http://clojure.org/special_forms#Special Forms--Binding Forms (Destructuring)

12:06 x^2: that would make sense

12:06 silasdavis: x^2 it indicates the first element isn't bound

12:06 we don't care about it

12:06 x^2: is that just convention?

12:06 Anderkent: yes

12:06 x^2: okay

12:06 silasdavis: it's part of the destructuring language

12:06 x^2: that makes sense

12:06 and then in this part:

12:06 teslanick: You can use it multiple times, if you want to signal that you're ignoring multiple things: let [[_ _ _ a] (re-find …)]

12:07 x^2: if (not (nil? cmd))

12:07 31 (def parsed_cmd {:from from :cmd cmd :chan chan}))

12:07 ignore the 31, lol

12:07 so what that's doing

12:07 is basically just defining a hash map of the things returned previously by re-find

12:07 Anderkent: something really ugly; I hope that's not in a function or anything

12:07 hiredman: being wrong

12:07 x^2: why is it wrong?

12:07 this isn't my code btw

12:07 hiredman: defs don't go in ifs

12:07 x^2: i see

12:08 what's the better idea

12:08 to use a "let?

12:08 silasdavis: unless you want some thread-local thing conditionally but that doesn't look like this case

12:08 Anderkent: you want something to be defined once and always the same; if your def is in an if, or in a function or whatever, you can't depend on it being there

12:08 hiredman: depends on the intent

12:08 Anderkent: yeah, intent and context

12:08 hiredman: def creates a global binding of a name to a value, always

12:09 x^2: ah

12:09 the full line

12:09 Anderkent: if this is in a function, just return the map instead of defing parsed_cmd

12:09 x^2: it'd be easier if you posted the entire file somewher

12:09 x^2: this person actually defined parsed_cmd as the map, and then returned parsed_cmd

12:09 im not sure why they didn't do it the way you just described

12:09 1 second

12:10 Anderkent: they might have been confused :)

12:10 x^2: ill pastebin it

12:10 very small program

12:11 http://pastebin.com/NVj5L1w6

12:11 it's just a simple irc bot

12:11 found it online, was going to use it to help me learn clojure as i do work on it

12:11 since im familiar with irc protocol from other stuff i've written

12:11 hiredman: this is not written by someone who knows clojure, obviously

12:11 x^2: i see

12:12 why do you say that?

12:12 rasmusto: )\n)\n for one :p

12:12 hiredman: defs inside functions is really gross

12:12 it is also old

12:12 silasdavis: it's trying to write procedurally

12:13 x^2: hm

12:13 hiredman: defstruct is pretty much abandoned

12:13 x^2: let me get this straight

12:13 silasdavis: the let binding could be used for intermediates

12:13 x^2: you're saying they shouldn't be using defs because instead, you could just return whatever you're setting a def to

12:13 correct?

12:13 silasdavis: and in any case they're not needed

12:13 muhoo: x^2: if you want to parse IRC logs, maybe try this http://p.hagelb.org/irc-logs.html

12:13 x^2: im actually working on making a bot

12:14 * technomancy blinks

12:14 x^2: but anything parsing irc would be useful im sure

12:14 technomancy: huh, apparently that's a thing I wrote

12:14 teslanick: x^2: The reason you don't def inside a function is that the function now has side effects.

12:14 x^2: i was looking at the code for clojurebot but it seemed pretty daunting

12:14 Anderkent: technomancy: lol

12:14 x^2: ah

12:14 i see teslanick

12:14 so instead of just performing a function, it is changing something outside of itself

12:14 which is not clojurey

12:14 i think

12:14 hiredman: technomancy: hah!

12:14 teslanick: And not like… ok side effects like logging.

12:14 Anderkent: x^2: more or less right, an in particular defining a global var as a side effect is fugly

12:14 amro: side effects are ugly, clojure or not

12:15 teslanick: It has not-ok side effects like changing the name-state.

12:15 hiredman: def has side effects at compile time, it interns a var

12:15 dnolen: x^2: nested defs are just really not supported but also a great source of crazy bugs.

12:15 x^2: hmm, ok

12:15 i was reading the O'Reilly book which did warn against using defs much

12:15 dnolen: x^2: Clojure isn't Scheme

12:15 x^2: oh i know

12:16 like i said, i didn't write that code

12:16 dnolen: x^2: in Scheme define is local, in Clojure def are always top-level

12:16 x^2: im just trying to work on something in clojure that's more complex than a basic number cruncher

12:16 right

12:16 for local we would want to use "let"

12:16 i think

12:17 teslanick: Yes. If you want to define something local to a function, let is usually the way to go.

12:17 muhoo: x^2: you might want to look at the code for lazybot or clojurebot for inspiration

12:18 x^2: alright, iwas looking at the code for clojure bot for a little

12:18 it seemed really daunting

12:18 rasmusto: ~let

12:18 clojurebot: let is creating a local binding in your lexical scope

12:18 x^2: because i am really new to this

12:18 hiredman: ~clojurebot

12:18 clojurebot: clojurebot has a poetic soul

12:18 x^2: lol

12:18 .let

12:19 muhoo: x^2: or if you really want to get going fast, https://github.com/flatland/irclj

12:19 rasmusto: ,(let [{:keys [a b c]} {:a 1 :b 2 :c 3}] [a b c])

12:19 clojurebot: [1 2 3]

12:19 x^2: oh nice

12:19 might check out this library, how it's written and then see if i can use it

12:19 teslanick: destructure the keys for god's sake!

12:20 ytmnd

12:20 Anderkent: I always forget the [] around keys in :keys

12:20 makes me sad, every time

12:20 hiredman: x^2: https://gist.github.com/hiredman/27733 is an older version of clojurebot as a single file

12:20 locks: Anderkent: time for an emacs plugin

12:21 Anderkent: locks: >emacs D;

12:21 x^2: hiredman: thanks a lot, i think this is actually good

12:21 because im still a little confused by how people break up files in clojure applications

12:22 now this code uses a few "def"'s for constants like irc channel

12:22 i assume that is the case where it's actually ok

12:22 if you want it to be basically an immutable thing

12:22 rasmusto: x^2: put similar functions in a namespace that makes sense, and everything else in a namespace called "misc", thought that's probably not the only way

12:22 x^2: hmm ok

12:22 i also haven't really seen the purpose of using multiple namespaces yet

12:23 but im sure that will come with time

12:23 teslanick: hiredman: I love your docstrings.

12:23 "just do this, I don't care"

12:23 Anderkent: I never know how to format a docstring

12:24 i.e. manual linebreaks? indent?

12:24 hiredman: async would be future in more modern clojure

12:24 rplaca: Anderkent: manual linebreaks yes (none of the tools add them for you)

12:25 Anderkent: rplaca: but that leaves you with the indent problem :P

12:25 I usually end up putting a new line after the opening quote then writing with 0 base indent

12:25 rplaca: Anderkent: do all the normal formatting manually (i,.e., indent when you have examples or whatnot)

12:25 Anderkent: also, damnit, I want triplequoted strings :(

12:26 rplaca: the thing is if your docstring is mutliline and indented itself, all but the first line will get indent that you don't want

12:26 rplaca: indent following lines to the original if you like it or leave it on the left margin

12:26 yeah, I know

12:26 rasmusto: ,(str "" "foo" "")

12:26 clojurebot: "foo"

12:26 rplaca: in autodoc I compensate for that by removong the constant indent on following lines

12:26 rasmusto: there's your triple quotes :p

12:26 Anderkent: rasmusto: try that for a docstring :)

12:27 rplaca: I keep meaning to submit a patch for the doc function to do the same

12:27 Anderkent: #=(str "" "foo" "") :D

12:27 technomancy: ,«let's add "literal" strings»

12:27 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: �let's in this context, compiling:(NO_SOURCE_PATH:0:0)>

12:27 rasmusto: true, I guess it wouldn't work in ^:doc either

12:27 technomancy: boooo

12:27 rplaca: Anderkent: I really wanted """ yesterday when I was putting a whole python program inline in my clojure program

12:27 Anderkent: technomancy: so each raw string takes a manually input unicode char?

12:27 :P

12:28 hyPiRion: ,'[«let's add "literal" strings»] ; ?

12:28 clojurebot: [�let's add "literal" strings�]

12:28 Anderkent: rplaca: I really really want """ because I'm writing a doctest library but kinda can't get arsed to finish it because without """ it's pretty much useless

12:28 technomancy: Anderkent: C-x 8 <; not that much more than three "s

12:28 hyPiRion: ,(apply str '[«let's add "literal" strings»])

12:28 clojurebot: "�let'saddliteralstrings�"

12:28 technomancy: plus it's easier to match open/closed with paredit =)

12:28 hyPiRion: whoops.

12:28 Anderkent: technomancy: editor specific solutions are not solutions

12:28 technomancy: Anderkent: it's the 21st century; editors need to get with the times =)

12:29 rplaca: Anderkent: probably you need to come to terms with that yourself. It seems very unlikely that you're going to get """

12:29 :)

12:29 Anderkent: : (

12:30 is that because people actively don't want """, or some other reason?

12:30 rasmusto: when I need literal strings I just slam everything over to the left

12:30 Anderkent: (I guess it'd be backward incompatible, but meh)

12:30 technomancy: Anderkent: probably just because it's very difficult to convince rich of any change

12:30 Anderkent: :( fork it! :P

12:30 rplaca: Anderkent: +1 technomancy

12:30 rasmusto: "lojure

12:30 hiredman: te

12:31 technomancy: lava is a pretty good name

12:31 Anderkent: or surely you could release it as a library? just hook into the reader and swap contents of """

12:31 rasmusto: reader macro? doesn't that require a fork too?

12:32 rplaca: Clojure doesn't support hooking into the reader that way. At least not now

12:32 hiredman: technomancy: I think it is because most literal string proposals to date would make the reader not LL(1)

12:32 Anderkent: rasmusto: just redefine clojure.core/load-lib :P

12:32 technomancy: Anderkent: technically possible, but not in a way that wouldn't make your stomach churn

12:32 x^2: thank yall again for the help, this seems like a friendly community. going to hang around here a bit.

12:32 rplaca: Rich has been concerned that having multiple reader syntaxes would harm code compatibility

12:32 Anderkent: or, can you replace methods by reflection in java?

12:32 :P

12:32 rplaca: x^2: thanks for stopping by

12:32 x^2: :)

12:32 rasmusto: ,(let [f (fn [x] (* x x))] (f 2))

12:32 clojurebot: 4

12:33 technomancy: Anderkent: the reason clojure doesn't have reader macros is that they have composability issues in CL

12:33 what you're describing is a giant composability issue =)

12:33 locks: I've only been here a while, but every other day I see """ mentioned

12:33 Anderkent: I wasn't serious for a while now :P

12:33 technomancy: hiredman: huh; shows how much attention I've been paying

12:33 Anderkent: locks: because it's so good :(

12:33 rplaca: :)

12:33 technomancy: Anderkent: neither was my «» fwiw

12:33 locks: Anderkent: what does it do?

12:34 Anderkent: locks: let you type stuff in your string without having to escape "! :X

12:34 locks: so, literal strings?

12:34 Anderkent: not quite, just an alternative terminator.

12:35 rplaca: actually the nice thing about my python program is that I could just convert all my " to ' and it went into a Clojure string just fine

12:35 locks: hm

12:35 Anderkent: rplaca: so you don't have any ' in your python " stirngs?

12:35 rplaca: (thoug I still needed to double up some \s in regexps)

12:35 Anderkent: :P

12:35 rplaca: Anderkent: not in that program, no

12:36 aconbere: I feel kind of dumb but I'm trying to find documentation on clojure (not sure what to call them) 'type annotations' like you see here `(defn read-chunks [^java.nio.ByteBuffer record]...)`

12:36 rplaca: someone decided that the correct data encoding for some data I needed was actual executable python

12:36 aconbere: what are those ^ things called?

12:36 Anderkent: aconbere: caret?

12:36 Bronsa: aconbere: type hints

12:36 rplaca: so I had to use python to exec it and spit out CSV that I could read in Clojure

12:36 aconbere: Bronsa: thanks :)

12:37 Anderkent: ah. not reading back strikes again

12:40 rhg135: rplaca: I'm so sorry

12:47 rplaca: rhg135: :) one of the little travails of living in the real world

12:48 rhg135: Edn ftw

12:48 rplaca: at least I didn't have to write my whole solution in python

12:49 actually here CSV or JSON would be excellent formats

12:49 rhg135: Hmm

12:49 rplaca: I don't need to sell the non-CLojure world on edn and the data itself is super simple

12:49 just a buch of node and roles in test runs for a distributed DB

12:49 *bunch

12:50 rhg135: Whomever gave you the python was a sadist

12:50 rasmusto: at least python has list slicing notation

12:50 rplaca: no, just didn't understand the implications of what he was doing

12:50 * rasmusto ducks

12:50 Anderkent: tbh I end up using csv quite often - the fact that you can just append lines to file without having to worry about collection terminators etc is convenient

12:51 rplaca: Anderkent: agreed. when you're data is fundamentally tabular it's my favorite

12:51 rasmusto: tell me that abc[-1:-3:-1][::-1] isn't easy to understand

12:51 rplaca: cause you can read and write it everywhere

12:51 rasmusto: :)

12:51 AimHere: I quite like spitting out JSON from clojure with a multimethod. If I can find an excuse to do that, I will ;)

12:52 rhg135: rasmusto: it burns

12:52 rplaca: AimHere: hah. In this case my little python program is doing that on it's side so it can parse the python format but also some CSV I create to describe systems and the JSON that I hope they'll adopt

12:53 rasmusto: yeah, that was too confusing so I wrote this instead: abc[::-1][::-1][0:8][::-1]

12:53 mdeboard: edn -> graphviz pls

12:53 rplaca: but it uses multiple if statements :)

12:53 rhg135: Uh

12:53 rasmusto: mdeboard: did you try out the code in that gist I posted?

12:53 mdeboard: rasmusto: Negative

12:53 rplaca: mdeboard: shouldn't be too hard to write

12:54 rasmusto: random graphs and clustering of the alphabet

12:54 sometimes it takes quite a while to render

12:55 rhg135: rasmusto: any reason you're reversing a list twice?

12:55 rasmusto: rplaca: see https://github.com/ztellman/rhizome

12:55 rhg135: it's actually for clarity's sake

12:55 as backwards as it sounds

12:55 rhg135: Really?

12:55 Anderkent: rasmusto: well, that's not really very clear :)

12:55 rasmusto: it would if you knew the context

12:55 would be*

12:56 rhg135: It confused me

12:56 rasmusto: well, abc is lsb first, so I need to reverse it, then I want to index it without using negative numbers, so I reverse it, then index it, then reverse it again

12:56 there's the clarity

12:57 rhg135: Hmm

12:57 riz_: can someone explain what the big deal about Monads is?

12:57 rhg135: Working with bytes is so uncouth in 2014 lol

12:57 riz_: i come from an imperative/OOP background

12:58 rplaca: rasmusto: ahh, cool. I hadn't seen that Zach had done that

12:58 Anderkent: riz_: they're a general way of threading state though your functional code

12:58 rhg135: riz_: more composition

12:58 technomancy: "No one can explain what a Monad is. you have to see it for yourself."

12:59 rasmusto: ,(take 2 (reverse (reverse "010011")))

12:59 clojurebot: (\0 \1)

12:59 riz_: more composition?

12:59 rasmusto: okay nvm, it's really unclear, especially in clojure

13:00 rhg135: bits, bytes are too coarse-grained

13:00 llasram: riz_: Are you familiar with function composition, such as via the Clojure `comp` function?

13:00 rplaca: technomancy: that's why there are so many tutorials on monads!

13:00 rhg135: Imagine two functions returning a pair

13:00 riz_: yes

13:00 rhg135: But taking one arg

13:01 How do you compose them?

13:01 llasram: riz_: Monads are essentially a type-based way of describing patterns around function composition

13:01 technomancy: rplaca: no, that's because of a secret condition in GHC's license that says you have to blog about monads within 3 months of starting to use GHC

13:01 rasmusto: rplaca: the random graphs I was talking about https://gist.github.com/rasmusto/8807304

13:01 rhg135: technomancy: I didn't

13:01 Anderkent: technomancy: ... that explains so much

13:01 rhg135: I broke the license

13:02 technomancy: ~guards

13:02 clojurebot: SEIZE HIM!

13:02 llasram: hehe

13:02 rasmusto: ~monad

13:02 clojurebot: monad is #=(str "super" "awesome")

13:02 rhg135: Lol

13:04 I use them for mostly state and error handling

13:04 hyPiRion: llasram: that was actually a good way of describing monads.

13:05 rhg135: Oh and that promise monad I wrote

13:13 llasram: hyPiRion: Well you don't need to act so surprised!

13:15 riz_: TIL, c# LINQ uses Monadic principles!

13:15 i'm still finding them hard to grasp, currently, but now I know that I've been using them all along!

13:16 rplaca: rasmusto: ahh, there's something to play with today!

13:16 technomancy: man, I'm in violation of that clause by many years I'm afraid :)

13:20 llasram: I need to dig through the clojure-user archives... khissen has this awesome post that was basically "Well, Clojure now has separate partial implementation of three different monads. Maybe it should be a core abstraction?"

13:20 er, khinsen, and that's IIRC

13:24 bbloom: llasram: which 3 monads?

13:24 technomancy: list, future, and STM?

13:24 llasram: bbloom: sequence, ... Er. Man, now I really need to find it

13:24 Oh, that sounds like a good guess

13:25 technomancy: uneducated guess

13:25 Anderkent: no guess is uneducated!

13:26 bbloom: frankly, i'm not convinced that there is value to reifying monads in core, since each concrete monad has unique syntax considerations and extra non-monadic operators

13:26 if you're going to reify an abstraction, you need to get something from it

13:26 in haskell, you get two things: 1) do syntax and 2) monad-level abstract operations

13:26 technomancy: inc

13:27 bbloom: frankly, we don't strictly need #1, since i'd rather per-monad syntax (we have for, some->, etc)... but this ties in to #2

13:27 #2 is *annoying*

13:27 technomancy: the STM has way more in common with other IDerefs than seqs; that's an actually-practical abstraction

13:27 bbloom: operating on abstract monads is kinda useless for pretty much everything but a compiler

13:28 and even that relies on details of the concrete monad isntantiated for maximum benefit!

13:28 instantiated*

13:30 maybe it's b/c i'm not a haskell programmer, but i look at http://hackage.haskell.org/package/base- and don't see anything i'd really ever want to use that we don't already have in clojure.core in one form or another

13:31 stuff like filterM isn't necessary with dynamic typing: you can just filter a list of pairs

13:31 lifting is a pain in the ass

13:31 worst of all, all this stuff obscures the data. monadic chains are opaque

13:31 i much rather a flattened lazy seq of operations and reduce over that eagerly. so much nicer b/c you can debug it interactively

13:31 hiredman: (see compojure routes)

13:31 bbloom: *shrug* monads :-P

13:32 rkneufeld: Can anyone offer any opinions on what the state of the art is for building quick CRUD services in Clojure is? Does Liberator serve this purpose?

13:33 llasram: Ok, I can't seem to find the post I mentioned, and am giving up before I waste excessive time on it.

13:33 It may be a memory implanted by the government, to discredit me

13:33 bbloom: rkneufeld: my impression from the talk on liberator was that it's the industrial strength http API design toolkit thinggie. i dunno if it has a more rails-like brain dead crud/rest/resource wrapper thinggie too

13:33 rasmusto: llasram: a monad of the state, if you will

13:34 hiredman: a liebnizian monad of the state

13:35 rhg135: Dat paranoid

13:36 llasram: See -- their plan is working

13:36 rhg135: Ic

13:37 I don't trust you anymore :P

13:54 mdrogalis: dnolen & tbaldridge: What's the difference between a coroutine and what core.async provides? I'm not familiar with the former.

13:54 dnolen: mdrogalis: coroutine is something the language runtime itself must support

13:55 mdrogalis: dnolen: Hm.

13:56 tbaldridge: mdrogalis: coroutines are basically co-operative multitasking. Like threads, but other threads only run when you call (yield) or (yield other-thread)

13:58 muhoo: technomancy: in clojars migrate.clj, why are you passing the vars of the migration functions to the migrate function, instead of just passing the function? i.e. why (migrate #'foo) not (migrate foo) ?

13:58 technomancy: muhoo: the function doesn't know its own name

13:58 so you can't record the fact that it ran in the migrations table

13:59 muhoo: ah, cool

13:59 technomancy: which is kind of silly

13:59 but that's the way it is

13:59 muhoo: there's no args[0] as in c

13:59 clever solution tho

13:59 mdrogalis: tbaldridge: Ah, I see.

13:59 technomancy: more just that defn doesn't copy the var metadata onto the function object itself

14:00 alandipert: mdrogalis: check out ftp://www.cs.indiana.edu/pub/techreports/TR158.pdf section 3 - coroutine =~ continuation

14:00 technomancy: for historical reasons

14:00 mdrogalis: tbaldridge: Would it be correct to say you can use core.async in that manner?

14:00 Thanks alandipert. Reading.

14:00 tbaldridge: mdrogalis: maybe? I think it's possible, but I haven't tried yet.

14:01 a bunch of gos all waiting on one channel might work. still it'd be a bit of a hack.

14:01 mdrogalis: Yeah

14:02 dakrone: if anyone here has a project that heavily uses clj-http, please try out the 0.9.0-SNAPSHOT as it has some drastic changes in the way headers are represented internally

14:03 muhoo: dakrone: i do. what broke? :-/

14:03 dakrone: muhoo: nothing should be broken, but you should be able to retrieve headers in a case-insensitive manner now

14:04 muhoo: clojure 1.2.1 and 1.3 support was dropped also

14:04 but that's why it's a snapshot, so if it actually breaks things, we can fix it before it's released :)

14:04 technomancy: dakrone: curious, known breakage or just "no longer tested"?

14:04 with 1.2/1.3

14:05 dakrone: technomancy: known breakage (:use -> :require, docstrings for defs, type hinting syntax)

14:05 technomancy: cool

14:06 hfaafb: is there a cool way to access items in a multidimensional array

14:06 muhoo: dakrone: great, thanks.

14:06 dakrone: muhoo: please do let me know if anything breaks (nothing should) :)

14:06 joegallo: hfaafb: one a skateboard while listening to "Go Ninja Go" from the TMNT soundtrack

14:06 s/one/on/

14:06 i think if you'd do it that way, it would be pretty cool

14:06 technomancy: (inc joegallo)

14:06 lazybot: ⇒ 3

14:08 hfaafb: i cant even skateboard

14:08 should i just learn haskell

14:08 technomancy: only if there's a skateboard monad

14:08 muhoo: joegallo: on irc while on a skateboard?

14:08 `cbp: hfaafb: if it's a java array use aget

14:08 muhoo: how is that even possible

14:08 hfaafb: its a clojure vector

14:09 `cbp: get-in

14:10 S11001001: hfaafb: how about some https://github.com/mikera/core.matrix#corematrix

14:10 teslanick: ,(get-in [[,,,]["hello" "world"][,,,][,,,]] [1 1])

14:10 clojurebot: "world"

14:10 hfaafb: thanks

14:10 you guys are pretty cool

14:11 teslanick: (pretty chuffed about that use of commas as whitespace)

14:11 `cbp: ~haskell

14:11 clojurebot: "you have to see features like that in the context of Haskell's community, which is something like Perl's community in the garden of Eden: detached from all shame or need to do any work." -- ayrnieu

14:12 alandipert: ,((fn [v [x y]] (get v (+ (* x 2) y))) [1 2, 3 4] [0 1]) ; for a flat vector posing as a multidimensional one

14:12 clojurebot: 2

14:41 sritchie_: cemerick: hey man, are you around?

14:41 I've got an austin setup that just… stopped working.

14:41 cemerick: I'm running the "connect" call in the browser (I've run it a couple of times in the console)

14:41 cemerick: but I have no visibility into whether the connection's failed, etc

14:41 no errors, nothing

14:42 cemerick: sritchie_: umm

14:42 Not sure what to say about that.

14:42 *something* changed

14:42 sritchie_: like, my first command at the repl in emacs (* 2 2) just hangs, as if it's waiting for a connection

14:42 cemerick: okay, fair :)

14:42 cemerick: the Q stands… any way to diagnose whether or not the connect call on the browser actually went through?

14:43 the whole thing is fragile enough that I worry about whether I'm even using it correctly.

14:43 cemerick: stackoverflow happens sometimes if I disconnect with :cljs/quit and try to reset the browser repl atom,

14:43 seangrove: sritchie_: Same issue, constantly and constantly

14:43 cemerick: sritchie_: look for a series of 3-4 requests right when the session starts in e.g. the network panel in chrome

14:43 sritchie_: cemerick: oh, jesus, there it goes

14:44 just connected after like a minute

14:44 muhoo: ,(get '(1 2 3) 1)

14:44 clojurebot: nil

14:44 muhoo: ,(get (vec '(1 2 3)) 1)

14:44 clojurebot: 2

14:44 muhoo: WHY?

14:44 seangrove: "cljs repl hangs", "hard refresh page", "still hung, C-b" "hard refresh", "try command again in cljs repl, hung", "hard refresh", "works!"

14:44 sritchie_: exactly

14:44 llasram: muhoo: Because lists don't provide constant-time indexed access?

14:45 sritchie_: cemerick: do you have that experience that seangrove is mentioning?

14:45 or is there some better way to set up the tools than injecting that script inside of your html and having the app connect back to the repl

14:45 cemerick: I don't, no.

14:45 muhoo: llasram: but, nil is surprising. throwing an exeption "you can't use get on a list" would be more helpful

14:45 seangrove: cemerick: Really? It's constantly happening to everyone I introduce cljs to

14:45 sritchie_: yeah, every single dev environment I've touched is extremely finicky

14:45 cemerick: sritchie_: that's sort of the entire premise of the browser-REPL :-P

14:45 llasram: muhoo: (get 'zoom 'what 'foo)

14:46 seangrove: cemerick: Although Austin is fantastic, please don't misinterpret my moaning ;)

14:46 llasram: muhoo: Er, ##(get 'zoom 'what 'foo)

14:46 lazybot: ⇒ foo

14:46 sritchie_: cemerick: yeah, I get that, which is why the experience is so confusing

14:46 like, the whole stackoverflow issue when you disconnect

14:46 yeah, it's great to have Austin, for sure

14:46 cemerick: seangrove: well, if I could get my hands on legitimately not-working environment, I'd do what I can. I've paved over all the rough spots I've ever hit. *shrug*

14:46 sritchie_: cemerick: we can Screenhero sometime if you like

14:46 seangrove: cemerick: I understand

14:47 sritchie_: hell, I can give you access to our PaddleGuru source if you want

14:47 seangrove: cemerick: I can repro it in a certain case though

14:47 sritchie_: cemerick: and you can try to run the browser repl

14:47 seangrove: cemerick: Hopefully I can find time for a minimum repro case

14:47 muhoo: llasram: hum. well. that's a sharp edge i guess i'll just have to watch out for. if i pass a list into a function that's expecting a vector, or if i try to do get-in on a nested structure and some part of it will be a list, i'll get a silent nill failure

14:47 sritchie_: seangrove: that'd be awesome

14:47 cemerick: any insight into that issue of clojure.tools.reader compilation failing when Austin's on the classpath?

14:47 seangrove: sritchie_: Maybe. Specifically if I try/catch at a certain point the repl never *actually* connects

14:47 cemerick: sritchie_: I have to draw the line at OSS contributions short of doing remote support skypes, etc. ;-P

14:48 sritchie_: sorry, link?

14:49 sritchie_: https://github.com/cemerick/austin/issues/37, https://github.com/cemerick/austin/issues/23

14:49 cemerick: sure, I write a bunch of open source too, I get it...

14:49 technomancy: muhoo: silent nil failures are the Clojure Way =\

14:49 sritchie_: I wasn't trying to ask for extra work, just offering a debugging environment for what seems like a fairly major issue in the library

14:50 muhoo: technomancy: not always, and i have many multiple-page-long stacktraces to prove it

14:50 sritchie_: cemerick: not so you can debug my stuff, you just mentioned getting your hands on a busted environment

14:50 * muhoo goes bananas with {:pre [(vector? foo)]}

14:51 stuartsierra: muhoo: I've filed issues on some of these; http://stuartsierra.com/2013/02/04/affordance-concision

14:51 cemerick: sritchie_: right, that; I hadn't associated it specifically with tools.reader. No, I haven't looked into that yet in detail.

14:51 very happy for some help with it, tho

14:51 technomancy: muhoo: silently returning nil and failing in an unrelated part of the codebase, rather

14:52 cemerick: sritchie_: Yeah, I appreciate the offer. Maybe I'll take you up on it at some point, but I'm extremely focused lately / now / hopefully as long as possible, etc.

14:53 sritchie_: yeah, for sure, the stuff you're putting out is awesome

15:07 muhoo: stuartsierra: thanks, that's a nice exposition on the topic.

15:09 stuartsierra: muhoo: you're welcome

15:25 Anderkent: were all bots dead on 3rd Feb? Trying to find the logs online :P

15:25 hiredman: freenode fell appart

15:25 Anderkent: hm, then that's probably not the day I'm looking for

15:25 TimMc: We could do a merge on people's logs...

15:26 Anderkent: damnit, i think it is the day I was looking for ;_;

15:26 hiredman: actually, most of the freenode issues were the 2nd and the 3rd for me, but maybe utc that would have been the 3rd and the 4th

15:26 Anderkent: logs for the 4th also seem very short for everyone?

15:26 eh.

15:28 TimMc: Anderkent: Whatcha looking for?

15:28 Anderkent: someone was helping me on tuesday, I think, with a No matching ctor found for class clojure.lang.AFunction$1 error

15:28 gfredericks: oh well use the matching constructor instead

15:28 Anderkent: and I just wanted to tell them they were half right, and damn I don't think I can fix it

15:29 * gfredericks 's work here is done

15:29 Anderkent: ;_;

15:30 eh no, goddamnit, I still don't get why it's breaking only in this particular case

15:31 doody1: what are some good references on clojurescript?

15:31 Anderkent: Anyone know where function pre/post conditions are built?

15:32 ah, in fn

15:32 clojurebot: Huh?

15:33 TimMc: Anderkent: Well, I can give you my logs for the last week or whatever.

15:33 Anderkent: nah, it's cool

15:33 not really important

15:34 TimMc: (Lines elapsed since start of Feb 3: 4000. Not actually that many.)

15:34 stuartsierra: clojurebot: classes?

15:34 clojurebot: Gabh mo leithscéal?

15:35 Anderkent: oh shit, I get why it's broken

15:35 clojurebot: Titim gan éirí ort.

15:35 Anderkent: precondition is literally included in the metadata of a fn

15:35 and my literal representation includes a function object

15:36 stuartsierra: I can never find that diagram of Clojure's classes/interfaces when I want it.

15:36 Anderkent: which it cant put in code. Gah.

15:39 TimMc: stuartsierra: Well, if you find it again, I'd be curious to see it.

15:41 gfredericks: does the leiningen dependency list get turned into a classpath in leiningen's code or maven code or somewhere else?

15:42 rhg135: stuartsierra, if you find it add it clojurebot

15:47 arrdem: clojurewiki too...

15:49 stuartsierra: http://n01se.net/paste/fZQ

15:49 PNG here: http://n01se.net/paste/HTx

15:50 SVG here: http://n01se.net/paste/fZQ?pretty=no

15:50 Anderkent: stuartsierra: how did you choose the colours?

15:51 stuartsierra: I didn't.

15:51 Anderkent: :D

15:51 stuartsierra: It's from https://groups.google.com/d/msg/clojure/H42kG6_aKms/gYyJoD7UUe8J

15:51 Chouser made it.

15:51 arrdem: (inc chouser)

15:51 lazybot: ⇒ 15

15:51 bmath: (+ 3 4)

15:51 clojurebot: *suffusion of yellow*

15:56 gfredericks: is there any succinct summary of what situations require `lein clean` to avoid having wrong dependencies?

15:57 Tolstoy: Is there any way to get tools.logging to use a logger name other than the namespace?

15:58 hiredman: gfredericks: it should never be required for dependenxies in lein 2, but can be required to clear out stale aot'ed stuff

15:58 gfredericks: hiredman: which might include dependencies?

15:59 stuartsierra: clojurebot: class chart is https://groups.google.com/d/topic/clojure/H42kG6_aKms/discussion

15:59 hiredman: yes, AOT is transitive'

15:59 clojurebot: Ik begrijp

15:59 stuartsierra: clojurebot: class chart ?

15:59 clojurebot: Titim gan éirí ort.

15:59 stuartsierra: Bah.

15:59 hiredman: clojurebot: class chart?

15:59 clojurebot: class chart is https://groups.google.com/d/topic/clojure/H42kG6_aKms/discussion

15:59 hiredman: clojurebot: class chart

15:59 clojurebot: class chart is https://groups.google.com/d/topic/clojure/H42kG6_aKms/discussion

16:01 Tolstoy: Looks like there's no way to do it.

16:04 Anderkent: That feeling when you can't remember why you're doing something, but it's breaking stuff, and removing it stops the breakage, so you remove it #bugfixed

16:05 Tolstoy: Is there a way to create a namespace "on the flow" to bind to *ns* temporarily?

16:07 hiredman: Tolstoy: yes, but don't

16:07 the cases where you would need that are vanishingly small

16:08 Tolstoy: I just want to be able to log to subject matter with tools.logging rather than namespaces.

16:08 hiredman: Tolstoy: just don't uses tools.logging then

16:08 Tolstoy: So it's not possible with that tool. Okay.

16:09 hiredman: or use the lower level functions it exposes (which I dunno, they may let you do whatever)

16:09 Tolstoy: Yeah, I looked at those. They pay attention to *ns* so thought maybe I could override that for the one case I need it.

16:09 stuartsierra: tools.logging just wraps Java logging APIs, all of which let you create a Logger object with an arbitrary name.

16:10 shriphani: hi. is it possible to do pass in extra arguments with lein ring server ? I can't see a way to do it and my google-fu is failing me.

16:10 Tolstoy: stuartsierra: I'm not seeing that, though. The logger they seem to want is a logger factory. I'll check again, though.

16:10 paulswilliamsesq: Hiya - can someone please advise what the benefits of using :require are without aliases, when you can use fully qualified references to functions outside of the current namespace? #not_trolling ;-)

16:10 stuartsierra: Tolstoy: Just use the Java API for your logging library.

16:12 paulswilliamsesq: Just referring to a function in another namespace does not load that namespace.

16:12 Tolstoy: stuartsierra: Heh. That'll work. ;)

16:12 hiredman: paulswilliamsesq: you can't, though, unless something else has already loaded the code

16:12 require loads the code, refering to a function with a full qualified name will not

16:14 paulswilliamsesq: stuartsierra: hiredman: does this rule include functions within clojure ns like clojure.set/intersection? I seem to be able to call it using fully qualified name without explicit requires. Could it be lein that autoloads clojure.* namespaces?

16:15 hiredman: the clojure runtime loads clojure.core and a few others

16:15 the ns macro automatically requires clojure.core

16:16 stuartsierra: In general you cannot rely on anything being loaded besides clojure.core.

16:16 hiredman: correct

16:16 the set of namespaces that the runtime loads besides clojure.core has changed overtime

16:16 paulswilliamsesq: hiredman: gotcha, just going through joy of clojure, which uses invocations of clojure.set/intersection as an example of when to use require, and being devious, I tried without the require and was suprised to see it work!

16:17 hiredman: clojure.set is a namespace where this changed, it used to be automatically loaded, then wasn't

16:18 paulswilliamsesq: hiredman: and now is again?

16:18 technomancy: it used to be loaded by clojure.main

16:18 hiredman: could be

16:18 technomancy: now clojure.main got disj'd from the set of things that load clojure.set

16:19 hiredman: paulswilliamsesq: if you are at a repl, and ran a require, it loaded it, and it will stay loaded

16:19 Anderkent: #reassuring-commit-messages: https://github.com/JacekLach/cloverage/commit/69fa5556e4cfe9ac884d7c6f2dffb66c976a462b

16:20 paulswilliamsesq: hiredman: not running in a repl, running in a testing ns tested through lein-autoexpect

16:20 hiredman: Anderkent: 90% of testing and code coverage frameworks for clojure are written by people who never seem to know what they are doing

16:20 Anderkent: hiredman: that's me :(

16:21 hiredman: which I sort of imagine why code coverage and tests apeal

16:21 paulswilliamsesq: autoexpect most likely isn't cleanly testing things, e.g. it is using the same jvm with whatever accumalted state for multiple test runs

16:22 Anderkent: would you say you know what you are doing with clojure then?

16:22 Anderkent: hiredman: Yeah, I'd think so. This is more of a case 'I don't have time to track it down right now' than a 'I don't understand the language I'm using'

16:23 paulswilliamsesq: hiredman: ok, I've been using it in a similar style to koans.

16:24 hiredman: I've previously found tdd a good way of learning and recording facts about languages / libraries etc.

16:24 hiredman: Anderkent: as whoever was trying to tell you, you are emitting a function object from a macro instead of a data structure that when evaluated is a function object

16:24 Anderkent: hiredman: that's me. on both sides.

16:25 hiredman: ,(let [a '(fn [x] x) b (fn [x] x)] [a b])

16:25 clojurebot: [(fn [x] x) #<sandbox$eval25$b__26 sandbox$eval25$b__26@183da96>]

16:25 Anderkent: hiredman: and tbh the function object is only emitted as an argument to the macro itself - it should never show up in macroexpanded code

16:25 hiredman: the reason you only see it once you try to tag the function object with metadata is a little esoteric, but basically it is because metadata on function objects is a bad hack

16:25 Anderkent: (which is the part I don't understand - apparently somewhere it does, and it has something to do with fn preconditions)

16:26 hiredman: oh?

16:26 hiredman: yes

16:27 Anderkent: care to elaborate? (or point me at a relevant resource)

16:28 hiredman: Anderkent: well, given a function, what would you do to create a new version of that function with metadata attached?

16:28 if you were writing it?

16:28 agocs_work: Here's a dumb question: I'm running a SpeClj test. In the describe block, I have "(with-all env (.toString (UUID/randomUUID)))". When I go to use the env variable inside an (it) block, I need to use the @ decorator before env. Why is that? I feel like I don't fully understand what @ is doing.

16:29 hiredman: you can't have some mutable field, because fns are values, not references, so you need to be able to return a "new" value with the metadata without effecting the old value

16:29 Anderkent: hiredman: right, so it delegates?

16:30 hiredman: anyway, just think it through, come up with some designs and tradeoffs for those designs, I have to go back to work

16:31 and follow it all the way through, given an abitrary object, and clojure compiels to bytecode, so for compilation you have to embed that object in the jvm bytecode somehow

16:37 Anderkent: hiredman: but that's my point, the function object should never be embedded into actual code - it's only ever passed around as an arg to a macro, or called from that macro

16:37 gfredericks: is there a lein plugin for sticking all the project data on the classpath in some manner?

16:38 hiredman: Anderkent: evidently that is not the case

16:38 technomancy: gfredericks: check out configleaf

16:40 Anderkent: well, duh. also, not very helpful. But yeah, I figure now it kinda works-by-accident since non-metadataed function objects are embeddable; I guess I really should track it down since this doesn't seem like a sane thing to rely on

16:45 gfredericks: technomancy: yo thx man u da bomb

16:46 Raynes: he is da bomb

16:48 scape_: when using core.async go blocks, I noticed using a loop within them will hog the pool-- even if the loops are basic and non-blocking; is it not advised to spin up many go blocks with loops? I could do this in reverse and have one loop which constantly spins up go blocks-- but then why is go-loop even a macro?

16:48 technomancy: "No mom, things aren't the bomb any more. Only bombs are the bomb."

16:51 stuartsierra: scape_: go blocks run on a fixed-size thread pool right now. If most of them are "parked" most of the time it's not a problem. But if they are all doing work they fill up that thread pool.

16:53 scape_: stuartsierra: they're each checking if an inputstream has data available. what constitutes parked in a loop?

16:53 stuartsierra: scape_: parked means waiting on the result of a channel operation like <!, >!, or alt!.

16:54 scape_: It sounds like you're creating "spin" loops that repeatedly check a flag. That will tie up a thread.

16:54 gfredericks: does (str some-lazy-seq) not print the seq for some intentional reason about infinite lazy seqs and such, or just because it was never implemented?

16:55 scape_: what's suggested then? spin off go blocks that check flag and <! their return on another go block?

16:55 apply str is needed gfredericks , I believe

16:55 stuartsierra: scape_: You probably don't want to be checking a flag in a loop.

16:55 gfredericks: scape_: I know that, I'm wondering why

16:55 ,(str '(1 2 3))

16:56 clojurebot: "(1 2 3)"

16:56 gfredericks: ,(str (seq "foo"))

16:56 clojurebot: "(\\f \\o \\o)"

16:56 gfredericks: oh nevermind

16:56 that's actually the behavior I was reacting to and that's totally consistent

16:56 stuartsierra: scape_: Either use a blocking operation on a real thread or use a callback-based API to `put!` into a channel.

16:56 gfredericks: ,[(str \x) (str [\x])]

16:56 clojurebot: ["x" "[\\x]"]

16:57 gfredericks: ^ that's a little bit weird though

16:57 scape_: okay, i was hoping to not write this in a call-back manner

16:58 stuartsierra: With core.async you generally use `put!` and `take!` with callbacks at the "edges" of your code, to interop with other libraries. Then your application can be written with `go` blocks.

16:59 scape_: stuartsierra: okay thanks, i'll have to rethink this :D

17:02 amalloy: gfredericks: i always assumed it was because of infinite seqs, yeah

17:02 it's perfectly sensible to include vectors' contents, since those are known to be finite

17:17 effy: how can i read a clojure stack-trace, there is not a single line of the trace that match my file, is there a tricks to make it more readable ?

17:18 technomancy: a recent study found that clojure stack traces are "not that bad" and "often bearable"; maybe check again?

17:18 amalloy: effy: usually it's noce the case that no single line comes from your file; the "trick" of reading them is to get more practice at it. you can also paste it to refheap.com and post a link here for more experienced analysis

17:18 technomancy: sorry

17:18 `cbp: start at the top! :p

17:19 amalloy: "noce"? "not", more like

17:21 technomancy: effy: if you paste defns into the repl you won't get line numbers; make sure you're compiling the whole file as a unit

17:23 effy: technomancy: mmmmh, it's probably because i call it with C-x C-e to the repl then, thanks

17:23 rplaca: effy: another thing to watch for is lazy sequence evaluation, often caused by the print at the repl forcing evaluation

17:23 technomancy: effy: there's no technical reason C-x C-e couldn't send line numbers

17:23 it's just that no one's bothered yet

17:24 effy: rplaca: i got lazy-seq but i dont think it should be displayed, it's a wrong type somewhere which my newbie-ness not allow me to easily spot

17:26 that's a good learning oportynity, is there an easy way to trace the code or dump a kind of stack-trace but with the parameters provided during the function calls ?

17:26 technomancy: effy: check out tools.trace

17:34 bahaha https://mobile.twitter.com/seanlevin/status/431548196809363456#tweet_431548196809363456

17:35 bbloom: technomancy: apparently twitter.com and mobile.twitter.com don't share login cookies

17:35 technomancy: bbloom: yeah, regular twitter is a real disaster when using a keyboard-driven browser

17:35 or with noscript

17:36 bbloom: technomancy: which i consider a feature b/c it means that i'm less likely to screw around if my mouse is out of reach :-P

17:36 technomancy: my mouse is always out of reach

17:39 rhg135: mouse?

17:40 it's over there

17:42 technomancy: sites that don't set meta rel=next/prev: threat or menace?

17:43 clj-noob: hey guys.. I'm having trouble understanding macros... I'd like to wrap the enfocus defsnippet macro in a new macro so I can dynamically create one of its parameters... in this case the uri parameter... can anyone point me to an example of a macro that does something like this ?

17:44 `cbp: clj-noob: timbre has a defmacro inside a defmacro if you're into that sort of thing

17:44 clj-noob: thx I'll go take a look

17:45 dsrx: yo dawg

17:46 `cbp: clj-noob: https://github.com/ptaoussanis/timbre/blob/master/src/taoensso/timbre.clj#L478

17:47 clj-noob: `cpb: oh.. I think I'm looking to do something different...

17:47 spit out a macro with one of its params generated by my own macro... not nest macros

17:48 `cbp: clj-noob: like this? https://github.com/ztellman/clj-tuple/blob/master/src/clj_tuple.clj#L69

17:50 clj-noob: `cbp: yes I think so thanks, just trying to understand that :-)

18:03 arrdem: so why does the ns macro not support nesting of partial ns's?

18:03 eg. :require [foo [bar [baz :refer :all] [bung :refer [bah]]] [other :refer :all]]

18:07 technomancy: arrdem: because namespaces aren't actually hierarchical

18:07 it's an illusion

18:08 arrdem: technomancy: I know that

18:08 technomancy: but it doesn't mean the macro couldn't present the illusion

18:08 technomancy: I think the whole prefix stuff is widely regarded as a mistake

18:08 arrdem: really.

18:08 that's rather unfortunate...

18:09 technomancy: you don't want to mess with grep

18:10 arrdem: see... you can say that but I'd rather have smarter tooling (nrepl tools, LT support, compiler -> editor integration) that allows symbol resolution rather than saying "oh go grep for it".

18:10 technomancy: arrdem: ok, well write some then =)

18:10 arrdem: we can build better tools. that the old ones work shouldn't be sufficient reason to keep them..

18:10 technomancy: nothing exists now, so don't break the best thing we have till we have something better

18:11 you burn bridges *after* you cross them, not before =)

18:14 arrdem: I'll bomb that bridge when I come to it..

18:26 bbloom: technomancy: arrdem: i agree firmly with both of you :-) damn tradeoffs

18:26 programming makes me feel like im skitzo more often than not

18:26 arrdem: we're all mad here... some tea?

18:38 * dacc breaks out the mercury.

18:42 gregorstocks: is there a way in lein to do something like (def profile {...}) (defproject ... :profiles {:x profile :y (merge profile {...})})?

18:43 i'm trying to combine a bunch of small lein projects into one big lein project with one profile per old project, because that should solve some git headaches

18:44 but everything I've tried has led to either "contains? not supported on type: clojure.lang.PersistentList" or it trying to evaluate my dependency symbols before they're loaded

18:45 i guess #leiningen is a better place to ask.

18:54 arrdem: gregorstocks: so project.clj gets read and eval'd normally...

18:55 gregorstocks: you should be able to add defs and soforth I thinl.

18:55 gregorstocks: arrdem: it turns out I want composite profiles

18:55 I think

18:56 arrdem: gregorstocks: maybe. I'm not terribly familiar with leiningen's internals.

19:01 ztellman: open sourced a thing: https://github.com/Factual/durable-queue

19:02 clj-noob: let me know if you have questions about clj-tuple

19:02 llasram: ztellman: That is sweet

19:02 (inc ztellman)

19:02 lazybot: ⇒ 10

19:03 ztellman: llasram: yeah, it was a surprising nothing like this already existed

19:03 Raynes: ztellman: Open sourced things!

19:03 ztellman: It used to be the case that basically everything I did ever was open source. Even professional stuff, cuz flatland.

19:03 :p

19:04 ztellman: Raynes: how's the new gig treating you?

19:04 Raynes: Very well!

19:04 ztellman: glad to hear it, give my best to Lance, haven't seen him in a while

19:04 is there going to be a scopely contingent at Clojure/West?

19:04 Raynes: Hopefully I can start dragging him to meetups.

19:05 bbloom: ztellman: i've made a bunch of file system queues... but with slab allocation?

19:05 * bbloom bows to ztellman

19:05 Raynes: ztellman: Sadly no -- this one caught me a bit off guard.

19:05 ztellman: The call for presentations opened like 5 minutes after I started this new job.

19:05 ztellman: bbloom: not sure how else you'd do it, if you want to be able to clean up after yourself and do append-only writes

19:06 Raynes: I would have submitted a presentation had I felt I had the time to actually prepare one :P

19:06 bbloom: ztellman: one file per task

19:06 ztellman: hahaha

19:06 bbloom: ztellman: performs better than (most people) think :-P

19:06 ztellman: admittedly, that didn't occur to me as a valid option

19:06 bbloom: ztellman: don't laugh, i've processed an absurd amount of shit with bash and inotify-tools

19:06 :-)

19:09 ztellman: i see you say 1.5k tasks/second, i've definitely done like nearly 1k with task per file :-)

19:10 ztellman: bbloom: must have not been on an AWS box

19:10 bbloom: ztellman: rackspace

19:10 ztellman: they give you fully tens of IOPS

19:10 bbloom: ztellman: if you're lucky

19:11 Raynes: Guys.

19:11 What happened to refheap? When it start getting so many pastes? Goodness.

19:12 We've now crossed 34k. I've had to outsource the database!

19:12 ztellman: Raynes: do you need a queue

19:12 Raynes: ztellman: 34k dude, I'm nearly in big data territory!

19:12 It's like two gigs man.

19:13 arrdem: Raynes: the all time IRC logs for #clojure were 1.9M records...

19:13 bigger data than my budget server can handle :P

19:13 Raynes: Hah

19:24 alew: ztellman: what was your use case for building durable queue?

19:24 ztellman: alew: some of our customers have realtime systems that emit data they want us to use

19:24 notably, one has 50k+ datapoints/sec

19:25 we need to journal it to S3, but sometimes S3 stops accepting writes for a bit

19:25 every few days, we'd get a hiccup, and all the processes would fall over, hard

19:25 meanwhile, the volume of data was increasing every week

19:25 this was using the Hadoop S3 client, at the time

19:27 but I've wanted something like this before, there's usually some sort of transaction log that shouldn't just be queued up in memory

19:27 alew: so durable-queue kicks in when S3 isn't accepting

19:28 ztellman: well, it's the intermediary even when S3 is working

19:28 alew: and the volume of data was high enough where memory would be prohibitively expensive?

19:28 right

19:29 ztellman: I suppose I could have gotten high-mem instances for a process whose healthy memory usage is ~100mb

19:30 but like I said, I think it's a problem that just needed to be solved, and had a bunch of applications elsewhere

19:30 alew: makes sense

19:30 ztellman: and then the processes with a bunch of in-memory backlogs aren't these fragile little bubbles you have to pray stay around long enough for them to clear

19:51 stirfoo: how do I keep emacs cider from eating tracebacks?

19:52 I use C-c M-j cider-jack-in and a lot of exceptions don't get printed. lien repl from the cl shows them all.

19:52 arrdem: stirfoo: they aren't eaten, they're just in *Messages*

19:52 Raynes: (setq cider-repl-popup-stacktraces t)

19:53 * arrdem grumps about cider

19:54 TEttinger: man Futures are great. as soon as you enter a new level, my game can preload the next level in another thread, even though the level generator is written in java.

19:54 never really used them before

19:54 arrdem: Futures are awesome until you start running more threads than you have hardware CPUs...

19:54 then things get weird fast.

19:55 TEttinger: I'm only using one at a time so far

19:55 stirfoo: arrdem: haha, I like it so far, but I was never a slime guru

19:55 TEttinger: (thread beyond the executing one)

19:55 stirfoo: thanks Raynes, I'll try that

19:55 arrdem: stirfoo: I appologize. cider is totally awesome, my brain read cider as nrepl, which is cider's old name.

19:55 stirfoo: ah

19:55 alew: Future use an unbounded thread pool, right?

19:55 rsenior: ztellman: looks awesome BTW

19:55 arrdem: alew: I believe so.

19:56 ztellman: rsenior: thanks!

19:56 arrdem: alew: which is a real problem when database transactions are in futures...

19:56 see bitemyapp/revise

19:56 rsenior: ztellman: is there a reason you didn't reach for a java message queue?

19:57 ztellman: rsenior: the closest to what I wanted was Kafka, but I figured a smaller library that could be embedded in anyone's project without dragging half the world along would be a nice thing to have

19:57 rsenior: ztellman: grim_radical and I were just talking about swapping it vs. ActiveMQ (which we're using in PuppetDB, but drags in a lot of deps)

19:57 ztellman: exactly, if all you're doing is in-process queueing, most existing products are way overkill

19:57 grim_radical: rsenior: yeah, looks like the only feature we'd be missing is scheduled retries

19:58 rsenior: ztellman: yeah, that's the PuppetDB use case

19:58 grim_radical: right

19:58 alew: arrdem: what's the problem with db transactions in future?

19:59 arrdem: alew: when you have absurdly high write throughput

19:59 alew: what I ran into was that I was spawning transaction futures faster than they could execute

20:00 alew: which lead to all kinds of "interesting" failures.

20:00 ztellman: unbounded thread poooooools

20:00 stirfoo: Raynes: much better, thank you!

20:00 * arrdem waves his pitchfork

20:00 arrdem: bounded thread pools with work queues!

20:01 Raynes: stirfoo: I got it directly from the README :P

20:01 alew: arrdem: besides an oom error, shouldn't unbounded thread pools work fine for something io bound?

20:01 stirfoo: guilty!

20:02 arrdem: alew: no because you loose order gurantees on the writes, and I ran into really weird issues where the connections each worker was using could actually time out before the worker finished or even started.

20:05 alew: arrdem: ah, yeah, if you expect order than unbounded thread pools wouldn't work. that must have been fun to debug :P

20:05 arrdem: alew: you have noooooo idea :c

20:05 doody1: ritz doesnt work with cider right?

20:06 how do you debug clojure with emacs?

20:09 rplaca: doody1: println & tools.trace

20:10 (I use cl-format instead of println, but I'm an outlier)

20:10 decidedly not ideal, but it works

20:12 doody1: so set a breakpoint, inspect a ring handler params, is no go ?

20:13 sritchie_: dnolen: any advice on how to get Om (and react, I guess) to not render UI elements when they're far from the viewport?

20:13 dnolen: or maybe this already just works - thinking of a TODO list with 10k items, for example

20:14 dnolen: sritchie_: you will need to do some windowing logic yourself.

20:14 rplaca: doody1: that's right

20:14 dnolen: sritchie_: but you can make a generic component for horizontal lists w/o too much trouble

20:14 sritchie_: er vertical lists

20:15 sritchie_: dnolen: trying to find the protocol to deal with this - I remember reading about IShouldRender or something in your docs...

20:16 dnolen: sritchie_: this logic should be in IRender(State), you select the list of things that are actually in view

20:17 sritchie_: it does mean you have to write some logic to know how big elements in your view are - this is way simpler if you have a fixed height of course. If you don't will be much more complicated.

20:17 doody1: rplaca: does that suck? or may be I am so lame

20:18 sritchie_: dnolen: yeah, for sure. so figure out the location of the top of the first one, then I guess I can somehow supply only the items that are supposed to be in scope given the current windowing...

20:18 dnolen: sritchie_: exactly

20:19 sritchie_: dnolen: so probably just a calculated top: css value on the first one that's rendered?

20:19 cool

20:19 then the rest just work

20:19 dnolen: sritchie_: if scroll y is 1000px, and elements are 100px tall, you know you can render starting at index 10

20:19 sritchie_: dnolen: and set the style of the first one to give it the right offset, correct?

20:19 dnolen: sritchie_: that's right

20:20 sritchie_: dnolen: boom, what might have been a hard problem turns in to a "don't fuck up CSS syntax" problem

20:20 so good

20:20 dnolen: sritchie_: the logic will be a little messy especially if you want to make it cross browser

20:20 sritchie_: but the point is that this component can be completely generic

20:20 sritchie_: you can just reuse it every time you need this functionality

20:21 sritchie_: if you write one for Om I'm sure everyone will just use yours :)

20:21 sritchie_: dnolen: sold

20:22 dnolen: gotta come up with a catchy name for the component, of course

20:22 dnolen: that's going to be the blocker

20:22 something about solipsism

20:26 rplaca: doody1: yeah, it somewhat sucks. But not quite as much as you would think, generally

20:29 muhoo: dnolen: is there any particular reason why the second arg to om/build-all needs to be a vector not a list? is it because get-in is used inside om?

20:29 dnolen: muhoo: the argument to build all can be any sequence

20:30 muhoo: but the requirement is that everything in app-state be associative for performance reasons

20:30 muhoo: cool, thanks.

20:30 dnolen: muhoo: you can of course make other things into cursors, but you do so at your own risk

20:30 muhoo: I only tests w/ things that satisfy map? or indexed?

20:31 muhoo: pretty sure lists do neither, that'd explain it then.

20:32 dnolen: muhoo: yeah leave lists and lazy-seqs out of your app-state

20:33 muhoo: you can of course *use* lazy-seq operations on things that you get out of the app state and that will work just fine.

20:33 muhoo: makes sense, thanks for om. i was working through the om-react-tutorial and there was a comment that the arg must be a vector for unknown reasons. i wanted to know what the unknown reasons were.

20:34 https://github.com/jalehman/react-tutorial-om, FYI

20:39 sritchie_: dnolen: one more Q - can you recommend a good way of passing an index in with build-all?

20:39 to get the index of the TODO item, for example

20:40 dnolen: actually, I can probably just zip an index on to each todo

20:40 dnolen: sritchie_: yep

20:40 sritchie_: boom, works

20:50 mlb-: $DAYJOB is massively enterprise. I want to deploy a webapp. What are my options?

20:51 muhoo: mlb-: build a uberjar and run it in a container?

20:52 sorry, war, not uberjar

20:52 mlb-: https://github.com/weavejester/lein-ring

20:52 mlb-: muhoo: I've been pondering that, but what's necessary to run a container environment on Windows?

20:53 muhoo: pretty sure tomcat runs on windows, but i've never tried it. i'd be shocked if it didn't tho.

20:53 arrdem: yep it does

20:53 $google apache tomcat war deploy windows

20:53 lazybot: [Apache Tomcat 6.0 (6.0.39) - Tomcat Web Application Deployment] http://tomcat.apache.org/tomcat-6.0-doc/deployer-howto.html

20:53 mlb-: ah, okay. Will do some research and probably pester people in #tomcat then :P

20:54 thanks, muhoo and aaronj1335_

20:54 err, arrdem

20:54 this tabcomplete :P

20:54 muhoo: np

20:55 arrdem: np

21:06 muhoo: speaking of lein-ring, is there a way to pass the nrepl start? args on the command line instead of mucking around in the source of (someone else's) project.clj?

21:07 i.e. i naively tried "lein ring server-headless :nrepl :start? true" and got a spectacular fail

21:08 arrdem: wouldn't you have to actually write your own main method? otherwise unless the args are stored there you're pretty much hosed since unlike in Python we don't have sys.argv

21:10 sritchie_: dnolen: my specific use, btw, is building a stopwatch -

21:10 so I'm hitting the state for a rerender every 10ms, to update the stopwatch

21:10 dnolen: qq - I KNOW nothing changes in the rest of the app until certain events take place

21:10 muhoo: arrdem: naw, there's some magic here i remember learning about from technomancy, looking through my notes, i think i'll get it

21:11 update-in, IIRC

21:11 sritchie_: dnolen: is there some preferred way to isolate the updates to the stopwatch timestamp from the rest of the app? It does need to be in the state, since when you hit "mark" I need to be able to create an athlete row (a todo, basically) from that current time

21:12 dnolen: feels like local state, but other components need to read it, and "requesting" a local timer state via channels seems like the wrong approach

21:16 muhoo: arrdem: fwiw, this was the magickal incantation that did what i wanted lein update-in :ring:nrepl merge "{:start? true :port 7777}" -- ring server-headless

21:17 arrdem: muhoo: truly an incantation worthy of my black grimoire...

21:17 * muhoo enjoys the blood of the goat he just sacrificed

21:27 sritchie_: any advice on how to convert a record to a normal map in cljs?

21:27 or to print it as a map, without the reader literal for the record class?

21:30 muhoo: sritchie_: (into {} ??

21:30 lazybot: muhoo: What are you, crazy? Of course not!

21:30 muhoo: lol lazybot

21:30 sritchie_: muhoo: ugh, duh

21:31 muhoo: I was surprised to see that records don't round trip through the reader i cljs

21:31 muhoo: i'm not too surprised by much with cljs. it's very young. very cool tho. just starting to play around with it.

21:31 sritchie_: for sure

21:33 muhoo: i'm hoping to backscroll later through the stuff you and david were talking about, looks fascinating.

21:34 ,into

21:34 clojurebot: #<core$into clojure.core$into@130b13c>

21:34 muhoo: $into

21:34 arrdem: (inc magnars) ;; clj-refactor looks awesome

21:34 lazybot: ⇒ 3

21:34 muhoo: #into

21:34 ~into

21:34 clojurebot: Titim gan éirí ort.

21:35 arrdem: ##into

21:35 &&into

21:35 lazybot: java.lang.RuntimeException: Unable to resolve symbol: &into in this context

21:35 arrdem: $google clojurewiki lazybot

21:36 muhoo: ~into is like a magical transformer ring. (into {} something) works for a surprisingly wide variety of things.

21:36 clojurebot: Ok.

21:37 muhoo: ~into is like a magical transformer ring. i.e. (into {} something) converts a surprisingly wide variety of things into maps.

21:37 clojurebot: In Ordnung

21:39 dsrx: ,(into {} "what what")

21:39 clojurebot: #<ExceptionInfo clojure.lang.ExceptionInfo: Don't know how to create ISeq from: java.lang.Character {:instance \w}>

21:39 dsrx: ,(into {} true)

21:39 clojurebot: #<ExceptionInfo clojure.lang.ExceptionInfo: Don't know how to create ISeq from: java.lang.Boolean {:instance true}>

21:39 muhoo: hahaha

21:40 ,(into {} [["what" "what"]])

21:40 clojurebot: {"what" "what"}

21:40 dsrx: boring

21:41 muhoo: ok, my factoid is not very precise. feel free to correct it.

21:44 dsrx: contrast with a Real Language that can get things done, like PHP http://ideone.com/GdLvdO

21:44 `oetjenj: hey, anyone can hint me to some good tutorials on bdd (preferably of course with clojure) with more complex examples than just calculators and/or very basic stuff?

21:44 arrdem: `oetjenj: bdd?

21:44 hiredman: calculators are the bdd killer app

21:45 akyte: Behavior driven development. I think the name is usually overkill. It's closer to "more semantic tests"

21:45 `oetjenj: arrdem behavious driven development

21:45 dsrx: bondage and discipline development

21:45 `oetjenj: ;)

21:49 oetjenj: but seriously i love to learn more about bdd, but i haven't been able to find anything useful beyond those very simple examples

22:29 sritchie_: dnolen: undefined.onChange: No protocol method ICursor.-path defined for type : [object Object]

22:29 hmm

22:30 when I try to set some local state

22:30 one idea, back in a minute

22:31 dnolen: yeah, happens when I stick an onChange handler onto a text field

22:31 (om/set-state! owner :racer-text (.. e -target -value))

22:44 technomancy: oetjenj: there's nothing really language-specific about bdd

22:44 oetjenj: the language-specific stuff is just "how do I write a test?"

22:46 benkay: i'd like to test that a byte-array that I've generated (via (.toByteArray (biginteger my-int))) matches a test-case hex string - where would you suggest I look for parsing the byte array into hex for comparison?

22:48 seangrove: $google clojure parse byte array to hex

22:48 lazybot: [character encoding - Clojure's equivalent to Python's encode('hex ...] http://stackoverflow.com/questions/10062967/clojures-equivalent-to-pythons-encodehex-and-decodehex

22:48 benkay: alternatively, I'd eagerly welcome reading material to improve my first-principles understanding of how to round-trip int -> bytes -> hex -> int

22:49 i've seen that one, yes. i'm ignorant on the subtleties of int -> byte and byte -> hex; hex -> int i think i have a handle on though.

22:50 seangrove: benkay: Just a bit of teasing. If you've read that SO page, you're probably not too far away. Just play around with it.

22:51 benkay: oh hey! i just found ztellman's byte-streams library. am i going to cripple my understanding of clojure/jvm byte operations by using that?

22:55 seangrove: The Salesforce world is a dark one

22:57 Heh, the man of the hour joins us

22:59 gtrak: I think I can implement piggieback for jruby, does that sound like a terrible idea?

23:05 seangrove: gtrak: What does that mean...?

23:05 Clojure => compile to ruby => send to remote ruby env => execute => roundtrip result?

23:06 gtrak: like... sooo, nrepl middleware that evals to a ruby runtime, just to make it easy embed

23:06 easy to embed*

23:06 I'd like to run a ruby repl and clojure repl in the same process.

23:06 for demo purposes

23:07 sritchie_: dnolen: if you're around, I think this may be a bug...

23:08 arrdem: has anyone tried to use core.logic to do pruning for AI search problems?

23:09 sritchie_: dnolen:(u/log (implements? om/ICursor (aget (.-props owner) "__om_cursor")))

23:09 is printing "false"

23:10 benkay: okay so using byte-streams, evaluating (print-bytes (.getBytes "foo")) shows foo in the hex quite clearly but (print-bytes (.toByteArray (biginteger 1096))) just shows me .H

23:18 noonian: anyone know why i get this warning when trying to implement INamed in cljs (the code seems to work fine)? "WARNING: Symbol cljs.core.INamed is not a protocol"

23:41 novochar: [1 :two "three"] ; what is `:two` here?

23:42 is [1 :two "three"] equal to [1 {:two "three"}]?

23:44 ddellacosta: novochar: no

23:44 novochar: what are you trying to do?

23:44 novochar: How would you access the number 2 in a (def aList [1 2 3]) ; I'm reading that items in a vector can be accessed by index

23:44 ddellacosta: I'm reading http://clojure-doc.org/articles/tutorials/introduction.html

23:44 ddellacosta: ,(nth [1 2 3] 1)

23:44 clojurebot: 2

23:44 pbostrom: vector supports get also

23:45 novochar: Thank you

23:45 dissipate: novochar, no. the first thing is a vector containing three values, the second is a vector with 2 values

23:45 novochar: What is :two in [1 :two "three"]

23:45 pbostrom: :two is a keyword

23:45 ddellacosta: novochar: what do you mean, what index is it at? what thing is it?

23:45 novochar: a keyword for?

23:45 pbostrom: keyword is a datatype

23:45 novochar: an atomic value of some sort, like in erlang maybe

23:45 dissipate: novochar, a keyword is a value

23:46 novochar, it is an immutable value

23:46 pbostrom: http://clojure.org/data_structures#Data Structures-Keywords

23:46 dissipate: novochar, have you tried the clojure koans series?

23:46 arrdem: http://clojure.org/data_structures#Data%20Structures-Keywords

23:47 * arrdem mutters darkly about url encoding

23:47 dissipate: pbostrom, i thought use of 'get' was optional

23:48 arrdem, are you going to mutter about punycoding?

23:48 pbostrom: dissipate: true, I guess I should say it implements IAssociative

23:49 arrdem: dissipate: sadly this also falls in the set of useful yet disgusting things which I'm willing to mutter about.

23:49 there was a double URL encoding bug that took me weeks to find in one of my previous projects :

23:49 dissipate: arrdem, punycoding: the bastardization of those 'other' languages. :P

23:50 benkay: i'm working on producing some byte arrays to be sent over tcp. i'm a total novice on this level of the jvm; what tools should I be using to serialize stuff onto the wire?

23:51 arrdem: whatever the JVM uses for sockets, combined with Clojures EDN formatting, (str) and .toByteArray I assume...

23:51 not the most efficient thing in the world but it should work...

23:52 benkay: complicating this is some C++ on the other end of the connection expecting to see ints and chars and specific magic bytes

23:52 dissipate: benkay, you might want to look into 'protocol buffers' or 'thrift'.

23:52 arrdem: benkay: do you have a specific byte frame protocol you are attempting to work with?

23:53 dissipate: benkay, protocol buffers is great for that. it is language independent. you compile the API to the language you are using.

23:54 benkay: dissipate: thrift and protobufs look awesome and maybe precisely what i'm looking for!

23:54 dissipate: benkay, https://code.google.com/p/protobuf/

23:55 benkay, sure sounds like it. :D

23:55 benkay: arrdem: it's the bitcoin protocol and about as poorly specified as one would expect. there isn't a 'byte frame protocol' so much as a shitty wikipedia page (https://en.bitcoin.it/wiki/Protocol_specification)

23:56 well, mediawiki but same diff.

23:57 arrdem: benkay: I think someone already built a BTC client for Clojure...

23:57 benkay: or are you looking to expose the "raw" network commands?

23:57 if you do I'll add hacking out a doge port to my todo list...

23:58 benkay: I'm actually working on a watcher for arbitrary cryptocurrencies adhering to the baseline bitcoin protocol.

Logging service provided by n01se.net