#clojure logs

2013-09-05

00:06xeqiddellacosta: I'm surprised how little value is placed on a test suite as regression prevention and code explination
00:07ddellacostaxeqi: 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.
00:07ddellacostaxeqi: 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
00:07clojurebotOk.
00:10ddellacostahear what I'm saying clojurebot?
00:12dnolenddellacosta: figuring out what to test is hard
00:14ddellacostadnolen: 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.
00:15ddellacostaanyways, I'm really interested to hear more of how people have approached this in their real-world Clojure projects.
00:15ddellacostaobviously a lot of folks are doing testing, in any case.
00:15sdegutisddellacosta: that's not unique to FP, most people I know can't tell the difference.
00:16sdegutisEven in Ruby land.
00:16sdegutisMyself included.
00:16ddellacostasdegutis: 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!
00:16ddellacostasdegutis: yeah, haha
00:17sdegutisI stopped worrying about unit tests and now I only focus on highest-domain-level integration tests.
00:17dobry-denall of my clojure projects are toy projects and i like inlining core.assert into source
00:17gwsi like to test things that could conceivably go in a spec for the project
00:17sdegutisI only do unit tests when I'm not sure something will work. And I only use integration tests to prevent regressions.
00:17gwsnot every little mechanical unit of code needs to have a test
00:17sdegutis(inc gws)
00:17lazybot⇒ 1
00:18sdegutisI used to test way too much, and my tests were bad, very possibly causing more damage than having no tests.
00:19gwsyeah, and causing extra overhead each time you refactored some unit...
00:19gwsbeen there :(
00:19sdegutisI guess we've both learned the hard way. But maybe there's no other way to learn.
00:19xeqiI find the most value at the feature test level
00:20gwsddellacosta: i think you're seeing a pattern :)
00:20sdegutisxeqi: yeah that's what I called "domain level".
00:20ddellacostagws: yah, maybe so!
00:21sdegutisBasically 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.
00:21xeqithough I wrote/ported two libraries to let you test ring apps that way, so I might be biased there
00:21sdegutisEven 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.
00:21sdegutis(For example moving away from MongoDB to Datomic.)
00:22ddellacostaI'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
00:22ddellacostaresolve and fix (I believe) because of the way I had approached it.
00:22ddellacostabut I've also had a lot of experiences like sdegutis where I test too much, my tests become brittle and hard to maintain
00:23xeqiunit 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
00:23sdegutisAnd 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?
00:24ddellacostasdegutis: 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.
00:25ddellacostabut yeah, with what xeqi and sdegutis are saying, I'm definitely seeing some trends.
00:25sdegutisddellacosta: 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.
00:25sdegutisOn one hand those tests are testing *both* feature-level and HTTP-level logic, which violates single-responsibility principle.
00:25ddellacostainteresting.
00:25ddellacostaare you talking specifically about Clojure, or some other platform?
00:25sdegutisAlso, they make it really easy to move feature-level code *into* HTTP-level code.
00:26sdegutisYes, this is for work, which is a Clojure app.
00:26sdegutisI'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.
00:26ddellacostaokay, interested to hear
00:26xeqisdegutis: are you using a lib for your "controller" tests?
00:27sdegutisNot that the website looks bad, it fit in just fine a few years ago.
00:28sdegutisxeqi: 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.
00:29sdegutisWe'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).
00:30sdegutisxeqi: joodo and speclj are tightly integrated, and joodo has "with-mock-rendering" and "with-routes".. http://joodoweb.com/tutorial/controllers
00:32ddellacostahuh, interesting. Never seen joodo but I have a bunch of routing helper functions which do a lot of the same things
00:33ddellacostaand which I feel mixed about. haha
00:34sdegutisI am personally not a fan of the abstractions it provides, which were borrowed heavily from Rails.
00:34sdegutisHowever, it executes them very well.
00:34ddellacostayeah, I remember looking at speclj and thinking, "uh, not sure we want Rspec in Clojure..."
00:34ddellacostaI'm sure
00:36sdegutisThat'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.
00:38technomancy"cultural fit" might be more convincing
00:38sdegutisNo comprendo amigo.
00:38technomancyyou can do it, but everyone will look at you funny
00:38technomancylike putting each paren on its own line
00:40xeqisdegutis: does that setup require you to specify the middleware stack in each (with-routes ..) ?
00:41sdegutistechnomancy: 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.
00:42sdegutisxeqi: with-routes is only used in tests, and he recommends not putting middleware in tests.
00:43sdegutistechnomancy: because when you have a message you want to get across to the world, that's more important than conforming to conventions.
00:43xeqiand you can write your "domain level" tests without middleware ?
00:44sdegutisxeqi: I'm not sure how to answer that.
00:44clj_newb_2345is 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
00:45xeqiyou 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
00:46sdegutisTo 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.
00:47xeqiclj_newb_2345: add (:refer-clojure :exclude [*]) to the ns declaration
00:47clj_newb_2345for eveyr file?
00:47clj_newb_2345is there a way to put it into some type of lein config?
00:47sdegutisxeqi: 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.
00:48sdegutisxeqi: 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.
00:49xeqisdegutis: ah, I was refering to a test that simulates how a user would interact with the system
00:49sdegutisxeqi: that's what I'm talking about too. Just at another level lower than HTTP.
00:50sdegutisI look at HTTP like a bridge between the user and the code, and that's helping my code a ton.
00:50sdegutisIdeally nothing in my test suite would test HTTP-level code at all.
00:51xeqisdegutis: so you test your route configuration to non-http-level code elsewhere?
00:51sdegutisxeqi: No, I don't test it.
00:52xeqiah
00:52sdegutisxeqi: Every time I make a change that could break one of those such tests, I always re-check that route in my browser anyway.
00:52sdegutisxeqi: 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.
00:53xeqi"at that level" ?
00:53sdegutisTesting my HTTP-bridging code.
00:53sdegutisThe production code that lives inside (defroute ...) and calls (add-to-cart).
00:54sdegutisIt might make more sense for a bigger project with a bigger team. But this is a one-man small website.
00:57reshpectabiggleReally? Nobody had this nick?
00:57reshpectabiggle*snatched*
01:00xeqiwe 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
01:01reshpectabigglexeqi: 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.
01:02reshpectabiggleI mean raw incoming data.
01:02reshpectabiggleThat encourages things like :packer and :type, in https://github.com/8thlight/hyperion#entities
01:05reshpectabiggleIt 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.
01:07ddellacostaargh, power died and looks like I missed out on some testing conversation
01:08respectabiggleddellacosta: http://logs.lazybot.org/irc.freenode.net/%23clojure/2013-09-04.txt
01:08respectabiggleScroll to the end.
01:08ddellacostarespectabiggle: cool, thanks. :-)
01:08respectabiggleAnyway I would take what I've said with a large dose of salt, I've only been at this for a few years.
01:09xeqiyou still have the conversion code right?
01:09ddellacostawtf does "gaeshi" mean
01:09sdegutisUhh..
01:09sdegutisddellacosta: It's from martial arts.
01:09ddellacostaah, google app engine pun, clever
01:10sdegutisddellacosta: ever heard of 8th Light?
01:10ddellacostasdegutis: yah, but what does it mean?
01:10ddellacostasdegutis: most definitely, I know Uncle Bob and Colin Jones are there
01:10ddellacostaamong others
01:10sdegutisHmm, where do you know them from?
01:10sdegutisI mean, besides 8L.
01:11ddellacostasdegutis: I mean, they are not people I know, other than by their writings.
01:11ddellacostasdegutis: Uncle Bob is of course the grand-old-curmudgeon of TDD and code-cleanliness
01:11sdegutisYeah.
01:11sdegutisYou have any of his cleancoders.com episodes?
01:11ddellacostasdegutis: and Colin Jones I know from his Clojure contributions, and excellent article on namespaces in Clojure
01:12sdegutisHeh yeah, the canonical namespaces article.
01:12ddellacostasdegutis: naw, can't justify paying for them as of yet
01:12sdegutisYeah I hear ya.
01:12ddellacostayeah, definitely a good one
01:12sdegutisI worked at 8L for a few years. That's where I learned TDD.
01:12seangrov`ddellacosta: Paying for what?
01:12technomancysdegutis: eh; it's fine to do your own thing, you just can't expect it to get any traction
01:12ddellacostasdegutis: 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.
01:13sdegutistechnomancy: wait hold on, what is that in response to?
01:13technomancyliterally never heard of anyone using speclj in the wider community
01:13sdegutisOh right.
01:13sdegutisddellacosta: I agree with your approach.
01:13ddellacostaseangrov`: 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
01:13technomancylisp in general has a long tradition of cowboy coders striking out and creating their own little worlds
01:14sdegutistechnomancy: Oh, is that where Ruby gets it from?
01:14technomancy(because that's practically all you could do in the 80s unless you went to MIT)
01:14ddellacostatechnomancy: totally
01:14sdegutisseangrov`: he's talking about cleancoders.com, you should check it out, some of the videos might be helpful
01:15sdegutisA few of us are in Episode 4 a few times.
01:15ddellacostasdegutis: ah, well for that I'd be interested in checking it out. ;-)
01:15sdegutisI think I called FP "a fad".
01:15ddellacostaah, haha
01:15sdegutis:D
01:15ddellacostaI mean, it is in some ways. Us developers as a group are pretty faddish
01:15sdegutisI also said temporal coupling was like what Spock did.
01:16technomancysdegutis: just wait, give Intel another couple years and this multicore thing will be a distant memory
01:16sdegutis(I was trolling Uncle Bob.)
01:16technomancywe'll have our 8GHz chips yet
01:16ddellacostasdegutis: gotcha. :-)
01:16ddellacostatechnomancy: sweet.
01:16sdegutistechnomancy: been holding my breath like they said to.
01:19sdegutisddellacosta: 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.
01:20sdegutisAlso Colin wrote REPLy which is part of Leiningen now, so that's pretty cool :)
01:20ddellacostasdegutis: 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.
01:21sdegutisddellacosta: gotcha
01:21ddellacostasdegutis: yeah, seems like Colin's written some real good stuff.
01:21xeqi$seen trptcolin
01:21lazybottrptcolin was last seen quitting 8 hours and 56 minutes ago.
01:22ddellacostaxeqi: damn, didn't know about that, very cool IRC command. I'm still such an IRC newb
01:22technomancycolin is great; he should spend more time on IRC =P
01:22xeqiyeah, we wanted him for something the other day... can't remember now tho
01:22sdegutisYeah I keep pressing "trp[TAB]" every few days and sigh when it doesn't autocomplete.
01:22ddellacostatechnomancy: yah, I think the time I was having trouble was the only time I saw him on here, and he was super helpful.
01:22ddellacostahaha
01:23sdegutisAnyway they have open office on Friday afternoons, I should visit them soon. If you're in the Chicago area you should too.
01:23sdegutisLots of very smart people.
01:24ddellacostasdegutis: never been to Chicago, would like to go. And would love to drop into 8th Light some day too, and meet those folks.
01:24sdegutisFor example this was a nice Friday talk to learn some Haskell: http://vimeo.com/63093231
01:28dissipate_sdegutis, why doesn't 8th light mention clojure on their site?
01:28sdegutisdissipate_: they haven't really gotten into it yet. Still doing Ruby mostly.
01:30dissipate_sdegutis, even though bob martin has been evangelizing clojure?
01:32sdegutislol... "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
01:34sdegutisdissipate_: 8th Light has clients and therefore not all their projects are greenfield. But I know that Bob's site uses Clojure.
01:36dissipate_sdegutis, hmm, sounds like Relevance is a better shop
01:36sdegutisdissipate_: seeing as the guy who literally wrote the book on Clojure works there, then yes, probably.
01:36dissipate_nevermind, i want to work at 8th light: http://8thlight.com/our-team/angeleah-daidone
01:37sdegutisdissipate_: why?
01:37ddellacostadissipate_: lame
01:37dissipate_sdegutis, hot female apprentices ^
01:37dissipate_want to touch the hiney!
01:37sdegutisdissipate_: wow.
01:37ddellacostadissipate_: super lame
01:37seabreGoing from cosmetology to software development is super impressive.
01:37sdegutisseabre: very.
01:38ddellacostawow
01:38spjti went from digging ditches to software development, but i'm an ugly guy, so who cares.
01:38dissipate_mmmmm, impressive
01:38sdegutisThey're very active in helping people learn from 0 to professional.
01:38ddellacostaspjt: that is also impressive.
01:38nightflyspjt: Still impressive
01:38dissipate_sdegutis, it had nothing to do with her looks?
01:38sdegutisColin went from having a master's in trumpet performance to being an 8L apprentice to finally a craftsman. That was pretty cool.
01:38sdegutisdissipate_: let's pretend this conversation didn't happen.
01:39dissipate_i bet they had a bunch of dudes who wanted to apprentice and they picked her
01:39ddellacostasdegutis: agreed
01:39sdegutisdissipate_: what do you do for a living?
01:39spjttbh that picture looks like they were trying pretty hard to make her look better than she actually does
01:40sdegutisspjt: what do you do for a living?
01:40dissipate_sdegutis, program
01:40sdegutisdissipate_: what language?
01:40spjtsdegutis: code
01:40dissipate_sdegutis, perl mostly
01:40sdegutisspjt: what language?
01:40sdegutisdissipate_: really? You write Perl for a living?
01:40spjtsdegutis: j2ee, at least when my boss is looking
01:40sdegutisI didn't know there were jobs for that.
01:40dissipate_sdegutis, correct
01:40sdegutisspjt: Ha. Have you been able to use Clojure at work?
01:41dissipate_sdegutis, when i was first in the job market there were more jobs for perl than python
01:41spjtsdegutis: yes
01:41sdegutisdissipate_: Cool. How do you like Clojure compared to Perl?
01:41dissipate_sdegutis, i want to switch to clojure really bad.
01:42sdegutisspjt: Sweet.
01:42sdegutisdissipate_: Why?
01:42spjtdissipate_: you might have better luck than me.
01:43dissipate_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.
01:43spjtI 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
01:43dissipate_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'
01:43sdegutisdissipate_: What about Ruby?
01:44sdegutisspjt: Ah good way to find use out of it. Have you used other languages to do that same thing (besides Java) before Clojure?
01:44dissipate_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.
01:45spjtsdegutis: I tried to learn clojure and gave up before learning scala, then came back and it made sense
01:45seabreYou can sorta do immutable data structures in ruby
01:45seabre[1,2,3,4].freeze
01:46dissipate_i just wish clojure was viable as a scripting language. seems like it is not because of the startup time of the JVM.
01:47sdegutisseabre: true but its stdlib is geared slightly more towards mutation
01:47sdegutisdissipate_: Have you looked into Racket? I hear good things about it.
01:47spjtdissipate_: Have you looked at scala
01:47dissipate_so for now i'm going with python and clojure. python for scriping, clojure for applications. and C for low level programming.
01:47gwshaskell? :D
01:47sdegutisOh boy, I've heard nothing but bad things about Scala from people I respect.
01:47zanesdissipate_: 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.
01:47dissipate_sdegutis, no. it is a viable scripting language that has good libs?
01:47sdegutiszanes: what do you do for a living?
01:48sdegutisdissipate_: It's a Scheme dialect which is very similar to Clojure.
01:48sdegutisdissipate_: read this, it's very informative about Clojure compared to Racket: http://technomancy.us/169
01:48spjtScala is good if you want to get into FP but you have a job
01:48dissipate_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.
01:49dissipate_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.
01:49sdegutisspjt: 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.
01:50s4muelScala 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.
01:50zanessdegutis: I'm a software engineer.
01:50dissipate_zanes, i was just joking about her. her story actually sounds quite interesting, going from cosmetology to software development.
01:50sdegutiszanes: cool, what language(s) do you primarily use?
01:50spjts4muel: That's why I said "if you have a job". If you know Java you can "learn" it in an hour.
01:51sdegutisdissipate_: 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
01:51zanesdissipate_: 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.
01:51spjts4muel: 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.
01:52sdegutiss4muel: 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.
01:52dissipate_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.
01:52zanessdegutis: These days I mostly use Clojure (in the form of Cascalog) and Javascript.
01:52sdegutiszanes: 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.
01:53s4muelspjt: 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
01:53dissipate_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.
01:55s4muelBut working with the libraries on the jvm from clojure has been so easy (so far, at least) that I keep wondering 'is that it?'
01:55sdegutisdissipate_: that philosophy doesn't play well with Mac OS X native apps.
01:55sdegutisdissipate_: using a JVM app on Mac feels so weird compared to a native ObjC app.
01:56sdegutiss4muel: ditto :)
01:56scottjsdegutis: even good jvm apps, like intellij idea?
01:56dissipate_sdegutis, i don't write native apps, so i wouldn't know. :P
01:57sdegutisscottj: 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.
01:57dissipate_sdegutis, as for objective c, i'll try to avoid that as i have avoided java.
01:57spjts4muel: It doesn't really have that much to do with syntax. Scala only encourages immutable state, it doesn't require it
01:57sdegutisdissipate_: meh, taking the approach "right tool for right job" has worked wonders for me.
01:57sdegutisdissipate_: if I avoided ObjC, I wouldn't have been able to write this window manager I'm using.
01:58dissipate_sdegutis, i agree. but i avoid the issue by just not doing native app development.
01:58sdegutisdissipate_: 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.
01:58scottjsdegutis: is it tiling? released?
01:58sdegutisdissipate_: that's one solution, but it's an awfully boring one isn't it?
01:58sdegutisscottj: yes, yes.
01:58sdegutisscottj: https://github.com/sdegutis/zephyros
01:59sdegutisscottj: well technically it's not tiling, it's *anything*
01:59am2605I have a bit of a dumb newbie question (sorry)...
01:59dissipate_sdegutis, why is it boring?
01:59zanessdegutis: Disagree. There's value in explicitly fostering diversity by making the tech community a welcoming space for women.
01:59ahihisdegutis, re: zipWithN — in my experience those are used very rarely. and things liftMN are more nicely expressed with the Applicative combinators
01:59sdegutisscottj: you write your own stuff in it. My AppGrid configuration is very much like tiling: https://github.com/sdegutis/zephyros/wiki/AppGrid
01:59sdegutisdissipate_: you're limiting how many fun/cool problems you can solve.
01:59zanesam2605: Don't ask if you can ask, just ask. :)
02:00ahihis/things/things like/
02:00sdegutiszanes: making it a welcoming space is fine, but inviting certain people in is really weird and creepy.
02:00sdegutisahihi: Then maybe I'm being unfair to Haskell. I should probably give it a real chance.
02:00zanessdegutis: I don't see what's creepy about outreach to an underrepresented minority.
02:00s4muelOr OCaml.
02:01am2605if 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") ?
02:01dissipate_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.
02:01am2605@zanes thanx :)
02:01sdegutiszanes: it's like saying "hey guys, we don't have enough ___ in here.. let's go get some ___ to join us!"
02:01sdegutisI dunno, it's like saying you know what's best for that person. It feels arrogant to me.
02:02zanesOh, yeah. I never imagined going about it that way.
02:02sdegutisdissipate_: I'm not saying there aren't. I'm just saying that's not all of them.
02:03sdegutiszanes: 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.
02:03sdegutisAnd to me that's weird and creepy.
02:04zanesI think it's possible to present the idea in a non-patronizing way.
02:04zanes"Here's an awesome career path you may not have considered."
02:05zanesAt this point I'm assuming we're discussing organizations like Black Girls Code (http://www.blackgirlscode.com/).
02:05dissipate_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.
02:05sdegutiszanes: I never heard of a concrete organization that does this, no.
02:06scottjzanes: I was actually thinking of the recent Conj extension for women presenters.
02:06sdegutisdissipate_: scary
02:06sdegutisscottj: yeah, see, that's weird.
02:06zanesscottj: Not familiar. What were your thoughts?
02:07sdegutisA call for presenter should be focused on content not on the presenter.
02:07sdegutisI don't care who's presenting, I just want great content. To care about who's presenting feels shallow and unprofessional.
02:07scottjzanes: I think that male/female distinction is not a particularly important one and there are a lot more important aspects of diversity.
02:08dissipate_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.
02:08zanesscottj: Go on.
02:08scottjzanes: I don't want to, this topic can too easily offend people :)
02:09sdegutisdissipate_: 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.
02:09sdegutisscottj: Oh. Well I hope I haven't offended anyone.
02:09zanesscottj: Fair enough. It's an important problem, though, and, I feel, one that benefits from conversations like this.
02:10dissipate_sdegutis, that app is for a specific platform, so that i understand.
02:11ahihiI got tired of CS being such a boys' club, so I'm switching to math ;)
02:11ahihi(there are other reasons, but it's certainly a factor)
02:12sdegutisThere's a lot of ways the programmer community could stop disrespecting *people in general*.
02:12zanes(This is why explicitly focusing on gender diversity matters — I don't want to lose people like ahihi. ;))
02:12ddellacostajust 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.
02:12sdegutisFor example they could stop having "drinkups" which focus on beer and late evenings, which don't really work well for us family people.
02:12zanessdegutis: 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.
02:13ddellacostasdegutis: 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
02:13sdegutiszanes: I don't disagree.
02:13seabream2605, did you ever figure out your problem
02:13sdegutisddellacosta: makes sense
02:13ddellacostasdegutis: but definitely, need a space so people can socialize around tech without it being about getting trashed
02:14ddellacostaand on that note, gonna go get lunch for reals
02:14sdegutis:)
02:14seabre,(map #(str (first %) " " (second %)) (partition 2 (list "Joe" "Bloggs" "Jenny" "Citizen")))
02:14clojurebot("Joe Bloggs" "Jenny Citizen")
02:15seabreProbably a terrible way to do it, but I guess that works.
02:15dissipate_zanes, are you kidding me? the culture is rife with brogrammerism
02:15zanesdissipate_: I don't disagree?
02:15sdegutisOn 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.
02:15dissipate_sdegutis, 'drinkups'? brogrammers
02:16dissipate_sdegutis, are you working with brogrammers?
02:16sdegutisdissipate_: https://github.com/blog
02:16sdegutisfirst big blue words: "Washington DC Drinkup"
02:16am2605seabre: that does work - thank you! I think the partition is what I was missing. Appreciated!
02:16seabreno prob
02:17dissipate_sdegutis, yep, brogramming
02:17sdegutisk
02:17scottjwomen don't drink?
02:17sdegutisWhat's everyone working on tonight?
02:18sdegutisI'm struggling to decide between making my app for-pay or making it open-source.
02:18seabreI was playing around with overtone.
02:18scottjsdegutis: what platform?
02:18sdegutisJVM.
02:18dissipate_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.
02:19sdegutisdissipate_: maybe also suggest he buy some cleancoders.com episodes on testing.
02:19sdegutisBob's got a lot of good advice on this topic.
02:19dissipate_sdegutis, i sent him the clean coder's stuff. but he's working with other people who aren't into that.
02:20sdegutisouch
02:20dissipate_but he had another problem with his piece of the project
02:20sdegutisseabre: looks neat
02:21dissipate_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.
02:21sdegutisAh, I had that happen with my music player Mac app.
02:22sdegutisFortunately the solution for me was to buy into Apple's Core Data framework, and it worked wonders.
02:22seabreOvertone is really cool. It reminds me a lot of Common Music: http://commonmusic.sourceforge.net/
02:23dissipate_sdegutis, you would think that academics who are often not brogrammers would practice clean code, but nope, i guess not
02:24dissipate_industry doesn't do clean code, academia doesn't do clean code, is open source the only hope?
02:25sdegutisAlso, 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.
02:25sdegutisdissipate_: 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.
02:28sdegutisIs the 'respectabiggle' joke lost on everyone? :(
02:28RaynesYes.
02:28respectabiggleAt least not technomancy I bet.
02:29respectabiggles/joke/reference/
02:29respectabiggle*in-crowd
02:30seabrewait
02:30seabreSilver Chair
02:30respectabiggle(inc seabre)
02:30lazybot⇒ 1
02:30RaynesGolden throne.
02:31respectabiggle(dec Raynes)
02:31lazybot⇒ 35
02:31Raynes(gtfo respectabiggle)
02:31respectabiggle(inc Raynes) ;; didn't know it would do something
02:31lazybot⇒ 36
02:32Raynes(lols :at respectabiggle)
02:34respectabiggleIs there a bias against open source apps, that they must somehow be inferior to pay-for apps?
02:35respectabiggleLike, "if it was really quality, then they would have charged for it"
02:36scottjrespectabiggle: 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.
02:38scottjrespectabiggle: 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.
02:38respectabigglescottj: In this case It's a Clojure IDE.
02:40respectabiggleI'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.
02:41respectabiggleBut I've not seen that be true with for-pay apps. If it's only barely better than the competition, people won't pay.
02:42respectabiggleEspecially if it's already a skeptical field, like IDEs.
02:43scottjis this nightcode or the new version of la clojure?
02:43respectabiggleNo. A new one.
02:43scottjahh, cool.
02:45sdegutisI want to name it Nepenthe but I think that might be taken wrong.
02:45seabreName it Couture
02:46sdegutisI don't even know how to pronounce that, so I can't name it that :P
02:49scottjsdegutis: so what's special about it?
02:50sdegutisNothing yet.
02:51sdegutisscottj: its specialness isn't something that can be communicated until it's done, since it has to be experienced
02:53sdegutisPartially because it may never be done, in which case it doesn't matter what features it would have had.
02:55scottjI think a whisker browser-inspired IDE for clojure would be fun to try http://www.maartensz.org/computing/squeak/Helps/Programming/WhiskerBrowser.gif
02:56scottjBut 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.
02:56sdegutis:)
02:59sdegutisOne 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.
02:59sdegutisFor example writing a text editor isn't hard, but writing a text editor that works with every single language ever is hard.
03:01sdegutisMy 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.
03:03zanessdegutis: Learn from Emacs and expose the language the editor is written in to the user!
03:03zanesThat way people can extend it to handle Ruby.
03:05sdegutiszanes: that's been done, it's called emacs :)
03:11sdegutis,(partition 2 1 [:end] "foo")
03:11clojurebot((\f \o) (\o \o) (\o :end))
03:12sdegutis,(map #(conj %1 %2) (iterate 0 inc) (partition 2 1 [:end] "test")
03:12clojurebot#<RuntimeException java.lang.RuntimeException: EOF while reading>
03:12sdegutis,(map #(conj %1 %2) (iterate 0 inc) (partition 2 1 [:end] "test"))
03:12clojurebot#<ClassCastException java.lang.ClassCastException: clojure.core$inc cannot be cast to clojure.lang.IPersistentCollection>
03:12sdegutis:)
03:13sdegutis,(map #(conj %2 %1) (iterate inc 0) (partition 2 1 [:end] "test"))
03:13clojurebot((0 \t \e) (1 \e \s) (2 \s \t) (3 \t :end))
03:13sdegutiswooo
03:32sdegutisI 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.
03:33sdegutisHow would you do this? Reduce?
03:33sdegutisI'm thinking reduce with a seed of [[] initial-coll]
03:33sdegutisKind of ugly, but with the right destructuring it shouldn't be too bad.
03:35ordnungswidrigsdegutis: what about reductions?
03:35sdegutisAh, yes!
03:35sdegutisI always forget about reductions, thanks ordnungswidrig :)
03:36ordnungswidrigsdegutis: you're welcome
03:37sdegutisAh, neither reduce nor reductions works here.
03:37sdegutisBecause the list (f) should operate on next is whatever (f) returns.
03:38sdegutisI think iterate may be close.
03:38ordnungswidrigsdegutis: you have some fn like (fn [coll] [(count coll) (conj coll :foo)]) ?
03:39ordnungswidrigsdegutis: this cries for the state monad :)
03:39sdegutisNot quite.
03:40ordnungswidrigsdegutis: but you f is coll -> [result coll] ?
03:41sdegutisActually it could just be: (f [results coll]) -> [new-results new-coll] and just keep calling it until the coll it receives is empty.
03:41sdegutisI wonder if I have to resort to recur, or if I can use some seq function(s) for this.
03:42ordnungswidrigyes, I would "lift" your basic fn coll -> [result coll] into a fn [results coll] -> [results coll] which can be used with reductions
03:42ordnungswidrigand take-while #(not (empty? (second %))
03:42sdegutisAh.
03:44sdegutisordnungswidrig: that take-while could be used with iterate instead, right?
03:45sdegutis(take-while #(not (empty? (second %))) (iterate my-fn))
03:45ordnungswidrigsdegutis: yes, that should work
03:45sdegutisCool, thanks for the idea of take-while, that was the missing piece all along :)
03:46ddellacostawhy do we have both rest and next?
03:46sdegutisddellacosta: http://clojure.org/lazy
03:47ddellacostasdegutis: they both return lazy sequences, from the docs
03:47sdegutisThat's more of a "Rich's thoughts on paper" type doc though.
03:47ddellacostasdegutis: oh sorry, I see there is more explanation on that page
03:47ddellacostasdegutis: thanks!
03:47sdegutisYes.
03:47sdegutisAny time.
03:48sdegutisPeriods at the bottom of the line are overrated· Let's put them in the middle from now on·
03:48callenbottom?
03:49sdegutisYes•
03:53rurumateHow 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.....
03:54sdegutisI thought CljS has no vars.
03:54rurumateoh
03:54ddellacostayep, no vars.
03:54rurumatehmm
03:54ddellacostayet.
03:54sdegutishttps://github.com/clojure/clojurescript/wiki/Differences-from-Clojure#concurrent-programming
03:54ddellacostaI think seangrov` is working on it.
03:55ddellacostasdegutis: I like Japanese periods: 。
03:55sdegutisOh
03:55ddellacostaheh
03:55sdegutis😄
03:56ddellacostacallen: how goes it?
03:56rurumateso 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
03:56rurumateis that even possible in clojurescript?
03:57ddellacostarurumate: should be...
03:58ddellacostarurumate: although I haven't used mapv in CLJS yet, but believe it exists.
03:58rurumatethe opening paren after format should not be there..
03:58ddellacostarurumate: although, map is lazy so I'm not sure you'll get what you're expecting
03:58rurumateddellacosta: mapv is eager
03:58ddellacostarurumate: d'oh, you're right, my bad
03:59sdegutisddellacosta: I think he's talking about the (name %) part
03:59rurumatesdegutis: aye
04:00ddellacostarurumate: yeah, there are too many parens is all, methinks
04:00sdegutisyeah, needs more haskell
04:00ddellacostaheh
04:01rurumateoff to the day jobs..
04:01ddellacostarurumate: cheers
04:05sdegutisOh hi ucb.
04:10TEttingerso 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?
04:10TEttingera lot already is covered, like I don't need to reimplement map.
04:10TEttingerbut simple things like array reshaping and rotation
04:12TEttingerI have kinda noticed that 2d primitive arrays are a pain in clojure. ^"[[L"
04:13SegFaultAXI'm pretty sure Mikera is working on a comprehensive matrix library.
04:13SegFaultAXhttps://github.com/mikera/matrix-api
04:14SegFaultAXTEttinger: If it's useful, maybe you could reach out to him on twitter/github/mailinglist and see if you can contribute there.
04:14TEttingerSegFaultAX, thanks. this looks much more professional than what I could do though
04:14Apage43see also https://github.com/prismatic/hiphip
04:16SegFaultAXI'm so happy to see prismatic re-opening stuff.
04:17shaungilchristTEttinger: I am an APL weirdo and a lisp practitioner, this article would be cool to redo for clojure http://archive.vector.org.uk/art10500180
04:17TEttingerApage43, heh I've been using hiphip
04:17TEttingerApage43, did you submit an issue on that?
04:17Apage43mm? Don't think so.
04:18TEttingerah, thought the nick sounded familiar
04:18TEttingerthere's an issue with AOT compiling hiphip
04:18TEttingerI made a total kludge hack of a fork of hiphip that fixes it
04:20Apage43interesting
04:20TEttingerhttps://github.com/tommyettinger/hiphip-aot/blob/master/src/hiphip/double.clj#L10
04:20ddellacostashaungilchrist: very cool article, thanks
04:20Apage43i have a project that indirectly does some array'y stuff
04:20TEttingershaungilchrist, I'll take a look
04:20sdegutisI think I may actually have a case where loop/recur is the cleanest/clearest solution.
04:20Apage43at some point i'll probably pull out mikera's matrix stuff and try and make it cleaner/less garbagey
04:21sdegutisThis is neat.
04:21Apage43it's already a dependency, since incanter drags it in and I use a thing from incanter
04:21ddellacostasdegutis: I don't think it's that uncommon.
04:21Apage43sdegutis: I have those sometimes. Every so often though I take a second look and it fits into reduce though
04:22sdegutisddellacosta: I've never had to resort to it before, in about a year of doing Clojure professionally, until now.
04:22ddellacostasdegutis: whenever I have to retain state over a loop that can't be handled cleanly with reduce, I use it
04:22Apage43though *those* largely wind up being even *more* nicely expressed with https://github.com/LonoCloud/synthread
04:22ddellacostaor, what Apage43 said
04:22sdegutisApage43: 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.
04:22ddellacostaApage43: oooh, didn't know about that, nice
04:22sdegutisApage43: (by mutated I only mean it may return a shorter collection)
04:23Apage43synthread.core/for
04:23Apage43er
04:23Apage43lonocloud.synthread/for
04:23Apage43rather
04:23Apage43 =P
04:24Apage43maybe
04:24Apage43might not fit there
04:25sdegutisI 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.
04:25ddellacostawow, really going to have to take a close look at synthread, lots of cool stuff there
04:25ddellacostasdegutis: I hear ya, sometimes it's just easier not to fight the beast, haha
04:25TEttingershaungilchrist, I didn't see any Common Lisp code?
04:27sdegutisAre there any uppercase symbols that are reserved words or core constants in Clojure?
04:28sdegutisLike "(def SYMBOL 1)"
04:29TEttingerMath/PI
04:29TEttingerbut that's java
04:29TEttingeractually I don't even know... ##(+ 1 Math/PI)
04:29lazybot⇒ 4.141592653589793
04:30Apage43ddellacosta: 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
04:30augustlsdegutis: I don't think so. The only reserved stuff is in clojure.core, which you can un-refer anyways.
04:31ddellacostaApage43: 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!
04:31Apage43less "how do i express this with reduce" more "this is what I am trying to do"
04:32Apage43it's just one function torn out of a checkers game
04:33ddellacostaApage43: yeah, it shares that nice quality with the threading operators in that it makes the intention much cleaner
04:37sdegutisTEttinger, augustl: thanks
04:38sdegutisAre vectors efficient at pushing on the end and enumerating from the front?
04:38augustlsdegutis: yes
04:38sdegutissweet :D
04:39sdegutisSo I'm using vectors, case, and loop/recur. This sounds pretty efficient so far.
04:40augustlsdegutis: FYI, if you use conj you'll get the "most efficient behaviour" so to speak
04:40sdegutisawesome, because I already am :)
04:53sdegutis$help
04:53lazybotYou're going to need to tell me what you want help with.
04:53sdegutis$help send
04:53lazybotTopic: "send" doesn't exist!
04:53sdegutis$help mail
04:53lazybotsdegutis: Send somebody a message. Takes a nickname and a message to send. Will alert the person with a notice.
04:54sdegutis$mail brehaut Thanks for https://github.com/brehaut/inc-clojure-brush/blob/master/shBrushClojure.js#L64-L385 :)
04:54lazybotMessage saved.
04:59sdegutisIs there a less dumb way of doing this?
04:59sdegutis,(not-any? #{\a \b \c} [\f])
04:59clojurebottrue
04:59sdegutisgiven #{\a \b \c} and \f
05:02benoystah.
05:03ddellacostasdegutis: what's dumb about that?
05:03sdegutisit creates a vector just to test if a char is in a group of chars
05:04ddellacostaI mean, you could do
05:04ddellacosta,(some #(= \f %) #{\a \b \c})
05:04clojurebotnil
05:04sdegutisNo other way?
05:04ddellacostanot much less concise though. And it creates a anon function in place of your vector.
05:04sdegutis,(doc contains?)
05:04clojurebot"([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'."
05:05sdegutisHmm.
05:07ddellacostasdegutis: yep, contains seems pretty good too.
05:07ddellacosta,(contains? #{\a \b \c} \f)
05:07clojurebotfalse
05:07ddellacosta,(contains? #{\a \b \c} \a)
05:07clojurebottrue
05:07sdegutisBut.. that doesn't make sense.
05:07sdegutisAh.
05:07ddellacostasdegutis: ?
05:08sdegutis,(contains? #{\x \y \z} \x)
05:08clojurebottrue
05:08sdegutisOh, in sets, each element is considered a "key" isn't it?
05:08sdegutisThat must be why it works.
05:09ddellacostaah, yeah, 'cause sets are not ordered I thought
05:09ddellacostaspeaking of sets
05:09ddellacosta,(clojure.set/intersection #{\a \b \c} #{\a})
05:09clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.set>
05:09ddellacostacrap
05:10ddellacostaa well. In any case, could do that too if you wanted to use an unnecessary set instead of an unnecessary vector. ;-)
05:10sdegutis,(require 'clojure.set)
05:10clojurebotnil
05:10sdegutis,(clojure.set/intersection #{\a \b \c} #{\a})
05:10clojurebot#{\a}
05:10sdegutisNah, contains? works great :)
05:11ddellacostasdegutis: yah, I was definitely joking. It's just fun to enumerate all the different possible ways to do something.
05:11ddellacostasdegutis: ah, so you can require just like in repl, cool, dunno why I didn't think of that.
05:13sdegutis,(drop 1 [7 8 9])
05:13clojurebot(8 9)
05:13sdegutisIs there short-hand for that, or is that already the short-hand?
05:13sdegutisOh duh.
05:13sdegutis,(rest [7 8 9])
05:13clojurebot(8 9)
05:13ddellacostasdegutis: I mean, other than rest/next?
05:13ddellacostaright
05:14ddellacostahaha
05:14sdegutisI should go to bed soon. 4am might not be the ideal coding time.
05:14ddellacostanaw, it's hard to connect all these things up in your head.
05:14ddellacostaprobably! damn, you are in North America aren't you.
05:14ddellacostago to bed!
05:14sdegutisLil bit.
05:14ddellacosta;-)
05:14sdegutis(re: NAmerica)
05:15sdegutisddellacosta: lol soon (maybe) but don't worry, I won't keep you from working any longer :)
05:15ddellacostaalthough, it's nice to have people around this time of day…always gets a bit dull in the afternoons/evenings in here. :-/
05:15ddellacostahaha
05:15ddellacostayah, good point.
05:15ddellacostasdegutis: well, you aren't keeping me from work, *I* am keeping me from work, let's be clear.
05:15sdegutis:P
05:19danlentzouch I have just been badly bitten by lisp-1-ness
05:20sdegutishow?
05:20clojurebotwith style and grace
05:20danlentzreally hard to get used to
05:21sdegutisdanlentz: care to share?
05:21danlentzsdegutis: 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
05:22danlentzbut then I foolishly named my constructors literal, stmt, graph as well
05:22sdegutisheh ah yeah, that
05:23sdegutisHyperion does that too. I've resorted to naming them (new-graph) etc.
05:23danlentzworks 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
05:24danlentzbut 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.
05:26danlentzit is really insidious how frequently one is conditioned to think in lisp2 without even realizing it
05:27danlentzlisp1 is prettier in many ways but it really is a mindfuck at times
05:29danlentzi guess i will have to change the constructors to make-* e.g. make-literal, make-stmt but i don't like it
05:30danlentzbecause all my entities are interned, so make-* is not quite accurate as well as ugly
05:31danlentzfind-or-make-literal….. egads...
05:32danlentzmaybe I shouldd use caps. (defschema Literal …) [defn literal ...)
05:34danlentzi 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
05:36danlentzbut i do like clojure a lot I'm enjoying learning it I just needed to vent for a moment :)
05:41danlentziI'm surprised there's not builtin prog1 -- first thing I write for any clojure coding. Calling it "returning" tho, since
05:41danlentzi believe I saw thart somewhere
05:41danlentzprog1 is one of the most useful forms
05:42clgvdanlentz: why? you have progn aka `do`
05:44sdegutisI wonder if (do ...) just turns into { ... } in Java
05:44danlentzwell 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
05:44sdegutisdanlentz: you can do that
05:44danlentzactually I most often use aprog1 which gives you an anaphoric 'it within the body
05:45clgvdanlentz: not in functional programming
05:45clj_newb_2345are there any good examples of mobile html apps built in clojurescript, or is clojurescript just too damn slow?
05:46sdegutisdanlentz: 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
05:46danlentzwell 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
05:47sdegutisdanlentz: btw do you mean Datomic?
05:48sdegutisdanlentz: btw you can do that with (let)
05:49clgvsdegutis: in defn it seems like you are right and `(do ...)` just evaluates to {...}
05:49clgvsdegutis: just tried it and looked at the class via jd-gui
05:50sdegutisclgv: neat :)
05:50danlentzyes, 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
05:50clgvsdegutis: (defn f [x] (do (println "1") 2)) => public Object invoke(Object x) { ((IFn)const__0.getRawRoot()).invoke("1"); return const__1;}
05:50danlentzy datomic
05:50clgvyou can guess the constants ;)
05:50sdegutisdanlentz: that's the beauty of Clojure, it's simple.
05:51Anderkent]awayclgv: 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
05:51danlentzmine is diatomic b/c it looks like dirt :)
05:51sdegutisCommon Lisp is "powerful" but very complex (unnecessarily so IMHO).
05:51Anderkent]awayi.e. do is just a language construct, it doesnt have a runtime signature
05:51clgv Anderkent]away: hm yeah defn has an implicit do ;)
05:52Anderkent]awaybut that doesn't mean it puts a do around its body, just that it 'parses the body as if it was in a do'
05:52danlentzcommon-lisp makes a point of not imposing any particular concept on how you think. clojure makes a point of very specifically doing the opposite
05:53clgvAnderkent]away: no it expands to somewhat containing (fn* ...) ;)
05:54danlentzI love CL a lot but its really exciting how vibrant the clojure community and ecosystem is
05:54sdegutisdanlentz: CL may say that it doesn't impose any way of thinking, but it actually imposes a mutable, imperative style of thinking
05:54sdegutisit's just implicit
05:54danlentznot at all. you can program in a functionl style as well as in clojure
05:55danlentzyou just don't have to
05:55sdegutisSure, but it's not nearly as well supported as the mutable/imperative style is.
05:55danlentzsupported?
05:55sdegutisJust like you can do imperative and mutable code in Clojure, it's just not nearly as easy or pleasant.
05:55danlentzwhat's missing?
05:56scottjdanlentz: does CL have immutable hash maps built-in?
05:56danlentzactually you can do immutable CLOS even very nicely. have a look at the project parallel for a sterling example of this style
05:57danlentzwell plists would be the equivalent
05:57danlentzyou cons to the front of them to use them immutability
05:58danlentza lists can be used this way as well.
05:59danlentzactually 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
06:01scottjdanlentz: 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.
06:01danlentzctrie is a really interesting example of a careful blend of functional and mutable approach that takes a lot of the benefits of both approaches
06:02danlentzif you removed it, that would be mutating it..
06:02danlentz[cdrr plist) would just remove a newley consed entry at the head w/o mutating
06:02danlentzcddr i mean
06:02scottj,(let [a {:a 1 :b 2} b (dissoc a :a)] [a b])
06:03clojurebot[{:a 1, :b 2} {:b 2}]
06:03scottjin CL?
06:03scottjso long as [:b 2] is at the front and you don't need fast lookup then CL is functional, right?
06:04sdegutisscottj: what are you working on these days
06:04danlentz( let ((a (list :a 1 :b 2))) (values a (cddr a)))
06:05sdegutisahhh i remember (values) well
06:05sdegutisI'm glad Clojure was able to ditch the legacy of CL.
06:06danlentzactually one would usually use plist-remove a common short utility function that would give you the same semantics as dissoc
06:07scottjdanlentz: 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.
06:07scottjI don't see plist-remove in hyperspec
06:08scottjoh, people write their own version of the the common missing functional utility functions :)
06:08danlentzwell 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
06:10sdegutisdanlentz: 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.
06:10danlentzthere 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.
06:11sdegutisdanlentz: 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.
06:12danlentzy 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.
06:13sdegutisdanlentz: a few weeks is reasonable.
06:13sdegutis4-5 years is unreasonable, and I blame the language.
06:13danlentzcommon lisp is not truly just one language, it is a fluid environment for developing a language that suits your problem
06:14danlentzcommon lisp has no philosophy -- the only thing that binds us together is a shared disgust for all the alternatives. (scott burson)
06:14sdegutisheh
06:15sdegutisWhoa, this Clojure lexer is only about 50 (readable) lines.
06:16danlentzmaybe.. 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.
06:18danlentzthere 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.
06:21sdegutisGuys,
06:21danlentzand 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.
06:21danlentzeverybody rewrites everything independently form the ground up
06:22sdegutisWhat 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)?
06:22danlentzcalled the NIH (not invented here) syndrome
06:22danlentzsubseq
06:22sdegutisdanlentz: barrier to entry is itself a feature of a language that can't be ignored or dismissed.
06:22sdegutisdanlentz: It's one reason CL is not mainstream but Clojure is getting there.
06:23danlentzwell I'm not disagreeing about that at all.
06:23sdegutisOkay. Maybe we should stop bikeshedding.
06:23sdegutis:)
06:24danlentz:) i needed a break and Its really the first conversation I've had in #clojure so I've enjoyed it :)
06:25danlentzi'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
06:26danlentzbut i'm glad to see a lisp on the rise, and if its clojure then i'm on board
06:27danlentzi do also hate these [] though…. :)
06:27sdegutisdanlentz: everyone else here's asleep, you should come back in about 5 hours for a better conversation :)
06:27danlentzhomogenous parens are so easy...
06:27devnfalse
06:27devnim around
06:27ddellacostasdegutis: you're still up??
06:27lazybotddellacosta: Definitely not.
06:27sdegutisdevn: hullo!
06:27devndanlentz: it reads better
06:27sdegutisddellacosta: sure
06:27ddellacostaheh
06:27sdegutisonly been what, an hour?
06:27devndanlentz: it's a matter of taste, but it reads better
06:28devnIMO
06:28sdegutisdanlentz: it reads way better.
06:28sdegutisdanlentz: to me it has the same purpose and benefit as syntax highlighting
06:28danlentzy I need to finally make peace with paredit.
06:28ucbI'm around too
06:28bamfordpeople, newb speaking: I'm trying to generate the sequence \a...\z. Best I can do is (map char (range (int \a) (inc (int \z))))
06:28sdegutisI 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.
06:28bamfordSurely there's a better way?
06:28ucbI know I'm quiet, but CMON
06:28devn,(map char (range 97 123))
06:29clojurebot(\a \b \c \d \e ...)
06:29sdegutisucb: hullo!
06:29ucbsdegutis: !
06:29Anderkent]away,(map char (range (int \a) (int \z)))
06:29clojurebot(\a \b \c \d \e ...)
06:29sdegutisdanlentz: okay you may get a better conversation any minute at this rate.
06:29devn,(int \z)
06:29clojurebot122
06:29Anderkentah right thats what oyu had
06:29devn,(map char (range 97 122))
06:29clojurebot(\a \b \c \d \e ...)
06:30sdegutis,(doc range)
06:30ddellacosta,(map char (range 97 123))
06:30clojurebot"([] [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."
06:30clojurebot(\a \b \c \d \e ...)
06:30devnI think Raynes made a range which will let you do char ranges
06:30ddellacostadoh, devn beat me to it
06:30bamforddevn: assuming the dear reader knows \a == Ascii 97 ...
06:30sdegutisend is exclusive, bamford is right for (inc)ing it.
06:30Anderkentwell
06:30sdegutisbamford: I like your solution best.
06:30Anderkent(seq "abcd...z")
06:30Anderkent:D
06:30bamford:)
06:30Anderkent,(seq "abcdefghijklmnopqrstuwxyz")
06:30clojurebot(\a \b \c \d \e ...)
06:30Anderkenttotally not error prone
06:31sdegutisAnderkent: ha
06:31devnheh
06:31sdegutis(inc Anderkent)
06:31lazybot⇒ 4
06:31ddellacostaactually, I agree w/sdegutis, it's nicer to see explicitly what you're ranging over
06:31sdegutisI'm *almost* done with my Clojure lexer (ignoring edge cases like weird numbers and stuff).
06:31bamfordok, thanks
06:31Anderkentyes, I prefer the (int \a) version too
06:31sdegutisAll I have left is strings, and it's getting weird.
06:32danlentzwith 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
06:32danlentz)))))))))) so I appreciate that clojure is attempting to appeal to a wider audience. which is the whole point anyway.
06:33devndanlentz: https://github.com/Raynes/morphin
06:33ddellacostadanlentz: I think it's mostly the question of visual signaling, but it seems like you're talking about writing code
06:33ddellacostadanlentz: 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.
06:34devn(morphin/range \a \z)
06:34sdegutisMan I'm hitting tons of 1-off errors. Thank goodness for these tests!
06:34devnwhere is marick to congratulate you?
06:35devn;)
06:35sdegutisdanlentz: paredit makes that a non-issue
06:35sdegutisdevn: heh im using attest
06:35sdegutisits pretty crappy right now, needs lotsa fixin up
06:35sdegutishttps://github.com/sdegutis/attest
06:35danlentzdevn: the seq concept of clojure is fantastic.
06:36devni love brian, fwiw, just having some fun because whenever someone takes something to an extreme, we owe it to the world to be critical
06:36devndanlentz: sure is :)
06:36sdegutisdevn: ha, I love how he says "on a growing number of types" and there's like 2
06:37sdegutisnot that it isn't true, just unexpected
06:37danlentzwell i'm sure at some point it was 1 :)
06:37devnhe's a sly writer
06:37ddellacostadevn: you missed our conversation about Uncle Bob earlier, if you want to talk about extremes
06:37devni have no interest in building a resume off of testing
06:37devnit's a valuable skill
06:38ddellacostadevn: agreed and agreed
06:38devnjust not my area of interest
06:38danlentzdid you guys see the posting of clojure v .000001a -- written in common lisp. just saying...
06:38devnheh, no i missed that
06:38devnif it's in CL then... what about JVM interop?
06:38danlentzi think it was on reddit. either in /r/lisp or /r/clojure
06:39ddellacostawhat is .000001a (not sure I got the right # of 0s)
06:39ddellacosta?
06:39sdegutisdevn: I don't understand your resume comment.
06:39danlentzit was a very early prototype i don't know the real version
06:39devnsdegutis: oh, just that i dont have a desire to build a career on TDD or whatever
06:39danlentzand there is a full cl implementation with MOP that runs on jam -- abcl
06:39ddellacostasdegutis: my interpretation was that "testing" being the defining feature of one's expertise is unappealing as a career strategy
06:40sdegutisdanlentz: he should have named it Lava
06:40ddellacostaat least, that's my take
06:40danlentzjvm rather
06:40devnddellacosta: that's the gist of it from my perspective, yeah
06:40danlentzmaybe larvae might have been apropos
06:40sdegutisAh.
06:40ddellacostalet me just take the opportunity to say that I hate writing CoffeeScript.
06:40ddellacostathat is all.
06:41devni find the whole "everything is about testing" to be a worldview that is limiting, rather than freeing
06:41devnit's reductive
06:42danlentzwriting good tests is more arduous than writing the code itself it seems to me a lot of times
06:42ddellacostadevn: 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.
06:42devnddellacosta: it's especially rad when people ask you to write coffeescript when they don't know it
06:42danlentzand more arduous to maintain and manage
06:42ddellacostadevn: I don't know it either, is the problem
06:42devnddellacosta: sure. no one is arguing there. i like to have good, informed tests, so i know whether or not im regressing
06:42ddellacostadanlentz: it can definitely be a challenge
06:43ddellacostadevn: 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.
06:43sdegutisSo, I'm finding myself just changing numbers randomly and hoping the test passes. This is probably a sign of poor design.
06:43devnbut the cult of testing produces a lot of garbage
06:43devnwhich im apparently supposed to admire
06:43ddellacostadevn: regression tests, however, are pretty much unequivocally awesome and necessary, imho
06:43sdegutisOn the other hand, "it's almost done I just need to make it pass then I'll never have to touch it again!"
06:44ddellacostasdegutis: or it's a sign you're tired.
06:44sdegutisdevn: I've seen great results and horrible results. Depends on who's doing it and how good they are at programming without tests.
06:44sdegutisddellacosta: mayhaps
06:44devn"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"
06:44devn^---lots of ruby projects due to the cult of testing
06:44danlentzlein 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...
06:45devngreen tests, however silly, become a requirement
06:45ddellacostadevn: yes, to the n-thousandth degree, re: rails (specifically within ruby, which is not all that way) cult of testing
06:45devnpatches will be accepted as long as they have tests, whether or not those tests matter
06:45devnmarick had some comment on twitter the other day that got my blood boiling about ruby's superior testing culture
06:45ddellacostaeven 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
06:46sdegutisI 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.
06:46danlentzthe spec english style testing seems ridiculous to me
06:46devnruby's testing culture is like watching someone cut themselves
06:46ddellacostahahaha
06:46devnthen you hear talks about fast tests and what-not
06:46devnthe quest for fast tests
06:46devngee, i wonder why
06:47ddellacostadevn: 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.
06:47sdegutisdevn: some people are Rubyists at heart
06:47devnmaybe because a lot of it is unecessary and indicative of poor design
06:47devnddellacosta: fair assessment i think
06:47sdegutisAt 8th Light they trained us in the ways of TDD before we were put on client projects.
06:48devnRubyist at heart seems to mean a lot of copying and pasting for a living
06:48ddellacostadanlentz: kind of agree re: making tests into English. Breaks down quickly
06:48sdegutisThey've got like 45 programmers now.
06:48sdegutis(Including apprentices.)
06:48ddellacostasdegutis: it's probably helpful in some ways, but people also need to be able to develop outside of that paradigm.
06:49devnyou 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
06:49sdegutisddellacosta: I'll withhold my opinion on TDD for now.
06:49ddellacostasdegutis: damn, that sounds like there's something interesting there though...
06:49devn"do i care about testing this? what is the value? is this exercised elsewhere?" etc.
06:49sdegutisdevn: I've found TDD leads to an alternative to that approach.
06:50danlentzthere 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.
06:50ddellacostadevn, 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
06:50sdegutisAlso I should stop communicating right now. Nothing's coming out right.
06:50ddellacostasdegutis: I thought that last statement was right on
06:50ddellacosta(with caveats)
06:50devnsdegutis: i work at a TDD shop, but im about producing value first and foremost. value is a careful balance of maintainability, performance, and verifiability
06:50ddellacostamost def
06:50sdegutisddellacosta: I meant that in practice, I've seen that TDD often seems to lead people away from the aforementioned approach.
06:51danlentzthe idea comes from eiffel, but the cl implementation is really seamlessly integrated into the generic function metaclasses and is pleasant to use
06:51sdegutis(inc devn)
06:51lazybot⇒ 9
06:51ddellacostasdegutis: oooh, whoops. haha
06:51sdegutisdevn: where?
06:51sdegutisdanlentz: in Clojure we have :pre and :post methinks
06:51devnI think Rich hit a nail on the head with his design, performance, and composition talk
06:51ddellacostaum, so, what is the inc <handle> thing? I'm embarrassed to say I still don't get it.
06:51ddellacostadevn: loved that one
06:51sdegutisddellacosta: on IRC it's convention to do this when devn makes a good point:
06:52sdegutisdevn++
06:52ddellacostadevn: as a music guy originally with a special love for Coltrane though, I was a bit biased I think
06:52sdegutisddellacosta: but that's C/C++ style, and we're Clojure
06:52ddellacostasdegutis: gotcha! thanks.
06:52devnthere'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
06:52devnit rarely bears fruit though
06:52ddellacosta(inc devn)
06:52lazybot⇒ 10
06:52ddellacostagot it.
06:52ddellacosta;-)
06:52sdegutisddellacosta: also Raynes and amalloy_ et al. made clojurebot actually keep karma
06:52sdegutis$karma devn
06:52lazybotdevn has karma 10.
06:53sdegutis(inc devn)
06:53lazybot⇒ 11
06:53devnheh
06:53sdegutiser I mean lazybot
06:53ddellacostahuh, I think I probably have 0
06:53ddellacosta$karma ddellacosta
06:53lazybotddellacosta has karma 0.
06:53ddellacostaheh
06:53sdegutis$karma sd
06:53lazybotsd has karma 0.
06:53sdegutis$karma sdegutis
06:53lazybotsdegutis has karma 1.
06:53sdegutisOh nice.
06:53sdegutis$karma futile
06:53lazybotfutile has karma 2.
06:53sdegutisHeh.
06:53devnanyway, i am not trying to hate on ruby, but the culture there, while it might be "more focused on testing" is broken
06:53devnthe tests are to prevent stupid ideas from creeping in
06:54danlentzits called quid-quo-pro IIRC
06:54devnthat's easy if you just..you know..sit down and think about what you're trying to accomplish
06:54danlentzquid-pro-quo rather
06:54sdegutisdevn: 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.
06:55devnsdegutis: there are issues with this in every community
06:55ddellacostaargh, now I have to figure out how to call a javascript function generated by coffeescript in clojurescript. WTF
06:56devnim just very much against calling the ruby community "exemplary"
06:56devnit's a total lie
06:56sdegutisdevn: wait who says that?
06:56devnoh, this is going back to marick's tweet the other day
06:56ddellacostadevn: link?
06:56sdegutisOh. He's *in* the Ruby community. That doesn't count.
06:56devnhe claimed that ruby's testing culture was "strong" or some nonsense
06:56ddellacostaah, gotta run. Ya'll take care.
06:57devnddellacosta: ciao
06:57devnsdegutis: well, so am i
06:57sdegutisddellacosta: cya
06:57devnbut i have the sense not to make such a blanket assertion
06:57sdegutisYou have to dismiss an active member of a community's opinion of that community.
06:57danlentzdevn: well thats what happens when the barrier-to-entry means of assessing the value of a particular language is followed to the extreme
06:58devndanlentz: well said
06:58sdegutisdevn: or maybe it's just blanket statements that we all know to dismiss.
06:58cmdrdatsis there a better way to tranform a hashmap's values than something like (into {} (map (fn [[k v]] {k (f v)}) m))?
06:58devnsdegutis: if there's some kind of subliminal message or hidden "juicing" in order to get a rise and spark a discussion
06:59devni find that distasteful
06:59sdegutisdevn: did you say that to him on twitter?
06:59devncome to think of it, no
06:59sdegutiscmdrdats: that's the best way I know of
06:59sdegutisdevn: try it
06:59sdegutiscmdrdats: actually yeah, use for instead
07:00devnsdegutis: he will reply either with something profound and topc-shifting
07:00cmdrdatssdegutis: (into {} (for [k v] {k (f v)})) ?
07:00devntopic*
07:00sdegutiscmdrdats: (into {} (for [[k v] m] [k (f v)]))
07:00devnor it will be an affirmation that i am correct, with no plan to change
07:00devnmaybe the solution here is to just not follow him
07:00devneureka.
07:01sdegutisdevn: I just plain don't have a twitter anymore.
07:01sdegutisdevn: So you know where I stand on this issue.
07:01cmdrdatssdegutis: ah, lol - forgot the m :) It just bugs me that I'm first creating a whole list, and then pushing into a map
07:01sdegutiscmdrdats: it's what you'd be doing anyway, since it's an immutable lang
07:02sdegutiscmdrdats: but to be fair, it's not that inefficient, with structural sharing and all that
07:02sdegutisprobably lightning fast too, compared to Ruby 1.8
07:02sdegutis*zing!*
07:02devnMRI
07:02devn"Matz' Ruby Interpreter"
07:02devnhow do you ever convince people to use something named like that?
07:03devna weak argument, but... man, that' like saying DIHMIHB
07:03devnDevn's Interpreter He Made In His Basement
07:03sdegutisdevn: to be fair, nobody knows where Matz made that interpreter
07:04devnhahaha
07:04sdegutisdevn: to be fair, Clojure is also a lame name compared to Lava
07:04devnRuby 2.0 got a little bit better
07:04sdegutis(Lisp in Java)
07:04devnI'm just bored with Ruby. it's a big playground where you can do whatever you want.
07:04cmdrdatssdegutis: i suppose - I imagine (reduce (fn [a [k v]] (assoc a k (f v))) {} m) would be a bit more direct?
07:05devnCarmack's assertion that in any language, any and all syntactic variations in a sufficiently large codebase, will eventually find a home, seems correct
07:05sdegutisdevn: it's an easy way to shoot yourself in the foot and not realize you're bleeding perfusely until after about 6 months
07:05devnClojure makes it harder
07:05devnbecause the blood is real
07:06cmdrdats(time (doseq [x (range 1000000)] (hmap #(+ 10 %) {:n1 10 :n2 20 :n3 30})))
07:06cmdrdats"Elapsed time: 2838.800182 msecs"
07:06cmdrdats(time (doseq [x (range 1000000)] (hmap2 #(+ 10 %) {:n1 10 :n2 20 :n3 30})))
07:06sdegutis*and* to think you're a huge success during those 6 months and even move on to "bigger and better" opportunities
07:06cmdrdats"Elapsed time: 811.519061 msecs"
07:06cmdrdatshmap2 = reduce version
07:07devnsdegutis: yeah, totally true
07:07devnive seen this a lot
07:07devnit's not a language thing, it's a people thing
07:07devnthere needs to be a consistent amount of doubt cast on whatever has been done to-date
07:07devnnot so much that it's toxic
07:08devna healthy amount
07:08sdegutisWelp, about to pass out.
07:08sdegutisGotta finish this string tokenizer.
07:08devnsdegutis: cheers
07:08sdegutisThen pass out.
07:08TEttingersdegutis, more complex than clojure.string/split ?
07:08sdegutisTEttinger: kinda
07:08devn["Then", "pass", "out", "."]
07:09sdegutis[\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]
07:09sdegutis(f that) => 11
07:10sdegutisGimme f.
07:10clgvcmdrdats: better use criterium for a thorough measurement
07:11TEttinger##(filter (partial not= "") (clojure.string/split "Then pass out." #"\b\s?"))
07:11lazybot⇒ ("Then" "pass" "out" ".")
07:11cmdrdatsclgv: thanks - i'll do that
07:12sdegutisor: (f [\" \a \\ \" \b \" \c]) => 6
07:12sdegutisWhat's f? :)
07:12clgvcmdrdats: pro tip: put criteroium in your user profile in ~/.lein/profiles.clj ;)
07:13cmdrdatsclgv: haha, thanks - good idea :)
07:13TEttingersdegutis, I have no idea what that is supposed to do
07:13sdegutisLook for the second non-escaped double-quote and tell me what position it's at.
07:14sdegutis(first one is always at index 0)
07:14TEttingerisn't there a find function for sequences?
07:15sdegutisI should hope so.
07:18TEttinger##(second (keep-indexed #(if (= %2 "\"") %1) [\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]))
07:18lazybot⇒ nil
07:18TEttingerhm
07:18TEttinger##(second (keep-indexed #(if (= %2 \") %1) [\" \f \o \o \\ \" \space \b \a \r \" \space \q \u \u \x]))
07:18lazybot⇒ 5
07:18TEttingersdegutis, does that do the trick?
07:18sdegutis:D
07:19sdegutisThanks TEttinger.
07:19TEttingerno prob, glad to help
07:20sdegutisPhew, my lexer is done.
07:21sdegutisWith many thanks to #clojure
07:21sdegutis(inc #clojure)
07:21lazybot⇒ 6
07:28cmdrdatsclgv: criterium is awesome :) the reduce version is still somewhat faster
07:29clgvcmdrdats: which two versions did you compare? I did not read that before.
07:29cmdrdats(into {} (for [[k v] m] [k (f v)])) vs (reduce (fn [a [k v]] (assoc a k (f v))) {} m)
07:29clgvcmdrdats: you should try out reduce-kv
07:30clgvcmdrdats: and transients of course
07:31clgvcmdrdats: try that one (persistent! (reduce-kv (fn [a k v] (assoc a k (f v))) (transient {}) m))
07:32cmdrdatshmm
07:32cmdrdatsClassCastException clojure.lang.PersistentArrayMap$TransientArrayMap cannot be cast to clojure.lang.Associative clojure.lang.RT.assoc (RT.java:702)
07:32cmdrdatsseems a bit odd :P
07:33cmdrdatsbusy sampling wihout transient for now, I imagine there should be a bit of a speedup using reduce-kv, thanks :D
07:34clgvoh sorry. try assoc!
07:34clgvcmdrdats: try that one (persistent! (reduce-kv (fn [a k v] (assoc! a k (f v))) (transient {}) m))
07:34cmdrdatsaha, of course xD
07:35cmdrdats Execution time mean : 2.509337 µs for the into {} version
07:35clgvcmdrdats: happens to me in 50% of the cases where I switch to transients ;)
07:35cmdrdats Execution time mean : 802.129138 ns for normal reduce
07:35cmdrdatshehe
07:35cmdrdats Execution time mean : 343.686788 ns fore reduce-kv
07:36cmdrdatsstill sampling the transient version
07:36cmdrdats Execution time mean : 408.096108 ns transient
07:36clgvhuh? how big is your map?
07:37cmdrdatsoh, in this case, tiny
07:37cmdrdatsthere's a lot of them
07:39clgvusually transients pay off starting from a suprisingly small number of elements
07:40TEttingerclgv, I wasn't sure if when returns nil for false conditions
07:40cmdrdatsclgv: I'll try slightly bigger maps
07:40clgvcmdrdats: I tried with 10 k-v-pairs
07:41cmdrdatsi tried with 3
07:41cmdrdats:P
07:42clgvnon-transient 4.155826 us vs transient 3.225121 us
07:44cmdrdatsnon-transient 2.604713 ms vs transient 978.255599 µs
07:44hhenkelHmm, 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?
07:44cmdrdatsfor maps with 5000 k-v's
07:45cmdrdatshhenkel: ye - get-in works through vectors, but not lists
07:45ordnungswidrighhenkel: get-in is only for assocs
07:45ordnungswidrigvectors are associative, lists are not
07:46ordnungswidrighhenkel: you can use nth
07:46clgvcmdrdats: `into` uses transients under the hood where possible
07:47cmdrdatsclgv: cool, but it still needs the overhead of some kind of transformed list of k-v pairs
07:47cmdrdatsclgv: that's where my intuition says it's slower
07:47hhenkelcmdrdats: ordnungswidrig: okay, so how to translate the list to a vector then? I don't understand how nth would help me here?
07:47clgvcmdrdats: in your case you had a lazy-seq and the overhead of the k-v-pairs and destructuring
07:48ordnungswidrig,(nth '(1 2 3 4 5) 4)
07:48clojurebot5
07:48hhenkelOr is it better to use something different then map?
07:48cmdrdatsclgv: ye
07:48cmdrdatshhenkel: you can (vec (map …)) if you really need to use get-in
07:48ordnungswidrighhenkel: ,(nth (map keyword ["foo" "bar" "baz"]) 2)
07:49ordnungswidrig,(nth (map keyword ["foo" "bar" "baz"]) 2)
07:49clojurebot:baz
07:49cmdrdats~botsnack
07:49clojurebotbotsnack is newline
07:50hhenkelordnungswidrig: my idea was to split a string and use the parts I get as keywords to look something up with get-in.
07:51cmdrdatsclgv: thanks for your help :)
07:51hhenkelI see how vec would help me there but I don't get it how returning one specific value with "nth" would help me here.
07:51ordnungswidrigwhat is the "key" for lockup? An numerical index?
07:52hhenkelordnungswidrig: it is a keyword in a nested datastructure (tree with keys (keywords) and values (string or longs)
07:52clgvcmdrdats: your welcome
07:53clgv*are ;)
07:53ordnungswidrighhenkel: where does (map keyword ...) into play?
07:56hhenkelordnungswidrig: 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.
07:57hhenkelordnungswidrig: therefore I split strings that match that form at the dot and then use "map keyword" to use these parts to address the keywords.
07:57hhenkelI thought it would be a good idea to "translate" the strings to keywords.
07:58ordnungswidrighhenkel: ah, so you need (get-in tree (map keyword (split ...)))
07:58hhenkelso the described "variable" points to something like {:level1 {:level2 {:value12 "Test-Text"}}} for example.
07:59hhenkelordnungswidrig: yes, I got (get-in collection (map keyword (clojure.string/split (clojure.string/replace variable-string #"\$\{(.*)\}" "$1") #"\."))))
08:00ordnungswidriglike that, yes.
08:01hhenkelBut it allways gives me nil or a null pointer exception and I don't fully understand why not the "real" value is set.
08:01ordnungswidrigis collection a sequence or a map?
08:02hhenkelmap
08:03ordnungswidrighhenkel: do you know how to use trace?
08:03ordnungswidrighhenkel: I think that would be helpful here
08:03hhenkelI 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....
08:03hhenkelordnungswidrig: Nope, but I'm willing to learn.
08:04ordnungswidrighhenkel: second, how do you want to handle transient dependencies? like {:a "${b}" :b "${c}" :c "foo"}?
08:04hhenkelordnungswidrig: Any docs you recommend? Or a short introduction?
08:04ordnungswidrighttps://github.com/clojure/tools.trace
08:04ordnungswidrigwrap any form with (trace) and get some nice trace output, like (get-in collection (trace "keys" (map keyword (split ...))))
08:05ordnungswidrigso you can see the intermediate results
08:05hhenkelordnungswidrig: currently I just ignore them...in the longterm maybe multiple runns.
08:05hyPiRionWhat is #"\$\{(.*)\}" supposed to match, anyway?
08:05Anderkenthhenkel: I'd assume your splitting is wrong :)
08:05hyPiRionoh derp.
08:06Anderkentbecause the get should work
08:06hyPiRionThis is why I need coffee in the morning.
08:06Anderkent,(get-in {:a {:b {:c :d}}} (map keyword ["a" "b" "c"]))
08:06clojurebot:d
08:07hyPiRionoh riiight
08:07hyPiRionhhenkel: ##(clojure.string/replace "${a}.${b}.${c}" #"\$\{(.*)\}" "$1")
08:07lazybot⇒ "a}.${b}.${c"
08:07hyPiRionversus ##(clojure.string/replace "${a}.${b}.${c}" #"\$\{(.*?)\}" "$1")
08:07lazybot⇒ "a.b.c"
08:08hyPiRionI make no sense today, ignore me for 15 minutes
08:08hhenkelhyPiRion: plan is to have only ${test.test1}
08:09hyPiRionyeah, I realized in hindsight
08:11ordnungswidrighhenkel: (if-let [path (re-matches #"\${.*}" expr)] (get-in collection (map keyword (clojure.string/split path #"\."))))
08:11hhenkelordnungswidrig: trace is really helpful....seems like it is working as expected...
08:11Anderkenthhenkel: I'd expect you're getting back a nil because the keyword chain does not exist in the map
08:11ordnungswidrighhenkel: aah, add path as else clause
08:11Anderkentbut it's hard to say without seeing all of your code
08:11ordnungswidrig (if-let [path (re-matches #"\${.*}" expr)] (get-in collection (map keyword (clojure.string/split path #"\."))) expr)
08:12ordnungswidrigso the expr is returned unless the re matches
08:12hhenkelTRACE keys: {:cycle 3600, :action "read", :mbean "java.lang:type=OperatingSystem", :attribute "FreeSwapSpaceSize", :option "ignoreErrors=true"}
08:12Anderkentyou want .+
08:12hhenkelIs what I get when I add trace in front of the get-in
08:12Anderkentright, and what's the string you're trying to look up?
08:12Anderkent${cycle} or sth like that?
08:13Anderkentwait, that trace is your collection, not the keys, right?
08:14hhenkelAnderkent: 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.
08:15hhenkelAnderkent: 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.
08:15Anderkentright, so it seems that bit is working
08:16Anderkentthis will be much easier if you post your code to refheap with an example of what gives you nil/npe
08:18hhenkelhttps://www.refheap.com/18356 contains the whole mess... ;)
08:20fredyr,(keyword (str '- (aget (Character/toChars 80) 0)))
08:20clojurebot:-P
08:21Anderkenthhenkel: right, you can't use clojure.string/replace with non-string values
08:21Anderkent,(clojure.stirng/replace "foo" "f" {:a 1})
08:21sheldonhdoes clojure have a fold function?
08:21clojurebot#<ClassNotFoundException java.lang.ClassNotFoundException: clojure.stirng>
08:21Anderkent,(clojure.string/replace "foo" "f" {:a 1})
08:21clojurebot#<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentArrayMap cannot be cast to java.lang.CharSequence>
08:22Anderkent,(clojure.string/replace "foo" #"f" {:a 1})
08:22clojurebot#<NullPointerException java.lang.NullPointerException>
08:22Anderkentyou just want to return (get-value collection %) instead of putting it to clojure.string/replace
08:23Anderkentsheldonh: reduce is foldl I think
08:23hhenkelAnderkent: I get a NullPointerException java.util.regex.Matcher.quoteReplacement
08:23Anderkenthhenkel: as I said. (clojure.string/replace % ... (get-value ...)) makes no sense
08:24hhenkelI'll test with just returning...
08:24Anderkentclojure.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
08:24Anderkentand of course you must return the old one if you're not changing it
08:25Anderkentsheldonh: also, reducers have fold, and it's potentially parallel
08:26Anderkentit's a little different than reduce
08:28hhenkelAnderkent: 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...
08:30Anderkenthhenkel: yes, you can't alter anything in clojure :) clojure.stirng/replace also doesnt alter anything, just gives you a new string back
08:30Anderkent(well ok, the you can't alter anyhting is not *quite* true)
08:30Anderkentthe 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
08:35sheldonhAnderkent: 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
08:36sheldonhdefinitely not fold :)
08:37Anderkentis that 'takes a vector of 2 elements' or 'takes 2 arguments'?
08:39Anderkentfor the first, you want (some my-condition-fn (partition my-collection 2 1))
08:39sheldonhAnderkent: i could live with either (it's a cheap transform). if filter is lazy and first is lazy, then it's just a partition
08:40sheldonhfirst calls seq on its argument. that means it doesn't defeat laziness, right?
08:40Anderkentfor the second it's more like (first (filter identity (map my-fn collection (next collection))))
08:40Anderkentseq realizes lazyseqs
08:41sheldonhoh dear
08:41sheldonhthat's crazy. how do i get the head of a lazy sequence without realizing it?
08:41Anderkentsosrry, I mean seq realizes the first element
08:42sheldonhphew
08:42Anderkent,(let [foo (take 5 (repeatedly #(do (println "boo") 1)))] (println "foo") (let [bar (seq foo)] (println "bar")))
08:43clojurebotfoo\nboo\nbar\n
08:43Anderkentthat's less useful than it was in my head ;_;
08:43sheldonhAnderkent: okay, then all is well. not exactly what i asked, but https://www.refheap.com/18357
08:43sheldonhAnderkent: you just described everything i ever typed :)
08:43Anderkentargh
08:44sheldonhAnderkent: that's always what you want to hear after a crack a 4clojure. "argh" :)
08:44Anderkenti think you just want to use reduce there :P enumerating all subsequences is... suboptimal
08:44Anderkent:P
08:45sheldonhAnderkent: i deleted (i think) 3 reduce-based attempts. maybe after a break :)
08:45Anderkentthe 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
08:45clgv Anderkent: but gets a good golfing score ;)
08:45Anderkentalternatively
08:45Anderkenttake it in two steps
08:45Anderkentfirst, split it into increasing subsequences
08:45Anderkentthen find which one is longest
08:46Anderkentobviously they can't overlap, so this should be simple
08:46sheldonhi thought that's what my for/partition did
08:46Anderkentno, you generate all subsequences then check which of them are increasing
08:47sheldonhthat 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
08:48sheldonhanyway, it felt like a reduce problem when i started, and i should totally take another shot at it once my circulation returns to normal :)
08:49sheldonh"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)
08:53sheldonhAnderkent: the real pig in that exercise is that the minimum eligible subsequence length is 2
08:59clgvsheldonh: ##(or nil [])
08:59lazybot⇒ []
08:59clgv;)
09:03sheldonhclgv: yeah, that's what i did. but usually when i have to do that at the outermost layer, my design sucks :)
09:03Anderkenttbh I think the nicest solution to this is either reduce or loop/recur
09:04clgvwell 4clojure encourages code golfing ;)
09:05clgvthat way you'll often end up with solutions you should not use in projects
09:05AnderkentI'm not familar with that term
09:05clgv"trying to get the smallest solution in terms of character count"
09:06Anderkentah
09:06AnderkentI went the opposite direction
09:06clgvthere is a chart where you can see where your solution landed after you completed the excercise
09:06Anderkent'write a solution that's actually easy to understand' :P
09:06clgvshortest runtime would be a nice contest as well
09:06sheldonhi start with "write a solution that goes green". that is usually enough of an achievement :)
09:07clgvtoo many people already have all solutions solved. I didnt do 4clojure since a long time and almost dropped out of the top100...
09:10borkdudeHow can I turn of the fancy f displaying in emacs?
09:10borkdudefor example, it displays incorrectly when I type #_
09:11Anderkent(remove-hook 'clojure-mode-hook 'esk-pretty-fn)
09:11Anderkentsays stack overflow
09:23mathiaspHi 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?
09:23mathiaspI'm a clojure novice, so maybe, hopefully I've forgotten something simple?
09:26TEttingermathiasp, it's an unfortunate time of day right now, but soon people will be more active I think. has to do with time zones.
09:26Anderkentmathiasp: looking at it, but don't get your hopes up :)
09:26mathiaspTEttingen, thanks, I assumed so, it's not really urgent. Thanks for looking!
09:27clgvmathiasp: that's because your `binding` exist only when you define those functions in its body and not at runtime
09:28Anderkentclgv: well, the go should run within the binding
09:28clgvmathiasp: "runtime" = when your functions are called
09:28clgvoh the `go` is not in the function?
09:28sheldonhbwahahahaha! i just evalled my code to examine the data structure my first stab produces, and it turns out the function's done!
09:28Anderkentyeah it's a top level loop afaik
09:28clgvis that on purpose?
09:29clgvthe other rpc call is in a function
09:29ToxicFrogAren't dynamic (binding)s threadlocal?
09:29AnderkentI believe it's just ment to be a continuously running listener
09:30AnderkentToxicFrog: yes, but core.async carries your bindings with you
09:30ToxicFrogAah.
09:30clgvI'd rewrite that with a startup function...
09:30ToxicFrogOh, and this is cljs. I've got nothing.
09:30clgvToxicFrog: threadlocal bindings are inherited to child threads as initial values
09:31clgvoh right. no idea if there is some non-standards cljs-thing at work^^
09:31Anderkenthttps://www.refheap.com/18359 seems to imply the bindings work
09:31Anderkentbut don't know about cljs obviously
09:31julienXXHi 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?
09:32julienXXstr/replace complains with "Unsupported escape character: \["
09:32AnderkentjulienXX: you need to escape the backslash, i.e. "\\["
09:32clgvjulienXX: "\\"
09:33Anderkenthm
09:33Anderkentactually
09:33Anderkentdoesn't seem to work the way I thought it would
09:33Anderkentouch, painful
09:34julienXXAnderkent clgv thanks!
09:34Anderkent,(print (clojure.string/replace "foo[bar" #"\[" (clojure.string/re-quote-replacement "\\[")))
09:34clojurebotfoo\[bar
09:34Anderkent,(print (clojure.string/replace "foo[bar" #"\[" #"\\\["))
09:34clojurebot#<ClassCastException java.lang.ClassCastException: java.util.regex.Pattern cannot be cast to clojure.lang.IFn>
09:34Anderkenthm oups
09:35Anderkent,(print (clojure.string/replace "foo[bar" #"\[" "\\\\["))
09:35clojurebotfoo\[bar
09:35Anderkentright
09:36Anderkentthat's... pretty awful
09:44Anderkentmathiasp: 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
09:45Anderkentif it does work, it's a cljs async bug, otherwise it might be something in your code
09:47mathiaspclgv, 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.
09:47mathiaspI have no idea why, though ;)
09:49clgvmathiasp: having a start funciton for that `go` block is cleaner anyway
09:50mathiaspclgv: I really don't know what you mean by the start function for the go block...
09:51clgvmathiasp: oh, I misread you. you just moved binding and rpc into the function...
09:51mathiaspjep
09:52mathiaspclgv: 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:02mathiaspcglv: 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:03clgvmathiasp: well maybe bindings in cljs work differently with go blocks or there is a bug
10:03Anderkentmathiasp: 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:03clgvmathiasp: might be worth a mailing list post
10:04mathiaspclgv: ok, will do
10:06Anderkentmathiasp: does https://www.refheap.com/18361 work for you?
10:11gdev,(let [slash (char-escape-string \\) re-bracket #"\[" ] (print (clojure.string/replace "foo[bar" re-bracket (str slash "\["))))
10:11clojurebot#<RuntimeException java.lang.RuntimeException: Unsupported escape character: \[>
10:11gdev,(let [slash (char-escape-string \\) re-bracket #"\[" ] (print (clojure.string/replace "foo[bar" re-bracket (str slash \[))))
10:11clojurebotfoo\[bar
10:17gdev,(let [slash (char-escape-string \\) re-bracket #"\[" bracket \[ target "foo[bar" replacement (str slash bracket)] (print (clojure.string/replace target re-bracket replacement)))
10:17clojurebotfoo\[bar
10:17gdevwell that was a fun little exercise
10:20gdevI've been trying to convert Sussman's scheme code to Clojure all morning so a string replace problem was a lot easier
10:23mathiaspclgv: 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:24Anderkent>31887
10:24Anderkent:D
10:24Anderkent:D
10:24mathiaspclgv: I have to go now, will look into this later...
11:00no7hingwhat 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:01sdegutisno7hing: map is lazy.
11:01sdegutis,(doc map)
11:01clojurebot"([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:01sdegutisno7hing: You have to realize it via doall, but a better solution is to just use doseq.
11:01no7hingdoesn't do all force it?
11:01sdegutis,(doc doseq)
11:01clojurebot"([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:02sdegutisActually 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:02clgv no7hing: what is your goal?
11:02hyPiRionno7hing: use pr-str instead of str
11:03no7hingi want a list of strings that then get used in a (format "…" ..)
11:03no7hingah
11:03mathiaspAnderkent, cglv: the test case does not work (e.g. shows OUPS BAD ASYNC). I've put this on the mailing list.
11:03sandbagsafternoon
11:03hyPiRionyou can also wrap it in a `(seq ...)` before str-ing it
11:05clgvno7hing: example function call and expected output?
11:12no7hingkind of embarrassing but the seq was wrapped in another seq as there was still a left-over '&' in the function arguments
11:12no7hingthanks for helping
11:33sdegutisGiven [\a \b \c] what's an efficient way to create a string from it?
11:33sdegutisI bet there's something smarter than (apply str coll).
11:35clgvsdegutis: (apply str coll) is pretty good since it uses stringbuilder internally which is the fastest way to build strings on the jvm
11:35sdegutisclgv: oh nice :)
11:38sdegutisThans
11:38sdegutisThanks
11:38clgvnp
11:44sdegutisWhoa, 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:44riggeryeah, called warming up the vm
11:45sdegutisAh I've heard of that.
11:45riggerJIT
11:46gdevthe JVM runs on diesel
11:46riggerhttp://4groundtechsolutions.com/jvm-warmup/
11:46sdegutisMy only experience with Java or JVM before using Clojure was ranting that Java's stupid and Ruby's better.
11:47gdevsdegutis, common mistake lumping the language and the VM in the same basket
11:47hhenkelThere is a reason why the call it hotspot jvm...
11:47nDuffsdegutis: Heh. Whereas I've seen folks using Ruby in large-scale production abandon it for Erlang due to issues with the Ruby VM.
11:48sdegutisnDuff: :D
11:48sdegutisnDuff: Elixir?
11:48nDuffsdegutis: Opscode's big rewrite of the Chef server for 0.11
11:48sdegutisThat'd seem less random :)
11:48sdegutisnDuff: ah
11:48sdegutisWe're using Chef. But I've heard good things about ansible, have to look into it..
11:49sdegutisOk time to do some premature optimization.
11:49sdegutisI bet (partition 2 1 [:end] string) is probably much slower than just using loop/recur with an index.
11:52callensdegutis: you're supposed to use things like criterium for benchmarking for a reason.
11:52callenit warms the JIT and is very meticulous about it in order to get accurate benchmarks.
11:52sdegutiscallen: Oh. Nice. I'll look into that.
11:53sdegutisYep looks perfect. Thanks callen.
11:55gdevdgrnbrg, saw your talk on piplin, looks interesting
11:55riggerurl?
11:55clojurebotsomething
11:56clgv&(let [... 42] ...)
11:56lazybotjava.lang.ClassFormatError: Illegal field name "..." in class sandbox91102$eval133977
11:56hyPiRion,(let [… 42] …)
11:56clojurebot42
11:56clgvbut lazybot is right ;)
11:56callenrigger: http://www.infoq.com/presentations/piplin?utm_source=dlvr.it&amp;utm_medium=twitter
11:56riggerthx
11:57clgv&(clojure-version)
11:57lazybot⇒ "1.4.0"
11:57callenrigger: could always google.
11:57clgv,(clojure-version)
11:57clojurebot"1.6.0-master-SNAPSHOT"
11:57callenbecause, you know, that's what I did.
11:57clgvui
11:57hyPiRionclgv: psh
11:57hyPiRion&(let [… 42] …)
11:57lazybot⇒ 42
11:57riggercallen, not sure dgrnbrg piplin would have yielded much
11:57xeqisdegutis: +1 for criterium when benchmarking. Also be careful of lein's default options for faster startup / less optimization
11:58riggerah, nm, thanks anyway
11:58clgvhyPiRion: :P
11:58callenrigger: ...yeah...yeah it would've.
11:58riggeroh shit, this is cool
11:59riggerdgrnbrg: you work in the hardware industry?
11:59riggerresearchmethodologist
11:59riggerhmm
12:00riggerwe wrote a dsl in python for describing memories
12:01rasmustoI need to try piplin, I said I would after I the talk...
12:01rasmustoBut I ended up rolling my own libraries instead
12:04BalvedaWhere can I learn to engineer software using Clojure? I can't wrap my head around structuring a program in it yet
12:06riggerbe curious to see how this scales against RTL
12:07coventryBalveda: 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:07rkneufeldBalveda: I'd say probably similarly to other disciplines: Read other people's functional software and practice.
12:07rkneufeldcoventry: As best I know the Clojure source itself is not always recommended reading for idiomatic Clojure. Tread with care ;)
12:08BalvedaComing from a Java/C++/C# background Clojure is so weird but it calls out to me.
12:08BalvedaIs that weird? Am I going nuts?
12:09clgvBalveda: books are a good start.
12:09nDuffBalveda: 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:09nDuffBalveda: If you haven't read Joy of Clojure, I recommend it.
12:09clgvbetter start with "Clojure Programming" and then read "Joy of Clojure" after that ;)
12:09hyPiRionIt's hard to program stuff in the beginning, but it comes easier with practise
12:10hyPiRionit's not only a new language, you have all the different new concepts
12:10sdegutisxeqi: cool
12:10dgrnbrgrigger: hey!
12:10sdegutisBalveda: what about it calls out to you?
12:10riggerhowdy
12:10dgrnbrgrigger: I work at a hedge fund, and in school and in the past I worked on hardware/low latency systems
12:11coventryRepeating 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:11dgrnbrgnow, I'm doing large scale distributed systems
12:11riggerdgrnbrg: i'm a design tools guy at AMD
12:11dgrnbrgrigger: cool!
12:11dgrnbrgI have been thinking a lot about pipline recently
12:11BalvedaIt just seems right, sdegutis.
12:11sdegutisBalveda: why?
12:11sdegutisBalveda: or in what way?
12:11dgrnbrgsince I used a model of time in piplin that makes sense for very low level abstractions
12:12dgrnbrgbut I think that core.async is a great basis for concurrent hardware development
12:12dgrnbrgI'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:12BalvedaHard 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:12coventryOh, I get it now. They are all subordinate forms to other special forms, which handle them directly without the need for dispatch.
12:12riggerwe "replaced" six guys writing skil code for memories with a python dsl and compiler
12:13riggerso 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:14dgrnbrgthat sounds awesome! is it myhdl, or something custom?
12:14riggerit's home grown
12:14rasmustorigger: skil?
12:14riggerskill
12:14riggerfrom Cadence
12:15riggervery lispy
12:15rasmustorigger: ah, will have to check it out.
12:15sdegutisBalveda: ah, cool, I know the feeling
12:16BalvedaI'm going to be working in automatized QA so I want to incorporate the language, as well
12:17BalvedaI've been trying out clj-webdriver and it seems good, trying things out in the console is just a blast.
12:17Balvedain the REPL, sorry. heh.
12:19sdegutis:)
12:19sdegutisExciting times.
12:22sdegutisWhat'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:22sdegutisLike, given "abc " I want to find the index of the first non-alphanum char starting at 0 which would return 3
12:24sdegutisMaybe regex is the fastest way after all.
12:25functionformwhoever 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:25hyPiRion,(let [matcher (.matcher #"[^A-Za-z]" "abc ")] (if (.find matcher) (.start matcher)))
12:25clojurebot3
12:26hyPiRionwell, that was just alpha, you could probably guess how to add in nums
12:26justin_smithfunctionform: my theory is that David Byrne has given up pop-world-beat for computer science
12:26justin_smithhyPiRion: aren't there unicode friendly character classes?
12:27hyPiRionjustin_smith: sure thing, I just randomly grabbed the thing I already knew
12:27sdegutishyPiRion: ok then I'll stick with regex for now.
12:27sdegutisThanks.
12:27justin_smith\w is "word constituent", should catch things like ü (had to look it up just now, but I knew it existed)
12:28justin_smithoh, never mind
12:28justin_smith,(re-find #"\w" "ü")
12:28clojurebotnil
12:28justin_smith,(re-find #"\w" "u")
12:28clojurebot"u"
12:29justin_smithmaybe there is a locale setting that affects these things?
12:30grandyquestion: 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:30ToxicFrogjustin_smith: lua string library is not utf8 aware. You need a utf8 library.
12:30justin_smithToxicFrog: lua?
12:30ToxicFrogOh whoops
12:30ToxicFrogGot confused about what channel I'm in
12:30mtpgrandy: that sounds like you actually want, like, a grammar.
12:31mtpinstead of this kludgey regex contratption you're envisioning
12:31hyPiRionYeah, that sounds like a task for instaparse
12:31grandyhmm
12:31coventryWhat does it mean when the symbol fn* has {:once true} in its metadata?
12:32grandyok going to read up on instaparse :)
12:32mtpgood idea :)
12:37justin_smithcoventry: 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:37technomancycoventry: I think it means the return value is cached
12:40justin_smithan 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:43justin_smithfn.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:43justin_smith
12:45rasmustojustin_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:45coventryI 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:46justin_smithrasmusto: it seems like the metadata is what tells it to do this (if I understand what you are saying)
12:46rasmustojustin_smith: that's what it looks like, I don't know any more detail than that
12:47rasmustojustin_smith: I'm looking up fn* source atm
12:47justin_smithAFn.java?
12:48justin_smithnever mind, clearly not that
12:48rasmustojustin_smith: it's always fun to look at the java source though :)
12:49justin_smithjava conventions are weird
12:49justin_smithbut then again, every non-lisp looks weird to me, so I guess that should be taken under advisement
12:52rasmustojustin_smith: I think I'm in over my head: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/IFn.java
12:53coventryNo, 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:55justin_smithrasmusto: line 297: static public interface LOLOL
12:55justin_smithso apropriate :P
12:57sdegutisI can't imagine writing Ruby anymore. "else" and "end" seem so unnecessary now.
12:58ToxicFrogjustin_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:00Raynessdegutis: I wrote some Haskell the other day. I can't imagine writing Clojure anymore. All the ( and ) seem so unnecessary now.
13:00sdegutisRaynes: you really feel that way?
13:00RaynesNo.
13:00ambrosebs_lol
13:01sdegutisOh.
13:01mdrogalisI kind of had a similar sarcastic though. The syntax is surface level
13:01mdrogalisthought*
13:02rasmustolisp has absolutely no syntax
13:03callenwell that's clearly not true, but it's a cute thought.
13:03sdegutis,(iinc 1)
13:03clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: iinc in this context, compiling:(NO_SOURCE_PATH:0:0)>
13:03technomancyif that were true we would be writing our code in clojure.jvm.analyzer format
13:03sdegutisIs there a shorthand for (+ 2 i) ?
13:03mdrogalisYeah uh, I'm gonna go get some coffee. Later.
13:03technomancywhich is pretty hideous
13:03technomancysdegutis: commonly referred to as dinc, the elusive double-inc
13:03callen##(inc (inc 1)) ##(+ 1 2)
13:03lazybot(inc (inc 1)) ⇒ 3
13:03lazybot(+ 1 2) ⇒ 3
13:03clojurebot*suffusion of yellow*
13:03sdegutis,(doc dinc)
13:03clojurebotPardon?
13:03sdegutisheh
13:03rasmusto,((comp inc inc) 1)
13:03clojurebot3
13:03sdegutis:)
13:04TimMcsdegutis: He *said* it was elusive. :-P
13:04sdegutisI'll stick with + 2
13:04TimMc&((apply comp (repeat 2 inc)) 5)
13:04lazybot⇒ 7
13:04TimMcsdegutis: ^ There's your shortcut.
13:05rasmusto,(-> 1 inc inc inc inc)
13:05clojurebot5
13:05sdegutisI was thinking more like: &(last (take 2 (iterate inc 4)))
13:05sdegutis,(last (take 2 (iterate inc 4)))
13:05clojurebot5
13:05sdegutis,(last (take 3 (iterate inc 4)))
13:05clojurebot6
13:05sdegutisYeah that.
13:06llasramThat's the *easy* way to use `iterate`: ##((second (iterate (partial comp inc) inc)) 1)
13:06lazybot⇒ 3
13:06callennow just write a macro that checks for the number of "i"s in iiiiiinc to implement this.
13:06sdegutisI 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:06sdegutis(+1 i) ... (+ 1 i)
13:06callen(s iiiiiinc 5) => 11
13:07callenyeah, should write that macro.
13:07callenit'd complete the circle of time-wasting.
13:07rasmustoand a ddddddddddec one too
13:07TimMc(dwim (inc8 5)) => 13
13:08sdegutisReminds me of my nomnomnom lib for Ruby: http://rubydoc.info/gems/omnomnom/0.0.1/frames
13:08rasmustoTimMc: haha, this is so pointless now
13:08TimMcToxicFrog: 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:09callenRaynes: in honor of the channel's multi-segment namespace argument, my @work clojure project's namespace is ${PROJECT_NAME}.is.awesome
13:09callenTimMc: both kind of terrifying.
13:09Raynescallen: Reasonable name.
13:10bjawe went with #{COMPANY_NAME}.lib and #{COMPANY_NAME}.app (for the clj/cljs frontend app)
13:10callenI prefer to have more fun with it :)
13:11bjaalthough also #{COMPANY_NAME}.storm
13:11callenmy namespace is designed to brainwash users into liking it.
13:11callen"YOU WILL LIKE THIS CODE"
13:12bjamy 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:12bjaI just like getting notifications when changes happen in some of my libraries
13:12bjathird-party code that is
13:14TimMccallen: The second one looks like a Tachikoma.
13:16callenTimMc: I haven't seen that in ages.
13:24rasmustojustin_smith: ah, I get it now, LOLOL
13:29sdegutisWoo, just made my tokenizer 14x faster.
13:30sdegutisIt's also more readable now.
13:33callenis there a better verb than canonicalize?
13:33sdegutiscallen: intern, according to Java strings
13:33llasramcanonize
13:33sdegutisWhat's a good way to get the first index of an element in coll that satisfies (f)?
13:33callencanonize is our winner so far.
13:33callenintern is not it.
13:33hyPiRion(first (filter
13:33sdegutisIt was a joke.
13:33llasramcallen: Ha, I was joking
13:34callenI just want something less awkward/shorter
13:34callenit's going to be a namespace unto itself.
13:34riggerhttp://piplin.deviantart.com/art/Archery-17657627
13:34hyPiRioncallen: (def ffilter (comp first filter))
13:34sdegutishyPiRion: that only gives the element. I was thinking of using that with a mapped coll zipped with (iterate inc 9(
13:34sdegutis*0)
13:34hyPiRionops, wrong
13:34llasramc10n
13:35llasramOops, c10e
13:35llasramThere we go
13:35callenit would be nice if it was a little more readable too P
13:35callen:P
13:35hyPiRionah, right. There's no elegant way for that, you'd have to do some magic with map-indexed I suppose
13:36rasmustowhat's wrong with 'some'?
13:36sdegutisrasmusto: how would you use it here?
13:36sdegutisrasmusto: it doesn't give the index
13:36sdegutisRight now I'm using recur to call fn on each element and return the index where fn passes.
13:37rasmusto(some (fn [[i v]] (if (pred v) [i v]) (map-indexed vector coll)) ... or something
13:37xeqicallen: awesomize
13:37sdegutisrasmusto: ah ok
13:37rasmustoI didn't proof read that btw
13:38llasramsdegutis: In the absence of something compact, I think a function using `recur` is pretty reasonable
13:38sdegutisllasram: okay, cool
13:38sdegutisthanks
13:38technomancy~(doc keep-indexed)
13:38clojurebotexcusez-moi
13:38technomancy,(doc keep-indexed)
13:38clojurebot"([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:39technomancyhrm
13:39hyPiRionsounds reasonable
13:39xeqi,(doc filter-indexed)
13:39clojurebotIt's greek to me.
13:39xeqiblah
13:39llasramHmm, so like (first (keep-indexed (fn [i x] (when (pred? x) x)) coll))
13:39llasramNot bad
13:39rasmustomuch nicer
13:39llasramwell, with `i` for that last `x`
13:40technomancyexcept for the when
13:40hyPiRionand with if for the last when
13:40technomancyhyPiRion: o/
13:40hyPiRion\o
13:40rasmustowhat's wrong with when? I've heard people say it's only used for side effects, but I don't get that
13:40llasramEh. I prefer when even for non-side-effects, which I know puts me in the minority, but so there I stand :-p
13:40rasmustois it the implicit do?
13:41technomancyrasmusto: yeah, and if does the job nicely in this case
13:41rasmustotechnomancy: gotcha
13:41technomancyI 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:41sdegutisCool thanks technomancy and llasram
13:44llasramtechnomancy: 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:45technomancyvariadic macros: how do they even work? =)
13:45llasramYeah yeah :-p
13:52ToxicFrogTimMc: quite.
13:54sdegutisWhat's the auto-runner for Expectations?
13:56sdegutisAh, https://github.com/jakemcc/lein-autoexpect
14:02coventryWhere is the metadata shorthand (^{}) parsed?
14:03clgvfor datomic is there a guide how to get fast queries? which constructions should be ommited?
14:04coventryOh, LispReader.java, of course.
14:07sdegutisWhich is preferred when using defrecord, (->Record) or (Record.)?
14:08sdegutisIs one more efficient than the other or something?
14:09riggeruse the source, luke!
14:11jkkramersdegutis: ->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:11clgvare there no datomic users around right now?
14:11sdegutisGood point.
14:11sdegutisclgv: try #datomic
14:12sdegutisOh you did.
14:12clgvsame..
14:15clgvits pretty strange I do not manage to use my cpus up to 100% but I do not why
14:31rasmustoclgv: my code uses 6000% cpu
14:31sdegutisI'm slightly concerned that maybe I'm jumping to loop/recur too often now.
14:31sdegutisThen again, this is a parser. That's probably okay.
14:31clgvrasmusto: certainly not per cpu or your server is on fire now ;)
14:31clgvor per core to be more specific ;)
14:38mklappstuhlwant 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:38SegFaultAXThere are lots of migrations libraries available.
14:39SegFaultAXMigratus is a good place to start.
14:39sdegutisis (def foo 'foo) dumb?
14:39mklappstuhlfound drift & lobos so far
14:39SegFaultAXmklappstuhl: Those are also things, yes.
14:40sdegutismklappstuhl: I like technomancy's approach
14:40SegFaultAXmklappstuhl: Find the one that suits you. They are all functionally similar (as are most migration frameworks)
14:40sdegutishttps://github.com/technomancy/syme/blob/master/src/syme/db.clj#L68-L125
14:40mklappstuhlsdegutis: what does that approach look like?
14:40sdegutismklappstuhl: https://github.com/technomancy/syme/blob/master/src/syme/db.clj#L68-L125
14:40SegFaultAXsdegutis: Any particular reason you want to def a single symbol?
14:41sdegutisSegFaultAX: 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:42sdegutisI think :foo would work too but then I lose type safety. And they're probably just as efficient.
14:42technomancydidn't we tell you to use a gensym yesterday?
14:42sdegutistechnomancy: I was using it up until 2 minutes ago
14:42tylereDoes 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:42amalloysdegutis: that doesn't sound much like C's enum :P
14:42sdegutistechnomancy: then I wanted to use the constant in a case statement
14:42SegFaultAXsdegutis: Are you using it as a sentinel value?
14:42amalloytylere: no
14:43coventrytylere: ##(source declare)
14:43lazybotjava.lang.RuntimeException: Unable to resolve symbol: source in this context
14:43coventry,(doc declare)
14:43clojurebot"([& names]); defs the supplied var names with no bindings, useful for making forward declarations."
14:43sdegutistechnomancy: and it said "no matching clause for BLAAERGGGBLLAAA"
14:43technomancylame
14:43sdegutistechnomancy: no, fast.
14:43technomancysdegutis: if you use read-time gensym it should work though
14:44sdegutistechnomancy: case doesn't even eval, it's constant time lookup, so (def foo 'foo) works great here
14:44technomancy,genned-sym#
14:44clojurebot#<CompilerException java.lang.RuntimeException: Unable to resolve symbol: genned-sym# in this context, compiling:(NO_SOURCE_PATH:0:0)>
14:44technomancy,:genned-sym#
14:44clojurebot:genned-sym#
14:44technomancyhuh
14:44technomancyI guess that would require wrapping the whole thing in a `
14:44sdegutistechnomancy: 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:48coventrytechnomancy: The # syntax doesn't seem to work with keywords: ##(list `(:genned-sym# genned-sym#))
14:48lazybot⇒ ((:genned-sym# genned-sym__134041__auto__))
14:48technomancycoventry: huh; must have been thinking of something else
14:49sdegutisSo, what's wrong with (def foo 'foo)?
14:50sdegutisHmm, it should be thread-safe. And it doesn't cause a stackoverflow.
14:50SegFaultAXsdegutis: It's probably entirely unnecessary.
14:50sdegutisSegFaultAX: Why's that?
14:50SegFaultAXsdegutis: Do you intend to use identical? somewhere?
14:51sdegutisSegFaultAX: I have (case ... foo ...), does that count?
14:51SegFaultAXsdegutis: Are multimethods not an option?
14:51sdegutisNow I'm confused.
14:52SegFaultAXsdegutis: 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:53sdegutisOh.
14:53mklappstuhlsdegutis: technomancy's approach is indeed quite interesting, especially since it's so simple :)
14:54sdegutisSegFaultAX: 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:54sdegutisSegFaultAX: (def sym 'sym) seems to solve that, but I'm concerned there might be hidden caveats
14:55coventryIf 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:55SegFaultAXsdegutis: 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:56sdegutisDunno, that's why I was asking you guys :)
14:56sdegutiscoventry: why do you say that?
14:57coventryYou'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:57sdegutisIt is? I didn't realize it is.
14:58SegFaultAXsdegutis: Everyone objecting wasn't a dead giveaway?
14:58coventryYou want to mess around with the namespace programmatically. Unless you are making a quarantined namespace for that purpose, that is ugly.
14:59sdegutiscoventry: ah that's an interesting way to look at it
14:59callenit's not interesting at all, it's pretty obviously a bad idea.
14:59sdegutiscallen: why?
15:00coventryWell, 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:00callenif you don't know why mucking around with namespaces programmatically is a bad idea, then I can't tell you either.
15:00callencoventry: yeah.
15:00sdegutisI guess I don't really look at this like too heavy a use of metaprogramming.
15:01sdegutisMainly because it's very simple: foo refers to foo.
15:01llasramWhich is exactly what keywords are for?
15:01TimMcsdegutis: Oh wait, you also go by the nick "futile", right?
15:01TimMcI thought I recognized this conversation.
15:01callenTimMc: yeah, same bloke.
15:01callenTimMc: lots of conversation about bad ideas, no actual usable code at the end.
15:02callenI wonder how much programmer time he's wasted in total.
15:02callenbetween his own efforts and everybody else he sucks into his pointless bullshit.
15:03coventryIf 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:03callenI have Datomic queries to write - I'm out too.
15:24sdegutisWell so much for trying to discuss design philosophies. Didn't expect so much condescending dismissiveness from #clojure.
15:25callensdegutis: http://i.imgur.com/Zoc8zR7.jpg
15:25sdegutisThat was probably uncalled for, sorry.
15:25gdevsdegutis, sorry I was out to lunch, what did I miss?
15:25riggerjust need to find the right person, right time
15:26gdevI like design discussions =)
15:26callengdev: #RUBY_DRAMA
15:26callengdev: namespace munging.
15:26mklappstuhlgetting errors like this: ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.Symbol clojure.lang.RT$1.invoke (RT.java:224)
15:26mklappstuhlhow can I get some better errors?
15:26mklappstuhllike line numbers and these sorts of things
15:27sdegutisgdev: 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:27coventrymklappstuhl: I generally (use 'clojure.repl) and then (pst) to get the full stacktrace.
15:27alejandro_mklappstuhl: or http://richhickey.github.io/clojure/clojure.stacktrace-api.html
15:28sdegutisgdev: 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:28coventrymklappstuhl: 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:29mklappstuhlcoventry: how exactly would I use pst?
15:29mklappstuhlcoventry: nevermind :)
15:29mklappstuhlhttp://clojuredocs.org/clojure_core/clojure.repl/pst
15:30mklappstuhlhaha, it doesn't list any of my source files though :D
15:31gfrederickswhy would (range 100000000) be twice as slow with (reduce +) than the same thing in a vector?
15:32nDuffgfredericks: because it can't seek, and thus can't parallelize.
15:32nDuffgfredericks: ...I'm actually surprised it's only twice as slow.
15:32gdevsdegutis, can you refheap the code? I'm bad at word problems =(
15:32nDuffOh, wait, this isn't core.reducers?
15:32nDuffDon't know, then.
15:32gfredericksnDuff: reduce + can't parallelize anyhow
15:32gfredericksk
15:33gfredericks,(time (reduce + (range 1000000)))
15:33clojurebot"Elapsed time: 187.122121 msecs"\n499999500000
15:33gfredericks,(let [v (vec (range 1000000))] (time (reduce + v)))
15:33clojurebot#<OutOfMemoryError java.lang.OutOfMemoryError: Java heap space>
15:34gdevthat was faster
15:34gfredericksthat is a small jvm.
15:34gfredericksI was doing mine 100 times as big
15:34gfredericks&(time (reduce + (range 1000000)))
15:34lazybot⇒ "Elapsed time: 257.85282 msecs" 499999500000
15:34gfredericks&(let [v (vec (range 1000000))] (time (reduce + v)))
15:34lazybot⇒ "Elapsed time: 1376.893624 msecs" 499999500000
15:34coventrygfredericks: 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:35callen##(time (apply + (range 10000)))
15:35lazybot⇒ "Elapsed time: 10.051635 msecs" 49995000
15:35callen##(time (apply + (range 1000000)))
15:35lazybot⇒ "Elapsed time: 349.833382 msecs" 499999500000
15:35callen##(time (apply + (range 10000000)))
15:35lazybot⇒ "Elapsed time: 3344.378229 msecs" 49999995000000
15:35sdegutisgdev: https://www.refheap.com/18374
15:35callen##(time (reduce + (range 1000000)))
15:35lazybot⇒ "Elapsed time: 269.19041 msecs" 499999500000
15:35callenmarginal. cool.
15:38gdevsdegutis, thanks, lemme have a look at it
15:39hiredmanI would suspect vectors are faster for sequential access in general, because they pack values in nice cache filling arrays
15:39mklappstuhlI 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:40hiredmanmklappstuhl: are you doing (ns 'foo) ?
15:40mklappstuhlhiredman:
15:40mklappstuhlyes
15:40hiredmanns is macro it doesn't need the quote
15:41callen##(time (reduce + (vec (range 1000000))))
15:41lazybot⇒ "Elapsed time: 4546.920025 msecs" 499999500000
15:41mklappstuhlhiredman: ok, thats good to know. should that also change whats printed by (pst) ?
15:41mklappstuhl(it doesn't for me)
15:41ztellmancallen: you're timing the conversion to a vector, too, in that benchmark
15:41callenI know
15:41callenI just caught it.
15:41mklappstuhlcode is here btw: https://github.com/mklappstuhl/goldman.clj/blob/master/src/mklappstuhl/stock_utils/db.clj
15:42callen##(let [v (vec (range 1000000))] (time (reduce + v)))
15:42lazybot⇒ "Elapsed time: 2281.862622 msecs" 499999500000
15:42ztellman"benchmark", I should say
15:42callenztellman: it's not serious, I'm just being idle.
15:42callenI know to use criterium in things I care about :P
15:42callen##(let [v (vec (range 1000000))] (time (reduce + v)))
15:42lazybot⇒ "Elapsed time: 1857.035772 msecs" 499999500000
15:42ztellmancallen: oh, sure, but if I don't keep the benchmark snootiness torch burning, who will?
15:43callen##(let [v (vec (range 1000000))] (time (apply + v)))
15:43lazybot⇒ "Elapsed time: 2516.47335 msecs" 499999500000
15:43callenztellman: well, I was, earlier.
15:43callentold futty to use criterium, haha.
15:43TimMcsdegutis: Anything beyond preconditions that check inputs for membership in a set is going to be pretty ugly.
15:43ztellmanby the way, you guys know you can use scientific notation with range, right?
15:43ztellmanway easier to visually parse
15:44callenwell it's not specific to range.
15:44sdegutisTimMc: how so?
15:44ztellmancallen: yes, but specifically with range it's almost always what you want to do
15:44TimMcsdegutis: Because if you want more than that, you're probably using the wrong language.
15:46coventrysdegutis: 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:47sdegutiscoventry: 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:48coventryThat's all good reading, if you want to write a parser.
15:50gfrederickshiredman: but (range n) is also chunked in 32s, is it not? is it somehow less cache-optimal than a vector?
15:53gfrederickscoventry: 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:53gfredericksfaster than the vector even, at first glance
15:55hiredmangfredericks: oh, right, chunking :(
15:57callen##(let [v (vec (range 1e6))] (time (apply + v)))
15:58lazybot⇒ "Elapsed time: 2175.583604 msecs" 499999500000
16:02coventrySeems like the JIT compiler optimizes all of this away, anyway. https://www.refheap.com/18375
16:09gdevsdegutis, 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:10sdegutisgdev: good plan
16:11Rubix(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:11gdevif you want to manage risk and be able to quickly refactor, you have definitely chosen the right language
16:16gdevRubix, bean only shows things exposed through its getter methods
16:17Rubixgdev: I have to define getter methods for it? shucks
16:18llasramRubix: Do you control the user-defined-class?
16:18Rubixllasram: yes
16:18gdev##(:members (clojure.reflect "foo"))
16:18lazybotjava.lang.ClassNotFoundException: clojure.reflect
16:19llasramRubix: does it exist to ship to a Java interface or such?
16:19Rubixllasram: no, its pojo,
16:19gdevRubix, 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:20llasramRubix: I mean, are you using a Java class because you need to pass it to some Java API?
16:20Rubixllasram: i've got a pile of legacy java code under my control, trying to extract pojos to maps
16:21llasramThere we go -- that's what I should have asked :-)
16:21llasramAnd the POJOs directly expose data via public members, not getter/setter methods?
16:22Rubixllasram: yes
16:22Rubixall public, all the time
16:22llasramRubix: Yeah, I don't think anything off-the-shelf exists, but as gdev suggested you should be able to use clojure.reflect/reflect
16:23callenhrm. yes. core.async is fast #_#
16:23gdev##(:members (clojure.reflect/reflect "foo"))
16:23lazybotjava.lang.ClassNotFoundException: clojure.reflect
16:24Rubixllasram, gdev : what's that argument to (clojure.reflect) ?
16:25Rubixstring-represented declared class name?
16:26gdevRubix, I'm just passing in a string so it will give me a map of all the members of java.lang.string
16:26Rubixah
16:27gdevRubix, you could also do (:members (clojure.reflect/reflect (MyClass.))
16:28mklappstuhlhow do I reload the namespace I'm currently in in the REPL?
16:28llasramgdev, Rubix: Well, and you can use reflect-type to reflect on a Class
16:28llasramEr, type-reflect even
16:29coventrymklappstuhl: Are you using emacs? I generally just do C-c C-k in the corresponding source file.
16:29llasram&(require 'clojure.reflect)
16:29lazybot⇒ nil
16:29llasram&(->> clojure.lang.Keyword clojure.reflect/type-reflect :members (filter #(and (instance? clojure.reflect.Field %) (-> % :flags :static not) (-> % :flags :public))) (map :name))
16:29lazybot⇒ (sym)
16:29mklappstuhlcoventry: no. vim + lein repl
16:29llasram&(.-sym :hello)
16:29lazybot⇒ hello
16:30TimMcmklappstuhl: (require (.name *ns*) :reload)
16:31TimMcmklappstuhl: (require 'my.ns :reload) if you want to reload it by name
16:31callenyou probably don't want to use reload.
16:31llasramTimMc: also (ns-name *ns*)
16:31mklappstuhlcallen: whats wrong with reload?
16:32callenno seriously
16:32callen(require '[clojure.tools.namespace.repl :refer [refresh]]) (refresh)
16:32callendo that. Don't use reload/reload-all
16:32callenmklappstuhl: cf. Stuart Sierra's workflow post and the documentation on clojure.tools.namespace.
16:32mklappstuhlcallen: link?
16:35TimMcIf you don't use protocols or multimethods (and you defonce your state) it is fine.
16:37callenrefresh is moar betta.
16:37callenand doesn't require that you cherry-pick.
16:39seangrov`Does lighttable work with clojure 1.5 projects?
16:39rasmustoseangrov`: I think the newest release requires 1.5.x in project.clj
16:43aaelonyI 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:43mklappstuhlcallen: if I run (require '[clojure.tools.namespace.repl :refer [refresh]]) and then (refresh) it can't resolve the symbol...
16:46justin_smithaaelony: maybe an iterate that updates the key to use on each time through?
16:46justin_smithaaelony: that would require a function that takes the previous key, and generates the next one from that
16:46justin_smithor an infinite list of keys
16:46justin_smithone of those
16:48aaelonyjustin_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:51aaelonyjustin_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:51aaelonyjustin_smith: maybe the answer is indeed "that's what let is for" and then merge it in the last step….
16:52justin_smith(zipmap (create-key-seq) (iterate process input))
16:53justin_smithmaybe?
16:54aaelonyjustin_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:55aaelonyjustin_smith: or maybe that is what you specify in the key-seq… interesting...
17:05coventryaaelony: Have not used it, but synthread may help you do this kind of thing. https://github.com/LonoCloud/synthread
17:05coventryEspecially ->/as
17:06aaelonyconventry: appreciate it, will take a look.. thanks
17:08aaelonycoventry: looks like a good fit! Need to figure out the syntax. thanks! :)
17:09SegFaultAXSynthread is awesome.
17:11aaelonykudos to chouser!
17:16callenSegFaultAX: yes it is.
17:17RaynesSegFaultAX: 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:21callenI think Raynes and callen switched brains today.
17:21Rayneslol
17:22Raynescallen: Was that *that* mean?
17:23callenwell. It wasn't as bad as waterboarding bloom with his CV, but it was surprisingly negative.
17:23hyPiRionIt could be amalloy too, for that matter.
17:23Raynescallen: :P
17:26amalloyc'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:26amalloythe fecal comparisons are a callen thing for sure
17:28callenso am I dumb for being surprised that (def f (memoize (fn [] (atom {})))) (swap! (f) assoc :a 1) @(f) did the right thing?
17:34dobry-dencallen: 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:34seangrov`Are watches enabled for lighttable?
17:35dobry-denseangrov`: i think so. i saw the keybindings for toggling them when i was editing the behavior/keymapping files
17:38TimMccallen: What were you expecting?
17:39coventryIs 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:40SegFaultAXRaynes: I don't think the synthread macros are that bad personally.
17:40callendobry-den: just try it
17:40callenSegFaultAX: I think it's more significant that an ex-Haskell user dislikes it.
17:40mabescoventry: I've been wondering that myself.. sometimes I comment out the form with #_, and reload, just to get rid of them...
17:40callenTimMc: for Clojure to be as ghetto as every language I'd previously used.
17:41callenTimMc: Python set my expectations kinda low.
17:41calleneven after ${X} years I still haven't learned to just trust it.
17:41seangrov`dobry-den: Ah, yes, found it, thank you
17:41seangrov`Hrm, lighttable is pretty nice
17:42SegFaultAXI don't think Python is particularly more ghetto than any other language.
17:43SegFaultAXEvery language has dark corners. Python doesn't have as many as some.
17:44unlinkI'm getting the following error when I run nrepl-jack-in: "error in process sentinel: Could not start nREPL server: "
17:44unlink`lein repl' works fine from M-x shell
17:45callenseangrov`: is it? lot of trouble with it lately.
17:45technomancyunlink: does M-! which lein work?
17:46rasmustocallen: my ctrl-space hotkey didn't work with my keyboard, so I couldn't un-fullscreen lighttable without uninstalling
17:46unlinktechnomancy: yes
17:46rasmustocallen: it's still usable enough for proj euler and 4clojure stuff
17:47Pupnikso is windows notepad
17:47technomancyunlink: huh; dunno. you could do `lein repl :headless` and M-x repl to connect to it
17:48technomancyM-x nrepl
17:50rasmustoPupnik: so is pencil and paper
17:50sdegutisI vaguely remember a short-hand for (and (> x min) (< x max)), does it exist or was I dreaming?
17:50unlinktechnomancy: open-network-stream: make client process failed: Can't assign requested address, :name, nrepl, :buffer, *nrepl-connection*, :host, 127.0.0.1, :service, 0, :nowait, nil
17:52technomancyunlink: did you give it a port?
17:53seangrov`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:53sdegutisAh, (< min x max)
17:53sdegutis,(< 3 4 5)
17:53clojurebottrue
17:53sdegutisNeat.
17:53seangrov`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:54seangrov`I recommended he try out lighttable, figured that's likely easier to pickup than emacs
17:54sdegutisseangrov`: sounds like it
17:54unlinktechnomancy: ah. I had mispelled :repl-options as :nrepl-options.
17:55unlinktechnomancy: I am able to connect via M-x nrepl.
17:55seangrov`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:55unlinktechnomancy: it would be nice if unrecognized forms in defproject weren't silently ignored.
17:55technomancyunlink: nice, but infeasible
17:56sdegutisseangrov`: I'm just really confused about the lack of syntax highlighting part.. doesn't Xcode have a built-in syntax highlighter?
17:56technomancygiven that any plugin can arbitrarily choose to recognize any form
17:56sdegutisseangrov`: oh yeah, probably not for Lisp langs..
17:56unlinksounds like an architectural limitation worth addressing.
17:56seangrov`sdegutis: Exactly.
17:56technomancyunlink: you would have to load every plugin for every execution
17:57seangrov`It's a worrisome sign for me when a developer hasn't spent a lot of time on their tools though
17:57unlinknot if you, for example, enforced a convention for plugin-specific options.
17:57callenseangrov`: to me too.
17:57seangrov`You use them for so many years, it makes sense to invest in making them nice and efficient
17:57callenseangrov`: I'm introducing Clojure guerilla style at my company. Going to conquer one mind at a time.
17:57seangrov`Haha
17:57rasmustocallen: what are your tactics?
17:57callenseangrov`: a lot of people aren't that invested in their careers.
17:57seangrov`callen: We'll have to grab drinks some time
17:57callenrasmusto: use Datomic as an excuse to use Clojure
17:57seangrov`Ah, fair enough
17:57rasmustocallen: oh damn
17:58callenrasmusto: steal labor for my project, brainwa^H^H^H^H^H^H convert them
17:58technomancyunlink: that just moves the problem around
17:58seangrov`I suppose I'm expecting a common level of desire to improve
17:58callenrasmusto: make project awesome, impress air support, conquer another thing.
17:58rasmustocallen: yeah, awesome projects can go a long way
17:58callenseangrov`: not what I've encountered. and yes, we should grab drinks. Are you coming to the meetup today?
17:58unlinktechnomancy: no, it solves that part of the problem. then you require projects to declare the configuration they understand.
17:59technomancyit's technically feasible, but it goes against the design principles of clojure
18:00unlink...fail slowly and silently?
18:00technomancyif you want to be able to catch unknown patterns properly you need a static type system
18:00seangrov`callen: Heading to a different meetup a friend asked me to join, sadly
18:01sdegutisAhh!!
18:01unlinkthis has nothing to do with types, and everything to do with (developer-)friendly user interfaces
18:01technomancy,(contains? [1] 1) ; <- unlink
18:01clojurebotfalse
18:01callenseangrov`: You're in the city right? you free tomorrow?
18:02seangrov`callen: Yeah, but heading out to JSConfEU soon, so prepping a lot
18:02seangrov`Our office is in the Mission, I'm in Twin Peaks
18:02coventrymabes: Just thought of the right google query: (defun drop-overlays () (interactive) (remove-overlays))
18:02callenseangrov`: SOMA / Ingleside for me, also I drive.
18:02technomancyignoring the significant backwards-compatibility challenges, it's just not in line with the zen of clojure to protect against that kind of mistake
18:03seangrov`callen: Early drinks at CBS?
18:03unlinktechnomancy: I'm not sure what user-interface compromise in the name of efficiency has to do with making leiningen hard to debug
18:04callenseangrov`: 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:04unlinkI think a better example would be: (contains? :x 1)
18:04unlinkyou pass it something invalid, so it throws an exception loudly and makes the error obvious
18:05unlinkinstead of silently doing the wrong thing and looking like it works, even when its input is never valid
18:06mabescoventry: nice, thanks for sharing.. adding that along with a keybinding for it :)
18:21sdegutisWhat's a good way to test if two ranges intersect? Convert them to sets and use the set lib?
18:21ztellmanare the ranges already turned into sequences?
18:22ztellmanor are they just intervals of [start end]?
18:25unlinkanother 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:25sdegutisztellman: I actually just have two pairs of pos/len
18:25technomancyunlink: for backwards-compatible changes there is the lein-precate plugin
18:26ztellmansdegutis: http://www.rgrjr.com/emacs/overlap.html
18:26ztellmanthat should be a bit more efficient than calculating the intersection
18:26unlinkI 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:26technomancyunlink: 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:26sdegutisztellman: sweet, thanks!
18:27technomancyfurther proof that the validity of a given key is undecidable
18:27gfrederickstechnomancy: is there a leiningen undecidability theorem?
18:27seangrov`ztellman is a wizard
18:27gfredericks(presumably referred to as LUT by the kids these days)
18:28ztellmaninterval arithmetic is wizardry?
18:28technomancygfredericks: maybe you're confusing it with the hagelberg uncertainty principle.
18:28unlinkof course it's undecidable. that's the problem. you have a declarative document without any checks for validity.
18:29sdegutisztellman: no, just that you do tons of crazy efficiency things
18:29sdegutisztellman: I'm never surprised to see ANNs about super-efficient this or that from you on the mailing list :)
18:30unlinkJava'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:31muhoothe 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:31muhooi think rchickey calls it "consenting adults programming" or somethign similarly pithy
18:31technomancythe first two are completely different: XML has schemas, Haskell has a static type system
18:31technomancyI have no idea how python works
18:31unlinkno, that's the general attitude of PHP and JavaScript.
18:32hyPiRionso, uh, is it the battle of the types again?
18:32unlinkHaskell has a static type system, but its setup descriptor is not code. it's a declarative document similar to project.clj.
18:32technomancyand actually in the case of maven it's a PITA that you can't attach arbitrary metadata to a pom
18:32mgaarecabal is also a terrifying nightmare :D
18:33gfredericksI think you can isolate certain cases in clojure core of returning nil when passed totally irrelevant types, e.g. ##(contains? :foo :bar)
18:33lazybot⇒ false
18:33hyPiRion`cabal install cabal-install` always gets me
18:33unlinkproject.clj is *excellent* in principle. it is exactly what you should want: a non-code datastructure specifying your project.
18:33gfredericksit's pretty easy to argue that that should throw an exception without violating the zen of clojure
18:33technomancygfredericks: this is more like (:foo {:bar 1}) though
18:33callenmuhoo: I tend to agree with the "consenting adults" thing btw
18:34seangrov`callen: Have you successfully got datomic into production?
18:34callenoh cool, we're getting a 64TB SSD Z-raid array installed in one of the servers at work.
18:35callenseangrov`: it's not finished, but it's going to be very soon.
18:35technomancyI would actually be interested in a language that had (:foo {:bar 1}) throw if you didn't provide a not-found value
18:35callenhave the license key for the pro edition ready to go, just hacking the code together.
18:35seangrov`callen: How's your experience been?
18:36technomancybut that's not what this is about, because having no :repl-options in your project.clj file is completely reasonable
18:36callentechnomancy: core.typed?
18:36mgaarecallen: have you played around with any larger data sets in datomic yet?
18:36callenseangrov`: there are idiosyncrasies, but it's good so far. The design seems solid so far.
18:36hyPiRioncallen: that has nothing to do with core.typed though? It's more about a lack of value.
18:36callenmgaare: nothing substantial yet, but I will when I stress test the pro instance...which will happen whenever IT gives me my server.
18:36hyPiRiona map entry, rather.
18:36callenhyPiRion: core.typed can enforce that, no?
18:36technomancycallen: I'd rather it worked that way without a substantial up-front investment
18:36seangrov`technomancy: Haven't been following along too closely, but how about a lein plugin that checks the project.clj for known mispellings?
18:37technomancyseangrov`: that's reasonable
18:37seangrov`Would be an easy one to submit pr's for on github and help people out
18:37mgaarecallen: one thing we noticed was that if you have a lot of entities, partitioning becomes very important
18:37technomancyseangrov`: or even "here's what you're using that's not in sample.project.clj"
18:37callenlevenshtein the keys?
18:37callenoh, that's better still.
18:38callenmgaare: interesting. Our needs are relatively minimal so far WRT performance/volume
18:38callenmgaare: the thing I'm building is multiple orders of magnitude overkill for our actual data needs (a conscious decision)
18:39callenmgaare: can you say what tier of entity pop-counts started necessitating paying attention to partitioning?
18:40mgaarecallen: our test data was about 8 figures of entities. Need to do it well before that point
18:40dissipate__what's up with datomic being closed source?
18:41callendissipate__: wanna make money. don't blame 'em. Their license terms are hyper-mega-reasonable.
18:41callen$3k perpetual license. ridiculously good deal.
18:41callenyou re-up a fraction of that for maintenance.
18:41callenpay more for more peers
18:41mgaarenot sure exactly where, because we ended up deciding against using it
18:41callenmgaare: we'd be hard pressed to get into anything like that, I think.
18:41dissipate__callen: Hickey should have closed sourced clojure as well, right?
18:42callenmgaare: we're more likely to run into trouble from churning history.
18:42callendissipate__: no.
18:42dissipate__callen: what's the difference?
18:42callenyou can't really get people to buy into a language like that, like you can a tool like a database.
18:42seangrov`callen: Even a database is tough
18:42callenit is, but Datomic is sufficiently compelling.
18:42mgaareThe 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:42dissipate__callen: there's a lot of open source free database engines out there
18:42callenDatomic was so compelling that many-many-many of my coworkers were really into it despite being deeply skeptical of Clojure
18:42callenI...don't really understand why yet.
18:43callenmgaare: so it's index size as a function of pop then probably, okay.
18:43dissipate__callen: did you pay $3K for diatomic?
18:43dissipate__er, datomic
18:43dissipate__callen: you are in a java shop, right?
18:43callenlol no
18:43callenPython.
18:44callenwe have a pro license of datomic lying around, yeah.
18:44callenI'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:44dissipate__callen: ah, that's better than java!
18:44mgaarecallen: 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:45callenmgaare: fucking lol
18:47callenhttp://www.informationweek.com/software/information-management/the-man-who-tortures-databases/240160850
18:48callenmgaare: next step is to just start breaking out partitions roughly by entity type right?
18:49callenhrm.
18:50mgaarecallen: 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:51callenmgaare: that's more or less what I expected.
18:51callenDatomic is just nicely designed, it's not magical.
18:51mgaarethere 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:52callen...wat
18:53mgaareI think it was medical data or something, so each user could have a huge number of entities associated with it
18:53holohi
18:53callenmgaare: oh I see. yeah I saw that his profile mentioned healthcare data.
18:54callenmgaare: I work at a genetics company, but our data "load" per human or logical 'thing' is much smaller
18:54callentons of raw data from the sequencers themselves, but that gets sifted quickly.
18:55callenRich handles some loony conversations on the mailing list.
18:56mgaarelisp seems to attract more than its share of strange minds
18:57holoI 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:57sdegutisI still don't think of Clojure when I see the word "lisp"
18:57sdegutisholo: I'd probably wrap it with boolean too
18:58sdegutisholo: or just document that the function returns "logical true"
18:58sdegutisIn that case, people know not to expect literal true
18:59callenmgaare: have you seen Haskell's menagerie of madness?
19:01holosdegutis, 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:01mgaarecallen: 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:01sdegutisholo: ah didn't know it would be shown in the readme
19:02sdegutisholo: another option is to just replace the output in the readme with "<truthy value>"
19:03holosdegutis, insightful. would you represent it verbatim "<truthy value>"?
19:03sdegutisholo: maybe.
19:07holo(inc sdegutis)
19:07lazybot⇒ 2
19:07sdegutisyay
19:23seangrov`Any compojure experts?
19:23sdegutisMany.
19:23callenseangrov`: expert no, journeyman...maybe. soup?
19:23callenaka, "just ask" :P
19:24seangrov`Sorry, looked away for a momenth
19:24seangrov`Looking to match on a route either for "/:callback" or "?callback=" - seems like I have to define two separate routes for that though
19:25seangrov`Any way to make the "/:callback" an optional route variable?
19:27Brand0callback hell
19:30callenseangrov`: is it namespaced or is this top-level?
19:31callenthe routes.
19:31callenas in, is there a prefix?
19:31seangrov`No, just the root url
19:32seangrov`Just wondering if there's a way to get compojure to do something like ["/user/:id" :optional :id]
19:32callennot directly, I'm thinking about a couple of indirect ways atm though.
19:33callenlet me test something.
19:34seangrov`No a huge deal, just something I've wanted
19:34riggerwhy are you providing two different apis?
19:35SegFaultAXrigger: Why aren't you?!
19:35riggerbecause i have no imagination
19:35seangrov`rigger: BAckwards compatibility
19:35riggergotcha
19:36sdegutisseangrov`: yeah those will need two separate routes
19:36SegFaultAXrigger: http://imgur.com/r/4chan/3YdJs
19:38callenseangrov`: nope.
19:38callenseangrov`: you can do it if you don't mind snagging the param yourself.
19:38seangrov`Ah well, no worries
19:38callenseangrov`: I have a workable solution.
19:39SegFaultAXYou wouldn't want to have 1 route anyway.
19:39callen(GET "*" [] route-handler), (str (:params blah)) in the handler => {:* "/blah"}
19:39seangrov`callen: This is what I ended up doing https://www.refheap.com/ad18f6f873ca84e34753cade5
19:39callenevil/messy, requires invoking the params parser with a wrapper
19:39riggerSegFaultAX: that's awesome
19:39callenseangrov`: hrm, I tried that and it didn't work for me.
19:39callenlet me try it again.
19:40riggerseangrov`: are you running this behind a webserver?
19:40clojurebotTitim gan éirí ort.
19:40callenoh yeah that does work.
19:40callenseangrov`: yeah that's way better. I forgot the keyword before the regex in my attempt.
19:40SegFaultAXseangrov`: You want 2 routes. /foos and /foos/:foo_id should logically name different resources.
19:41riggerbecause i'd just stuff that compatability layer in a rewrite rule
19:47sdegutisAll my time being spent in clojure.lang.Reflector.getMethods and .getField means I should probably drop down to Java, doesn't it.
19:47sdegutis:(
19:50technomancyno, just add type hints
19:52sdegutisthanks
19:58callensdegutis: your life would be easier if you just went through a Clojure book
19:58sdegutiscallen: roger
19:58callensdegutis: and would involve less time-wastey questions
19:58sdegutis:|
20:03rasmustosdegutis: don't take that the wrong way
20:03rasmustosdegutis: Clojure Programming followed by Joy of Clojure really are that good
20:04callen^^ yes.
20:05sdegutisrasmusto: Very good suggestion, thanks. I'm not taking it the wrong way.
20:05sdegutisAlthough I may have to trip callen if I ever see him walking by in real life.
20:06rasmustosdegutis: oh? A trip to where?
20:06sdegutis:)
20:06sdegutiscallen: you know I'm teasing :)
20:06sdegutis:|
20:09sdegutis:)
20:18callenhe's lucky he left.
20:18rasmusto:o
20:19callenrasmusto: I was about to correct him on my not teasing :P
20:19callenI was quite serious when I said he wastes time.
20:19rasmustocallen: I like being told that I'm writing terrible code/wasting time
20:19rasmustoOther people should be too
20:19callenhis problem is he refuses to read or really do anything other than poke at projects he'll abandon in a week.
20:20callenand in the process waste peoples' time with his flavor of the week
20:20callenI've seen 1,000 other people on IRC like him
20:21callenproductive 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:21mtpthis is why my client has a fools list
20:21callenwhen was the last time you saw amalloy ask a question that wasn't hypothetical, rhetorical, or sarcastic?
20:22amalloyor irrelevant
20:22rasmustoare we tring to quantify peoples' software productivity? :p
20:22callenI'm not saying asking questions is bad, but you can definitely up your game in terms of the quality of the questions.
20:22TEttingercallen, was that rhetorical?
20:22callenTEttinger: astute.
20:23TEttingercallen, yeah I do think if there was a required reading for IRC, How to Ask Good Questions should be most of it
20:23rasmustodoes anybody else know how to ask good questions?
20:24callenhttp://www.catb.org/esr/faqs/smart-questions.html
20:24TEttingerrasmusto, how do i lern to spel
20:24callenhe's a blow-hard, but he's not wrong here.
20:24callenfrom 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:24coventryrasmusto, 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:25callenit's selfish to expect people to piecemeal teach you what there's already excellent material for.
20:25rasmustocoventry: this is getting a bit meta
20:25TEttingerif 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:26callenyep, very good example.
20:26callenor 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:33callenoh my dear god I hate mercurial.
20:39seangrov`If I run-jetty in a background thread (:join? false), how can I get access to the error?
20:39seangrov`Err, the output of the server
20:41callenseangrov`: by output do you mean stdout?
20:41callenseangrov`: or something else?
20:42callenstdout should just work.
20:42seangrov`When running `lein ring server` I get the stack trace on errors in the browser
20:42callendo you want them...in the terminal? in a data structure? what do you want?
20:42seangrov`Let me look at how lein-ring does it
20:42seangrov`callen: Yeah, sorry for being vague, will look into it
20:42callenseangrov`: I've solved this very problem, if you just tell me what you want I can...
20:43seangrov`Ah, I'd like the stack trace printed in stdout
20:43technomancyseangrov`: check *nrepl* if using nrepl.el
20:43seangrov`The contractor is using lighttable
20:43technomancyerr--*nrepl-server*
20:43callenseangrov`: add a failsafe middleware that catches the error, snags the stacktrace, and prints it to stdout.
20:43callenyou can let the error re-bubble or squash it, up to you.
20:43seangrov`Ah, ok
20:43technomancyor better yet put it in the HTTP response
20:44callenlein ring only does its thing for unhandled exceptions.
20:44callentechnomancy: that's what lein ring does, puts it in the HTTP response.
20:44technomancyhttps://github.com/technomancy/syme/blob/master/src/syme/web.clj#L153
20:44technomancyoh gotcha
20:44callenit's just hoomans.
20:44callenseangrov` wanted stdout...presumably so LT knows what's up.
20:45technomancyit's probably going to stdout, just not to *out*
20:45technomancySystem/out that is
20:45bjathis 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:46technomancygfredericks is in chicago iirc
20:46callenbja: you might ping the mailing list as well.
20:46bjathanks, I'll give that a shot
20:47bjawas at the chicago clojure meetup last month, but had to leave pretty quick after the presentation
20:51bjaerr, 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:51callenI've been using core.async to force callbacks to self-destruct. I feel like I could be doing this in a better way.
20:51bjacallen: self-destruct how?
20:52callenbja: do no evil, return nil.
20:52callenlangohr's consumer cancellation stuff is a little awkward when you forget to set a consumer tag.
20:54callenI'm not even really using core.async holistically but I'm still really enjoying using it to clean up code here and there.
20:54callenI'm getting close to turning all of my callbacks into dumb channel funnels.
21:08dnolencallen: fun stuff
21:12bbloomspeaking of callbacks, just saw https://idea.popcount.org/2013-09-05-it-aint-about-the-callbacks/ on HN
21:15aaelonythis is interesting… a clojure library for financial planning! https://github.com/sebhoss/finj/ has anybody used it?
21:16dnolenbbloom: 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:17bbloomdnolen: so i'm beginning to think that it's just generally a good idea to minimize "upward funargs" to use some legacy vernacular
21:17bbloomdnolen: when you register for a callback, you're effectively throwing a closure up to the infinity point of the stack: the event loop
21:17dnolenbbloom: yes
21:17bbloomdnolen: the lower down the stack your event loops & the less closed over context, the easier they are to reason about
21:18bbloomdnolen: another example: higher order functions are easier to reason about than function factories
21:18bbloomdnolen: 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:19bbloomdnolen: but once you close over *state* then you've got a compounded problem
21:25dnolenbbloom: I think the problem with that Twitter discussion is thinking that with CSP you even need a Stream abstraction
21:25dnolenbbloom: agreed on your other points
21:27bbloomdnolen: Add to the infinite queue of projects: IStream that wraps core.async w/ good interop w/ seqs & channels
21:27bbloomdnolen: not that i think it's a good idea
21:27dnolenbbloom: but what would IStream consist of?
21:27bbloomdnolen: basically Rx :-P
21:27dnolenbbloom: I think the the fact that Node.js has the notion of pause/resume troublesome.
21:27bbloomdnolen: 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:29dnolenbbloom: agreed, though of course many cases where you have no choice - those are the cases you want to account for.
21:31bbloomdnolen: yeah, i guess my view is now as follows:
21:32bbloomdnolen: i can get by with like 1 or a very small number of atoms/refs/etc
21:32bbloomdnolen: so i can probably get by with a very small number of async constructs
21:32bbloomdnolen: well, "devices" is probably a better word, to use the zmq terminology
21:32bbloomsome bits of code literally need ONE atom
21:33bbloombut 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:33bbloomsimilarly, i suspect the same would be true of async code
21:33sdegutisTEttinger: http://mikeash.com/getting_answers.html is the best one I've found
21:33bbloomdnolen: for example, i might have a server loop & a client loop
21:33bbloomdnolen: or maybe the server also has worker loops
21:33bbloomdnolen: while the running app may have 50+ goroutines, there really are only 3 devices: server, worker, client
21:34bbloomdnolen: 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:36seancorfieldooh! *claps hands* core.async talk!
21:37seancorfieldi just posted to clojure-dev asking about stability and the proximity of an 0.1.0 release on maven central
21:37seancorfieldheck, even an 0.1.0-alpha1 on maven central would make me happy :)
21:38bja+1 to that
21:38bjaalso, is there a public CI for this?
21:38bjaI set one up local to my company as we began experimenting with core.async and wanted to stay abreast of changes
21:39seancorfieldbuild.clojure.org
21:39seancorfieldhttp://build.clojure.org/job/core.async-test-matrix/ specifically
21:39seancorfieldall 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:54sdegutis_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:54sdegutis_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:54sdegutis_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:54sdegutis_\cc callen
21:55muhoosdegutis_: 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:56brehaut"a total black-hole of dumbass" love it
21:56muhoonow 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:57muhoosometimes it just takes doing a few large-ish projects to find the horizon.
21:59seancorfieldI'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:01ddellacostasdegutis_: I talked to you a lot yesterday and generally felt like you were being a pretty good IRC citizen.
22:01sdegutis_ddellacosta: Nah, I asked a few too many questions yesterday, and way too many today.
22:02ddellacostasdegutis_: 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:02ddellacostasdegutis_: okay. Well, I'm not going to question your own feelings on the thing, but just giving you my subjective impression.
22:02sdegutis_:)
22:02seancorfieldSome channels are a lot more tolerant of "noise" than others, as well.
22:02sdegutis_Part of the charm of #clojure is that the maturity level is (generally) extremely high, which means a really high signal/noise ratio.
22:03seancorfieldindeed.
22:03ddellacostaSeanCorfield: 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:03TimMcsdegutis_: And to the extent that you were exhibiting *any* bad behavior (very little!), callen was being a dick about it.
22:03ddellacostas/sound/signal/
22:04sdegutis_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:04ddellacostacallen can be a tough customer and prickly but generally he means well, in my experience.
22:04TimMcThere's a 40% chance I would have banned callen by now if I were the channel founder.
22:05TimMcSmart guy, has good experience... but pretty rude.
22:05ddellacostaTimMc: 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:06ddellacostaTimMc: yeah. I mean, again just expressing my subjective experience. I know everyone interacts with him differently.
22:06TimMcOh, and I'm not talking about a permaban, just a 5 minute kickban.
22:06sdegutis_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:08ddellacostasdegutis_: 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:08ddellacostasdegutis_: sorry, you asked for references
22:08technomancyusually if there is reflection in a tight loop, it will overshadow any other potential causes of slowdowns
22:08sdegutis_technomancy: good to know
22:09ddellacostagreat link btw
22:09ddellacostamikera knows his shit...
22:09technomancyespecially dispatch; you can optimize dispatch all day and you won't notice if there's a reflective call
22:10sdegutis_technomancy: hmm..
22:10technomancysdegutis_: `lein check` will show all reflective points
22:11sdegutis_technomancy: what do you mean by dispatch?
22:11sdegutis_technomancy: *whoa*, cool
22:11technomancysdegutis_: like replacing multimethods with protocols
22:11sdegutis_ahh
22:11technomancybut `lein check` will include ones that aren't in tight loops, so pay attention
22:11sdegutis_right :)
22:12sdegutis_Yeah I read recently that multimethods were deprecated in favor of protocols.. Not sure if that's legit though, gotta research more.
22:12ambrosebs_sdegutis_: on HN?
22:12technomancytotally BS
22:13technomancymultimethods are much more powerful
22:13sdegutis_ambrosebs_: don't think so..
22:13brehautstructs were deprecated in favour of records, but thats the only related deprecation
22:14ambrosebs_sdegutis_: I remember a comment on a very popular Clojure post. That guy was full of it.
22:14ambrosebs_nvm
22:14sdegutis_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:14sdegutis_I misinterpreted what he said.
22:16technomancystill pretty suspect
22:17cjfrisz_Oh man..I missed the conversation about being able to ask newb questions
22:18cjfrisz_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:19seancorfieldgreat documentation? where?
22:19ambrosebs_haha
22:20seancorfieldmmm, 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:21mlb-What's the commonly refered name of the "->" macro?
22:21seancorfieldthread
22:21seancorfieldthread-first for -> and thread-last for ->>
22:21cjfrisz_mlb-: also known as one of my least favorite parts of Clojure
22:21seancorfield(i believe)
22:21seancorfieldcjfrisz_: you no like? nor as-> / some-> / cond-> i guess? :(
22:22S11001001seancorfield: we always called it arrow
22:22mlb-cjfrisz_: easily abused?
22:22S11001001hence rplevy's "swiss-arrows" name for his lib
22:22cjfrisz_seancorfield: I actually really like as->
22:22cjfrisz_Haven't messed with the others yet
22:23cjfrisz_mlb-: I find that they make code unreadable for non-trivial uses
22:23sdegutis_cjfrisz_: but as-> only makes sense inside -> or ->>
22:23ddellacostaSeanCorfield: 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:23cjfrisz_sdegutis_: I disagree
22:23sdegutis_cjfrisz_: and I have to disagree, -> and ->> make code way more readable in my experience
22:23seancorfieldddellacosta: leiningen scowls on having release builds depending on snapshots :)
22:23cjfrisz_sdegutis_: I find that depends on prior experience reading inside-out Lisp code?
22:23cjfrisz_Er…not ?
22:24seancorfieldddellacosta: and this is production code, after all so i'm wondering how stable core.async really is...
22:24cjfrisz_sdegutis_: Also, I find as-> as a _replacement_ for -> in many places
22:24ddellacostaSeanCorfield: ah. I always rename things and install via uberjar, maybe it's bad form. ;-)
22:24ddellacostaSeanCorfield: 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:25sdegutis_cjfrisz_: here's one use of -> I like https://www.refheap.com/16959
22:25cjfrisz_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:25sdegutis_cjfrisz_: that sounds highly suspect to me
22:25seancorfieldddellacosta: i asked on clojure-dev for guidance but may go ahead and integrate my p.o.c. and just hammer it under test...
22:25TimMcmlb-: I prefer "stitch-first" and "stitch-last" to avoid confusion with concurrency topics. :-)
22:25bjaddellacosta: 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:26ddellacostaSeanCorfield: yes, would definitely be interested to hear more what your experiences are like.
22:26sdegutis_"The friend of my friend is my enemy"
22:26ddellacostabja: glad to hear it. No big issues so far?
22:26bjaddellacosta: plans on releasing to paying customers in a private beta in about a month
22:26bjanope
22:26bjawe have nothing to compare it to though
22:26ddellacostabja: that's part of the problem, haha
22:26bjabut we were doing stress testing to make sure it's capable of handling the load we want to throw at it
22:26cjfrisz_sdegutis_: I really find it comes down to personal taste
22:27ddellacostabja: 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:27seancorfieldit'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:27sdegutis_cjfrisz_: let's agree to disagree about that
22:27ddellacostaSeanCorfield: yah, good point
22:27cjfrisz_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:27cjfrisz_And I was already predisposed against it, so that completely soured me on it
22:28seancorfieldbja: your experience sounds encouraging ... thank you!
22:28ddellacostaditto
22:28bjaddellacosta: 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:28sdegutis_cjfrisz_: ->> is almost mandatory for clean code when doing a bunch of map/filter/etc in a row
22:28bjathen 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:29bjaalthough it does remind me a Qt app I wrote once
22:30cjfrisz_sdegutis_: I see your point, though I'd likely break up that computation rather than use ->> (again, personal taste
22:30ddellacostabja: 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:30ddellacostareally addressing the stuff regarding DOM updates, so still trying to figure that part out.
22:30cjfrisz_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:30sdegutis_cjfrisz_: can you show me an example of it broken up like you say? Maybe I just haven't seen it done right.
22:30ddellacostabja: this was an interesting, useful article I thought: http://keminglabs.com/blog/cljs-app-designs/
22:30callenseanaway: are you at the meetup?
22:30callenTimMc: <3 you too.
22:31seanawaycallen: no, couldn't make it this month, nor next, so Amit is running the SF group for a while
22:31ddellacostabja: but anyways, always interested to hear more about what people's experiences have been with CLJS, especially with core.async
22:31bjain 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:31callenseanaway: cool, well hopefully I'll catch you sometime in the near future, would love to talk about c.j.j for a bit.
22:31seanawayddellacosta: we're consider cljs + angularjs based on some of the stuff kevin lynagh posted about the kerning labs app etc
22:32ddellacostadamn, maybe I should move to a city/country with a Clojure meetup…or I guess start one here
22:32callenseanaway: keming labs ain't it? or is that the joke?
22:32ddellacostaseanaway: 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:32TimMccallen: I wouldn't *like* to do it. :-(
22:33seanawaycallen: 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:33callenddellacosta: I'm fond of Angular, but you have to be okay with the design philosophically speaking.
22:33callenseanaway: fair enough, thanks :)
22:33callenTimMc: awww. thank you. :)
22:33ddellacostacallen: yeah, I should write a few simple apps with it to get a feel before I judge it
22:33seanawayoh year, keminglabs.com ... always read that as k-e-r-n-ing... silly me!
22:34TimMcseanaway: Every. Single. Time.
22:34ddellacostaddellacosta: mostly I'm not excited about integrating an outside JS lib, but that's probably irrational
22:34seanawayhttp://keminglabs.com/blog/
22:34ddellacostawhoops, addressed me
22:34ddellacostawas to callen
22:34cjfrisz_sdegutis_: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62
22:34callenddellacosta: 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:35ddellacostacallen: interesting. I'll give it a shot and see what I learn.
22:35callenddellacosta: 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:35sdegutis_cjfrisz_: why do you prefer the last one? because it has all 3 args in it at once?
22:35ddellacostacallen: yeah, we have a…semi-SPA, so it may be appropriate, we'll see.
22:35cjfrisz_sdegutis_: I didn't repl-check that code, so it might have typos in it
22:35sdegutis_cjfrisz_: I mean, because each fn (map/reduce) have all args and no magic?
22:35cjfrisz_sdegutis_: precisely
22:36sdegutis_cjfrisz_: hmm, that is kind of neat
22:36ddellacostacallen: 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:36ddellacostamakes me cry
22:36callenddellacosta: yikes.
22:36sdegutis_It certainly eliminates the need for as-> within it for when the arg isn't in the position you wnat
22:36ddellacostacallen: yeah, I do a lot of sticking fingers in leaking holes
22:37ddellacostacallen: meh, it did what it needed to do for a while though, and it'll get better.
22:37sdegutis_cjfrisz_: btw I made a slight adjustment to how I'd do the ->> version: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62#comment-901309
22:38cjfrisz_sdegutis_: Ah, that does make it a little better
22:39cjfrisz_sdegutis_: There's still something that bothers me about implicitly keeping track of where the invisible value gets inserted
22:39sdegutis_cjfrisz_: I can see that. I'm not sure where I stand on the issue now that you gave this example.
22:39sdegutis_cjfrisz_: thanks
22:39cjfrisz_sdegutis_: no problem :-)
22:40bbloomcjfrisz_: gotta embrace the threading macros :-)
22:40cjfrisz_bbloom: nooooooooo :-O
22:40bbloomcjfrisz_: they make pipelines incredibly clear
22:40sdegutis_I'll defer my opinion on it: (def my-opinion (future (defer-opinion gfredericks)))
22:40bbloomcjfrisz_: also make it super nice to skip or insert steps when debugging
22:41cjfrisz_If those pipelines are all (rator rand) then I'm totally cool with it
22:41bbloomcjfrisz_: for example try throwing (doto prn) into a -> pipeline
22:41bbloomglorious.
22:41sdegutis_bbloom: have you seen his example?
22:41sdegutis_bbloom: https://gist.github.com/cjfrisz/7f3e118098bb7a472e62#file-gistfile1-clj
22:41bbloomsdegutis_: what about it?
22:41sdegutis_bbloom: as-> looks compelling in it
22:42bbloomsdegutis_: *shrug* not if they are all thread-last
22:42sdegutis_no implicitness about arg positions, it's all on screen
22:42bbloomsdegutis_: there is no implicitness with -> and ->>, it's right there lexically explicit :-)
22:43bbloombut i'm the guy who wrote a concatenative DSL, so my opinion might not count here :-P
22:43bbloomswap, dip, keep, drop, bi, cleave, etc -- now *that's* implicit :-)
22:43sdegutis_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:44sdegutis_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:44bbloombasically 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:45bbloomand ->> 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:45bbloomnevermind that you could also apply + and reduce * 1 ;-)
22:46cjfrisz_bbloom: thanks for simplifying my highly contrived example ;-)
22:47sinistersnarei always have trouble understanding ->
22:47sinistersnarei get its threading, but being a clojure (/lisp) newbie, its still hard to fathom
22:47callensinistersnare: ,,,
22:47bbloomsinistersnare: that's why i draw the parallel between -> and dotted access chains
22:47nightflysinistersnare: Look at how the macro is expanded a few times.
22:47callensinistersnare: http://blog.fogus.me/2013/09/04/a-ha-ha-ha-aah/
22:47TimMcYeah, ,,, is a good crutch.
22:48bjasinistersnare: clojure.walk/macroexpand-all is your friend
22:48callenbja: just let the ,,, magic happen.
22:48bbloombja: except when it lies to you :-P
22:48bjabbloom: macroexpand lies to you? I feel like I'm getting lied to and I don't know it
22:48gfrederickswhat is this ,,, nonsense?
22:49coventrybja, bbloom: riddley.walk/macroexpand-all tries to do a more accurate job.
22:49gfredericksis this what fogus was tooting about?
22:49coventryIf you're going to use ,,, why not use as->?
22:49sinistersnareoh cool
22:49gfredericksoh it's sticking a comma in the threading position for reference? or three commas?
22:49callengfredericks: yeah
22:49bbloomthe 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:50callengfredericks: yeah to both questions.
22:50callenanother way to learn how -> and ->> work is to reinvent them.
22:50gfredericksoh look he has a blag
22:50callenI don't think they merit much pondering though.
22:52dobry-denhaha, i just read about ,,, on http://rubylearning.com/blog/2010/07/26/clojure-tips-from-the-experts/
22:53cjfrisz_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:54bbloomcjfrisz_: but less paren counting :-)
22:54dobry-denor when ->> works for all argument order except for one function
22:54bbloomcjfrisz_: they can dramatically reduce stacked up close parens
22:55cjfrisz_bbloom: Look, I've written a *lot* of Scheme in my time; I'm so friggin fast at counting those parens :-p
22:55Foxboroncjfrisz_: i think having a imperative background helps you a lot reading ->> and ->
22:55cjfrisz_I think it also relates to why I don't like let* in general in Scheme
22:55bbloomcjfrisz_: it's interesting. i love the prefix notation & much prefer the explicitness of parens, but if i see like ))))) i suddenly cringe & refactor
22:55Foxboronmy only problem is trying to recall which one does what
22:56bbloomcjfrisz_: a few extra names here or there can dramatically reduce stacked up parens & make code much easier to read
22:56sdegutis_technomancy: wow thanks for the tip for lein check, this is super helpful
22:56cjfrisz_That's why I'm currently a fan of as->
22:56cjfrisz_It takes care of most of that bit of mental parsing by naming the bit that's getting threaded through
22:57bbloomcjfrisz_: but when i see as-> i say "oh no, i have to be on the look out for non-standard argument positions"
22:57bbloomcjfrisz_: it's like when people stick fucking ! on everything
22:57sinistersnare,(doc as->)
22:57clojurebot"([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:58cjfrisz_bbloom: It's not really any worse than a let-bound variable
22:58bbloomcjfrisz_: right, but it's also no better ;-)
22:58bbloomcjfrisz_: as-> is strictly less clear than let, unless you're mixing it in to an existing -> and ->>
22:58bbloomso far, i've needed as-> like twice ever
22:59cjfrisz_bbloom: That's probably because you're more willing to use -> or ->> than me
22:59cjfrisz_I totally use as-> in places where other people would use -> or ->>
23:00bbloomcjfrisz_: but in your "best, in my opinion" example. why not just use let?
23:00bbloomhttps://gist.github.com/cjfrisz/7f3e118098bb7a472e62 <- i added a comment
23:01bbloomoh dur, i'm an idiot
23:01cjfrisz_bbloom There's something uneven looking about those kinds of lets
23:01bbloomwait, i don't even know how as-> works
23:01cjfrisz_bbloom: Again, why I'm always cranky that Clojure only has let* semantics for let
23:01bbloom(doc as->)
23:01clojurebot"([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:01bbloomso does num-vec change it's binding every time?
23:01bbloomi've never used an as-> bound name more than once
23:01bbloomare those 3 different values for num-vec ?
23:02bbloomi *never* override names unless it's a loop or something really obvious
23:02bbloomi'd rather have num-vec and num-vec* and num-vec** or some more descriptive names
23:02bbloomcjfrisz_: as for parallel let, that's b/c clojure discourages you from having cyclic structures, which is actually a really good thing
23:02bbloomcjfrisz_: if you're gonna have immutable data, then a cycle KILLS your potential for structural sharing
23:03bbloomcjfrisz_: you can't copy *part* of a cyclic structure
23:03bbloomcjfrisz_: you need an indiction, which is what "identities" give you (ie IDeref)
23:03bbloomcjfrisz_: s/indiction/indirection/
23:04bbloomcjfrisz_: 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:04cjfrisz_bbloom: In all the times that I've complained about let, nobody has ever made that argument
23:04cjfrisz_I'ma need to let that one soak in for a minute
23:04bbloompointers are like having only one concrete implementation of IDeref
23:04bbloomwhere you can't ever change the value it points to
23:05bblooma pointer is the least useful type of identity there is
23:05bbloomthere can be no sensible succession of values
23:05bbloomthat's why there is letfn: you can't edit a function anyway, so there is no sense having structural sharing
23:05bbloombut if there was, you'd just inline one mutually recursive function in to the other
23:06cjfrisz_bbloom: I'm really not sure if I'm misunderstanding you or you me
23:06bbloomcjfrisz_: you're talking about sequential vs parallel let, right?
23:06bbloomcjfrisz_: scheme & common lisp have let and let*
23:06bbloomlet is parallel, let* is sequential
23:06cjfrisz_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:06bbloomclojure has let and letfn
23:06bbloomlet is sequential, letfn is parallel
23:07cjfrisz_bbloom: right
23:07bbloomparallel bindings enable cyclic structures
23:08bbloomcyclic structures are an anti-feature for most use cases, in my opinion
23:08sdegutis_amalloy_: does being so prolific on stackoverflow get many contracting gigs knocking on your door?
23:08cjfrisz_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:08cjfrisz_letrec, yes
23:09bbloomcjfrisz_: 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:11gfredericksI just tried scheme
23:11gfrederickslet is parallel in the sense of none of them are visible to the others
23:11cjfrisz_bbloom: Scheme/CL -- (let* ([a 1] [b a] [c b]) c) === (let ([a 1]) (let ([b a]) (let ([c b]) c)))
23:12bbloomok so i had forgotten about letrec
23:12cjfrisz_let* in Scheme is always a really simpl
23:12bbloomwhat's the use of parallel let without letrec ?
23:12cjfrisz_Er…didn't mean to send that
23:12bbloomcjfrisz_: i get the usefulness of let* and letrec, but what's the use of let?
23:13cjfrisz_bbloom: Makes lexical scope clearer and discourages imperative programming
23:13bbloomcjfrisz_: in what way does it do either of those things?
23:13gfredericks(letrec ((x (cons 3 '())) (y (cons 4 x))) y) ;; => (4 . #!unbound)
23:14cjfrisz_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:14sdegutis_you guys are such nerds
23:14sdegutis_so awesome :)
23:14cjfrisz_sdegutis_: :-D
23:15callencjfrisz_: I have sequential bindings so often that I like sequential let being the default.
23:15gfredericksmaybe that's the imperative programming he was referring to?
23:15cjfrisz_^^^
23:16cjfrisz_There's certainly nothing wrong with it
23:16bbloomcjfrisz_: *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:16cjfrisz_The downside the parallel let is that it tends to make your code indent further
23:16amalloysdegutis_: i don't do contracting; being prolific on SO and IRC is what got me my current job
23:17sdegutis_amalloy: ok
23:17cjfrisz_But preferring parallel let does make it obvious that any variable is bound in a strictly enclosing scope
23:17bbloomcjfrisz_: hold on. gotta kill a giant fucking bug
23:17gfredericksman bbloom gets passionate about debugging
23:18bbloomcjfrisz_: no like one with legs....
23:18cjfrisz_gfredericks: I think bbloom is just into really, *really* traditional debugging
23:18bbloomer i mean cjfrisz_
23:18gfredericksman bbloom really does not want to say my name
23:19gfrederickscjfrisz_: that's interesting about the scoping
23:21bbloomLOL
23:21bbloomgfredericks: sorry man
23:21cjfrisz_gfredericks: it's nice
23:21bbloomgfredericks: total brain fart b/c i had to kill that ugly mother fucker
23:21bbloomgfredericks: no idea what that thing was, it had like a ton of legs & didn't look friendly
23:22bbloomcjfrisz_: but w/ parallel let, that scope is *further down* under the other bindings
23:22bbloomcjfrisz_: w/ sequential let, it's the very next line. close locality
23:22cjfrisz_bbloom: but then you don't have indentation as a visual cue
23:22bbloomcjfrisz_: yeah, it's a larger extent than w/ parallel let, but i don't think it's a big deal
23:23cjfrisz_bbloom: Agreed. I'm just an old PL curmudgeon and don't like things that are different than what I'm used to
23:24bbloomcjfrisz_: *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:26bbloomcjfrisz_: 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:26bbloomcjfrisz_: if your answer is "functional is good" then you lose :-)
23:27bbloomcjfrisz_: 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:27bbloomcjfrisz_: turns out that immutablity is 100X more important than not sequentially refining values
23:27cjfrisz_bbloom: I don't dispute that
23:28cjfrisz_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:28cjfrisz_If it bugged me that much I would probably have a far lower volume of Clojure code
23:28cjfrisz_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:28bbloomfair enough :-)
23:29bbloombut the letrec thing is a big deal ;-)
23:29bbloomcyclic structures without explicit identities == nightmare
23:29bbloombrb
23:30cjfrisz_bbloom: Agreed
23:30cjfrisz_bbloom: Hence why there had to be a series of papers called "Fixing Letrec"
23:30cjfrisz_It turns out that pretty much all of them do it wrong
23:31cjfrisz_I do have to say that it's really, really smart that Rich decided not to add letrec to Clojure
23:35sdegutis_I find myself day after day saying "wow, Rich (and the team?) made a great decision [including/excluding] [that/that] feature".
23:35cjfrisz_sdegutis_: agreed
23:36shaungilchristit is definitely what keeps me happy with clojure
23:36unlinkWhen I run `lein ring server', it thinks for a second, and then exits with error code 0, printing nothing.
23:36cjfrisz_Overall, Clojure is a really well-designed language
23:36sdegutis_unlink: does your project.clj point to a legit handler?
23:36unlinksdegutis_: yes.
23:36cjfrisz_Most of my qualms are nit-picky, and the things that bother me the most are because of the JVM
23:37unlinklein ring war works.
23:37cjfrisz_But the benefits of the JVM are also really nice
23:37sdegutis_Yeah, I do enjoy that my code is much faster than Ruby.
23:38cjfrisz_sdegutis_: I lolled
23:39bbloomcjfrisz_: i'm not familiar with the fixing letrec series. what's the gist?
23:39shaungilchristIt definitely helps to be able to show the viability of jvm interop when a potential client winces when you say "lisp"
23:39sdegutis_shaungilchrist: oh man, you get clients?
23:40shaungilchristjust build things people want and it happens
23:40unlinkhah
23:40gwsyou 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:40sdegutis_shaungilchrist: but I have.. https://github.com/sdegutis/zephyros
23:41sdegutis_gws: that seems downright immoral
23:41cjfrisz_bbloom: That dealing with undefined values is really hard when you allow for arbitrary cyclic expressions
23:41cjfrisz_bbloom: It gets even worse when you have first-class continuations in the mix
23:41gwssdegutis_: i agree, but somebody said it was "good business sense" and i just believed them
23:41sdegutis_:)
23:41sdegutis_oh man, just one more star
23:43bbloomcjfrisz_: yeah, i'm 100% against cyclic pointer structures, as you can tell
23:43cjfrisz_bbloom: Me too
23:43cjfrisz_I honestly don't remember the last time I used a letrec
23:44bbloomcjfrisz_: 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:45cjfrisz_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:46cjfrisz_bbloom: Dybvig has also told me that he would prefer prompt/k over call/cc
23:46bbloomcjfrisz_: turns out that there are 4 versions, but i think one is clearly a dumb idea :-P
23:46cjfrisz_bbloom: remembering that there were 3 was a guess, too
23:47cjfrisz_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:47bbloomcjfrisz_: anyway, the low-level encoding that seems to be preferred is newPrompt, pushPrompt, withSubCont, pushSubCont
23:47cjfrisz_And apparently possibly another that's super dumb
23:48bbloomcjfrisz_: basically, gensym, mark stack, capture range of stack, install range of stack
23:48cjfrisz_bbloom Right, and those four can be used to implement any of the models
23:48sinistersnarerandom question: has it ever been thought to make asm.js a viable backend for clojurescript compilation?
23:49cjfrisz_Did you pick that up from Dybvig, Sabry, & Oleg's Monadic Framework for Delimited Continuations?
23:49sinistersnarei get that asm.js is more of a static language, maybe we should enforce typed-clojure on it then :p
23:49bbloomcjfrisz_: 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:49sinistersnarei mean core.typed*
23:49unlinkI 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:49bbloomcjfrisz_: that's where i grabbed it from just now, but it is also in the ocaml & haskell demo implementations
23:49bbloomcjfrisz_: similar names, same functions
23:50cjfrisz_bbloom: I need to reread that; I don't think I was careful enough the first time or actually understood what I read
23:50cjfrisz_bbloom: and it's been about a year and a half, I think?
23:51cjfrisz_bbloom: Dybvig grilled me on it at my Cisco interview for kicks
23:51bbloomcjfrisz_: it's probably the most enlightening paper on delimited continuations, even though i find talk of monads to be generally gobblty gook
23:51cjfrisz_bbloom: agreed on that last bit :-)
23:52bbloomcjfrisz_: but what made it all FINALLY click for me was this paper: http://arxiv.org/abs/1203.1539
23:52cjfrisz_bbloom: And earmarked for later
23:55bbloomcjfrisz_: 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:55bbloomcjfrisz_: 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:56cjfrisz_bbloom: That is a cool idea
23:57bbloomcjfrisz_: yeah, see this one too for a haskell version: http://www.reddit.com/r/haskell/comments/1j9n5y/extensible_effects_an_alternative_to_monad/
23:58cjfrisz_bbloom: I've been meaning to read that; one of my friends is the third author
23:58cjfrisz_But I didn't know he could do any Haskell
23:59bbloomcjfrisz_: 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