#clojure log - Aug 16 2013

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

1:36 heath: what's a vector?

1:36 i hail from python and javascript with some experience in haskell

1:37 http://www.cplusplus.com/reference/vector/vector/

1:37 that explains

1:37 similar to the math concept

1:38 callen: heath: no

1:38 heath: it's not the same.

1:38 brehaut: a vector is closer to an array in javascript or a list in python

1:38 but backed by a trie structure

1:38 its associative with integer keys

1:38 heath: tree?

1:38 callen: heath: trie.

1:38 brehaut: trie

1:38 heath: wow

1:38 ya really meant that

1:38 kk

1:39 brehaut: its cheap to add and remove from the end of a vector,

1:39 callen: heath: hash array mapped tries. (HAMT)

1:39 brehaut: (rahter than the start like a list)

1:39 and it has fast (near constant time) lookup for indices

1:39 callen: heath: the data structures are designed to be persistent, that's how you have efficient immutability.

1:40 heath: without it, you'd basically have to copy-on-create or copy-on-write.

1:40 which, you know, sucks.

1:40 and COW doesn't even really make sense in this context.

1:40 brehaut: oh, and (unlike python lists) vectors are values

1:41 callen: heath: http://www.infoq.com/presentations/Value-Values

1:41 heath: how could you make use of a vector's value?

1:41 callen: for any wondering, yes carmine is awesome.

1:41 brehaut: compare {(1,2): "a"} and {([1,2]: "b"} in python

1:41 callen: ,(conj [] :blah)

1:41 clojurebot: [:blah]

1:41 brehaut: ,{[1 2] "b"}

1:41 clojurebot: {[1 2] "b"}

1:42 callen: ,([:a :b :c :d] 2)

1:42 clojurebot: :c

1:44 brehaut: (you cant use a python list as a key because it has no intrinsic value)

1:44 (a tuple (or clojure vector) on the other hand has a value derived from the values of its members)

1:48 glosoli: newbie here, what is the equivalent when doing it Clojure way, when I for example define some sort of Person object with various attributes to it name, last name, address and tt ? was considering some sort of Map though

1:49 brehaut: just use a map

1:49 {:name "foo bar" :address "123 fake st"}

1:50 slightly apropos http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/

1:52 glosoli: brehaut: thanks

1:57 callen: brehaut: people are way too eager to grant data "thinghood"

1:57 (I said it that way instead of saying "reify" so as to avoid confusion)

2:20 jwpalmer: pwd

2:20 lazybot: #clojure

2:20 jwpalmer: gah - sorry

2:20 heh

2:32 heath: are a lot of you using clojure within your workplaces?

2:32 i've been dependent upon coffeescript

2:33 started to learn c++ to write node addons, i figure i'll need them at some point

2:33 but i'm interested in learning clojurescript

2:33 so many things to do! :)

2:40 SegFaultAX: Rowing is hard work.

2:40 TEttinger: heath, I think the south african clojure users are awake now. there are some smart businesses starting to see the functional programming light over there, and the pattern seems to be repeating

2:41 for certain tasks, you want the benefits of interop, a strong ecosystem, and stability that come with a language like clojure, more than you want anything else.

2:44 I tried writing a game in clojure and the performance left something to be desired. for a normal app, you don't have 16 AI creatures that need to scan a large map in 1 ms or 2, to keep up with a user hammering keys lightning fast. for a normal app, clojure's performance is fine.

2:46 heath: what's the value in immuatable collections, especially in the context of clojurescript/

2:47 SegFaultAX: heath: Mutation free code is inherently easier to reason about.

2:47 amalloy: heath: what's the value in immutable strings?

2:47 SegFaultAX: heath: Data in, data out.

2:47 But more importantly /values/ in, /values/ out.

2:48 noonian: you get referential transparency pretty much for free

2:48 SegFaultAX: noonian: That's not strictly a side effect of immutable data.

2:48 noonian: don't have to think about not mutating things or protecting things from mutation with copying

2:48 heath: for some reason, i thought this was for languages like haskell :) a desire for mutation free code

2:49 it kind of threw me off to see this in clojure

2:49 SegFaultAX: heath: In Clojure we have both. Immutable data structures are the default, but you can always drop down to good ol bit bashing when you need to.

2:49 The nice thing is, it's pretty rare in general that you even need those facilities.

2:50 noonian: SegFaultAX: but you tend to write code with that property when everything defaults to being immutable

2:51 SegFaultAX: I guess you're right its not directly from immutability my bad

2:51 SegFaultAX: noonian: The term you're looking for is probably purity, anyway.

2:51 Referential transparency is orthogonal.

2:52 noonian: purity huh

2:52 SegFaultAX: (Unfortunately those words are often conflated with each other, but they are distinct)

2:52 noonian: maybe, but then I sound like the haskell guys

2:52 SegFaultAX: noonian: You say that like it's a bad thing! :D

2:53 noidi: SegFaultAX, is it possible for a function to be pure without being referentially transparent, or vice versa?

2:53 noonian: I just think its kind of preachy and monads were invented so they can say 'we have the purist functional language of them all'

2:54 SegFaultAX: noonian: Monads are far, far older than Haskell.

2:54 noonian: And the monads you know and love from Haskell are only a very particular formulation of monads anyway.

2:54 noonian: not sure if you mean the theory or the technique, but no one called them monads when using them before

2:55 SegFaultAX: noonian: The fact that you weren't aware of it doesn't mean anything.

2:55 You personally, I mean.

2:55 noonian: weren't aware of what?

2:55 SegFaultAX: Monads.

2:55 Or category theory in general.

2:56 noonian: heh, you can use monads without calling them that

2:56 I know they came out of category theory, but you're right, I never heard of them before I heard of haskell

2:57 SegFaultAX: noonian: But that doesn't mean monads only /just/ popped into existence, and certainly not when /you/ became aware of Haskell.

2:57 noonian: and I'm not saying they did

2:57 sorry if I offended you sire

2:57 sir*

2:57 SegFaultAX: but no one called them monads when using them before < not sure what other way there is to interpret that, then.

2:58 noonian: Sire is fine.

2:58 noonian: forget it then, just interpret it as drunken ramblings

2:59 SegFaultAX: noidi: Sure!

3:01 noidi: So long as an expression/function/process/whatever can be substituted for its result or value without changing the semantics of the overall program, it can be considered effectively referentially transparent.

3:01 noidi: That really doesn't have much at all to do with mutating state.

3:02 noonian: but you can also have pure functions which mutate data in their local scope yes?

3:02 SegFaultAX: noonian: Depends on the definition of purity I guess. But in a strict sense, no.

3:03 noonian: I mean even Haskell can't be considered pure of you regard the mutation of the processor state to be a side effect.

3:03 In Clojure nothing is pure. The JVM is a black box of statefulness.

3:04 We might consider most stuff to be /effectively/ pure because out our level of abstraction, we are safe from most of the ills of side effecting code.

3:04 noonian: the wiki for pure function only talks about 'observable' side effects, and always evaluating to the same result given the same input (I know wiki isn't authoritative)

3:04 SegFaultAX: noonian: Right, but observable to whom is the question.

3:04 noonian: semantically observable

3:05 SegFaultAX: Exactly.

3:05 noonian: yeah, so if you are the processor then you're out of luck. But as a programmer, we get to have pure functions that may or may not mutate state internally

3:06 SegFaultAX: Haskells state monad uses this trick extensively. It creates an opaque memory region to localize mutation, but since literally nothing else can see into that mutation, it can be considered pure.

3:08 noonian: In Clojure we have to remember that we're interoping with a fundamentally stateful host, so nothing we write is truly pure. It's doing IO and stuff /all the time/. It's arguable if you can even consider it effectively pure, but I'm not pedantic enough to argue the point beyond that.

3:08 noonian: hmm, I don't understand that point

3:09 how is a function, say (fn [x] (+ x 10)), not pure?

3:09 SegFaultAX: noonian: The JVM is not pure.

3:10 noonian: but that doesn't mean you can't write pure functions that run on the jvm

3:10 SegFaultAX: noonian: Meh.

3:10 noonian: Like I said, it's a pedantic argument at best.

3:10 noonian: I can agree with that at least :P

3:11 actually, that was the point I tried to make originally

3:22 noidi: SegFaultAX, ah, right. so a function calling (reset! nobody-uses-this :foo) is referentially transparent but impure

3:24 noonian: hmm, I don

3:25 don't think its referentially transparent either, because if you replaced it with the return value it would change the programs behavior

3:31 I guess according to the definition of purity segfault put forth earlier, any referentially transparent function that uses mutation internally wouldn't be pure

4:45 supersym: SegFaultAX: I recall RH wrote somewhere the 'if a tree falls in the forrest but no one is around, does it make a sound?' parabole, which was internal mutations as well I believe

4:46 I hadn't related it to monads yet though so I think that was a nice summary of some stuff somewhere I knew subconsiously

4:52 callen: parable

5:06 supersym: really, I made an error? nooo.... or are you french? Are you French Clyde?

5:06 sorry, I'm baked :P

5:06 Raynes: supersym: Need more edibles.

5:09 supersym: lol... yea

5:10 * ucb waves

5:35 turbopape: Hi all,

5:35 anyone can share experience working with Riak / Welle ?

5:35 is it sable ? Well maintained ?

5:38 schmir: turbopape: I'm using langohr from michael klishin...he's quite responsive

6:50 antares_: turbopape: it is but don't use master, I'm breaking many things for 2.0

6:50 Riak is wonderful if its data model fits your problem well. Unbreakable in prod, easy to operate.

6:51 can be a royal pain to develop against, too

6:54 Only a few places left for the 2 day Munich Clojure workshop in October: http://clojureworkshop.com

7:00 callen: oi vey. finally done.

7:01 https://github.com/bitemyapp/bulwark

8:36 noncom: hi, in clojurescript, how do i create a Date object and then setFullYear on it?

8:36 currently I do (.setFullYear (js/Date. ) 2000) but it does not work

8:37 says Uncaught Error: No protocol method ILookup.-lookup defined for type object: Fri Aug 16 2013 16:09:29 GMT+0400 (Russian Standard Time)

8:38 i would believe that it can't call the method on the date-time string, but it is not a string, the (type (js/Date.)) gives function Date() { [native code] }

8:46 edlothiol: noncom: (.setFullYear (js/Date. ) 2000) does work for me, are you sure that's what you're using? though note that setFullYear doesn't return the date object, so you probably want something like (let [d (js/Date.)] (.setFullYear d 2000) d)

8:47 mpenet: ,(doc doto)

8:47 clojurebot: "([x & forms]); Evaluates x then calls all of the methods and functions with the value of x supplied at the front of the given arguments. The forms are evaluated in order. Returns x. (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))"

8:47 edlothiol: or that

8:48 tbaldridge: dnolen: have you seen the problem described in http://dev.clojure.org/jira/browse/ASYNC-2 recently?

8:52 mdrogalis: tbaldridge: Is there any plans to add a "topic"-like queue-construct to core.async?

8:52 E.g. a queue that multiple people can consume the same messages from.

8:54 tbaldridge: mdrogalis: you mean pub/sub?

8:55 H4ns: is there function that returns a function's name, if it has one?

8:55 noncom: edlothiol: actually, i have a clojuric datastructure that pronts to the console as {:value "2000"} then, when I try (.setFullYear (js/Date. ) (:value my-struct)) i get that error

8:56 now i see that "2000" in the structure is not a stringwhen i print (type) of it, it is function String() { [native code] }

8:56 mdrogalis: tbaldridge: Pretty much, yup

8:56 noncom: and if i (js/parseInt) on it, i get NaN

8:57 ,(js/Date.)

8:57 clojurebot: #<CompilerException java.lang.RuntimeException: No such namespace: js, compiling:(NO_SOURCE_PATH:0:0)>

8:57 noncom: sure

8:57 tbaldridge: mdrogalis: no, there are no official plans. in clojure.core.async.lab there are primitives for pub/sub but they are experimental as they use low level core.async protocols.

8:58 mdrogalis: that being said, you can build pub/sub from normal channels in about 30 lines of code or so

8:58 mdrogalis: H4ns: (:name (meta (var f)))

8:58 tbaldridge: Yeah I was thinking about that this morning. Doesn't seem difficult.

8:58 H4ns: mdrogalis: *bow*

8:58 mdrogalis: H4ns: :)

8:58 tbaldridge: Why go down to low level protocols to do it in exp then?

8:59 noncom: edlothiol: somehow that "2000" is not a string...

8:59 tbaldridge: mdrogalis: the nice thing about that approach is that you can build your own semantics that work for you. E.g. do you add new subs via a subscribe channel, or do you call a function that updates an atom, etc.

9:01 mdrogalis: tbaldridge: Intriguing.

9:01 noncom: edlothiol: then what is it?.. i have got it by calling (subs) on s string

9:09 ok, i have got why it happens. (str), (subs) and other stringy functions in clojurescript return not javascript strings but something other... how do i make it into javascript string again?

10:10 anybody fluent with clojurescript strings here?

10:41 Anderkent: did clojure.contrib.generic.functor survive the contrib apocalypse?

10:41 I'm looking for fmap in particular

10:43 llasram: Anderkent: I don't think it did. Of the recent category theory libraries I know at least fluokitten has an implementation of functors and fmap https://github.com/uncomplicate/fluokitten

10:43 Anderkent: mhm. I found algo.generic which does does have it

10:43 llasram: Oh, ok cool

10:44 Anderkent: but it's nowhere near as powerful

10:45 (as what's in fluokitten, that is. I don't need all that power tho)

11:10 papercup: Hi, does anybody use pallet here (specially with node-list option) ?

11:21 boodle: hi, can someone point me to an example of selecting an aggregate (sum/count etc) data using clojure.java.jdbc (not w/ a basic SQL stmt but it's select fn)

11:27 Anderkent: boodle: I think you can use strings as identifiers.. Something like (select [{"COUNT(id)" :count}] :tablename) ? Didn't try it though

11:27 boodle: Anderkent: great, tyvm!

11:28 was trying to figure out 'entities'.. that helps alot

11:28 Anderkent: entities sounds like sqlkorma not the simple jdbc wrapper

11:28 with korma it's easier :P

11:28 ah nvm it also has entities

11:29 boodle: Anderkent: and works great. I'm converting away as no pass/fail/anysort of results returned from Korma on Updates

11:29 Anderkent: oh. That sucks.

11:29 luckily we have an append-only db so don't have to worry about that! :P

11:30 boodle: Anderkent: heh lucky

12:07 abp: cemerick: around?

12:08 cemerick: abp: some :-)

12:10 abp: cemerick: Can I easily re-add those whitespaces? Would you probably merge as is also?

12:10 cemerick: Regarding https://github.com/cemerick/friend/pull/70

12:10 cemerick: abp: I'd like to keep the blame clean. You should be able to selectively stage just the relevant changes to the file(s)?

12:11 abp: cemerick: Oh ok, will try tha, I'm a git newb.

12:13 cemerick: abp: git gui will allow you to do it easily, or you can use git add -i and work through it on the command line

12:18 Anderkent: if you're new to it i'd recommend using a gui to do the staging - much easier than exploring the somewhat awkward interface of git add -i

12:18 gitk does pretty well I think

12:18 abp: cemerick: Anderkent where using magit

12:19 cemerick: Anderkent: gitk is just a viewer, can't stage anything there AFAIK

12:19 bbloom: the best feature of git add -i is that it can launch vim for editing patches :-)

12:20 i use add -p frequently to review my changes when i commit them

12:20 cemerick: abp: selective staging is in magit, though I don't know anything about how it's used.

12:20 Anderkent: sorry, ment gitg

12:21 cemerick: bbloom: I've become unreasonably picky about clean commits since I started using git gui and then sourcetree for staging all my commits.

12:21 bbloom: cemerick: sure, at least for publicly sharing commits

12:21 i tend to have dozens of WIP and "hack" and other nonsense commits on a branch

12:21 and then i rebase a bunch

12:22 i'm only a tiny bit interested in clean commits in history so much as i am understanding my own commits, which necessitates they be clean while working with them

12:23 abp: yeah, I'm more puzzled about how to stage my commits again

12:23 cemerick: Anderkent: oh, right. Yeah, gitg is okay. I never used it because it shows sources with such a large font. :-P

12:24 Anderkent: abp: if you want to keep each commit, you can rebase --interactive and mark them both as 'edit'... But i'd just take your current state, git reset master, git add -i, select meaningful changes, and commit to create a new commit on top of master with just the right changes

12:31 rasmusto: bbloom: if you're using vim for git edits, have you used fugitive.vim?

12:31 bbloom: rasmusto: yeah, i have it installed, but i use it very sparingly

12:32 rasmusto: bbloom: I love using :Gdiff and dp/do to do the equivalent of 'git add --patch', or to just manually edit the index

12:33 bbloom: rasmusto: yeah, i've used it a few times, but i kinda suck at gitdiff. i use :Gmove all the time though to rename a file without having to close/reopen a buffer

12:34 rasmusto: bbloom: I need to rename files more, I tend to stick with my filename/fn name choices to a fault

12:34 heh

12:35 steckerhalter: I'm a bit confused... shouldn't clojure.core be available in any project? yet `eval` is not as it seems in some projects I try

12:36 Anderkent: steckerhalter: the (ns ..) form imports clojure.core stuff

12:36 if you're evaluating outside a ns (for example in a repl you say (in-ns 'new.ns) ) then you might not have core functions referred

12:37 shiranaihito: is anyone happily writing Clojure in IDEA?

12:37 Anderkent: though hm calling them via clojure.core/something should still work

12:37 shiranaihito: I tried it, but found it lacking in comparison to CCW. Might be my knowledge of eclipse is better than of IDEA

12:37 (i mean the second is definitely true, but it might be why I found ccw better)

12:37 shiranaihito: Anderkent: what's CCW?

12:38 hm

12:38 steckerhalter: anderkent: ah, ok. it's ac-nrepl that calls eval without "clojure.core" and that produces an error then in Emacs

12:38 shiranaihito: well, i know IDEA _much_ better than Eclipse, would prefer to work with it instead of anything else, pretty much

12:38 justin_smith: shiranaihito: maybe counterclockwise, the clojure ide for eclipse

12:38 shiranaihito: ah, right

12:38 Anderkent: yeah

12:39 shiranaihito: JetBrains' IDEs are simply the best out there

12:39 so i'd like to keep using them even with clojure :)

12:40 but yeah.. the integration is not quite "there" yet :p

12:41 Anderkent: one thing i remember in la clojure was that it would do unsafe refactorings and be wrong about it without prompting

12:41 but that was a while ago and maybe has changed since

12:43 shiranaihito: oh :/

12:50 technomancy: a few of the issue comments on idea's lein integration gave me the impression they were a bit confused about how things worked

12:51 but that was like a year ago

12:54 abp: interactively staging with magit is wicked

12:54 steckerhalter: abp: why?

12:54 Anderkent: is that a positive wicked or a negative wicked

12:54 :P

12:55 abp: :D

12:55 positive

13:01 * steckerhalter is trying pedestal

13:05 abp: steckerhalter: Already read tutorial etc?

13:05 technomancy: does anything besides nrepl.el use the target/repl-port file that leiningen writes?

13:06 rasmusto: technomancy: vim-fireplace does

13:06 steckerhalter: abp: going through the app-tutorial

13:06 Anderkent: yeah, but it looks at it in the wrong place afaik

13:06 rasmusto: there's already a patch for the 2.3 moved repl-port file

13:06 technomancy: rasmusto: oy; I was about to fix that

13:06 ystael: Anderkent: i never knew before why i sometimes found myself in a strange ns without clojure.core referred! thank you :)

13:07 technomancy: rasmusto: is there a discussion you could point me to?

13:07 Anderkent: technomancy: there's a github issue.

13:07 i'd link but github is dying

13:07 rasmusto: technomancy: https://github.com/tpope/vim-fireplace/pull/98

13:07 technomancy: dang it

13:08 when are they going to switch github issues over to a distributed system like everything else =P

13:08 rasmusto: thanks!

13:08 Anderkent: 98 and 88 it is

13:08 mdrogalis: Seriously bad day for GitHub.

13:08 rasmusto: technomancy: np

13:09 Anderkent: seriously bad two days for github :P

13:11 steckerhalter: I imagine it to be a tough job to keep this running with so much data and users...

13:11 Anderkent: it's not the data and users, it's the ddos

13:11 usually

13:12 steckerhalter: hmm, right, sure it's just that?

13:12 TimMc: Yes.

13:12 Anderkent: when it's completely down instead of just slow I'd guess it's mostly ddos

13:12 when you just get a random unicorn it might be some unlucky deadlock or sth

13:12 mdrogalis: GH was in Philly for a drink up last weekend. I was told they have a team of 4 exclusively to deal with stuff like this

13:13 pandeiro: anyone know about how long it takes to build openjdk7 on something like an i5? minutes? hours?

13:13 steckerhalter: and what does it benefit them DDOSing github?

13:13 Anderkent: steckerhalter: there are a couple possible motivations

13:14 technomancy: bragging rights I guess?

13:14 Anderkent: one for example is that it acts as a proof of capability. If you're trying to sell ddos to someone and you can say 'we took down github for 20 minutes' it shows you know your stuff

13:15 other, as technomancy says, is bragging rights. Then comes general maliciousness

13:15 and if you have your tinfoil hat on I can tell you about githubs competitors

13:16 ystael: Anderkent: :( that's just sad. i can see why someone might want to ddos any number of people out there, but hitting github just makes you a jerk.

13:17 Anderkent: hitting github proves you can take down a serious infrastructure, not just some random website

13:17 it's in the right place between huge things that ddosers cant really touch (google) and small things that no one is gonna be impressed by (your local school webpage)

13:18 i'm not saying its the only possible target, but it's one of them, so it gets its own share :

13:18 i'd be curious on what kind of ddos they're doing tho

13:19 dnolen: tbaldridge: ping

13:20 tbaldridge: dnolen: pong

13:20 Anderkent: .. for a moment there i was like 'wow, it aligned'

13:20 mdrogalis: lol

13:22 dnolen: tbaldridge: so I'm thinking about a channel where I want the throttle to be toggleable, like be able to flip it on or off

13:22 abp: what happens if I force-push to github after resetting my local branch and already opened a pull-request?

13:22 Anderkent: abp: the pull is updated

13:22 it 'just works' :)

13:22 abp: oh cool

13:22 thanks!

13:23 tbaldridge: dnolen: throttle being, the buffer drop size?

13:23 dnolen: tbaldridge: no like a milliseconds throttle

13:23 tbaldridge: it takes a channel of events and only emits them at a throttle speed

13:23 throttled

13:23 bbloom: dnolen: what about 3 channels: 1) the messages 2) the timeouts 3) a control channel to set the timeout speed?

13:23 dnolen: tbaldridge: but the point here is about the flip on/off

13:24 bbloom: I'm looking for the absolutely most succinct solution that gets the job done in this case

13:24 bbloom: dnolen: you can encapsulate the timeout channel & the control channel into a little timeout machine

13:25 that way you could reuse a synchronization process that just syncs one channel to any arbitrary interval channel

13:25 dnolen: bbloom: yes I know the obvious ways to do this - I want to know if there's something different, smaller|simpler is key

13:25 tbaldridge: dnolen: what's the use case? are we thinking of creating thousands of these? or why does it need to be so small?

13:26 dnolen: tbaldridge: I've been working this autocompleter blog post / code for a week now

13:26 tbaldridge: autocompleter takes throttle query strings from input field, 750 msecs throttled

13:26 tbaldridge: but when the user switches over the menu selection, we defer control to the menu subprocess

13:27 tbaldridge: dnolen: right.

13:27 dnolen: tbaldridge: this can happen via mouse or arrow keys, autocompleter process freezes at this point

13:27 tbaldridge: So we're just creating a single one of these throttled chans in this example.

13:27 dnolen: tbaldridge: but the menu subprocess needs the unthrottled key stream to know to exit

13:28 tbaldridge: it sounded simpler to me and generally useful to have some sort of generic toggle pattern - so I could disable to throttle when I had the channel to the menu process

13:28 s/had/hand

13:32 tbaldridge: dnolen: hold on...I'm writing up something

13:37 dnolen: I think this is all you need: https://gist.github.com/halgari/6251731

13:37 takes an input and then outputs [output-chan throttle-chan]

13:38 you can send :disabled or msec to the throttle-chan to change the behavior

13:38 eh, I had to edit that, there was a bug, if you reload it s/when/when-not on line 6

13:39 justin_smith: http://sprunge.us/NEWR?clojure really weird emacs / nrepl ppring behavior - anyone know what would do this, or how to track down what would do it?

13:39 *pprint

13:39 dnolen: tbaldridge: heh maybe I wasn't clear I already have a working throttle

13:39 tbaldridge: I only care about generic toggle

13:39 tbaldridge: but throttling isn't part of channels, so I don't know how it can be made generic

13:52 dnolen: tbaldridge: I think I may have to go w/ something closer to what bbloom suggested, untested version of what I'm thinking of http://gist.github.com/swannodette/6251850

13:54 tbaldridge: dnolen: that'd work, although I'd imagine that in your use case tap would be spinning up a go for each message right?

13:55 benedikt:

13:55 dnolen: tbaldridge: gist updated with something that makes more sense :)

13:56 tbaldridge: dnolen: so less of a throttle and more of a router

13:56 dnolen: tbaldridge: sorry I wasn't clear earlier - I never needed a throttle :)

13:56 tbaldridge: I have a throttle, I wanted a router/switch

13:57 tbaldridge: so we route into the throttle or we don't

13:57 tbaldridge: dnolen: so yeah, I think this sort of thing would be good for general use. This is kindof what clojure.core.async.lab is for. We can throw random stuff into there and see if people use it.

13:58 eric_normand: dnolen: an idea for a toggle https://gist.github.com/halgari/6251731

13:58 dnolen: added as comment

13:59 dnolen: eric_normand: I don't need an enhanced toggle :)

13:59 eric_normand: dnolen: then I misunderstood

14:00 `cbp: justin_smith: I've noticed that before. Are you using windows by any chance?

14:00 justin_smith: `cbp: ubuntu, latest build of emacs from gnu source

14:00 dnolen: eric_normand: also I'm of the mind if you can avoid returning maps you should

14:00 justin_smith: latest nrepl from marmalade

14:00 *nrepl-el

14:01 dnolen: an improved sketch for router/switch which can take N taps http://gist.github.com/swannodette/6251850

14:01 `cbp: justin_smith: ah, just asking cus I'm used to things not working randomly on windows but I think it's an emacs issue. When I printed on a terminal it would print fine.

14:03 justin_smith: yeah, emacs but, does not appear in a terminal repl

14:04 so theoretically if I pprint into a string, and then print the string...

14:04 eric_normand: dnolen: I'm confused. Where are tap and control defined?

14:05 dnolen: eric_normand: typos updated

14:05 justin_smith: `cbp: (println (with-out-str (clojure.pprint/pprint ...))) does not display the bug

14:05 so at least we have a workaround until someone fixes the elisp issue (whatever that is)

14:07 nacon: Suppose I have a function f that formats my variables. And I want to pass them to the format function, like this: (format "%s %s: %s" (f fst) (f snd) (f thrd)). Is there a way to reduce the number of f calls I have to write? I tried to "unpack" with apply, but was not successfull in passing them to format afterwards.

14:07 * nDuff is very, very happy to see core.typed's move to def-time metadata rather than a separate form

14:09 dnolen: gist updated again with `tapify`

14:10 technomancy: nDuff: yeah, was happy to see that

14:10 eric_normand: dnolen: looks cool. what do you use it for?

14:11 dnolen: eric_normand: I want to be able to route dynamically

14:11 eric_normand: so I may have a stream of key events and I want to dynamically apply a throttle or disable it

14:11 eric_normand: dnolen: much more sophisticated than my toggle! :)

14:12 dnolen: eric_normand: I think is a pretty handy one :)

14:13 eric_normand: dnolen: yes

14:13 rasmusto: nacon: something like this? (apply format "%s %s: %s" (map f [fst snd thrd]))?

14:14 IamDrowsy: rasmusto: haha :) i was typing the exact same line

14:14 rasmusto: IamDrowsy: IhadCoffee

14:15 dnolen: eric_normand: a lot of my ideas since Lambda Jam have changed, never returns maps if you can avoid, avoid multiplex or anything like it

14:15 eric_normand: also you were right about the race condition in my presentation

14:15 IamDrowsy: rasmusto: i am kind of drowsy.. you know... :)

14:18 nacon: rasmusto: Yes, perfect! Hmmm.. *scratches head*, I probably have to play with apply a bit to finally "get it".

14:20 rasmusto: nacon: just imagine the last argument without one set of parens

14:20 TEttinger: I honestly have no idea how that would work if you gave it the wrong number of args in the collection. ##(apply format "%s %s: %s" ["alpha" "beta" "gamma" "kappa"])

14:20 lazybot: ⇒ "alpha beta: gamma"

14:20 TEttinger: correctly!

14:21 rasmusto: TEttinger: !! nice

14:21 TEttinger: wow, I guess format discards args it doesn't need for the format string, great

14:23 justin_smith: sadly, it is not lazy: (apply format "a %s and a %s and a %s %s %s..." (range))

14:25 TimMc: &(apply format "a %s and a %s and a %s %s %s..." (range))

14:25 Oh, does it build an array?

14:25 justin_smith: it might

14:25 TimMc: Sorry 'bout that, lazybot.

14:25 lazybot: Execution Timed Out!

14:25 justin_smith: like I said, it is not lazy

14:26 TimMc: It calls to-array.

14:26 So... that probably tries to count the seq.

14:27 justin_smith: A laziness-compatible format may be nice

14:28 tbaldridge: what's the recommended way of using a JS lib from CLJs?

14:28 TimMc: justin_smith: (defn lazy-format [s & args] (apply format s (take 1000 args))) ;; no one needs more than 1000 string interpolations, dude

14:29 justin_smith: depending on the cost of realizing the elements, a version that only realized as many items as it needs may be nice

14:29 ystael: TimMc: what about gnu autoconf

14:30 bbloom: tbaldridge: first, see the Google Closure docs for externs

14:30 tbaldridge: then use it just like any other gclosure namespace, import goog, for example

14:31 TimMc: ystael: Nonsense, why would I ever build a tool that would have its arguments supplied dynamically?

14:32 I'm sure every usage will be in call position.

14:36 futile: tbaldridge: is clojure-py still alive?

14:37 Foxboron: futile: if you want a LISP on python i know a option :3

14:39 eric_normand: dnolen: race condition? wow!

14:39 gvickers: Is pomegranate the only option for dynamically loading classes and their dependecies?

14:39 eric_normand: dnolen: one question about your switch: why not pass the function you want down the control channel?

14:40 futile: Foxboron: what?

14:40 dnolen: eric_normand: you mean the tap that I want to apply?

14:41 Foxboron: futile: afaik, clojure-py is dead or rather low activity, but there is something called Hy if you want a LISP on python.

14:42 eric_normand: dnolen: right; tapify just does this: (apply f in args)

14:42 dnolen: and wraps it neatly in a map

14:42 dnolen: why not just pass f and args on control channel?

14:42 dnolen: do it right there inline?

14:43 dnolen: eric_normand: hmm, worth thinking about ... I broke out tapify because it might be useful elsewhere

14:44 eric_normand: dnolen: maybe it wouldn't work with your use cases

14:44 futile: Foxboron: setv :P

14:44 eric_normand: dnolen: I don't know how you could make a throttle with a regular function

14:45 dnolen: eric_normand: right

14:45 eric_normand: f in tapify must be a channel constructor

14:45 eric_normand: so (tapify throttle 200)

14:45 dnolen: eric_normand: yes

14:45 eric_normand: dnolen: makes sense

14:46 dnolen: keeps channel state around

14:46 dnolen: if you passed the constructor down the control channel (instead of an index), you'd lose state

14:46 dnolen: eric_normand: yes

14:47 eric_normand: dnolen: I am satisfied :)

14:47 Foxboron: futile: *cough* a few CL people there :3 Should note it has some clojure inspired features, but it isnt clojure. Just a LISP dialect

14:47 futile: Foxboron: gross

14:47 Foxboron: futile: it compiles down to Python AST, so you can import hy too python and python too hy

14:47 dnolen: eric_normand: now that you mention it, you can build a scheduler with this

14:47 Foxboron: futile: its neat

14:47 eric_normand: dnolen: yes?

14:48 futile: Foxboron: sounds neat. just wish it was more like clojure.

14:48 Foxboron: id rather use clojure-py if it compiles down to pythonast

14:49 eric_normand: dnolen: I've been thinking a lot about generic channel transformers

14:49 dnolen: eric_normand: a very simplistic one anyway

14:49 eric_normand: dnolen: such as map, filter, etc

14:49 edw: dakrone, you around?

14:49 dnolen: eric_normand: like reactive stuff?

14:49 Foxboron: futile: i don't think doe actually. Can't remember.

14:49 does*

14:49 dakrone: edw: yep

14:49 eric_normand: dnolen: they are tough when you have to take into account closing

14:49 futile: Foxboron: k

14:50 eric_normand: dnolen: yes

14:50 dakrone: edw: what's up?

14:50 eric_normand: dnolen: closing upstream vs downstream, etc

14:50 edw: Hi. I was having a prob with the clj-http client and was wondering if you might have some thoughts.

14:50 dnolen: eric_normand: yes though closing is less important in interactive applications than it would seem

14:50 eric_normand: just remove event sources at exit at the root, everything will get GCed

14:50 dakrone: edw: what's the issue?

14:50 edw: Basically, I'm trying to get connection pooling to work with a cookie store, without success.

14:50 eric_normand: dnolen: yes, you could just leave things open, never closing

14:51 edw: Sorry dakrone, long sentences…

14:51 dakrone: edw: no worries

14:51 eric_normand: dnolen: but would things get gc'd in complex scenarios?

14:51 dnolen: eric_normand: I've got some fun stuff here - https://github.com/swannodette/swannodette.github.com/blob/autocomplete/code/blog/src/blog/utils/reactive.cljs

14:51 eric_normand: yes

14:51 eric_normand: dnolen: like say we had a fan-in

14:52 tford: after looking at this for a while I think I finally understand it. tapify turns a function into a "tap" that can be passed to 'switch'. 'switch' takes an input channel, N taps, and a control channel.. a value sent on the control channel tells 'switch' which 'tap' to send values to. Is that right?

14:52 dnolen: eric_normand: it doesn't matter how complex the graph is

14:52 eric_normand: just remove event sources at exit at the root

14:52 s/at/and

14:52 eric_normand: dnolen: I suppose if you are careful to remove them all

14:52 dnolen: from the root

14:54 dnolen: eric_normand: yes, though no different from JavaScript

14:54 eric_normand: dnolen: I still believe a truly generic fan-in would have to handle closing

14:55 dnolen: can't be having nils, can we?

14:55 edw: dakrone, I was wondering if the issue was thread-related, so I'm not using a dynamic var; that didn't work. Also, I tried the with-connection-pool form outside and inside with-connection-pool binding and neither worked.

14:56 dakrone: edw: can you post some code of what you're trying?

14:56 edw: Sure; I'll put together a sample.

14:59 dakrone: edw: gotta go grab a bite to eat, pm me a link and I'll check it out?

14:59 edw: Cool; thank you, dakrone.

15:00 eric_normand: dnolen: I'm curious: would a closed output channel break the idea of back pressure?

15:01 dnolen: eric_normand: how so (should probably get tbaldridge on this question)

15:01 eric_normand: dnolen: let's say you have the map implementation from your blog.utils.reactive

15:01 dnolen: if the out channel is closed, the >! never blocks

15:02 dnolen: so it will read everything from the channel and throw it away

15:02 dnolen: closing the out channel generates infinite back pressure

15:03 dnolen: eric_normand: I'm not sure what you're suggesting

15:03 eric_normand: you mean closing the out channel outside of map?

15:04 eric_normand: dnolen: yes

15:04 jtoy: how do I use case with constants? this does not work when I pass 1 into the case: https://www.refheap.com/17705

15:04 dnolen: eric_normand: yeah don't do that

15:04 eric_normand: dnolen: right

15:05 `cbp: ,(case 1 1 ":)")

15:05 clojurebot: ":)"

15:07 jtoy: but doesnt work with constants?

15:07 i put a 1 1 in and it works, if I put (def ^:const user_pay1_status 1) and then do user_pay1_status 1 it doesnt work

15:07 tbaldridge: dnolen: I'm not sure I understand any of this. Is this the same problem from yesterday?

15:08 dnolen: tbaldridge: well eric_normand was suggesting something you should not do

15:08 tbaldridge: lol ok

15:08 dnolen: tbaldridge: unrelated to yesterday's convo

15:08 eric_normand: tbaldridge: hello!

15:08 jtoy: i want condp then

15:09 eric_normand: tbaldridge: sorry to cause trouble :)

15:10 tbaldridge: np, I love talking about this stuff

15:11 timvisher: what's the current tutorial we're passing out to people who want to get started with emacs and clojure?

15:12 technomancy: timvisher: the one on clojure-doc.org is good

15:13 justin_smith: also have them install clojure-cheatsheet.el - I just discovered it today, it is awesome

15:13 https://github.com/krisajenkins/clojure-cheatsheet

15:13 timvisher: technomancy: that does look pretty good. thanks!

15:15 gvickers: wow thats very cool

15:15 `cbp: jtoy: it seems like a bug with case

15:17 jtoy: https://www.refheap.com/17706

15:17 jtoy: that -1640523857 should be a 2

15:23 jtoy: `cbp: nice, found a bug

15:27 juhu_chapa: Is dynamic binding conveyed to future calls?

15:30 justin_smith: (do (def ^:dynamic *foo* 1) (binding [*foo* 2] (future (println *foo*))))

15:30 returns 2 for me

15:30 *prints 2

15:30 returns pending future

15:38 juhu_chapa: justin_smith: :O

15:42 llasram: jtoy, `cbp: In `case`, "not evaluated" means "not evaluated". The `x` in the test-constant in `cbp's example is matching against the symbol `x`, just as it should

15:50 `cbp: llasram: i thought the const stuff would replace the x with the number at compile time but i was wrong :). Need to know the language better.

15:55 gtrak: juhu_chapa: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6320

16:00 juhu_chapa: gtrak: thanks!

16:00 gtrak: np!

16:01 'binding conveyed future calls' happens to be in the implemenatation.. gotta love lisp

16:01 implementation*

16:17 edbond: I don't understand how macros in clojurescript works - https://gist.github.com/edbond/6253042

16:18 Trying to create macro that will prepend dom queries like (inside ".div-class" ($ "#id-inside-div)) ;; => ".div-class #id-inside-div"

16:19 bbloom: edbond: you are resolving inside-sel to that dynamic var, not a local

16:20 ,`(let [inc 1] (inc 2))

16:20 clojurebot: (clojure.core/let [clojure.core/inc 1] (clojure.core/inc 2))

16:20 bbloom: you need to use a gensym or force variable capture

16:20 nDuff: ...well, is the _goal_ a local?

16:20 bbloom: ,`(let [inc# 1] (inc# 2))

16:20 clojurebot: (clojure.core/let [inc__57__auto__ 1] (inc__57__auto__ 2))

16:20 nDuff: It looks to me like the goal is maybe a binding.

16:20 bbloom: locals may not have namespaces in their symbols

16:21 edbond: I will not be able to use gensym in $ func? Maybe a binding needed?

16:21 cap10morgan: why doesn't this work? (binding [*foo* :bar] (deftest foo-is-bar (is (= *foo* :bar))))

16:21 nDuff: edbond: ...looks to me like you also want to unquote sel inside the macro

16:21 cap10morgan: *foo* is back to its pre-binding value inside the test

16:22 bbloom: edbond: you're trying to call $ in your cljs, but that's defined in your clj

16:22 edbond: how are your general macro skills? ie outside of cljs, just in clj

16:22 edbond: bbloom, not much. What did you mean by "force variable capture" ?

16:23 cap10morgan: is it because of the compile-time vs. run-time difference?

16:23 edbond: I can refer $ in cljs

16:23 bbloom: ,`[inc #'inc inc# ~'inc]

16:23 clojurebot: [clojure.core/inc (var clojure.core/inc) inc__86__auto__ inc]

16:23 bbloom: that last one is forced capture

16:24 edbond: if your macro skills are weak, you may want to practice in big brother jvm clojure first. cljs introduces some serious ADDITIONAL gotchas to macro programming that will be very surprising if you haven't fully internalized macros, vars, resolution, quasiquoting, etc

16:24 edbond: I see, thanks

16:25 this probably my best macro - https://www.refheap.com/16357

16:31 callen: edbond: that's pretty sweet :)

16:33 amalloy_: is flatland/useful being maintained? Is it still a good dumping ground for random stuff of good utility?

16:55 technomancy: cap10morgan: yeah, basically

16:56 cap10morgan: technomancy: OK, makes sense. I ended up writing another macro to insert the binding inside the test body. Seems to work pretty well. Thanks.

17:02 technomancy: cap10morgan: that's one way to do it. fixtures are another, if the binding needs to be shared for all tests in a namespace

17:03 cap10morgan: technomancy: yeah, I'll probably investigate that approach too.

17:03 technomancy: definitely worth learning to use fixtures

17:11 Profpatsch: I’m kind of clueless. How can I make this dry? (and (integer? duration) (pos? duration))

17:13 cespare: Profpatsch: http://stackoverflow.com/questions/7922636/how-do-you-compose-two-or-more-predicates-in-clojure

17:13 bbloom: (doc every-pred)

17:13 clojurebot: "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns true if all of its composing predicates return a logical true value against all of its arguments, else it returns false. Note that f is short-circuiting in that it will stop execution on the first argument that triggers a logical false result against the original predicates."

17:13 bbloom: ,(map (every-pred integer? pos?) [5 -2 :foo])

17:13 clojurebot: (true false false)

17:13 Profpatsch: Many thanks.

17:13 bbloom: that said, it's probably dry enough already :-)

17:14 Profpatsch: Well, there’s a variable name occuring twice. ;)

17:14 bbloom: sure, but i'm quite certain there will be bigger fish to fry in your program :-)

17:15 hiredman: dry makes horribly brittle programs, I would not worry about it

17:16 bbloom: hiredman: that's something i wish i learned sooner

17:16 justin_smith: as shannon told us, redundancy helps with detecting errors

17:16 bbloom: hiredman: would be nice to see a list of what types of "dryness" cause what sorts of problems & how to avoid them

17:17 Profpatsch: When would you start using every-pred? Three tests? Four?

17:17 hiredman: if I have two things, a and b, and they have a common thing they do, and I factor it out in to c, now any change to c effects both a and b

17:17 technomancy: "two or more; use a for" - thus spake edsger

17:17 bbloom: Profpatsch: when you want to construct a higher order predicate at run time :-)

17:17 hiredman: do that a few times and now every change you make breaks something

17:18 Profpatsch: @hiredman Do what?

17:18 hiredman: intertwine components through shared subsystems

17:19 sharing is not a problem as long as the shared things never change, but software always changes

17:19 Profpatsch: Isn’t that the basic principle of inheritance?

17:19 hiredman: inheritance is gross

17:20 avishai: hi

17:20 bbloom: gross partially because it shares things that are likely to need to be later unshared

17:20 avishai: what namespace contains math functions?

17:20 bbloom: but goes one step further: making it harder for you to unshare them later

17:20 avishai: what math functions are you looking for?

17:21 avishai: e.g. sqrt

17:21 Profpatsch: Don’t multimethods share a similar problem?

17:21 justin_smith: java.lang.Math/* is not a namespace, but it has a bunch of that stuff

17:21 bbloom: use java's Math

17:21 avishai: ah. no clojure style functions?

17:21 justin_smith: ,(Math/sqrt 4.0)

17:21 clojurebot: 2.0

17:21 bbloom: not in core

17:22 hiredman: Profpatsch: multimethods are very flexible and you can certainly do all manner of things with them, but they are not hard wired for a particular thing

17:22 patchwork: (def sqrt [x] (Math/sqrt x))

17:22 *defn

17:22 hiredman: Profpatsch: so you have to be more specific about the kind of usage of multimethods you are asking about

17:23 Profpatsch: They support arbitrary polymorphism, right?

17:23 bbloom: no, not arbitrary

17:23 Profpatsch: What about

17:23 bbloom: they support table-dispatch with an arbitrary key function

17:24 technomancy: how is that different?

17:24 Profpatsch: Could you theoretically create cycles?

17:24 technomancy: because it's cached I guess?

17:24 bbloom: technomancy: b/c it is a fixed set of cases

17:24 at least at dispatch time

17:25 it's a subset of predicate dispatch, for example

17:25 hiredman: Profpatsch: the polymorphism in multimethods is not inheritance based

17:26 bts-: Profpatsch: dispatch and inheritance are separate concepts

17:26 technomancy: sure; if you ignore methods defining other methods I guess

17:26 bbloom: "methods defining other methods"?

17:26 hiredman: Profpatsch: it really is arbitrary polymorphism, your dispatch function can dispatch on things besides the arguments if you really want

17:26 bbloom: like :default runs, i analyze the expression, defmethod with some new case, then recurse?

17:26 Profpatsch: Can you point me to an article explaining the difference?

17:26 bbloom: technomancy: gross. :-P

17:26 technomancy: bbloom: yeah, dnolen had a blog post about that a while back

17:27 self-optimizing multimethods for when the dispatch cases aren't known up-front

17:27 bts-: Profpatsch: it just happens to be that most mainstream OO languages have both concepts baked-in

17:28 bbloom: technomancy: are you talking about his extend-type trick for an unknown set of concrete data types implementing a protocol?

17:28 dnolen: technomancy: actually I wrote about that for protocols, not multimethods - and protocol case was about lack of ISeqable and how to handle the fact that primitive array types are open ended

17:28 Profpatsch: I have the feeling most OO languages mix up a lot of orthogonal concepts.

17:28 bts-: Profpatsch: dispatch is merely calling a different implementation of a function depending on the receiver

17:28 Profpatsch: Found something:http://stackoverflow.com/questions/5671627/what-is-predicate-dispatch

17:28 dnolen: bbloom: yes

17:28 mikerod: Where is this dnolen blog?

17:28 bts-: Profpatsch: inheritance is sharing of those function implementations via a common ancestor in a hierarchy of types

17:28 technomancy: dnolen: oh right; it's been a while. but the concept could be applied to either.

17:28 dnolen: mikerod: history now, thanks to Posterous

17:29 mikerod: dnolen: oh, well that's sad

17:29 dnolen: technomancy: it could yes, Stuart Sierra's multimethod idea probably gave me the seed of the idea

17:29 technomancy: does anyone have .lein-* files in their project root that aren't gitignored?

17:29 bts-: Profpatsch: i should say "method implementations"

17:29 dnolen: mikerod: I have new blog though, I may revisit some of the more interesting examples at some point on the new blog

17:30 hiredman: technomancy: I do, I'm not sure why, or what those files are, or what projects they are in, they certainly aren't checked in to git either

17:30 I've seen them in my untracked files

17:30 technomancy: hiredman: heh... have you considered gitignore?

17:30 hiredman: I would, but I would have to care about them first

17:31 technomancy: good point

17:31 mikerod: dnolen: ah, ok. It just seemed to be an interesting topic.

17:31 Profpatsch: Take any feature of an OO language, abstract it one or two times and you have a Clojure functionality…

17:31 hiredman: abstract it?

17:31 cut it in to a few pieces

17:31 Profpatsch: Then abstract those pieces?

17:32 Well if -> cond -> condp type dispatch -> predicate dispatch functions -> first class functions …

17:33 * technomancy invokes sturgeon's law

17:34 noncom|2: hi, if i am writing a lein plugin that is, by idea, extends functionality of an existing one, but the amount of invasion is big enough that more than 50% of original àòû have to be changed inside. Do I simply create a new plugin withou references to the existing one or do I somehow re-use the existing one?

17:34 s/àòû/fns

17:34 technomancy: noncom|2: hard to say without knowing what the old one does

17:35 hiredman: functions being the unit of programming in clojures can be viewed as a direct result of taking classes and breaking them up, the namespace features of classes become real namespaces, the functionality of classes get broken down in to the smallest unit of function, a function, and dispatch is further broken up

17:35 Profpatsch: And the field? (Data?)

17:36 hiredman: data is just data, maps, sets, lists, and vectors

17:36 bts-: data are just values. state is a sequence of value changes over time associated with an "identity"

17:36 noncom|2: technomancy: i am extending uberjar to provide full support for any user jars and native libs using jdot jcl and it needs rewriting of (let) that starts at line 93 of uberjar

17:37 bts-: where values are immutable

17:37 Profpatsch: That’s what I like about immutabiliy, it actually resembles the way the world works much better.

17:37 technomancy: noncom|2: I'd just have it generate the uberjar and make a further modified copy of that

17:37 Profpatsch: Discretely.

17:38 noncom|2: hiderman: i would also encourage anyone who interests in namespaces classes and functions to read about mathematical definition of class.

17:38 technomancy: wow, you're genius :)

17:39 oh yes, it does that already with uberjar dependency on jar, afais

17:39 technomancy: it's like... the circle of life or something

17:40 calp: Hello, getting started with clojure, but have some history with Common Lisp. Using emacs, is clojure-mode really the best, or is there some kind of slime extension I should use?

17:40 technomancy: calp: clojure-mode and slime do different things.

17:41 clojure-mode is for static stuff; you definitely want that.

17:41 slime is for dynamic code loading; you probably want nrepl.el instead

17:41 calp: http://clojure-doc.org/articles/tutorials/emacs.html

17:41 calp: ok, I'll go with that, thanks.

17:41 Profpatsch: There has to be a better way to assign this map, something with zipping? I’m lost. https://www.refheap.com/17710

17:42 Can I get all function args as a seq?

17:42 Or a vec?

17:42 justin_smith: (defn trip [& args] ...)

17:43 Profpatsch: But then there is no documentation.

17:43 justin_smith: (defn trip [& [origin destination mot duration :as args]] ...)

17:43 maybe throw in an ignored after duration to doc the fast the first four are the only needed

17:44 Profpatsch: Hm. The whole args array isn’t available without the destructuring?

17:45 justin_smith: it is

17:45 [& args]

17:45 Profpatsch: oh-you.png

17:45 justin_smith: I was just adding the implicit documentation you mentioned

17:45 but preserving the fact you can access args

17:45 Profpatsch: Hm, okay. Thanks.

17:45 justin_smith: [& args] is not destructuring, if that is what you mean

17:46 Profpatsch: Okay.

17:48 `cbp: darn it I need a way to run dbase code in java. Or make java(clojure) work properly with dot matrix printers =P /rant

18:20 lynaghk: I'm having some angst about the API design of one of my libraries: https://github.com/lynaghk/zmq-async

18:20 dnolen: lynaghk: what's the problem?

18:20 lynaghk: in particular, whether or not I should offer a set of "easy" API functions that hide the creation of a thread pool and other backing "context" stuff

18:20 or if I should just force everyone to be totally explicit about it and create/manage a context

18:21 dnolen: lynaghk: hmm, is this any different than core.async provide a default thread pool which configurable?

18:21 bbloom: i was gonna just say what dnolen said ^^

18:21 lynaghk: dnolen: I didn't know core.async had a configurable threadpool

18:22 if there's a nice idiomatic way to have "easy" but make it configurable, I'm open to hear it

18:23 ultimately everything goes through the "simple" single function, `register-socket!`; I'm not sure if it'll be a net gain for people to hide that fn under the covers and provide helpers for typical use cases, or if I should just be consistent and simple and expose the single fn only.

18:24 dnolen: lynaghk: ok it looks like core.async thread pool isn't configurable yet, but I'm pretty sure there's been talk about this

18:27 lynaghk: One problem with the "easy" API is that I'd be spinning up threads under the table for people, which just feels rude.

18:30 bbloom: lynaghk: when would it spin up threads? would it be one-to-one with some obvious init function?

18:30 lynaghk: or would there just be one general pool?

18:31 lynaghk: bbloom: that's the big question = )

18:31 bbloom: Right now you can use the "simple" API to explicitly create a context, initialize it, and then give it sockets

18:33 bbloom: I'm on the fence about offering another API for the people who want to get up and running with one line of code---behind the scenes that line would be using a private context that was initialized at the toplevel of the library

18:34 noonian: I've seen the phrase "using clojure in anger" a few places on the web to mean using clojure for real stuff, what does that actually mean and how did that come about?

18:34 bbloom: lynaghk: would any reasonable program ever create two contexts?

18:34 technomancy: noonian: it's a reference to the Oasis song "Don't look back in Anger"

18:34 (not really)

18:34 noonian: lol

18:35 bbloom: http://english.stackexchange.com/questions/30939/is-used-in-anger-a-britishism-for-something

18:35 lynaghk: bbloom: yes, if you want to prioritize different sets of sockets---you'd have one context to handle big/slow messages and a separate one to accept smaller control messages

18:35 bbloom: since each context can only read/write one socket at a time.

18:35 bbloom: lynaghk: could those contexts ever communicate? can something be shared between them?

18:35 lynaghk: bbloom: no, they're independent.

18:36 noonian: bbloom: thanks :)

18:37 lynaghk: bbloom: my main hesitation is that it just feels rude for a library to startup two threads when it's loaded. I could jigger some other global state up to lazily start the context as soon as it's needed, but the idea in general feels gross.

18:37 bbloom: lynaghk: yeah, but that doesn't stop like 789357893 java libs from doing it

18:37 lynaghk: bbloom: trying to lead by example here =P

18:38 bbloom: then again, limiting it to the "simple" fn only is the kind of thinking that evenutally gets you to a factorycontextfactory

18:39 bbloom: lynaghk: are contexts thread local? ie does the pool of threads for a given context share a common necessarily ancestor thread?

18:39 Profpatsch: Why don’t you simply create the simple API and document that it starts a threadpool in the background? ;)

18:40 lynaghk: Profpatsch: the simple API asks you for a context that you've already created and started for it =)

18:40 bbloom: I don't understand your question. Each context has two threads, and initializing the context starts those threads and binds a ZeroMQ in-proc socket that they use to communicate

18:41 Profpatsch: As long as the programmer knows what’s going on in the background, it’s okay, isn’t it?

18:41 lynaghk: Profpatsch: well, that's the thing with easy APIs---too easy to not think about what's going on in the background until it's too late

18:41 technomancy: lynaghk: just be sure to offer an alternate arity that lets users bring their own thread pool

18:42 bbloom: technomancy: i think the issue is that w/ an auto thread pool, there would be no single entry point

18:42 technomancy: ah, that chews

18:42 lynaghk: technomancy: yeah, I was thinking something along those lines myself. the only issue there is that there are now three ways to get the same thing

18:42 bbloom: or is there? lynaghk: is the only entry point creating sockets?

18:42 noonian: doesn't seem all that gross to me, and it's necessary if you need multiple threads listening (blocking) for different things

18:43 technomancy: three arities when you only need one is way better than one arity when you need three

18:43 lynaghk: This is the simple fn entry point: https://github.com/lynaghk/zmq-async/blob/master/src/com/keminglabs/zmq_async/core.clj#L253

18:43 bbloom: lynaghk: rephrasing: my question about the ancestor thread: will all sockets be created within the dynamic extent of the process which creates the context?

18:44 lynaghk: It requires that you have a started context object and a constructed ZeroMQ socket that is already bound/connected and otherwise setup the way you like it.

18:44 bbloom: lynaghk: but creating a socket requires a context....

18:44 line 270

18:45 lynaghk: bbloom: yep. take a look at the example code in the README. You have to create a socket with the context and then pass that same context into the register fn.

18:45 bbloom: lynaghk: my suggestion is as follows: create a macro that initializes & shutsdown a context in a try/finally & use a dynamic var

18:45 lynaghk: That could be a problem because you might shoot yourself in the foot by creating a socket with one context and trying to register it with another.

18:46 bbloom: but require the var be specified

18:46 then provide overloads that do or do not take that var

18:46 so you can get the thread local context, or override it

18:46 noncom|2: what is the recommended way to access arbitrary web url from a lein plugin?

18:46 lynaghk: bbloom: why a dynamic var vs. passing in a value?

18:46 justin_smith: noncom|2: slurp it?

18:46 bbloom: b/c then if two people use your "easy" API from two different entry points, they won't collide

18:46 noncom|2: ok, i'll try

18:47 bbloom: it's not global then, it's connected to the session, like a repl or another servlet host or whatever

18:47 lynaghk: bbloom: not sure what you mean. If there were an implicit context it could be used globally and be threadsafe

18:47 justin_smith: there is also http.async.client if you need to get fancy

18:48 bbloom: lynaghk: if you have one implicit global context, and two containers in the same web app try to use it, they'll get the same context & then one can shut it down on the other, for example

18:48 lynaghk: but really, i wouldn't bother at all and do the easy thing and then wait for somebody to complain :-)

18:48 lynaghk: bbloom: I'm tempted to strip out the "easy" API entirely and just make the explicit context creation and management the only way to use the thing

18:49 bbloom: lynaghk: or that

18:49 noncom|2: i think slurp will do, i just have to fetch a txt

18:49 lynaghk: bbloom: but now I'm thinking of this problem where you might create a socket against one context and register it on another...so I might try and wrap up socket creation and registration for you.

18:49 justin_smith: noncom|2: yeah slurp is in core, and very easy to use

18:49 bbloom: lynaghk: what does registration do exactly?

18:50 lynaghk: why are creation and registration separate in the first place?

18:50 lynaghk: bbloom: because I didn't want to wrap all of ZeroMQ's options

18:50 bbloom: so you create the socket and set it up the way you like it, then give it to my library to manage for you.

18:51 bbloom: what I could do is have the registration fn take a "configurator" in the same way that run-jetty takes one

18:51 justin_smith: ,(slurp "http://www.google.com")

18:51 clojurebot: #<SecurityException java.lang.SecurityException: denied>

18:51 justin_smith: :(

18:51 bbloom: lynaghk: yeah, you could just do (create-socket :foo (fn [socket] configure here))

18:52 lynaghk: so it creates a socket for you against the right context but still lets you call whatever java-y things you need to

18:52 bbloom: sure

18:52 lynaghk: yeah. I think that might be the way to go.

18:53 bbloom: although i might prefer a configuration map :-)

19:19 noncom|2: will (spit) create the path if it does not exist?

19:20 bbloom: noncom|2: surely you can try "/tmp/some/path" yourself

19:37 justin_smith: ,(apply < (map count ["(spit \"/tmp/a/b/c/d/e\" \"hello\")" "will (spit) create the path if it does not exist?"]))

19:37 clojurebot: true

19:37 justin_smith: :P

19:37 noncom|2: :D

19:43 justin_smith: ,36RCRAZY

19:43 clojurebot: 21429358

20:09 cespare: Anyone use fireplace and have trouble with it finding the repl?

20:09 lein repl, that is

20:09 I've got target/repl-port.

20:18 technomancy: cespare: temporary fix: `:target-path "target"` in your user profile

20:18 will have a proper fix in a couple days

20:19 cespare: technomancy: turns out I was editing a file that was somewhere else (through a symlink)

20:19 I assumed fireplace used my cwd to find nrepl, but I guess it looks at where the file is.

20:29 yedi: whats the simplest way to install clojure

20:30 bbloom: ~lein

20:30 clojurebot: "[Clojure ...] feels like a general-purpose language beamed back from the near future."

20:30 bbloom: *sigh*

20:30 yedi: install leinigen

20:32 hiredman: the new inference code in clojurebot follows things besides "are" and "is", which it shouldn't

20:46 muhoo: ~what is life?

20:46 clojurebot: No entiendo

20:46 metellus: ~what is love?

20:46 clojurebot: Gabh mo leithscéal?

21:16 dnolen: hrm, bbloom I can't think of any reason why channels don't support metadata ...

21:18 bbloom: dnolen: i don't know why you're telling me that, but i assume it's for the same reason reference types don't support metadata

21:18 dnolen: bbloom: well I was gonna complain to tbaldridge but he's gone :)

21:18 bbloom: channels aren't reference types so I'm not sure I buy that.

21:18 bbloom: dnolen: channels have object identity

21:19 dnolen: with-meta returns a new object

21:19 dnolen: bbloom: oh right

21:19 bbloom: yeah, metadata only makes sense on things with value identity

21:19 dnolen: hmm

21:20 bbloom: dnolen: so rewinding. what makes you want the metadata? what issue are you trying to solve?

21:21 dnolen: bbloom: listening to events on the dom, but what wanting to clean up listener when something is done

21:22 bbloom: how would metadata help?

21:23 unrelated: i'm not sure why reify puts metadata on all object types. i really don't think metadata makes sense for objects that don't have custom equals defined

21:23 dnolen: bbloom: I wasn't considering the object identity issue, wanted store goog id for removing listeners

21:24 bbloom: metadata doesn't factor into equality so I don't know how what you're saying makes sense

21:24 bbloom: dnolen: can't you store that in a loop loop variable in some goroutine?

21:24 dnolen: bbloom: still hacking away at autocompleter, introducing another bit of state would be obnoxious

21:25 bbloom: ,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)])

21:25 clojurebot: (true false)

21:26 bbloom: adding metadata to any-old object makes it impossible for you to get back to the underlying object to check identical? against some other object

21:27 any time you "new" up anything that doesn't have value identity, that's basically implicit state / a side effect. if you want metadata on it, you need to store that metadata elsewhere, such as in a map, then manage the lifetime of that metadata along with the lifetime of the new-ed up object

21:27 yet another reason objects suck

21:27 dnolen: bbloom: I just don't see why that's a problem, identical? checks are rare - is there something specific you're trying to do?

21:27 bbloom: dnolen: identical? checks are only rare b/c working with objects is rare

21:28 dnolen: bbloom: so why should it be any different for reify?

21:28 bbloom: = uses identical? internally if the object doesn't have a custom implementation

21:29 if you reify some object & want to put metadata on it, you can't put that meta-data-deocrated object into a set or map or whatever & then later expect to look it up given the underlying non-meta-decorated object

21:30 unless you also implement a method for =

21:33 dnolen: bbloom: sure but I guess I just don't see this as a problem, as it has nothing to do with metadata anyhow. metadata doesn't factor into equality

21:33 bbloom: dnolen: except it does for reify, i just showed you that:

21:33 dnolen: bbloom: if you make a new thing of something without defining equality w/o metadata you have the same problem

21:33 bbloom: ,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)])

21:33 clojurebot: (true false)

21:34 dnolen: bbloom: yeah non-problem to me

21:35 bbloom: (doc with-meta)

21:35 clojurebot: "([obj m]); Returns an object of the same type and value as obj, with map m as its metadata."

21:36 bbloom: clojure has a very specific definition of "value" and, as far as i can tell, a non-value shouldn't have metadata

21:36 but *shrug* i could be wrong

21:36 dnolen: bbloom: the doc the isn't even true for fns w/ which support metadata

21:36 ,(= inc (with-meta inc {:foo 'bar}))

21:36 clojurebot: false

21:36 bbloom: yeah i discovered that recently too

21:37 dnolen: bbloom: ship sailed when people asked for that, so I just think non-issue

21:37 bbloom: in fact, i had this precise problem: i was tried to put a function in a map

21:37 and then tried to put metadata on it

21:37 later on, i couldn't look the function up

21:37 if you use a metadata-ed function as a map or set key, you can't ever look it up

21:37 dnolen: bbloom: prior to fns supporting metadata doc string made sense, doesn't make sense after that change

21:40 bbloom: anyway, let's solve your actual problem

21:40 you want to store the dom element ID somewhere?

21:43 subscribe/unsubscribe function pairs for callbacks are basically the same as reference counting

21:44 dnolen: bbloom: no, no I know how to solve, just wanted the convenience of metadata :)

21:44 but that was a weird thing to want

21:44 bbloom: if i have to deal w/ sub/unsub functions at all, i rather it be implemented as garbage collection :-)

22:02 holo: hi

22:02 akurilin: Say you're doing a MVC-style API in Clojure. Where would you validate input for POST/PUT request, if you don't really have a class to represent the model?

22:02 Would you make that check right before making the DB call?

22:08 holo: can someone point me to an fn that will search for a value, given the coll to search in, and a predicate? when first truthy value is found, will short circuit and return it

22:09 gfredericks: akurilin: if you're validating I suppose it makes sense to have the "schema" described somewhere using an appropriate lib? and you can put that with your model logic, and just call it directly from some middleware perhaps

22:09 holo: (some pred coll)

22:09 no wait

22:10 that's just (first (filter pred coll)) which doesn't have a built-in shorter form

22:10 akurilin: gfredericks, sure, that sounds good, thanks!

22:14 holo: akurilin, i do most of my validation against the db schema constraints themselves. besides that, when additional validation logic is necessary, i put it in each model, and call it in the corresponding view POST defn. i didn't do client validation yet, cause at least i know server one always works. i've done validation through middleware too, but not so often

22:16 gfredericks, does it short circuit? i need to get myself around lazy sequences

22:16 akurilin: holo, perfect, thanks.

22:17 gfredericks: holo: it short-circuits because of laziness

22:17 modulo chunking

22:17 holo: akurilin, validation by db schema constraints is dry, but it was a pain to get it working

22:18 akurilin: Ok here's another one that's been bothering me, I hope you guys have thoughts on this. Say you're doing model validation, and if it's incorrect you just throw an exception (as a quick return mechanism) which is ultimately turned into a 400 in the middleware. Because the validation doesn't do anything on the map you pass in, does it make sense to put it in a do block?

22:18 holo: gfredericks.. great!

22:19 akurilin: holo, I'm a believer in both api and db level constraint checking as a way of short-circuiting, so I tend to have both if possible.

22:20 holo, or I guess it's just simpler to edit stuff in clj rather than messing with db migrations, so it's nicer to put more logic in there.

22:20 So as in (do (validate input-map) (save map))

22:21 Can think of exceptions as side-effects/

22:21 holo: akurilin wait, i didn't mean that.. i mean i get the constraints from db schema, but i use them at the api level

22:24 i also use naming convention for validation. if a column name is *email*, the record will be checked for a valid email string

22:29 akurilin, if i was reading that do block code, i would think (save map) was always executed, which is not, by your words

22:30 akurilin: holo, right. It seems like the issue here is more about readability.

22:30 holo, on one hand the do makes it obvious that input-map will not change, on the other it also does what you said.

22:33 Man, you guys created so many validation libraries, that's awesome.

22:38 holo: akurilin, why not do (when (validate input-map) (save map)) instead? the code flow is obvious, and it does the same as your code

22:45 akurilin: holo, it just means I'm going to have to check for nil somewhere upstream and turn that into a 400

22:45 as opposed to generalizing it

22:46 I can see that working too, though, don't get me wrong :)

22:48 holo: nil? no nil will ever be returned. remember it will throw an exception

22:49 i'm assuming you'll throw an exception there or return some truthy value

22:50 akurilin: holo, oh sorry, for some reason I assumed you meant not to throw an exception, my bad.

22:50 holo: akurilin, glad to help :)

22:50 akurilin: holo, yep, thank you!

23:28 callen: More idiomatic way to express this? - https://www.refheap.com/17716

23:40 TimMc: Argh, how can Emacs packages always be such a hassle?

23:42 clojure-mode seems to have disappeared from Marmalade.

23:42 callen: TimMc: Emacs configs didn't even have packages until recently.

23:42 We've been carving the stories of our elders into tree bark for centuries.

23:43 It wasn't until these young turks with their papyrus and stone that we started being able to reuse anytihng.

23:43 TimMc: clojure-mode comes up in Marmalade repo search.

23:43 TimMc: I strongly recommend having redundant repos in your config.

23:43 I usually use Marmalade, MELPA, and the GNU one.

23:47 TimMc: Hrm.

23:48 I'll shave that yak another day; it's not actually essential for my new home server to have a Clojure editor on it. Yet.

23:51 callen: TimMc: you could just git clone my dotfiles.

23:51 TimMc: shake-n-bake Clojure env :P

Logging service provided by n01se.net