#clojure logs

2013-08-16

01:36heathwhat's a vector?
01:36heathi hail from python and javascript with some experience in haskell
01:37heathhttp://www.cplusplus.com/reference/vector/vector/
01:37heaththat explains
01:37heathsimilar to the math concept
01:38callenheath: no
01:38callenheath: it's not the same.
01:38brehauta vector is closer to an array in javascript or a list in python
01:38brehautbut backed by a trie structure
01:38brehautits associative with integer keys
01:38heathtree?
01:38callenheath: trie.
01:38brehauttrie
01:38heathwow
01:38heathya really meant that
01:38heathkk
01:39brehautits cheap to add and remove from the end of a vector,
01:39callenheath: hash array mapped tries. (HAMT)
01:39brehaut(rahter than the start like a list)
01:39brehautand it has fast (near constant time) lookup for indices
01:39callenheath: the data structures are designed to be persistent, that's how you have efficient immutability.
01:40callenheath: without it, you'd basically have to copy-on-create or copy-on-write.
01:40callenwhich, you know, sucks.
01:40callenand COW doesn't even really make sense in this context.
01:40brehautoh, and (unlike python lists) vectors are values
01:41callenheath: http://www.infoq.com/presentations/Value-Values
01:41heathhow could you make use of a vector's value?
01:41callenfor any wondering, yes carmine is awesome.
01:41brehautcompare {(1,2): "a"} and {([1,2]: "b"} in python
01:41callen,(conj [] :blah)
01:41clojurebot[:blah]
01:41brehaut,{[1 2] "b"}
01:41clojurebot{[1 2] "b"}
01:42callen,([:a :b :c :d] 2)
01:42clojurebot:c
01:44brehaut(you cant use a python list as a key because it has no intrinsic value)
01:44brehaut(a tuple (or clojure vector) on the other hand has a value derived from the values of its members)
01:48glosolinewbie 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
01:49brehautjust use a map
01:49brehaut{:name "foo bar" :address "123 fake st"}
01:50brehautslightly apropos http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/
01:52glosolibrehaut: thanks
01:57callenbrehaut: people are way too eager to grant data "thinghood"
01:57callen(I said it that way instead of saying "reify" so as to avoid confusion)
02:20jwpalmerpwd
02:20lazybot#clojure
02:20jwpalmergah - sorry
02:20jwpalmerheh
02:32heathare a lot of you using clojure within your workplaces?
02:32heathi've been dependent upon coffeescript
02:33heathstarted to learn c++ to write node addons, i figure i'll need them at some point
02:33heathbut i'm interested in learning clojurescript
02:33heathso many things to do! :)
02:40SegFaultAXRowing is hard work.
02:40TEttingerheath, 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
02:41TEttingerfor 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.
02:44TEttingerI 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.
02:46heathwhat's the value in immuatable collections, especially in the context of clojurescript/
02:47SegFaultAXheath: Mutation free code is inherently easier to reason about.
02:47amalloyheath: what's the value in immutable strings?
02:47SegFaultAXheath: Data in, data out.
02:47SegFaultAXBut more importantly /values/ in, /values/ out.
02:48noonianyou get referential transparency pretty much for free
02:48SegFaultAXnoonian: That's not strictly a side effect of immutable data.
02:48nooniandon't have to think about not mutating things or protecting things from mutation with copying
02:48heathfor some reason, i thought this was for languages like haskell :) a desire for mutation free code
02:49heathit kind of threw me off to see this in clojure
02:49SegFaultAXheath: 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.
02:49SegFaultAXThe nice thing is, it's pretty rare in general that you even need those facilities.
02:50noonianSegFaultAX: but you tend to write code with that property when everything defaults to being immutable
02:51noonianSegFaultAX: I guess you're right its not directly from immutability my bad
02:51SegFaultAXnoonian: The term you're looking for is probably purity, anyway.
02:51SegFaultAXReferential transparency is orthogonal.
02:52noonianpurity huh
02:52SegFaultAX(Unfortunately those words are often conflated with each other, but they are distinct)
02:52noonianmaybe, but then I sound like the haskell guys
02:52SegFaultAXnoonian: You say that like it's a bad thing! :D
02:53noidiSegFaultAX, is it possible for a function to be pure without being referentially transparent, or vice versa?
02:53noonianI just think its kind of preachy and monads were invented so they can say 'we have the purist functional language of them all'
02:54SegFaultAXnoonian: Monads are far, far older than Haskell.
02:54SegFaultAXnoonian: And the monads you know and love from Haskell are only a very particular formulation of monads anyway.
02:54nooniannot sure if you mean the theory or the technique, but no one called them monads when using them before
02:55SegFaultAXnoonian: The fact that you weren't aware of it doesn't mean anything.
02:55SegFaultAXYou personally, I mean.
02:55noonianweren't aware of what?
02:55SegFaultAXMonads.
02:55SegFaultAXOr category theory in general.
02:56noonianheh, you can use monads without calling them that
02:56noonianI know they came out of category theory, but you're right, I never heard of them before I heard of haskell
02:57SegFaultAXnoonian: But that doesn't mean monads only /just/ popped into existence, and certainly not when /you/ became aware of Haskell.
02:57noonianand I'm not saying they did
02:57nooniansorry if I offended you sire
02:57nooniansir*
02:57SegFaultAXbut no one called them monads when using them before < not sure what other way there is to interpret that, then.
02:58SegFaultAXnoonian: Sire is fine.
02:58noonianforget it then, just interpret it as drunken ramblings
02:59SegFaultAXnoidi: Sure!
03:01SegFaultAXnoidi: 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.
03:01SegFaultAXnoidi: That really doesn't have much at all to do with mutating state.
03:02noonianbut you can also have pure functions which mutate data in their local scope yes?
03:02SegFaultAXnoonian: Depends on the definition of purity I guess. But in a strict sense, no.
03:03SegFaultAXnoonian: I mean even Haskell can't be considered pure of you regard the mutation of the processor state to be a side effect.
03:03SegFaultAXIn Clojure nothing is pure. The JVM is a black box of statefulness.
03:04SegFaultAXWe 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.
03:04noonianthe 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)
03:04SegFaultAXnoonian: Right, but observable to whom is the question.
03:04nooniansemantically observable
03:05SegFaultAXExactly.
03:05noonianyeah, 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
03:06SegFaultAXHaskells 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.
03:08SegFaultAXnoonian: 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.
03:08noonianhmm, I don't understand that point
03:09noonianhow is a function, say (fn [x] (+ x 10)), not pure?
03:09SegFaultAXnoonian: The JVM is not pure.
03:10noonianbut that doesn't mean you can't write pure functions that run on the jvm
03:10SegFaultAXnoonian: Meh.
03:10SegFaultAXnoonian: Like I said, it's a pedantic argument at best.
03:10noonianI can agree with that at least :P
03:11noonianactually, that was the point I tried to make originally
03:22noidiSegFaultAX, ah, right. so a function calling (reset! nobody-uses-this :foo) is referentially transparent but impure
03:24noonianhmm, I don
03:25nooniandon't think its referentially transparent either, because if you replaced it with the return value it would change the programs behavior
03:31noonianI guess according to the definition of purity segfault put forth earlier, any referentially transparent function that uses mutation internally wouldn't be pure
04:45supersymSegFaultAX: 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
04:46supersymI hadn't related it to monads yet though so I think that was a nice summary of some stuff somewhere I knew subconsiously
04:52callenparable
05:06supersymreally, I made an error? nooo.... or are you french? Are you French Clyde?
05:06supersymsorry, I'm baked :P
05:06Raynessupersym: Need more edibles.
05:09supersymlol... yea
05:35turbopapeHi all,
05:35turbopapeanyone can share experience working with Riak / Welle ?
05:35turbopapeis it sable ? Well maintained ?
05:38schmirturbopape: I'm using langohr from michael klishin...he's quite responsive
06:50antares_turbopape: it is but don't use master, I'm breaking many things for 2.0
06:50antares_Riak is wonderful if its data model fits your problem well. Unbreakable in prod, easy to operate.
06:51antares_can be a royal pain to develop against, too
06:54antares_Only a few places left for the 2 day Munich Clojure workshop in October: http://clojureworkshop.com
07:00callenoi vey. finally done.
07:01callenhttps://github.com/bitemyapp/bulwark
08:36noncomhi, in clojurescript, how do i create a Date object and then setFullYear on it?
08:36noncomcurrently I do (.setFullYear (js/Date. ) 2000) but it does not work
08:37noncomsays Uncaught Error: No protocol method ILookup.-lookup defined for type object: Fri Aug 16 2013 16:09:29 GMT+0400 (Russian Standard Time)
08:38noncomi 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] }
08:46edlothiolnoncom: (.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)
08:47mpenet,(doc doto)
08:47clojurebot"([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))"
08:47edlothiolor that
08:48tbaldridgednolen: have you seen the problem described in http://dev.clojure.org/jira/browse/ASYNC-2 recently?
08:52mdrogalistbaldridge: Is there any plans to add a "topic"-like queue-construct to core.async?
08:52mdrogalisE.g. a queue that multiple people can consume the same messages from.
08:54tbaldridgemdrogalis: you mean pub/sub?
08:55H4nsis there function that returns a function's name, if it has one?
08:55noncomedlothiol: 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
08:56noncomnow i see that "2000" in the structure is not a stringwhen i print (type) of it, it is function String() { [native code] }
08:56mdrogalistbaldridge: Pretty much, yup
08:56noncomand if i (js/parseInt) on it, i get NaN
08:57noncom,(js/Date.)
08:57clojurebot#<CompilerException java.lang.RuntimeException: No such namespace: js, compiling:(NO_SOURCE_PATH:0:0)>
08:57noncomsure
08:57tbaldridgemdrogalis: 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.
08:58tbaldridgemdrogalis: that being said, you can build pub/sub from normal channels in about 30 lines of code or so
08:58mdrogalisH4ns: (:name (meta (var f)))
08:58mdrogalistbaldridge: Yeah I was thinking about that this morning. Doesn't seem difficult.
08:58H4nsmdrogalis: *bow*
08:58mdrogalisH4ns: :)
08:58mdrogalistbaldridge: Why go down to low level protocols to do it in exp then?
08:59noncomedlothiol: somehow that "2000" is not a string...
08:59tbaldridgemdrogalis: 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.
09:01mdrogalistbaldridge: Intriguing.
09:01noncomedlothiol: then what is it?.. i have got it by calling (subs) on s string
09:09noncomok, 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:10noncomanybody fluent with clojurescript strings here?
10:41Anderkentdid clojure.contrib.generic.functor survive the contrib apocalypse?
10:41AnderkentI'm looking for fmap in particular
10:43llasramAnderkent: 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:43Anderkentmhm. I found algo.generic which does does have it
10:43llasramOh, ok cool
10:44Anderkentbut it's nowhere near as powerful
10:45Anderkent(as what's in fluokitten, that is. I don't need all that power tho)
11:10papercupHi, does anybody use pallet here (specially with node-list option) ?
11:21boodlehi, 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:27Anderkentboodle: I think you can use strings as identifiers.. Something like (select [{"COUNT(id)" :count}] :tablename) ? Didn't try it though
11:27boodleAnderkent: great, tyvm!
11:28boodlewas trying to figure out 'entities'.. that helps alot
11:28Anderkententities sounds like sqlkorma not the simple jdbc wrapper
11:28Anderkentwith korma it's easier :P
11:28Anderkentah nvm it also has entities
11:29boodleAnderkent: and works great. I'm converting away as no pass/fail/anysort of results returned from Korma on Updates
11:29Anderkentoh. That sucks.
11:29Anderkentluckily we have an append-only db so don't have to worry about that! :P
11:30boodleAnderkent: heh lucky
12:07abpcemerick: around?
12:08cemerickabp: some :-)
12:10abpcemerick: Can I easily re-add those whitespaces? Would you probably merge as is also?
12:10abpcemerick: Regarding https://github.com/cemerick/friend/pull/70
12:10cemerickabp: I'd like to keep the blame clean. You should be able to selectively stage just the relevant changes to the file(s)?
12:11abpcemerick: Oh ok, will try tha, I'm a git newb.
12:13cemerickabp: 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:18Anderkentif 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:18Anderkentgitk does pretty well I think
12:18abpcemerick: Anderkent where using magit
12:19cemerickAnderkent: gitk is just a viewer, can't stage anything there AFAIK
12:19bbloomthe best feature of git add -i is that it can launch vim for editing patches :-)
12:20bbloomi use add -p frequently to review my changes when i commit them
12:20cemerickabp: selective staging is in magit, though I don't know anything about how it's used.
12:20Anderkentsorry, ment gitg
12:21cemerickbbloom: I've become unreasonably picky about clean commits since I started using git gui and then sourcetree for staging all my commits.
12:21bbloomcemerick: sure, at least for publicly sharing commits
12:21bbloomi tend to have dozens of WIP and "hack" and other nonsense commits on a branch
12:21bbloomand then i rebase a bunch
12:22bbloomi'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:23abpyeah, I'm more puzzled about how to stage my commits again
12:23cemerickAnderkent: oh, right. Yeah, gitg is okay. I never used it because it shows sources with such a large font. :-P
12:24Anderkentabp: 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:31rasmustobbloom: if you're using vim for git edits, have you used fugitive.vim?
12:31bbloomrasmusto: yeah, i have it installed, but i use it very sparingly
12:32rasmustobbloom: I love using :Gdiff and dp/do to do the equivalent of 'git add --patch', or to just manually edit the index
12:33bbloomrasmusto: 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:34rasmustobbloom: I need to rename files more, I tend to stick with my filename/fn name choices to a fault
12:34rasmustoheh
12:35steckerhalterI'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:36Anderkentsteckerhalter: the (ns ..) form imports clojure.core stuff
12:36Anderkentif 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:37shiranaihitois anyone happily writing Clojure in IDEA?
12:37Anderkentthough hm calling them via clojure.core/something should still work
12:37Anderkentshiranaihito: I tried it, but found it lacking in comparison to CCW. Might be my knowledge of eclipse is better than of IDEA
12:37Anderkent(i mean the second is definitely true, but it might be why I found ccw better)
12:37shiranaihitoAnderkent: what's CCW?
12:38shiranaihitohm
12:38steckerhalteranderkent: ah, ok. it's ac-nrepl that calls eval without "clojure.core" and that produces an error then in Emacs
12:38shiranaihitowell, i know IDEA _much_ better than Eclipse, would prefer to work with it instead of anything else, pretty much
12:38justin_smithshiranaihito: maybe counterclockwise, the clojure ide for eclipse
12:38shiranaihitoah, right
12:38Anderkentyeah
12:39shiranaihitoJetBrains' IDEs are simply the best out there
12:39shiranaihitoso i'd like to keep using them even with clojure :)
12:40shiranaihitobut yeah.. the integration is not quite "there" yet :p
12:41Anderkentone thing i remember in la clojure was that it would do unsafe refactorings and be wrong about it without prompting
12:41Anderkentbut that was a while ago and maybe has changed since
12:43shiranaihitooh :/
12:50technomancya few of the issue comments on idea's lein integration gave me the impression they were a bit confused about how things worked
12:51technomancybut that was like a year ago
12:54abpinteractively staging with magit is wicked
12:54steckerhalterabp: why?
12:54Anderkentis that a positive wicked or a negative wicked
12:54Anderkent:P
12:55abp:D
12:55abppositive
13:05abpsteckerhalter: Already read tutorial etc?
13:05technomancydoes anything besides nrepl.el use the target/repl-port file that leiningen writes?
13:06rasmustotechnomancy: vim-fireplace does
13:06steckerhalterabp: going through the app-tutorial
13:06Anderkentyeah, but it looks at it in the wrong place afaik
13:06rasmustothere's already a patch for the 2.3 moved repl-port file
13:06technomancyrasmusto: oy; I was about to fix that
13:06ystaelAnderkent: i never knew before why i sometimes found myself in a strange ns without clojure.core referred! thank you :)
13:07technomancyrasmusto: is there a discussion you could point me to?
13:07Anderkenttechnomancy: there's a github issue.
13:07Anderkenti'd link but github is dying
13:07rasmustotechnomancy: https://github.com/tpope/vim-fireplace/pull/98
13:07technomancydang it
13:08technomancywhen are they going to switch github issues over to a distributed system like everything else =P
13:08technomancyrasmusto: thanks!
13:08Anderkent98 and 88 it is
13:08mdrogalisSeriously bad day for GitHub.
13:08rasmustotechnomancy: np
13:09Anderkentseriously bad two days for github :P
13:11steckerhalterI imagine it to be a tough job to keep this running with so much data and users...
13:11Anderkentit's not the data and users, it's the ddos
13:11Anderkentusually
13:12steckerhalterhmm, right, sure it's just that?
13:12TimMcYes.
13:12Anderkentwhen it's completely down instead of just slow I'd guess it's mostly ddos
13:12Anderkentwhen you just get a random unicorn it might be some unlucky deadlock or sth
13:12mdrogalisGH 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:13pandeiroanyone know about how long it takes to build openjdk7 on something like an i5? minutes? hours?
13:13steckerhalterand what does it benefit them DDOSing github?
13:13Anderkentsteckerhalter: there are a couple possible motivations
13:14technomancybragging rights I guess?
13:14Anderkentone 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:15Anderkentother, as technomancy says, is bragging rights. Then comes general maliciousness
13:15Anderkentand if you have your tinfoil hat on I can tell you about githubs competitors
13:16ystaelAnderkent: :( 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:17Anderkenthitting github proves you can take down a serious infrastructure, not just some random website
13:17Anderkentit'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:18Anderkenti'm not saying its the only possible target, but it's one of them, so it gets its own share :
13:18Anderkenti'd be curious on what kind of ddos they're doing tho
13:19dnolentbaldridge: ping
13:20tbaldridgednolen: pong
13:20Anderkent.. for a moment there i was like 'wow, it aligned'
13:20mdrogalislol
13:22dnolentbaldridge: 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:22abpwhat happens if I force-push to github after resetting my local branch and already opened a pull-request?
13:22Anderkentabp: the pull is updated
13:22Anderkentit 'just works' :)
13:22abpoh cool
13:22abpthanks!
13:23tbaldridgednolen: throttle being, the buffer drop size?
13:23dnolentbaldridge: no like a milliseconds throttle
13:23dnolentbaldridge: it takes a channel of events and only emits them at a throttle speed
13:23dnolenthrottled
13:23bbloomdnolen: what about 3 channels: 1) the messages 2) the timeouts 3) a control channel to set the timeout speed?
13:23dnolentbaldridge: but the point here is about the flip on/off
13:24dnolenbbloom: I'm looking for the absolutely most succinct solution that gets the job done in this case
13:24bbloomdnolen: you can encapsulate the timeout channel & the control channel into a little timeout machine
13:25bbloomthat way you could reuse a synchronization process that just syncs one channel to any arbitrary interval channel
13:25dnolenbbloom: yes I know the obvious ways to do this - I want to know if there's something different, smaller|simpler is key
13:25tbaldridgednolen: what's the use case? are we thinking of creating thousands of these? or why does it need to be so small?
13:26dnolentbaldridge: I've been working this autocompleter blog post / code for a week now
13:26dnolentbaldridge: autocompleter takes throttle query strings from input field, 750 msecs throttled
13:26dnolentbaldridge: but when the user switches over the menu selection, we defer control to the menu subprocess
13:27tbaldridgednolen: right.
13:27dnolentbaldridge: this can happen via mouse or arrow keys, autocompleter process freezes at this point
13:27tbaldridgeSo we're just creating a single one of these throttled chans in this example.
13:27dnolentbaldridge: but the menu subprocess needs the unthrottled key stream to know to exit
13:28dnolentbaldridge: 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:28dnolens/had/hand
13:32tbaldridgednolen: hold on...I'm writing up something
13:37tbaldridgednolen: I think this is all you need: https://gist.github.com/halgari/6251731
13:37tbaldridgetakes an input and then outputs [output-chan throttle-chan]
13:38tbaldridgeyou can send :disabled or msec to the throttle-chan to change the behavior
13:38tbaldridgeeh, I had to edit that, there was a bug, if you reload it s/when/when-not on line 6
13:39justin_smithhttp://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:39justin_smith*pprint
13:39dnolentbaldridge: heh maybe I wasn't clear I already have a working throttle
13:39dnolentbaldridge: I only care about generic toggle
13:39tbaldridgebut throttling isn't part of channels, so I don't know how it can be made generic
13:52dnolentbaldridge: 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:54tbaldridgednolen: that'd work, although I'd imagine that in your use case tap would be spinning up a go for each message right?
13:55benedikt
13:55dnolentbaldridge: gist updated with something that makes more sense :)
13:56tbaldridgednolen: so less of a throttle and more of a router
13:56dnolentbaldridge: sorry I wasn't clear earlier - I never needed a throttle :)
13:56dnolentbaldridge: I have a throttle, I wanted a router/switch
13:57dnolentbaldridge: so we route into the throttle or we don't
13:57tbaldridgednolen: 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:58eric_normanddnolen: an idea for a toggle https://gist.github.com/halgari/6251731
13:58eric_normanddnolen: added as comment
13:59dnoleneric_normand: I don't need an enhanced toggle :)
13:59eric_normanddnolen: then I misunderstood
14:00`cbpjustin_smith: I've noticed that before. Are you using windows by any chance?
14:00justin_smith`cbp: ubuntu, latest build of emacs from gnu source
14:00dnoleneric_normand: also I'm of the mind if you can avoid returning maps you should
14:00justin_smithlatest nrepl from marmalade
14:00justin_smith*nrepl-el
14:01dnolenan improved sketch for router/switch which can take N taps http://gist.github.com/swannodette/6251850
14:01`cbpjustin_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:03justin_smithyeah, emacs but, does not appear in a terminal repl
14:04justin_smithso theoretically if I pprint into a string, and then print the string...
14:04eric_normanddnolen: I'm confused. Where are tap and control defined?
14:05dnoleneric_normand: typos updated
14:05justin_smith`cbp: (println (with-out-str (clojure.pprint/pprint ...))) does not display the bug
14:05justin_smithso at least we have a workaround until someone fixes the elisp issue (whatever that is)
14:07naconSuppose 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:09dnolengist updated again with `tapify`
14:10technomancynDuff: yeah, was happy to see that
14:10eric_normanddnolen: looks cool. what do you use it for?
14:11dnoleneric_normand: I want to be able to route dynamically
14:11dnoleneric_normand: so I may have a stream of key events and I want to dynamically apply a throttle or disable it
14:11eric_normanddnolen: much more sophisticated than my toggle! :)
14:12dnoleneric_normand: I think is a pretty handy one :)
14:13eric_normanddnolen: yes
14:13rasmustonacon: something like this? (apply format "%s %s: %s" (map f [fst snd thrd]))?
14:14IamDrowsyrasmusto: haha :) i was typing the exact same line
14:14rasmustoIamDrowsy: IhadCoffee
14:15dnoleneric_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:15dnoleneric_normand: also you were right about the race condition in my presentation
14:15IamDrowsyrasmusto: i am kind of drowsy.. you know... :)
14:18naconrasmusto: Yes, perfect! Hmmm.. *scratches head*, I probably have to play with apply a bit to finally "get it".
14:20rasmustonacon: just imagine the last argument without one set of parens
14:20TEttingerI 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:20lazybot⇒ "alpha beta: gamma"
14:20TEttingercorrectly!
14:21rasmustoTEttinger: !! nice
14:21TEttingerwow, I guess format discards args it doesn't need for the format string, great
14:23justin_smithsadly, it is not lazy: (apply format "a %s and a %s and a %s %s %s..." (range))
14:25TimMc&(apply format "a %s and a %s and a %s %s %s..." (range))
14:25TimMcOh, does it build an array?
14:25justin_smithit might
14:25TimMcSorry 'bout that, lazybot.
14:25lazybotExecution Timed Out!
14:25justin_smithlike I said, it is not lazy
14:26TimMcIt calls to-array.
14:26TimMcSo... that probably tries to count the seq.
14:27justin_smithA laziness-compatible format may be nice
14:28tbaldridgewhat's the recommended way of using a JS lib from CLJs?
14:28TimMcjustin_smith: (defn lazy-format [s & args] (apply format s (take 1000 args))) ;; no one needs more than 1000 string interpolations, dude
14:29justin_smithdepending on the cost of realizing the elements, a version that only realized as many items as it needs may be nice
14:29ystaelTimMc: what about gnu autoconf
14:30bbloomtbaldridge: first, see the Google Closure docs for externs
14:30bbloomtbaldridge: then use it just like any other gclosure namespace, import goog, for example
14:31TimMcystael: Nonsense, why would I ever build a tool that would have its arguments supplied dynamically?
14:32TimMcI'm sure every usage will be in call position.
14:36futiletbaldridge: is clojure-py still alive?
14:37Foxboronfutile: if you want a LISP on python i know a option :3
14:39eric_normanddnolen: race condition? wow!
14:39gvickersIs pomegranate the only option for dynamically loading classes and their dependecies?
14:39eric_normanddnolen: one question about your switch: why not pass the function you want down the control channel?
14:40futileFoxboron: what?
14:40dnoleneric_normand: you mean the tap that I want to apply?
14:41Foxboronfutile: afaik, clojure-py is dead or rather low activity, but there is something called Hy if you want a LISP on python.
14:42eric_normanddnolen: right; tapify just does this: (apply f in args)
14:42eric_normanddnolen: and wraps it neatly in a map
14:42eric_normanddnolen: why not just pass f and args on control channel?
14:42eric_normanddnolen: do it right there inline?
14:43dnoleneric_normand: hmm, worth thinking about ... I broke out tapify because it might be useful elsewhere
14:44eric_normanddnolen: maybe it wouldn't work with your use cases
14:44futileFoxboron: setv :P
14:44eric_normanddnolen: I don't know how you could make a throttle with a regular function
14:45dnoleneric_normand: right
14:45dnoleneric_normand: f in tapify must be a channel constructor
14:45eric_normandso (tapify throttle 200)
14:45dnoleneric_normand: yes
14:45eric_normanddnolen: makes sense
14:46eric_normanddnolen: keeps channel state around
14:46eric_normanddnolen: if you passed the constructor down the control channel (instead of an index), you'd lose state
14:46dnoleneric_normand: yes
14:47eric_normanddnolen: I am satisfied :)
14:47Foxboronfutile: *cough* a few CL people there :3 Should note it has some clojure inspired features, but it isnt clojure. Just a LISP dialect
14:47futileFoxboron: gross
14:47Foxboronfutile: it compiles down to Python AST, so you can import hy too python and python too hy
14:47dnoleneric_normand: now that you mention it, you can build a scheduler with this
14:47Foxboronfutile: its neat
14:47eric_normanddnolen: yes?
14:48futileFoxboron: sounds neat. just wish it was more like clojure.
14:48futileFoxboron: id rather use clojure-py if it compiles down to pythonast
14:49eric_normanddnolen: I've been thinking a lot about generic channel transformers
14:49dnoleneric_normand: a very simplistic one anyway
14:49eric_normanddnolen: such as map, filter, etc
14:49edwdakrone, you around?
14:49dnoleneric_normand: like reactive stuff?
14:49Foxboronfutile: i don't think doe actually. Can't remember.
14:49Foxborondoes*
14:49dakroneedw: yep
14:49eric_normanddnolen: they are tough when you have to take into account closing
14:49futileFoxboron: k
14:50eric_normanddnolen: yes
14:50dakroneedw: what's up?
14:50eric_normanddnolen: closing upstream vs downstream, etc
14:50edwHi. I was having a prob with the clj-http client and was wondering if you might have some thoughts.
14:50dnoleneric_normand: yes though closing is less important in interactive applications than it would seem
14:50dnoleneric_normand: just remove event sources at exit at the root, everything will get GCed
14:50dakroneedw: what's the issue?
14:50edwBasically, I'm trying to get connection pooling to work with a cookie store, without success.
14:50eric_normanddnolen: yes, you could just leave things open, never closing
14:51edwSorry dakrone, long sentences…
14:51dakroneedw: no worries
14:51eric_normanddnolen: but would things get gc'd in complex scenarios?
14:51dnoleneric_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:51dnoleneric_normand: yes
14:51eric_normanddnolen: like say we had a fan-in
14:52tfordafter 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:52dnoleneric_normand: it doesn't matter how complex the graph is
14:52dnoleneric_normand: just remove event sources at exit at the root
14:52dnolens/at/and
14:52eric_normanddnolen: I suppose if you are careful to remove them all
14:52eric_normanddnolen: from the root
14:54dnoleneric_normand: yes, though no different from JavaScript
14:54eric_normanddnolen: I still believe a truly generic fan-in would have to handle closing
14:55eric_normanddnolen: can't be having nils, can we?
14:55edwdakrone, 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:56dakroneedw: can you post some code of what you're trying?
14:56edwSure; I'll put together a sample.
14:59dakroneedw: gotta go grab a bite to eat, pm me a link and I'll check it out?
14:59edwCool; thank you, dakrone.
15:00eric_normanddnolen: I'm curious: would a closed output channel break the idea of back pressure?
15:01dnoleneric_normand: how so (should probably get tbaldridge on this question)
15:01eric_normanddnolen: let's say you have the map implementation from your blog.utils.reactive
15:01eric_normanddnolen: if the out channel is closed, the >! never blocks
15:02eric_normanddnolen: so it will read everything from the channel and throw it away
15:02eric_normanddnolen: closing the out channel generates infinite back pressure
15:03dnoleneric_normand: I'm not sure what you're suggesting
15:03dnoleneric_normand: you mean closing the out channel outside of map?
15:04eric_normanddnolen: yes
15:04jtoyhow do I use case with constants? this does not work when I pass 1 into the case: https://www.refheap.com/17705
15:04dnoleneric_normand: yeah don't do that
15:04eric_normanddnolen: right
15:05`cbp,(case 1 1 ":)")
15:05clojurebot":)"
15:07jtoybut doesnt work with constants?
15:07jtoyi 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:07tbaldridgednolen: I'm not sure I understand any of this. Is this the same problem from yesterday?
15:08dnolentbaldridge: well eric_normand was suggesting something you should not do
15:08tbaldridgelol ok
15:08dnolentbaldridge: unrelated to yesterday's convo
15:08eric_normandtbaldridge: hello!
15:08jtoyi want condp then
15:09eric_normandtbaldridge: sorry to cause trouble :)
15:10tbaldridgenp, I love talking about this stuff
15:11timvisherwhat's the current tutorial we're passing out to people who want to get started with emacs and clojure?
15:12technomancytimvisher: the one on clojure-doc.org is good
15:13justin_smithalso have them install clojure-cheatsheet.el - I just discovered it today, it is awesome
15:13justin_smithhttps://github.com/krisajenkins/clojure-cheatsheet
15:13timvishertechnomancy: that does look pretty good. thanks!
15:15gvickerswow thats very cool
15:15`cbpjtoy: it seems like a bug with case
15:17`cbpjtoy: https://www.refheap.com/17706
15:17`cbpjtoy: that -1640523857 should be a 2
15:23jtoy`cbp: nice, found a bug
15:27juhu_chapaIs dynamic binding conveyed to future calls?
15:30justin_smith(do (def ^:dynamic *foo* 1) (binding [*foo* 2] (future (println *foo*))))
15:30justin_smithreturns 2 for me
15:30justin_smith*prints 2
15:30justin_smithreturns pending future
15:38juhu_chapajustin_smith: :O
15:42llasramjtoy, `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`cbpllasram: 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:55gtrakjuhu_chapa: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6320
16:00juhu_chapagtrak: thanks!
16:00gtraknp!
16:01gtrak'binding conveyed future calls' happens to be in the implemenatation.. gotta love lisp
16:01gtrakimplementation*
16:17edbondI don't understand how macros in clojurescript works - https://gist.github.com/edbond/6253042
16:18edbondTrying to create macro that will prepend dom queries like (inside ".div-class" ($ "#id-inside-div)) ;; => ".div-class #id-inside-div"
16:19bbloomedbond: you are resolving inside-sel to that dynamic var, not a local
16:20bbloom,`(let [inc 1] (inc 2))
16:20clojurebot(clojure.core/let [clojure.core/inc 1] (clojure.core/inc 2))
16:20bbloomyou need to use a gensym or force variable capture
16:20nDuff...well, is the _goal_ a local?
16:20bbloom,`(let [inc# 1] (inc# 2))
16:20clojurebot(clojure.core/let [inc__57__auto__ 1] (inc__57__auto__ 2))
16:20nDuffIt looks to me like the goal is maybe a binding.
16:20bbloomlocals may not have namespaces in their symbols
16:21edbondI will not be able to use gensym in $ func? Maybe a binding needed?
16:21cap10morganwhy doesn't this work? (binding [*foo* :bar] (deftest foo-is-bar (is (= *foo* :bar))))
16:21nDuffedbond: ...looks to me like you also want to unquote sel inside the macro
16:21cap10morgan*foo* is back to its pre-binding value inside the test
16:22bbloomedbond: you're trying to call $ in your cljs, but that's defined in your clj
16:22bbloomedbond: how are your general macro skills? ie outside of cljs, just in clj
16:22edbondbbloom, not much. What did you mean by "force variable capture" ?
16:23cap10morganis it because of the compile-time vs. run-time difference?
16:23edbondI can refer $ in cljs
16:23bbloom,`[inc #'inc inc# ~'inc]
16:23clojurebot[clojure.core/inc (var clojure.core/inc) inc__86__auto__ inc]
16:23bbloomthat last one is forced capture
16:24bbloomedbond: 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:24edbondI see, thanks
16:25edbondthis probably my best macro - https://www.refheap.com/16357
16:31callenedbond: that's pretty sweet :)
16:33callenamalloy_: is flatland/useful being maintained? Is it still a good dumping ground for random stuff of good utility?
16:55technomancycap10morgan: yeah, basically
16:56cap10morgantechnomancy: OK, makes sense. I ended up writing another macro to insert the binding inside the test body. Seems to work pretty well. Thanks.
17:02technomancycap10morgan: that's one way to do it. fixtures are another, if the binding needs to be shared for all tests in a namespace
17:03cap10morgantechnomancy: yeah, I'll probably investigate that approach too.
17:03technomancydefinitely worth learning to use fixtures
17:11ProfpatschI’m kind of clueless. How can I make this dry? (and (integer? duration) (pos? duration))
17:13cespareProfpatsch: http://stackoverflow.com/questions/7922636/how-do-you-compose-two-or-more-predicates-in-clojure
17:13bbloom(doc every-pred)
17:13clojurebot"([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:13bbloom,(map (every-pred integer? pos?) [5 -2 :foo])
17:13clojurebot(true false false)
17:13ProfpatschMany thanks.
17:13bbloomthat said, it's probably dry enough already :-)
17:14ProfpatschWell, there’s a variable name occuring twice. ;)
17:14bbloomsure, but i'm quite certain there will be bigger fish to fry in your program :-)
17:15hiredmandry makes horribly brittle programs, I would not worry about it
17:16bbloomhiredman: that's something i wish i learned sooner
17:16justin_smithas shannon told us, redundancy helps with detecting errors
17:16bbloomhiredman: would be nice to see a list of what types of "dryness" cause what sorts of problems & how to avoid them
17:17ProfpatschWhen would you start using every-pred? Three tests? Four?
17:17hiredmanif 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:17technomancy"two or more; use a for" - thus spake edsger
17:17bbloomProfpatsch: when you want to construct a higher order predicate at run time :-)
17:17hiredmando that a few times and now every change you make breaks something
17:18Profpatsch@hiredman Do what?
17:18hiredmanintertwine components through shared subsystems
17:19hiredmansharing is not a problem as long as the shared things never change, but software always changes
17:19ProfpatschIsn’t that the basic principle of inheritance?
17:19hiredmaninheritance is gross
17:20avishaihi
17:20bbloomgross partially because it shares things that are likely to need to be later unshared
17:20avishaiwhat namespace contains math functions?
17:20bbloombut goes one step further: making it harder for you to unshare them later
17:20bbloomavishai: what math functions are you looking for?
17:21avishaie.g. sqrt
17:21ProfpatschDon’t multimethods share a similar problem?
17:21justin_smithjava.lang.Math/* is not a namespace, but it has a bunch of that stuff
17:21bbloomuse java's Math
17:21avishaiah. no clojure style functions?
17:21justin_smith,(Math/sqrt 4.0)
17:21clojurebot2.0
17:21bbloomnot in core
17:22hiredmanProfpatsch: 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:22patchwork(def sqrt [x] (Math/sqrt x))
17:22patchwork*defn
17:22hiredmanProfpatsch: so you have to be more specific about the kind of usage of multimethods you are asking about
17:23ProfpatschThey support arbitrary polymorphism, right?
17:23bbloomno, not arbitrary
17:23ProfpatschWhat about
17:23bbloomthey support table-dispatch with an arbitrary key function
17:24technomancyhow is that different?
17:24ProfpatschCould you theoretically create cycles?
17:24technomancybecause it's cached I guess?
17:24bbloomtechnomancy: b/c it is a fixed set of cases
17:24bbloomat least at dispatch time
17:25bbloomit's a subset of predicate dispatch, for example
17:25hiredmanProfpatsch: the polymorphism in multimethods is not inheritance based
17:26bts-Profpatsch: dispatch and inheritance are separate concepts
17:26technomancysure; if you ignore methods defining other methods I guess
17:26bbloom"methods defining other methods"?
17:26hiredmanProfpatsch: it really is arbitrary polymorphism, your dispatch function can dispatch on things besides the arguments if you really want
17:26bbloomlike :default runs, i analyze the expression, defmethod with some new case, then recurse?
17:26ProfpatschCan you point me to an article explaining the difference?
17:26bbloomtechnomancy: gross. :-P
17:26technomancybbloom: yeah, dnolen had a blog post about that a while back
17:27technomancyself-optimizing multimethods for when the dispatch cases aren't known up-front
17:27bts-Profpatsch: it just happens to be that most mainstream OO languages have both concepts baked-in
17:28bbloomtechnomancy: are you talking about his extend-type trick for an unknown set of concrete data types implementing a protocol?
17:28dnolentechnomancy: 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:28ProfpatschI have the feeling most OO languages mix up a lot of orthogonal concepts.
17:28bts-Profpatsch: dispatch is merely calling a different implementation of a function depending on the receiver
17:28ProfpatschFound something:http://stackoverflow.com/questions/5671627/what-is-predicate-dispatch
17:28dnolenbbloom: yes
17:28mikerodWhere is this dnolen blog?
17:28bts-Profpatsch: inheritance is sharing of those function implementations via a common ancestor in a hierarchy of types
17:28technomancydnolen: oh right; it's been a while. but the concept could be applied to either.
17:28dnolenmikerod: history now, thanks to Posterous
17:29mikeroddnolen: oh, well that's sad
17:29dnolentechnomancy: it could yes, Stuart Sierra's multimethod idea probably gave me the seed of the idea
17:29technomancydoes anyone have .lein-* files in their project root that aren't gitignored?
17:29bts-Profpatsch: i should say "method implementations"
17:29dnolenmikerod: I have new blog though, I may revisit some of the more interesting examples at some point on the new blog
17:30hiredmantechnomancy: 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:30hiredmanI've seen them in my untracked files
17:30technomancyhiredman: heh... have you considered gitignore?
17:30hiredmanI would, but I would have to care about them first
17:31technomancygood point
17:31mikeroddnolen: ah, ok. It just seemed to be an interesting topic.
17:31ProfpatschTake any feature of an OO language, abstract it one or two times and you have a Clojure functionality…
17:31hiredmanabstract it?
17:31hiredmancut it in to a few pieces
17:31ProfpatschThen abstract those pieces?
17:32ProfpatschWell if -> cond -> condp type dispatch -> predicate dispatch functions -> first class functions …
17:34noncom|2hi, 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:34noncom|2s/àòû/fns
17:34technomancynoncom|2: hard to say without knowing what the old one does
17:35hiredmanfunctions 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:35ProfpatschAnd the field? (Data?)
17:36hiredmandata is just data, maps, sets, lists, and vectors
17:36bts-data are just values. state is a sequence of value changes over time associated with an "identity"
17:36noncom|2technomancy: 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:37bts-where values are immutable
17:37ProfpatschThat’s what I like about immutabiliy, it actually resembles the way the world works much better.
17:37technomancynoncom|2: I'd just have it generate the uberjar and make a further modified copy of that
17:37ProfpatschDiscretely.
17:38noncom|2hiderman: i would also encourage anyone who interests in namespaces classes and functions to read about mathematical definition of class.
17:38noncom|2technomancy: wow, you're genius :)
17:39noncom|2oh yes, it does that already with uberjar dependency on jar, afais
17:39technomancyit's like... the circle of life or something
17:40calpHello, 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:40technomancycalp: clojure-mode and slime do different things.
17:41technomancyclojure-mode is for static stuff; you definitely want that.
17:41technomancyslime is for dynamic code loading; you probably want nrepl.el instead
17:41technomancycalp: http://clojure-doc.org/articles/tutorials/emacs.html
17:41calpok, I'll go with that, thanks.
17:41ProfpatschThere has to be a better way to assign this map, something with zipping? I’m lost. https://www.refheap.com/17710
17:42ProfpatschCan I get all function args as a seq?
17:42ProfpatschOr a vec?
17:42justin_smith(defn trip [& args] ...)
17:43ProfpatschBut then there is no documentation.
17:43justin_smith(defn trip [& [origin destination mot duration :as args]] ...)
17:43justin_smithmaybe throw in an ignored after duration to doc the fast the first four are the only needed
17:44ProfpatschHm. The whole args array isn’t available without the destructuring?
17:45justin_smithit is
17:45justin_smith[& args]
17:45Profpatschoh-you.png
17:45justin_smithI was just adding the implicit documentation you mentioned
17:45justin_smithbut preserving the fact you can access args
17:45ProfpatschHm, okay. Thanks.
17:45justin_smith[& args] is not destructuring, if that is what you mean
17:46ProfpatschOkay.
17:48`cbpdarn it I need a way to run dbase code in java. Or make java(clojure) work properly with dot matrix printers =P /rant
18:20lynaghkI'm having some angst about the API design of one of my libraries: https://github.com/lynaghk/zmq-async
18:20dnolenlynaghk: what's the problem?
18:20lynaghkin 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:20lynaghkor if I should just force everyone to be totally explicit about it and create/manage a context
18:21dnolenlynaghk: hmm, is this any different than core.async provide a default thread pool which configurable?
18:21bbloomi was gonna just say what dnolen said ^^
18:21lynaghkdnolen: I didn't know core.async had a configurable threadpool
18:22lynaghkif there's a nice idiomatic way to have "easy" but make it configurable, I'm open to hear it
18:23lynaghkultimately 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:24dnolenlynaghk: ok it looks like core.async thread pool isn't configurable yet, but I'm pretty sure there's been talk about this
18:27lynaghkOne problem with the "easy" API is that I'd be spinning up threads under the table for people, which just feels rude.
18:30bbloomlynaghk: when would it spin up threads? would it be one-to-one with some obvious init function?
18:30bbloomlynaghk: or would there just be one general pool?
18:31lynaghkbbloom: that's the big question = )
18:31lynaghkbbloom: Right now you can use the "simple" API to explicitly create a context, initialize it, and then give it sockets
18:33lynaghkbbloom: 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:34noonianI'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:34bbloomlynaghk: would any reasonable program ever create two contexts?
18:34technomancynoonian: it's a reference to the Oasis song "Don't look back in Anger"
18:34technomancy(not really)
18:34noonianlol
18:35bbloomhttp://english.stackexchange.com/questions/30939/is-used-in-anger-a-britishism-for-something
18:35lynaghkbbloom: 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:35lynaghkbbloom: since each context can only read/write one socket at a time.
18:35bbloomlynaghk: could those contexts ever communicate? can something be shared between them?
18:35lynaghkbbloom: no, they're independent.
18:36noonianbbloom: thanks :)
18:37lynaghkbbloom: 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:37bbloomlynaghk: yeah, but that doesn't stop like 789357893 java libs from doing it
18:37lynaghkbbloom: trying to lead by example here =P
18:38lynaghkbbloom: then again, limiting it to the "simple" fn only is the kind of thinking that evenutally gets you to a factorycontextfactory
18:39bbloomlynaghk: are contexts thread local? ie does the pool of threads for a given context share a common necessarily ancestor thread?
18:39ProfpatschWhy don’t you simply create the simple API and document that it starts a threadpool in the background? ;)
18:40lynaghkProfpatsch: the simple API asks you for a context that you've already created and started for it =)
18:40lynaghkbbloom: 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:41ProfpatschAs long as the programmer knows what’s going on in the background, it’s okay, isn’t it?
18:41lynaghkProfpatsch: 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:41technomancylynaghk: just be sure to offer an alternate arity that lets users bring their own thread pool
18:42bbloomtechnomancy: i think the issue is that w/ an auto thread pool, there would be no single entry point
18:42technomancyah, that chews
18:42lynaghktechnomancy: 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:42bbloomor is there? lynaghk: is the only entry point creating sockets?
18:42nooniandoesn't seem all that gross to me, and it's necessary if you need multiple threads listening (blocking) for different things
18:43technomancythree arities when you only need one is way better than one arity when you need three
18:43lynaghkThis is the simple fn entry point: https://github.com/lynaghk/zmq-async/blob/master/src/com/keminglabs/zmq_async/core.clj#L253
18:43bbloomlynaghk: rephrasing: my question about the ancestor thread: will all sockets be created within the dynamic extent of the process which creates the context?
18:44lynaghkIt 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:44bbloomlynaghk: but creating a socket requires a context....
18:44bbloomline 270
18:45lynaghkbbloom: 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:45bbloomlynaghk: my suggestion is as follows: create a macro that initializes & shutsdown a context in a try/finally & use a dynamic var
18:45lynaghkThat 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:46bbloombut require the var be specified
18:46bbloomthen provide overloads that do or do not take that var
18:46bbloomso you can get the thread local context, or override it
18:46noncom|2what is the recommended way to access arbitrary web url from a lein plugin?
18:46lynaghkbbloom: why a dynamic var vs. passing in a value?
18:46justin_smithnoncom|2: slurp it?
18:46bbloomb/c then if two people use your "easy" API from two different entry points, they won't collide
18:46noncom|2ok, i'll try
18:47bbloomit's not global then, it's connected to the session, like a repl or another servlet host or whatever
18:47lynaghkbbloom: not sure what you mean. If there were an implicit context it could be used globally and be threadsafe
18:47justin_smiththere is also http.async.client if you need to get fancy
18:48bbloomlynaghk: 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:48bbloomlynaghk: but really, i wouldn't bother at all and do the easy thing and then wait for somebody to complain :-)
18:48lynaghkbbloom: 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:49bbloomlynaghk: or that
18:49noncom|2i think slurp will do, i just have to fetch a txt
18:49lynaghkbbloom: 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:49justin_smithnoncom|2: yeah slurp is in core, and very easy to use
18:49bbloomlynaghk: what does registration do exactly?
18:50bbloomlynaghk: why are creation and registration separate in the first place?
18:50lynaghkbbloom: because I didn't want to wrap all of ZeroMQ's options
18:50lynaghkbbloom: 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:51lynaghkbbloom: what I could do is have the registration fn take a "configurator" in the same way that run-jetty takes one
18:51justin_smith,(slurp "http://www.google.com&quot;)
18:51clojurebot#<SecurityException java.lang.SecurityException: denied>
18:51justin_smith:(
18:51bbloomlynaghk: yeah, you could just do (create-socket :foo (fn [socket] configure here))
18:52lynaghkso it creates a socket for you against the right context but still lets you call whatever java-y things you need to
18:52bbloomsure
18:52lynaghkyeah. I think that might be the way to go.
18:53bbloomalthough i might prefer a configuration map :-)
19:19noncom|2will (spit) create the path if it does not exist?
19:20bbloomnoncom|2: surely you can try "/tmp/some/path" yourself
19:37justin_smith,(apply < (map count ["(spit \"/tmp/a/b/c/d/e\" \"hello\")" "will (spit) create the path if it does not exist?"]))
19:37clojurebottrue
19:37justin_smith:P
19:37noncom|2:D
19:43justin_smith,36RCRAZY
19:43clojurebot21429358
20:09cespareAnyone use fireplace and have trouble with it finding the repl?
20:09cesparelein repl, that is
20:09cespareI've got target/repl-port.
20:18technomancycespare: temporary fix: `:target-path "target"` in your user profile
20:18technomancywill have a proper fix in a couple days
20:19cesparetechnomancy: turns out I was editing a file that was somewhere else (through a symlink)
20:19cespareI assumed fireplace used my cwd to find nrepl, but I guess it looks at where the file is.
20:29yediwhats the simplest way to install clojure
20:30bbloom~lein
20:30clojurebot"[Clojure ...] feels like a general-purpose language beamed back from the near future."
20:30bbloom*sigh*
20:30bbloomyedi: install leinigen
20:32hiredmanthe new inference code in clojurebot follows things besides "are" and "is", which it shouldn't
20:46muhoo~what is life?
20:46clojurebotNo entiendo
20:46metellus~what is love?
20:46clojurebotGabh mo leithscéal?
21:16dnolenhrm, bbloom I can't think of any reason why channels don't support metadata ...
21:18bbloomdnolen: 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:18dnolenbbloom: well I was gonna complain to tbaldridge but he's gone :)
21:18dnolenbbloom: channels aren't reference types so I'm not sure I buy that.
21:18bbloomdnolen: channels have object identity
21:19bbloomdnolen: with-meta returns a new object
21:19dnolenbbloom: oh right
21:19bbloomyeah, metadata only makes sense on things with value identity
21:19dnolenhmm
21:20bbloomdnolen: so rewinding. what makes you want the metadata? what issue are you trying to solve?
21:21dnolenbbloom: listening to events on the dom, but what wanting to clean up listener when something is done
21:22bbloomhow would metadata help?
21:23bbloomunrelated: 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:23dnolenbbloom: I wasn't considering the object identity issue, wanted store goog id for removing listeners
21:24dnolenbbloom: metadata doesn't factor into equality so I don't know how what you're saying makes sense
21:24bbloomdnolen: can't you store that in a loop loop variable in some goroutine?
21:24dnolenbbloom: still hacking away at autocompleter, introducing another bit of state would be obnoxious
21:25bbloom,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)])
21:25clojurebot(true false)
21:26bbloomadding 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:27bbloomany 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:27bbloomyet another reason objects suck
21:27dnolenbbloom: I just don't see why that's a problem, identical? checks are rare - is there something specific you're trying to do?
21:27bbloomdnolen: identical? checks are only rare b/c working with objects is rare
21:28dnolenbbloom: so why should it be any different for reify?
21:28bbloom= uses identical? internally if the object doesn't have a custom implementation
21:29bbloomif 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:30bbloomunless you also implement a method for =
21:33dnolenbbloom: 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:33bbloomdnolen: except it does for reify, i just showed you that:
21:33dnolenbbloom: if you make a new thing of something without defining equality w/o metadata you have the same problem
21:33bbloom,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)])
21:33clojurebot(true false)
21:34dnolenbbloom: yeah non-problem to me
21:35bbloom(doc with-meta)
21:35clojurebot"([obj m]); Returns an object of the same type and value as obj, with map m as its metadata."
21:36bbloomclojure has a very specific definition of "value" and, as far as i can tell, a non-value shouldn't have metadata
21:36bbloombut *shrug* i could be wrong
21:36dnolenbbloom: the doc the isn't even true for fns w/ which support metadata
21:36dnolen,(= inc (with-meta inc {:foo 'bar}))
21:36clojurebotfalse
21:36bbloomyeah i discovered that recently too
21:37dnolenbbloom: ship sailed when people asked for that, so I just think non-issue
21:37bbloomin fact, i had this precise problem: i was tried to put a function in a map
21:37bbloomand then tried to put metadata on it
21:37bbloomlater on, i couldn't look the function up
21:37bbloomif you use a metadata-ed function as a map or set key, you can't ever look it up
21:37dnolenbbloom: prior to fns supporting metadata doc string made sense, doesn't make sense after that change
21:40bbloomanyway, let's solve your actual problem
21:40bbloomyou want to store the dom element ID somewhere?
21:43bbloomsubscribe/unsubscribe function pairs for callbacks are basically the same as reference counting
21:44dnolenbbloom: no, no I know how to solve, just wanted the convenience of metadata :)
21:44dnolenbut that was a weird thing to want
21:44bbloomif i have to deal w/ sub/unsub functions at all, i rather it be implemented as garbage collection :-)
22:02holohi
22:02akurilinSay 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:02akurilinWould you make that check right before making the DB call?
22:08holocan 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:09gfredericksakurilin: 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:09gfredericksholo: (some pred coll)
22:09gfredericksno wait
22:10gfredericksthat's just (first (filter pred coll)) which doesn't have a built-in shorter form
22:10akurilingfredericks, sure, that sounds good, thanks!
22:14holoakurilin, 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:16hologfredericks, does it short circuit? i need to get myself around lazy sequences
22:16akurilinholo, perfect, thanks.
22:17gfredericksholo: it short-circuits because of laziness
22:17gfredericksmodulo chunking
22:17holoakurilin, validation by db schema constraints is dry, but it was a pain to get it working
22:18akurilinOk 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:18hologfredericks.. great!
22:19akurilinholo, 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:20akurilinholo, 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:20akurilinSo as in (do (validate input-map) (save map))
22:21akurilinCan think of exceptions as side-effects/
22:21holoakurilin wait, i didn't mean that.. i mean i get the constraints from db schema, but i use them at the api level
22:24holoi also use naming convention for validation. if a column name is *email*, the record will be checked for a valid email string
22:29holoakurilin, if i was reading that do block code, i would think (save map) was always executed, which is not, by your words
22:30akurilinholo, right. It seems like the issue here is more about readability.
22:30akurilinholo, on one hand the do makes it obvious that input-map will not change, on the other it also does what you said.
22:33akurilinMan, you guys created so many validation libraries, that's awesome.
22:38holoakurilin, why not do (when (validate input-map) (save map)) instead? the code flow is obvious, and it does the same as your code
22:45akurilinholo, it just means I'm going to have to check for nil somewhere upstream and turn that into a 400
22:45akurilinas opposed to generalizing it
22:46akurilinI can see that working too, though, don't get me wrong :)
22:48holonil? no nil will ever be returned. remember it will throw an exception
22:49holoi'm assuming you'll throw an exception there or return some truthy value
22:50akurilinholo, oh sorry, for some reason I assumed you meant not to throw an exception, my bad.
22:50holoakurilin, glad to help :)
22:50akurilinholo, yep, thank you!
23:28callenMore idiomatic way to express this? - https://www.refheap.com/17716
23:40TimMcArgh, how can Emacs packages always be such a hassle?
23:42TimMcclojure-mode seems to have disappeared from Marmalade.
23:42callenTimMc: Emacs configs didn't even have packages until recently.
23:42callenWe've been carving the stories of our elders into tree bark for centuries.
23:43callenIt wasn't until these young turks with their papyrus and stone that we started being able to reuse anytihng.
23:43callenTimMc: clojure-mode comes up in Marmalade repo search.
23:43callenTimMc: I strongly recommend having redundant repos in your config.
23:43callenI usually use Marmalade, MELPA, and the GNU one.
23:47TimMcHrm.
23:48TimMcI'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:51callenTimMc: you could just git clone my dotfiles.
23:51callenTimMc: shake-n-bake Clojure env :P