#clojure log - Sep 05 2013

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

0:06 xeqi: ddellacosta: I'm surprised how little value is placed on a test suite as regression prevention and code explination

0:07 ddellacosta: xeqi: yeah, the big thing I felt was missing from that article was a coherent appraisal of the value of regression tests--which imho is the *biggest* win when doing testing.

0:07 xeqi: and insofar as TDD contributes to that, I feel like it is also a big win. But I recognize that it is not always the right way to approach development

0:07 clojurebot: Ok.

0:10 ddellacosta: hear what I'm saying clojurebot?

0:12 dnolen: ddellacosta: figuring out what to test is hard

0:14 ddellacosta: dnolen: one thing I really struggle with in Clojure (functional?) -land is understanding how to really distinguish between what may be considered an "integration test" vs. a "unit test." Often times I find myself creating fixtures to write a reasonable "unit" test, and it seems like I'm blurring the lines between the two. Maybe these labels don't apply, and I'm stuck in the old testing modality.

0:15 anyways, I'm really interested to hear more of how people have approached this in their real-world Clojure projects.

0:15 obviously a lot of folks are doing testing, in any case.

0:15 sdegutis: ddellacosta: that's not unique to FP, most people I know can't tell the difference.

0:16 Even in Ruby land.

0:16 Myself included.

0:16 ddellacosta: sdegutis: true. It took me a while before I really started to "feel" the difference, although I may be deluding myself--maybe the issue is that I still don't get it!

0:16 sdegutis: yeah, haha

0:17 sdegutis: I stopped worrying about unit tests and now I only focus on highest-domain-level integration tests.

0:17 dobry-den: all of my clojure projects are toy projects and i like inlining core.assert into source

0:17 gws: i like to test things that could conceivably go in a spec for the project

0:17 sdegutis: I only do unit tests when I'm not sure something will work. And I only use integration tests to prevent regressions.

0:17 gws: not every little mechanical unit of code needs to have a test

0:17 sdegutis: (inc gws)

0:17 lazybot: ⇒ 1

0:18 sdegutis: I used to test way too much, and my tests were bad, very possibly causing more damage than having no tests.

0:19 gws: yeah, and causing extra overhead each time you refactored some unit...

0:19 been there :(

0:19 sdegutis: I guess we've both learned the hard way. But maybe there's no other way to learn.

0:19 xeqi: I find the most value at the feature test level

0:20 gws: ddellacosta: i think you're seeing a pattern :)

0:20 sdegutis: xeqi: yeah that's what I called "domain level".

0:20 ddellacosta: gws: yah, maybe so!

0:21 sdegutis: Basically I write a test for (add-to-cart user item) with an assertion that (items-in-cart user) contains item, and I don't worry about anything it calls internally.

0:21 xeqi: though I wrote/ported two libraries to let you test ring apps that way, so I might be biased there

0:21 sdegutis: Even the definition of "user" and "item" are domain-driven and not implementation-driven, so that I can swap out the database at any given time.

0:21 (For example moving away from MongoDB to Datomic.)

0:22 ddellacosta: I've had all kinds of experiences testing though. Recently I built a bit of functionality which entailed determining how different clients could access a resource stored in a data structure, basically a tiny little data access protocol I suppose. I wrote it using a TDD approach, and the code turned out quite nice, and the tests I got out of it showed me some other errors I had introduced in the implementation, which were easy to

0:22 resolve and fix (I believe) because of the way I had approached it.

0:22 but I've also had a lot of experiences like sdegutis where I test too much, my tests become brittle and hard to maintain

0:23 xeqi: unit tests are best for single functions that you can control with arguments, and even then if there was a way to do property testing for the function it might be better

0:23 sdegutis: And I've been moving away from writing tests that go through the HTTP "controller". I figure, even if I write those tests, I have to manually test it in my browser at every change anyway, so why do double work?

0:24 ddellacosta: sdegutis: yeah, that's one area (routing/"controllers") in particular where I've started to feel like I am building "integration" tests rather than "unit" tests.

0:25 but yeah, with what xeqi and sdegutis are saying, I'm definitely seeing some trends.

0:25 sdegutis: ddellacosta: we have an entire suite built up of these, and they make it impossible to add/remove/change features because they're so over-complicated.

0:25 On one hand those tests are testing *both* feature-level and HTTP-level logic, which violates single-responsibility principle.

0:25 ddellacosta: interesting.

0:25 are you talking specifically about Clojure, or some other platform?

0:25 sdegutis: Also, they make it really easy to move feature-level code *into* HTTP-level code.

0:26 Yes, this is for work, which is a Clojure app.

0:26 I'll tell you guys what it is after I push the redesign, since I'm not proud of the site as it looks right now.

0:26 ddellacosta: okay, interested to hear

0:26 xeqi: sdegutis: are you using a lib for your "controller" tests?

0:27 sdegutis: Not that the website looks bad, it fit in just fine a few years ago.

0:28 xeqi: Yep, we're using joodo and speclj, because my colleague wrote them, and he wrote the site, and he extracted them out of the site.

0:29 We're gradually moving away from most joodo features now that the rest of the Clojure-web-ecosystem has matured (he wrote Joodo back when Ring was barely a baby).

0:30 xeqi: joodo and speclj are tightly integrated, and joodo has "with-mock-rendering" and "with-routes".. http://joodoweb.com/tutorial/controllers

0:32 ddellacosta: huh, interesting. Never seen joodo but I have a bunch of routing helper functions which do a lot of the same things

0:33 and which I feel mixed about. haha

0:34 sdegutis: I am personally not a fan of the abstractions it provides, which were borrowed heavily from Rails.

0:34 However, it executes them very well.

0:34 ddellacosta: yeah, I remember looking at speclj and thinking, "uh, not sure we want Rspec in Clojure..."

0:34 I'm sure

0:36 sdegutis: That's something I'm hoping I can convince him of. But it's hard to come up with empirical evidence that Ruby idioms don't fit well into Clojure. It looks an awful lot like a question of preference.

0:38 technomancy: "cultural fit" might be more convincing

0:38 sdegutis: No comprendo amigo.

0:38 technomancy: you can do it, but everyone will look at you funny

0:38 like putting each paren on its own line

0:40 xeqi: sdegutis: does that setup require you to specify the middleware stack in each (with-routes ..) ?

0:41 sdegutis: technomancy: He released gaeshi, which has sub-libs named kuzushi, kake, and tsukuri. He's not afraid to admit that culture-fit isn't a big priority to him.

0:42 xeqi: with-routes is only used in tests, and he recommends not putting middleware in tests.

0:43 technomancy: because when you have a message you want to get across to the world, that's more important than conforming to conventions.

0:43 xeqi: and you can write your "domain level" tests without middleware ?

0:44 sdegutis: xeqi: I'm not sure how to answer that.

0:44 clj_newb_2345: is there an easy way to say : don't auto ":use clojure.core" ? I'm building a dsl, and I'm clashing with the clojure.core/* names

0:45 xeqi: you previously mentioned what I refered to as "feature tests" might be what you call "domain level" tests, so was just trying to get a feel there

0:46 sdegutis: To clarify about the gaeshi thing: I'm not saying it's bad that he used those names, just using it as an example of his driving philosophy.

0:47 xeqi: clj_newb_2345: add (:refer-clojure :exclude [*]) to the ns declaration

0:47 clj_newb_2345: for eveyr file?

0:47 is there a way to put it into some type of lein config?

0:47 sdegutis: xeqi: Oh. I mean, I would write a test that does (add-to-cart cart item) and assert that (items-in-cart cart) contains item, and that would be my domain-level test. It wouldn't have anything to do with HTTP or anything else. And it wouldn't know the details of *how* add-to-cart or items-in-cart work.

0:48 xeqi: In fact even the data structures themselves would be created by other opaque functions like (create-cart ...) and (create-item ...) and they would have domain-driven keys like (:quantity item) etc, rather than being driven by any implementation details.

0:49 xeqi: sdegutis: ah, I was refering to a test that simulates how a user would interact with the system

0:49 sdegutis: xeqi: that's what I'm talking about too. Just at another level lower than HTTP.

0:50 I look at HTTP like a bridge between the user and the code, and that's helping my code a ton.

0:50 Ideally nothing in my test suite would test HTTP-level code at all.

0:51 xeqi: sdegutis: so you test your route configuration to non-http-level code elsewhere?

0:51 sdegutis: xeqi: No, I don't test it.

0:52 xeqi: ah

0:52 sdegutis: xeqi: Every time I make a change that could break one of those such tests, I always re-check that route in my browser anyway.

0:52 xeqi: The tests at that level don't tell me if anything actually works in real life, only that the code I wrote in file A matches the code I wrote in file B.

0:53 xeqi: "at that level" ?

0:53 sdegutis: Testing my HTTP-bridging code.

0:53 The production code that lives inside (defroute ...) and calls (add-to-cart).

0:54 It might make more sense for a bigger project with a bigger team. But this is a one-man small website.

0:57 reshpectabiggle: Really? Nobody had this nick?

0:57 *snatched*

1:00 xeqi: we are talking pretty close to the same level. I do prefer mine to go through the ring interface, mainly to gain changes from the middleware stack

1:01 reshpectabiggle: xeqi: That's one of the reasons I don't test at that level, because I don't want my tests to deal with raw user-data.

1:02 I mean raw incoming data.

1:02 That encourages things like :packer and :type, in https://github.com/8thlight/hyperion#entities

1:05 It leads to leaky abstractions, where the first representation of your data that you get from the HTTP level ends up being passed all the way down through your code, instead of being converted right away to something meaningful to your feature-specific-logic.

1:05 * reshpectabiggle is confusing himself

1:07 ddellacosta: argh, power died and looks like I missed out on some testing conversation

1:08 respectabiggle: ddellacosta: http://logs.lazybot.org/irc.freenode.net/%23clojure/2013-09-04.txt

1:08 Scroll to the end.

1:08 ddellacosta: respectabiggle: cool, thanks. :-)

1:08 respectabiggle: Anyway I would take what I've said with a large dose of salt, I've only been at this for a few years.

1:09 xeqi: you still have the conversion code right?

1:09 ddellacosta: wtf does "gaeshi" mean

1:09 sdegutis: Uhh..

1:09 ddellacosta: It's from martial arts.

1:09 ddellacosta: ah, google app engine pun, clever

1:10 sdegutis: ddellacosta: ever heard of 8th Light?

1:10 ddellacosta: sdegutis: yah, but what does it mean?

1:10 sdegutis: most definitely, I know Uncle Bob and Colin Jones are there

1:10 among others

1:10 sdegutis: Hmm, where do you know them from?

1:10 I mean, besides 8L.

1:11 ddellacosta: sdegutis: I mean, they are not people I know, other than by their writings.

1:11 sdegutis: Uncle Bob is of course the grand-old-curmudgeon of TDD and code-cleanliness

1:11 sdegutis: Yeah.

1:11 You have any of his cleancoders.com episodes?

1:11 ddellacosta: sdegutis: and Colin Jones I know from his Clojure contributions, and excellent article on namespaces in Clojure

1:12 sdegutis: Heh yeah, the canonical namespaces article.

1:12 ddellacosta: sdegutis: naw, can't justify paying for them as of yet

1:12 sdegutis: Yeah I hear ya.

1:12 ddellacosta: yeah, definitely a good one

1:12 sdegutis: I worked at 8L for a few years. That's where I learned TDD.

1:12 seangrov`: ddellacosta: Paying for what?

1:12 technomancy: sdegutis: eh; it's fine to do your own thing, you just can't expect it to get any traction

1:12 ddellacosta: sdegutis: I mean, I can't buy into any one person's ideas too strongly, especially a pedant like Uncle Bob, not to be derogatory--I like some of what he says a lot.

1:13 sdegutis: technomancy: wait hold on, what is that in response to?

1:13 technomancy: literally never heard of anyone using speclj in the wider community

1:13 sdegutis: Oh right.

1:13 ddellacosta: I agree with your approach.

1:13 ddellacosta: seangrov`: oh, I mean, I just don't want to pay for videos on uncle Bob's philosophy right now, since I get as much of it as I need from reading clean code

1:13 technomancy: lisp in general has a long tradition of cowboy coders striking out and creating their own little worlds

1:14 sdegutis: technomancy: Oh, is that where Ruby gets it from?

1:14 technomancy: (because that's practically all you could do in the 80s unless you went to MIT)

1:14 ddellacosta: technomancy: totally

1:14 sdegutis: seangrov`: he's talking about cleancoders.com, you should check it out, some of the videos might be helpful

1:15 A few of us are in Episode 4 a few times.

1:15 ddellacosta: sdegutis: ah, well for that I'd be interested in checking it out. ;-)

1:15 sdegutis: I think I called FP "a fad".

1:15 ddellacosta: ah, haha

1:15 sdegutis: :D

1:15 ddellacosta: I mean, it is in some ways. Us developers as a group are pretty faddish

1:15 sdegutis: I also said temporal coupling was like what Spock did.

1:16 technomancy: sdegutis: just wait, give Intel another couple years and this multicore thing will be a distant memory

1:16 sdegutis: (I was trolling Uncle Bob.)

1:16 technomancy: we'll have our 8GHz chips yet

1:16 ddellacosta: sdegutis: gotcha. :-)

1:16 technomancy: sweet.

1:16 sdegutis: technomancy: been holding my breath like they said to.

1:19 ddellacosta: anyway reason I asked about Colin and Bob is cuz I only knew them from 8L and I'm always curious to see how it is that different people I know also know each other. So thanks for letting me know.

1:20 Also Colin wrote REPLy which is part of Leiningen now, so that's pretty cool :)

1:20 ddellacosta: sdegutis: sure. I mean, I should be clear I've never met them in person or even exchanged emails, I meant know as in "know of." Although I think Colin did give me a tip on getting fixtures working in clojurescript.test at one point here on IRC.

1:21 sdegutis: ddellacosta: gotcha

1:21 ddellacosta: sdegutis: yeah, seems like Colin's written some real good stuff.

1:21 xeqi: $seen trptcolin

1:21 lazybot: trptcolin was last seen quitting 8 hours and 56 minutes ago.

1:22 ddellacosta: xeqi: damn, didn't know about that, very cool IRC command. I'm still such an IRC newb

1:22 technomancy: colin is great; he should spend more time on IRC =P

1:22 xeqi: yeah, we wanted him for something the other day... can't remember now tho

1:22 sdegutis: Yeah I keep pressing "trp[TAB]" every few days and sigh when it doesn't autocomplete.

1:22 ddellacosta: technomancy: yah, I think the time I was having trouble was the only time I saw him on here, and he was super helpful.

1:22 haha

1:23 sdegutis: Anyway they have open office on Friday afternoons, I should visit them soon. If you're in the Chicago area you should too.

1:23 Lots of very smart people.

1:24 ddellacosta: sdegutis: never been to Chicago, would like to go. And would love to drop into 8th Light some day too, and meet those folks.

1:24 sdegutis: For example this was a nice Friday talk to learn some Haskell: http://vimeo.com/63093231

1:25 * sdegutis is nostalgia-izing.

1:28 dissipate_: sdegutis, why doesn't 8th light mention clojure on their site?

1:28 sdegutis: dissipate_: they haven't really gotten into it yet. Still doing Ruby mostly.

1:30 dissipate_: sdegutis, even though bob martin has been evangelizing clojure?

1:32 sdegutis: lol... "but who honestly, in their right mind, uses list literals without putting a space after the comma... Yeah, 'nobody', is the answer." -- http://vimeo.com/63093231#t=292

1:34 dissipate_: 8th Light has clients and therefore not all their projects are greenfield. But I know that Bob's site uses Clojure.

1:36 dissipate_: sdegutis, hmm, sounds like Relevance is a better shop

1:36 sdegutis: dissipate_: seeing as the guy who literally wrote the book on Clojure works there, then yes, probably.

1:36 dissipate_: nevermind, i want to work at 8th light: http://8thlight.com/our-team/angeleah-daidone

1:37 sdegutis: dissipate_: why?

1:37 ddellacosta: dissipate_: lame

1:37 dissipate_: sdegutis, hot female apprentices ^

1:37 want to touch the hiney!

1:37 sdegutis: dissipate_: wow.

1:37 ddellacosta: dissipate_: super lame

1:37 seabre: Going from cosmetology to software development is super impressive.

1:37 sdegutis: seabre: very.

1:38 ddellacosta: wow

1:38 spjt: i went from digging ditches to software development, but i'm an ugly guy, so who cares.

1:38 dissipate_: mmmmm, impressive

1:38 sdegutis: They're very active in helping people learn from 0 to professional.

1:38 ddellacosta: spjt: that is also impressive.

1:38 nightfly: spjt: Still impressive

1:38 dissipate_: sdegutis, it had nothing to do with her looks?

1:38 sdegutis: Colin went from having a master's in trumpet performance to being an 8L apprentice to finally a craftsman. That was pretty cool.

1:38 dissipate_: let's pretend this conversation didn't happen.

1:39 dissipate_: i bet they had a bunch of dudes who wanted to apprentice and they picked her

1:39 ddellacosta: sdegutis: agreed

1:39 sdegutis: dissipate_: what do you do for a living?

1:39 spjt: tbh that picture looks like they were trying pretty hard to make her look better than she actually does

1:40 sdegutis: spjt: what do you do for a living?

1:40 dissipate_: sdegutis, program

1:40 sdegutis: dissipate_: what language?

1:40 spjt: sdegutis: code

1:40 dissipate_: sdegutis, perl mostly

1:40 sdegutis: spjt: what language?

1:40 dissipate_: really? You write Perl for a living?

1:40 spjt: sdegutis: j2ee, at least when my boss is looking

1:40 sdegutis: I didn't know there were jobs for that.

1:40 dissipate_: sdegutis, correct

1:40 sdegutis: spjt: Ha. Have you been able to use Clojure at work?

1:41 dissipate_: sdegutis, when i was first in the job market there were more jobs for perl than python

1:41 spjt: sdegutis: yes

1:41 sdegutis: dissipate_: Cool. How do you like Clojure compared to Perl?

1:41 dissipate_: sdegutis, i want to switch to clojure really bad.

1:42 sdegutis: spjt: Sweet.

1:42 dissipate_: Why?

1:42 spjt: dissipate_: you might have better luck than me.

1:43 dissipate_: sdegutis, i'm not a fan of syntax heavy languages. i got into perl because i didn't want to do java or .net, and python jobs weren't really available.

1:43 spjt: I use clojure for one-off things like moving data from one format to another, but I'm not allowed to use it in the application

1:43 dissipate_: sdegutis, also, i'm convinced that pure functions and immutable data structures are the way to go after watching Hickey's talks and reading the paper 'Out of the Tar Pit'

1:43 sdegutis: dissipate_: What about Ruby?

1:44 spjt: Ah good way to find use out of it. Have you used other languages to do that same thing (besides Java) before Clojure?

1:44 dissipate_: sdegutis, not too interested in it. i'm sure is fairly on par with python, but it suffers like all the OO languages: mutable state and non-pure functions.

1:45 spjt: sdegutis: I tried to learn clojure and gave up before learning scala, then came back and it made sense

1:45 seabre: You can sorta do immutable data structures in ruby

1:45 [1,2,3,4].freeze

1:46 dissipate_: i just wish clojure was viable as a scripting language. seems like it is not because of the startup time of the JVM.

1:47 sdegutis: seabre: true but its stdlib is geared slightly more towards mutation

1:47 dissipate_: Have you looked into Racket? I hear good things about it.

1:47 spjt: dissipate_: Have you looked at scala

1:47 dissipate_: so for now i'm going with python and clojure. python for scriping, clojure for applications. and C for low level programming.

1:47 gws: haskell? :D

1:47 sdegutis: Oh boy, I've heard nothing but bad things about Scala from people I respect.

1:47 zanes: dissipate_: re: Angeleah Daidone - There would probably be more female programmers if men like us a) stopped objectifying them, and b) stopped ascribing their success to their looks.

1:47 dissipate_: sdegutis, no. it is a viable scripting language that has good libs?

1:47 sdegutis: zanes: what do you do for a living?

1:48 dissipate_: It's a Scheme dialect which is very similar to Clojure.

1:48 dissipate_: read this, it's very informative about Clojure compared to Racket: http://technomancy.us/169

1:48 spjt: Scala is good if you want to get into FP but you have a job

1:48 dissipate_: spjt, i have not looked at scala. it has OO so that's a turn off. plus heavy syntax (so i've heard), another turn off.

1:49 i'm also interested in haskell to some degree, but the fact that it compiles to native executables is a big turn off for me. they need to make it compatible with the JVM.

1:49 sdegutis: spjt: I'm not sure about that. For example I could hear someone saying the same thing about using Ruby "to get into OOP" when you have a job, but I'm not sure I'd recommend Ruby to anyone anymore.

1:50 s4muel: Scala to me didn't seem removed enough from Java, conversely that's touted as a strong point. But the syntax is verbose and it felt like Java. Clojure (obviously) doesn't.

1:50 zanes: sdegutis: I'm a software engineer.

1:50 dissipate_: zanes, i was just joking about her. her story actually sounds quite interesting, going from cosmetology to software development.

1:50 sdegutis: zanes: cool, what language(s) do you primarily use?

1:50 spjt: s4muel: That's why I said "if you have a job". If you know Java you can "learn" it in an hour.

1:51 sdegutis: dissipate_: I love native executables. They're great! What I don't like about Haskell is the super-strict typing, to the point that you have multiple functions with numbers at the end describing how many args they take, like zipWith3 zipWith4 etc

1:51 zanes: dissipate_: Fair enough. I just think we need to be careful about the kinds of jokes we make; the tech community is notoriously hostile towards women.

1:51 spjt: s4muel: You can then gradually transition, eventually you realize you're not using mutable state anymore and then it's much easier to pick up Clojure, etc.

1:52 sdegutis: s4muel: yeah, I'm actually really surprised and impressed at how well Clojure fits into the JVM while being such a completely different language from Java.

1:52 dissipate_: sdegutis, i don't because you have to worry about what machine your code is running on. virtual machines FTW. love or hate the JVM, it beats native.

1:52 zanes: sdegutis: These days I mostly use Clojure (in the form of Cascalog) and Javascript.

1:52 sdegutis: zanes: to throw in my 2¢, I don't think the goal is to get more women programmers, but to become more respectful of everyone in general.

1:53 s4muel: spjt: I see where you're coming from. Yeah, a lot of J2EE folks I know are right at home with Scala. I was never heavy into Java but more into Python/Perl and a little Haskell, so the biggest jump for me was a) state and b) lisp-y syntax

1:53 dissipate_: sdegutis, BTW, i'm not saying virtual machines are always better, but if my app can run on a virtual machine, i'll use that every time.

1:55 s4muel: But working with the libraries on the jvm from clojure has been so easy (so far, at least) that I keep wondering 'is that it?'

1:55 sdegutis: dissipate_: that philosophy doesn't play well with Mac OS X native apps.

1:55 dissipate_: using a JVM app on Mac feels so weird compared to a native ObjC app.

1:56 s4muel: ditto :)

1:56 scottj: sdegutis: even good jvm apps, like intellij idea?

1:56 dissipate_: sdegutis, i don't write native apps, so i wouldn't know. :P

1:57 sdegutis: scottj: I haven't used IntelliJ. I dunno how it runs. Maybe it has a cool container that makes it less weird. I should look into that since I'm writing a Swing app that I plan to use on my Mac.

1:57 dissipate_: sdegutis, as for objective c, i'll try to avoid that as i have avoided java.

1:57 spjt: s4muel: It doesn't really have that much to do with syntax. Scala only encourages immutable state, it doesn't require it

1:57 sdegutis: dissipate_: meh, taking the approach "right tool for right job" has worked wonders for me.

1:57 dissipate_: if I avoided ObjC, I wouldn't have been able to write this window manager I'm using.

1:58 dissipate_: sdegutis, i agree. but i avoid the issue by just not doing native app development.

1:58 sdegutis: dissipate_: for the same reason, I'm writing a GUI app in Swing because Clojure is the right language for this task, not ObjC, even though I plan to use it on a Mac.

1:58 scottj: sdegutis: is it tiling? released?

1:58 sdegutis: dissipate_: that's one solution, but it's an awfully boring one isn't it?

1:58 scottj: yes, yes.

1:58 scottj: https://github.com/sdegutis/zephyros

1:59 scottj: well technically it's not tiling, it's *anything*

1:59 am2605: I have a bit of a dumb newbie question (sorry)...

1:59 dissipate_: sdegutis, why is it boring?

1:59 zanes: sdegutis: Disagree. There's value in explicitly fostering diversity by making the tech community a welcoming space for women.

1:59 ahihi: sdegutis, re: zipWithN — in my experience those are used very rarely. and things liftMN are more nicely expressed with the Applicative combinators

1:59 sdegutis: scottj: you write your own stuff in it. My AppGrid configuration is very much like tiling: https://github.com/sdegutis/zephyros/wiki/AppGrid

1:59 dissipate_: you're limiting how many fun/cool problems you can solve.

1:59 zanes: am2605: Don't ask if you can ask, just ask. :)

2:00 ahihi: s/things/things like/

2:00 sdegutis: zanes: making it a welcoming space is fine, but inviting certain people in is really weird and creepy.

2:00 ahihi: Then maybe I'm being unfair to Haskell. I should probably give it a real chance.

2:00 zanes: sdegutis: I don't see what's creepy about outreach to an underrepresented minority.

2:00 s4muel: Or OCaml.

2:01 am2605: if I have a list of say '("Joe" "Bloggs" "Jenny" "Citizen") how can I pick off each pair of values and return them as a list such as '("Joe Bloggs" "Jenny Citizen") ?

2:01 dissipate_: sdegutis, not really. there are plenty of fun/cool problems that can be solved that can be deployed via the web. i know the web sucks, but coding for native platforms is worse.

2:01 am2605: @zanes thanx :)

2:01 sdegutis: zanes: it's like saying "hey guys, we don't have enough ___ in here.. let's go get some ___ to join us!"

2:01 I dunno, it's like saying you know what's best for that person. It feels arrogant to me.

2:02 zanes: Oh, yeah. I never imagined going about it that way.

2:02 sdegutis: dissipate_: I'm not saying there aren't. I'm just saying that's not all of them.

2:03 zanes: well "outreach" may seem abstract, targeted at a group, but groups are always made up of real individuals. So at the end of the day, an "outreach" means that some very real individual girl in high school sees an ad that says maybe she should become a programmer and she might be happier that way.

2:03 And to me that's weird and creepy.

2:04 zanes: I think it's possible to present the idea in a non-patronizing way.

2:04 "Here's an awesome career path you may not have considered."

2:05 At this point I'm assuming we're discussing organizations like Black Girls Code (http://www.blackgirlscode.com/).

2:05 dissipate_: sdegutis, of course not, i know. i had a stint doing embedded linux development. it was a bit of a pain because each board had it's own architecture, so you couldn't just use gcc out of the box. you had to set up a cross compiler.

2:05 sdegutis: zanes: I never heard of a concrete organization that does this, no.

2:06 scottj: zanes: I was actually thinking of the recent Conj extension for women presenters.

2:06 sdegutis: dissipate_: scary

2:06 scottj: yeah, see, that's weird.

2:06 zanes: scottj: Not familiar. What were your thoughts?

2:07 sdegutis: A call for presenter should be focused on content not on the presenter.

2:07 I don't care who's presenting, I just want great content. To care about who's presenting feels shallow and unprofessional.

2:07 scottj: zanes: I think that male/female distinction is not a particularly important one and there are a lot more important aspects of diversity.

2:08 dissipate_: sdegutis, another advantage of developing via a virtual machine is collaboration. anyone who wants to contribute to such an open source project can do so on whatever platform has the virtual machine set up properly.

2:08 zanes: scottj: Go on.

2:08 scottj: zanes: I don't want to, this topic can too easily offend people :)

2:09 sdegutis: dissipate_: yeah, that's a great advantage. But it doesn't always apply. For example my Mac OS X window manager only works on Mac OS X.

2:09 scottj: Oh. Well I hope I haven't offended anyone.

2:09 zanes: scottj: Fair enough. It's an important problem, though, and, I feel, one that benefits from conversations like this.

2:10 dissipate_: sdegutis, that app is for a specific platform, so that i understand.

2:11 ahihi: I got tired of CS being such a boys' club, so I'm switching to math ;)

2:11 (there are other reasons, but it's certainly a factor)

2:12 sdegutis: There's a lot of ways the programmer community could stop disrespecting *people in general*.

2:12 zanes: (This is why explicitly focusing on gender diversity matters — I don't want to lose people like ahihi. ;))

2:12 ddellacosta: just popping in to voice agreement with zanes. I want the tech community in general, and Clojure in particular, to be open and welcoming to women, and that includes being conscious of how people receive what you say.

2:12 sdegutis: For example they could stop having "drinkups" which focus on beer and late evenings, which don't really work well for us family people.

2:12 zanes: sdegutis: It's worthwhile to focus on specific problem areas. I think it's hard to argue with the fact that the tech community, on average, is fairly hostile towards women.

2:13 ddellacosta: sdegutis: I've definitely had some of my co-workers complain about drink ups too, although it's more that I just think we should have multiple venues for people

2:13 sdegutis: zanes: I don't disagree.

2:13 seabre: am2605, did you ever figure out your problem

2:13 sdegutis: ddellacosta: makes sense

2:13 ddellacosta: sdegutis: but definitely, need a space so people can socialize around tech without it being about getting trashed

2:14 and on that note, gonna go get lunch for reals

2:14 sdegutis: :)

2:14 seabre: ,(map #(str (first %) " " (second %)) (partition 2 (list "Joe" "Bloggs" "Jenny" "Citizen")))

2:14 clojurebot: ("Joe Bloggs" "Jenny Citizen")

2:15 seabre: Probably a terrible way to do it, but I guess that works.

2:15 dissipate_: zanes, are you kidding me? the culture is rife with brogrammerism

2:15 zanes: dissipate_: I don't disagree?

2:15 sdegutis: On the other hand, there are some people (both men and women) who find a reason to be upset about *everything and anything*. And some of them hide it behind feminism. But that doesn't help the cause either.

2:15 dissipate_: sdegutis, 'drinkups'? brogrammers

2:16 sdegutis, are you working with brogrammers?

2:16 sdegutis: dissipate_: https://github.com/blog

2:16 first big blue words: "Washington DC Drinkup"

2:16 am2605: seabre: that does work - thank you! I think the partition is what I was missing. Appreciated!

2:16 seabre: no prob

2:17 dissipate_: sdegutis, yep, brogramming

2:17 sdegutis: k

2:17 scottj: women don't drink?

2:17 sdegutis: What's everyone working on tonight?

2:18 I'm struggling to decide between making my app for-pay or making it open-source.

2:18 seabre: I was playing around with overtone.

2:18 scottj: sdegutis: what platform?

2:18 sdegutis: JVM.

2:18 dissipate_: sdegutis, just got done giving a PhD student some advice on TDD. he got trapped in a project that is a ball of mud, with stuff not working.

2:19 sdegutis: dissipate_: maybe also suggest he buy some cleancoders.com episodes on testing.

2:19 Bob's got a lot of good advice on this topic.

2:19 dissipate_: sdegutis, i sent him the clean coder's stuff. but he's working with other people who aren't into that.

2:20 sdegutis: ouch

2:20 dissipate_: but he had another problem with his piece of the project

2:20 sdegutis: seabre: looks neat

2:21 dissipate_: he spent a lot of time on some fancy data structure, but he wasn't using generative testing to make sure it was working fast enough. apparently, when he integrated his data structure into the larger project, things got slower than expected.

2:21 sdegutis: Ah, I had that happen with my music player Mac app.

2:22 Fortunately the solution for me was to buy into Apple's Core Data framework, and it worked wonders.

2:22 seabre: Overtone is really cool. It reminds me a lot of Common Music: http://commonmusic.sourceforge.net/

2:23 dissipate_: sdegutis, you would think that academics who are often not brogrammers would practice clean code, but nope, i guess not

2:24 industry doesn't do clean code, academia doesn't do clean code, is open source the only hope?

2:25 sdegutis: Also, emacs package authors need to stop saying "you're using melpa so it's your fault your stuff is broken" and just stop putting broken stuff on master.

2:25 dissipate_: I've seen a lot of clean open source apps and a lot of very messy ones. Same is probably true in academia and industry.

2:28 Is the 'respectabiggle' joke lost on everyone? :(

2:28 Raynes: Yes.

2:28 respectabiggle: At least not technomancy I bet.

2:29 s/joke/reference/

2:29 * respectabiggle is part of the in-crown, and is the only one who is actually.

2:29 respectabiggle: *in-crowd

2:30 seabre: wait

2:30 Silver Chair

2:30 respectabiggle: (inc seabre)

2:30 lazybot: ⇒ 1

2:30 Raynes: Golden throne.

2:31 respectabiggle: (dec Raynes)

2:31 lazybot: ⇒ 35

2:31 Raynes: (gtfo respectabiggle)

2:31 respectabiggle: (inc Raynes) ;; didn't know it would do something

2:31 lazybot: ⇒ 36

2:32 Raynes: (lols :at respectabiggle)

2:34 respectabiggle: Is there a bias against open source apps, that they must somehow be inferior to pay-for apps?

2:35 Like, "if it was really quality, then they would have charged for it"

2:36 scottj: respectabiggle: I think there might be in my mind because I was going to suggest that he try to charge for it and if that fails then open source it.

2:38 respectabiggle: though I think it might be limited to some domains. I don't think I would have thought that way if it were something server-side/linux. iPhone app, definitely.

2:38 respectabiggle: scottj: In this case It's a Clojure IDE.

2:40 I've always operated on the idea that, if an app is truly worth it, then people will pay for it and spread the word to their colleagues.

2:41 But I've not seen that be true with for-pay apps. If it's only barely better than the competition, people won't pay.

2:42 Especially if it's already a skeptical field, like IDEs.

2:43 scottj: is this nightcode or the new version of la clojure?

2:43 respectabiggle: No. A new one.

2:43 scottj: ahh, cool.

2:45 sdegutis: I want to name it Nepenthe but I think that might be taken wrong.

2:45 seabre: Name it Couture

2:46 sdegutis: I don't even know how to pronounce that, so I can't name it that :P

2:49 scottj: sdegutis: so what's special about it?

2:50 sdegutis: Nothing yet.

2:51 scottj: its specialness isn't something that can be communicated until it's done, since it has to be experienced

2:53 Partially because it may never be done, in which case it doesn't matter what features it would have had.

2:55 scottj: I think a whisker browser-inspired IDE for clojure would be fun to try http://www.maartensz.org/computing/squeak/Helps/Programming/WhiskerBrowser.gif

2:56 But of course then you get into all the boring stuff of editors/IDEs and you start to wish it were just an extension for emacs.

2:56 sdegutis: :)

2:59 One of the main things I've learned in my short career is that most real-world problems aren't actually hard to solve, it's just the way that people think you should solve them is hard.

2:59 For example writing a text editor isn't hard, but writing a text editor that works with every single language ever is hard.

3:01 My IDE won't be good for editing Ruby files. And it probably won't be able to handle files millions-of-lines long. But it'll work great with typical Clojure projects.

3:03 zanes: sdegutis: Learn from Emacs and expose the language the editor is written in to the user!

3:03 That way people can extend it to handle Ruby.

3:05 sdegutis: zanes: that's been done, it's called emacs :)

3:11 ,(partition 2 1 [:end] "foo")

3:11 clojurebot: ((\f \o) (\o \o) (\o :end))

3:12 sdegutis: ,(map #(conj %1 %2) (iterate 0 inc) (partition 2 1 [:end] "test")

3:12 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

3:12 sdegutis: ,(map #(conj %1 %2) (iterate 0 inc) (partition 2 1 [:end] "test"))

3:12 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.core$inc cannot be cast to clojure.lang.IPersistentCollection>

3:12 sdegutis: :)

3:13 ,(map #(conj %2 %1) (iterate inc 0) (partition 2 1 [:end] "test"))

3:13 clojurebot: ((0 \t \e) (1 \e \s) (2 \s \t) (3 \t :end))

3:13 sdegutis: wooo

3:32 I think I want reduce. Or maybe iterate. I want apply (f coll) which gives me back [result new-coll] and apply (f new-coll) etc etc, conjing all results into a new vector.

3:33 How would you do this? Reduce?

3:33 I'm thinking reduce with a seed of [[] initial-coll]

3:33 Kind of ugly, but with the right destructuring it shouldn't be too bad.

3:35 ordnungswidrig: sdegutis: what about reductions?

3:35 sdegutis: Ah, yes!

3:35 I always forget about reductions, thanks ordnungswidrig :)

3:36 ordnungswidrig: sdegutis: you're welcome

3:37 sdegutis: Ah, neither reduce nor reductions works here.

3:37 Because the list (f) should operate on next is whatever (f) returns.

3:38 I think iterate may be close.

3:38 ordnungswidrig: sdegutis: you have some fn like (fn [coll] [(count coll) (conj coll :foo)]) ?

3:39 sdegutis: this cries for the state monad :)

3:39 sdegutis: Not quite.

3:40 ordnungswidrig: sdegutis: but you f is coll -> [result coll] ?

3:41 sdegutis: Actually it could just be: (f [results coll]) -> [new-results new-coll] and just keep calling it until the coll it receives is empty.

3:41 I wonder if I have to resort to recur, or if I can use some seq function(s) for this.

3:42 ordnungswidrig: yes, I would "lift" your basic fn coll -> [result coll] into a fn [results coll] -> [results coll] which can be used with reductions

3:42 and take-while #(not (empty? (second %))

3:42 sdegutis: Ah.

3:44 ordnungswidrig: that take-while could be used with iterate instead, right?

3:45 (take-while #(not (empty? (second %))) (iterate my-fn))

3:45 ordnungswidrig: sdegutis: yes, that should work

3:45 sdegutis: Cool, thanks for the idea of take-while, that was the missing piece all along :)

3:46 ddellacosta: why do we have both rest and next?

3:46 sdegutis: ddellacosta: http://clojure.org/lazy

3:47 ddellacosta: sdegutis: they both return lazy sequences, from the docs

3:47 sdegutis: That's more of a "Rich's thoughts on paper" type doc though.

3:47 ddellacosta: sdegutis: oh sorry, I see there is more explanation on that page

3:47 sdegutis: thanks!

3:47 sdegutis: Yes.

3:47 Any time.

3:48 Periods at the bottom of the line are overrated· Let's put them in the middle from now on·

3:48 callen: bottom?

3:49 sdegutis: Yes•

3:53 rurumate: How to get the name of var a in clojurescript? in clojure I'd do (name (meta (var a))), but apparently var is not a function in clojurescript.....

3:54 sdegutis: I thought CljS has no vars.

3:54 rurumate: oh

3:54 ddellacosta: yep, no vars.

3:54 rurumate: hmm

3:54 ddellacosta: yet.

3:54 sdegutis: https://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#concurrent-programming

3:54 ddellacosta: I think seangrov` is working on it.

3:55 sdegutis: I like Japanese periods: 。

3:55 sdegutis: Oh

3:55 ddellacosta: heh

3:55 sdegutis: 😄

3:56 ddellacosta: callen: how goes it?

3:56 rurumate: so the situation is this: I have a buch of functions, say fn0, fn1 and fn2 and now I want to (mapv #(js/alert (format ("result of % is %" (name %) (%)) [fn0 fn1 fn2]) or something

3:56 is that even possible in clojurescript?

3:57 ddellacosta: rurumate: should be...

3:58 rurumate: although I haven't used mapv in CLJS yet, but believe it exists.

3:58 rurumate: the opening paren after format should not be there..

3:58 ddellacosta: rurumate: although, map is lazy so I'm not sure you'll get what you're expecting

3:58 rurumate: ddellacosta: mapv is eager

3:58 ddellacosta: rurumate: d'oh, you're right, my bad

3:59 * ddellacosta needs to read the docs *before* making the comments

3:59 sdegutis: ddellacosta: I think he's talking about the (name %) part

3:59 rurumate: sdegutis: aye

4:00 ddellacosta: rurumate: yeah, there are too many parens is all, methinks

4:00 sdegutis: yeah, needs more haskell

4:00 * sdegutis ducks

4:00 ddellacosta: heh

4:01 rurumate: off to the day jobs..

4:01 ddellacosta: rurumate: cheers

4:03 * ucb waves

4:05 sdegutis: Oh hi ucb.

4:10 TEttinger: so I'm wondering about array processing a la APL in clojure. is this already covered by Incanter's data sorcery? or would it be a worthwhile project for me to implement the standard set of verbs from APL for use from clojure?

4:10 a lot already is covered, like I don't need to reimplement map.

4:10 but simple things like array reshaping and rotation

4:12 I have kinda noticed that 2d primitive arrays are a pain in clojure. ^"[[L"

4:13 SegFaultAX: I'm pretty sure Mikera is working on a comprehensive matrix library.

4:13 https://github.com/mikera/matrix-api

4:14 TEttinger: If it's useful, maybe you could reach out to him on twitter/github/mailinglist and see if you can contribute there.

4:14 TEttinger: SegFaultAX, thanks. this looks much more professional than what I could do though

4:14 Apage43: see also https://github.com/prismatic/hiphip

4:16 SegFaultAX: I'm so happy to see prismatic re-opening stuff.

4:17 shaungilchrist: TEttinger: I am an APL weirdo and a lisp practitioner, this article would be cool to redo for clojure http://archive.vector.org.uk/art10500180

4:17 TEttinger: Apage43, heh I've been using hiphip

4:17 Apage43, did you submit an issue on that?

4:17 Apage43: mm? Don't think so.

4:18 TEttinger: ah, thought the nick sounded familiar

4:18 there's an issue with AOT compiling hiphip

4:18 I made a total kludge hack of a fork of hiphip that fixes it

4:20 Apage43: interesting

4:20 TEttinger: https://github.com/tommyettinger/hiphip-aot/blob/master/src/hiphip/double.clj#L10

4:20 ddellacosta: shaungilchrist: very cool article, thanks

4:20 Apage43: i have a project that indirectly does some array'y stuff

4:20 TEttinger: shaungilchrist, I'll take a look

4:20 sdegutis: I think I may actually have a case where loop/recur is the cleanest/clearest solution.

4:20 Apage43: at some point i'll probably pull out mikera's matrix stuff and try and make it cleaner/less garbagey

4:21 sdegutis: This is neat.

4:21 Apage43: it's already a dependency, since incanter drags it in and I use a thing from incanter

4:21 ddellacosta: sdegutis: I don't think it's that uncommon.

4:21 Apage43: sdegutis: I have those sometimes. Every so often though I take a second look and it fits into reduce though

4:22 sdegutis: ddellacosta: I've never had to resort to it before, in about a year of doing Clojure professionally, until now.

4:22 ddellacosta: sdegutis: whenever I have to retain state over a loop that can't be handled cleanly with reduce, I use it

4:22 Apage43: though *those* largely wind up being even *more* nicely expressed with https://github.com/LonoCloud/synthread

4:22 ddellacosta: or, what Apage43 said

4:22 sdegutis: Apage43: In this case it won't fit into reduce because the input collection is mutated by the fn itself at each loop and may get shorter than just one element.

4:22 ddellacosta: Apage43: oooh, didn't know about that, nice

4:22 sdegutis: Apage43: (by mutated I only mean it may return a shorter collection)

4:23 Apage43: synthread.core/for

4:23 er

4:23 lonocloud.synthread/for

4:23 rather

4:23 =P

4:24 maybe

4:24 might not fit there

4:25 sdegutis: I do know that this is the first time my test passed all night, and the code is much less ugly than it was when I was trying to use sequences.

4:25 ddellacosta: wow, really going to have to take a close look at synthread, lots of cool stuff there

4:25 sdegutis: I hear ya, sometimes it's just easier not to fight the beast, haha

4:25 TEttinger: shaungilchrist, I didn't see any Common Lisp code?

4:27 sdegutis: Are there any uppercase symbols that are reserved words or core constants in Clojure?

4:28 Like "(def SYMBOL 1)"

4:29 TEttinger: Math/PI

4:29 but that's java

4:29 actually I don't even know... ##(+ 1 Math/PI)

4:29 lazybot: ⇒ 4.141592653589793

4:30 Apage43: ddellacosta: dunno if its a good example as this was stuff I was doing in a hurry last week, but here's some code before/after I synthreadified it https://www.refheap.com/18344

4:30 augustl: sdegutis: I don't think so. The only reserved stuff is in clojure.core, which you can un-refer anyways.

4:31 ddellacosta: Apage43: very cool, thanks. I don't have time to dig into it at the moment, but excited to learn about this library. Thanks for your extra example!

4:31 Apage43: less "how do i express this with reduce" more "this is what I am trying to do"

4:32 it's just one function torn out of a checkers game

4:33 ddellacosta: Apage43: yeah, it shares that nice quality with the threading operators in that it makes the intention much cleaner

4:37 sdegutis: TEttinger, augustl: thanks

4:38 Are vectors efficient at pushing on the end and enumerating from the front?

4:38 augustl: sdegutis: yes

4:38 sdegutis: sweet :D

4:39 So I'm using vectors, case, and loop/recur. This sounds pretty efficient so far.

4:40 augustl: sdegutis: FYI, if you use conj you'll get the "most efficient behaviour" so to speak

4:40 sdegutis: awesome, because I already am :)

4:53 $help

4:53 lazybot: You're going to need to tell me what you want help with.

4:53 sdegutis: $help send

4:53 lazybot: Topic: "send" doesn't exist!

4:53 sdegutis: $help mail

4:53 lazybot: sdegutis: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.

4:54 sdegutis: $mail brehaut Thanks for https://github.com/brehaut/inc-clojure-brush/blob/master/shBrushClojure.js#L64-L385 :)

4:54 lazybot: Message saved.

4:59 sdegutis: Is there a less dumb way of doing this?

4:59 ,(not-any? #{\a \b \c} [\f])

4:59 clojurebot: true

4:59 sdegutis: given #{\a \b \c} and \f

5:02 benoyst: ah.

5:03 ddellacosta: sdegutis: what's dumb about that?

5:03 sdegutis: it creates a vector just to test if a char is in a group of chars

5:04 ddellacosta: I mean, you could do

5:04 ,(some #(= \f %) #{\a \b \c})

5:04 clojurebot: nil

5:04 sdegutis: No other way?

5:04 ddellacosta: not much less concise though. And it creates a anon function in place of your vector.

5:04 sdegutis: ,(doc contains?)

5:04 clojurebot: "([coll key]); Returns true if key is present in the given collection, otherwise returns false. Note that for numerically indexed collections like vectors and Java arrays, this tests if the numeric key is within the range of indexes. 'contains?' operates constant or logarithmic time; it will not perform a linear search for a value. See also 'some'."

5:05 sdegutis: Hmm.

5:07 ddellacosta: sdegutis: yep, contains seems pretty good too.

5:07 ,(contains? #{\a \b \c} \f)

5:07 clojurebot: false

5:07 ddellacosta: ,(contains? #{\a \b \c} \a)

5:07 clojurebot: true

5:07 sdegutis: But.. that doesn't make sense.

5:07 Ah.

5:07 ddellacosta: sdegutis: ?

5:08 sdegutis: ,(contains? #{\x \y \z} \x)

5:08 clojurebot: true

5:08 sdegutis: Oh, in sets, each element is considered a "key" isn't it?

5:08 That must be why it works.

5:09 ddellacosta: ah, yeah, 'cause sets are not ordered I thought

5:09 speaking of sets

5:09 ,(clojure.set/intersection #{\a \b \c} #{\a})

5:09 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>

5:09 ddellacosta: crap

5:10 a well. In any case, could do that too if you wanted to use an unnecessary set instead of an unnecessary vector. ;-)

5:10 sdegutis: ,(require 'clojure.set)

5:10 clojurebot: nil

5:10 sdegutis: ,(clojure.set/intersection #{\a \b \c} #{\a})

5:10 clojurebot: #{\a}

5:10 sdegutis: Nah, contains? works great :)

5:11 ddellacosta: sdegutis: yah, I was definitely joking. It's just fun to enumerate all the different possible ways to do something.

5:11 sdegutis: ah, so you can require just like in repl, cool, dunno why I didn't think of that.

5:13 sdegutis: ,(drop 1 [7 8 9])

5:13 clojurebot: (8 9)

5:13 sdegutis: Is there short-hand for that, or is that already the short-hand?

5:13 Oh duh.

5:13 ,(rest [7 8 9])

5:13 clojurebot: (8 9)

5:13 ddellacosta: sdegutis: I mean, other than rest/next?

5:13 right

5:13 * sdegutis facepalms

5:14 ddellacosta: haha

5:14 sdegutis: I should go to bed soon. 4am might not be the ideal coding time.

5:14 ddellacosta: naw, it's hard to connect all these things up in your head.

5:14 probably! damn, you are in North America aren't you.

5:14 go to bed!

5:14 sdegutis: Lil bit.

5:14 ddellacosta: ;-)

5:14 sdegutis: (re: NAmerica)

5:15 ddellacosta: lol soon (maybe) but don't worry, I won't keep you from working any longer :)

5:15 ddellacosta: although, it's nice to have people around this time of day…always gets a bit dull in the afternoons/evenings in here. :-/

5:15 haha

5:15 yah, good point.

5:15 sdegutis: well, you aren't keeping me from work, *I* am keeping me from work, let's be clear.

5:15 sdegutis: :P

5:19 danlentz: ouch I have just been badly bitten by lisp-1-ness

5:20 sdegutis: how?

5:20 clojurebot: with style and grace

5:20 danlentz: really hard to get used to

5:21 sdegutis: danlentz: care to share?

5:21 danlentz: sdegutis: i have macros defschema, etc for diatomic which create vars literal, resource, stmt, graph, etc. Also defining many diatomic attributes :resource/uri stmt.scope/global, etc

5:22 but then I foolishly named my constructors literal, stmt, graph as well

5:22 sdegutis: heh ah yeah, that

5:23 Hyperion does that too. I've resorted to naming them (new-graph) etc.

5:23 danlentz: works fine when evaluating things by hand as the schema is only needed at the top of the evaluation, and dodnt notice that these functions overwrote the schema defs

5:24 but of course when loading the whole file in order this is not the case, as the db initialization happens only when you start doing something. thus the schemas are all blown away at that point.

5:26 it is really insidious how frequently one is conditioned to think in lisp2 without even realizing it

5:27 lisp1 is prettier in many ways but it really is a mindfuck at times

5:29 i guess i will have to change the constructors to make-* e.g. make-literal, make-stmt but i don't like it

5:30 because all my entities are interned, so make-* is not quite accurate as well as ugly

5:31 find-or-make-literal….. egads...

5:32 maybe I shouldd use caps. (defschema Literal …) [defn literal ...)

5:34 i really haven't read enough clojure source yet to have soaked up all the common practices such as naming, and lisp1 definitely exacerbates my naivete

5:36 but i do like clojure a lot I'm enjoying learning it I just needed to vent for a moment :)

5:41 iI'm surprised there's not builtin prog1 -- first thing I write for any clojure coding. Calling it "returning" tho, since

5:41 i believe I saw thart somewhere

5:41 prog1 is one of the most useful forms

5:42 clgv: danlentz: why? you have progn aka `do`

5:44 sdegutis: I wonder if (do ...) just turns into { ... } in Java

5:44 danlentz: well its pretty common to compute a value, then do a bunch of other things based on it, whose value is not returned to the caller

5:44 sdegutis: danlentz: you can do that

5:44 danlentz: actually I most often use aprog1 which gives you an anaphoric 'it within the body

5:45 clgv: danlentz: not in functional programming

5:45 clj_newb_2345: are there any good examples of mobile html apps built in clojurescript, or is clojurescript just too damn slow?

5:46 sdegutis: danlentz: yeah a lot of your comments strongly indicate you would benefit from a total paradigm shift instead of transliterating what you're used to into Clojure

5:46 danlentz: well for example for diatomic queries, initially I compute the entity, which is what I want to return, then I do various things around it which i dont

5:47 sdegutis: danlentz: btw do you mean Datomic?

5:48 danlentz: btw you can do that with (let)

5:49 clgv: sdegutis: in defn it seems like you are right and `(do ...)` just evaluates to {...}

5:49 sdegutis: just tried it and looked at the class via jd-gui

5:50 sdegutis: clgv: neat :)

5:50 danlentz: yes, it is a paradigm shift. But step by step things are improving… Actually I've been pleasantly surprised that clojure hasn't been too bad to pick up and start writing stuff… IIRC it took me a month to get a workable asdf/package dicipline/etc down in CL and probably a year to really master the finer points

5:50 clgv: sdegutis: (defn f [x] (do (println "1") 2)) => public Object invoke(Object x) { ((IFn)const__0.getRawRoot()).invoke("1"); return const__1;}

5:50 danlentz: y datomic

5:50 clgv: you can guess the constants ;)

5:50 sdegutis: danlentz: that's the beauty of Clojure, it's simple.

5:51 Anderkent]away: clgv: a more meaningful test would be to compare (defn f [x] (println "1")) and (defn f [x] (do (println "1"))). I'd expect the same bytecode

5:51 danlentz: mine is diatomic b/c it looks like dirt :)

5:51 sdegutis: Common Lisp is "powerful" but very complex (unnecessarily so IMHO).

5:51 Anderkent]away: i.e. do is just a language construct, it doesnt have a runtime signature

5:51 clgv: Anderkent]away: hm yeah defn has an implicit do ;)

5:52 Anderkent]away: but that doesn't mean it puts a do around its body, just that it 'parses the body as if it was in a do'

5:52 danlentz: common-lisp makes a point of not imposing any particular concept on how you think. clojure makes a point of very specifically doing the opposite

5:53 clgv: Anderkent]away: no it expands to somewhat containing (fn* ...) ;)

5:54 danlentz: I love CL a lot but its really exciting how vibrant the clojure community and ecosystem is

5:54 sdegutis: danlentz: CL may say that it doesn't impose any way of thinking, but it actually imposes a mutable, imperative style of thinking

5:54 it's just implicit

5:54 danlentz: not at all. you can program in a functionl style as well as in clojure

5:55 you just don't have to

5:55 sdegutis: Sure, but it's not nearly as well supported as the mutable/imperative style is.

5:55 danlentz: supported?

5:55 sdegutis: Just like you can do imperative and mutable code in Clojure, it's just not nearly as easy or pleasant.

5:55 danlentz: what's missing?

5:56 scottj: danlentz: does CL have immutable hash maps built-in?

5:56 danlentz: actually you can do immutable CLOS even very nicely. have a look at the project parallel for a sterling example of this style

5:57 well plists would be the equivalent

5:57 you cons to the front of them to use them immutability

5:58 a lists can be used this way as well.

5:59 actually though I wrote my own weight-balanced tee collections lib and also a impelmentation of the ctrie ds with quite a bunch of stuff http://github.com/danlentz/cl-ctrie

6:01 scottj: danlentz: and how do you remove something from the plist without messing with a "copy" elsewhere? See, this is what people mean by CL doesn't support functional very well.

6:01 danlentz: ctrie is a really interesting example of a careful blend of functional and mutable approach that takes a lot of the benefits of both approaches

6:02 if you removed it, that would be mutating it..

6:02 [cdrr plist) would just remove a newley consed entry at the head w/o mutating

6:02 cddr i mean

6:02 scottj: ,(let [a {:a 1 :b 2} b (dissoc a :a)] [a b])

6:03 clojurebot: [{:a 1, :b 2} {:b 2}]

6:03 scottj: in CL?

6:03 so long as [:b 2] is at the front and you don't need fast lookup then CL is functional, right?

6:04 sdegutis: scottj: what are you working on these days

6:04 danlentz: ( let ((a (list :a 1 :b 2))) (values a (cddr a)))

6:05 sdegutis: ahhh i remember (values) well

6:05 I'm glad Clojure was able to ditch the legacy of CL.

6:06 danlentz: actually one would usually use plist-remove a common short utility function that would give you the same semantics as dissoc

6:07 scottj: danlentz: anyway, I think a wide array of immutable (not immutable by convention) data structures built-in is one thing people mean by CL not supporting functional as well as it could.

6:07 I don't see plist-remove in hyperspec

6:08 oh, people write their own version of the the common missing functional utility functions :)

6:08 danlentz: well I'm glad that clojure is being successful, although I think many of the perceptions of CL are just from being misunderstood. But, its partially to blame for that, since it is extremely easy to misunderstand it. learning CL for me at least was unbelievably hard

6:10 sdegutis: danlentz: I don't think it's misunderstood, in fact that's the perception I have: it's unbelievably hard. And that's a symptom of the problem with it: it's unnecessarily complex to the point of being convoluted and detrimental to productivity.

6:10 danlentz: there are 738 built-in symbols, and 1135 pages of spec. It is not unreasonable to have users write a few 3 or four line utile. That is exactly the clojure approach as well. You can't argue that clojure.core is nearly as replete as cl.

6:11 sdegutis: danlentz: You can get good at the language, but that doesn't mean the language is good. Such a steep learning curve is often a sign of a poorly designed language.

6:12 danlentz: y it is unbelievably hard to learn. I never in a million years expected it to take 4-5 years to get fluent. My experience before that was a few weeks to master the basics of a new lang, with the gaps filling in after that while working.

6:13 sdegutis: danlentz: a few weeks is reasonable.

6:13 4-5 years is unreasonable, and I blame the language.

6:13 danlentz: common lisp is not truly just one language, it is a fluid environment for developing a language that suits your problem

6:14 common lisp has no philosophy -- the only thing that binds us together is a shared disgust for all the alternatives. (scott burson)

6:14 sdegutis: heh

6:15 Whoa, this Clojure lexer is only about 50 (readable) lines.

6:15 * sdegutis claps giddily

6:16 danlentz: maybe.. having gone through the process in retrospect it was extremely rewarding and I think it helped me think about programming in a fundamentally different way. So I am grateful for the experience. But it was indeed painful for a long time.

6:18 there is nothing in clojur that couldn't be done better in common lisp IMO. but, the barrier to entry and learning curve is just never going to be suitable to most people.

6:21 sdegutis: Guys,

6:21 danlentz: and the community is somehow broken. no two cl programmers can ever agree on anything. collaboration is almost unheard of. There are very academic minded enthusiasts who debate endlessly the finest details. It is a social problem to a large extent.

6:21 everybody rewrites everything independently form the ground up

6:22 sdegutis: What approach would you take, given a sequence of chars beginning with a double-quote, if you wanted to find the end of the string (ignoring escaped double-quotes)?

6:22 danlentz: called the NIH (not invented here) syndrome

6:22 subseq

6:22 sdegutis: danlentz: barrier to entry is itself a feature of a language that can't be ignored or dismissed.

6:22 danlentz: It's one reason CL is not mainstream but Clojure is getting there.

6:23 danlentz: well I'm not disagreeing about that at all.

6:23 sdegutis: Okay. Maybe we should stop bikeshedding.

6:23 :)

6:24 danlentz: :) i needed a break and Its really the first conversation I've had in #clojure so I've enjoyed it :)

6:25 i've never understood the schism of CL with other lisps. e.g. emacs-lisp seems quite hostile to cl and there is little code sharing or cross pollination. rms is in particular CL-hostile

6:26 but i'm glad to see a lisp on the rise, and if its clojure then i'm on board

6:27 i do also hate these [] though…. :)

6:27 sdegutis: danlentz: everyone else here's asleep, you should come back in about 5 hours for a better conversation :)

6:27 danlentz: homogenous parens are so easy...

6:27 devn: false

6:27 im around

6:27 ddellacosta: sdegutis: you're still up??

6:27 lazybot: ddellacosta: Definitely not.

6:27 sdegutis: devn: hullo!

6:27 devn: danlentz: it reads better

6:27 sdegutis: ddellacosta: sure

6:27 ddellacosta: heh

6:27 sdegutis: only been what, an hour?

6:27 devn: danlentz: it's a matter of taste, but it reads better

6:28 IMO

6:28 sdegutis: danlentz: it reads way better.

6:28 danlentz: to me it has the same purpose and benefit as syntax highlighting

6:28 danlentz: y I need to finally make peace with paredit.

6:28 ucb: I'm around too

6:28 bamford: people, newb speaking: I'm trying to generate the sequence \a...\z. Best I can do is (map char (range (int \a) (inc (int \z))))

6:28 sdegutis: I think it's a matter of taste, in the same way that pizza is a matter of taste: everyone I know agrees with me about it.

6:28 bamford: Surely there's a better way?

6:28 ucb: I know I'm quiet, but CMON

6:28 devn: ,(map char (range 97 123))

6:29 clojurebot: (\a \b \c \d \e ...)

6:29 sdegutis: ucb: hullo!

6:29 ucb: sdegutis: !

6:29 Anderkent]away: ,(map char (range (int \a) (int \z)))

6:29 clojurebot: (\a \b \c \d \e ...)

6:29 sdegutis: danlentz: okay you may get a better conversation any minute at this rate.

6:29 devn: ,(int \z)

6:29 clojurebot: 122

6:29 Anderkent: ah right thats what oyu had

6:29 devn: ,(map char (range 97 122))

6:29 clojurebot: (\a \b \c \d \e ...)

6:30 sdegutis: ,(doc range)

6:30 ddellacosta: ,(map char (range 97 123))

6:30 clojurebot: "([] [end] [start end] [start end step]); Returns a lazy seq of nums from start (inclusive) to end (exclusive), by step, where start defaults to 0, step to 1, and end to infinity."

6:30 (\a \b \c \d \e ...)

6:30 devn: I think Raynes made a range which will let you do char ranges

6:30 ddellacosta: doh, devn beat me to it

6:30 bamford: devn: assuming the dear reader knows \a == Ascii 97 ...

6:30 sdegutis: end is exclusive, bamford is right for (inc)ing it.

6:30 Anderkent: well

6:30 sdegutis: bamford: I like your solution best.

6:30 Anderkent: (seq "abcd...z")

6:30 :D

6:30 bamford: :)

6:30 Anderkent: ,(seq "abcdefghijklmnopqrstuwxyz")

6:30 clojurebot: (\a \b \c \d \e ...)

6:30 Anderkent: totally not error prone

6:31 sdegutis: Anderkent: ha

6:31 devn: heh

6:31 sdegutis: (inc Anderkent)

6:31 lazybot: ⇒ 4

6:31 ddellacosta: actually, I agree w/sdegutis, it's nicer to see explicitly what you're ranging over

6:31 sdegutis: I'm *almost* done with my Clojure lexer (ignoring edge cases like weird numbers and stuff).

6:31 bamford: ok, thanks

6:31 Anderkent: yes, I prefer the (int \a) version too

6:31 sdegutis: All I have left is strings, and it's getting weird.

6:32 danlentz: with all parens there is no issue with mismatching and the structure is made clear by the indentation. clojure is convenient for brevity but some of the deterministic structuring of code is sacrificed and there is constant need to match what kind of delimiter you're closing. not a huge problem, but the idea that [] makes things easier is a little misguided, imo. But there are a lot of people who get turned off immediately when see

6:32 )))))))))) so I appreciate that clojure is attempting to appeal to a wider audience. which is the whole point anyway.

6:33 devn: danlentz: https://github.com/Raynes/morphin

6:33 ddellacosta: danlentz: I think it's mostly the question of visual signaling, but it seems like you're talking about writing code

6:33 danlentz: I feel like I get a very quick read with stuff like [] and {} so I can tell what I'm working with very easily. That said, I've never written CL or any other Lisp variant to the degree I've done Clojure, so it may totally be because I'm used to it.

6:34 devn: (morphin/range \a \z)

6:34 sdegutis: Man I'm hitting tons of 1-off errors. Thank goodness for these tests!

6:34 devn: where is marick to congratulate you?

6:35 ;)

6:35 sdegutis: danlentz: paredit makes that a non-issue

6:35 devn: heh im using attest

6:35 its pretty crappy right now, needs lotsa fixin up

6:35 https://github.com/sdegutis/attest

6:35 danlentz: devn: the seq concept of clojure is fantastic.

6:36 devn: i love brian, fwiw, just having some fun because whenever someone takes something to an extreme, we owe it to the world to be critical

6:36 danlentz: sure is :)

6:36 sdegutis: devn: ha, I love how he says "on a growing number of types" and there's like 2

6:37 not that it isn't true, just unexpected

6:37 danlentz: well i'm sure at some point it was 1 :)

6:37 devn: he's a sly writer

6:37 ddellacosta: devn: you missed our conversation about Uncle Bob earlier, if you want to talk about extremes

6:37 devn: i have no interest in building a resume off of testing

6:37 it's a valuable skill

6:38 ddellacosta: devn: agreed and agreed

6:38 devn: just not my area of interest

6:38 danlentz: did you guys see the posting of clojure v .000001a -- written in common lisp. just saying...

6:38 devn: heh, no i missed that

6:38 if it's in CL then... what about JVM interop?

6:38 danlentz: i think it was on reddit. either in /r/lisp or /r/clojure

6:39 ddellacosta: what is .000001a (not sure I got the right # of 0s)

6:39 ?

6:39 sdegutis: devn: I don't understand your resume comment.

6:39 danlentz: it was a very early prototype i don't know the real version

6:39 devn: sdegutis: oh, just that i dont have a desire to build a career on TDD or whatever

6:39 danlentz: and there is a full cl implementation with MOP that runs on jam -- abcl

6:39 ddellacosta: sdegutis: my interpretation was that "testing" being the defining feature of one's expertise is unappealing as a career strategy

6:40 sdegutis: danlentz: he should have named it Lava

6:40 ddellacosta: at least, that's my take

6:40 danlentz: jvm rather

6:40 devn: ddellacosta: that's the gist of it from my perspective, yeah

6:40 danlentz: maybe larvae might have been apropos

6:40 sdegutis: Ah.

6:40 ddellacosta: let me just take the opportunity to say that I hate writing CoffeeScript.

6:40 that is all.

6:41 devn: i find the whole "everything is about testing" to be a worldview that is limiting, rather than freeing

6:41 it's reductive

6:42 danlentz: writing good tests is more arduous than writing the code itself it seems to me a lot of times

6:42 ddellacosta: devn: I will say that TDD has proven itself to be a viable way for me to work through *some* design problems and provide nice regression tests simultaneously. I'm not saying it's the be-all end-all though.

6:42 devn: ddellacosta: it's especially rad when people ask you to write coffeescript when they don't know it

6:42 danlentz: and more arduous to maintain and manage

6:42 ddellacosta: devn: I don't know it either, is the problem

6:42 devn: ddellacosta: sure. no one is arguing there. i like to have good, informed tests, so i know whether or not im regressing

6:42 ddellacosta: danlentz: it can definitely be a challenge

6:43 devn: yeah, mostly I was just stating that 'cause I think TDD has its place, and I think a lot of people take an either/or interpretation with it. The recent article by Alex Miller felt that way regarding TDD.

6:43 sdegutis: So, I'm finding myself just changing numbers randomly and hoping the test passes. This is probably a sign of poor design.

6:43 devn: but the cult of testing produces a lot of garbage

6:43 which im apparently supposed to admire

6:43 ddellacosta: devn: regression tests, however, are pretty much unequivocally awesome and necessary, imho

6:43 sdegutis: On the other hand, "it's almost done I just need to make it pass then I'll never have to touch it again!"

6:44 ddellacosta: sdegutis: or it's a sign you're tired.

6:44 sdegutis: devn: I've seen great results and horrible results. Depends on who's doing it and how good they are at programming without tests.

6:44 ddellacosta: mayhaps

6:44 devn: "check out this sweet stubbed and mocked stub which is a mock that i stubbed with a mock and then asserted that the crap i put in is the crap i get out"

6:44 ^---lots of ruby projects due to the cult of testing

6:44 danlentz: lein is really nice and test-is has been pretty easy to get along with so far. I don't want to ooh at the other testing libs so I won't get the wants for whatever cool features i don't know i'm missing...

6:45 devn: green tests, however silly, become a requirement

6:45 ddellacosta: devn: yes, to the n-thousandth degree, re: rails (specifically within ruby, which is not all that way) cult of testing

6:45 devn: patches will be accepted as long as they have tests, whether or not those tests matter

6:45 marick had some comment on twitter the other day that got my blood boiling about ruby's superior testing culture

6:45 ddellacosta: even though I disagree with the way some people think about tests in the Clojure community, I *can* disagree without someone looking at me like I'm trying to poop on the floor

6:46 sdegutis: I have a seq of chars that make up "test\"ing" if you join them together, and I want to get the length of the whole string from it, which is 8, even though there are more chars after it.

6:46 danlentz: the spec english style testing seems ridiculous to me

6:46 devn: ruby's testing culture is like watching someone cut themselves

6:46 ddellacosta: hahaha

6:46 devn: then you hear talks about fast tests and what-not

6:46 the quest for fast tests

6:46 gee, i wonder why

6:47 ddellacosta: devn: I think some of it grows out of the insanity you can inflict with Ruby's object model, and finding ways to mitigate it…combined with a highly normative culture.

6:47 sdegutis: devn: some people are Rubyists at heart

6:47 devn: maybe because a lot of it is unecessary and indicative of poor design

6:47 ddellacosta: fair assessment i think

6:47 sdegutis: At 8th Light they trained us in the ways of TDD before we were put on client projects.

6:48 devn: Rubyist at heart seems to mean a lot of copying and pasting for a living

6:48 ddellacosta: danlentz: kind of agree re: making tests into English. Breaks down quickly

6:48 sdegutis: They've got like 45 programmers now.

6:48 (Including apprentices.)

6:48 ddellacosta: sdegutis: it's probably helpful in some ways, but people also need to be able to develop outside of that paradigm.

6:49 devn: you can train TDD all day, but in my experience there is careful assesment that ought to take place with each line written in a changeset

6:49 sdegutis: ddellacosta: I'll withhold my opinion on TDD for now.

6:49 ddellacosta: sdegutis: damn, that sounds like there's something interesting there though...

6:49 devn: "do i care about testing this? what is the value? is this exercised elsewhere?" etc.

6:49 sdegutis: devn: I've found TDD leads to an alternative to that approach.

6:50 danlentz: there are some nice CL facilities that allow contract-driven development -- it is a very useful supplement/alternative to legions of small tests that must be independently written and maintained.

6:50 ddellacosta: devn, sdegutis: I think that TDD can provide some of the same benefits to that careful assessment. They are different methods for providing the same kind of focus on the problem at hand, if you are doing them right

6:50 sdegutis: Also I should stop communicating right now. Nothing's coming out right.

6:50 ddellacosta: sdegutis: I thought that last statement was right on

6:50 (with caveats)

6:50 devn: sdegutis: i work at a TDD shop, but im about producing value first and foremost. value is a careful balance of maintainability, performance, and verifiability

6:50 ddellacosta: most def

6:50 sdegutis: ddellacosta: I meant that in practice, I've seen that TDD often seems to lead people away from the aforementioned approach.

6:51 danlentz: the idea comes from eiffel, but the cl implementation is really seamlessly integrated into the generic function metaclasses and is pleasant to use

6:51 sdegutis: (inc devn)

6:51 lazybot: ⇒ 9

6:51 ddellacosta: sdegutis: oooh, whoops. haha

6:51 sdegutis: devn: where?

6:51 danlentz: in Clojure we have :pre and :post methinks

6:51 devn: I think Rich hit a nail on the head with his design, performance, and composition talk

6:51 ddellacosta: um, so, what is the inc <handle> thing? I'm embarrassed to say I still don't get it.

6:51 devn: loved that one

6:51 sdegutis: ddellacosta: on IRC it's convention to do this when devn makes a good point:

6:52 devn++

6:52 ddellacosta: devn: as a music guy originally with a special love for Coltrane though, I was a bit biased I think

6:52 sdegutis: ddellacosta: but that's C/C++ style, and we're Clojure

6:52 ddellacosta: sdegutis: gotcha! thanks.

6:52 devn: there's really a failure on lots of ruby projects where people lean on their iterative TDD testing strategy to provide insight into the larger design

6:52 it rarely bears fruit though

6:52 ddellacosta: (inc devn)

6:52 lazybot: ⇒ 10

6:52 ddellacosta: got it.

6:52 ;-)

6:52 sdegutis: ddellacosta: also Raynes and amalloy_ et al. made clojurebot actually keep karma

6:52 $karma devn

6:52 lazybot: devn has karma 10.

6:53 sdegutis: (inc devn)

6:53 lazybot: ⇒ 11

6:53 devn: heh

6:53 sdegutis: er I mean lazybot

6:53 ddellacosta: huh, I think I probably have 0

6:53 $karma ddellacosta

6:53 lazybot: ddellacosta has karma 0.

6:53 ddellacosta: heh

6:53 sdegutis: $karma sd

6:53 lazybot: sd has karma 0.

6:53 sdegutis: $karma sdegutis

6:53 lazybot: sdegutis has karma 1.

6:53 sdegutis: Oh nice.

6:53 $karma futile

6:53 lazybot: futile has karma 2.

6:53 sdegutis: Heh.

6:53 devn: anyway, i am not trying to hate on ruby, but the culture there, while it might be "more focused on testing" is broken

6:53 the tests are to prevent stupid ideas from creeping in

6:54 danlentz: its called quid-quo-pro IIRC

6:54 devn: that's easy if you just..you know..sit down and think about what you're trying to accomplish

6:54 danlentz: quid-pro-quo rather

6:54 sdegutis: devn: I'll say that I agree that there are some cultural issues that lead to technical issues in the broader technical community as well as some subcommunities.

6:55 devn: sdegutis: there are issues with this in every community

6:55 ddellacosta: argh, now I have to figure out how to call a javascript function generated by coffeescript in clojurescript. WTF

6:56 devn: im just very much against calling the ruby community "exemplary"

6:56 it's a total lie

6:56 sdegutis: devn: wait who says that?

6:56 devn: oh, this is going back to marick's tweet the other day

6:56 ddellacosta: devn: link?

6:56 sdegutis: Oh. He's *in* the Ruby community. That doesn't count.

6:56 devn: he claimed that ruby's testing culture was "strong" or some nonsense

6:56 ddellacosta: ah, gotta run. Ya'll take care.

6:57 devn: ddellacosta: ciao

6:57 sdegutis: well, so am i

6:57 sdegutis: ddellacosta: cya

6:57 devn: but i have the sense not to make such a blanket assertion

6:57 sdegutis: You have to dismiss an active member of a community's opinion of that community.

6:57 danlentz: devn: well thats what happens when the barrier-to-entry means of assessing the value of a particular language is followed to the extreme

6:58 devn: danlentz: well said

6:58 sdegutis: devn: or maybe it's just blanket statements that we all know to dismiss.

6:58 cmdrdats: is there a better way to tranform a hashmap's values than something like (into {} (map (fn [[k v]] {k (f v)}) m))?

6:58 devn: sdegutis: if there's some kind of subliminal message or hidden "juicing" in order to get a rise and spark a discussion

6:59 i find that distasteful

6:59 sdegutis: devn: did you say that to him on twitter?

6:59 devn: come to think of it, no

6:59 sdegutis: cmdrdats: that's the best way I know of

6:59 devn: try it

6:59 cmdrdats: actually yeah, use for instead

7:00 devn: sdegutis: he will reply either with something profound and topc-shifting

7:00 cmdrdats: sdegutis: (into {} (for [k v] {k (f v)})) ?

7:00 devn: topic*

7:00 sdegutis: cmdrdats: (into {} (for [[k v] m] [k (f v)]))

7:00 devn: or it will be an affirmation that i am correct, with no plan to change

7:00 maybe the solution here is to just not follow him

7:00 eureka.

7:01 sdegutis: devn: I just plain don't have a twitter anymore.

7:01 devn: So you know where I stand on this issue.

7:01 cmdrdats: sdegutis: ah, lol - forgot the m :) It just bugs me that I'm first creating a whole list, and then pushing into a map

7:01 sdegutis: cmdrdats: it's what you'd be doing anyway, since it's an immutable lang

7:02 cmdrdats: but to be fair, it's not that inefficient, with structural sharing and all that

7:02 probably lightning fast too, compared to Ruby 1.8

7:02 *zing!*

7:02 devn: MRI

7:02 "Matz' Ruby Interpreter"

7:02 how do you ever convince people to use something named like that?

7:03 a weak argument, but... man, that' like saying DIHMIHB

7:03 Devn's Interpreter He Made In His Basement

7:03 sdegutis: devn: to be fair, nobody knows where Matz made that interpreter

7:04 devn: hahaha

7:04 sdegutis: devn: to be fair, Clojure is also a lame name compared to Lava

7:04 devn: Ruby 2.0 got a little bit better

7:04 sdegutis: (Lisp in Java)

7:04 devn: I'm just bored with Ruby. it's a big playground where you can do whatever you want.

7:04 cmdrdats: sdegutis: i suppose - I imagine (reduce (fn [a [k v]] (assoc a k (f v))) {} m) would be a bit more direct?

7:05 devn: Carmack's assertion that in any language, any and all syntactic variations in a sufficiently large codebase, will eventually find a home, seems correct

7:05 sdegutis: devn: it's an easy way to shoot yourself in the foot and not realize you're bleeding perfusely until after about 6 months

7:05 devn: Clojure makes it harder

7:05 because the blood is real

7:06 cmdrdats: (time (doseq [x (range 1000000)] (hmap #(+ 10 %) {:n1 10 :n2 20 :n3 30})))

7:06 "Elapsed time: 2838.800182 msecs"

7:06 (time (doseq [x (range 1000000)] (hmap2 #(+ 10 %) {:n1 10 :n2 20 :n3 30})))

7:06 sdegutis: *and* to think you're a huge success during those 6 months and even move on to "bigger and better" opportunities

7:06 cmdrdats: "Elapsed time: 811.519061 msecs"

7:06 hmap2 = reduce version

7:07 devn: sdegutis: yeah, totally true

7:07 ive seen this a lot

7:07 it's not a language thing, it's a people thing

7:07 there needs to be a consistent amount of doubt cast on whatever has been done to-date

7:07 not so much that it's toxic

7:08 a healthy amount

7:08 sdegutis: Welp, about to pass out.

7:08 Gotta finish this string tokenizer.

7:08 devn: sdegutis: cheers

7:08 sdegutis: Then pass out.

7:08 TEttinger: sdegutis, more complex than clojure.string/split ?

7:08 sdegutis: TEttinger: kinda

7:08 devn: ["Then", "pass", "out", "."]

7:09 sdegutis: [\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]

7:09 (f that) => 11

7:10 Gimme f.

7:10 clgv: cmdrdats: better use criterium for a thorough measurement

7:11 TEttinger: ##(filter (partial not= "") (clojure.string/split "Then pass out." #"\b\s?"))

7:11 lazybot: ⇒ ("Then" "pass" "out" ".")

7:11 cmdrdats: clgv: thanks - i'll do that

7:12 sdegutis: or: (f [\" \a \\ \" \b \" \c]) => 6

7:12 What's f? :)

7:12 clgv: cmdrdats: pro tip: put criteroium in your user profile in ~/.lein/profiles.clj ;)

7:13 cmdrdats: clgv: haha, thanks - good idea :)

7:13 TEttinger: sdegutis, I have no idea what that is supposed to do

7:13 sdegutis: Look for the second non-escaped double-quote and tell me what position it's at.

7:14 (first one is always at index 0)

7:14 TEttinger: isn't there a find function for sequences?

7:15 sdegutis: I should hope so.

7:18 TEttinger: ##(second (keep-indexed #(if (= %2 "\"") %1) [\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]))

7:18 lazybot: ⇒ nil

7:18 TEttinger: hm

7:18 ##(second (keep-indexed #(if (= %2 \") %1) [\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]))

7:18 lazybot: ⇒ 5

7:18 TEttinger: sdegutis, does that do the trick?

7:18 sdegutis: :D

7:19 Thanks TEttinger.

7:19 TEttinger: no prob, glad to help

7:20 sdegutis: Phew, my lexer is done.

7:21 With many thanks to #clojure

7:21 (inc #clojure)

7:21 lazybot: ⇒ 6

7:25 * clgv prefers (when x y) over (if x y)

7:28 cmdrdats: clgv: criterium is awesome :) the reduce version is still somewhat faster

7:29 clgv: cmdrdats: which two versions did you compare? I did not read that before.

7:29 cmdrdats: (into {} (for [[k v] m] [k (f v)])) vs (reduce (fn [a [k v]] (assoc a k (f v))) {} m)

7:29 clgv: cmdrdats: you should try out reduce-kv

7:30 cmdrdats: and transients of course

7:31 cmdrdats: try that one (persistent! (reduce-kv (fn [a k v] (assoc a k (f v))) (transient {}) m))

7:32 cmdrdats: hmm

7:32 ClassCastException clojure.lang.PersistentArrayMap$TransientArrayMap cannot be cast to clojure.lang.Associative clojure.lang.RT.assoc (RT.java:702)

7:32 seems a bit odd :P

7:33 busy sampling wihout transient for now, I imagine there should be a bit of a speedup using reduce-kv, thanks :D

7:34 clgv: oh sorry. try assoc!

7:34 cmdrdats: try that one (persistent! (reduce-kv (fn [a k v] (assoc! a k (f v))) (transient {}) m))

7:34 cmdrdats: aha, of course xD

7:35 Execution time mean : 2.509337 µs for the into {} version

7:35 clgv: cmdrdats: happens to me in 50% of the cases where I switch to transients ;)

7:35 cmdrdats: Execution time mean : 802.129138 ns for normal reduce

7:35 hehe

7:35 Execution time mean : 343.686788 ns fore reduce-kv

7:36 still sampling the transient version

7:36 Execution time mean : 408.096108 ns transient

7:36 clgv: huh? how big is your map?

7:37 cmdrdats: oh, in this case, tiny

7:37 there's a lot of them

7:39 clgv: usually transients pay off starting from a suprisingly small number of elements

7:40 TEttinger: clgv, I wasn't sure if when returns nil for false conditions

7:40 cmdrdats: clgv: I'll try slightly bigger maps

7:40 clgv: cmdrdats: I tried with 10 k-v-pairs

7:41 cmdrdats: i tried with 3

7:41 :P

7:42 clgv: non-transient 4.155826 us vs transient 3.225121 us

7:44 cmdrdats: non-transient 2.604713 ms vs transient 978.255599 µs

7:44 hhenkel: Hmm, calling (map keyword (clojure.string/split .....)) seems to give me clojure.lang.LazySeq which can't be processed with "get-in". Is my assumption correct?

7:44 cmdrdats: for maps with 5000 k-v's

7:45 hhenkel: ye - get-in works through vectors, but not lists

7:45 ordnungswidrig: hhenkel: get-in is only for assocs

7:45 vectors are associative, lists are not

7:46 hhenkel: you can use nth

7:46 clgv: cmdrdats: `into` uses transients under the hood where possible

7:47 cmdrdats: clgv: cool, but it still needs the overhead of some kind of transformed list of k-v pairs

7:47 clgv: that's where my intuition says it's slower

7:47 hhenkel: cmdrdats: ordnungswidrig: okay, so how to translate the list to a vector then? I don't understand how nth would help me here?

7:47 clgv: cmdrdats: in your case you had a lazy-seq and the overhead of the k-v-pairs and destructuring

7:48 ordnungswidrig: ,(nth '(1 2 3 4 5) 4)

7:48 clojurebot: 5

7:48 hhenkel: Or is it better to use something different then map?

7:48 cmdrdats: clgv: ye

7:48 hhenkel: you can (vec (map …)) if you really need to use get-in

7:48 ordnungswidrig: hhenkel: ,(nth (map keyword ["foo" "bar" "baz"]) 2)

7:49 ,(nth (map keyword ["foo" "bar" "baz"]) 2)

7:49 clojurebot: :baz

7:49 cmdrdats: ~botsnack

7:49 clojurebot: botsnack is newline

7:50 hhenkel: ordnungswidrig: my idea was to split a string and use the parts I get as keywords to look something up with get-in.

7:51 cmdrdats: clgv: thanks for your help :)

7:51 hhenkel: I see how vec would help me there but I don't get it how returning one specific value with "nth" would help me here.

7:51 ordnungswidrig: what is the "key" for lockup? An numerical index?

7:52 hhenkel: ordnungswidrig: it is a keyword in a nested datastructure (tree with keys (keywords) and values (string or longs)

7:52 clgv: cmdrdats: your welcome

7:53 *are ;)

7:53 ordnungswidrig: hhenkel: where does (map keyword ...) into play?

7:56 hhenkel: ordnungswidrig: I got a string somewhere in the tree, it is something like ${level1.level2.value12} and points to a value in the same tree. I want to fetch it and replace the "variable string" with the actual values.

7:57 ordnungswidrig: therefore I split strings that match that form at the dot and then use "map keyword" to use these parts to address the keywords.

7:57 I thought it would be a good idea to "translate" the strings to keywords.

7:58 ordnungswidrig: hhenkel: ah, so you need (get-in tree (map keyword (split ...)))

7:58 hhenkel: so the described "variable" points to something like {:level1 {:level2 {:value12 "Test-Text"}}} for example.

7:59 ordnungswidrig: yes, I got (get-in collection (map keyword (clojure.string/split (clojure.string/replace variable-string #"\$\{(.*)\}" "$1") #"\."))))

8:00 ordnungswidrig: like that, yes.

8:01 hhenkel: But it allways gives me nil or a null pointer exception and I don't fully understand why not the "real" value is set.

8:01 ordnungswidrig: is collection a sequence or a map?

8:02 hhenkel: map

8:03 ordnungswidrig: hhenkel: do you know how to use trace?

8:03 hhenkel: I think that would be helpful here

8:03 hhenkel: I first thought the variable points to the wrong part and the actual value is not found but I tested that and it seems to work. I tried to catch the exception....

8:03 ordnungswidrig: Nope, but I'm willing to learn.

8:04 ordnungswidrig: hhenkel: second, how do you want to handle transient dependencies? like {:a "${b}" :b "${c}" :c "foo"}?

8:04 hhenkel: ordnungswidrig: Any docs you recommend? Or a short introduction?

8:04 ordnungswidrig: https://github.com/clojure/tools.trace

8:04 wrap any form with (trace) and get some nice trace output, like (get-in collection (trace "keys" (map keyword (split ...))))

8:05 so you can see the intermediate results

8:05 hhenkel: ordnungswidrig: currently I just ignore them...in the longterm maybe multiple runns.

8:05 hyPiRion: What is #"\$\{(.*)\}" supposed to match, anyway?

8:05 Anderkent: hhenkel: I'd assume your splitting is wrong :)

8:05 hyPiRion: oh derp.

8:06 Anderkent: because the get should work

8:06 hyPiRion: This is why I need coffee in the morning.

8:06 Anderkent: ,(get-in {:a {:b {:c :d}}} (map keyword ["a" "b" "c"]))

8:06 clojurebot: :d

8:07 hyPiRion: oh riiight

8:07 hhenkel: ##(clojure.string/replace "${a}.${b}.${c}" #"\$\{(.*)\}" "$1")

8:07 lazybot: ⇒ "a}.${b}.${c"

8:07 hyPiRion: versus ##(clojure.string/replace "${a}.${b}.${c}" #"\$\{(.*?)\}" "$1")

8:07 lazybot: ⇒ "a.b.c"

8:08 * hyPiRion leaves.

8:08 hyPiRion: I make no sense today, ignore me for 15 minutes

8:08 hhenkel: hyPiRion: plan is to have only ${test.test1}

8:09 hyPiRion: yeah, I realized in hindsight

8:11 ordnungswidrig: hhenkel: (if-let [path (re-matches #"\${.*}" expr)] (get-in collection (map keyword (clojure.string/split path #"\."))))

8:11 hhenkel: ordnungswidrig: trace is really helpful....seems like it is working as expected...

8:11 Anderkent: hhenkel: I'd expect you're getting back a nil because the keyword chain does not exist in the map

8:11 ordnungswidrig: hhenkel: aah, add path as else clause

8:11 Anderkent: but it's hard to say without seeing all of your code

8:11 ordnungswidrig: (if-let [path (re-matches #"\${.*}" expr)] (get-in collection (map keyword (clojure.string/split path #"\."))) expr)

8:12 so the expr is returned unless the re matches

8:12 hhenkel: TRACE keys: {:cycle 3600, :action "read", :mbean "java.lang:type=OperatingSystem", :attribute "FreeSwapSpaceSize", :option "ignoreErrors=true"}

8:12 Anderkent: you want .+

8:12 hhenkel: Is what I get when I add trace in front of the get-in

8:12 Anderkent: right, and what's the string you're trying to look up?

8:12 ${cycle} or sth like that?

8:13 wait, that trace is your collection, not the keys, right?

8:14 hhenkel: Anderkent: Nope, that is the actual result. I would like to replace the string value with all of that if possible. There are two possible cases string replaced by string or string replaced by datastructure.

8:15 Anderkent: actually it is result not collection or keys, by accident I putted it up in front and forget to rename it - and was surprised seeing the values I was looking for.

8:15 Anderkent: right, so it seems that bit is working

8:16 this will be much easier if you post your code to refheap with an example of what gives you nil/npe

8:18 hhenkel: https://www.refheap.com/18356 contains the whole mess... ;)

8:20 fredyr: ,(keyword (str '- (aget (Character/toChars 80) 0)))

8:20 clojurebot: :-P

8:21 Anderkent: hhenkel: right, you can't use clojure.string/replace with non-string values

8:21 ,(clojure.stirng/replace "foo" "f" {:a 1})

8:21 sheldonh: does clojure have a fold function?

8:21 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.stirng>

8:21 Anderkent: ,(clojure.string/replace "foo" "f" {:a 1})

8:21 clojurebot: #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.CharSequence>

8:22 Anderkent: ,(clojure.string/replace "foo" #"f" {:a 1})

8:22 clojurebot: #<NullPointerException java.lang.NullPointerException>

8:22 Anderkent: you just want to return (get-value collection %) instead of putting it to clojure.string/replace

8:23 sheldonh: reduce is foldl I think

8:23 hhenkel: Anderkent: I get a NullPointerException java.util.regex.Matcher.quoteReplacement

8:23 Anderkent: hhenkel: as I said. (clojure.string/replace % ... (get-value ...)) makes no sense

8:24 hhenkel: I'll test with just returning...

8:24 Anderkent: clojure.string/replace is for replacing parts of a string with something else, you just want to return the new object instead of the original stirng

8:24 and of course you must return the old one if you're not changing it

8:25 sheldonh: also, reducers have fold, and it's potentially parallel

8:26 it's a little different than reduce

8:28 hhenkel: Anderkent: you're right...now it works...seems like I'm still to much into "altering defined variables" instead of having functions returning the right stuff...

8:30 Anderkent: hhenkel: yes, you can't alter anything in clojure :) clojure.stirng/replace also doesnt alter anything, just gives you a new string back

8:30 (well ok, the you can't alter anyhting is not *quite* true)

8:30 the walk function already does the 'replacing' for you, that's why you have to return the original value if you dont want to replace anything

8:35 sheldonh: Anderkent: hmmm. maybe not fold. i want to traverse a list with a function that takes successive pairs of elements, returning the first logical true value

8:36 definitely not fold :)

8:37 Anderkent: is that 'takes a vector of 2 elements' or 'takes 2 arguments'?

8:39 for the first, you want (some my-condition-fn (partition my-collection 2 1))

8:39 sheldonh: Anderkent: i could live with either (it's a cheap transform). if filter is lazy and first is lazy, then it's just a partition

8:40 first calls seq on its argument. that means it doesn't defeat laziness, right?

8:40 Anderkent: for the second it's more like (first (filter identity (map my-fn collection (next collection))))

8:40 seq realizes lazyseqs

8:41 sheldonh: oh dear

8:41 that's crazy. how do i get the head of a lazy sequence without realizing it?

8:41 Anderkent: sosrry, I mean seq realizes the first element

8:42 sheldonh: phew

8:42 Anderkent: ,(let [foo (take 5 (repeatedly #(do (println "boo") 1)))] (println "foo") (let [bar (seq foo)] (println "bar")))

8:43 clojurebot: foo\nboo\nbar\n

8:43 Anderkent: that's less useful than it was in my head ;_;

8:43 sheldonh: Anderkent: okay, then all is well. not exactly what i asked, but https://www.refheap.com/18357

8:43 Anderkent: you just described everything i ever typed :)

8:43 Anderkent: argh

8:44 sheldonh: Anderkent: that's always what you want to hear after a crack a 4clojure. "argh" :)

8:44 Anderkent: i think you just want to use reduce there :P enumerating all subsequences is... suboptimal

8:44 :P

8:45 sheldonh: Anderkent: i deleted (i think) 3 reduce-based attempts. maybe after a break :)

8:45 Anderkent: the basic algorithm shuold be: for each element, if it's larger than previous one, append it to 'current subseq'. If not, check if 'current subseq' is longer then 'longest seen subseq', if so save it as longest seen subseq

8:45 clgv: Anderkent: but gets a good golfing score ;)

8:45 Anderkent: alternatively

8:45 take it in two steps

8:45 first, split it into increasing subsequences

8:45 then find which one is longest

8:46 obviously they can't overlap, so this should be simple

8:46 sheldonh: i thought that's what my for/partition did

8:46 Anderkent: no, you generate all subsequences then check which of them are increasing

8:47 sheldonh: that is true. i was hoping, though, that since i start with the longest subsequence, i would only test for increasingness (and so realize) as many as absolutely necessary

8:48 anyway, it felt like a reduce problem when i started, and i should totally take another shot at it once my circulation returns to normal :)

8:49 "what do i do if i come up nil?" was a smell. it should have taken me back to the initial value for reduce (since 4clojure wants [], not nil)

8:53 Anderkent: the real pig in that exercise is that the minimum eligible subsequence length is 2

8:59 clgv: sheldonh: ##(or nil [])

8:59 lazybot: ⇒ []

8:59 clgv: ;)

9:03 sheldonh: clgv: yeah, that's what i did. but usually when i have to do that at the outermost layer, my design sucks :)

9:03 Anderkent: tbh I think the nicest solution to this is either reduce or loop/recur

9:04 clgv: well 4clojure encourages code golfing ;)

9:05 that way you'll often end up with solutions you should not use in projects

9:05 Anderkent: I'm not familar with that term

9:05 clgv: "trying to get the smallest solution in terms of character count"

9:06 Anderkent: ah

9:06 I went the opposite direction

9:06 clgv: there is a chart where you can see where your solution landed after you completed the excercise

9:06 Anderkent: 'write a solution that's actually easy to understand' :P

9:06 clgv: shortest runtime would be a nice contest as well

9:06 sheldonh: i start with "write a solution that goes green". that is usually enough of an achievement :)

9:07 clgv: too many people already have all solutions solved. I didnt do 4clojure since a long time and almost dropped out of the top100...

9:10 borkdude: How can I turn of the fancy f displaying in emacs?

9:10 for example, it displays incorrectly when I type #_

9:11 Anderkent: (remove-hook 'clojure-mode-hook 'esk-pretty-fn)

9:11 says stack overflow

9:23 mathiasp: Hi all, I'm trying to use shoreleave-remote with a non-default uri inside a go block. Sadly, rebinding shoreleave.remotes.http-rpc/*remote-uri* shows no effect inside a go block - it works just fine outside it. See my small experiment here https://gist.github.com/mathiasp/6448753 The call to shoreleave in line 45 succeeds, the one in line 32 tries in vain to reach the standard /_shoreleave url. Any ideas how I can further investigate this?

9:23 I'm a clojure novice, so maybe, hopefully I've forgotten something simple?

9:26 TEttinger: mathiasp, it's an unfortunate time of day right now, but soon people will be more active I think. has to do with time zones.

9:26 Anderkent: mathiasp: looking at it, but don't get your hopes up :)

9:26 mathiasp: TEttingen, thanks, I assumed so, it's not really urgent. Thanks for looking!

9:27 clgv: mathiasp: that's because your `binding` exist only when you define those functions in its body and not at runtime

9:28 Anderkent: clgv: well, the go should run within the binding

9:28 clgv: mathiasp: "runtime" = when your functions are called

9:28 oh the `go` is not in the function?

9:28 sheldonh: bwahahahaha! i just evalled my code to examine the data structure my first stab produces, and it turns out the function's done!

9:28 Anderkent: yeah it's a top level loop afaik

9:28 clgv: is that on purpose?

9:29 the other rpc call is in a function

9:29 ToxicFrog: Aren't dynamic (binding)s threadlocal?

9:29 Anderkent: I believe it's just ment to be a continuously running listener

9:30 ToxicFrog: yes, but core.async carries your bindings with you

9:30 ToxicFrog: Aah.

9:30 clgv: I'd rewrite that with a startup function...

9:30 ToxicFrog: Oh, and this is cljs. I've got nothing.

9:30 clgv: ToxicFrog: threadlocal bindings are inherited to child threads as initial values

9:31 oh right. no idea if there is some non-standards cljs-thing at work^^

9:31 Anderkent: https://www.refheap.com/18359 seems to imply the bindings work

9:31 but don't know about cljs obviously

9:31 julienXX: Hi I'm having trouble with something really trivial. I'd like to replace the first "[" in a string with "\[". What would be the best way to do it?

9:32 str/replace complains with "Unsupported escape character: \["

9:32 Anderkent: julienXX: you need to escape the backslash, i.e. "\\["

9:32 clgv: julienXX: "\\"

9:33 Anderkent: hm

9:33 actually

9:33 doesn't seem to work the way I thought it would

9:33 ouch, painful

9:34 julienXX: Anderkent clgv thanks!

9:34 Anderkent: ,(print (clojure.string/replace "foo[bar" #"\[" (clojure.string/re-quote-replacement "\\[")))

9:34 clojurebot: foo\[bar

9:34 Anderkent: ,(print (clojure.string/replace "foo[bar" #"\[" #"\\\["))

9:34 clojurebot: #<ClassCastException java.lang.ClassCastException: java.util.regex.Pattern cannot be cast to clojure.lang.IFn>

9:34 Anderkent: hm oups

9:35 ,(print (clojure.string/replace "foo[bar" #"\[" "\\\\["))

9:35 clojurebot: foo\[bar

9:35 Anderkent: right

9:36 that's... pretty awful

9:44 mathiasp: sorry, no idea. If you can reduce it to a minimal example (one dynamic variable being bound in different places, I assume) that doesn't work on cljs, you could check if it also doesnt work in normal clojure

9:45 if it does work, it's a cljs async bug, otherwise it might be something in your code

9:47 mathiasp: clgv, Anderkent, ToxicFrog: thanks for the ideas, I created a function making the rpc insde the binding, and called that within the go block, now it works fine.

9:47 I have no idea why, though ;)

9:49 clgv: mathiasp: having a start funciton for that `go` block is cleaner anyway

9:50 mathiasp: clgv: I really don't know what you mean by the start function for the go block...

9:51 clgv: mathiasp: oh, I misread you. you just moved binding and rpc into the function...

9:51 mathiasp: jep

9:52 clgv: and it's ok for now, this will probably be throwaway code, running just for a few days or so. Good enough for now. Again, thanks!

10:02 cglv: if you thought of something like this, it still doesn't work. And just for my understanding of go blocks: this should work, shouldn't it? https://gist.github.com/mathiasp/6450181

10:03 clgv: mathiasp: well maybe bindings in cljs work differently with go blocks or there is a bug

10:03 Anderkent: mathiasp: can you make an example that just prints from a dynamic variable? It's hard to tell because we don't know what srm does.

10:03 clgv: mathiasp: might be worth a mailing list post

10:04 mathiasp: clgv: ok, will do

10:06 Anderkent: mathiasp: does https://www.refheap.com/18361 work for you?

10:11 gdev: ,(let [slash (char-escape-string \\) re-bracket #"\[" ] (print (clojure.string/replace "foo[bar" re-bracket (str slash "\["))))

10:11 clojurebot: #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \[>

10:11 gdev: ,(let [slash (char-escape-string \\) re-bracket #"\[" ] (print (clojure.string/replace "foo[bar" re-bracket (str slash \[))))

10:11 clojurebot: foo\[bar

10:17 gdev: ,(let [slash (char-escape-string \\) re-bracket #"\[" bracket \[ target "foo[bar" replacement (str slash bracket)] (print (clojure.string/replace target re-bracket replacement)))

10:17 clojurebot: foo\[bar

10:17 gdev: well that was a fun little exercise

10:20 I've been trying to convert Sussman's scheme code to Clojure all morning so a string replace problem was a lot easier

10:23 mathiasp: clgv: very funny, even though I've refer'd it, I get [15:57:35.070] TypeError: cljs.core.async._GT__BANG__BANG_ is undefined @ http://localhost:8080/opnenablement/javascripts/opnenablement.js:31887

10:24 Anderkent: >31887

10:24 :D

10:24 :D

10:24 mathiasp: clgv: I have to go now, will look into this later...

11:00 no7hing: what am i doing wrong when (map #(str "A" %) (range 1 (:a entry))) gets serialised as lazyseq when spitting to a file? doall didn't help..

11:01 sdegutis: no7hing: map is lazy.

11:01 ,(doc map)

11:01 clojurebot: "([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & ...]); Returns a lazy sequence consisting of the result of applying f to the set of first items of each coll, followed by applying f to the set of second items in each coll, until any one of the colls is exhausted. Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments."

11:01 sdegutis: no7hing: You have to realize it via doall, but a better solution is to just use doseq.

11:01 no7hing: doesn't do all force it?

11:01 sdegutis: ,(doc doseq)

11:01 clojurebot: "([seq-exprs & body]); Repeatedly executes body (presumably for side-effects) with bindings and filtering as provided by \"for\". Does not retain the head of the sequence. Returns nil."

11:02 sdegutis: Actually let me stop giving advice, I have a baby in my lap that's kicking my desk and shaking things, and that's distracting enough to let me give wrong answers.

11:02 clgv: no7hing: what is your goal?

11:02 hyPiRion: no7hing: use pr-str instead of str

11:03 no7hing: i want a list of strings that then get used in a (format "…" ..)

11:03 ah

11:03 mathiasp: Anderkent, cglv: the test case does not work (e.g. shows OUPS BAD ASYNC). I've put this on the mailing list.

11:03 sandbags: afternoon

11:03 hyPiRion: you can also wrap it in a `(seq ...)` before str-ing it

11:05 clgv: no7hing: example function call and expected output?

11:12 no7hing: kind of embarrassing but the seq was wrapped in another seq as there was still a left-over '&' in the function arguments

11:12 thanks for helping

11:33 sdegutis: Given [\a \b \c] what's an efficient way to create a string from it?

11:33 I bet there's something smarter than (apply str coll).

11:35 clgv: sdegutis: (apply str coll) is pretty good since it uses stringbuilder internally which is the fastest way to build strings on the jvm

11:35 sdegutis: clgv: oh nice :)

11:38 Thans

11:38 Thanks

11:38 clgv: np

11:44 sdegutis: Whoa, the JVM must be doing cool stuff, cuz when I run my benchmarks multiple times in a row, it goes from 9msec to 3msec in about 5 iterations and stays at 3msec pretty consistently thereafter.

11:44 rigger: yeah, called warming up the vm

11:45 sdegutis: Ah I've heard of that.

11:45 rigger: JIT

11:46 gdev: the JVM runs on diesel

11:46 rigger: http://4groundtechsolutions.com/jvm-warmup/

11:46 sdegutis: My only experience with Java or JVM before using Clojure was ranting that Java's stupid and Ruby's better.

11:47 gdev: sdegutis, common mistake lumping the language and the VM in the same basket

11:47 hhenkel: There is a reason why the call it hotspot jvm...

11:47 nDuff: sdegutis: Heh. Whereas I've seen folks using Ruby in large-scale production abandon it for Erlang due to issues with the Ruby VM.

11:48 sdegutis: nDuff: :D

11:48 nDuff: Elixir?

11:48 nDuff: sdegutis: Opscode's big rewrite of the Chef server for 0.11

11:48 sdegutis: That'd seem less random :)

11:48 nDuff: ah

11:48 We're using Chef. But I've heard good things about ansible, have to look into it..

11:49 Ok time to do some premature optimization.

11:49 I bet (partition 2 1 [:end] string) is probably much slower than just using loop/recur with an index.

11:52 callen: sdegutis: you're supposed to use things like criterium for benchmarking for a reason.

11:52 it warms the JIT and is very meticulous about it in order to get accurate benchmarks.

11:52 sdegutis: callen: Oh. Nice. I'll look into that.

11:53 Yep looks perfect. Thanks callen.

11:55 gdev: dgrnbrg, saw your talk on piplin, looks interesting

11:55 rigger: url?

11:55 clojurebot: something

11:56 clgv: &(let [... 42] ...)

11:56 lazybot: java.lang.ClassFormatError: Illegal field name "..." in class sandbox91102$eval133977

11:56 hyPiRion: ,(let [… 42] …)

11:56 clojurebot: 42

11:56 clgv: but lazybot is right ;)

11:56 callen: rigger: http://www.infoq.com/presentations/piplin?utm_source=dlvr.it&utm_medium=twitter

11:56 rigger: thx

11:57 clgv: &(clojure-version)

11:57 lazybot: ⇒ "1.4.0"

11:57 callen: rigger: could always google.

11:57 clgv: ,(clojure-version)

11:57 clojurebot: "1.6.0-master-SNAPSHOT"

11:57 callen: because, you know, that's what I did.

11:57 clgv: ui

11:57 hyPiRion: clgv: psh

11:57 &(let [… 42] …)

11:57 lazybot: ⇒ 42

11:57 rigger: callen, not sure dgrnbrg piplin would have yielded much

11:57 xeqi: sdegutis: +1 for criterium when benchmarking. Also be careful of lein's default options for faster startup / less optimization

11:58 rigger: ah, nm, thanks anyway

11:58 clgv: hyPiRion: :P

11:58 callen: rigger: ...yeah...yeah it would've.

11:58 rigger: oh shit, this is cool

11:59 dgrnbrg: you work in the hardware industry?

11:59 researchmethodologist

11:59 hmm

11:59 * rigger reads bio

12:00 rigger: we wrote a dsl in python for describing memories

12:01 rasmusto: I need to try piplin, I said I would after I the talk...

12:01 But I ended up rolling my own libraries instead

12:04 Balveda: Where can I learn to engineer software using Clojure? I can't wrap my head around structuring a program in it yet

12:06 rigger: be curious to see how this scales against RTL

12:07 coventry: Balveda: Pick a project in a rough approximation to your problem domain, and read the source code for it. If you can't find anything related, the clojure source itself is pretty representative.

12:07 rkneufeld: Balveda: I'd say probably similarly to other disciplines: Read other people's functional software and practice.

12:07 coventry: As best I know the Clojure source itself is not always recommended reading for idiomatic Clojure. Tread with care ;)

12:08 Balveda: Coming from a Java/C++/C# background Clojure is so weird but it calls out to me.

12:08 Is that weird? Am I going nuts?

12:09 clgv: Balveda: books are a good start.

12:09 nDuff: Balveda: It takes a while to wrap your head around FP after spending that much time in OO land. It's well worth it, though.

12:09 Balveda: If you haven't read Joy of Clojure, I recommend it.

12:09 clgv: better start with "Clojure Programming" and then read "Joy of Clojure" after that ;)

12:09 hyPiRion: It's hard to program stuff in the beginning, but it comes easier with practise

12:10 it's not only a new language, you have all the different new concepts

12:10 sdegutis: xeqi: cool

12:10 dgrnbrg: rigger: hey!

12:10 sdegutis: Balveda: what about it calls out to you?

12:10 rigger: howdy

12:10 dgrnbrg: rigger: I work at a hedge fund, and in school and in the past I worked on hardware/low latency systems

12:11 coventry: Repeating my question from last night, anyone know why catch, finally and "&" have null entries in the clojure.lang.Compiler/specials dispatch map, and what that means for the analysis of those forms?

12:11 dgrnbrg: now, I'm doing large scale distributed systems

12:11 rigger: dgrnbrg: i'm a design tools guy at AMD

12:11 dgrnbrg: rigger: cool!

12:11 I have been thinking a lot about pipline recently

12:11 Balveda: It just seems right, sdegutis.

12:11 sdegutis: Balveda: why?

12:11 Balveda: or in what way?

12:11 dgrnbrg: since I used a model of time in piplin that makes sense for very low level abstractions

12:12 but I think that core.async is a great basis for concurrent hardware development

12:12 I've been designing the next version of piplin, that'll be even closer to clojure's semantics, because core.async makes modules better to express

12:12 Balveda: Hard to say. I guess the syntax, the REPL and potential to overcome everything else. And even tough I barely started I feel eventually one could be very productive, very quickly with it.

12:12 coventry: Oh, I get it now. They are all subordinate forms to other special forms, which handle them directly without the need for dispatch.

12:12 rigger: we "replaced" six guys writing skil code for memories with a python dsl and compiler

12:13 so the design engineers are now just constructing the design in the dsl, run it through the compiler (still generating skil), but saves a ton of time

12:14 dgrnbrg: that sounds awesome! is it myhdl, or something custom?

12:14 rigger: it's home grown

12:14 rasmusto: rigger: skil?

12:14 rigger: skill

12:14 from Cadence

12:15 very lispy

12:15 rasmusto: rigger: ah, will have to check it out.

12:15 sdegutis: Balveda: ah, cool, I know the feeling

12:16 Balveda: I'm going to be working in automatized QA so I want to incorporate the language, as well

12:17 I've been trying out clj-webdriver and it seems good, trying things out in the console is just a blast.

12:17 in the REPL, sorry. heh.

12:19 sdegutis: :)

12:19 Exciting times.

12:22 What's a fast way to find the first occurrence of a char that's not in a given set, within a string, starting at an index?

12:22 Like, given "abc " I want to find the index of the first non-alphanum char starting at 0 which would return 3

12:24 Maybe regex is the fastest way after all.

12:25 functionform: whoever dbyrne is (4clojure.com) thank you for blowing my mind. i'm always surprised at how much i learn from doing one of his "easy" problems

12:25 hyPiRion: ,(let [matcher (.matcher #"[^A-Za-z]" "abc ")] (if (.find matcher) (.start matcher)))

12:25 clojurebot: 3

12:26 hyPiRion: well, that was just alpha, you could probably guess how to add in nums

12:26 justin_smith: functionform: my theory is that David Byrne has given up pop-world-beat for computer science

12:26 hyPiRion: aren't there unicode friendly character classes?

12:27 hyPiRion: justin_smith: sure thing, I just randomly grabbed the thing I already knew

12:27 sdegutis: hyPiRion: ok then I'll stick with regex for now.

12:27 Thanks.

12:27 justin_smith: \w is "word constituent", should catch things like ü (had to look it up just now, but I knew it existed)

12:28 oh, never mind

12:28 ,(re-find #"\w" "ü")

12:28 clojurebot: nil

12:28 justin_smith: ,(re-find #"\w" "u")

12:28 clojurebot: "u"

12:29 justin_smith: maybe there is a locale setting that affects these things?

12:30 grandy: question: i want to take a map of keywords and regexes, and apply the regexes in succession to a long string, and return a map of the keywords to the parts of the string matched by each regex ... the reason for the ordered application of regexes is to remove ambiguity from the string... any recommendations for idiomatic clojure ways to write this ?

12:30 ToxicFrog: justin_smith: lua string library is not utf8 aware. You need a utf8 library.

12:30 justin_smith: ToxicFrog: lua?

12:30 ToxicFrog: Oh whoops

12:30 Got confused about what channel I'm in

12:30 mtp: grandy: that sounds like you actually want, like, a grammar.

12:31 instead of this kludgey regex contratption you're envisioning

12:31 hyPiRion: Yeah, that sounds like a task for instaparse

12:31 grandy: hmm

12:31 coventry: What does it mean when the symbol fn* has {:once true} in its metadata?

12:32 grandy: ok going to read up on instaparse :)

12:32 mtp: good idea :)

12:37 justin_smith: coventry: I thought maybe it was a defonce thing, but nope, defonce does not add :once to the metadata, at least not from the repl

12:37 technomancy: coventry: I think it means the return value is cached

12:40 justin_smith: an egrep -r in clojure core source finds the keyword used twice in such a context, as metadata to a clojure.lang.LazySeq object and a clojure.lang.Delay

12:43 fn.onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), Keyword.intern(null, "once"))); ... later fn.onceOnly gets used as the final arg to fn.compile


12:45 rasmusto: justin_smith: the docstrings in clojure.core imply that the result is cached after the first invokation. I'm not sure where the metadata fits into all of this

12:45 coventry: I don't fully understand it, but the last opcode generated by ObjExpr.emit when onceOnly is true puts something currently on the stack in a nonstatic field, which may be the caching technomancy is talking about. https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L4796

12:46 justin_smith: rasmusto: it seems like the metadata is what tells it to do this (if I understand what you are saying)

12:46 rasmusto: justin_smith: that's what it looks like, I don't know any more detail than that

12:47 justin_smith: I'm looking up fn* source atm

12:47 justin_smith: AFn.java?

12:48 never mind, clearly not that

12:48 rasmusto: justin_smith: it's always fun to look at the java source though :)

12:49 justin_smith: java conventions are weird

12:49 but then again, every non-lisp looks weird to me, so I guess that should be taken under advisement

12:52 rasmusto: justin_smith: I think I'm in over my head: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IFn.java

12:53 coventry: No, actually, that snippet is clearing the locals (sticking null in that field.) Still consistent with technomancy's interpretation, though I don't know where the caching is happening.

12:55 justin_smith: rasmusto: line 297: static public interface LOLOL

12:55 so apropriate :P

12:57 sdegutis: I can't imagine writing Ruby anymore. "else" and "end" seem so unnecessary now.

12:58 ToxicFrog: justin_smith: speaking as someone who is still in the lua headspace more than the clojure one most days - it's not just you, Java is full of spiders.

13:00 Raynes: sdegutis: I wrote some Haskell the other day. I can't imagine writing Clojure anymore. All the ( and ) seem so unnecessary now.

13:00 sdegutis: Raynes: you really feel that way?

13:00 Raynes: No.

13:00 ambrosebs_: lol

13:01 sdegutis: Oh.

13:01 mdrogalis: I kind of had a similar sarcastic though. The syntax is surface level

13:01 thought*

13:02 rasmusto: lisp has absolutely no syntax

13:03 callen: well that's clearly not true, but it's a cute thought.

13:03 sdegutis: ,(iinc 1)

13:03 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: iinc in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:03 technomancy: if that were true we would be writing our code in clojure.jvm.analyzer format

13:03 sdegutis: Is there a shorthand for (+ 2 i) ?

13:03 mdrogalis: Yeah uh, I'm gonna go get some coffee. Later.

13:03 technomancy: which is pretty hideous

13:03 sdegutis: commonly referred to as dinc, the elusive double-inc

13:03 callen: ##(inc (inc 1)) ##(+ 1 2)

13:03 lazybot: (inc (inc 1)) ⇒ 3

13:03 (+ 1 2) ⇒ 3

13:03 clojurebot: *suffusion of yellow*

13:03 sdegutis: ,(doc dinc)

13:03 clojurebot: Pardon?

13:03 sdegutis: heh

13:03 rasmusto: ,((comp inc inc) 1)

13:03 clojurebot: 3

13:03 sdegutis: :)

13:04 TimMc: sdegutis: He *said* it was elusive. :-P

13:04 sdegutis: I'll stick with + 2

13:04 TimMc: &((apply comp (repeat 2 inc)) 5)

13:04 lazybot: ⇒ 7

13:04 TimMc: sdegutis: ^ There's your shortcut.

13:05 rasmusto: ,(-> 1 inc inc inc inc)

13:05 clojurebot: 5

13:05 sdegutis: I was thinking more like: &(last (take 2 (iterate inc 4)))

13:05 ,(last (take 2 (iterate inc 4)))

13:05 clojurebot: 5

13:05 sdegutis: ,(last (take 3 (iterate inc 4)))

13:05 clojurebot: 6

13:05 sdegutis: Yeah that.

13:06 llasram: That's the *easy* way to use `iterate`: ##((second (iterate (partial comp inc) inc)) 1)

13:06 lazybot: ⇒ 3

13:06 callen: now just write a macro that checks for the number of "i"s in iiiiiinc to implement this.

13:06 sdegutis: I wonder if the "+1" function in Common Lisp was named +1 to make people who used it feel ashamed that they're trying to take shortcuts in an already-terse language.

13:06 (+1 i) ... (+ 1 i)

13:06 callen: (s iiiiiinc 5) => 11

13:07 yeah, should write that macro.

13:07 it'd complete the circle of time-wasting.

13:07 rasmusto: and a ddddddddddec one too

13:07 TimMc: (dwim (inc8 5)) => 13

13:08 sdegutis: Reminds me of my nomnomnom lib for Ruby: http://rubydoc.info/gems/omnomnom/0.0.1/frames

13:08 rasmusto: TimMc: haha, this is so pointless now

13:08 TimMc: ToxicFrog: And when you say "Java is full of spiders", I assume you mean this kind http://i.imgur.com/BVSvL7Q.jpg, not this kind: http://i.imgur.com/CZldxjjh.jpg

13:09 callen: Raynes: in honor of the channel's multi-segment namespace argument, my @work clojure project's namespace is ${PROJECT_NAME}.is.awesome

13:09 TimMc: both kind of terrifying.

13:09 Raynes: callen: Reasonable name.

13:10 bja: we went with #{COMPANY_NAME}.lib and #{COMPANY_NAME}.app (for the clj/cljs frontend app)

13:10 callen: I prefer to have more fun with it :)

13:11 bja: although also #{COMPANY_NAME}.storm

13:11 callen: my namespace is designed to brainwash users into liking it.


13:12 bja: my coworkers are still a little edgy about using code that we keep under CI because it either doesn't have a release or has very few releases

13:12 I just like getting notifications when changes happen in some of my libraries

13:12 third-party code that is

13:14 TimMc: callen: The second one looks like a Tachikoma.

13:16 callen: TimMc: I haven't seen that in ages.

13:24 rasmusto: justin_smith: ah, I get it now, LOLOL

13:29 sdegutis: Woo, just made my tokenizer 14x faster.

13:30 It's also more readable now.

13:33 callen: is there a better verb than canonicalize?

13:33 sdegutis: callen: intern, according to Java strings

13:33 llasram: canonize

13:33 sdegutis: What's a good way to get the first index of an element in coll that satisfies (f)?

13:33 callen: canonize is our winner so far.

13:33 intern is not it.

13:33 hyPiRion: (first (filter

13:33 sdegutis: It was a joke.

13:33 llasram: callen: Ha, I was joking

13:34 callen: I just want something less awkward/shorter

13:34 it's going to be a namespace unto itself.

13:34 rigger: http://piplin.deviantart.com/art/Archery-17657627

13:34 hyPiRion: callen: (def ffilter (comp first filter))

13:34 sdegutis: hyPiRion: that only gives the element. I was thinking of using that with a mapped coll zipped with (iterate inc 9(

13:34 *0)

13:34 hyPiRion: ops, wrong

13:34 llasram: c10n

13:35 Oops, c10e

13:35 There we go

13:35 callen: it would be nice if it was a little more readable too P

13:35 :P

13:35 hyPiRion: ah, right. There's no elegant way for that, you'd have to do some magic with map-indexed I suppose

13:36 rasmusto: what's wrong with 'some'?

13:36 sdegutis: rasmusto: how would you use it here?

13:36 rasmusto: it doesn't give the index

13:36 Right now I'm using recur to call fn on each element and return the index where fn passes.

13:37 rasmusto: (some (fn [[i v]] (if (pred v) [i v]) (map-indexed vector coll)) ... or something

13:37 xeqi: callen: awesomize

13:37 sdegutis: rasmusto: ah ok

13:37 rasmusto: I didn't proof read that btw

13:38 llasram: sdegutis: In the absence of something compact, I think a function using `recur` is pretty reasonable

13:38 sdegutis: llasram: okay, cool

13:38 thanks

13:38 technomancy: ~(doc keep-indexed)

13:38 clojurebot: excusez-moi

13:38 technomancy: ,(doc keep-indexed)

13:38 clojurebot: "([f coll]); Returns a lazy sequence of the non-nil results of (f index item). Note, this means false return values will be included. f must be free of side-effects."

13:39 technomancy: hrm

13:39 hyPiRion: sounds reasonable

13:39 xeqi: ,(doc filter-indexed)

13:39 clojurebot: It's greek to me.

13:39 xeqi: blah

13:39 llasram: Hmm, so like (first (keep-indexed (fn [i x] (when (pred? x) x)) coll))

13:39 Not bad

13:39 rasmusto: much nicer

13:39 llasram: well, with `i` for that last `x`

13:40 technomancy: except for the when

13:40 hyPiRion: and with if for the last when

13:40 technomancy: hyPiRion: o/

13:40 hyPiRion: \o

13:40 rasmusto: what's wrong with when? I've heard people say it's only used for side effects, but I don't get that

13:40 llasram: Eh. I prefer when even for non-side-effects, which I know puts me in the minority, but so there I stand :-p

13:40 rasmusto: is it the implicit do?

13:41 technomancy: rasmusto: yeah, and if does the job nicely in this case

13:41 rasmusto: technomancy: gotcha

13:41 technomancy: I don't believe the fact that you can omit `if`'s else arg is a design flaw, which seems to be implied by people who use `when` for the return value

13:41 sdegutis: Cool thanks technomancy and llasram

13:42 * sdegutis runs out of hot air

13:44 llasram: technomancy: That's fair. I think it's something I just need to get over. When I see `when` I think "returns nil when false," which isn't the first thing I think when I see an `if`

13:45 technomancy: variadic macros: how do they even work? =)

13:45 llasram: Yeah yeah :-p

13:52 ToxicFrog: TimMc: quite.

13:54 sdegutis: What's the auto-runner for Expectations?

13:56 Ah, https://github.com/jakemcc/lein-autoexpect

14:02 coventry: Where is the metadata shorthand (^{}) parsed?

14:03 clgv: for datomic is there a guide how to get fast queries? which constructions should be ommited?

14:04 coventry: Oh, LispReader.java, of course.

14:07 sdegutis: Which is preferred when using defrecord, (->Record) or (Record.)?

14:08 Is one more efficient than the other or something?

14:09 rigger: use the source, luke!

14:11 jkkramer: sdegutis: ->Record is easier to work with, since it's just a function and can be required as usual from other namespaces. for the latter, you have to import the class

14:11 clgv: are there no datomic users around right now?

14:11 sdegutis: Good point.

14:11 clgv: try #datomic

14:12 Oh you did.

14:12 clgv: same..

14:15 its pretty strange I do not manage to use my cpus up to 100% but I do not why

14:31 rasmusto: clgv: my code uses 6000% cpu

14:31 sdegutis: I'm slightly concerned that maybe I'm jumping to loop/recur too often now.

14:31 Then again, this is a parser. That's probably okay.

14:31 clgv: rasmusto: certainly not per cpu or your server is on fire now ;)

14:31 or per core to be more specific ;)

14:38 mklappstuhl: want to setup some database stuff that might change later, what are you guys using for migrations? or is there something conceptually different I didnt think of?

14:38 SegFaultAX: There are lots of migrations libraries available.

14:39 Migratus is a good place to start.

14:39 sdegutis: is (def foo 'foo) dumb?

14:39 mklappstuhl: found drift & lobos so far

14:39 SegFaultAX: mklappstuhl: Those are also things, yes.

14:40 sdegutis: mklappstuhl: I like technomancy's approach

14:40 SegFaultAX: mklappstuhl: Find the one that suits you. They are all functionally similar (as are most migration frameworks)

14:40 sdegutis: https://github.com/technomancy/syme/blob/master/src/syme/db.clj#L68-L125

14:40 mklappstuhl: sdegutis: what does that approach look like?

14:40 sdegutis: mklappstuhl: https://github.com/technomancy/syme/blob/master/src/syme/db.clj#L68-L125

14:40 SegFaultAX: sdegutis: Any particular reason you want to def a single symbol?

14:41 sdegutis: SegFaultAX: basically want to emulate C's enum, ie I want a unique value that only compares truly to itself and is fast to compare

14:42 * technomancy squints at sdegutis

14:42 sdegutis: I think :foo would work too but then I lose type safety. And they're probably just as efficient.

14:42 technomancy: didn't we tell you to use a gensym yesterday?

14:42 sdegutis: technomancy: I was using it up until 2 minutes ago

14:42 tylere: Does clojure use deferred name resolution? e.g. I define functions a and b, can I call b from a even if a comes first in the source file?

14:42 amalloy: sdegutis: that doesn't sound much like C's enum :P

14:42 sdegutis: technomancy: then I wanted to use the constant in a case statement

14:42 SegFaultAX: sdegutis: Are you using it as a sentinel value?

14:42 amalloy: tylere: no

14:43 coventry: tylere: ##(source declare)

14:43 lazybot: java.lang.RuntimeException: Unable to resolve symbol: source in this context

14:43 coventry: ,(doc declare)

14:43 clojurebot: "([& names]); defs the supplied var names with no bindings, useful for making forward declarations."

14:43 sdegutis: technomancy: and it said "no matching clause for BLAAERGGGBLLAAA"

14:43 technomancy: lame

14:43 sdegutis: technomancy: no, fast.

14:43 technomancy: sdegutis: if you use read-time gensym it should work though

14:44 sdegutis: technomancy: case doesn't even eval, it's constant time lookup, so (def foo 'foo) works great here

14:44 technomancy: ,genned-sym#

14:44 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: genned-sym# in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:44 technomancy: ,:genned-sym#

14:44 clojurebot: :genned-sym#

14:44 technomancy: huh

14:44 I guess that would require wrapping the whole thing in a `

14:44 sdegutis: technomancy: but I don't need it to be super unique, only unique to the others, which means typos is the only real worry, and that's a one-time problem

14:48 coventry: technomancy: The # syntax doesn't seem to work with keywords: ##(list `(:genned-sym# genned-sym#))

14:48 lazybot: ⇒ ((:genned-sym# genned-sym__134041__auto__))

14:48 technomancy: coventry: huh; must have been thinking of something else

14:49 sdegutis: So, what's wrong with (def foo 'foo)?

14:50 Hmm, it should be thread-safe. And it doesn't cause a stackoverflow.

14:50 SegFaultAX: sdegutis: It's probably entirely unnecessary.

14:50 sdegutis: SegFaultAX: Why's that?

14:50 SegFaultAX: sdegutis: Do you intend to use identical? somewhere?

14:51 sdegutis: SegFaultAX: I have (case ... foo ...), does that count?

14:51 SegFaultAX: sdegutis: Are multimethods not an option?

14:51 sdegutis: Now I'm confused.

14:52 SegFaultAX: sdegutis: Me too, I have no idea what you're doing. It's hard to determine exactly why defing a symbol is useful for you.

14:53 sdegutis: Oh.

14:53 mklappstuhl: sdegutis: technomancy's approach is indeed quite interesting, especially since it's so simple :)

14:54 sdegutis: SegFaultAX: I'm writing a tokenizer/parser. And I want a fast/efficient way to represent a token's type, and later in the parser I want to switch off on token-types using case. So I need a way to represent token types that works both as a value and a constant suitable for case.

14:54 SegFaultAX: (def sym 'sym) seems to solve that, but I'm concerned there might be hidden caveats

14:55 coventry: If you're writing this tokenizer for educational reasons, now would probably be a good time to back away from the keyboard and think about the design for a while. Maybe look at how other people have done it and compare.

14:55 SegFaultAX: sdegutis: Still don't understand why that's useful, but what caveats do you think there could be? Symbols are stable values just like any other.

14:56 sdegutis: Dunno, that's why I was asking you guys :)

14:56 coventry: why do you say that?

14:57 coventry: You've been stuck on this point for a while, and the solution you're considering is strange and ugly. There might be a better way.

14:57 sdegutis: It is? I didn't realize it is.

14:58 SegFaultAX: sdegutis: Everyone objecting wasn't a dead giveaway?

14:58 coventry: You want to mess around with the namespace programmatically. Unless you are making a quarantined namespace for that purpose, that is ugly.

14:59 sdegutis: coventry: ah that's an interesting way to look at it

14:59 callen: it's not interesting at all, it's pretty obviously a bad idea.

14:59 sdegutis: callen: why?

15:00 coventry: Well, sometimes it's not ugly. Adding a function name, or whatever is OK. :-) Adding a bunch of tokens for the purpose of speeding up a switch is way out of balance, though.

15:00 callen: if you don't know why mucking around with namespaces programmatically is a bad idea, then I can't tell you either.

15:00 coventry: yeah.

15:00 sdegutis: I guess I don't really look at this like too heavy a use of metaprogramming.

15:01 Mainly because it's very simple: foo refers to foo.

15:01 llasram: Which is exactly what keywords are for?

15:01 TimMc: sdegutis: Oh wait, you also go by the nick "futile", right?

15:01 I thought I recognized this conversation.

15:01 callen: TimMc: yeah, same bloke.

15:01 TimMc: lots of conversation about bad ideas, no actual usable code at the end.

15:02 I wonder how much programmer time he's wasted in total.

15:02 between his own efforts and everybody else he sucks into his pointless bullshit.

15:03 coventry: If I hadn't procrastinated making that suggestion, I probably would have procrastinated some other way. But yes, this is improving no one's life. Back to work for me. :-)

15:03 callen: I have Datomic queries to write - I'm out too.

15:24 sdegutis: Well so much for trying to discuss design philosophies. Didn't expect so much condescending dismissiveness from #clojure.

15:25 callen: sdegutis: http://i.imgur.com/Zoc8zR7.jpg

15:25 sdegutis: That was probably uncalled for, sorry.

15:25 gdev: sdegutis, sorry I was out to lunch, what did I miss?

15:25 rigger: just need to find the right person, right time

15:26 gdev: I like design discussions =)

15:26 callen: gdev: #RUBY_DRAMA

15:26 gdev: namespace munging.

15:26 mklappstuhl: getting errors like this: ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol clojure.lang.RT$1.invoke (RT.java:224)

15:26 how can I get some better errors?

15:26 like line numbers and these sorts of things

15:27 sdegutis: gdev: I have a tokenizer/parser where the tokenizer returns tokens with types and the parser has to switch off on them. I came up with the solution (def RParen 'RParen) so that I could use RParen as the token type, and use (case) to switch off on it.

15:27 coventry: mklappstuhl: I generally (use 'clojure.repl) and then (pst) to get the full stacktrace.

15:27 alejandro_: mklappstuhl: or http://richhickey.github.io/clojure/clojure.stacktrace-api.html

15:28 sdegutis: gdev: I was going to use keywords, but this solution gives me a little more type safety. What do you think of that solution? Do you think it's bad on account of messing with the namespace?

15:28 coventry: mklappstuhl: It's a lot of spew, (don't think the stacktrace api will save you from that), so you have to scan the output for references to your source files.

15:29 mklappstuhl: coventry: how exactly would I use pst?

15:29 coventry: nevermind :)

15:29 http://clojuredocs.org/clojure_core/clojure.repl/pst

15:30 haha, it doesn't list any of my source files though :D

15:31 gfredericks: why would (range 100000000) be twice as slow with (reduce +) than the same thing in a vector?

15:32 nDuff: gfredericks: because it can't seek, and thus can't parallelize.

15:32 gfredericks: ...I'm actually surprised it's only twice as slow.

15:32 gdev: sdegutis, can you refheap the code? I'm bad at word problems =(

15:32 nDuff: Oh, wait, this isn't core.reducers?

15:32 Don't know, then.

15:32 gfredericks: nDuff: reduce + can't parallelize anyhow

15:32 k

15:33 ,(time (reduce + (range 1000000)))

15:33 clojurebot: "Elapsed time: 187.122121 msecs"\n499999500000

15:33 gfredericks: ,(let [v (vec (range 1000000))] (time (reduce + v)))

15:33 clojurebot: #<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>

15:34 gdev: that was faster

15:34 gfredericks: that is a small jvm.

15:34 I was doing mine 100 times as big

15:34 &(time (reduce + (range 1000000)))

15:34 lazybot: ⇒ "Elapsed time: 257.85282 msecs" 499999500000

15:34 gfredericks: &(let [v (vec (range 1000000))] (time (reduce + v)))

15:34 lazybot: ⇒ "Elapsed time: 1376.893624 msecs" 499999500000

15:34 * gfredericks gives up

15:34 coventry: gfredericks: You aren't including the construction of the vector in the time. Isn't it likely that it's the increments by range which are slowing things down?

15:35 callen: ##(time (apply + (range 10000)))

15:35 lazybot: ⇒ "Elapsed time: 10.051635 msecs" 49995000

15:35 callen: ##(time (apply + (range 1000000)))

15:35 lazybot: ⇒ "Elapsed time: 349.833382 msecs" 499999500000

15:35 callen: ##(time (apply + (range 10000000)))

15:35 lazybot: ⇒ "Elapsed time: 3344.378229 msecs" 49999995000000

15:35 sdegutis: gdev: https://www.refheap.com/18374

15:35 callen: ##(time (reduce + (range 1000000)))

15:35 lazybot: ⇒ "Elapsed time: 269.19041 msecs" 499999500000

15:35 callen: marginal. cool.

15:38 gdev: sdegutis, thanks, lemme have a look at it

15:39 hiredman: I would suspect vectors are faster for sequential access in general, because they pack values in nice cache filling arrays

15:39 mklappstuhl: I get an error 'ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol' when switching into a namespace I'm working in & (pst) doesnt give me any hint about where I made the mistake. Is there anything else I could do?

15:40 hiredman: mklappstuhl: are you doing (ns 'foo) ?

15:40 mklappstuhl: hiredman:

15:40 yes

15:40 hiredman: ns is macro it doesn't need the quote

15:41 callen: ##(time (reduce + (vec (range 1000000))))

15:41 lazybot: ⇒ "Elapsed time: 4546.920025 msecs" 499999500000

15:41 mklappstuhl: hiredman: ok, thats good to know. should that also change whats printed by (pst) ?

15:41 (it doesn't for me)

15:41 ztellman: callen: you're timing the conversion to a vector, too, in that benchmark

15:41 callen: I know

15:41 I just caught it.

15:41 mklappstuhl: code is here btw: https://github.com/mklappstuhl/goldman.clj/blob/master/src/mklappstuhl/stock_utils/db.clj

15:42 callen: ##(let [v (vec (range 1000000))] (time (reduce + v)))

15:42 lazybot: ⇒ "Elapsed time: 2281.862622 msecs" 499999500000

15:42 ztellman: "benchmark", I should say

15:42 callen: ztellman: it's not serious, I'm just being idle.

15:42 I know to use criterium in things I care about :P

15:42 ##(let [v (vec (range 1000000))] (time (reduce + v)))

15:42 lazybot: ⇒ "Elapsed time: 1857.035772 msecs" 499999500000

15:42 ztellman: callen: oh, sure, but if I don't keep the benchmark snootiness torch burning, who will?

15:43 callen: ##(let [v (vec (range 1000000))] (time (apply + v)))

15:43 lazybot: ⇒ "Elapsed time: 2516.47335 msecs" 499999500000

15:43 callen: ztellman: well, I was, earlier.

15:43 told futty to use criterium, haha.

15:43 TimMc: sdegutis: Anything beyond preconditions that check inputs for membership in a set is going to be pretty ugly.

15:43 ztellman: by the way, you guys know you can use scientific notation with range, right?

15:43 * callen goes back to trying to break RabbitMQ

15:43 ztellman: way easier to visually parse

15:44 callen: well it's not specific to range.

15:44 sdegutis: TimMc: how so?

15:44 ztellman: callen: yes, but specifically with range it's almost always what you want to do

15:44 TimMc: sdegutis: Because if you want more than that, you're probably using the wrong language.

15:46 coventry: sdegutis: Why not dispatch off the token characters themselves? https://github.com/clojure/tools.reader/blob/master/src/main/clojure/clojure/tools/reader.clj#L543

15:47 sdegutis: coventry: hmm that's an interesting solution. I didn't think it'd work on account of the dispatch # char, but this solution is neat.

15:48 coventry: That's all good reading, if you want to write a parser.

15:50 gfredericks: hiredman: but (range n) is also chunked in 32s, is it not? is it somehow less cache-optimal than a vector?

15:53 coventry: oh that's an interesting point about the increments. When I (doall (range n)) first, so the whole thing is in memory, it is faster.

15:53 faster than the vector even, at first glance

15:55 hiredman: gfredericks: oh, right, chunking :(

15:57 callen: ##(let [v (vec (range 1e6))] (time (apply + v)))

15:58 lazybot: ⇒ "Elapsed time: 2175.583604 msecs" 499999500000

16:02 coventry: Seems like the JIT compiler optimizes all of this away, anyway. https://www.refheap.com/18375

16:09 gdev: sdegutis, my 2 pennies is that when it comes to design I try to make design decisions reversible so once there are no more unknowns I can refactor bad decisions

16:10 sdegutis: gdev: good plan

16:11 Rubix: (bean instance-of-user-defined-class) gives me {:class instance-of-user-defined-class} ... I wish it would show the data members therein ... any suggestions?

16:11 gdev: if you want to manage risk and be able to quickly refactor, you have definitely chosen the right language

16:16 Rubix, bean only shows things exposed through its getter methods

16:17 Rubix: gdev: I have to define getter methods for it? shucks

16:18 llasram: Rubix: Do you control the user-defined-class?

16:18 Rubix: llasram: yes

16:18 gdev: ##(:members (clojure.reflect "foo"))

16:18 lazybot: java.lang.ClassNotFoundException: clojure.reflect

16:19 llasram: Rubix: does it exist to ship to a Java interface or such?

16:19 Rubix: llasram: no, its pojo,

16:19 gdev: Rubix, if your class really is a JavaBean all of its members should only be accessible through getters and setters so sayeth the sun lord, so it shall be done

16:20 llasram: Rubix: I mean, are you using a Java class because you need to pass it to some Java API?

16:20 Rubix: llasram: i've got a pile of legacy java code under my control, trying to extract pojos to maps

16:21 llasram: There we go -- that's what I should have asked :-)

16:21 And the POJOs directly expose data via public members, not getter/setter methods?

16:22 Rubix: llasram: yes

16:22 all public, all the time

16:22 llasram: Rubix: Yeah, I don't think anything off-the-shelf exists, but as gdev suggested you should be able to use clojure.reflect/reflect

16:23 callen: hrm. yes. core.async is fast #_#

16:23 gdev: ##(:members (clojure.reflect/reflect "foo"))

16:23 lazybot: java.lang.ClassNotFoundException: clojure.reflect

16:24 Rubix: llasram, gdev : what's that argument to (clojure.reflect) ?

16:25 string-represented declared class name?

16:26 gdev: Rubix, I'm just passing in a string so it will give me a map of all the members of java.lang.string

16:26 Rubix: ah

16:27 gdev: Rubix, you could also do (:members (clojure.reflect/reflect (MyClass.))

16:28 mklappstuhl: how do I reload the namespace I'm currently in in the REPL?

16:28 llasram: gdev, Rubix: Well, and you can use reflect-type to reflect on a Class

16:28 Er, type-reflect even

16:29 coventry: mklappstuhl: Are you using emacs? I generally just do C-c C-k in the corresponding source file.

16:29 llasram: &(require 'clojure.reflect)

16:29 lazybot: ⇒ nil

16:29 llasram: &(->> clojure.lang.Keyword clojure.reflect/type-reflect :members (filter #(and (instance? clojure.reflect.Field %) (-> % :flags :static not) (-> % :flags :public))) (map :name))

16:29 lazybot: ⇒ (sym)

16:29 mklappstuhl: coventry: no. vim + lein repl

16:29 llasram: &(.-sym :hello)

16:29 lazybot: ⇒ hello

16:30 TimMc: mklappstuhl: (require (.name *ns*) :reload)

16:31 mklappstuhl: (require 'my.ns :reload) if you want to reload it by name

16:31 callen: you probably don't want to use reload.

16:31 llasram: TimMc: also (ns-name *ns*)

16:31 mklappstuhl: callen: whats wrong with reload?

16:32 callen: no seriously

16:32 (require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh)

16:32 do that. Don't use reload/reload-all

16:32 mklappstuhl: cf. Stuart Sierra's workflow post and the documentation on clojure.tools.namespace.

16:32 mklappstuhl: callen: link?

16:35 TimMc: If you don't use protocols or multimethods (and you defonce your state) it is fine.

16:37 callen: refresh is moar betta.

16:37 and doesn't require that you cherry-pick.

16:39 seangrov`: Does lighttable work with clojure 1.5 projects?

16:39 rasmusto: seangrov`: I think the newest release requires 1.5.x in project.clj

16:43 aaelony: I am building a map where I start from an initial map and use assoc to make a new key and new value, x1, that is the result of some computation. Now, I want to compute x2 and use the result value x1 in the computation of x2 and then assoc x2 into my growing map. Can I do this? Or need I create a monster let statement with all my dependent calcs x1, …, xn and merge them into my final map?

16:43 mklappstuhl: callen: if I run (require '[clojure.tools.namespace.repl :refer [refresh]]) and then (refresh) it can't resolve the symbol...

16:46 justin_smith: aaelony: maybe an iterate that updates the key to use on each time through?

16:46 aaelony: that would require a function that takes the previous key, and generates the next one from that

16:46 or an infinite list of keys

16:46 one of those

16:48 aaelony: justin_smith: I guess I am hoping there was something like (-> initial-map (assoc :x1 (some-calc)) (assoc :x2 (something that uses value of :x1)) (assoc (:x3 (something that uses :x2 )) etc… )

16:51 justin_smith: thanks for your thoughts… will think about it some more… I think that hard part is that it needs to be as flexible as a let statement would be, but the results would go in to the final map...

16:51 justin_smith: maybe the answer is indeed "that's what let is for" and then merge it in the last step….

16:52 justin_smith: (zipmap (create-key-seq) (iterate process input))

16:53 maybe?

16:54 aaelony: justin_smith: maybe… but there may not be reliable structure in the function sequence.. For example, x2 may need to access 3 values from keys in the map that is being built, but x3 may need some other combination...

16:55 justin_smith: or maybe that is what you specify in the key-seq… interesting...

17:05 coventry: aaelony: Have not used it, but synthread may help you do this kind of thing. https://github.com/LonoCloud/synthread

17:05 Especially ->/as

17:06 aaelony: conventry: appreciate it, will take a look.. thanks

17:08 coventry: looks like a good fit! Need to figure out the syntax. thanks! :)

17:09 SegFaultAX: Synthread is awesome.

17:11 aaelony: kudos to chouser!

17:13 * SegFaultAX didn't know chouser was a rocket scientist

17:16 callen: SegFaultAX: yes it is.

17:17 Raynes: SegFaultAX: In that it'd take a rocket scientist to have any clue what code is doing after it has been infected with that shit?

17:21 callen: I think Raynes and callen switched brains today.

17:21 Raynes: lol

17:22 callen: Was that *that* mean?

17:23 callen: well. It wasn't as bad as waterboarding bloom with his CV, but it was surprisingly negative.

17:23 hyPiRion: It could be amalloy too, for that matter.

17:23 Raynes: callen: :P

17:26 amalloy: c'mon, that doesn't sound like me at all. i would have found a subtly sarcastic way to object to it, if i didn't like it

17:26 the fecal comparisons are a callen thing for sure

17:28 callen: so am I dumb for being surprised that (def f (memoize (fn [] (atom {})))) (swap! (f) assoc :a 1) @(f) did the right thing?

17:30 * callen assumes yes

17:34 dobry-den: callen: would that create a new atom when you swap! it with different arguments, but return the same atom when you swap it with the same arguments?

17:34 seangrov`: Are watches enabled for lighttable?

17:35 dobry-den: seangrov`: i think so. i saw the keybindings for toggling them when i was editing the behavior/keymapping files

17:38 TimMc: callen: What were you expecting?

17:39 coventry: Is there a way to get rid of the red underlining which appears on a form when you compile it under nrepl's C-c C-k? (Other than correcting the error and re-evaluating. :-)

17:40 SegFaultAX: Raynes: I don't think the synthread macros are that bad personally.

17:40 callen: dobry-den: just try it

17:40 SegFaultAX: I think it's more significant that an ex-Haskell user dislikes it.

17:40 mabes: coventry: I've been wondering that myself.. sometimes I comment out the form with #_, and reload, just to get rid of them...

17:40 callen: TimMc: for Clojure to be as ghetto as every language I'd previously used.

17:41 TimMc: Python set my expectations kinda low.

17:41 even after ${X} years I still haven't learned to just trust it.

17:41 seangrov`: dobry-den: Ah, yes, found it, thank you

17:41 Hrm, lighttable is pretty nice

17:42 SegFaultAX: I don't think Python is particularly more ghetto than any other language.

17:43 Every language has dark corners. Python doesn't have as many as some.

17:44 unlink: I'm getting the following error when I run nrepl-jack-in: "error in process sentinel: Could not start nREPL server: "

17:44 `lein repl' works fine from M-x shell

17:45 callen: seangrov`: is it? lot of trouble with it lately.

17:45 technomancy: unlink: does M-! which lein work?

17:46 rasmusto: callen: my ctrl-space hotkey didn't work with my keyboard, so I couldn't un-fullscreen lighttable without uninstalling

17:46 unlink: technomancy: yes

17:46 rasmusto: callen: it's still usable enough for proj euler and 4clojure stuff

17:47 Pupnik: so is windows notepad

17:47 technomancy: unlink: huh; dunno. you could do `lein repl :headless` and M-x repl to connect to it

17:48 M-x nrepl

17:50 rasmusto: Pupnik: so is pencil and paper

17:50 sdegutis: I vaguely remember a short-hand for (and (> x min) (< x max)), does it exist or was I dreaming?

17:50 unlink: technomancy: open-network-stream: make client process failed: Can't assign requested address, :name, nrepl, :buffer, *nrepl-connection*, :host,, :service, 0, :nowait, nil

17:52 technomancy: unlink: did you give it a port?

17:53 seangrov`: callen: I've only used it for ~5 minutes, it's better than I expected. Not expecting to leave emacs for it of course.

17:53 sdegutis: Ah, (< min x max)

17:53 ,(< 3 4 5)

17:53 clojurebot: true

17:53 sdegutis: Neat.

17:53 seangrov`: But we have a contractor here learning clojure and he was using x-code, no syntax highlighting, no paren matching... it was painful to watch

17:54 I recommended he try out lighttable, figured that's likely easier to pickup than emacs

17:54 sdegutis: seangrov`: sounds like it

17:54 unlink: technomancy: ah. I had mispelled :repl-options as :nrepl-options.

17:55 technomancy: I am able to connect via M-x nrepl.

17:55 seangrov`: sdegutis: Learning a new language, toolchain, programming style, and editor at the same time seems a bit overwhelming. Trying not to scare him away too quickly.

17:55 unlink: technomancy: it would be nice if unrecognized forms in defproject weren't silently ignored.

17:55 technomancy: unlink: nice, but infeasible

17:56 sdegutis: seangrov`: I'm just really confused about the lack of syntax highlighting part.. doesn't Xcode have a built-in syntax highlighter?

17:56 technomancy: given that any plugin can arbitrarily choose to recognize any form

17:56 sdegutis: seangrov`: oh yeah, probably not for Lisp langs..

17:56 unlink: sounds like an architectural limitation worth addressing.

17:56 seangrov`: sdegutis: Exactly.

17:56 technomancy: unlink: you would have to load every plugin for every execution

17:57 seangrov`: It's a worrisome sign for me when a developer hasn't spent a lot of time on their tools though

17:57 unlink: not if you, for example, enforced a convention for plugin-specific options.

17:57 callen: seangrov`: to me too.

17:57 seangrov`: You use them for so many years, it makes sense to invest in making them nice and efficient

17:57 callen: seangrov`: I'm introducing Clojure guerilla style at my company. Going to conquer one mind at a time.

17:57 seangrov`: Haha

17:57 rasmusto: callen: what are your tactics?

17:57 callen: seangrov`: a lot of people aren't that invested in their careers.

17:57 seangrov`: callen: We'll have to grab drinks some time

17:57 callen: rasmusto: use Datomic as an excuse to use Clojure

17:57 seangrov`: Ah, fair enough

17:57 rasmusto: callen: oh damn

17:58 callen: rasmusto: steal labor for my project, brainwa^H^H^H^H^H^H convert them

17:58 technomancy: unlink: that just moves the problem around

17:58 seangrov`: I suppose I'm expecting a common level of desire to improve

17:58 callen: rasmusto: make project awesome, impress air support, conquer another thing.

17:58 rasmusto: callen: yeah, awesome projects can go a long way

17:58 callen: seangrov`: not what I've encountered. and yes, we should grab drinks. Are you coming to the meetup today?

17:58 unlink: technomancy: no, it solves that part of the problem. then you require projects to declare the configuration they understand.

17:59 technomancy: it's technically feasible, but it goes against the design principles of clojure

18:00 unlink: ...fail slowly and silently?

18:00 technomancy: if you want to be able to catch unknown patterns properly you need a static type system

18:00 seangrov`: callen: Heading to a different meetup a friend asked me to join, sadly

18:01 sdegutis: Ahh!!

18:01 unlink: this has nothing to do with types, and everything to do with (developer-)friendly user interfaces

18:01 technomancy: ,(contains? [1] 1) ; <- unlink

18:01 clojurebot: false

18:01 callen: seangrov`: You're in the city right? you free tomorrow?

18:02 seangrov`: callen: Yeah, but heading out to JSConfEU soon, so prepping a lot

18:02 Our office is in the Mission, I'm in Twin Peaks

18:02 coventry: mabes: Just thought of the right google query: (defun drop-overlays () (interactive) (remove-overlays))

18:02 callen: seangrov`: SOMA / Ingleside for me, also I drive.

18:02 technomancy: ignoring the significant backwards-compatibility challenges, it's just not in line with the zen of clojure to protect against that kind of mistake

18:03 seangrov`: callen: Early drinks at CBS?

18:03 unlink: technomancy: I'm not sure what user-interface compromise in the name of efficiency has to do with making leiningen hard to debug

18:04 callen: seangrov`: the only word I understood in there is "drinks". I don't know what early is for you, and I don't know what CBS either, sorry. haha.

18:04 unlink: I think a better example would be: (contains? :x 1)

18:04 you pass it something invalid, so it throws an exception loudly and makes the error obvious

18:05 instead of silently doing the wrong thing and looking like it works, even when its input is never valid

18:06 mabes: coventry: nice, thanks for sharing.. adding that along with a keybinding for it :)

18:21 sdegutis: What's a good way to test if two ranges intersect? Convert them to sets and use the set lib?

18:21 ztellman: are the ranges already turned into sequences?

18:22 or are they just intervals of [start end]?

18:25 unlink: another example: how is a user supposed to discover that :dev-dependencies has been deprecated, particularly when current documentation (such as the documentation for ring.util.serve) continues to refer to it?

18:25 sdegutis: ztellman: I actually just have two pairs of pos/len

18:25 technomancy: unlink: for backwards-compatible changes there is the lein-precate plugin

18:26 ztellman: sdegutis: http://www.rgrjr.com/emacs/overlap.html

18:26 that should be a bit more efficient than calculating the intersection

18:26 unlink: I happen to have studied the differences between the example project.clj files for 1.6 and 2.0, so I know what changed; but here is the error message a newbie would be confronted with: FileNotFoundException Could not locate ring/util/serve__init.class or ring/util/serve.clj on classpath: clojure.lang.RT.load (RT.java:443)

18:26 technomancy: unlink: including :dev-dependencies in a project.clj is not always a bad idea if your users might be using 1.x or 2.x though

18:26 sdegutis: ztellman: sweet, thanks!

18:27 technomancy: further proof that the validity of a given key is undecidable

18:27 gfredericks: technomancy: is there a leiningen undecidability theorem?

18:27 seangrov`: ztellman is a wizard

18:27 gfredericks: (presumably referred to as LUT by the kids these days)

18:28 ztellman: interval arithmetic is wizardry?

18:28 technomancy: gfredericks: maybe you're confusing it with the hagelberg uncertainty principle.

18:28 unlink: of course it's undecidable. that's the problem. you have a declarative document without any checks for validity.

18:29 sdegutis: ztellman: no, just that you do tons of crazy efficiency things

18:29 ztellman: I'm never surprised to see ANNs about super-efficient this or that from you on the mailing list :)

18:30 unlink: Java's maven, Haskell's cabal, and even Python's setuptools will complain (or crash) if they are given improper build descriptors. leiningen stands alone in chugging along with an (often provably) incorrect project descriptor.

18:31 muhoo: the general attitude of clojure is to encourage you to do the right thing, but not go out of the way to put up barriers to prevent you from doing the wrong thing, AFAICT

18:31 i think rchickey calls it "consenting adults programming" or somethign similarly pithy

18:31 technomancy: the first two are completely different: XML has schemas, Haskell has a static type system

18:31 I have no idea how python works

18:31 unlink: no, that's the general attitude of PHP and JavaScript.

18:32 hyPiRion: so, uh, is it the battle of the types again?

18:32 unlink: Haskell has a static type system, but its setup descriptor is not code. it's a declarative document similar to project.clj.

18:32 technomancy: and actually in the case of maven it's a PITA that you can't attach arbitrary metadata to a pom

18:32 mgaare: cabal is also a terrifying nightmare :D

18:33 gfredericks: I think you can isolate certain cases in clojure core of returning nil when passed totally irrelevant types, e.g. ##(contains? :foo :bar)

18:33 lazybot: ⇒ false

18:33 hyPiRion: `cabal install cabal-install` always gets me

18:33 unlink: project.clj is *excellent* in principle. it is exactly what you should want: a non-code datastructure specifying your project.

18:33 gfredericks: it's pretty easy to argue that that should throw an exception without violating the zen of clojure

18:33 technomancy: gfredericks: this is more like (:foo {:bar 1}) though

18:33 callen: muhoo: I tend to agree with the "consenting adults" thing btw

18:34 seangrov`: callen: Have you successfully got datomic into production?

18:34 callen: oh cool, we're getting a 64TB SSD Z-raid array installed in one of the servers at work.

18:35 seangrov`: it's not finished, but it's going to be very soon.

18:35 technomancy: I would actually be interested in a language that had (:foo {:bar 1}) throw if you didn't provide a not-found value

18:35 callen: have the license key for the pro edition ready to go, just hacking the code together.

18:35 seangrov`: callen: How's your experience been?

18:36 technomancy: but that's not what this is about, because having no :repl-options in your project.clj file is completely reasonable

18:36 callen: technomancy: core.typed?

18:36 mgaare: callen: have you played around with any larger data sets in datomic yet?

18:36 callen: seangrov`: there are idiosyncrasies, but it's good so far. The design seems solid so far.

18:36 hyPiRion: callen: that has nothing to do with core.typed though? It's more about a lack of value.

18:36 callen: mgaare: nothing substantial yet, but I will when I stress test the pro instance...which will happen whenever IT gives me my server.

18:36 hyPiRion: a map entry, rather.

18:36 callen: hyPiRion: core.typed can enforce that, no?

18:36 technomancy: callen: I'd rather it worked that way without a substantial up-front investment

18:36 seangrov`: technomancy: Haven't been following along too closely, but how about a lein plugin that checks the project.clj for known mispellings?

18:37 technomancy: seangrov`: that's reasonable

18:37 seangrov`: Would be an easy one to submit pr's for on github and help people out

18:37 mgaare: callen: one thing we noticed was that if you have a lot of entities, partitioning becomes very important

18:37 technomancy: seangrov`: or even "here's what you're using that's not in sample.project.clj"

18:37 callen: levenshtein the keys?

18:37 oh, that's better still.

18:38 mgaare: interesting. Our needs are relatively minimal so far WRT performance/volume

18:38 mgaare: the thing I'm building is multiple orders of magnitude overkill for our actual data needs (a conscious decision)

18:39 mgaare: can you say what tier of entity pop-counts started necessitating paying attention to partitioning?

18:40 mgaare: callen: our test data was about 8 figures of entities. Need to do it well before that point

18:40 dissipate__: what's up with datomic being closed source?

18:41 callen: dissipate__: wanna make money. don't blame 'em. Their license terms are hyper-mega-reasonable.

18:41 $3k perpetual license. ridiculously good deal.

18:41 you re-up a fraction of that for maintenance.

18:41 pay more for more peers

18:41 mgaare: not sure exactly where, because we ended up deciding against using it

18:41 callen: mgaare: we'd be hard pressed to get into anything like that, I think.

18:41 dissipate__: callen: Hickey should have closed sourced clojure as well, right?

18:42 callen: mgaare: we're more likely to run into trouble from churning history.

18:42 dissipate__: no.

18:42 dissipate__: callen: what's the difference?

18:42 callen: you can't really get people to buy into a language like that, like you can a tool like a database.

18:42 seangrov`: callen: Even a database is tough

18:42 callen: it is, but Datomic is sufficiently compelling.

18:42 mgaare: The issue is that if you're doing a query, the peer needs to pull in the entire index for the partition (or at least that's what we concluded was happening)

18:42 dissipate__: callen: there's a lot of open source free database engines out there

18:42 callen: Datomic was so compelling that many-many-many of my coworkers were really into it despite being deeply skeptical of Clojure

18:42 I...don't really understand why yet.

18:43 mgaare: so it's index size as a function of pop then probably, okay.

18:43 dissipate__: callen: did you pay $3K for diatomic?

18:43 er, datomic

18:43 callen: you are in a java shop, right?

18:43 callen: lol no

18:43 Python.

18:44 we have a pro license of datomic lying around, yeah.

18:44 I've been using free and mem while I get the rest of the data firehose hooked up, I'll flip over whenever I get my server.

18:44 dissipate__: callen: ah, that's better than java!

18:44 mgaare: callen: yea. We did some profiling, and what we were seeing with our huge partition was that on a query it would pull in like 600 MB worth of longs (e-ids presumably) and then whatever other data we were querying against, and then immediately GC all of it :D

18:45 callen: mgaare: fucking lol

18:47 http://www.informationweek.com/software/information-management/the-man-who-tortures-databases/240160850

18:48 mgaare: next step is to just start breaking out partitions roughly by entity type right?

18:49 hrm.

18:50 mgaare: callen: that's what we were doing, but the majority of the entities were the same type. What I've concluded is that if you're trying to store a lot of data in datomic, you have to think about the low level stuff about partitioning just as much as you would in any other db

18:51 callen: mgaare: that's more or less what I expected.

18:51 Datomic is just nicely designed, it's not magical.

18:51 mgaare: there was a discussion group post between I think Ian Eslick and Rich that touched on this situation. Ian was trying to store a lot of data about users, and the solution was to create a partition for every 100 or so users

18:52 callen: ...wat

18:53 mgaare: I think it was medical data or something, so each user could have a huge number of entities associated with it

18:53 holo: hi

18:53 callen: mgaare: oh I see. yeah I saw that his profile mentioned healthcare data.

18:54 mgaare: I work at a genetics company, but our data "load" per human or logical 'thing' is much smaller

18:54 tons of raw data from the sequencers themselves, but that gets sifted quickly.

18:55 Rich handles some loony conversations on the mailing list.

18:56 mgaare: lisp seems to attract more than its share of strange minds

18:57 holo: I have a dilemma. I have some pred? that always return some logical truth that is not really true value, but "foo". the problem is, i want to expose those pred? as part of api, and want to give examples of usage, but returning "foo" in examples instead of true looks ugly. should i clutter the pred? implementation with a boolean or similar? or do i have too much free time?

18:57 sdegutis: I still don't think of Clojure when I see the word "lisp"

18:57 holo: I'd probably wrap it with boolean too

18:58 holo: or just document that the function returns "logical true"

18:58 In that case, people know not to expect literal true

18:59 callen: mgaare: have you seen Haskell's menagerie of madness?

19:01 holo: sdegutis, even if I document at the fn, the users still see the usage first in the readme.md, an ugly and probably meaningless "foo". maybe they will be even tempted to reuse that return value as a non boolean value. i'm more and more convinced about the wrap it as boolean option, as you suggested

19:01 * sdegutis could go for some Rolos right now

19:01 mgaare: callen: a little bit. It has a bit of a different feel though, not sure exactly how to describe it. Filtered through a love of structure, perhaps

19:01 sdegutis: holo: ah didn't know it would be shown in the readme

19:02 holo: another option is to just replace the output in the readme with "<truthy value>"

19:03 holo: sdegutis, insightful. would you represent it verbatim "<truthy value>"?

19:03 sdegutis: holo: maybe.

19:07 holo: (inc sdegutis)

19:07 lazybot: ⇒ 2

19:07 sdegutis: yay

19:23 seangrov`: Any compojure experts?

19:23 sdegutis: Many.

19:23 callen: seangrov`: expert no, journeyman...maybe. soup?

19:23 aka, "just ask" :P

19:24 seangrov`: Sorry, looked away for a momenth

19:24 Looking to match on a route either for "/:callback" or "?callback=" - seems like I have to define two separate routes for that though

19:25 Any way to make the "/:callback" an optional route variable?

19:27 Brand0: callback hell

19:30 callen: seangrov`: is it namespaced or is this top-level?

19:31 the routes.

19:31 as in, is there a prefix?

19:31 seangrov`: No, just the root url

19:32 Just wondering if there's a way to get compojure to do something like ["/user/:id" :optional :id]

19:32 callen: not directly, I'm thinking about a couple of indirect ways atm though.

19:33 let me test something.

19:34 seangrov`: No a huge deal, just something I've wanted

19:34 rigger: why are you providing two different apis?

19:35 SegFaultAX: rigger: Why aren't you?!

19:35 rigger: because i have no imagination

19:35 seangrov`: rigger: BAckwards compatibility

19:35 rigger: gotcha

19:36 sdegutis: seangrov`: yeah those will need two separate routes

19:36 SegFaultAX: rigger: http://imgur.com/r/4chan/3YdJs

19:38 callen: seangrov`: nope.

19:38 seangrov`: you can do it if you don't mind snagging the param yourself.

19:38 seangrov`: Ah well, no worries

19:38 callen: seangrov`: I have a workable solution.

19:39 SegFaultAX: You wouldn't want to have 1 route anyway.

19:39 callen: (GET "*" [] route-handler), (str (:params blah)) in the handler => {:* "/blah"}

19:39 seangrov`: callen: This is what I ended up doing https://www.refheap.com/ad18f6f873ca84e34753cade5

19:39 callen: evil/messy, requires invoking the params parser with a wrapper

19:39 rigger: SegFaultAX: that's awesome

19:39 callen: seangrov`: hrm, I tried that and it didn't work for me.

19:39 let me try it again.

19:40 rigger: seangrov`: are you running this behind a webserver?

19:40 clojurebot: Titim gan éirí ort.

19:40 callen: oh yeah that does work.

19:40 seangrov`: yeah that's way better. I forgot the keyword before the regex in my attempt.

19:40 SegFaultAX: seangrov`: You want 2 routes. /foos and /foos/:foo_id should logically name different resources.

19:41 rigger: because i'd just stuff that compatability layer in a rewrite rule

19:47 sdegutis: All my time being spent in clojure.lang.Reflector.getMethods and .getField means I should probably drop down to Java, doesn't it.

19:47 :(

19:50 technomancy: no, just add type hints

19:52 * sdegutis googles

19:52 sdegutis: thanks

19:58 callen: sdegutis: your life would be easier if you just went through a Clojure book

19:58 sdegutis: callen: roger

19:58 callen: sdegutis: and would involve less time-wastey questions

19:58 sdegutis: :|

20:03 rasmusto: sdegutis: don't take that the wrong way

20:03 sdegutis: Clojure Programming followed by Joy of Clojure really are that good

20:04 callen: ^^ yes.

20:05 sdegutis: rasmusto: Very good suggestion, thanks. I'm not taking it the wrong way.

20:05 Although I may have to trip callen if I ever see him walking by in real life.

20:06 rasmusto: sdegutis: oh? A trip to where?

20:06 sdegutis: :)

20:06 callen: you know I'm teasing :)

20:06 :|

20:09 :)

20:18 callen: he's lucky he left.

20:18 rasmusto: :o

20:19 callen: rasmusto: I was about to correct him on my not teasing :P

20:19 I was quite serious when I said he wastes time.

20:19 rasmusto: callen: I like being told that I'm writing terrible code/wasting time

20:19 Other people should be too

20:19 callen: his problem is he refuses to read or really do anything other than poke at projects he'll abandon in a week.

20:20 and in the process waste peoples' time with his flavor of the week

20:20 I've seen 1,000 other people on IRC like him

20:20 * seangrov` has a hard time keeping track of productive people in #clojure

20:21 callen: productive people often don't have to ask questions that frequently unless encountering something new, so they're sorta invisible. github is sometimes a better measure.

20:21 mtp: this is why my client has a fools list

20:21 callen: when was the last time you saw amalloy ask a question that wasn't hypothetical, rhetorical, or sarcastic?

20:22 amalloy: or irrelevant

20:22 rasmusto: are we tring to quantify peoples' software productivity? :p

20:22 callen: I'm not saying asking questions is bad, but you can definitely up your game in terms of the quality of the questions.

20:22 TEttinger: callen, was that rhetorical?

20:22 callen: TEttinger: astute.

20:23 TEttinger: callen, yeah I do think if there was a required reading for IRC, How to Ask Good Questions should be most of it

20:23 rasmusto: does anybody else know how to ask good questions?

20:24 callen: http://www.catb.org/esr/faqs/smart-questions.html

20:24 TEttinger: rasmusto, how do i lern to spel

20:24 callen: he's a blow-hard, but he's not wrong here.

20:24 from there, simply not doing things or asking questions for things that can be resolved by reading a basic introduction to the language/library is good etiquette.

20:24 coventry: rasmusto, If you rephrase that a little more specifically we might be able to help more. For instance, how are the results from your questions inadequate? :-)

20:25 callen: it's selfish to expect people to piecemeal teach you what there's already excellent material for.

20:25 rasmusto: coventry: this is getting a bit meta

20:25 TEttinger: if it's something like lib coverage, yeah, no tutorials have that. that's a good question to ask experienced clojure devs. that's how several people found out about that code threading lib yesterday

20:26 callen: yep, very good example.

20:26 or the deeper darker bits of libraries you are using that aren't well documented and for which you're not finding the code very elucidating.

20:33 oh my dear god I hate mercurial.

20:39 seangrov`: If I run-jetty in a background thread (:join? false), how can I get access to the error?

20:39 Err, the output of the server

20:41 callen: seangrov`: by output do you mean stdout?

20:41 seangrov`: or something else?

20:42 stdout should just work.

20:42 seangrov`: When running `lein ring server` I get the stack trace on errors in the browser

20:42 callen: do you want them...in the terminal? in a data structure? what do you want?

20:42 seangrov`: Let me look at how lein-ring does it

20:42 callen: Yeah, sorry for being vague, will look into it

20:42 callen: seangrov`: I've solved this very problem, if you just tell me what you want I can...

20:43 seangrov`: Ah, I'd like the stack trace printed in stdout

20:43 technomancy: seangrov`: check *nrepl* if using nrepl.el

20:43 seangrov`: The contractor is using lighttable

20:43 technomancy: err--*nrepl-server*

20:43 callen: seangrov`: add a failsafe middleware that catches the error, snags the stacktrace, and prints it to stdout.

20:43 you can let the error re-bubble or squash it, up to you.

20:43 seangrov`: Ah, ok

20:43 technomancy: or better yet put it in the HTTP response

20:44 callen: lein ring only does its thing for unhandled exceptions.

20:44 technomancy: that's what lein ring does, puts it in the HTTP response.

20:44 technomancy: https://github.com/technomancy/syme/blob/master/src/syme/web.clj#L153

20:44 oh gotcha

20:44 callen: it's just hoomans.

20:44 seangrov` wanted stdout...presumably so LT knows what's up.

20:45 technomancy: it's probably going to stdout, just not to *out*

20:45 System/out that is

20:45 bja: this might be OT and unwelcome discussion here, but any hints on places to find people who might want to work on a project in clojure/clojurescript in chicago?

20:46 technomancy: gfredericks is in chicago iirc

20:46 callen: bja: you might ping the mailing list as well.

20:46 bja: thanks, I'll give that a shot

20:47 was at the chicago clojure meetup last month, but had to leave pretty quick after the presentation

20:51 err, gfredericks seems to work for Groupon. I seem to remember a couple of their recruiters asking me if I'd be interested in clojure for them in chicago...

20:51 callen: I've been using core.async to force callbacks to self-destruct. I feel like I could be doing this in a better way.

20:51 bja: callen: self-destruct how?

20:52 callen: bja: do no evil, return nil.

20:52 langohr's consumer cancellation stuff is a little awkward when you forget to set a consumer tag.

20:54 I'm not even really using core.async holistically but I'm still really enjoying using it to clean up code here and there.

20:54 I'm getting close to turning all of my callbacks into dumb channel funnels.

21:08 dnolen: callen: fun stuff

21:12 bbloom: speaking of callbacks, just saw https://idea.popcount.org/2013-09-05-it-aint-about-the-callbacks/ on HN

21:15 aaelony: this is interesting… a clojure library for financial planning! https://github.com/sebhoss/finj/ has anybody used it?

21:16 dnolen: bbloom: I've having a back and forth with somebody about that one on Twitter, how a lot of those issues seem solvable with CSP, but he doesn't seem to think so - could be wrong about that - but it doesn't seem so to me.

21:17 bbloom: dnolen: so i'm beginning to think that it's just generally a good idea to minimize "upward funargs" to use some legacy vernacular

21:17 dnolen: when you register for a callback, you're effectively throwing a closure up to the infinity point of the stack: the event loop

21:17 dnolen: bbloom: yes

21:17 bbloom: dnolen: the lower down the stack your event loops & the less closed over context, the easier they are to reason about

21:18 dnolen: another example: higher order functions are easier to reason about than function factories

21:18 dnolen: people seem to have no problem learning map & reduce, but juxt and fnil and friends occur less often b/c people don't think to reach for them as much

21:19 dnolen: but once you close over *state* then you've got a compounded problem

21:25 dnolen: bbloom: I think the problem with that Twitter discussion is thinking that with CSP you even need a Stream abstraction

21:25 bbloom: agreed on your other points

21:27 bbloom: dnolen: Add to the infinite queue of projects: IStream that wraps core.async w/ good interop w/ seqs & channels

21:27 dnolen: not that i think it's a good idea

21:27 dnolen: bbloom: but what would IStream consist of?

21:27 bbloom: dnolen: basically Rx :-P

21:27 dnolen: bbloom: I think the the fact that Node.js has the notion of pause/resume troublesome.

21:27 bbloom: dnolen: it seems to me that it would be useful if you had to write a lot of async code, but much better idea: write a lot less async code

21:29 dnolen: bbloom: agreed, though of course many cases where you have no choice - those are the cases you want to account for.

21:31 bbloom: dnolen: yeah, i guess my view is now as follows:

21:32 dnolen: i can get by with like 1 or a very small number of atoms/refs/etc

21:32 dnolen: so i can probably get by with a very small number of async constructs

21:32 dnolen: well, "devices" is probably a better word, to use the zmq terminology

21:32 some bits of code literally need ONE atom

21:33 but other times i've got like one place that makes atoms & i have a variable number of atoms, but only one logical state "device"

21:33 similarly, i suspect the same would be true of async code

21:33 sdegutis: TEttinger: http://mikeash.com/getting_answers.html is the best one I've found

21:33 bbloom: dnolen: for example, i might have a server loop & a client loop

21:33 dnolen: or maybe the server also has worker loops

21:33 dnolen: while the running app may have 50+ goroutines, there really are only 3 devices: server, worker, client

21:34 dnolen: for such a small amount of async code, it makes sense to me to use a more general construct, even if it's slightly harder to use, since it will give me the flexibility and clarity i need

21:36 seancorfield: ooh! *claps hands* core.async talk!

21:37 i just posted to clojure-dev asking about stability and the proximity of an 0.1.0 release on maven central

21:37 heck, even an 0.1.0-alpha1 on maven central would make me happy :)

21:38 bja: +1 to that

21:38 also, is there a public CI for this?

21:38 I set one up local to my company as we began experimenting with core.async and wanted to stay abreast of changes

21:39 seancorfield: build.clojure.org

21:39 http://build.clojure.org/job/core.async-test-matrix/ specifically

21:39 all contrib libs are listed here http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go with links to their CI status, maven releases, and JIRA bug trackers

21:54 sdegutis_: I admit that today and yesterday I've been disrespecting the channel by asking questions that I really should have researched myself first. There's no excuse for that, and I'm going to make a more conscious effort to do my homework thoroughly before wasting anyone's time in here. I apologize.

21:54 But it's not always caused by habitual help vampirism. I work remotely and rarely communicate with other programmers, so socializing on IRC is a big help. And I'm sure I'm not the only person in this boat. And when you're already in here and have a question on the mind, the habit of typing it in the channel as a way of rubber-ducking can gradually form, much like thinking out loud.

21:54 And I recommend http://mikeash.com/getting_answers.html for future reference, it's written in a very welcoming style, much more likely to actually be read than some of the alternatives.

21:54 \cc callen

21:55 muhoo: sdegutis_: don't sweat it. i was a total black-hole of dumbass when i first started with clojure, way more than anyone i've seen on here since.

21:56 brehaut: "a total black-hole of dumbass" love it

21:56 muhoo: now i've got enough of my brain around this stuff that i can figure out most of what i need to just by reading docs and books and experimenting. you'll get there.

21:57 sometimes it just takes doing a few large-ish projects to find the horizon.

21:59 seancorfield: I'm actually impressed that #clojure has gotten so big without needing some sort of #clojure-n00b channel to help filter lots of basic questions away

22:01 ddellacosta: sdegutis_: I talked to you a lot yesterday and generally felt like you were being a pretty good IRC citizen.

22:01 sdegutis_: ddellacosta: Nah, I asked a few too many questions yesterday, and way too many today.

22:02 ddellacosta: sdegutis_: I feel like IRC is for asking questions, and if people want to say, RTFM they can, and if they want to say, "here's one way to do it" they can do that too. So I don't know what you did that was particularly bad, but I can understand personally feeling the need to dial it back.

22:02 sdegutis_: okay. Well, I'm not going to question your own feelings on the thing, but just giving you my subjective impression.

22:02 sdegutis_: :)

22:02 seancorfield: Some channels are a lot more tolerant of "noise" than others, as well.

22:02 sdegutis_: Part of the charm of #clojure is that the maturity level is (generally) extremely high, which means a really high signal/noise ratio.

22:03 seancorfield: indeed.

22:03 ddellacosta: SeanCorfield: I think there are times when it is noisy on here (and I am guilty of contributing to that) and times with a super high sound-to-noise ratio, but generally it's a good place to be.

22:03 TimMc: sdegutis_: And to the extent that you were exhibiting *any* bad behavior (very little!), callen was being a dick about it.

22:03 ddellacosta: s/sound/signal/

22:04 sdegutis_: TimMc: meh, we all have our bad days, all I can say is that I'm sorry that I was disrespectful to everyone in here and I'm gonna try to avoid it better from now on.

22:04 ddellacosta: callen can be a tough customer and prickly but generally he means well, in my experience.

22:04 TimMc: There's a 40% chance I would have banned callen by now if I were the channel founder.

22:05 Smart guy, has good experience... but pretty rude.

22:05 ddellacosta: TimMc: mean, he's helped me a TON on here, I just have to say. I know he rubs some people the wrong way but I get on with him pretty well, and I know a bunch of folks who do as well.

22:06 TimMc: yeah. I mean, again just expressing my subjective experience. I know everyone interacts with him differently.

22:06 TimMc: Oh, and I'm not talking about a permaban, just a 5 minute kickban.

22:06 sdegutis_: Anyone know of some good references on optimizing Clojure code, especially in tight loops where Java interop is happening? I've been reading Programming Clojure about type hints and when to use defrecord vs [etc], as well as the chosen answer here: http://stackoverflow.com/questions/5549319/real-world-clojure-performance-tuning-tips

22:08 ddellacosta: sdegutis_: depending on the problem at hand, I've had swapping out clojure data structures for java native data structures to produce a lot of speed gains, but of course it comes at a price

22:08 sdegutis_: sorry, you asked for references

22:08 technomancy: usually if there is reflection in a tight loop, it will overshadow any other potential causes of slowdowns

22:08 sdegutis_: technomancy: good to know

22:09 * sdegutis_ focuses on reading about getting rid of reflection with type hints and whatever else

22:09 ddellacosta: great link btw

22:09 mikera knows his shit...

22:09 technomancy: especially dispatch; you can optimize dispatch all day and you won't notice if there's a reflective call

22:10 sdegutis_: technomancy: hmm..

22:10 technomancy: sdegutis_: `lein check` will show all reflective points

22:11 sdegutis_: technomancy: what do you mean by dispatch?

22:11 technomancy: *whoa*, cool

22:11 technomancy: sdegutis_: like replacing multimethods with protocols

22:11 sdegutis_: ahh

22:11 technomancy: but `lein check` will include ones that aren't in tight loops, so pay attention

22:11 sdegutis_: right :)

22:12 Yeah I read recently that multimethods were deprecated in favor of protocols.. Not sure if that's legit though, gotta research more.

22:12 ambrosebs_: sdegutis_: on HN?

22:12 technomancy: totally BS

22:13 multimethods are much more powerful

22:13 sdegutis_: ambrosebs_: don't think so..

22:13 brehaut: structs were deprecated in favour of records, but thats the only related deprecation

22:14 ambrosebs_: sdegutis_: I remember a comment on a very popular Clojure post. That guy was full of it.

22:14 nvm

22:14 sdegutis_: Oh, "Use deftype/defrecord/defprotocol where appropriate. These are heavily optimised, and in particular should be preferred to defstruct/multimethods as of Clojure 1.2 onwards." in that SO link.

22:14 I misinterpreted what he said.

22:16 technomancy: still pretty suspect

22:17 cjfrisz_: Oh man..I missed the conversation about being able to ask newb questions

22:18 I was really cranky about the "don't ask questions when there's so much great documentation," but took the coward's way out of grumbling into my code instead of saying anything

22:19 seancorfield: great documentation? where?

22:19 * seancorfield ducks and runs

22:19 ambrosebs_: haha

22:20 seancorfield: mmm, core.async would be such an elegant solution to a problem i have to solve (for real production code!)... just did a p.o.c. and it's so much cleaner than anything else i've yet come up with for this problem...

22:21 mlb-: What's the commonly refered name of the "->" macro?

22:21 seancorfield: thread

22:21 thread-first for -> and thread-last for ->>

22:21 cjfrisz_: mlb-: also known as one of my least favorite parts of Clojure

22:21 seancorfield: (i believe)

22:21 cjfrisz_: you no like? nor as-> / some-> / cond-> i guess? :(

22:22 S11001001: seancorfield: we always called it arrow

22:22 mlb-: cjfrisz_: easily abused?

22:22 S11001001: hence rplevy's "swiss-arrows" name for his lib

22:22 cjfrisz_: seancorfield: I actually really like as->

22:22 Haven't messed with the others yet

22:23 mlb-: I find that they make code unreadable for non-trivial uses

22:23 sdegutis_: cjfrisz_: but as-> only makes sense inside -> or ->>

22:23 ddellacosta: SeanCorfield: what's stopping you from using core.async--the pre-alpha-status of the lib? (Admittedly enough I suppose, even if it works quite well)

22:23 cjfrisz_: sdegutis_: I disagree

22:23 sdegutis_: cjfrisz_: and I have to disagree, -> and ->> make code way more readable in my experience

22:23 seancorfield: ddellacosta: leiningen scowls on having release builds depending on snapshots :)

22:23 cjfrisz_: sdegutis_: I find that depends on prior experience reading inside-out Lisp code?

22:23 Er…not ?

22:24 seancorfield: ddellacosta: and this is production code, after all so i'm wondering how stable core.async really is...

22:24 cjfrisz_: sdegutis_: Also, I find as-> as a _replacement_ for -> in many places

22:24 ddellacosta: SeanCorfield: ah. I always rename things and install via uberjar, maybe it's bad form. ;-)

22:24 SeanCorfield: yeah, that's a fair point. I ask because I'm in a similar boat, and wanted to know if you'd experienced anything in particular...

22:25 sdegutis_: cjfrisz_: here's one use of -> I like https://www.refheap.com/16959

22:25 cjfrisz_: For stuff like (-> my-map :int-key inc), I think -> is fine, but when you have functions in there that take multiple arguments, it quickly turns into a mess

22:25 sdegutis_: cjfrisz_: that sounds highly suspect to me

22:25 seancorfield: ddellacosta: i asked on clojure-dev for guidance but may go ahead and integrate my p.o.c. and just hammer it under test...

22:25 TimMc: mlb-: I prefer "stitch-first" and "stitch-last" to avoid confusion with concurrency topics. :-)

22:25 bja: ddellacosta: I took the implement and measure approach. we've already shipped some alpha releases of a dashboard/search system based on core.async to our internal group

22:26 ddellacosta: SeanCorfield: yes, would definitely be interested to hear more what your experiences are like.

22:26 sdegutis_: "The friend of my friend is my enemy"

22:26 ddellacosta: bja: glad to hear it. No big issues so far?

22:26 bja: ddellacosta: plans on releasing to paying customers in a private beta in about a month

22:26 nope

22:26 we have nothing to compare it to though

22:26 ddellacosta: bja: that's part of the problem, haha

22:26 bja: but we were doing stress testing to make sure it's capable of handling the load we want to throw at it

22:26 cjfrisz_: sdegutis_: I really find it comes down to personal taste

22:27 ddellacosta: bja: but yeah, I've written a half dozen little one-offs with it by now, and will start writing some code integrating it on the CLJS side at first

22:27 seancorfield: it's not like we haven't gone to production with prerelease builds before... we went live with clojure 1.3 alpha 7 two years ago... and we've been using alpha builds of java.jdbc 0.3.0 in production for... months...

22:27 sdegutis_: cjfrisz_: let's agree to disagree about that

22:27 ddellacosta: SeanCorfield: yah, good point

22:27 cjfrisz_: sdegutis_: There was a newbie in here at one point who got understandably confused about lexical scope because a piece of code he was looking at used -> in a weird way

22:27 And I was already predisposed against it, so that completely soured me on it

22:28 seancorfield: bja: your experience sounds encouraging ... thank you!

22:28 ddellacosta: ditto

22:28 bja: ddellacosta: we were in a boat of nobody really being a frontend person so we had to pick something to learn to ship an app. cljs+core.async seemed less threatening than needing to learn angular

22:28 sdegutis_: cjfrisz_: ->> is almost mandatory for clean code when doing a bunch of map/filter/etc in a row

22:28 bja: then again, none of us have every really done anything besides integrating jquery plugins before either. so our app probably looks nothing like a typical web app

22:29 although it does remind me a Qt app I wrote once

22:30 cjfrisz_: sdegutis_: I see your point, though I'd likely break up that computation rather than use ->> (again, personal taste

22:30 ddellacosta: bja: interesting. I'm now struggling through the right paradigm to use for frontend development. Having Clojure on the backend and CLJS on the front-end brings some gains in terms of avoiding context switching and maintaining similar data structures, but I'm really looking forward to being able to do stuff (along with browser channel) where we are pushing messages back and forth on channels using only core.async. But that's not

22:30 really addressing the stuff regarding DOM updates, so still trying to figure that part out.

22:30 cjfrisz_: Even though bbloom and I just had a conversation about how I don't like to let-bind computations that get used exactly once :-)

22:30 sdegutis_: cjfrisz_: can you show me an example of it broken up like you say? Maybe I just haven't seen it done right.

22:30 ddellacosta: bja: this was an interesting, useful article I thought: http://keminglabs.com/blog/cljs-app-designs/

22:30 callen: seanaway: are you at the meetup?

22:30 TimMc: <3 you too.

22:31 seanaway: callen: no, couldn't make it this month, nor next, so Amit is running the SF group for a while

22:31 ddellacosta: bja: but anyways, always interested to hear more about what people's experiences have been with CLJS, especially with core.async

22:31 bja: in our app, we have a "widget controller" which coordinates with other widgets and our query service. It's responsible for maintaining it's local data structure and rending it into a template when it changes

22:31 callen: seanaway: cool, well hopefully I'll catch you sometime in the near future, would love to talk about c.j.j for a bit.

22:31 seanaway: ddellacosta: we're consider cljs + angularjs based on some of the stuff kevin lynagh posted about the kerning labs app etc

22:32 ddellacosta: damn, maybe I should move to a city/country with a Clojure meetup…or I guess start one here

22:32 callen: seanaway: keming labs ain't it? or is that the joke?

22:32 ddellacosta: seanaway: definitely want to talk more. I'm reluctant to integrate angular but I haven't given it a fair shake yet, to be honest

22:32 TimMc: callen: I wouldn't *like* to do it. :-(

22:33 seanaway: callen: i won't be at any meetups for a while - ping me on IM if you want (skype, aim, y!m... or gtalk... should be obvious what my handle is on all of those :)

22:33 callen: ddellacosta: I'm fond of Angular, but you have to be okay with the design philosophically speaking.

22:33 seanaway: fair enough, thanks :)

22:33 TimMc: awww. thank you. :)

22:33 ddellacosta: callen: yeah, I should write a few simple apps with it to get a feel before I judge it

22:33 seanaway: oh year, keminglabs.com ... always read that as k-e-r-n-ing... silly me!

22:34 TimMc: seanaway: Every. Single. Time.

22:34 ddellacosta: ddellacosta: mostly I'm not excited about integrating an outside JS lib, but that's probably irrational

22:34 seanaway: http://keminglabs.com/blog/

22:34 ddellacosta: whoops, addressed me

22:34 was to callen

22:34 cjfrisz_: sdegutis_: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62

22:34 callen: ddellacosta: very good idea. part of the reason I like angular is that it lends itself well to being isolated widgets, pages, and growing from there to whole apps.

22:35 ddellacosta: callen: interesting. I'll give it a shot and see what I learn.

22:35 callen: ddellacosta: well you just have to decide if Angular does things in a way you're happy with. I think it's a productive way to do most SPAs.

22:35 sdegutis_: cjfrisz_: why do you prefer the last one? because it has all 3 args in it at once?

22:35 ddellacosta: callen: yeah, we have a…semi-SPA, so it may be appropriate, we'll see.

22:35 cjfrisz_: sdegutis_: I didn't repl-check that code, so it might have typos in it

22:35 sdegutis_: cjfrisz_: I mean, because each fn (map/reduce) have all args and no magic?

22:35 cjfrisz_: sdegutis_: precisely

22:36 sdegutis_: cjfrisz_: hmm, that is kind of neat

22:36 ddellacosta: callen: but anything is better than what we have now, which is a mix of old CoffeeScript with a ton of hard-coded selectors, which I'm slow porting over, and some "stopgap" CLJS

22:36 makes me cry

22:36 callen: ddellacosta: yikes.

22:36 sdegutis_: It certainly eliminates the need for as-> within it for when the arg isn't in the position you wnat

22:36 ddellacosta: callen: yeah, I do a lot of sticking fingers in leaking holes

22:37 callen: meh, it did what it needed to do for a while though, and it'll get better.

22:37 sdegutis_: cjfrisz_: btw I made a slight adjustment to how I'd do the ->> version: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62#comment-901309

22:38 cjfrisz_: sdegutis_: Ah, that does make it a little better

22:39 sdegutis_: There's still something that bothers me about implicitly keeping track of where the invisible value gets inserted

22:39 sdegutis_: cjfrisz_: I can see that. I'm not sure where I stand on the issue now that you gave this example.

22:39 cjfrisz_: thanks

22:39 cjfrisz_: sdegutis_: no problem :-)

22:40 bbloom: cjfrisz_: gotta embrace the threading macros :-)

22:40 cjfrisz_: bbloom: nooooooooo :-O

22:40 bbloom: cjfrisz_: they make pipelines incredibly clear

22:40 sdegutis_: I'll defer my opinion on it: (def my-opinion (future (defer-opinion gfredericks)))

22:40 bbloom: cjfrisz_: also make it super nice to skip or insert steps when debugging

22:41 cjfrisz_: If those pipelines are all (rator rand) then I'm totally cool with it

22:41 bbloom: cjfrisz_: for example try throwing (doto prn) into a -> pipeline

22:41 glorious.

22:41 sdegutis_: bbloom: have you seen his example?

22:41 bbloom: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62#file-gistfile1-clj

22:41 bbloom: sdegutis_: what about it?

22:41 sdegutis_: bbloom: as-> looks compelling in it

22:42 bbloom: sdegutis_: *shrug* not if they are all thread-last

22:42 sdegutis_: no implicitness about arg positions, it's all on screen

22:42 bbloom: sdegutis_: there is no implicitness with -> and ->>, it's right there lexically explicit :-)

22:43 but i'm the guy who wrote a concatenative DSL, so my opinion might not count here :-P

22:43 swap, dip, keep, drop, bi, cleave, etc -- now *that's* implicit :-)

22:43 sdegutis_: bbloom: also I've had times where I wanted to do another form in the middle of the threading (maybe a let-block) and the magic stepped on my toes, but with this as-> version that's a non-issue

22:44 granted, I can't think right now of *legitimate* reasons for wanting to stick something in the middle of such a threading chain, but it could have been legit

22:44 bbloom: basically the style rule is that -> for threading through "this" and you can think of -> the same way you think of dotted.memberAccess.likeThis.inOOP

22:45 and ->> threading through last for when you've got a bunch of operations where it would make a lot of sense to curry the first args, like sequence ops. in cjfrisz_'s example, you could conceivably (def sum (comp reduce +)) and (def product (comp apply *))

22:45 nevermind that you could also apply + and reduce * 1 ;-)

22:46 cjfrisz_: bbloom: thanks for simplifying my highly contrived example ;-)

22:47 sinistersnare: i always have trouble understanding ->

22:47 i get its threading, but being a clojure (/lisp) newbie, its still hard to fathom

22:47 callen: sinistersnare: ,,,

22:47 bbloom: sinistersnare: that's why i draw the parallel between -> and dotted access chains

22:47 nightfly: sinistersnare: Look at how the macro is expanded a few times.

22:47 callen: sinistersnare: http://blog.fogus.me/2013/09/04/a-ha-ha-ha-aah/

22:47 TimMc: Yeah, ,,, is a good crutch.

22:48 bja: sinistersnare: clojure.walk/macroexpand-all is your friend

22:48 callen: bja: just let the ,,, magic happen.

22:48 bbloom: bja: except when it lies to you :-P

22:48 bja: bbloom: macroexpand lies to you? I feel like I'm getting lied to and I don't know it

22:48 gfredericks: what is this ,,, nonsense?

22:49 coventry: bja, bbloom: riddley.walk/macroexpand-all tries to do a more accurate job.

22:49 gfredericks: is this what fogus was tooting about?

22:49 coventry: If you're going to use ,,, why not use as->?

22:49 sinistersnare: oh cool

22:49 gfredericks: oh it's sticking a comma in the threading position for reference? or three commas?

22:49 callen: gfredericks: yeah

22:49 bbloom: the best thing about -> and ->> is that they are obvious to indent. i still can't figure out how to indent multi-line chains in java, scala, javascript, coffeescript, etc

22:50 callen: gfredericks: yeah to both questions.

22:50 another way to learn how -> and ->> work is to reinvent them.

22:50 gfredericks: oh look he has a blag

22:50 callen: I don't think they merit much pondering though.

22:52 dobry-den: haha, i just read about ,,, on http://rubylearning.com/blog/2010/07/26/clojure-tips-from-the-experts/

22:53 cjfrisz_: bbloom: my only problem with -> and ->> is that there's just a touch more parsing you have to do in your head when reading them to remember where the implicit expression is going to go

22:54 bbloom: cjfrisz_: but less paren counting :-)

22:54 dobry-den: or when ->> works for all argument order except for one function

22:54 bbloom: cjfrisz_: they can dramatically reduce stacked up close parens

22:55 cjfrisz_: bbloom: Look, I've written a *lot* of Scheme in my time; I'm so friggin fast at counting those parens :-p

22:55 Foxboron: cjfrisz_: i think having a imperative background helps you a lot reading ->> and ->

22:55 cjfrisz_: I think it also relates to why I don't like let* in general in Scheme

22:55 bbloom: cjfrisz_: it's interesting. i love the prefix notation & much prefer the explicitness of parens, but if i see like ))))) i suddenly cringe & refactor

22:55 Foxboron: my only problem is trying to recall which one does what

22:56 bbloom: cjfrisz_: a few extra names here or there can dramatically reduce stacked up parens & make code much easier to read

22:56 sdegutis_: technomancy: wow thanks for the tip for lein check, this is super helpful

22:56 cjfrisz_: That's why I'm currently a fan of as->

22:56 It takes care of most of that bit of mental parsing by naming the bit that's getting threaded through

22:57 bbloom: cjfrisz_: but when i see as-> i say "oh no, i have to be on the look out for non-standard argument positions"

22:57 cjfrisz_: it's like when people stick fucking ! on everything

22:57 sinistersnare: ,(doc as->)

22:57 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

22:58 cjfrisz_: bbloom: It's not really any worse than a let-bound variable

22:58 bbloom: cjfrisz_: right, but it's also no better ;-)

22:58 cjfrisz_: as-> is strictly less clear than let, unless you're mixing it in to an existing -> and ->>

22:58 so far, i've needed as-> like twice ever

22:59 cjfrisz_: bbloom: That's probably because you're more willing to use -> or ->> than me

22:59 I totally use as-> in places where other people would use -> or ->>

23:00 bbloom: cjfrisz_: but in your "best, in my opinion" example. why not just use let?

23:00 https://gist.github.com/cjfrisz/7f3e118098bb7a472e62 <- i added a comment

23:01 oh dur, i'm an idiot

23:01 cjfrisz_: bbloom There's something uneven looking about those kinds of lets

23:01 bbloom: wait, i don't even know how as-> works

23:01 cjfrisz_: bbloom: Again, why I'm always cranky that Clojure only has let* semantics for let

23:01 bbloom: (doc as->)

23:01 clojurebot: "([expr name & forms]); Binds name to expr, evaluates the first form in the lexical context of that binding, then binds name to that result, repeating for each successive form, returning the result of the last form."

23:01 bbloom: so does num-vec change it's binding every time?

23:01 i've never used an as-> bound name more than once

23:01 are those 3 different values for num-vec ?

23:02 i *never* override names unless it's a loop or something really obvious

23:02 i'd rather have num-vec and num-vec* and num-vec** or some more descriptive names

23:02 cjfrisz_: as for parallel let, that's b/c clojure discourages you from having cyclic structures, which is actually a really good thing

23:02 cjfrisz_: if you're gonna have immutable data, then a cycle KILLS your potential for structural sharing

23:03 cjfrisz_: you can't copy *part* of a cyclic structure

23:03 cjfrisz_: you need an indiction, which is what "identities" give you (ie IDeref)

23:03 cjfrisz_: s/indiction/indirection/

23:04 cjfrisz_: the ease with which you can tie the knot in haskell is a very bad thing. it's absurdly difficult to reason about pointer cycles

23:04 cjfrisz_: bbloom: In all the times that I've complained about let, nobody has ever made that argument

23:04 I'ma need to let that one soak in for a minute

23:04 bbloom: pointers are like having only one concrete implementation of IDeref

23:04 where you can't ever change the value it points to

23:05 a pointer is the least useful type of identity there is

23:05 there can be no sensible succession of values

23:05 that's why there is letfn: you can't edit a function anyway, so there is no sense having structural sharing

23:05 but if there was, you'd just inline one mutually recursive function in to the other

23:06 cjfrisz_: bbloom: I'm really not sure if I'm misunderstanding you or you me

23:06 bbloom: cjfrisz_: you're talking about sequential vs parallel let, right?

23:06 cjfrisz_: scheme & common lisp have let and let*

23:06 let is parallel, let* is sequential

23:06 cjfrisz_: I understand your point, but for the life of me can't wrap my brain around how it relates to Scheme's let semantics

23:06 bbloom: clojure has let and letfn

23:06 let is sequential, letfn is parallel

23:07 cjfrisz_: bbloom: right

23:07 bbloom: parallel bindings enable cyclic structures

23:08 cyclic structures are an anti-feature for most use cases, in my opinion

23:08 sdegutis_: amalloy_: does being so prolific on stackoverflow get many contracting gigs knocking on your door?

23:08 cjfrisz_: bbloom: You seem sure enough that I don't want to discount what you're saying, but I don't think that Scheme/CL let enables cyclic structures the way you're claiming

23:08 letrec, yes

23:09 bbloom: cjfrisz_: i haven't written much scheme/CL, so let me go look at docs & refresh my memory. but i can't see what the point of parallel bindings would be w/o recursive definitions

23:11 gfredericks: I just tried scheme

23:11 let is parallel in the sense of none of them are visible to the others

23:11 cjfrisz_: bbloom: Scheme/CL -- (let* ([a 1] [b a] [c b]) c) === (let ([a 1]) (let ([b a]) (let ([c b]) c)))

23:12 bbloom: ok so i had forgotten about letrec

23:12 cjfrisz_: let* in Scheme is always a really simpl

23:12 bbloom: what's the use of parallel let without letrec ?

23:12 cjfrisz_: Er…didn't mean to send that

23:12 bbloom: cjfrisz_: i get the usefulness of let* and letrec, but what's the use of let?

23:13 cjfrisz_: bbloom: Makes lexical scope clearer and discourages imperative programming

23:13 bbloom: cjfrisz_: in what way does it do either of those things?

23:13 gfredericks: (letrec ((x (cons 3 '())) (y (cons 4 x))) y) ;; => (4 . #!unbound)

23:14 cjfrisz_: bbloom: let* in Scheme when used properly is a signal of "these bindings are very much related and the value of one is dependent on the other"

23:14 sdegutis_: you guys are such nerds

23:14 so awesome :)

23:14 cjfrisz_: sdegutis_: :-D

23:15 callen: cjfrisz_: I have sequential bindings so often that I like sequential let being the default.

23:15 gfredericks: maybe that's the imperative programming he was referring to?

23:15 cjfrisz_: ^^^

23:16 There's certainly nothing wrong with it

23:16 bbloom: cjfrisz_: *shrug* i don't like to shadow names if i can help it, so when i cursor over a name and it lights up in other places, i can see the dataflow. if it shows up on the very next line, then yeah, it's sequential :-P

23:16 cjfrisz_: The downside the parallel let is that it tends to make your code indent further

23:16 amalloy: sdegutis_: i don't do contracting; being prolific on SO and IRC is what got me my current job

23:17 sdegutis_: amalloy: ok

23:17 cjfrisz_: But preferring parallel let does make it obvious that any variable is bound in a strictly enclosing scope

23:17 bbloom: cjfrisz_: hold on. gotta kill a giant fucking bug

23:17 gfredericks: man bbloom gets passionate about debugging

23:18 bbloom: cjfrisz_: no like one with legs....

23:18 cjfrisz_: gfredericks: I think bbloom is just into really, *really* traditional debugging

23:18 bbloom: er i mean cjfrisz_

23:18 gfredericks: man bbloom really does not want to say my name

23:19 cjfrisz_: that's interesting about the scoping

23:21 bbloom: LOL

23:21 gfredericks: sorry man

23:21 cjfrisz_: gfredericks: it's nice

23:21 bbloom: gfredericks: total brain fart b/c i had to kill that ugly mother fucker

23:21 gfredericks: no idea what that thing was, it had like a ton of legs & didn't look friendly

23:22 cjfrisz_: but w/ parallel let, that scope is *further down* under the other bindings

23:22 cjfrisz_: w/ sequential let, it's the very next line. close locality

23:22 cjfrisz_: bbloom: but then you don't have indentation as a visual cue

23:22 bbloom: cjfrisz_: yeah, it's a larger extent than w/ parallel let, but i don't think it's a big deal

23:23 cjfrisz_: bbloom: Agreed. I'm just an old PL curmudgeon and don't like things that are different than what I'm used to

23:24 bbloom: cjfrisz_: *shrug* i think i'd get annoyed that i'd have to nest more deeply if i wanted to use a binding in an intermediate expression. i like forms that flatten my code

23:26 cjfrisz_: as for the "imperative style" thing, i think you need to ask yourself "why is it a good thing that i don't program in an imperative style?"

23:26 cjfrisz_: if your answer is "functional is good" then you lose :-)

23:27 cjfrisz_: clojure is all about… because rich is all about…. separating out the components of things to understand the essence of why we do things the way we do them & how we can do them better

23:27 cjfrisz_: turns out that immutablity is 100X more important than not sequentially refining values

23:27 cjfrisz_: bbloom: I don't dispute that

23:28 bbloom: but it's still nice to have separate let and let* to make the visual distinction of when rebinding is likely to happen

23:28 If it bugged me that much I would probably have a far lower volume of Clojure code

23:28 It's just one of those things that Schemers notice and think is weird and people who started with Clojure don't notice and think is fine

23:28 bbloom: fair enough :-)

23:29 but the letrec thing is a big deal ;-)

23:29 cyclic structures without explicit identities == nightmare

23:29 brb

23:30 cjfrisz_: bbloom: Agreed

23:30 bbloom: Hence why there had to be a series of papers called "Fixing Letrec"

23:30 It turns out that pretty much all of them do it wrong

23:31 I do have to say that it's really, really smart that Rich decided not to add letrec to Clojure

23:35 sdegutis_: I find myself day after day saying "wow, Rich (and the team?) made a great decision [including/excluding] [that/that] feature".

23:35 cjfrisz_: sdegutis_: agreed

23:36 shaungilchrist: it is definitely what keeps me happy with clojure

23:36 unlink: When I run `lein ring server', it thinks for a second, and then exits with error code 0, printing nothing.

23:36 cjfrisz_: Overall, Clojure is a really well-designed language

23:36 sdegutis_: unlink: does your project.clj point to a legit handler?

23:36 unlink: sdegutis_: yes.

23:36 cjfrisz_: Most of my qualms are nit-picky, and the things that bother me the most are because of the JVM

23:37 unlink: lein ring war works.

23:37 cjfrisz_: But the benefits of the JVM are also really nice

23:37 sdegutis_: Yeah, I do enjoy that my code is much faster than Ruby.

23:38 cjfrisz_: sdegutis_: I lolled

23:39 bbloom: cjfrisz_: i'm not familiar with the fixing letrec series. what's the gist?

23:39 shaungilchrist: It definitely helps to be able to show the viability of jvm interop when a potential client winces when you say "lisp"

23:39 sdegutis_: shaungilchrist: oh man, you get clients?

23:39 * sdegutis_ can never figure out where to find these "clients"

23:40 shaungilchrist: just build things people want and it happens

23:40 unlink: hah

23:40 gws: you can even build things people don't want, and hire "sales people" (i dunno, that's what they said to call them) to convince "clients" that they want the thing

23:40 sdegutis_: shaungilchrist: but I have.. https://github.com/sdegutis/zephyros

23:41 gws: that seems downright immoral

23:41 cjfrisz_: bbloom: That dealing with undefined values is really hard when you allow for arbitrary cyclic expressions

23:41 bbloom: It gets even worse when you have first-class continuations in the mix

23:41 gws: sdegutis_: i agree, but somebody said it was "good business sense" and i just believed them

23:41 sdegutis_: :)

23:41 oh man, just one more star

23:43 bbloom: cjfrisz_: yeah, i'm 100% against cyclic pointer structures, as you can tell

23:43 cjfrisz_: bbloom: Me too

23:43 I honestly don't remember the last time I used a letrec

23:44 bbloom: cjfrisz_: as for first-class continuations, oleg & company have sold me on the delimited continuations thing. shift/reset is a nightmare tho, i really like what the Eff folks are doing. huge fan of that approach

23:45 cjfrisz_: bbloom: It's been long enough since I thought about delimited continuations that I forget the differences between the three versions, but I remember that Felleisen's prompt/k was better than shift/reset

23:46 bbloom: Dybvig has also told me that he would prefer prompt/k over call/cc

23:46 bbloom: cjfrisz_: turns out that there are 4 versions, but i think one is clearly a dumb idea :-P

23:46 cjfrisz_: bbloom: remembering that there were 3 was a guess, too

23:47 I remember that shift/reset was Danvy and prompt/k was Felleisen, and there was one I don't remember who came up with

23:47 bbloom: cjfrisz_: anyway, the low-level encoding that seems to be preferred is newPrompt, pushPrompt, withSubCont, pushSubCont

23:47 cjfrisz_: And apparently possibly another that's super dumb

23:48 bbloom: cjfrisz_: basically, gensym, mark stack, capture range of stack, install range of stack

23:48 cjfrisz_: bbloom Right, and those four can be used to implement any of the models

23:48 sinistersnare: random question: has it ever been thought to make asm.js a viable backend for clojurescript compilation?

23:49 cjfrisz_: Did you pick that up from Dybvig, Sabry, & Oleg's Monadic Framework for Delimited Continuations?

23:49 sinistersnare: i get that asm.js is more of a static language, maybe we should enforce typed-clojure on it then :p

23:49 bbloom: cjfrisz_: yeah, but then you have first class "sub continuations", which are just ranges of the stack. but i don't think you really need those. i think the effect/handlers model covers all the bases & is much easier to work with

23:49 sinistersnare: i mean core.typed*

23:49 unlink: I am able to run the war created by `lein ring uberwar' in tomcat, but `lein ring server' exits without an error (or error status code).

23:49 bbloom: cjfrisz_: that's where i grabbed it from just now, but it is also in the ocaml & haskell demo implementations

23:49 cjfrisz_: similar names, same functions

23:50 cjfrisz_: bbloom: I need to reread that; I don't think I was careful enough the first time or actually understood what I read

23:50 bbloom: and it's been about a year and a half, I think?

23:51 bbloom: Dybvig grilled me on it at my Cisco interview for kicks

23:51 bbloom: cjfrisz_: it's probably the most enlightening paper on delimited continuations, even though i find talk of monads to be generally gobblty gook

23:51 cjfrisz_: bbloom: agreed on that last bit :-)

23:52 bbloom: cjfrisz_: but what made it all FINALLY click for me was this paper: http://arxiv.org/abs/1203.1539

23:52 cjfrisz_: bbloom: And earmarked for later

23:55 bbloom: cjfrisz_: i'm a big believer in "capabilities" as a security model, both for actual security & as a simpler/superior model for private/public/etc

23:55 cjfrisz_: i like the idea that i can control which parts of my app can have which side effects by controlling whether or not i pass a particular object to that path of code

23:56 cjfrisz_: bbloom: That is a cool idea

23:57 bbloom: cjfrisz_: yeah, see this one too for a haskell version: http://www.reddit.com/r/haskell/comments/1j9n5y/extensible_effects_an_alternative_to_monad/

23:58 cjfrisz_: bbloom: I've been meaning to read that; one of my friends is the third author

23:58 But I didn't know he could do any Haskell

23:59 bbloom: cjfrisz_: cool. in general, this feels like to me a way to get all the cool tricks monads give you without any category theory nonsense AND sensible composability w/o monad transformer stacks. meanwhile, you get to keep a straightforward, direct style of programming

Logging service provided by n01se.net