#clojure log - Oct 25 2013

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

0:11 sritchie: hey all --

0:11 do you guys have a rec for functional reactive programming libraries for Clojurescript?

0:12 tbaldridge: sritchie: I'd look into core.async. You'll probably find that it's much more sensible than FRP

0:13 sritchie: tbaldridge: okay, that's fair. I've been following dnolen's examples

0:13 just trying to figure out how all of the pieces fit together

0:13 tbaldridge: sritchie: FRP tends you put you into a world where you have to put everything into a FRP world. Core.async makes it easier to mix event streams into existing code.

0:15 sritchie: cool. just found a good todo list example

0:15 should be perfect

0:21 bitemyapp: seangrove: not yet, but there have been rumblings of cljx.

0:21 ddellacosta: sritchie: not that I disagree with tbaldridge--I've found core.async a real blessing--but this is useful if you want to investigate FRP in Clojure(/Script) further: http://kevinoncode.blogspot.jp/2013/05/a-short-survey-on-state-of-functional.html

0:22 bitemyapp: sritchie: I'm with tbaldridge. I had a pretty easy time mixing core.async into a work project without having to remodel everything in terms of FRP

0:23 sritchie: good to know - I'll go core.async, and play with FRP in Scala (in the upcoming coursera class)

0:23 one more qq, as it looks like we've got some clojurescript folks around -

0:23 justicefries: ooh, mind linking to the coursera class?

0:23 sritchie: sure, one sec

0:24 This is the "intro the scala" course on Coursera, supposedly really good: https://www.coursera.org/course/progfun

0:24 I'm at Twitter, and a bunch of folks here took this and loved it

0:24 and this is the sequel, Principles of Reactive Programming: https://www.coursera.org/course/reactive

0:25 Erik Meijer wrote that Reactive Manifesto, and Odersky wrote scala, so good instructors

0:25 one more qq - lein-cljsbuild seems to be the tool of choice?

0:25 and it looks compatible with cljz?

0:25 err

0:25 cljx

0:25 bitemyapp: sritchie: lein-cljsbuild is the tool of choice.

0:26 sritchie: I would just mention that cljs isn't required to experiment with core.async if that is exclusively what you have in mind.

0:26 sritchie: bitemyapp: yup, I've played with it in clojure - I'm working on a race timing system,

0:27 and want to update my app to show live results on each race page

0:27 so core.async + websockets + cljs seems like the way to go there

0:27 seangrove: sritchie: Sounds like a pretty good match, yeah

0:28 sritchie: Just trying to figure out if the right way to start sharing code; looks like cljsbuild's crossovers will do it

0:28 and I'm not seeing pitches for cljx; but I'll play with both

0:28 bitemyapp: Erlang users have to be pissed that their concurrency model is getting co-opted into a marketing campaign for a different language.

0:28 sritchie: it's exciting to be back coding more clojure!

0:28 bitemyapp: pi-calculus not-withstanding

0:29 sritchie: haha

0:29 bitemyapp: sritchie: if I know Haskell and Clojure, what do you think I would get out of learning more Scala?

0:29 you seem best positioned to know out of most here.

0:29 * ddellacosta is also interested in the answer to that question, although still a Haskell beginner

0:30 sritchie: bitemyapp: if you know Haskell already… the eye opener for me was an understanding of the type system, but that won't be new for you

0:30 bitemyapp: The primary utility of Scala over Haskell for me would be the JVM, which is fine, but I'm wondering what I could *learn*.

0:30 sritchie: yes, for sure

0:30 learning Scala taught me a lot about proper object oriented design

0:30 bitemyapp: sritchie: I've already been poking my nose around Scalaz. I'm a Fluokitten nut in Clojure too :P

0:31 proper OOP? I think you just tripped over the Clojure anti-shibboleth. ;)

0:31 sritchie: haha

0:31 I was terrible at writing these libraries when I first started, not trusting the type system;

0:31 but I find myself using records and protocols in Clojure much more heavily now

0:31 bitemyapp: I think given the history of the compiler, I wouldn't trust it either >:P

0:31 sritchie: :)

0:32 as a way to write Clojure libraries that are extensible by the user

0:32 bitemyapp: sritchie: multimethods are fine too ;_;

0:32 technomancy: when I was playing with OCaml, it seemed like the whole point of using records was to get exhaustiveness checks from pattern matches

0:32 which was very cool

0:33 but not applicable at all to untyped clojure

0:33 bitemyapp: technomancy: seems like a cherry-picking of what Haskellers use monads for.

0:33 pretty interesting.

0:33 sritchie: technomancy: yeah, you end up just hoping you don't forget one of the damned types, and adding nodes only with much thought

0:34 technomancy: sritchie: does scala give you exhastiveness checks on matches too?

0:34 sritchie: yup

0:34 technomancy: handy

0:34 sritchie: you can do algebraic data types with the pattern of

0:34 sealed trait A; case class B extends A; case class C extends A;

0:34 "sealed" means that all implementations are found in that file

0:35 technomancy: does typed clojure cover core.match yet?

0:35 that could be a stretch goal =)

0:35 sritchie: :) I haven't played with core.typed yet; really excited that Ambrose has gotten so much support, though

0:37 bitemyapp: so, yeah, JVM, object oriented design, learning to lean on type inference and type classes;

0:37 bitemyapp: another thing that Scala does really well (not sure what it maps to in Haskell) is implicit parameters

0:37 which took a while to learn to think about

0:38 basically, a function can declare that it takes some parameter of type T implicitly (or many parameters); the type system has a series of scopes that it searches for declared variables of that type

0:38 and the process works recursively

0:38 it's type-safe dependency injection, basically

0:38 and you can make the type system do a hell of a lot of work for you

0:38 technomancy: compiler-enforced dynamic binding?

0:39 sritchie: yeah, that's one way of putting it -

0:39 folks use this to pass around little environments, say by taking an implicit Config object on all methods -

0:40 then it can be used in the functions, but you don't have to actually pass it in each time

0:40 bitemyapp: oh whoa.

0:40 sritchie: we use it in the work I've been doing to build up these Monoid instances to do aggregation in analytics

0:41 here's one example (then I'll shut up about Scala in this channel :)

0:41 bitemyapp: sritchie: I'm enjoying this!

0:41 sritchie: say my function takes an (implicit monoid: Monoid[V])

0:41 (a monoid is an interface with "plus", so it can add two Vs together to get a third V… super simple, not a Monad, just an Adder)

0:42 bitemyapp: sritchie: Haskell does have this in case you were wondering.

0:42 "Implicit parameters: dynamic scoping with static types", J Lewis, MB Shields, E Meijer, J Launchbury, 27th ACM Symposium on Principles of Programming Languages (POPL'00), Boston, Jan 2000

0:42 sritchie: okay, cool, shame on me to think they're missing any of this business :)

0:42 a function that takes an implicit Monoid[V] basically "asks" the compiler for an instance of a Monoid for whatever V you actually used

0:43 bitemyapp: You know people wise-crack about how Emacs has an option or key combo for everything? GHC's compiler flags are like that.

0:43 sritchie: nice

0:43 so if I called that function with V = Map[String, Long],

0:43 the compiler would go do a search and find a function I wrote that declares the Monoid[Map[K, V]]

0:44 bitemyapp: type constraints on implicit parameters in Haskell are optional, due to the Damas Milner.

0:44 sritchie: (which is basically (partial merge-with <some-monoid-on-V>)

0:44 bitemyapp: so the compiler will go on similar "search", but it'll do so with the most generalizable Damas Milner type signature for the function.

0:44 you can constrain with a specified type if desired though.

0:44 sritchie: and then that function ALSO implicitly takes a Monoid[V]; so the compiler goes and finds that, and passes the final one in the the function I wanted.

0:44 bitemyapp: okay, wild

0:45 bitemyapp: it does require pausing for a moment to think about the most general applicable typeclass for your function is though.

0:45 leads to pretty reusable code, which is nice, since anybody can implement something for the same typeclass.

0:45 doesn't have to be a specific impl or anything.

0:46 sritchie: Scala does that with different implicit scopes

0:46 bitemyapp: sritchie: are monoids common to your work because commutative operations are useful in your work?

0:46 sritchie: so you can override the default Monoid[Int]

0:46 bitemyapp: yeah, we built this MapReduce library called Summingbird that uses them for that reason

0:46 http://github.com/twitter/summingbird

0:46 bitemyapp: I knew you worked on Summingbird, was just wondering in general.

0:47 sritchie: bitemyapp: so we as library implementers have been trying to solve the systems issues in terms of the algebraic properties of the V,

0:47 bitemyapp: sritchie: how much cross-talk is there between Summingbird and Cascalog/Cascalog 2?

0:47 sritchie: and yeah, commutativity and associativity

0:47 dobry-den: What's the go-to method for writing the function (foo "ffff") -> 65535

0:47 sritchie: bitemyapp: after Summingbird was released I found a few days and rewrote the guts of Cascalog to make the planner implementation generic;

0:47 which means that before clojure/conj we'll have a Storm planner

0:48 dobry-den: (unsigned numbers)

0:48 bitemyapp: sritchie: one of the things I like about writing Haskell is that I can often just "guess" at the correct code and let the compiler inform me as to how to write what I meant. Do you find Scala lends itself to this as well?

0:48 also, how do you deal with the slow compile times? this is a genuine concern if I'm doing the "mash build, get type error" event loop.

0:48 sritchie: bitemyapp: it still has java stack trace awfulness, but yes;

0:48 bitemyapp: I'd heard about fsc but didn't know how much it helped.

0:49 sritchie: and the same loveliness with refactorings and large code changes as well

0:49 bitemyapp: sritchie: oh pish. I write Clojure. I eat stacktraces taller than my desk for breakfast.

0:49 sritchie: haha

0:49 bitemyapp: sritchie: what about compile times? Does fsc help? Do you use anything for this?

0:49 a build cluster? :P

0:49 sritchie: no, it's freaking terrible

0:49 on our large internal projects

0:49 it's absolutely abysmal

0:49 bitemyapp: there's nothing to help with this?

0:50 sritchie: there is,

0:50 coventry: dobry-den: ##(Long/parseLong "ffff" 16)

0:50 lazybot: ⇒ 65535

0:50 sritchie: and Ensime + Emacs does a really good job

0:50 but we have an old pythonish build system at Twitter compiling our Scala,

0:50 and it's just not good at incremental compilation

0:50 bitemyapp: Ensime...handles the incremental compilation for you?

0:50 dobry-den: coventry: How about for bigintegers?

0:50 sritchie: bitemyapp: yeah

0:50 I think a lot of folks just use Intellij, which does use Zinc under the hood for incremental compilation

0:50 bitemyapp: Whoa.

0:51 Brava my Emacs brethren, brava.

0:51 sritchie: yup, no compelling reason to leave emacs yet, even for Scsala

0:51 for java, hell yeah

0:51 bitemyapp: sritchie: when you say pythonish build system...is this standing in for what people use sbt for?

0:51 coventry: dobry-den: Don't know.

0:51 sritchie: bitemyapp: yes

0:51 whoops, gotta run for some dinner --

0:51 back soon

0:51 fun talking about this stuff!

0:52 bitemyapp: sritchie: please do come back. I have to go to a birthday thing but look forward to speaking to you more!

0:52 dobry-den: coventry: nevermind, (BigInteger. 1 (hex-decode "ffff")) -> 65535

0:52 yeah, dumb question but ive been staring at my mess of hex/bytes/int converter functions for too long

0:53 coventry: Hmm, where would you find the docs for that? It's not on http://docs.oracle.com/javase/6/docs/api/java/math/BigInteger.html

0:53 dobry-den: coventry: yeah i was just there and saw this constructor: BigInteger(int signum, byte[] magnitude)

0:53 i guessed that 1 for signum is positive, 0 is negative

0:54 coventry: Ah, I see.

0:54 dobry-den: im new to working with bytes/hex/number-overflow so ive been rewriting my code to just pretend everything is a biginteger

1:13 What would a Typed Clojure workflow look like? Do you add annotations as you go or are annotations more helpful when you want to 'solidify' your code?

1:15 bitemyapp: dobry-den: I'd recommend adding them as you go.

1:48 marcopolo2: how does the cljs hash function work?

2:03 nvm source code was pretty helpful

2:32 arrdem: is there a compelling reason to use something besides clojure.tools.reader for EDN?

2:34 muhoo: arrdem: clojure.edn/read-string is what i use

2:35 or other things in clojure.edn namespace. is either included in 1.5.1 or as a transitive dependency of things i always include, not sure which

2:36 what's the tool of choice for creating api docs from a library that doesn't come with api docs?

2:36 arrdem: muhoo: ok thanks. I knew there was tools.reader, but I couldn't find data.edn. yay naming consistency.

2:42 ugh. If I want function literals I'm stuck with "real" clojure, arn't I.

2:43 Apage43: meaning #(do stuff here) ? yeah, those aren't "in" EDN

2:43 oh fun

2:44 muhoo: just use read-string

2:44 arrdem: hey guys, chord is begging to get unbant :P

2:45 Okay. fooie.

2:45 muhoo: not the edn version. it evals, IIRC, and that's something to consider the security issues of.

2:46 ,(doc read-string)

2:46 clojurebot: "([s]); Reads one object from the string s. Note that read-string can execute code (controlled by *read-eval*), and as such should be used only with trusted sources. For data structure interop use clojure.edn/read-string"

2:46 arrdem: yeah so the issue I'm running into is that I need configuration files with embedded code. I really don't want to build a DSL, so that's probably just embedded clojure.

2:46 the security risks of having a directory of plugin source files that are assumed safe are obvious, but I fear unavoidable.

2:47 Apage43: that's leiningen, riemann

2:47 your "configuration" is just a clojure program

2:48 What's the trust model here?

2:49 arrdem: Apage43: user provided configs eval'd on the users host. AKA none.

2:49 Apage43: I mean, if you don't actually have any reason to prevent input from any particular class of source from executing code, don't bother. It's a headache.

2:50 arrdem: Okie doke... (load-file) it is :D

2:51 Apage43: Hell, it's a feature :)

2:52 arrdem: haha. If I really decide that I care I'll create a sandboxed ns and (load-file) in there. some other day once the prototype works.

4:38 ChongLi: yeah I keep dying to eels

4:38 oops

5:18 dobry-den: Anybody on OSX Mavericks notice process `distnoted` taking up large chunk of memory?

5:21 vijaykiran: dobry-den: yup - it has been like that since betas

5:22 I keep killing it every now and then

5:27 dobry-den: i keep feeling like i have 5 zombie jvms running

5:28 not sure why i upgraded. it was an impulse at 4am. anything to procrastinate sleep, even potentially breaking my environment

5:29 but frankly the only thing ive noticed amiss aside from distnoted is Alfred

5:30 "define <word>", "spell <word>" no longer work which i depend on for sounding coherent on the internet

5:59 deg: What is the compiler trying to tell me when lein jar suddenly starts failing on the first line of my program with "Exception in thread "main" java.lang.NoClassDefFoundError: clojure/tools/reader/reader_types/Reader, compiling:(server.clj:1:1)"

6:01 mercwithamouth: has anyone tried Cider out yet? it's built on top of emacs-live....

6:02 i'm having a hard time understanding what it actually is...emacs-live seems overly damn complete

6:02 ahh just an update to nrepl...m

6:02 nm*

6:17 CookedGryphon: Hi, I'm trying to reflect all the public fields of some POD java objects

6:17 bean does exactly what I want, but isn't available on this platform

6:18 clojure.reflect is available and I can get a list of the symbols I want off the class but am having trouble turning that into a way of accessing the field on the object

6:35 broquaint: FYI my nrepl/cider problem was resolved by removing the *.elc files.

6:37 ambrosebs: technomancy: core.typed support for core.match will happen

6:38 CinC really helps, played around a bit already http://www.youtube.com/watch?v=g2zts1hW19k

7:43 Viesti: dunno if it is even worth asking, but is there a way to find references to a symbol in nrepl.el, like a counterpart to nrepl-jump

7:44 supreme__: Hi, has anyone used moving average to smoothen out "hotness" over time for "topics"?

7:44 like topic A got 10 hits but they happend 50 minutes ago and topic B has only 8 hits but they all happend 5 minutes ago, then topic B is more "hot"

7:44 is moving average a good choice for this?

7:45 without overdoing it and using something like Storm

8:18 corecode: looking for people interested in creating a good open-source schematic capture + layout system in clojure. plz take a number, everybody will get in.

9:14 mdrogalis: tbaldridge: You start work awfully early for being a west-coaster. :P

9:15 tbaldridge: mdrogalis: I work on EST time, so yeah, I tend to start early.

9:16 mdrogalis: tbaldridge: I suppose you get to finish early, so that's good. :)

9:40 dobry-den: datomic has been the perfect database for modeling the bitcoin blockchain

9:42 not so much h2 though -_-

9:47 i wonder how they stand on granting something like open-source licenses for datomic

9:48 mdrogalis: dobry-den: You can use the free edition for open source.

10:51 silasdavis: I want every thread in my application to have its own s3 client

10:51 what's a nice way of doing this?

10:53 mdrogalis: silasdavis: Are you using futures?

10:54 silasdavis: I'm using a scheduledtaskexecutor

10:54 through at-at

10:54 so.. um, no?

10:55 currently I'm doing a lot of passing s3-client around

10:55 which I don't particularly like

10:59 mdrogalis: silasdavis: You could use thread-local bindings I suppose.

11:01 silasdavis: so use a set! statement in the head of my thread's main function?

11:02 mdrogalis: silasdavis: http://stackoverflow.com/questions/7387098/threadlocal-counter-in-clojure

11:31 noncom: hi, what is the idiomatic way to get a subvector from a vector by indices. for example, i have a vector and i want a subvector which starts at index 5 and goes up for 10 positions, ending on index 15

11:32 drop-take?

11:38 nathanic: noncom: http://clojuredocs.org/clojure_core/clojure.core/subvec

11:58 seangrove: cemerick: We have an html page we use for developing that has a few dom elements and the generated javascript - it's not clear how I can get austin to open up that page. Am I misunderstanding the usecase for austin?

11:59 cemerick: seangrove: this is the page that contains/loads your app?

11:59 seangrove: Yes

12:00 With piggieback, we call `(repl/connect "http://localhost:9000/repl")` from it

12:00 cemerick: seangrove: in that use case, _you_ open that page in your browser.

12:00 Just like the classic browser REPL, except you don't have to mess with port numbers, can have multiple browser REPLs running, etc.

12:02 seangrove: cemerick: Do I open the page in the window that opens from running `(cemerick.austin.repls/exec :exec-cmds ["open" "-ga" "/Applications/Google Chrome Canary.app"])`? Navigating away seems to (obviously) break the connection

12:02 cemerick: seangrove: no, that's solely for "headless" REPLs that still have your project's code on the classpath, etc.

12:02 seangrove: Say my page is on http://localhost:3001/example.html and the repl env has opened on http://localhost:59554/2305/repl/start

12:03 Ok, let me re-read

12:03 cemerick: There's two use cases; the classic browser-connected REPL one is detailed @ https://github.com/cemerick/austin/tree/master/browser-connected-repl-sample

12:04 seangrove: cemerick: Wait, do I want the classic browser-connected REPL? I'm manipulating the dom and rendering templates to see how they look.

12:07 cemerick: seangrove: Yeah, you need your app open and initiating the connection so you can see it behaving, etc.

12:07 The headless option is fine for automated testing of DOM manipulations and such, but none of that is going to be human-visible, etc.

12:08 seangrove: cemerick: Yeah, sorry, I thought I was doing the project repl

12:12 cemerick: Also, while you're around, this patch look like the right way for cljsbuild to hook into analyzer warnings? http://dev.clojure.org/jira/browse/CLJS-636

12:18 cemerick: seangrove: yeah, something like that would work, though I flinch at more dynamic vars floating around. I'd prefer to have all warnings and the result of compilation (i.e. the analysis or a string of js) bundled into a return value, but I don't know that anyone (including dnolen) has the stamina to write/review such a sweeping change at the moment.

12:18 Also, I'd like to hear what ambrosebs and Bronsa need in this area before running full bore into anything.

12:20 seangrove: cemerick: Yeah, I suppose the iterative warning-callback approach isn't as nice as a complete datastructure with the results of the compilation at the end.

12:22 cemerick: seangrove: it goes along with the nature of things at the moment, since everything is done on a form-by-form basis, but we really want to think of compilation/analysis as a per-file (maybe per-namespace) thing.

12:23 Just having gotten done tweaking around how the reader interacts with the analysis of ns forms, the imperativeness left a strong impression. :-)

12:32 seangrove: cemerick: Also, thank you so much for everything you've done, you're hugely responsible for cljs being usable at all

12:32 cemerick: seangrove: thanks, just hacking the underbrush I come across :-)

12:33 Just wait 'til my stuff breaks, then you won't be so happy! ;-)

12:33 seangrove: cemerick: Oh your stuff breaks all over the place, hence my recent issues ;)

12:34 cemerick: hah, well

12:34 * cemerick runs to add a liability disclaimer to all his projects

12:34 seangrove: One difference I've notice while in the cljs-nrepl.el vs jvm-nrepl.el envs though is that when in ns example.a in the repl, and evaulating a form in example.b's buffer, the form is evaulated in the repl in example.a, which causes plenty of problems

12:35 yeoj___: what's the proper way to wrap "new's" of class names, when it comes to java interop?

12:35 seangrove: I just switch namespaces with C-c M-n, but I often trip over this, and with the newcomers around me, they're really running into a lot of these things I've just learned to work around

12:35 yeoj___: for instance, new OutputStreamWriter(new FileOutputStream("outfilename"), "UTF-8")

12:36 seangrove: yeoj___: (OutputStreamWriter. (FileOutputStream "outfilename") "UTF-8")

12:36 Woops, a period at the end of the FileOutputStream too

12:37 yeoj___: ahh, ok.

12:37 seangrove: thanks.

12:39 cemerick: seangrove: That *should* work, but I haven't looked into how cider sends "eval expression" operations. Feel free to open a ticket on piggieback describing the observed problem.

12:40 seangrove: cemerick: Will do, would like to start helping out a bit more on the cljsbuild/piggieback side

12:40 cemerick: What did you do around the namespaces? I've noticed quite a few problems with them actually

12:41 cemerick: seangrove: not sure what you mean; do around namespaces where?

12:42 seangrove: You mentioned you tweaked how the reader interacts with the analysis of ns forms

12:43 cemerick: seangrove: oh, that change is still just on HEAD, hasn't been released yet

12:50 poppingtonic: hello

12:50 dnolen: cemerick: yeah I think anything major should probably wait for integration with standard analyzer and backend tools

12:51 poppingtonic: cemerick: I'm reading your book, and it's amazing. Thanks. :)

12:53 cemerick: dnolen: Yeah. Though, I will be adding a hack in cljsbuild v2 to be able to fail on different warnings based on grepping the output.

12:53 poppingtonic: how do I get pprint to work? 1.5.1

12:54 cemerick: Dirty, but I need builds to fail when there's particular classes of problems. Right now, automated deployment processes can leak out busted .js without a peep.

12:54 dnolen: cemerick: why wouldn't you just use what seangrove is working on?

12:54 cemerick: dnolen: If you decide to merge it, I'll use it. :-)

12:55 But, that's a month out anyway. Hoping to finish cljsbuild v1.0 early Nov.

12:55 poppingtonic: cemerick: doesn't pprint work out of the box? I can't get to use it for the game-of-life example.

12:55 dnolen: cemerick: heh, we need a stop gap, I'm pretty sure seangrove's thing'll make it in.

12:56 cemerick: Then we can start ripping things up into some simpler/easier bits.

12:56 poppingtonic: glad you're liking the book. My coauthors were instrumental. :-)

12:56 poppingtonic: Have you done (require 'clojure.pprint), or similar?

12:57 poppingtonic: cemerick: I get this: "CompilerException java.lang.RuntimeException: Unable to resolve symbol: requie in this context, compiling:(NO_SOURCE_PATH:1:1) "

12:58 cemerick: poppingtonic: you misspelled 'require'

12:58 poppingtonic: because it's a misspell :)

12:59 works.

13:02 cemerick: poppingtonic: :-)

13:04 poppingtonic: cemerick: Thank you.

13:10 seangrove: ddellacosta: I wasn't really talking about the library ecosystem (I think that's a different story that'll improve on its own) re: cljs tooling challenges

13:10 ddellacosta: seangrove: sorry if I digressed. Was thinking generally about the beginner story, as you put it

13:12 seangrove: ddellacosta: Quick start guide could definitely be updated

13:12 With a lein template, there's probably a one-liner someone could copy/paste and have a full lein cljs app running and open in their browser

13:12 The step after that is tough though...

13:13 rads: I noticed with lein-cljsbuild 0.3.4, when I use "lein cljsbuild auto", it sometimes fails with an error and stops the process. this means I have to fire up a new JVM every time this happens. is there a way to keep it recompiling even when there's an error?

13:13 ddellacosta: yeah, I think a template is part of it

13:13 ^^ haha

13:13 sorry, just funny timing

13:14 seangrove: but yeah, don't mean to suggest it is a simple fix--was really just trying to brainstorm. Twitter maybe not best place for that.

13:14 technomancy: rads: `lein do cljsbuild auto, cljsbuild auto, cljsbuild auto, cljsbuild auto` =)

13:16 there are a bunch more actually useful higher-order lein plugins that should exist, but I just want to write lein-ski

13:16 rads: I see, so the answer is, restarting the process is out of the scope of lein-cljsbuid?

13:17 technomancy: sorry, I haven't actually used lein-cljsbuild. ignore me. =)

13:18 cemerick: rads: that's a recent regression; use 0.3.3 until it's fixed for v1.0

13:18 poppingtonic: cemerick: the ghastly exception returns: "CompilerException java.lang.RuntimeException: Unable to resolve symbol: pprint in this context, compiling:(NO_SOURCE_PATH:1:1) "

13:18 cemerick: rads: https://github.com/emezeske/lein-cljsbuild/issues/249

13:18 poppingtonic: you've probably switched namespaces

13:19 rads: cemerick: oh cool. I was thinking it was intentional after reading gh-234. good to hear it's not

13:19 ty!

13:21 gfredericks: technomancy: how usable would leiningen be w/o maven?

13:21 as a "run tasks in deployment" kind of tool

13:21 technomancy: gfredericks: without aether you mean?

13:22 gfredericks: e.g., if I have all the jars for lein itself already on the machine somewhere, and ditto for the project, can I do a reasonable subset of lein things without it using maven?

13:23 justin_smith: gfredericks: no dependencies list, and manually put each jar in the classpath via resource-paths or source-paths ?

13:23 gfredericks: well the dependencies list will still be in the project.clj, but presumably no need to read it

13:23 technomancy: gfredericks: depends how deeply you're interested in mangling lein I guess?

13:24 gfredericks: technomancy: just trying to get a feel for how much work that would be to enable

13:24 justin_smith: gfredericks: then you would need to create the classpath including all those jars in some other way, right?

13:24 technomancy: gfredericks: you could (ns leiningen.core.classpath) (def get-classpath (constantly ["/some/" "/coll" "/of" "/paths"])) (ns user) (defproject ...)

13:24 maybe

13:25 gfredericks: hmmm

13:25 interesting; thanks

13:26 technomancy: probably better to dump everything in :resource-paths and leave :dependencies empty though

13:28 gfredericks: ideally wouldn't have to muck with the project.clj to make this work

13:28 but I'm leaning toward abandoning the idea altogether

13:36 cemerick: gfredericks: what's your original pain?

13:51 dnolen: if somebody has time it would be nice to test this one on a non-Windows box - http://dev.clojure.org/jira/browse/CLJS-637

14:01 seangrove: dnolen: I can check it out later today

14:01 dnolen: seangrove: thanks much

14:02 dobry-den: does byte-array of a single byte have an endianness (even though it can't be expressed with a single byte), or does it have no endianess.

14:03 nevermind. painful to read my own question. is ["a"] sorted a-z or z-a?

14:04 znDuff: dobry-den: How is it "sorted" in any sense at all?

14:04 dobry-den: znDuff: I would say it's sorted in the way it would be sorted had it one more byte of info

14:04 justin_smith: dobry-den: I don't think endianness comes into play, bytes are always signed 8 bit in the jvm no?

14:05 znDuff: ...but vectors are ordered, so the sorting is user-defined.

14:05 dobry-den: yeah, the context is weird

14:05 justin_smith: it is only when you coerce a byte array into some other type that endianness is even a factor, and "a" is not a byte

14:06 dobry-den: that was me judging myself with an analogy

14:06 in my codebase, i decided to represent all bytes as vectors of hexstr pairs

14:06 justin_smith: ok, but 8 bit things are immune to all concerns of endianness

14:07 just remember to do the signed conversion

14:08 dobry-den: in my head, endianness describes a collection of 8-bit things.

14:08 justin_smith: right, but if each one is 8 bits, endianness does nothing

14:08 now if the question is "what is the endianness of a double when stored as a byte array" - that may be getting at what we want

14:09 but that is not the byte's endianness - it is the object being converted to byte

14:31 dobry-den: justin_smith: thanks. that reminded me that endianness only matters in that it describes how to interpret the bytes that represent something (when there's more more than 1 byte)

14:39 justin_smith: np

14:42 dobry-den: the eternal `util` namespace is like a function waiting room for abstractions/extractions that will probably never happen

14:44 mdrogalis: I used to think that, but on projects of bigger size, little things emerge.

14:44 Simulant as a util ns.

14:44 Has*

14:45 dobry-den: yeah i think a util namespace is a solid place to put some things until you can see the patterns that lead to abstractions

14:48 im just looking at my util namespace right now and it's starting to feel like a massive CSS file i keep telling myself im gonna refactor

14:50 but i think the uneasiness comes from other languages where a large file means im probably coupling things together

14:50 in clojure ive found it usually more trouble than it's worth to try and organize prematurely

14:51 em-dash: I started porting clojure's persistent data structures to objective-c: https://github.com/emmanuel/clojure-objc

14:51 I conceived the effort as a start towards a full implementation of Clojure in Objective-C. My intentions were self-pedagogical, but I have some hopes that the effort will be more widely useful.

14:52 dnolen: em-dash: how will that work w/o GC? (honestly curious)

14:52 em-dash: Now I'm taking a look around and trying to get a sense of what's out there

14:52 dnolen: reference counting

14:52 ARC, specifically

14:53 though, frankly, I may be completely oblivious to major issues on that front

14:53 The underlying storage of pointers is managed by NSArray (persistent vector) & NSPointerArray (persistent hash map)

14:54 poppingtonic: I need a little help figuring out why pprint won't work. This is basically what's happening every time: https://www.refheap.com/20169

14:54 dobry-den: em-dash: i like this kind of stuff m8.

14:54 em-dash: both of which provide ARC retain/release management of their contents (when the content is objc objects)

14:54 mdrogalis: dobry-den: I hear that.

14:54 dobry-den: it's my kind of yak shaving

14:56 em-dash: dobry-den: you and me both :D

14:56 `cbp: poppingtonic: you need to call it like clojure.pprint/pprint

14:57 poppingtonic: em-dash: can you help me out?

14:57 hi :)

14:57 em-dash: poppingtonic: one bit of irony is, I don't know clojure well (yet)

14:57 poppingtonic: oh, `cbp: thanks. works quite well.

14:58 `cbp: poppingtonic: or you need to require like (require '[clojure.pprint :refer [pprint]])

14:59 poppingtonic: `cbp: that's even better! I was wondering if (require x) has syntax like the (:require x) during namespace creation. Like (:require 'clojure.pprint :as pprint)

15:00 em-dash: you and me both :)

15:02 `cbp: poppingtonic: they're practically the same thing

15:02 justin_smith: poppingtonic: yes it does - if you look at almost any well used clojure project on github you will see them doing that in their namespace definitions

15:02 em-dash: dnolen: re: your question about memory management/GC, I'd love to chat through what considerations one should bear in mind. I think that ARC will work for the persistent collections, but I am far from an expert there.

15:03 poppingtonic: justin_smith: Well, I have seen that pattern many times from the projects I've cloned.

15:09 em-dash: and... I've got to run for a bit...

15:28 jtoy: how would I convert BytesInputStream into a string? str and other methods I have tried dont seem to work

15:29 noonian: jtoy: i think you can use slurp

15:29 ,(doc slurp_

15:29 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

15:29 noonian: ,(doc slurp)

15:29 clojurebot: "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments."

15:30 justin_smith: jtoy: apply str

15:33 jtoy: slurp worked but apply str didnt work in this situation,thx

15:34 justin_smith: ok, interesting

15:34 maybe I was thinking of something different, I thought that had worked for me before

15:35 jtoy: justin_smith: it could be the library i am using

15:35 that is acting differently

15:36 justin_smith: I see now I wasn't using a BytesInputStream - is that something from org.httpkit?

15:36 jtoy: justin_smith: yes, exactly

15:36 noonian: (apply str blah) would be for converting a seq of chars to a string for instance

15:36 or turning a seq of strings into a single string

15:37 justin_smith: I misremembered

15:37 I was using (String. bytes)

15:37 or, more exactly (String. bytes "UTF-8")

15:38 jtoy: justin_smith: are slurp and (String. bytes "UTF-8") equivalent here?

15:39 justin_smith: String. works for me with bytes where str and (apply slurp ...) do not- but I don't know that it would be identical to slurp

15:39 errr... make that (apply str ...) above, sorry

15:39 ,(slurp (.getBytes "hello"))

15:40 clojurebot: "hello"

15:40 justin_smith: ,(String. (.getBytes "hello"))

15:40 clojurebot: "hello"

15:40 justin_smith: ,(str (.getBytes "hello"))

15:40 clojurebot: "[B@1f2929c"

15:40 justin_smith: ,(apply str (.getBytes "hello"))

15:40 clojurebot: "104101108108111"

15:40 justin_smith: so yeah, String. and slurp seem to be doing something similar

15:43 noonian: i just like reading the word 'slurp' in my code :p

15:44 coventry: Yay, http://clojure-log.n01se.net/ is back.

15:58 dobry-den: How can you check for value equality regardless of the sequence type? (= [:a [1]] '(:a '(1)))

16:02 shoshin_: ping. i came across this snippet of code recently, i didn't understand this fully.

16:02 (every? identity (mapv (fn [x] (println x))[1 2 3 4 5]))

16:02 returns 1 2 3 4 5 false.

16:03 this is form (every? identity ...) used for iterating over a collection?

16:03 coventry: shoshin_: ##(nil? (println "foo"))

16:03 lazybot: ⇒ foo true

16:03 hiredman: ,(doc every?)

16:03 clojurebot: "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false."

16:03 hiredman: ,(doc identity)

16:03 clojurebot: "([x]); Returns its argument."

16:03 coventry: shoshin_: ##(every? odd? '(3 5 7))

16:03 lazybot: ⇒ true

16:04 shoshin_: yeah. i understand what every? and identity do separately.

16:04 but what exactly is happening in this code here?

16:04 coventry, hiredman ^^ :)

16:05 coventry: println is printing out the vector elements, then returning nil, so you end up with a list of nills, passed through identity to every?, which then returns false when it hits the first nil.

16:07 shoshin_: coventry a list of nils?

16:07 coventry: ,(mapv (fn [x] (println x))[1 2 3 4 5])

16:07 clojurebot: 1\n2\n3\n4\n5\n[nil nil nil nil nil]

16:08 shoshin_: coventry oh. okay. got it.

16:08 thank you!

16:08 is it an effective way to iterate over a collection?

16:09 coventry: You need to be more specific. It can be.

16:10 shoshin_: coventry the collection here is a vector of URLs and the anonymous function is used to determine if they are valid URLs or not.

16:10 coventry: shoshin_: Try it and see.

16:13 sritchie: anyone here using the piggieback repl?

16:14 technomancy: ~anyone

16:14 clojurebot: Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..."

16:14 bitemyapp: sritchie: I see piggieback mentioned regularly.

16:16 sritchie: bitemyapp: was curious about the workflow for having a clojure + clojurescript repl up at the same time

16:19 bitemyapp: sritchie: seangrove recently got somebody rolling with such a setup, I don't think anything is stopping you from having two nrepls.

16:19 sritchie: nice

16:19 boom

16:23 sveri: hi, i am trying to include the java recaptcha library, but i get a java.lang.ClassCastException when i run my code, i think that i use the java lib wrong in the clojure sense, can someone hint me how to do it right please? here is the code: http://pastebin.com/Xk1jQY7B

16:24 cmajor7: is "https://github.com/pauldorman/clj-ldap" the way to go with LDAP in Clojure? thx

16:28 coventry: sveri: http://clojure.org/java_interop You are trying to call a java object as if it were a clojure one. You need to learn about the . notation.

16:28 gfredericks: is it weird that sorted sets don't support nth?

16:29 sveri: coventry: ok, i will have a look at it, thank you

16:29 bitemyapp: gfredericks: no

16:31 gfredericks: bitemyapp: why is that?

16:33 bitemyapp: gfredericks: sets fall under "blind seq'ing and membership checks". nth-ness isn't meaningful and relies on the exact composition of the entire set.

16:33 sets are not associative by position.

16:34 so between the overly data-dependent nature of what an nth against a sorted set will get you, and that they aren't associative by position, I don't think it makes sense.

16:34 It would just, no offense, lead to brittle code.

16:34 coventry: lists aren't associative by position either, are they?

16:35 bitemyapp: coventry: vectors are, but lists don't suffer from the data dependence total re-ordering of all values that sorted sets do.

16:35 technomancy: yeah, i dont buy that

16:35 bitemyapp: all your shit gets shuffled to the right if a "least" value gets added to the sorted set

16:35 gfredericks: total re-ordering?

16:35 oh

16:36 bitemyapp: sorry, not re-ordering. The shuffle/waterfall effect from shoving things around.

16:36 lists get cons'd predictably and vectors get conj'd predictably.

16:36 conjing onto the end of a vector doesn't invalidate the "nth-ness" of all preceding values.

16:37 I'm less concerned with the validity of nth'ing lists, it has practical value and is less brittle than sorted set nth, but vectors are the best example.

16:37 gfredericks: does my position make sense?

16:37 gfredericks: I can definitely see the distinction

16:38 coventry: Sometimes that's exactly the data dependence you'd want though. Sometimes you want to know the 5th lowest element in a set.

16:38 technomancy: it feels like an attempt to retroactively justify the behaviour though =)

16:38 gfredericks: the particular reason this has come up for me is when doing algorithms on undirected graphs, where I represent an edge as #{a b}

16:39 and I kept wanting to destructure the edge without caring which thing came out first

16:39 (let [[a b] #{1 2}] ...)

16:41 I somewhat understood it failing for regular sets; then it failed for sorted sets and my other eyebrow went up

16:42 stuartsierra: gfredericks: You can call `seq` on the set and then destructuring will work

16:42 gfredericks: yep

16:42 bitemyapp: technomancy: it makes perfect sense to me, I'm not bending over backwards here.

16:42 TimMc: I'm surprised it doesn't call seq automatically.

16:42 gfredericks: that's what I ended up doing

16:54 l3dx: I'm playing around with compojure and trying to fetch both a url param and the body content of the request. Here's what I got -> http://pastebin.com/wzNLSARk

16:56 probably a newbie error

16:58 znDuff: l3dx: would you mind posting that somewhere without the ads? pastebin.com is something of an eyesore for folks not running adblock.

16:59 l3dx: znDuff: oh, I didn't know

16:59 give me a sec

17:01 https://gist.github.com/tskardal/c4141b519a0e591ff159

17:04 znDuff: l3dx: thanks; just a moment while I get set up to validate what I remember about compojure's destructuring syntax.

17:14 l3dx: https://gist.github.com/charles-dyfis-net/6e7362a50e043ae7b327

17:14 l3dx: note the :as keyword

17:15 TimMc: I've been using Clojure's PersistentHashMap from Java, and now I'm getting some bullpucky about contains? not being supported on PersistentList: https://www.refheap.com/20171

17:16 All I did was change some internal dependencies internal to my project; is there something I should be doing to initalize Clojure?

17:18 l3dx: znDuff: ah, thanks! :)

17:19 stuartsierra: TimMc: `contains?` was never supported on PersistentList.

17:19 znDuff: l3dx: ...by the way, you can do that kind of experimenting in Light Table, if it makes the feedback loop a bit quicker. :)

17:20 stuartsierra: TimMc: Clojure 1.5 changed `contains?` to throw an exception if you try to call it on something it doesn't support, instead of returning nil.

17:20 TimMc: stuartsierra: But if I put static { RT.init(); } near the top of one of my main Java files, the error goes away.

17:21 stuartsierra: TimMc: Then I have no idea what's going on. :)

17:21 TimMc: (And RT.init() chides me for calling it.)

17:21 dnolen: nice core.logic video from tbaldridge - http://www.youtube.com/watch?v=HHZ8iqswiCw&feature=youtu.be&a

17:21 l3dx: znDuff: I'll check it out

17:22 TimMc: stuartsierra: But to your knowledge I should just be able to use PHM and Util such?

17:22 *and such

17:22 stuartsierra: TimMc: Theoretically yes, although those APIs are not stable across Clojure versions.

17:23 TimMc: But that stack trace looks like an error in Clojure code caused by calling `contains?` on a list.

17:23 coventry: Yeah, I'm curious what file it's trying to load.

17:23 TimMc: Yeah, haven't really dug into what's going on there.

17:26 https://github.com/clojure/clojure/blob/clojure-1.5.1/src/clj/clojure/core.clj#L5364

17:27 (contains? @*loaded-libs* lib)

17:27 stuartsierra: *loaded-libs* is a set

17:27 TimMc: So you claim. :-P

17:27 hiredman: TimMc: you shouldn't call init, the satic init for RT will take care of that

17:28 TimMc: hiredman: It was a debugging step.

17:28 stuartsierra: https://github.com/clojure/clojure/blob/clojure-1.5.1/src/clj/clojure/core.clj#L5271-L5274

17:28 TimMc: And yet.

17:29 I mean, it *should* be a set...

17:32 stuartsierra: TimMc: Check if you somehow have multiple versions of Clojure on the classpath.

17:34 rurumate: ,(count (clojure.lang.Var/getThreadBindings))

17:34 clojurebot: 9

17:35 rurumate: what is this, and why is it 9?

17:36 jacktasia: is there a way to convert a string (code from a file) to something that can be used by clojure.pprint/write?

17:36 coventry: jacktasia: Convert a string to a clojure datastructure? Maybe read-string is what you're after?

17:36 stuartsierra: ,(doc get-thread-bindings)

17:36 clojurebot: "([]); Get a map with the Var/value pairs which is currently in effect for the current thread."

17:36 rurumate: in my repl, it's 26

17:37 jacktasia: coventry: thanks, i've tried read-string but it seems to only take the first line of the string

17:37 rurumate: ,(let [afasdf 1328767658] (count (clojure.lang.Var/getThreadBindings)))

17:37 stuartsierra: rurumate: It's the set of thread-local Var bindings currently in effect. The REPL sets a bunch of thread-local bindings automatically.

17:37 clojurebot: 9

17:37 gfredericks: ,(->> (get-thread-bindings) (keys) (map str))

17:37 clojurebot: ("#'clojure.core/*err*" "#'clojure.core/*print-length*" "#'clojure.core/*out*" "#<Var: --unnamed-->" "#'clojure.core/*ns*" ...)

17:37 stuartsierra: Tools like Leiningen and nREPL set a bunch more bindings.

17:38 TimMc: stuartsierra: Pretty darn sure.

17:38 jtoy: im trying to do some basic macros with korma, could anyone let me know what I am doing wrong: https://www.refheap.com/20172

17:39 coventry: jacktasia: It will take the first form. You could do something like ##(read-string (str "[" "(1 2 3) {4 5 6 7}" "]"))

17:39 lazybot: ⇒ [(1 2 3) {4 5, 6 7}]

17:40 gfredericks: jtoy: you have feeds as a keyword in the not-macro example

17:40 but it'll be a symbol with your macro

17:40 so you should get the same error as having used (table feeds)

17:40 coventry: jacktasia: But actually, you probably want clojure.edn/read-string

17:41 pjh_: hey ben, welcome to the clojure channel

17:43 jtoy: gfredericks: I thought that might be the issue, I also tried with this but got the same error https://www.refheap.com/20172

17:45 rurumate: stuartsierra: thanks for the insight; I'm trying to make sense of the mess that (macroexpand '(go (<! c)) produces

17:45 stuartsierra: rurumate: Ha! Talk to tbaldridge.

17:48 tim_: rurumate: short answer: http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/

17:48 jtoy: anyone else know what I am doing wrong with this macro definition ? https://www.refheap.com/20172

17:49 rurumate: tbaldridge: gee thanks, that's exactly what I'm brooding over!

17:49 tbaldridge: jtoy: the argument to (table ...) is a kw, not a symbol

17:50 rurumate: if you want the long answer, there's about 2 hours of video on the subject here : http://www.youtube.com/channel/UCLxWPHbkxjR-G-y6CVoEHOw

17:51 jtoy: tbaldridge: i tried with symbol, keyword, and passing directly in and get the same error

17:52 (table (keyword ~ent))

17:52 dnolen: tbaldridge: nice core.logic video

17:52 rurumate: tbaldridge: that's so cool

17:52 tbaldridge: dnolen: thanks.

17:52 * rurumate grabs popcorn

17:53 jtoy: the error always says it is this line : (deftable feeds)

17:56 gfredericks: jtoy: you want to convert it to a keyword at macroexpand time

17:56 so ~(keyword (name ent))

17:57 jacktasia: coventry: thanks clojure.edn/read-string works but it still with only the first form...and ##(read-string (str "[" "(1 2 3) {4 5 6 7}" "]")) doesn't seem to work for me

17:57 lazybot: ⇒ [(1 2 3) {4 5, 6 7}]

17:57 gfredericks: jtoy: i.e., you want to insert a keyword into the code, not write code that calls the keyword function

17:58 jtoy: gfredericks: ah, i see, i need to study that more

18:00 jacktasia: conventry: or are you saying just wrap the code in []?

18:00 coventry: jacktasia: Leave off the ## prefix. That is just a way to tell lazybot to report the result of evaluation here.

18:01 mattmoss: Maybe I'm missing something obvious... but how can I "functionally bind"? What I mean is being able to do something like: (let [{:keys ids} (reduce #(assoc % %2 (str %2)) {} ids)] a)

18:01 But where the (str %2) is some non-trivial result.

18:01 gfredericks: jtoy: shameless plug: http://www.infoq.com/presentations/macros-clojure-west-2013

18:02 * Raynes plugs gfredericks

18:02 mattmoss: And that last 'a' would be a larger body, able to make use of any ident found in ids.

18:02 ids being a vector like: [:a :b :c]

18:11 * gfredericks plugs Raynes back

18:11 Raynes: Ow! My back!

18:12 stuartsierra: Was there ever an answer on how to prevent Leiningen from injecting 'test'-scoped dependencies into the pom.xml it generates?

18:16 staafl: good evening

18:16 i'm solving this: http://www.4clojure.com/problem/28#prob-title

18:16 is there a concise way to check if sth is a list OR a vector

18:18 mattmoss: (or (list? x) (vector? x)

18:19 with closing paren

18:20 staafl: mattmoss, nothing built-in?

18:20 justin_smith: seqential? is close, but maybe not quite it

18:21 staafl: justin_smith, it seems to work nicely

18:21 that's the catch?

18:21 mattmoss: staafl: Those are all builtins. And fairly concise, I'd say. Though you could define a new function if you like: (defn list-or-vector? [x] (or (list? x) (vector? x))) and then just use (list-or-vector? x)

18:21 justin_smith: maybe java arrays and bytevectors

18:21 those may be also sequential?

18:21 jacktasia: coventry: thanks that worked - although now i have to strip off the extra brackets, but i can't get pprint-write to go into a variable. i thought print-str would work but doesn't

18:21 AimHere: Both lists and vectors have the java.util.List type

18:21 mattmoss: seq? or sequential? is close, but means something different, methinks

18:22 AimHere: ,(seq [3 4 5])

18:22 clojurebot: (3 4 5)

18:22 AimHere: ,(seq? [3 4 5])

18:22 clojurebot: false

18:22 justin_smith: staafl: acutally those are not sequential?

18:22 ,(sequential? (into-array (range 34)))

18:22 clojurebot: false

18:23 justin_smith: ,(sequential? (.getBytes "hello"))

18:23 clojurebot: false

18:23 justin_smith: those surprise me

18:23 staafl: for my purposes, sequential? will do nicely

18:23 justin_smith: but they mean sequential? does what you want

18:23 yeah

18:23 staafl: yeah

18:23 mattmoss: staafl: sequential? may be what you want, but you may have meant a different question than what you asked.

18:24 ,(sequential? #{1 2 3})

18:24 clojurebot: false

18:24 staafl: mattmoss, in general it'd be nice to be able to check if something is "iterable"

18:24 justin_smith: seq

18:24 staafl: being a total newb i don't know if sequential is the proper word for it

18:24 justin_smith: err not seq

18:24 mattmoss: ,(map sequential? ['(1 2 3) [1 2 3] #{1 2 3} {:a 1 :b 2 :c 3} (seq 1 2 3)])

18:24 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (3) passed to: core$seq>

18:24 justin_smith: iterable would be coll?

18:25 mattmoss: ,(map sequential? ['(1 2 3) [1 2 3] #{1 2 3} {:a 1 :b 2 :c 3})

18:25 clojurebot: #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )>

18:25 mattmoss: danngit

18:25 justin_smith: (map coll? [[] '() {} #{}])

18:25 mattmoss: (map sequential? ['(1 2 3) [1 2 3] #{1 2 3} {:a 1 :b 2 :c 3}])

18:25 ,(map sequential? ['(1 2 3) [1 2 3] #{1 2 3} {:a 1 :b 2 :c 3}])

18:25 clojurebot: (true true false false)

18:25 justin_smith: ,(map coll? [[] '() {} #{}])

18:25 clojurebot: (true true true true)

18:25 justin_smith: coll is for things you can iterate with map etc.

18:25 *coll?

18:26 staafl: justin_smith, looks quite useful

18:26 and good to know, anyway for this little exercise either will do nicely

18:26 justin_smith: not quite complete though

18:26 mattmoss: staafl: Okay, yeah, "iterable" is different than "list or vector". coll? sounds close (http://clojuredocs.org/clojure_core/clojure.core/coll_q)

18:26 justin_smith: ,(map identity (.getBytes "hello"))

18:26 clojurebot: (104 101 108 108 111)

18:26 justin_smith: ,(coll? (.getBytes "hello"))

18:26 clojurebot: false

18:27 justin_smith: so there is something missing still to finding if you can map on something

18:27 staafl: mattmoss, i indicated the limited scope of my question :-)

18:27 btw, how do i hook into the repl startup process

18:27 i want to change the prompt

18:27 jacktasia: coventry: nvm (with-out-str) is what i was looking for

18:27 justin_smith: so what is the more general version of coll? that would also return true for a jvm array you can map over? I wonder

18:28 AimHere: ,(instance? java.util.List [:a :b :c])

18:28 clojurebot: true

18:28 AimHere: ,(instance? java.util.List #{:a :b :c})

18:28 clojurebot: false

18:28 stuartsierra: (try (seq x) true (catch Exception _ false)))

18:28 justin_smith: really, no way without a try/catch?

18:30 stuartsierra: `seq` is defined as a bunch of special cases for things like Java arrays, so there's no one predicate that defines what it works on.

18:30 justin_smith: good to know, thanks

18:31 stuartsierra: Some things are "sequable" but are not really collections, e.g. Strings.

18:32 justin_smith: heh, at that point, why not make namespaces and classes sequable too (just kidding lets not actually do that)

18:34 stuartsierra: If you want the gory details: https://github.com/clojure/clojure/blob/c32511a4073edc7e7a38d47e097fb9e0c2b0a3f5/src/jvm/clojure/lang/RT.java#L480

18:35 staafl: there is no reason not to consider a string a collection

18:35 a read-only collection of chars

18:35 justin_smith: a namespace is a collection of vars

18:36 a class is a collection of methods and fields

18:36 stuartsierra: staafl: It depends on your use case. E.g. ##(flatten [1 [2] "345"])

18:36 lazybot: ⇒ (1 2 "345")

18:37 staafl: hmm

18:37 stuartsierra: justin_smith: Clojure's Namespace is essentially a map in an Atom.

18:37 dnolen: ,(doc coll?)

18:37 clojurebot: "([x]); Returns true if x implements IPersistentCollection"

18:37 justin_smith: stuartsierra: I kind of assumed that was hiding under there somewhere :)

18:38 `cbp: bitemyapp: ping

18:45 nicholas_: hey, I want to write a simple json API, writing to postgres

18:45 what's a good framework for that? I'm thinking of using Luminus

18:46 bitemyapp: `cbp: pong

18:46 `cbp: I was discussing connection life cycle management strategies with yogthos last night, he seemed to think what I had in mind made sense.

18:46 `cbp: you know the current state of things isn't thread-safe at all right?

18:47 yogthos: can confirm :P

18:47 bitemyapp: actually, you don't even need threads to cause a race condition, just one query that is slower than the next.

18:47 `cbp: did you have a question/desire?

18:47 I was hoping to get the connection management stuff done this weekend. (I'm still at work atm)

18:48 `cbp: bitemyapp: yeah i was gonna ask you if you had any ideas regarding the connection handling

18:49 bitemyapp: `cbp: I most certainly do. I can either outline them ahead of time or provide a report/commits after I'm done experimenting.

18:49 `cbp: I want to get the test harness up, move the commented queries to their own tests, and then reproduce a race condition

18:49 then start hammering out the connection stuff based on the design I have in mind.

18:50 `cbp: the main change is simply that (run ...) will take two arguments instead of one - you'll pass the connection object directly. No implicits/globals.

18:50 `cbp: I'm writing some tests but nothing interacting with the db so far

18:50 bitemyapp: `cbp: just beware, I might have to make sweeping changes for testability and/or the conn mgmt stuff.

18:51 `cbp: that's ok

18:51 bitemyapp: `cbp: also, I'm refusing to do any client-side connection pooling. I don't think it's a good idea, I don't think it's a good idea for Revise/RethinkDB, and RethinkDB provides a conn pooling service to run on each client anyway.

18:51 I may consider a conn reconnect/retry mechanism though.

18:51 `cbp: Oh ok

18:51 bitemyapp: something with backoff -> exponential backoff or something.

18:52 or just failure after so many tries. Whatever.

18:52 `cbp: langohr has something like what I am talking about where if the connection is lost it'll attempt to bring it back up.

18:54 `cbp: rdb has different kind of queries, start, continue and so on. The start queries are working. But I'll prolly wait to see what you have in mind to implement the others

18:54 what you have in mind regarding the connections*

18:54 since that's part of the send fn

18:55 bitemyapp: `cbp: yeah, you'll want to wait until I hammer out some of that. I'm thinking of a conn object that you pass around, possibly arbitrating query results through an agent that delivers into promises returned by the API

18:56 `cbp: queries and their results are matched by the unique number associated with the protobuf message and dissoc'd out of the "on-deck" hash-map associated with the connection object

18:56 `cbp: "parallelization" insofar as that's a thing basically just means firing up more connections with can be m-n mapped through the pooling servers RethinkDB provides.

18:56 the agents aren't a guarantee, it's just an idea.

18:56 staafl: ,(map char (range (int \a) (int \d)))

18:56 clojurebot: (\a \b \c)

18:56 staafl: how do I turn this into "abc"?

18:57 bitemyapp: staafl: (apply str ...)

18:57 staafl: bitemyapp, neat, thanks

18:57 bitemyapp: `cbp: a while loop and a dedicated thread are equally as possible as an agent. NO SINGLETONS THOUGH.

18:58 staafl: any way to create an operator section with the first operator

18:58 being on the left

18:58 I mean, something like (partial > 0) is misleading

18:59 bitemyapp: I want people to be able to use arbitrary databases/connections with their queries. I hate the unnecessary global singleton crap people do.

18:59 staafl: it's (0>) but looks like (>0)

18:59 bitemyapp: staafl: that's prefix notation for you.

18:59 staafl: if you speak it out loud, it makes more sense.

18:59 `cbp: Yeah ofc

19:00 staafl: bitemyapp, you're right, but I don't want to risk confusing someone or myself

19:00 technomancy: staafl: with < and > in particular just think of it as args-in-increasing-order? and args-in-decreasing-order? respectively

19:00 because they're variadic

19:01 staafl: technomancy, I don't like thinking

19:01 technomancy: this could be a problem

19:01 bitemyapp: sritchie: without necessarily wanting to confuse Scala's actual "apply" method, is there a way to do something like Clojure's apply in Scala?

19:01 staafl: i'll just use #(> 0 %1)

19:01 technomancy: or pos?

19:01 staafl: technomancy, i mean i don't like having to think :-)

19:01 or forcing others to do it

19:01 sritchie: sort of - you can call "tupled" on a function

19:02 and it returns a version that takes one arg that's a tuple

19:02 then you can pass the return of another func in directly

19:02 makes composition easier

19:02 technomancy: staafl: it's part of learning lisp

19:02 staafl: everyone who knows clojure already reads it that way

19:04 `cbp: bitemyapp: good stuff. Let me know if you need any help understanding the smoke signals you need to send to rdb for it to accept a connection

19:04 bitemyapp: `cbp: dude, I tackled that nonsense when I first started Revise.

19:04 `cbp: I hate that.

19:04 `cbp: hopefully I don't need to bug you. Thanks :)

19:04 `cbp: bitemyapp: yeah they also changed it since last time hah

19:05 They like to make backward incompatible changes

19:05 bitemyapp: sritchie: well, tupled is fine, but can the arguments just be Object typed?

19:05 staafl: ,(filter Character/isUpperCase "aAaA")

19:05 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to find static field: isUpperCase in class java.lang.Character, compiling:(NO_SOURCE_PATH:0:0)>

19:05 staafl: some help with the syntax here

19:05 sritchie: bitemyapp: nope, not that I know of

19:05 those patterns go out the window

19:06 bitemyapp: hum.

19:06 sritchie: I will meditate on this. Thank you.

19:06 `cbp: The queries are fns so it should be very easy to add some preconditions or even typed clojure on them

19:07 staafl: ##(filter Character/isUpperCase "aAaA")

19:07 lazybot: java.lang.RuntimeException: Unable to find static field: isUpperCase in class java.lang.Character

19:07 `cbp: er ##(filter #(Character/isUpperCase %) "aAaA")

19:07 bitemyapp: `cbp: you could define a typed clojure HMap for a document coll but the database isn't going to enforce it.

19:07 lazybot: ⇒ (\A \A)

19:07 bitemyapp: `cbp: clj-schema might be a better fit. Maybe.

19:07 kinda almost want both.

19:08 staafl: `cbp, so the anon function is the only way?

19:08 `cbp: No i mean something like (table 1) will throw some obscure protocol buffer error

19:08 justin_smith: staafl: yeah, jvm methods are not first class functions, so you can't use them as first class values

19:09 staafl: that's unfortunate

19:09 `cbp: So that error doesn't get caught until it gets compiled into protocol buffers

19:09 technomancy: staafl: it really is =\

19:09 justin_smith: it's either we expect more than methods provide, or reduce what we can do with functions, right?

19:10 *what we can expect of functions

19:10 staafl: justin_smith, what do functions do that methods can't?

19:10 `cbp: So we could throw something like table expects a string, keyword or var kind of thing

19:10 justin_smith: staafl: they are objects, you can make collections of them, provide them as arguments to callable things...

19:11 staafl: justin_smith, oh, I see

19:11 I forgot the jvm doesn't have delegate types

19:12 justin_smith: which is basically what #(.method %) gets you, right?

19:13 `cbp: Although type checking the schema sounds interesting.

19:13 staafl: justin_smith, yeah. and wrapping them implicitly would have been bad for perf

19:13 it makes sense as a design decision

19:15 bitemyapp: `cbp: core.typed doesn't "enforce" anything

19:15 `cbp: it's purely voluntary. If we want table to spew on bad inputs, that's clj-schema or some-such and tossing an exception at runtime.

19:15 core.typed will only help the people using core.typed.

19:15 justin_smith: staafl: I am not sure, but I think even with implicit wrapping the discrepency would come up somewhere - and be more surprising because more rare

19:16 bitemyapp: although forcing an invocation of core.typed at macro-expansion time could be cute, I don't think that's wise.

19:17 `cbp: bitemyapp: I'm only mentioning it to have better error messages than what the protobuf compiler gives you when you call a query with incorrect arguments. Not so much to enforce a schema

19:17 bitemyapp: `cbp: I know, but you can use clj-schema for basic runtime type checking.

19:18 simplest thing to do is (when-not (string? table-name) (throw (Exception. "fuck you man, table names are strings")))

19:20 `cbp: bitemyapp: Well I'll be writing some tests and some docs hopefully we can release a 0.1.0 this weekend eh?

19:21 bitemyapp: thanks for your help :)

19:22 justin_smith: ,(assert (string? \f) "fuck you")

19:22 clojurebot: #<AssertionError java.lang.AssertionError: Assert failed: fuck you\n(string? \f)>

19:22 justin_smith: maybe easier?

19:24 bordatoue: could anyone tell me how overloading is handled in clojure, for example if I want to call indexOf(char ), how would i do it in clojure (.indexOf "ABCD" \A) seems to refers to indexOf(String)

19:25 hlship: So I noticed that type hints on method parameters for protocols

19:25 do not trickle down to the extend

19:26 justin_smith: bordatoue: what would the working java implementation look like?

19:26 hlship: (defprotocol Writer

19:26 "May receive strings, which printed, or stored."

19:26 (write [this s] "Writes the string to the Writer."))

19:26 (extend-protocol Writer

19:26 ;; Appendable is implemented by StringBuilder and PrintWriter.

19:26 Appendable

19:26 (write [this ^CharSequence s] (.append this s)))


19:26 noonian: bordatoue: overloading by number of arguments is the only way to do it with basic functions, if you want to dispatch on type then you need to use protocols

19:26 hlship: I'd rather have the ^CharSequence type hint up in the defprotocol

19:27 bordatoue: so how would you call IndexOf(char) in clojure ?

19:27 hlship: but that generated reflection warnings inside the extend-protocol

19:27 bordatoue: using java interop

19:27 `cbp: bordatoue: can you provide a java example? It's pretty much the same thing in clojure

19:28 noonian: bordatoue: (.indexOf "foobar" \b)

19:28 ,(.indexOf "foobar" \b)

19:28 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: No matching method found: indexOf for class java.lang.String>

19:28 noonian: hmm

19:29 justin_smith: noonian: I tried that too, that's why I was asking what the working java invocation looked like

19:29 `cbp: bordatoue: im looking here http://docs.oracle.com/javase/7/docs/api/java/lang/String.html and theres no indexOf(char ..)

19:29 dnolen: hlship: not possible, I doubt something like that would be

19:30 bitemyapp: `cbp: yep, I'd like that.

19:30 justin_smith: ,(.indexOf "ABCD" (int \A))

19:30 clojurebot: 0

19:30 bitemyapp: A release this weekend would be glorious.

19:30 bordatoue: I am just trying to figure how clojure would decide which method to call if it is overloaded with different parameter type

19:30 justin_smith: notice the docs say int!

19:30 hlship: really, not possible? Seems like you could capture the type hint meta data from the method decl in the defrecord, and "apply" it inside the extend. The trick would be to handle conflict.

19:30 justin_smith: ,(.indexOf "ABCD" (int \C))

19:30 clojurebot: 2

19:30 noonian: ah

19:30 must cast it to an int

19:30 justin_smith: bordatoue: answer above, cast to int

19:30 hlship: e.g., what happens if the extend changes its mind and applies its own type hint.

19:30 bordatoue: justin_smith: ok, thanks .. is it because char are actually int

19:30 bitemyapp: justin_smith: even better.

19:30 justin_smith: javadoc clearly shows the arg is an int

19:30 hlship: but that could be resolved by having the local type hint merge with the protocol-supplied type hint

19:30 bitemyapp: I should make a macro for "fuck you" assertions.

19:31 hlship: anyway, why do you think it is impossible, rather than not implemented?

19:31 BTW, have you been in Portland, OR lately? 'cause I saw your dopplerganger recently.

19:32 * justin_smith is in PDX too...

19:32 noonian: me too...

19:32 justin_smith: SMALL WORLD

19:32 noonian: lol

19:32 `cbp: bitemyapp: also let me know if you think the responses are parsed acceptably. Dunno if you've tried that stuff yet

19:32 justin_smith: hlship: oh, now I realize who you are

19:32 hlship: is that a good thing or a bad thing?

19:33 dnolen: hlship: what I mean is that seems to go against the grain, specifying a type hint at the protocol level.

19:33 hlship: I do make it difficult with my bizarre handle, "hlship"

19:33 dnolen: hlship: type hints are only about performance

19:33 bordatoue: does typing \A resove to an int in clojurexb

19:33 justin_smith: hlship: we hung out after the last pjug :)

19:33 noonian: ,(type \A)

19:33 clojurebot: java.lang.Character

19:33 hlship: dnolen: to me, it means that each implementation of the protocol may duplicate the type hint.

19:34 bitemyapp: `cbp: not yet, been hammocking the connection stuff.

19:34 I'll surely let you know when I expand the test cases.

19:34 bordatoue: so in java 'A' is resolved to int, while in clojure it is not resolved to int

19:34 dnolen: hlship: protocols aren't primarily a interop feature, type-hinting is all about interop, and in a pretty gross way

19:34 `cbp: bitemyapp: okies well ill stop bothering you now

19:34 dnolen: avoiding reflection

19:35 hlship: ah, so it's about priorities.

19:35 I see avoiding reflection as a high priority, especially in code to be reused.

19:35 bitemyapp: `cbp: it's no problem at all. I'll be able to start poking things tonight (FRIDAY FRIDAY FRIDAY FRIDAY FRIDAY) :)

19:35 `cbp: for now, back to tuning the JVM.

19:35 noonian: bordatoue: i think it's because \H in clojure is a java Character, not a primitive java char

19:35 dnolen: hlship: but it's a host-y thing. avoiding reflection is completely irrelevant for ClojureScript for example.

19:36 hlship: You see that in Tapestry, where I've gone to some herculean efforts to avoid runtime reflection with tons of bytecode generation (at runtime)

19:36 dnolen: hlship: in anycase, I don't see this idea going anywhere.

19:36 hlship: I like runtime bytecode when you know what all the types are ...

19:36 yep, I'll let it go

19:36 but I do tend to define protocols as much as for "taming" interop as for anything else

19:38 justin_smith: Yep, I just barely made my bus that night. I'm trying to make it back out for some Clojure, Java, Functional users groups, but its been hard. Everyone at home has this nasty cold, and our nanny broke her ankle and caught the flu.

19:38 When I see people doing amazing things in code lately, my first reaction is "that person has no kids"

19:38 justin_smith: you mentioned

19:38 bitemyapp: hlship: do you want counter examples, or do you need to believe that?

19:38 noonian: hlship: lol

19:39 hlship: Just let me believe it.

19:40 bitemyapp: hlship: okay. I'm here if you ever decide being inspired to greater things is more valuable than embracing pillow-topped failure.

19:40 hlship: My 3.5 yo demands a lot of attention, and my 9 month-old has a burning need to be held while awake and often while asleep

19:40 bitemyapp: hlship: do you swaddle the 9 m/o?

19:40 especially for sleep?

19:40 hlship: she's actually a great sleeper

19:41 we swaddled when she was younger

19:41 now she gets out of them, even the velcro ones, just like big brother

19:41 noonian: i'm thankful i don't even know what 'swaddling' means :p

19:42 bitemyapp: noonian: you should be wondering why a 25 year old single young man knows.

19:43 wink: I never heard that word either

19:44 bitemyapp: noonian: wink: http://en.wikipedia.org/wiki/Swaddling boom, knowledge bomb.

19:44 Works great on kids that really want to be held.

19:44 wink: yeah, I looked it up already

19:44 noonian: noooo!

19:44 bitemyapp: noonian: don't be such a baby :)

19:44 noonian: now I know what it means as a 24 year old single young man... :(

19:44 xuser:

19:47 `cbp: :-O I thought bitemyapp was older

19:48 benkay: here's to having kids while you still have the energy to chase 'em

19:48 bitemyapp: `cbp: I started working at 18, dropout. Started coding before that.

19:51 benkay: (another thing to keep in mind about kids is that the fraction of your income they demand is likely constant no matter when you have 'em, and seeing as the integral of their cost is going to be a function of your income...

19:51 ...sooner will be cheaper)

19:52 hlship: Oops. Missed that memo. Had first kid at 46.

19:52 rasmusto: having derivatives is an integral part of a healthy life

19:52 hlship: No wait, I was 44.

19:52 bitemyapp: Area under the curve of the cost of kids.

19:52 hlship: Still, late start.

19:52 bitemyapp: benkay: couldn't you just like, raise them as if they were living in a third world country?

19:53 then the percentage drops.

19:53 znDuff: Hmm.

19:53 benkay: even kids get on the hedonic treadmill, bitemyapp.

19:53 hlship: True, but your income tends to increase over time and your ability to (for example) control your emotions in the face of unreasoning 3 year old tantrums and contents of wills is quite valuable.

19:53 benkay: keeping up with itty-bitty joneses.

19:53 bitemyapp: benkay: yeah but the paycheck isn't theirs to spend.

19:53 * znDuff has a vasectomy scheduled on the theory that having teenagers while in 50s isn't likely to be highly manageable.

19:54 benkay: there are two camps of parenting: a - that having kids makes adults, and b - that only adults should make kids

19:54 bitemyapp: I'm not in either camp.

19:54 hlship: Probably early 30's is better than 40's, but I wouldn't want to do this in 20's. I know I wasn't adult enough then. Not now, either, but I can fake it better.

19:54 benkay: (obviously it's a spectrum)

19:55 noonian: either way, if you never want to grow up - don't have kids

19:56 bitemyapp: what if you want to spread your genetic material but don't find kids interesting in their own right?

19:56 become a conquering barbarian?

19:56 * znDuff is actually on the other end -- interested in spreading memetics

19:56 benkay: introduce yourself to the pickup community?

19:57 bitemyapp: Ick.

19:57 znDuff: (currently starting with a new tutoring student)

19:57 bitemyapp: benkay: I mean more in the sense of absentee parenting.

19:57 znDuff: I've always found tutoring very rewarding.

19:58 znDuff: bitemyapp: *nod*. Last time I was seriously devoted to it, though, I had a job I hated. Harder to balance today.

19:59 benkay: bitemyapp: should be easy. find someone who wants to raise your spawn for you

19:59 bitemyapp: benkay: a stay at home parent?

19:59 benkay: but i gotta wonder why even bother

19:59 why expend the resources if you don't care about kids in the first place?

20:00 bitemyapp: benkay: what could possibly be more hilarious than creating a bunch of people that are half-me?

20:00 I could bring about the apocalypse if I made enough of them.

20:00 benkay: i guess if that's your preferred capex model go for it

20:01 if i were just burning dollars for the sake of it i'd spend it on elaborate masquerade balls

20:01 or trolling silicon valley

20:01 i do have visions of teaching mine javascript and css at a young age

20:02 tdd etc

20:02 offering them the staggering sum of 20/hr to work for me

20:02 hlship: Are protocol methods and rest arguments not compatible?

20:05 noonian: hlship: i don't think so, googling shows threads from 2011 about it not being supported so probably not unless there's been a change

20:06 bitemyapp: benkay: there is that too.

20:07 benkay: bitemyapp: i mean, whatever happened to the grand tradition of training one's offspring in the fine arts of one's business?

20:07 ones'

20:07 noonian: i'm pretty sure logic and programming will be part of the core curriculum by the time any of my future offspring would be old enough to start school

20:08 znDuff: noonian: doesn't mean it's going to be taught properly.

20:08 noonian: znDuff: thats true

20:08 bitemyapp: noonian: yeah I don't trust those people. I'd rather raise my own FP uber-henchpeople.

20:09 then I'll name them all Alexandra and Alexander so I can never get their names wrong.

20:09 noonian: lol

20:10 if i had 2 kids iraise each of them totally differently

20:10 bitemyapp: it is galling how many times I make a minor change to an upstart init config and I end up facepalming at my own stupidity.

20:11 Can I get type-checked init configs?

20:11 yeesh.

20:11 technomancy: uuuuugh upstart

20:11 bitemyapp: I mean, I've got some fairly stable configs that are in version control, but god help me if I need to do something slightly different.

20:11 technomancy: remind me why these people feel the need to make their own daemons for everything?

20:12 technomancy: I dont even

20:12 * znDuff shrugs -- will take upstart over SysV init any day.

20:12 znDuff: ...hell, will take *anything* over SysV init

20:12 * znDuff waits oh-so-anxiously for systemd to rule the world

20:13 technomancy: systemd terrifies me

20:13 bitemyapp: znDuff: I didn't like sys v either, I used to flirt with BSD for that reason.

20:13 lando23: hi there guys. i'm new to clojure and trying to solve a little synthetic problem. i'm a bit stuck was wondering if i could ask some questions.

20:13 bitemyapp: technomancy: I don't know a lot about it - what terrifies you about it?

20:14 technomancy: bitemyapp: binary logging format? from the mind that brought you pulseaudio and is out to prove how smart he is? what could go wrong

20:14 noonian: lando23: go for it

20:14 bitemyapp: technomancy: oh GOD

20:14 both of those reasons are horrifying.

20:15 lando23: the problem is that i have a list that looks like [2 10 10 1 2 3] with the interpretation that the first number denotes the number of players N, the next N numbers are the players score, and the numbers after that are score changes to each player in turn.

20:15 technomancy: the problem is he actually *is* really clever

20:15 bitemyapp: somehow I'm not surprised systemd is popular in Arch-land.

20:15 technomancy: so he sorta gets away with it

20:15 bitemyapp: Those people always seemed kinda impractical.

20:15 technomancy: yeah, there is a definite neophilia in arch-land

20:16 fedora people should know better though

20:16 lando23: i've started with lein repl and (def input [2 10 10 1 2 3])

20:16 averell: at least pulseaudio is not the default there...

20:16 lando23: next i defined a function to get the number of players: (defn numPlayers [input] (take 1 input))

20:17 next i defined a function to get the initial scores: (defn scores [input] (take (numPlayers input) (rest input)))

20:17 technomancy: averell: well it took like four years, but pulse is actually very stable now.

20:18 lando23: at this point i'm totally stuck. it feels like a reduction problem.

20:18 technomancy: but I don't have to write pulseaudio scripts to launch music programs, so all that complexity isn't as problematic as it is with systemd

20:18 bitemyapp: technomancy: does Heroku use Ubuntu on AWS?

20:18 technomancy: bitemyapp: yeah, with chef =\

20:18 bitemyapp: lolchef.

20:18 technomancy: for things that can't be self-hosted

20:19 znDuff: technomancy: *shrug*. With my ops hat on, a lot of the functionality there is hugely sensible and long-overdue -- particularly the launch-on-demand containers and such.

20:19 noonian: lando23: if i were you i would make my scores function take a map instead of a vector so you don't have to keep track of all that by convention

20:19 bitemyapp: technomancy: at least Ubuntu insulates you from the craziness of Arch.

20:19 lando23: noonian: thanks, any pointers appreciated. I'm a professional programmer learning clojure in my free time.

20:19 technomancy: bitemyapp: people don't use arch when money is on the line

20:19 noonian: {:num-players 4, :scores [1 0 4 9], ...}

20:19 bitemyapp: technomancy: I've said as much to Arch users before and they got really cranky.

20:19 if I can't get my laptop's wireless to work on Arch, why would I deploy a server on it??

20:19 lazybot: bitemyapp: Uh, no. Why would you even ask?

20:20 bitemyapp: sigh.

20:20 noonian: or {:players [{:score 4, ...}]}

20:20 technomancy: bitemyapp: job security

20:20 znDuff: technomancy: once, in my younger/more foolish days, I was part of an organization that ran Gentoo in production.

20:20 technomancy: Including Oracle on Gentoo.

20:20 technomancy: whoa

20:20 znDuff: ...including support for RAC clusters.

20:20 lando23: i'm trying to assume that my input is constrained to a vector - and perhaps produce that map

20:21 i can use destructuring for num-players but the rest is tricky

20:21 znDuff: technomancy: ...Oracle's support contracts, incidentally, _do_ continue to operate even on platforms they don't support -- they just try as hard as they can to demonstrate things to be the platform's fault.

20:21 noonian: if you really want to take a flat vector as args, i'd make a seperate function that just converts that to the map

20:22 technomancy: znDuff: as if using oracle on a supported platform wasn't bad enough

20:22 lando23: noonian: okay, but then how do i iterate over the inputs and modify the starting score?

20:22 bitemyapp: znDuff: that's insane.

20:23 noonian: (let [[num-players & rest-args] args, scores (take num-players rest-args), other-args (drop num-players rest-args)] ...)

20:23 lando23: you shoulnd't have to modify anything if you're making your game functionallty

20:23 znDuff: technomancy: Indeed. One of our major investors insisted.

20:23 (on Oracle, that is)

20:23 lando23: when i say 'modify' i mean 'produce a new value' :)

20:24 noonian: if you really want to modify stuff and treat your games world as a mutable structure then i would suggest sticking the whole thing into an atom and use swap! to update it

20:24 ah

20:24 znDuff: ...why in the world they'd insist on software costs dwarfing our hardware costs I still don't understand, but... eh.

20:24 lando23: no i really want to learn immutable functional programming

20:24 noonian: thats why a map would be way easier

20:24 assoc is meant for that

20:25 technomancy: lando23: (let [[n & r] input] scores (take n r) changes (drop n r)] ....)

20:26 there's probably a way to destructure take and drop together in one line

20:26 noonian: lando23: why do you want the input to be constrained to be a vector?

20:26 lando23: thanks. but i'm still not sure how to model the central problem of iterating over the score changes and create new scores that reflect the changes

20:26 technomancy: lando23: if you're constrained in your input you shouldn't let that constrain your internal representation

20:26 lando23: i was thinking of adding string parsing and command line support later on. also, it's the simplest possible representation.

20:27 noonian: lando23: you're game will probably be a recursive function, and each time it make the recursive call you would pass in a slightly different vector or map as the input

20:27 lando23: also, those variables could be entirely seperate parameters which would probably make the code simler

20:27 simpler*

20:30 if you just took a vector maps as the input where each map represents a player i think it would be much easier to reason about, num-players is just (count players)

20:31 lando23: vector maps?

20:32 this gets to the thing that's hurting me i think: my fingers ache to define types for the players, but how do you define data structures in clojure? is it all just maps and vectors?

20:33 technomancy: clean code is all just maps and vectors, yes

20:33 fast code sometimes is more

20:33 noonian: lando23: for the most part, you could write a function called 'player' for instance, that takes an initial score or w/e and returns a map of {:score score, ...}

20:34 lando23: conceptually I see it as some sort of reduce function that initializes on the first N+1 elements, and then proceeds to produce a new game state for each score change.

20:34 noonian: what do you mean initializes?

20:35 lando23: the game has a variable number of players with variable starting scores

20:35 noonian: i would just take a vector of players as an argument, or a map with a :players key

20:36 then just write an initialize fn that takes the values from your ui, or serialized state, or however initial values are determinied, and creates that vector or players and then pass that result to your game when you start it

20:36 lando23: perhaps i need a higher order function that initializes a game function

20:41 noonian: here's an example that just increments every players score each round, it would never terminate so your game logic should do more than this like printing to the screen and updating the state based on user input or w/e: https://www.refheap.com/20175

20:42 excuse the poor indentation, tabbing is different on refheap than what i'm used to

20:44 players would be something like [{:name "player0", :score 3}, {:name "player1", :score 17}]

20:44 lando23: thanks noonian. a) didn't know about ref heap, b) didn't know about update-in, c) thanks

20:44 noonian: yeah, no problem

20:45 instead of update-in in that example you could also do (assoc player :score (inc (:score player)))

20:46 update-in gets really nice when you need to update maps within maps

20:49 lando23: is there a difference between ref heap and gist?

20:49 noonian: refheap is written in clojure :p

20:49 Raynes: Every single thing is different about them.

20:49 They're written by different people in different languages with different designs at different domains...

20:50 Refheap is to gist as oranges are to apples.

20:50 noonian: ^ wrote refheap

20:50 Raynes: Yeah, I'm a pretty big fan of oranges.

20:50 lando23: :)

20:53 so noonian your code doesn't quite capture my intent. it looks like your code will only increment a score by one - i would like to increment a score by a variable amount. also, i notice that you define 2 functions but never invoke them.

20:53 it's not clear to me where the scoring input would go

20:55 i think the function i want is one that advances state - perhaps with two numbers, a player index and a core - and then returns a new state

20:55 then the problem devolves into successive application of that function - in a reduce

20:55 score, not core

20:57 something like (update-in (players active-player-index) [:score] (+ score))

20:57 where active-player-index and score are the parms

20:59 noonian: 1 sec, working on a more in-depth example

20:59 lando23: (defn game [players]

21:00 (if (empty? players)

21:00 true ; exit game

21:00 (let [players-with-new-state (game-logic players)]

21:00 (recur players-with-new-state))))

21:00 that recur will loop back to 'game' right?

21:01 noonian: yes

21:01 lando23: also i'm sensing that dashes are used instead of camel case in clojure :

21:02 noonian: here's a more complete example that is meant to terminate, but is still untested: https://www.refheap.com/20177

21:02 yes, thats true

21:03 you can give any number of arguments to your "modify" function in update-in

21:04 Foxboron: "Clojure isnt a real LISP!" "Why?" "It dosn't got a real debugger!" *sighs*

21:04 noonian: also, i forgot to implement amount-to-increase-score heh

21:09 lando23: doseq! aha

21:10 can you explain the indentation convention? i'm a little confused about what governs that

21:10 and what is ->

21:13 noonian: -> is awesome

21:14 the indentation is messed up on those refheaps, heres a pretty good style guide for Clojure: https://github.com/bbatsov/clojure-style-guide

21:15 ,(doc ->)

21:15 clojurebot: "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

21:16 noonian: not a great doc string, but it feeds the value of the initial expression as the first argument to the next expression recursively

21:20 lando23: Raynes: ref heap is using hard tabs, contradicting the style guide. FYI

21:22 technomancy: ~guards

21:22 clojurebot: SEIZE HIM!

21:23 lando23: noonian: thanks

21:24 noonian: lando23: oops, because i used the threading macro '->' i shouldn't have left player there as the first argument to update-in since the threading macro would be putting that there for me

21:24 welcome

21:25 lando23: i always like to use things in the "simplest way that will work", and came up with this: (+ 1 2 (-> 3)) much to my surprise, it evaluated to 6, what I expected! yay

21:25 * seangrove squints

21:25 noonian: heh, you don't need (-> 3) there

21:26 (-> 3) gets re-written by the macro to be 3

21:26 lando23: ho

21:26 oh

21:26 noonian: + takes any number of args

21:26 seangrove: (-> (+ 3 4) (* 7) -)

21:26 lando23: so what is the simplest use of ->

21:26 seangrove: ,(-> (+ 3 4) (* 7) -)

21:26 clojurebot: -49

21:27 lando23: ,(-> (+ 2 4) (* 7) -)

21:27 clojurebot: -42

21:27 noonian: (-> {} (assoc :foo 5) (assoc :bar "bar"))

21:27 ,(-> {} (assoc :foo 5) (assoc :bar "bar"))

21:27 clojurebot: {:bar "bar", :foo 5}

21:27 lando23: i like that example

21:27 noonian: although you can do it all in 1 assoc

21:27 lando23: it reads like "successive application"

21:27 noonian: you mainly need it when you are nesting a bunch of forms

21:28 it will clean that up and take up less horizontal space

21:28 lando23: wait i have to try and hack the clojurebot

21:28 ,(quit)

21:28 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: quit in this context, compiling:(NO_SOURCE_PATH:0:0)>

21:28 lando23: oh well :

21:28 ,(doc ->)

21:28 clojurebot: "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc."

21:29 lando23: ,(assoc {} :a 2)

21:29 clojurebot: {:a 2}

21:29 noonian: ,(-> 5 inc (* 4 (+ 2 7)))

21:29 clojurebot: 216

21:29 noonian: ,(-> 5 inc (* 4) (+ 2 7))

21:29 clojurebot: 33

21:30 lando23: ,(5 inc)

21:30 clojurebot: #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn>

21:30 noonian: it turns inc into (inc)

21:30 lando23: so the arrow kind of switches the function and it's argument

21:30 noonian: that last expression is the same as (+ (* (inc 5) 4) 2 7)

21:31 ,(+ (* (inc 5) 4) 2 7)

21:31 clojurebot: 33

21:31 lando23: ,(-> 5 inc 2

21:31 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

21:31 lando23: (-> 5 inc 2)

21:31 nightfly: ,(-> 5 (inc 2))

21:31 clojurebot: #<CompilerException clojure.lang.ArityException: Wrong number of args (2) passed to: core$inc, compiling:(NO_SOURCE_PATH:0:0)>

21:31 noonian: that will turn into (2 6)

21:31 nightfly: ,(-> 5 (inc))

21:31 clojurebot: 6

21:31 nightfly: ,(-> 5 inc)

21:31 clojurebot: 6

21:31 nightfly: ,(-> 5 inc inc inc inc inc inc inc inc)

21:31 clojurebot: 13

21:32 gfredericks: ,(reduce #(%2 %1) 1 (repeat 1000000 inc))

21:32 clojurebot: 1000001

21:32 lando23: ,(inc (inc(inc(inc 5))))

21:32 clojurebot: 9

21:32 gfredericks: I have a hard time imagining that I just made clojurebot do a million things

21:32 nightfly: ,(reduce #(%2 %1) 1 (repeat 1000000000 inc))

21:32 gfredericks: and also clojurebot is probably thousands of miles away from me

21:32 technomancy: , (macroexpand-1 '(-> 1 inc inc)) ; macroexpand is your friend

21:32 clojurebot: (clojure.core/-> (clojure.core/-> 1 inc) inc)

21:32 Execution Timed Out

21:33 lando23: ,(doall(print "what the heck is this anyway?") (reduce #(%2 %1)))

21:33 clojurebot: what the heck is this anyway?#<ArityException clojure.lang.ArityException: Wrong number of args (1) passed to: core$reduce>

21:33 gfredericks: technomancy: macroexpand is your acquaintance; a friend would make the code look a bit saner

21:34 lando23: thanks for the help noonian. i'll no doubt be around again.

21:34 noonian: lando23: #(+ % 10) is syntactic sugar for (fn [x] (+ x 10)), its reader syntax for an anonymous function

21:34 lando23: clojure is just so....strange

21:34 noonian: lol

21:34 for sure, take care

21:34 lando23: so the percent sign is a placeholder

21:35 noonian: yeah

21:35 i think you can do %1 and %2 also but i hardly ever use that syntax

21:35 gfredericks: you can

21:35 and %&

21:35 lando23: #() is easily confused with #{} :/

21:35 gfredericks: lando23: # signals some sort of special syntax

21:35 it's used in a variety of ways

21:35 lando23: doesn't it denote a hashmap?

21:35 gfredericks: with curly braces, yes

21:36 noonian: #{1 3 4} is a literal for a set

21:36 (set 1 2 3)

21:36 gfredericks: oh right of course

21:36 * gfredericks is ragingly drunk

21:36 noonian: er, (set [1 2 3])

21:36 lando23: ha. well enjoy. cya

21:39 iguano: http://www.theweeklypay.com/index.php?share=19844/

21:40 mtp: i prefer not to

22:10 bitemyapp: sritchie: can you make your own data type literals in Scala? I know of the prebaked ones. How flexible is it?

22:13 sritchie: more saliently, can I make stuff that looks like reader macros?

22:16 sritchie: bitemyapp: for the first one, do you mean algebraic data types?

22:18 bitemyapp: Scala 2.10 does have this, I think

22:18 check out the string interpolation macro stuff:

22:18 http://stackoverflow.com/questions/15329027/string-interpolation-and-macro-how-to-get-the-stringcontext-and-expression-loca

22:18 ticking: \n

22:20 bitemyapp: muh-lud macros in Scala are scurry.

22:20 justin_smith: clojure reader macros and string interpolation macros look like totally different things

22:23 bitemyapp: sritchie: can I embed a Scala REPL that I can connect to into a running Scala service?

22:27 Seeing some stuff like: http://stackoverflow.com/questions/12630018/scala-initialize-repl-environment - but nothing like nrepl so far.

22:28 sritchie: bitemyapp: I don't think that's possible as of now

22:28 nor do I know how to do it -

22:29 since the repl is maintaining an environment of type information as well as evaluated code, so it gets pretty confusing

22:29 bitemyapp: sritchie: yeah I found the interpret + type information stuff hella confusing.

22:30 sritchie: the forms are just nesting deeper and deeper

22:30 bitemyapp: sritchie: would a resident compiler with runtime bytecode execution lead to something easier to understand?

22:31 sritchie: oh man, who knows...

22:31 at that point, I just fire up a clojure repl

22:33 bitemyapp: sritchie: the point isn't the REPL, the point is that I'm used to being able to plunge my hands into the guts of my applications ala Clojure embedded nREPL, Common Lisp, and Erlang.

22:33 sritchie: yes, of course

22:33 bitemyapp: I don't regard logging as being "good enough", even if I do it anyway.

22:33 sritchie: I've just let those desires die as I work more with Scala

22:34 bitemyapp: hum. Guess I'll just have to hope people adopt core.typed.

22:34 sritchie: that's my plan, anyway

22:35 bitemyapp: sritchie: you're hoping to use more Clojure?

22:35 sritchie: bitemyapp: yes, I'll be releasing Cascalog 2.0 this weekend, then spending more time in that codebase -

22:35 I'm shifting my work life around to have more Clojure time

22:35 bitemyapp: oh that's exciting.

22:35 sritchie: more info on that next week

22:35 yeah! definitely exciting

22:35 bitemyapp: I look forward to it :)

22:35 sritchie: hence this clojurescript exploration today

22:36 core.async is awesome

22:36 (two separate new awesome tools for me)

22:37 bitemyapp: sritchie: ambrose started on core.typed for CLJS

22:37 core.typed for core.async with typed channels could be cool. (don't need to wait on CLJS for that)

22:39 sritchie: or a Cascalog core.async planner implementation that takes channels as sources and returns a new channel that "solves" for its inptuts

22:39 inputs*

22:39 bitemyapp: Dreamy.

22:39 There are some cascalog features I want in Datalog.

22:39 sritchie: oh yeah?

22:39 not the other way around?

22:39 looking for a good cljs repl experience, now...

22:39 bitemyapp: Datalog in Datomic is pretty spare right now.

22:40 sritchie: ah, yeah

22:40 bitemyapp: Cascalog is more featureful and completely developed.

22:41 sritchie: probably time to look more at datomic

22:41 bitemyapp: Datomic's lack of certain features has made some query patterns awkward/painful for my coworkers.

22:41 er, Datalog in Datomic

22:42 justin_smith: bitemyapp: does that mean cascalog would be a better choice, or is there some other consideration like performance?

22:43 bitemyapp: justin_smith: I don't think Cascalog would know how to use the indexes.

22:43 justin_smith: I mean for me, not using either yet?

22:43 bitemyapp: they're two very different things.

22:43 Datalog is a generic unification-based query language. It's somewhat...spare if you don't tack stuff on it.

22:44 sritchie: justin_smith: Cascalog is for writing Hadoop

22:44 for now

22:44 bitemyapp: Datomic is OLTP, Cascalog is OLAP on Hadoop.

22:44 two totally different workloads, but a lot of the needed query semantics overlap.

22:44 justin_smith: ok, shows how much I know, thanks

22:44 bitemyapp: Cascalog is how I stayed sane when I managed a Hadoop herd.

22:44 sritchie: justin_smith: haha, no totally reasonable question

22:45 justin_smith: especially since Cascalog COULD have a local-only implementation,

22:45 and probably will soon

22:46 bitemyapp: but even if it did, and it worked on the same nested vector format Datalog expects, I'm pretty sure Datalog uses special knowledge of the database indexes in Datomic.

22:46 justin_smith: my use case is a system that used to be a php orm, then moved to a rails based one, and now is translated to clojure - and I would like something more sane than orm that still allows integrating a cms to display of web pages

22:47 already we are not doing full fledged oo orm, but the old design still shows through in places - I was thinking some datalog implementation would help with some of our problems

22:47 bitemyapp: justin_smith: you can use straight-up datalog for that (bacwn)

22:48 I've been considering writing a library for Datalog->SQL && SQL->Datalog

22:48 justin_smith: cool

22:49 so what is the storage backend with bacwn?

22:51 bitemyapp: justin_smith: <INSERT YOUR CODE HERE>

22:51 justin_smith: ahh, ok

22:51 so it just does the in-memory representation and querying, no serialization?

22:52 bitemyapp: justin_smith: https://github.com/tailrecursion/bacwn/blob/master/src/clojure/fogus/datalog/bacwn/impl/database.clj

22:52 justin_smith: hah, I have that file open right now

22:52 bitemyapp: presently, yes, but you can just make it an interface to anything you want.

22:52 justin_smith: I was just wondering if there was a hidden storage layer I was too daft to see

22:52 bitemyapp: which is why I'm considering the datalog <> SQL thingy.

22:52 datalog tends to be abstracted from storage.

22:52 justin_smith: right, it's coming together

22:53 ok, my deploy is finally working, I'm headed home

22:53 see y'all around

22:53 bitemyapp: justin_smith: cheers.

23:24 iguano: http://www.theweeklypay.com/index.php?share=19844/

23:26 yedi: http://z.caudate.me/learning-angular-js-through-macros/

23:26 what do you guys think about purnam?

23:42 jared314: yedi: I wish he had samples on the purnam read me comparing normal clojurescript js interop syntax with his lib

23:42 yedi: nm, I just needed to scroll more

Logging service provided by n01se.net