2013-11-11
| 00:10 | arrdem | TimMc: trash-cli is quite nice... thanks! |
| 00:19 | `cbp | bitemyapp: give me your steam id sometime ;) |
| 00:20 | arrdem | `cbp: starcrafts? |
| 00:20 | `cbp | arrdem: only broodwar |
| 00:27 | arrdem | `cbp: aw.. bitemyapp and I've been playing when I have access to an sc2 capable box. |
| 00:27 | bitemyapp | my main games lately have been starcraft 2 and LoL. I'll play DotA2 if somebody invites me. |
| 00:28 | `cbp | arrdem: maybe ill get it once i remember my damn blizzard password :P |
| 00:29 | bitemyapp | arrdem: DotA2 is available for Linux. |
| 00:29 | bitemyapp | arrdem: if you played that, you wouldn't need the other boxen. |
| 00:29 | bitemyapp | arrdem: why not install Steam and see how it goes? |
| 00:29 | arrdem | M-x pacman -S steam |
| 00:34 | arrdem | oh right. now I remember why I didn't have steam on linux.... |
| 00:34 | bitemyapp | arrdem: ? |
| 00:34 | arrdem | there's a Kerbal Space Program build for linux. |
| 00:35 | bitemyapp | arrdem: well install steam, I'm really curious if DotA2 works. |
| 00:35 | arrdem | bitemyapp: installed and installing.. |
| 00:35 | bitemyapp | I like DotA2 quite a bit, better than LoL in most respects and would like to play it if possible. |
| 00:37 | arrdem | I know a bunch of people who favor d2 over LoL I've just never gotten into d2 |
| 00:37 | technomancy | kerbal sounds nuts (in a good way) |
| 00:37 | bitemyapp | arrdem: it's like any other MOBA. It's somewhere in between HoN and LoL in design principle. |
| 00:38 | bitemyapp | the pacing and design of DotA2 is a lot better though. Much more balanced and interesting game. |
| 00:38 | `cbp | dota2 works kinda crappily on my macbook air |
| 00:38 | `cbp | not like its a machine meant for gaming |
| 00:38 | `cbp | not that* |
| 00:38 | bitemyapp | :( |
| 00:38 | `cbp | (i play on a pc though) |
| 00:39 | bitemyapp | I keep thinking about getting a gaming PC so that I don't have to play on a mac. |
| 00:39 | `cbp | it should be pretty affordabe to build one :P |
| 00:39 | arrdem | bitemyapp: if you do don't just build a gaming box. build a multihead dev box with enough power to play games. |
| 00:40 | bitemyapp | arrdem: I have a Thinkpad for work, what specifically are you angling for with your recommendation? |
| 00:42 | arrdem | bitemyapp: I got a 3x 23" monitor desktop with more than reasonable specs out of a research position freshman year |
| 00:42 | bitemyapp | I don't want a ton of hardware. |
| 00:42 | bitemyapp | just a machine that can game. |
| 00:42 | arrdem | shrug. I don't mind the metal, and I don't know enough about portable gaming boxes to comment. |
| 00:43 | technomancy | any machine can game; you just have to pick the games right |
| 00:43 | arrdem | my perception is that there's a significant price and power primium, but I know some people who are happy with theirs. |
| 00:44 | arrdem | technomancy: that's more of an operating system than a game... |
| 00:44 | technomancy | don't get me started on nethack |
| 00:46 | arrdem | bitemyapp: it's gonna take a bit to get dota2 downloaded.. I'll let you know what happens tomorrow. |
| 00:47 | bitemyapp | arrdem: okiedokie. |
| 00:48 | swarthy | nethack the Roguelike? I really enjoy Roguelikes but I haven't played nethack. I loved Brogue, I have a hope to one day code a squad based ala Dungeon Siege style rogue-like. |
| 00:49 | bitemyapp | swarthy: have you played dungeon crawl stone soup? |
| 00:49 | swarthy | bitemyapp: I have that one was fun as well, I need to fire that one up again soon. |
| 00:50 | bitemyapp | I like roguelikes a lot partly because of the ephemerality |
| 00:50 | bitemyapp | I was really pleased to see the indie game scene learn from the genre and incorporate it into new ideas. |
| 00:50 | bitemyapp | I really like 2d games too. |
| 00:51 | swarthy | Yeah, making a word out of ascii or bland tilesets is amazing fun. |
| 00:51 | swarthy | I played d&d for the first time the other day and realized how advanced modern gaming is. The average gamer copes with a ton of systems. |
| 00:51 | swarthy | Other than making up and 'playing a role' d&d was so simple. |
| 00:51 | bitemyapp | I like 2d pixel based graphics too. |
| 00:52 | swarthy | Bastion is really cool. 3d but locked into isometric. |
| 00:52 | swarthy | So it has this cool 2d feel. |
| 00:54 | bitemyapp | I really liked that. |
| 00:55 | john2x | ooh roguelikes. I love Brogue. It's so pretty, considering it's ASCII "graphics" |
| 00:55 | justin_smith | nethack is my jam |
| 00:56 | justin_smith | I want to port nethack.el to clojure |
| 00:56 | justin_smith | make clojure nethack bots |
| 00:56 | swarthy | yeah Brogue did look really good. I'm eager to play the new Dwarf Fortress style game from the makes of Dungeons of Dredmor when it comes out. |
| 00:57 | swarthy | makers* |
| 00:58 | bitemyapp | swarthy: oh damn, I really liked Dredmor, what game is that? |
| 01:00 | bitemyapp | ohhh clockwork empires. |
| 01:00 | bitemyapp | yeah that's been long coming |
| 01:00 | justin_smith | one of these weekends I will play amnesia: a machine for pigs some more |
| 01:00 | justin_smith | works great on my linux system |
| 01:01 | justin_smith | (no wine, native support) |
| 01:01 | bitemyapp | justin_smith: yeah, indie folk are pretty good about mac and linux support. |
| 01:01 | swarthy | I have played games most of my life, and I've recently killed all my old Windows for Gaming Only harddrives. I thought I would rarely play games now. Turns out the Linux story for games is really good now. So that didn't curb my addiction at all. |
| 01:02 | bitemyapp | that's partly why I'm struggling with whether or not I want a dedicated gaming machine. |
| 01:02 | bitemyapp | I would consider outsourcing that to consoles, if consoles had the kind of games I like. |
| 01:02 | arrdem | bitemyapp: wait 12 months see what happens with steambox, re-evaluate. |
| 01:03 | justin_smith | I used to have a really good rhythm, where I would play some nethack, and when I started doing real good I knew my wits were sharp, so I would do some coding, then I would get stumped and play some more nethack |
| 01:03 | bitemyapp | arrdem: that was one option I was considering. |
| 01:03 | justin_smith | but people at work would think I was just slacking |
| 01:03 | bitemyapp | justin_smith: that's a good idea. |
| 01:03 | bitemyapp | justin_smith: I usually take a walk or make tea to accomplish the same thing. |
| 01:03 | justin_smith | heh, maybe healthier :) |
| 01:04 | bitemyapp | I suppose so. |
| 01:04 | bitemyapp | The real point is to empty my mind. |
| 01:04 | justin_smith | I keep my instrument by my desk, so I can stop and play if I am home |
| 01:04 | justin_smith | yeah |
| 01:04 | justin_smith | playing an instrument is good for that |
| 01:05 | swarthy | Yeah I built an HTPC but it turns out it was so cheap and so nice I could just put my gaming GFX card in it was a gaming pc. |
| 01:05 | swarthy | Technology is too good to get any real work done. |
| 01:05 | justin_smith | alter right next to me on the first level, first room |
| 01:05 | justin_smith | *altar |
| 01:06 | bitemyapp | arrdem: http://i.imgur.com/tOTISJF.jpg |
| 01:07 | arrdem | bitemyapp: nice |
| 01:15 | muhoo | wait, did thrown? get removed from the language since these docs? http://clojuredocs.org/clojure_core/clojure.test/is |
| 01:16 | muhoo | it isn't in clojure.test ns public vars AFAICT |
| 01:25 | coventry | muhoo: I've used thrown? relatively recently. It's a method of the assert-expr multimethod. |
| 01:33 | mindbender1 | Please can somebody delete the page at http://en.wikipedia.org/wiki/Communicating_sequential_processes? |
| 01:33 | justin_smith | why? |
| 01:33 | clojurebot | why is startup slow is busy compiling the `for` macroexpansion |
| 01:34 | mindbender1 | justin_smith: because of http://en.wikipedia.org/wiki/Communicating_sequential_processes#Examples |
| 01:35 | mindbender1 | How does that represent the objectives of CSP? |
| 01:35 | mindbender1 | Boring! |
| 01:36 | justin_smith | /ignore mindBender1 |
| 01:39 | bitemyapp | mindbender1: you just got plonked old school style son, you should consider that a Sign (TM) |
| 01:40 | justin_smith | bitemyapp: my classic newb mistake, typing a space before the / that made it a command |
| 01:40 | muhoo | coventry: CompilerException java.lang.RuntimeException: Unable to resolve symbol: thrown? in this context, compiling:(/tmp/form-init1896962088566288833.clj:1:771) |
| 01:42 | muhoo | maybe i don't understand multimethods then. i thought the symbol would resolve. pretty sure i've been able to (doc some-multimethod) before |
| 01:56 | arrdem | bitemyapp: dota2 is totally playable |
| 01:56 | arrdem | now bed |
| 01:57 | bitemyapp | arrdem: awesome, catch you later. |
| 02:18 | amalloy | muhoo: clojure.test/assert-expr is a multimethod that dispatches on first |
| 02:18 | amalloy | it has a defmethod for the symbol 'thrown? |
| 02:18 | amalloy | but there is no multimethod named thrown? anywhere |
| 03:26 | muhoo | oh! duh. then thrown? isn't a function, it's the firt arg to (is |
| 03:26 | muhoo | (is thrown? (expr....)) not (is (thrown? (expr....))) |
| 03:28 | amalloy | no, it's (is (thrown? ...)) |
| 03:28 | amalloy | but it's still not a function |
| 03:28 | muhoo | now i have to go look at the source of assert-expr |
| 03:29 | amalloy | 'is is a macro that uses the assert-expr multimethod to decide how to expand |
| 03:29 | amalloy | it passes assert-expr the first symbol in the list you're expanding |
| 03:30 | Jarda | hmm https://github.com/mylesmegyesi/metis seems great but does anyone know of a variant that could be used to export a 'sanitized' version of the passed data? |
| 03:32 | Jarda | I mean, if I hava data like {:my-number "123.4"} and I run it through a validator that :my-number actually is numeric and I would then get {:my-number 123.4} as output |
| 03:32 | Jarda | or do I have to bake it myself |
| 03:37 | muhoo | amalloy: thanks, just looked at it, saw where the dispatch is. neat. |
| 05:33 | sm0ke | i just copied my project to a new one a changed namespaces |
| 05:34 | sm0ke | now lein repl fails with Unable to resolve symbol create: is in this context |
| 05:34 | sm0ke | i doesnt give anything useful in stack trace |
| 05:35 | sm0ke | oh wow i misspelled a namespace |
| 05:46 | sm0ke | wtf is :ssl :yes!!!11} in |
| 05:46 | sm0ke | posta wiki |
| 05:46 | sm0ke | postal* |
| 05:46 | sm0ke | cant he just use a straight :yes! |
| 05:59 | CookedGryphon | sm0ke: you can just use true |
| 05:59 | CookedGryphon | that annoyed me too |
| 05:59 | CookedGryphon | i think it's just anything truthy |
| 06:01 | sm0ke | CookedGryphon: thanks i thought that so |
| 06:01 | sm0ke | funny that author would give such contrived example |
| 06:01 | CookedGryphon | send a pull request chganging the docs? It genuinely put me off using postal for a while |
| 06:02 | sm0ke | hehe yea i will do that |
| 06:02 | CookedGryphon | I only used it as a last resort, and functionally it's the best I've tried |
| 06:02 | sm0ke | CookedGryphon: do you seem to have used html formatting in your mails? |
| 06:02 | sm0ke | any easy way to do that? |
| 06:02 | CookedGryphon | yeah |
| 06:02 | sm0ke | tell me |
| 06:02 | CookedGryphon | one second, i'll find it |
| 06:04 | CookedGryphon | Instead of a plain text string, send it [:alternative {:type "text/plain" :content "blah"}{:type "text/html; charset=utf-8" :content (hiccup [:html [:body [:p "blah"]]])}] |
| 06:05 | CookedGryphon | that was probably too long to type inline, sorry, should have done a refheap |
| 06:05 | sm0ke | awesome sauce |
| 06:05 | sm0ke | i am copying that |
| 06:10 | sm0ke | CookedGryphon: just wondering whats that :alternative? |
| 06:10 | sm0ke | fallback from clients which dont have html |
| 06:10 | sm0ke | for* |
| 06:13 | CookedGryphon | I can't remember, I think so yes. It's in the README |
| 06:13 | CookedGryphon | you can do attachments, multipart and all sorts in that format |
| 06:13 | sm0ke | ok thanks |
| 07:00 | ambroseb_ | only 20 hours left in the Typed Clojure dev campaign. Don't miss out! ;) http://www.indiegogo.com/projects/typed-clojure |
| 07:01 | rstandy | hello Clojure community |
| 07:01 | ambroseb_ | rstandy: hello there |
| 07:01 | Jarda | ambroseb_: why should I care about typed clojure |
| 07:02 | rstandy | I'm sorry to ask a possible flame war starting question, but, what framework do people use in Clojure when developing webapps? |
| 07:02 | justin_smith | rstandy: not a flame-invoking question at all |
| 07:03 | rstandy | well, then this is a really neat community :-) |
| 07:03 | ambroseb_ | Jarda: it's AFAIK the only way to make strong static claims about Clojure code. |
| 07:03 | cark | rstandy: i only use ring, but it's not a full featured framework |
| 07:03 | justin_smith | liberator, pedastel, Luminous are popular |
| 07:04 | CookedGryphon | I tend to avoid frameworks and use the small libraries i need |
| 07:04 | justin_smith | there have been flames about the design of Noir in the past, but even the autor of noir depricated it :) |
| 07:04 | gwillickers | rstandy: i just started too, i went with compojure |
| 07:04 | ambroseb_ | Jarda: prevents you from misusing null, *really* helps using plain maps. |
| 07:04 | gwillickers | which sits atop ring |
| 07:04 | rstandy | justin_smith: thank, I've seen there are various frameworks, but being new to Clojure I would love to invest some time in the "right" one... |
| 07:04 | ambroseb_ | Jarda: and it's just a library, sprinkle it where you want. |
| 07:05 | cark | rstandy: most frameworks are based on ring, you c&n't go wrong by learning that |
| 07:05 | Jarda | I'm using compojure for routing, haven't felt the need for anything else than compojure+ring |
| 07:05 | rstandy | justin_smith: "the right one" being that which is popular enough to give me documentation, great community to ask, ecc. |
| 07:05 | CookedGryphon | thing is, if you just go with small libraries, building on top of ring and maybe compojure, anything else you use isn't a large investment |
| 07:05 | noidi | Jarda, +1 |
| 07:05 | CookedGryphon | you can swap out smaller components when a better library comes along |
| 07:05 | justin_smith | rstandy: I actually am a developer for a framework, that will likely be getting its official "public release" in a day or two, I could say more after that, don't want to overshare before the event |
| 07:05 | noidi | we've been happily using ring + compojure + stencil for templating |
| 07:06 | justin_smith | CookedGryphon: yeah, start with ring and compojure, most things should modularly combine with those |
| 07:06 | justin_smith | inc CookedGryphon |
| 07:06 | Jarda | I use hickup templates, haven't really looked into alternatives |
| 07:06 | justin_smith | (inc CookedGryphon) |
| 07:06 | lazybot | ⇒ 1 |
| 07:06 | justin_smith | there we go |
| 07:06 | rstandy | wow so many choices |
| 07:06 | gwillickers | i went hiccup too, no complaints |
| 07:06 | justin_smith | rstandy: they are made of modular parts, mostly |
| 07:06 | Jarda | anything that builds on top of ring is fine as long as they do not try to hide ring |
| 07:07 | justin_smith | yeah |
| 07:07 | rstandy | any commercial site I can see to have an idea of what I can accomplish with which framework? |
| 07:07 | justin_smith | it is not so much "frameworks" you get with clojure as 'sets of libs that work together' |
| 07:07 | cark | there are some frameworks |
| 07:07 | rstandy | justin_smith: right, I understand it's one of the objectives of Clojure too |
| 07:07 | cark | medestal maybe ? |
| 07:07 | rstandy | justin_smith: this is so good |
| 07:07 | cark | pedestal* |
| 07:08 | Jarda | in my philosophy: frameworks that try to do everything _always_ fail at doing every possible use case -> go with the one that helps but doesn't block you when you need to go low-level |
| 07:08 | justin_smith | the one my group is releasing in a day or two from now is a similar model to luminous - giving you a decent set of default libs as middleware, and leaving things modular |
| 07:08 | rstandy | Jarda: very true! I used Weblocks from CL, which is very nice, but forced me again to work its way |
| 07:09 | cark | ah there was hunchentoot in CL ... nothing else was need"ed, and so easy to use ! |
| 07:09 | justin_smith | pedastel is a more "total solution" top to bottom design (for better and/or worse) |
| 07:10 | CookedGryphon | a rule of thumb I have found from experience - avoid anything which requires you to use a defblah macro |
| 07:10 | rstandy | ok, so pedestal force you to model in its way |
| 07:10 | justin_smith | CookedGryphon: you are trying to get inced by me again aren't you? |
| 07:10 | CookedGryphon | usually means they are doing something unidiomatic which isn't going to compose or play nice with other things down the line |
| 07:10 | justin_smith | very good advice |
| 07:11 | CookedGryphon | :) |
| 07:11 | rstandy | looking for compojure |
| 07:11 | cark | i think the defXXXX thing isn't too bad as long as there is a functional interface as well |
| 07:13 | CookedGryphon | cark: yeah, and as long as it's not doing too much to obscure how it actually works underneath. I've never really liked the magic of compojure's defroutes, but it does make for a good quick-start guide |
| 07:13 | rstandy | so for example, if I need a webapp with session management and login/registration, what can I use to start very fast? |
| 07:13 | justin_smith | rstandy: there are ring middlewares for session and auth |
| 07:13 | justin_smith | friend is great for auth |
| 07:14 | justin_smith | I did a kind of roll-my-own but plan to upgrade to friend |
| 07:14 | justin_smith | ring-session for session management |
| 07:14 | rstandy | justin_smith: thanks! looking for friend right now |
| 07:14 | justin_smith | https://github.com/cemerick/friend |
| 07:14 | justin_smith | http://clojuredocs.org/ring/ring.middleware.session/wrap-session |
| 07:17 | rstandy | thank you very much guys, very helpful! |
| 07:18 | justin_smith | CookedGryphon: regarding def-foo ugliness, for the webapp template I've been working on, we ended up dropping compojure because it was so defroutes centric, and we wanted to manage the routes via the cms |
| 07:19 | justin_smith | so that a frontend guy who does no clojure could use the cms interface to define the page he needs |
| 07:19 | justin_smith | and it is messy integrating routes created as data in a db with a defroutes model |
| 07:20 | rstandy | looking for all of this libraries |
| 07:20 | justin_smith | rstandy: that is what lein templates are good for |
| 07:21 | justin_smith | it basically copy/pastes a sane default app setup, complete with requiring the right deps |
| 07:23 | justin_smith | https://clojars.org/search?q=lein-template |
| 07:24 | justin_smith | for anything that defines a foo/lein-template you should be able to run lein new foo |
| 07:26 | justin_smith | so from that list you have compojure-app, cljs-template, mies, noir, pedestal-service, luminus, each providing some kind of web service / web app functionality |
| 07:27 | justin_smith | sadly clojars has not been auto-indexing quite right, because I know of others that exist that are not on that results page |
| 07:37 | sm0ke | what a mess i am unable to send mails with postal |
| 07:37 | justin_smith | there is a good postmark lib for clojure |
| 07:37 | sm0ke | it says {:code 0, :error :SUCCESS, :message message sent} but i dont get no mail |
| 07:38 | CookedGryphon | odd, spam? |
| 07:38 | justin_smith | sm0ke: the reason people use postmark, is email providers use whitelists |
| 07:38 | CookedGryphon | what sort of account are you sending from sm0ke |
| 07:38 | sm0ke | nothing in spam too |
| 07:38 | justin_smith | roll your own email server is very hard because you need to get on whitelists and shit, easier to use a whitelisted service |
| 07:39 | CookedGryphon | depending on your use case though, you might want to just send from a gmail account (that's what i have been doing) |
| 07:39 | justin_smith | CookedGryphon: from the looks of it, postal is not imap or such, it is actual smtp, so it would not get far on the open net |
| 07:39 | sm0ke | CookedGryphon: yes me too |
| 07:39 | sm0ke | i am using a gmail accout |
| 07:39 | CookedGryphon | all the appropriate gmail options set? |
| 07:39 | sm0ke | why would postal be so cruel to give success message |
| 07:40 | CookedGryphon | it's not suspicious about the sending and asking for a captcha on the web interface is it? |
| 07:40 | sm0ke | CookedGryphon: i guess so .. everything he has in docs |
| 07:40 | CookedGryphon | i mean on the gmail site itself |
| 07:40 | CookedGryphon | imap and smtp aren't on by default |
| 07:40 | sm0ke | i am using smtp settings only |
| 07:40 | CookedGryphon | but presumably you wouldn't then get a success message |
| 07:40 | sm0ke | i only need to send |
| 07:41 | justin_smith | sm0ke: does mail within localhost work? |
| 07:41 | sm0ke | hmm i guess i need only sendmail installed on my machine right? |
| 07:41 | justin_smith | postal should be doing what sendmail does already |
| 07:42 | sm0ke | i think it uses a mail agent underneath |
| 07:42 | CookedGryphon | you don't need anything set up locally to send with a gmail account |
| 07:42 | justin_smith | CookedGryphon: the reason I suggested localhost testing, is that eliminates a bunch of weird variables |
| 07:43 | CookedGryphon | yeah, introduces a load more though to have a working local mailserver |
| 07:43 | sm0ke | hmm weird i jusr installed ssmtp and everything fails now |
| 07:43 | justin_smith | sm0ke: what os are you using? a normal linux os will set up local mail (for system messages to administrator) |
| 07:43 | sm0ke | i get {:code 1, :error nil, :message nil} |
| 07:43 | sm0ke | ubuntu 12.04 |
| 07:43 | justin_smith | yeah, ubuntu already has mail out of the box |
| 07:44 | sm0ke | eee |
| 07:44 | justin_smith | that is how root gets messages about system status stuff |
| 07:44 | justin_smith | with a normal install |
| 07:44 | justin_smith | err... maybe I was wrong |
| 07:45 | justin_smith | debian does this, but ubuntu may not |
| 07:45 | justin_smith | postfix sets it up though |
| 07:45 | sm0ke | i have postfix |
| 07:45 | sm0ke | ssmtp stopped it though |
| 07:45 | sm0ke | and now i get errors |
| 07:45 | sm0ke | rightfully* |
| 07:46 | CookedGryphon | sm0ke: so my settings for sending via gmail are (send-message {:username "...@gmail.com" :password "***" :host smtp.gmail.com :port 465 :ssl true} {:to "" :subject "" :body ""}) |
| 07:46 | CookedGryphon | are you doing exactly the same? |
| 07:47 | justin_smith | sm0ke: you can test local mail by using mail or mutt, it should just install and work |
| 07:47 | justin_smith | CookedGryphon: so you are able to use the postal lib with gmail? |
| 07:47 | CookedGryphon | yeah |
| 07:47 | CookedGryphon | wait, sorry, user and pass, not username and password |
| 07:47 | sm0ke | hmm weird |
| 07:48 | CookedGryphon | i rename them on teh way in so my config is consistent |
| 07:48 | guns | I use postal with smtp.gmail.com; works well. Maybe the machine sm0ke is hitting is failing |
| 07:48 | sm0ke | i am using ^{:user "... " :pass "**"} ..with that meta sign |
| 07:48 | sm0ke | weird thats what the doc mentions |
| 07:48 | CookedGryphon | yeah, don't know what on earth that's about |
| 07:48 | CookedGryphon | teh docs need editing |
| 07:48 | CookedGryphon | makes far more sense to just send settings then message |
| 07:49 | sm0ke | hmm let me try your version |
| 07:49 | CookedGryphon | i was including a :from in the message too |
| 07:49 | CookedGryphon | gmail might need that |
| 07:49 | sm0ke | yup i have that already |
| 07:51 | CookedGryphon | hmm, there's a pull request to fix the docs from 2 years ago... |
| 07:58 | sm0ke | some progress, i get com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required. now |
| 07:58 | justin_smith | sounds like its time to fork it just to get better docs |
| 07:58 | justin_smith | lol |
| 07:58 | sm0ke | weird though |
| 08:04 | sm0ke | CookedGryphon: hey it worked |
| 08:04 | sm0ke | actually it needs :user and :pass |
| 08:04 | sm0ke | not :username and :password |
| 08:04 | sm0ke | i think main problem was with the meta sign |
| 08:06 | sm0ke | bye for now |
| 08:17 | tim___ | dnolen: ping |
| 08:26 | gtuckerkellogg | forcer, with the simple setup, elpy-shell-send-region-or-buffer only seems to work for me with an active region |
| 08:27 | justin_smith | gtuckerkellogg: wrong channel? |
| 08:27 | gtuckerkellogg | justin_smith, indeed! |
| 08:29 | justin_smith | this here city slicker thinks he can use INDENTATION instead of PARENTHESIS as God intended |
| 08:29 | justin_smith | get 'im boys |
| 08:29 | noidi | :D |
| 08:33 | tbaldridge | ~guards |
| 08:33 | clojurebot | SEIZE HIM! |
| 08:33 | mdrogalis | Heh |
| 08:33 | gtuckerkellogg | lol |
| 08:53 | hyPiRion | ~gourds |
| 08:53 | clojurebot | SQUEEZE HIM! |
| 09:26 | terom | There seems to be a JSON-RPC library for Clojure called clj-json-rpc for the server side. I'm looking for a library to help building a JSON-RPC client, is there a such thing already? |
| 09:28 | justin_smith | terom: seems like with cheshire and one of the http client libs it would be pretty simple without a dedicated json-rpc client |
| 09:29 | justin_smith | terom: the spec is simple enough http://json-rpc.org/wiki/specification |
| 09:30 | justin_smith | oh, I see that version 2 is a bit more complex http://www.jsonrpc.org/specification |
| 09:37 | rstandy | just another newbie question: is there some in production web app or site developed in clojure? |
| 09:37 | justin_smith | I have deployed a few |
| 09:37 | justin_smith | (my company, I did the clojure part on the backend) |
| 09:38 | justin_smith | there is an out of date list on clojure.org somewhere |
| 09:38 | justin_smith | soundcloud |
| 09:38 | rstandy | justin_smith: wow, can I see of them (those which are publicly available) |
| 09:38 | justin_smith | http://corp.zinio.com/ the only evidence of clojure is how fast it loads |
| 09:38 | justin_smith | I guess |
| 09:39 | justin_smith | http://weareinstrument.com/work/featured/the-build this one is pretty awesome actually |
| 09:39 | rstandy | justin_smith: souncloud.org is simply wonderful! |
| 09:39 | justin_smith | both that blog, and the site it links to, use clojure with the framework I helped write, though I have not coded much for those two projects |
| 09:40 | justin_smith | http://thebuildfilm.com/ be sure to see this, the actual site that last blog post was about |
| 09:40 | justin_smith | flash-like ui in html5 |
| 09:41 | justin_smith | with clojure backend, of course |
| 09:42 | justin_smith | almost forgot this one: done in clojure + clojurescript http://onenorthpdx.com/ |
| 09:42 | rstandy | justin_smith: by backend you mean that clojure builds the html pages or not? |
| 09:42 | justin_smith | it handles the cms |
| 09:42 | justin_smith | it serves all the data |
| 09:42 | justin_smith | handles the requests |
| 09:42 | justin_smith | renders templates |
| 09:42 | rstandy | justin_smith: ok, got it |
| 09:43 | justin_smith | resizes images for your screen resolution (caching existing resizes) |
| 09:43 | rstandy | justin_smith: thank you very much for the info man |
| 09:43 | justin_smith | with that last one (one north) the whole UI is built in clojurescript using core.async to handle events |
| 09:44 | rstandy | justin_smith: wow |
| 09:44 | rstandy | justin_smith: awesome sites! |
| 09:44 | justin_smith | thanks, that's mostly because we have awesome designers |
| 09:44 | justin_smith | and very meticulous frontend devs that can realize those designs |
| 09:45 | justin_smith | but it helps that I can make sure the pages load fast and get the right data too :) |
| 09:45 | rstandy | justin_smith: is your backend donwlodable free software? :-))) |
| 09:45 | justin_smith | rstandy: it is open source, we will be announcing and publicising it soon |
| 09:46 | rstandy | justin_smith: this is very interesting!!! Will you email the clojure ml? |
| 09:46 | justin_smith | basically "watch this space", we have a nice frontend site for intro and docs that will be public in a day or two |
| 09:46 | justin_smith | yeah, I think that is the plan |
| 09:47 | rstandy | justin_smith: exciting news, I hope to be productive with clojure pretty soon, I want to push it in my workplace |
| 09:47 | justin_smith | it is a pretty cool setup, I can take only marginal credit, the main dev is an old friend of mine that pulled me in to help because he knew I liked programming lisp |
| 09:48 | justin_smith | rstandy: huge selling points are reduced server resources (thus less deployment cost) massively reduced development time (meaning more agile to accomidate design changes, and your project will never be behind schedule for backend reasons) |
| 09:48 | rstandy | justin_smith: nice, what was your language and environment before clojure |
| 09:48 | rstandy | justin_smith: huge selling points! |
| 09:48 | justin_smith | I got hired to do clojure |
| 09:49 | justin_smith | before that they were using ruby |
| 09:49 | justin_smith | but server costs and reliability sucked |
| 09:49 | rstandy | justin_smith: dream job for me :D |
| 09:49 | justin_smith | before that php |
| 09:49 | justin_smith | rstandy: it is very nice |
| 09:49 | rstandy | justin_smith: yeah, ruby sucks in many ways |
| 09:49 | rstandy | justin_smith: are you coming from CL+Emacs |
| 09:49 | rstandy | +Slime? |
| 09:49 | justin_smith | it is especially since I can be productive enough in clojure that I spend more of my time honing my skills and improving our libs than I spend developing sites |
| 09:50 | justin_smith | yeah, common lisp / scheme / ocaml |
| 09:50 | justin_smith | definitely emacs no matter what, but that's the tool not the medium :) |
| 09:51 | rstandy | justin_smith: yeah, any advice/tip for an CL+Emacs+Slime developer approaching clojure? |
| 09:51 | justin_smith | actually I was not even a professional programmer before jumping into this, I was just fascinated by algorithms and functional programming |
| 09:51 | justin_smith | hmm |
| 09:51 | justin_smith | get cider |
| 09:51 | justin_smith | which is the update to nrepl.el |
| 09:52 | justin_smith | use paredit, after a few days learning it it is indespensible |
| 09:52 | rstandy | justin_smith: yeah! Wonderful mode I already use in CL |
| 09:52 | justin_smith | and (source fn) (doc fn) are your friends :) |
| 09:53 | justin_smith | oh, and throw (ns-publics ns) in the mix too |
| 09:53 | rstandy | justin_smith: I installed cider, and I'm starting to explore clojre through it, but I miss the Slime Inspector |
| 09:53 | justin_smith | we are working on a cdt web frontend |
| 09:53 | justin_smith | I have not had much luck with ritz |
| 09:54 | rstandy | justin_smith: so a Slime-like inspector is still missing in clojure |
| 09:54 | justin_smith | cdt assumes you are connecting to a separate program that is being debugged, so we can connect to the process with the server, have an html UI, and click on stack trace lines to evaluate expressions in that context / see locals |
| 09:54 | nDuff | ...well, there _is_ ritz |
| 09:55 | nDuff | ...if you're willing to go through the pain to set it up. |
| 09:55 | justin_smith | rstandy: theoretically ritz can do that stuff, I have not had luck with it |
| 09:55 | rstandy | justin_smith: will check that then |
| 09:55 | justin_smith | we looked at ritz as the backend for our web-based debugger, and decided cdt was easier and had all the functionality we needed |
| 09:55 | rstandy | justin_smith: ok, sometimes do you miss some CL and Slime features when using clojure (sorry for so many questions)? |
| 09:55 | justin_smith | yeah, for sure |
| 09:56 | justin_smith | like the step debugging etc. |
| 09:56 | rstandy | justin_smith: just trying to understand what I'll miss and what I'll gather with clojure |
| 09:56 | justin_smith | but, with immutible data structures and a more strictly functional approach, I find invasive debugging less neccessary |
| 09:56 | justin_smith | I can do a lot just by verifying each function produces the right output for the expected input |
| 09:57 | justin_smith | also I often miss static checks and currying from ocaml |
| 09:58 | rstandy | justin_smith: man your answers are really useful for me, many thanks! |
| 09:58 | justin_smith | speaking of debugging, I released a middleware for ring the other day called groundhog, that archives requests so that they can be reconstructed and replayed to verify bugfixes |
| 09:58 | justin_smith | https://github.com/noisesmith/groundhog |
| 09:58 | rstandy | justin_smith: wow, nice |
| 09:59 | justin_smith | I need to update that readme, the latest is 0.4 |
| 09:59 | justin_smith | *0.0.4 |
| 10:00 | rstandy | justin_smith: You gave me so much info to starts with that I'm tempted to abandon the idea to learn clojure... :D |
| 10:01 | justin_smith | ? |
| 10:01 | justin_smith | why would you not want to learn clojure? |
| 10:01 | rstandy | justin_smith: just joking, it's so much good info that I want to learn everything now! |
| 10:01 | justin_smith | hah |
| 10:02 | rstandy | justin_smith: very intriguing language and community with fantastic libraries, this is what the clojure world is for me right now |
| 10:02 | justin_smith | I concur |
| 10:02 | justin_smith | it's great to work with a language that I unreservedly love |
| 10:03 | rstandy | justin_smith: hope to be able to become very productive soon. You know, when the boss ask what work has been done, I have to answer something :D |
| 10:03 | rstandy | justin_smith: I tried to stick with CL, but lack of libraries is becoming to restrictive |
| 10:03 | mdrogalis | rstandy: Just take your time. It's worth learning, but go slowly and thoroughly. |
| 10:03 | justin_smith | well, clojure does have some features (and default / recommended coding style) that leads to productivity once you internalize it |
| 10:04 | rstandy | justin_smith: very interesting perspective about OOP. I think I more or less agree. It's interesting to see how complexity is managed with the clojure way |
| 10:05 | cemerick | dnolen: is continuing to support :export meta carrying an alternative name (rather than truthiness) a real objective? In the face of supporting downstream mutability, it complicates things significantly. |
| 10:06 | rstandy | justin_smith: thanks, man, very nice and helpful! |
| 10:06 | rstandy | justin_smith: have a nice day and hope to talk with you again |
| 10:06 | justin_smith | thanks, you too |
| 10:07 | dnolen | cemerick: I don't really understand what you just said |
| 10:07 | shoshin | hello |
| 10:07 | shoshin | how does one iterate in clojure? |
| 10:08 | shoshin | i want to iterate a body twice. how do i achieve this using doseq? |
| 10:08 | justin_smith | shoshin: iterate to do an action, or iterate a transformation of a sequential input? |
| 10:08 | cemerick | dnolen: right now, you can (defn ^{:export "foo"} bar 5); bar will be emitted and optimized away by GClosure, foo will be an exported "symbol", changes to which will not affect any fns that refer to bar in cljs source. |
| 10:08 | Morgawr | ,(doc dotimes) |
| 10:08 | clojurebot | "([bindings & body]); bindings => name n Repeatedly executes body (presumably for side-effects) with name bound to integers from 0 through n-1." |
| 10:08 | justin_smith | ,(dotimes [i 2] (print i)) |
| 10:08 | clojurebot | 01 |
| 10:09 | justin_smith | Morgawr: beat me to it |
| 10:09 | Morgawr | :P |
| 10:09 | Morgawr | how do you @ clojurebot to somebody? |
| 10:09 | Morgawr | (if it's even possible) |
| 10:09 | justin_smith | hmm |
| 10:09 | llasram | ,(str "like this?") ; Morgawr |
| 10:09 | clojurebot | "like this?" |
| 10:09 | Morgawr | I could do something like |
| 10:10 | dnolen | cemerick: yes I know that, but I don't understand what you said above. |
| 10:10 | cemerick | dnolen: The fix for CLJS-670 will make such an arrangement impossible, since two properties will need to change in order to maintain consistency between the exported property, and the "internal" one that GClosure has renamed, etc. |
| 10:10 | Morgawr | ,(str "shoshin:" (doc dotimes)) |
| 10:10 | clojurebot | "shoshin:([bindings & body]); bindings => name n Repeatedly executes body (presumably for side-effects) with name bound to integers from 0 through n-1." |
| 10:10 | Morgawr | :D |
| 10:10 | shoshin | Morgawr thanks! will try! |
| 10:10 | Morgawr | refer to justin_smith's example (which was probably more useful) |
| 10:10 | seangrove | ,(println (str "seangrove:" (doc dotimes))) |
| 10:10 | clojurebot | seangrove:([bindings & body]); bindings => name n Repeatedly executes body (presumably for side-effects) with name bound to integers from 0 through n-1.\n |
| 10:11 | Morgawr | seangrove: that's better |
| 10:11 | seangrove | Morgawr: Just wondering if there's another chance for a bot quine... it's almost been one year now |
| 10:11 | dnolen | cemerick: I'm pretty sure this has come up before, what's the problem with ^:export ^:expose or something like that? |
| 10:11 | Morgawr | a bot quine? |
| 10:12 | justin_smith | Morgawr: making the bots trigger one another, infinitely |
| 10:12 | rstandy | justin_smith: so, one last question: the most advanced ide, editor, tool for writing and debugging cloujre apps? |
| 10:12 | Morgawr | haha |
| 10:12 | cemerick | dnolen: you mean expose in the @expose GClosure sense? |
| 10:12 | shoshin | Morgawr http://clojuredocs.org/clojure_core/clojure.core/dorun i'm looking for something like example in the first case. repeat some action n number of times. |
| 10:12 | Morgawr | rstandy: probably emacs. I personally use both vim and LightTable (LightTable is getting really good) |
| 10:12 | seangrove | Morgawr: Yeah, last one was in December 2012... |
| 10:12 | justin_smith | rstandy: : we had a "show your editing environment" night for the last clojerks pdx |
| 10:12 | Morgawr | shoshin: that's another way, yes |
| 10:13 | justin_smith | rstandy: emacs and vim looked the most impressive |
| 10:13 | justin_smith | though cursive looked nice if you want a java style IDE experience |
| 10:13 | shoshin | Morgawr doesn't seem to work though. :/ |
| 10:13 | shoshin | i get a null pointer exception. |
| 10:13 | Morgawr | dorun is to resolve lazy sequences |
| 10:13 | justin_smith | light table was surprisingly disappointing, though it could be because the guy presenting it wasn't adept enough with it |
| 10:13 | Morgawr | dotimes is to run N times the same expression |
| 10:13 | rstandy | justin_smith: I'm definately on the Emacs side, but what should I use? swank-clojure + swank-cdt? Or cider? |
| 10:14 | rstandy | and nrepl? |
| 10:14 | justin_smith | rstandy: cider or nrepl |
| 10:14 | justin_smith | swank is to be avoided at this point |
| 10:14 | dnolen | cemerick: yes, if I recall. |
| 10:14 | rstandy | justin_smith: no one is the real winner right now, then |
| 10:14 | justin_smith | rstandy: try cider first, since nrepl is transitioning to that |
| 10:14 | Morgawr | ,(dotimes [_ 5] (println "hi")) |
| 10:14 | clojurebot | hi\nhi\nhi\nhi\nhi\n |
| 10:14 | Morgawr | ^ |
| 10:14 | rstandy | oh ok, so cdt is not recommended anymore |
| 10:14 | Morgawr | or use n instead of _ if you care about the variable bound to the iteration count |
| 10:14 | justin_smith | rstandy: cdt is only partially tied to swank |
| 10:15 | justin_smith | rstandy: I use it without using swank at all |
| 10:15 | rstandy | justin_smith: ah ok |
| 10:15 | justin_smith | via the browser |
| 10:15 | justin_smith | not even in the editor |
| 10:15 | rstandy | justin_smith: sorry for the silly question |
| 10:15 | justin_smith | np |
| 10:15 | justin_smith | glad to help |
| 10:15 | rstandy | justin_smith: :-) |
| 10:16 | CoconutCrab | okay, maybe it would be more proper to ask in #emacs instead, but how can one remove nrepl from emacs (via package.el) to install cider? |
| 10:16 | dnolen | cemerick: I'm guess didn't affect *set-print-fn* because we didn't give it an initial value? |
| 10:16 | dnolen | er *print-fn* |
| 10:16 | cemerick | dnolen: Two different topics, really. First, we definitely don't want @expose, it takes a bunch of analysis/optimizations off the table when applied to fns, which inevitably yields piles of (spurious AFAICT based on testing) warnings. |
| 10:17 | cemerick | dnolen: the issue with the alternative ^:export name is that we're setting up two different properties when it's used, a natural source of inconsistency if there's mutability about. |
| 10:17 | justin_smith | CoconutCrab: in the package interface, d will mark a package for deletion, and x will act on all marks |
| 10:18 | CoconutCrab | justin_smith: oh, silly me... sorry for bothering you... |
| 10:18 | CoconutCrab | and thank for answering |
| 10:18 | justin_smith | CoconutCrab: no problem, it is not intuitive unless you are used to gnus, mh, dired, and all the other little emacs things that use the mark / act paradigm |
| 10:19 | justin_smith | the downside with emacs is it is not consistent with "normal", the upside is it is pretty good at being internally consistent |
| 10:19 | CoconutCrab | justin_smith: I see now uninstall option and tend to use '-' for marking |
| 10:19 | CoconutCrab | (like in debian's aptitude) |
| 10:20 | CoconutCrab | then I forgot that emacs has C-h m... |
| 10:20 | justin_smith | yeah, never expect emacs to act like another program you are used to... |
| 10:20 | augustl | what _does_ harmonikit sound like? :) https://twitter.com/richhickey/status/399918185450704897 |
| 10:20 | cemerick | dnolen: well, set-print-fn! was never really "exposed", at least w.r.t. mutation, because it was just aliased to the exported symbol. |
| 10:21 | justin_smith | augustl: I would say a clojure library for midi controlled compressed air actuated harmonica robots |
| 10:21 | napper | does anyone have a recconmendation for image manipulation libs with clojure? |
| 10:21 | justin_smith | augustl: and I will be severely disappointed if it is not that |
| 10:21 | justin_smith | napper: what kind of manipulations? |
| 10:22 | justin_smith | napper: for basic stuff interop with BufferedImage has worked well for me, but there is also imgscalr |
| 10:22 | cemerick | dnolen: anyway, my fundamental Q is whether I can sacrifice e.g. ^{:export "some.other.name"} in order to support downstream mutation of exported properties. They're really fundamentally incompatible. Alternatively, we could say that properties exported with alternative names are read-only. |
| 10:23 | cemerick | i.e. retain the same semantics they have now, and don't get the same support as described in CLJS-670 |
| 10:23 | napper | justin_smith: to begin, just plastering images together to make css sprites - but I'm always a fan of graph-based-algorithum-image-manipulation |
| 10:23 | karls | napper: i tried to find an image manipulation library that does more than scale/rotate, but couldn't. had to drop down to java. |
| 10:24 | napper | karls: it's been a few years for me. what is the current java img-lib? |
| 10:24 | napper | karls: ie, in python its PIL |
| 10:25 | justin_smith | napper: I use java.awt and javax.imageio |
| 10:25 | karls | napper: i re-wrote something that originally used PIL, in clojure. i didn't use a library at all. the interop is so good that i just ended up using BufferedImage related java facilities. |
| 10:26 | karls | napper: what justin_smith said :-) |
| 10:26 | justin_smith | that's java.awt.image.BufferedImage, if you are looking for the javadoc |
| 10:26 | napper | justin_smith, awesome, I'll look into them. BufferedImage + those libs |
| 10:27 | justin_smith | napper: they come as part of the jvm, you just need to import them |
| 10:27 | napper | justin_smith, karls, I'll see what I can do about building something more then just rotation and scaling. :) |
| 10:27 | justin_smith | next part is adapting yourself to learning via javadoc |
| 10:27 | justin_smith | napper: please do! though you may just find the built in interop is enough (as we did) |
| 10:28 | napper | justin_smith, heh, there was a time when I was a j2ee dev, then I found python o: |
| 10:28 | napper | thanks for the leads! |
| 10:28 | justin_smith | np |
| 10:34 | johnpete | Hi - I'm trying Clojure and Compojure for the first time. The lein template has given me some code that has an application of some function called -> How do I find what this function is? I can't google it! |
| 10:35 | seangrove | cemerick dnolen: Any tickets or help you'd like with cljs or cljsbuild? |
| 10:35 | justin_smith | wow, it looks like the analemma svg generation library doesn't use java interop, so it may be clojurescript compatible |
| 10:35 | karls | ,(doc ->) |
| 10:35 | clojurebot | "([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc." |
| 10:35 | karls | or http://clojuredocs.org/clojure_core/clojure.core/-%3E |
| 10:35 | seangrove | ,(println (str "johnpete: " (doc ->))) |
| 10:35 | clojurebot | johnpete: ([x] [x form] [x form & more]); Threads the expr through the forms. Inserts x as the second item in the first form, making a list of it if it is not a list already. If there are more forms, inserts the first form as the second item in second form, etc.\n |
| 10:36 | mdrogalis | johnpete: Yeah it's a weird one. It's called "thread first". |
| 10:36 | justin_smith | johnpete: also there is a cool site for searching symbols that other engines don't index http://symbolhound.com/?q=clojure+-%3E |
| 10:36 | johnpete | great, thanks everyone |
| 10:38 | cemerick | seangrove: cljsbuild is semi-frozen until 1.0.0 is out, then we can start seriously recasting it. If you're in an investigative mood, you could look into what is in certain Chrome extensions that breaks the browser-REPL, e.g. https://github.com/emezeske/lein-cljsbuild/issues/262 and https://github.com/cemerick/austin/issues/17 |
| 10:38 | seangrove | cemerick: Uhg |
| 10:39 | cemerick | heh |
| 10:39 | cemerick | The one in the first link is far simpler than the Google Voice extension, so it might be tractable. |
| 10:39 | seangrove | cemerick: Will check into it, we make a chrome extension as our primary product right now :) |
| 10:39 | cemerick | seangrove: my exact sentiment |
| 10:40 | cemerick | seangrove: That's interesting. As the primary business, or is the extension a complement to an online service, etc? |
| 10:40 | seangrove | cemerick: http://www.zenboxapp.com/ - clojure and clojurescript |
| 10:41 | seangrove | cemerick: As an extension working inside of gmail with other unaware extensions... it's all a nightmare |
| 10:42 | cemerick | seangrove: what's the business model, if I may ask? |
| 10:42 | seangrove | cemerick: We charge people for premium features, pretty straightforward |
| 10:43 | cemerick | seangrove: oh, cool; I guess the upsell is in the extension itself? I didn't see anything obvious about it on the site. |
| 10:43 | seangrove | cemerick: Yeah, exactly. Most things are free and it just works, but when someone reaches deeper into the integrations we start a time trial, and then get cc info, charge, etc. |
| 10:44 | cemerick | nice |
| 10:44 | cemerick | seangrove: the reviews are glowing, congrats. :-) |
| 10:44 | justin_smith | or if they want the sidebar to wear a custom hat or get that powerup they need to beat the level... |
| 10:44 | seangrove | cemerick: Wsan't always that way, but things have been moving in the right direction :) Getting reified keywords into cljs helped quite a bit |
| 10:45 | justin_smith | seangrove: that does look cool, our producers all use gmail, I'll see if they use it already or might find it useful |
| 10:45 | seangrove | justin_smith: IAP for level upgrades coming soon, I suppose |
| 10:45 | justin_smith | heh |
| 10:45 | justin_smith | angry birds does well with holiday editions |
| 10:46 | justin_smith | "$1 to add the christmas theme, $100 to remove it again" |
| 10:46 | seangrove | hah |
| 10:47 | justin_smith | so for a chrome extension do you basically compile to a javascript package? |
| 10:48 | seangrove | justin_smith: I believe it's a tar, but we use openforge to take care of the gritty details these days |
| 10:48 | justin_smith | cool |
| 10:54 | mdrogalis | Anyone here using ZooKeeper for coordination? #zookeeper is a bit quiet. |
| 10:54 | justin_smith | it's near the top of my "we should be using this lib" pile |
| 10:54 | justin_smith | haven't tried it though |
| 10:54 | TheLastProject | ,(println ((first '[One Two Three]) (nth '[One Two Three] 2)) (second '[One Two Three])) |
| 10:54 | clojurebot | nil Two\n |
| 10:54 | TheLastProject | Hmm... |
| 10:54 | mdrogalis | Not really a lib, more of a service. |
| 10:55 | justin_smith | mdrogalis: I meant the clojure client lib |
| 10:55 | mdrogalis | justin_smith: Ah, understood. |
| 10:55 | TheLastProject | ,(println (join " "((first '[One Two Three]) (nth '[One Two Three] 2))) (second '[One Two Three])) |
| 10:55 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: join in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 10:55 | justin_smith | TheLastProject: did you mean (println [(first ... |
| 10:55 | mdrogalis | It has some annoying semantics around watching for changes. |
| 10:56 | TheLastProject | justin_smith: I'm trying to get the dispatch feature to work better, but every attempt I throw at it just turns into chaos |
| 10:56 | justin_smith | TheLastProject: ((first '[One Two Three])) will try to execute 'One as a function |
| 10:57 | TimMc | mdrogalis: We are, but I can't claim to be familiar with it. |
| 10:57 | mdrogalis | TimMc: Hmm, alrighty. Thanks anyway :) |
| 10:57 | justin_smith | one of these weekends I plan to make a zookeeper client as a ring middleware |
| 10:57 | mdrogalis | It pretty much supports "watching" a piece of state. But after the event triggers, it kills the watch. |
| 10:57 | justin_smith | so coordination is ensured with each request |
| 10:58 | mdrogalis | So it's more like "watch-once" semantics. |
| 10:58 | justin_smith | can't you make your response action create the watch again? |
| 10:58 | justin_smith | recursion :) |
| 10:58 | TheLastProject | justin_smith: http://pastebin.com/F9rEx7KG (line 29) - I still have two problems with it. It somehow complains about "java.lang.String cannot be cast to clojure.lang.IFn", but I can't figure out why, and I still need to figure out how to have it also send all additional arguments given, ugh... |
| 10:58 | mdrogalis | justin_smith: It's a distributed system. Interesting things can happen inbetween that would be missed. |
| 10:59 | justin_smith | mdrogalis: true |
| 10:59 | justin_smith | TheLastProject: that error means that you put something that returns a string in the calling position |
| 11:00 | TheLastProject | justin_smith: I can't see what that would be, though. If I use print to test it it nicely resolves to "list clothing" and the likes, which (dispatch) should resolve to the function before calling... |
| 11:01 | justin_smith | TheLastProject: I am going to do a small cleanup of your code to make it a little easier to think about, one moment |
| 11:01 | ltw | what's the best approach for creating a library with support for core.typed, but that doesn't require it? |
| 11:01 | TheLastProject | justin_smith: I guess it could need that. I can't say it doesn't look like an utter mess. Wonder how much different your version will be from mine, hmm |
| 11:02 | ltw | i was thinking multiple versions (i.e. 0.1.0 and 0.1.0-typed) |
| 11:03 | justin_smith | TheLastProject: mainly I am using let so you don't have repeated calls to the same function noising things up, I'll paste it in a moment |
| 11:05 | justin_smith | TheLastProject: https://www.refheap.com/20719 |
| 11:06 | justin_smith | that is not yet correct, but I think it is easier to read |
| 11:06 | justin_smith | I put it on refheap because refheap is less spammy |
| 11:06 | terom | justin_smith: thanks. I've heard of cheshire but not used it. Version 2.0 of JSON-RPC definetely seems a little bit more complex... maybe I'll try to come up with a library of my own. |
| 11:07 | justin_smith | terom: cheshire is very easy to use, it turns clojure vectors / maps / strings / numbers into json, and the reverse |
| 11:10 | TheLastProject | justin_smith: I should've probably updated the println above, but I'm trying to make it execute (list-clothing upper) if the user types "list upper clothing" and, after I get that working, also take the other parameters so I can get add-clothing to work, but those as just strings |
| 11:11 | TheLastProject | justin_smith: I see that your command thing only takes the first parameter :P |
| 11:11 | justin_smith | TheLastProject: was that my mistake? I thought I was just following the nesting of the original, one sec |
| 11:12 | justin_smith | oh, I did mess it up, but neither of our versions are correct :) |
| 11:12 | TheLastProject | Well, I know mine isn't correct |
| 11:12 | TheLastProject | At least yours looks more readable |
| 11:13 | justin_smith | in your original, if you linebreak and autoindent, you can see that the result of calling dispatch on the third arg is being called as a function |
| 11:13 | justin_smith | with (collection ...) as its arg |
| 11:14 | TheLastProject | Huh. I tried to very carefully retype it with print and it returned "first third" when I tried to do that. Now I wonder if I'm really so used to how most object-oriented languages use () that I just can't even read it properly |
| 11:15 | TheLastProject | s/print/println |
| 11:17 | justin_smith | TheLastProject: https://www.refheap.com/20719 |
| 11:17 | justin_smith | edited, I think closer to what you want |
| 11:17 | justin_smith | using amalloy_'s suggestion to use apply |
| 11:18 | justin_smith | so we split that input into tokens, first of those looks up the command, rest are args, first arg looks up the collection, and then we just pass in the rest |
| 11:18 | TheLastProject | The first and third arg combined is supposed to be the command :x |
| 11:18 | justin_smith | ok, but you know how to fix that, right? |
| 11:19 | justin_smith | by changing the definition of command in the let statement |
| 11:19 | TheLastProject | Well, no, because command ((first tokens) (nth tokens2)) causes Clojure to complain about it being a string |
| 11:19 | TheLastProject | Err... |
| 11:20 | TheLastProject | Yeah, that's what I'm trying to do, but I can't understand why it complains it is a string that it can't convert to a function |
| 11:20 | justin_smith | ((first tokens)) tries to execute the return value of (first tokens) |
| 11:20 | TheLastProject | s/tokens2/tokens 2 |
| 11:20 | TheLastProject | Oh... |
| 11:20 | TheLastProject | Oh, darn it |
| 11:20 | justin_smith | , (:hello {:hello "world"}) |
| 11:20 | clojurebot | "world" |
| 11:20 | justin_smith | , ((:hello {:hello "world"})) |
| 11:20 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to clojure.lang.IFn> |
| 11:20 | justin_smith | that is your error |
| 11:21 | justin_smith | () is not for grouping in clojure |
| 11:21 | justin_smith | ever |
| 11:21 | justin_smith | it can make a literal list, or apply a function |
| 11:21 | justin_smith | that's it |
| 11:21 | TheLastProject | Okay, I need to get that in my head |
| 11:21 | TheLastProject | But now I wonder how to "group" it then because otherwise it will complain about having too many arguments, hmm... |
| 11:22 | justin_smith | what you want is to construct the string so it matches your lookup table |
| 11:22 | justin_smith | ,(str "add" \space "clothing") |
| 11:22 | clojurebot | "add clothing" |
| 11:22 | justin_smith | ,(clojure.string/join " " ["add" "clothing"]) |
| 11:22 | clojurebot | "add clothing" |
| 11:22 | bja | ,(+ 1 2 3) |
| 11:22 | clojurebot | 6 |
| 11:22 | bja | wow, didn't realize that worked for anybody |
| 11:23 | justin_smith | bja: you can also send a private message to clojurebot |
| 11:23 | TheLastProject | Ah... |
| 11:24 | justin_smith | TheLastProject: the funny thing is you even use clojure.string/join at the top of the file |
| 11:24 | TheLastProject | Okay, yeah |
| 11:24 | TheLastProject | I get it, [] is for turning it into a list, which is the closest to grouping you get |
| 11:24 | justin_smith | there is also the list function |
| 11:24 | TimMc | [] is for creating a vector |
| 11:24 | TimMc | ,[1 2 3] |
| 11:24 | clojurebot | [1 2 3] |
| 11:25 | TimMc | ,(list 1 2 3) |
| 11:25 | clojurebot | (1 2 3) |
| 11:25 | justin_smith | or () if quoted |
| 11:25 | TheLastProject | Ugh, yeah |
| 11:25 | TheLastProject | You people call it a vector |
| 11:25 | TheLastProject | My bad |
| 11:25 | TimMc | Well, we also *have* lists. |
| 11:25 | TheLastProject | Every language uses different names, and a "list" isn't the same thing in all of them :P |
| 11:25 | justin_smith | eventually keeping track of which one you are using avoids weird bugs :) |
| 11:25 | TheLastProject | Okay, well, thanks |
| 11:26 | TheLastProject | Now I just need to do the args stuff, let's see how that goes |
| 11:26 | justin_smith | TheLastProject: here is a trick I sometimes use when debugging |
| 11:26 | justin_smith | ,(let [a 2 _ (println a) b 3] (+ a b)) |
| 11:26 | clojurebot | 2\n5 |
| 11:26 | justin_smith | so it prints a, then returns 5 |
| 11:27 | TheLastProject | I'm having trouble following that, heh... |
| 11:27 | justin_smith | the _ is a convention that says "I am not using this return value" in a let |
| 11:27 | justin_smith | so I assign a with the value 2 |
| 11:27 | justin_smith | I assign _ with the value nil (returned by print) |
| 11:27 | justin_smith | the reason to do it there is I can then look at things as I construct them |
| 11:27 | justin_smith | it helps sometimes |
| 11:27 | TheLastProject | Hmm |
| 11:28 | TimMc | Clojure lists are basically stacks (append and peek at the front); vectors are log-time random-access and append at the end. |
| 11:28 | justinjaffray | justin_smith: that is so useful, thanks :D |
| 11:29 | justin_smith | justinjaffray: np |
| 11:29 | TheLastProject | Is there a way to have something like (rest) but starting at the 4th point in the list, instead of the third? |
| 11:29 | TheLastProject | s/third/second/ |
| 11:29 | TheLastProject | Oh man, such a headache, heh... |
| 11:29 | TheLastProject | I'm not used to coding this way |
| 11:30 | TheLastProject | It's interesting, but it's... different |
| 11:30 | justin_smith | TheLastProject: nthrest |
| 11:30 | justin_smith | TheLastProject: http://clojure.org/cheatsheet is helpful |
| 11:30 | TheLastProject | That actually makes sense |
| 11:30 | justin_smith | TheLastProject: the pain is your brain growing stronger! |
| 11:31 | TheLastProject | Yay! It works! |
| 11:31 | TheLastProject | Thank you SO much justin_smith |
| 11:31 | justin_smith | very nice, can I see the final result? |
| 11:32 | justin_smith | no problem, glad I could help |
| 11:32 | TheLastProject | Of course |
| 11:32 | TheLastProject | justin_smith: https://www.refheap.com/20722 |
| 11:32 | faust45 | is it possible assign metadata to types ? |
| 11:33 | faust45 | like (deftype User ^{}) |
| 11:33 | TimMc | What would the behavior be? |
| 11:34 | justin_smith | TheLastProject: the order of assigning the values in the let is a little tangled, but yeah, that looks great |
| 11:34 | justin_smith | by tangled I don't mean incorrect, just not in the easiest to read order |
| 11:34 | TheLastProject | I guess collection-string should go for args |
| 11:34 | TheLastProject | Makes more sense |
| 11:35 | TheLastProject | But I'm mostly glad it works now, heh... |
| 11:35 | justin_smith | heh, yeah, it is an accomplishment |
| 11:36 | napper | has anyone putout a repl like ipdb in clojure? |
| 11:36 | justin_smith | another suggestion is to put everything after the last defn (and all the printlns) into a -main function |
| 11:36 | justin_smith | then lein run will work |
| 11:36 | napper | I'd like the opition to break in my code without having to use an ide. |
| 11:36 | TheLastProject | Ah, I'm running it with "clojure" but I've heard leiningen is really popular, should probably strive for leiningen-compatibility |
| 11:37 | justin_smith | TheLastProject: it makes things much easier, eventually |
| 11:37 | justin_smith | and even if you are just running the clojure command, you can put (-main) at the end of the file, to explicitly execute it |
| 11:38 | TheLastProject | clojure-main? |
| 11:38 | justin_smith | napper: cdt can do breaks that you define in a repl, and you can use it without swank pretty easily |
| 11:39 | justin_smith | napper: we've been working on a web UI that would let us set breakpoints and investigate values / run code in a clojure project we attach to |
| 11:39 | justin_smith | we use cdt for that |
| 11:40 | justin_smith | TheLastProject: ? |
| 11:40 | TheLastProject | justin_smith: I'll take that question mark as a "no" |
| 11:40 | justin_smith | I don't understand the question |
| 11:40 | justin_smith | the magic function name defaults to -main |
| 11:41 | TheLastProject | justin_smith: (defn -main [] (doseq [line (repeatedly read-line) :while line] (getinput line) (request-command))) |
| 11:41 | TheLastProject | So, that stuff? |
| 11:41 | napper | justin_smith, interesting, I'm curious as to how you would break on a line with a gui per thread. - How do you trace anom functions? |
| 11:41 | TheLastProject | (Put it on one line to not spam, I'm not undoing your improvements) |
| 11:41 | justin_smith | yeah, put all the printlns in there too |
| 11:41 | TheLastProject | Ah |
| 11:41 | justin_smith | napper: that is a UI for stack traces on exception |
| 11:41 | TheLastProject | So that they execute when it is first run |
| 11:41 | TheLastProject | Got it! |
| 11:42 | justin_smith | napper: we haven't done source line breakpoints, but that would be a different UI |
| 11:43 | napper | justin_smith: when using ipdb, it would break/stop tho code execution in a single thread allowing you to inspect what is in memory. Much like the gdb interface ( at least what I know of the gdb interface. ) |
| 11:43 | justin_smith | napper: yes, same idea |
| 11:43 | napper | justin_smith: ideally, you'd build a pure function and concat them together with threads in mind. |
| 11:43 | justin_smith | but we show all the available stacks at once |
| 11:44 | napper | justin_smith: neat, I'm eager to see it - it's the last thing I need to convert. :P |
| 11:44 | justin_smith | *available frames |
| 11:44 | justin_smith | source line breakpoints is something we may do later - but that gets weird when you are using the repl / debugger to redefine things |
| 11:46 | CookedGryphon | justin_smith: it'd be cool if defn attached the source as metadata |
| 11:46 | justin_smith | CookedGryphon: it does |
| 11:46 | justin_smith | but that doesn't give you line number breaks inside it :) |
| 11:46 | CookedGryphon | oh, cool, well in that case I don't care what line it is in a file, as long as i can look at the source. |
| 11:46 | justin_smith | CookedGryphon: (source fn) |
| 11:46 | napper | justin_smith: redefine? Well, yeah, but if a user does that at run time, it's their prerogative - using in debugging would be ideal, redfined code at runtime, I agree can create issues |
| 11:46 | CookedGryphon | or is it that your stack traces no longer relate to anything |
| 11:47 | justin_smith | that's in the clojure.repl ns, so you may need to use that first |
| 11:47 | justin_smith | napper: this debugger lets you redefine things while debugging |
| 11:47 | napper | are we talking about cdt or your webui? |
| 11:48 | justin_smith | the webui is just a view of cdt |
| 11:48 | justin_smith | all the functionality, including changing remote definitions, is in cdt |
| 11:48 | napper | right |
| 11:49 | napper | I'm reading over the main-page. it looks like what I want is already accomplishable via the debug-repl |
| 11:49 | justin_smith | napper: I think the problem with that is it is swank |
| 11:49 | napper | oh |
| 11:50 | justin_smith | ritz tries to provide an alternative |
| 11:50 | justin_smith | but I couldn't make any sense of ritz |
| 11:53 | justin_smith | if your workflow is "I am starting the debugger and the debugged process as one action", then the nrepl ritz module probably does what you want |
| 11:53 | justin_smith | in my case, I am running ring, ring creates a repl I can interact with, and I want to fire up an external debugger to connect to it and investigate if something breaks |
| 11:54 | muhoo | http://www.youtube.com/watch?v=9m3lu59Cz4g |
| 11:54 | justin_smith | muhoo: nice |
| 11:54 | napper | eventually I'll be running ring, my next question is how can you pause execution. looking through cdt, it seems that might be pretty straightforward. - I think I have what I need. |
| 11:55 | dnolen | cemerick: yeah I don't think we should change the current behavior |
| 11:55 | justin_smith | napper: yeah, you can set a break, if you know how to specify the location |
| 11:55 | napper | justin_smith, is your webui public or closedsource? |
| 11:55 | justin_smith | napper: open source, but not really "there" yet |
| 11:55 | napper | I understand |
| 11:55 | napper | do let me know when it's there |
| 11:56 | justin_smith | someone else is doing the main development, I don't even know how much he has pushed as opposed to just mostly working on his box at this point |
| 11:56 | justin_smith | https://github.com/prismofeverything/schmetterling repo |
| 11:56 | justin_smith | may be a pile of bugs right now |
| 11:56 | cemerick | dnolen: hah, here I just finished a writeup on the ticket :-P |
| 11:57 | justin_smith | napper: it is something you would check out and run, standalone |
| 11:57 | justin_smith | not a lib you include |
| 11:58 | napper | this would be great for pointing it to production servers if anything ever went south |
| 11:58 | justin_smith | yeah, though you would need to open a tunnel with ssh -X |
| 11:58 | justin_smith | because you sure as hell don't want a dt-thread socket available to the outside world :) |
| 11:59 | dnolen | cemerick: also I don't really like the idea of adding any compiler support for this - just export a config function? |
| 11:59 | napper | hah |
| 11:59 | napper | i take it you've seen that before? |
| 12:00 | justin_smith | no, but it's something that could be a disaster |
| 12:00 | justin_smith | full control of your app's state |
| 12:00 | justin_smith | and full access and introspection |
| 12:00 | justin_smith | someone with malice could do a lot with that |
| 12:00 | lpvb | how do I use vector-of to create a filled vector of a specified length? |
| 12:01 | lpvb | (vector-of :int & elements) |
| 12:01 | lpvb | ,(vector-of :int) |
| 12:01 | clojurebot | [] |
| 12:01 | lpvb | ,(vector-of :int (repeat 5 0)) |
| 12:01 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.LazySeq cannot be cast to java.lang.Character> |
| 12:02 | justin_smith | ,(apply vector-of :int (repeat 3 6)) |
| 12:02 | clojurebot | [6 6 6] |
| 12:02 | justin_smith | lml |
| 12:04 | cemerick | dnolen: The original use case was being able to change test-time parameters. There are workarounds, including the config function notion, having a fixture that looks up params set from the test runner on window, etc. |
| 12:04 | lpvb | oh cool |
| 12:05 | justin_smith | lpvb: apply is good when a function expects a bunch of args at the end that you already have in a list |
| 12:05 | justin_smith | with how many varargs functions clojure has, this comes up a lot |
| 12:06 | cemerick | What ^:export does now is pretty surprising tho. If someone wants some low-hanging contrib fruit, documenting that @ https://github.com/clojure/clojurescript/wiki/Quick-Start#using-clojurescript-on-a-web-page (the only place I know of that mentions ^:export?) would be one such spot. |
| 12:06 | justin_smith | ,(apply vector-of int "Hello World") |
| 12:06 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 12:06 | justin_smith | erm |
| 12:07 | justin_smith | ,(apply vector-of :int (seq "hello world")) |
| 12:07 | clojurebot | [104 101 108 108 111 ...] |
| 12:07 | justin_smith | neato |
| 12:07 | dnolen | cemerick: you're one of the few people that have asked for this or been surprised by the behavior. ^:export is mostly used for exporting functions note constants that will be mutated as this isn't considered good CLJS style. The testing case is not even particularly interesting IMO since it's trivially worked around. |
| 12:07 | dnolen | s/note/not |
| 12:09 | dnolen | cemerick: it has come up once before in a different ticket I believe, but I'm not convinced any of this requires compiler changes. I think just make the documentation more clear is sufficient for now. |
| 12:10 | cemerick | dnolen: Fair enough, I'm not lobbying hard or anything. :-) My understanding of ^:export was that it was primarily there to provide entry points and to make providing JS-friendly APIs (where mutable properties are common). |
| 12:11 | cemerick | APIs easy* |
| 12:11 | dnolen | cemerick: I don't recall anyone suggesting ^:export for mutable properties, nor do I see such documented anywhere (could be wrong) |
| 12:12 | cemerick | dnolen: No, I inferred "JS APIs" => "mutable properties". |
| 12:13 | cemerick | I'll close the issue and leave a note potential workarounds, etc. |
| 12:13 | dnolen | cemerick: cool, thanks |
| 12:14 | technomancy | huh; I could have sworn the `hub` CLI tool had gist support in it; am I making that up? |
| 12:14 | nDuff | ...I've seen a separate ''gist'' tool |
| 12:15 | nDuff | perhaps its functionality has been split out from ''hub''. |
| 12:15 | Sigma | technomancy: not that I remember. there's a separate "gist" tool though |
| 12:15 | technomancy | oh, I was thinking of gist-mode for emacs |
| 12:16 | technomancy | which supports fetching but not cloning; oh well |
| 12:16 | Sigma | technomancy: patches welcome :) |
| 12:17 | deech | Hi all, how do I make a set with a custom comparator? |
| 12:17 | technomancy | Sigma: nice =) |
| 12:17 | Sigma | btw I'm considering (as of yesterday) implementing a tramp method for accessing gists. guess it might make the whole experience a bit better |
| 12:17 | faust45 | guys, how i can attache some static info to my deftype ? |
| 12:18 | TEttinger | deech, like sorted-set-by but not sorted? |
| 12:18 | technomancy | Sigma: huh... I never thought of it that way, but tramp can be considered a FUSE alternative in a way. |
| 12:18 | Sigma | technomancy: I already have one for git itself, sounds like a logicial next step :) |
| 12:19 | technomancy | that's wild =) |
| 12:19 | deech | TEttinger: I thought that function took a set and sorted it. Guess I was wrong. |
| 12:19 | justin_smith | tramp access to well designed RESTful apis all over the web would finally catch us all up to plan9 networking |
| 12:19 | faust45 | any ideas ? |
| 12:20 | technomancy | Sigma: lemme know if you ever end up tackling issues; that's the main pain point for me with github currently |
| 12:20 | faust45 | how attach static info to deftype ? |
| 12:20 | Sigma | technomancy: I guess the final step would be to reimplement magit over a tramp method that would use github API instead of local git commands. Then I can die |
| 12:21 | technomancy | Sigma: the technical term is "ascend" |
| 12:21 | justin_smith | faust45: you could make the data be a method that ignores the value of this and returns the data |
| 12:22 | faust45 | justin_smith: yes, but sounds strange |
| 12:23 | faust45 | justin_smith: i don't need behavior i need static data |
| 12:23 | justin_smith | (getStatic [this] {:foo "bar"}) |
| 12:23 | TEttinger | deech, fun stuff: ##(sorted-set-by #(= %1 %2) 1 1 1 2 2 3 3) |
| 12:23 | lazybot | ⇒ #{1 1 1} |
| 12:23 | justin_smith | a behavior can mimic static data :) |
| 12:23 | faust45 | ok thanks |
| 12:23 | justin_smith | faust45: or you could use genclass instead of deftype |
| 12:24 | justin_smith | they generate the same kind of thing under the hood |
| 12:24 | justin_smith | then you can have a final data member in the class itself |
| 12:24 | justin_smith | just think of how java would do it, then figure out the interop that would make that happen, because all this is defined by the java model |
| 12:34 | TimMc | faust45: I think you can attach :static to methods in a gen-class :methods form. |
| 12:45 | justin_smith | TimMc: is that the only way to make static methods? |
| 12:45 | justin_smith | I was looking at it, it seemed like you would only be able to define one :static key? |
| 12:46 | justin_smith | sorry |
| 12:46 | justin_smith | not :static |
| 12:46 | justin_smith | it's :state |
| 12:46 | justin_smith | or are these two separate things? |
| 12:46 | justin_smith | http://clojuredocs.org/clojure_core/clojure.core/gen-class |
| 12:46 | dobry-den | gen-class OO in clojure is fun |
| 12:47 | dobry-den | feels like some newfangled OO language |
| 12:47 | tbaldridge | for certain definitions of fun |
| 12:47 | dobry-den | ^ |
| 12:48 | dobry-den | funny* |
| 12:48 | justin_smith | clearly gen-class is missing the essential :laffs key |
| 12:48 | dobry-den | every time i use gen-class, i do the same google search to knit together the same 4 blog posts that show how to use it |
| 12:52 | lpvb | how do I split a vector into chunks of a specified length like [1 2 3 4 5 6 7 8 9] -> [[1 2 3] [4 5 6] [7 8 9]] |
| 12:52 | AimHere | lpvb > partition |
| 12:52 | rasmusto | ,(partition 3 (range 10)) |
| 12:52 | clojurebot | ((0 1 2) (3 4 5) (6 7 8)) |
| 12:53 | justin_smith | ,(partition-all 3 (range 10)) |
| 12:53 | clojurebot | ((0 1 2) (3 4 5) (6 7 8) (9)) |
| 12:53 | justin_smith | if you wanted all of it :) |
| 12:53 | rasmusto | ,(partition 3 1 (range 10)) |
| 12:53 | clojurebot | ((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6) ...) |
| 12:53 | rasmusto | if you want overlap |
| 12:53 | lpvb | thanks |
| 13:18 | danneu | I've never done something like this before - If I wanted to distribute Datomic along with my app.jar, what would that sort of thing look like? |
| 13:18 | llasram | I've come to the opinion that there's ~0 situations where `gen-class` is the right solution |
| 13:19 | danneu | Naively, I imagine my app.jar would boot another jvm that runs the transactor and java would handle things like shutting down the child jvm |
| 13:20 | mdrogalis | danneu: Can you put a wire between those 2 components? |
| 13:20 | mdrogalis | Just avoid all that. |
| 13:20 | danneu | What do you mean? |
| 13:20 | bitemyapp | yeah don't do that. |
| 13:21 | mdrogalis | Well, if I was to tell you that you can avoid the oddness that is multiple JVMs on a machine, doesnt that sound nice? |
| 13:21 | danneu | Basically, all I know is that I can't distribute a single jar that contains my app + datomic-db, so I'm looking up solutions |
| 13:21 | mdrogalis | danneu: What's your deployment scenario? |
| 13:22 | danneu | mdrogalis: I have a bitcoin node that uses datomic to store the blockchain. I'm not sure how to distribute it to other people |
| 13:24 | danneu | really, just a project that uses datomic as the db, and im not sure how to package it for end users |
| 13:24 | mdrogalis | danneu: I mean, do you *have* to ship just 1 jar? |
| 13:25 | mdrogalis | I dont think there's anything wrong with saying "Here's my app jar. Go stand up Datomic and they'll place nicely." |
| 13:25 | nDuff | ...folks don't try to ship PostgreSQL built into their applications. :) |
| 13:25 | mdrogalis | nDuff: Thanks, was trying to verbalize that. |
| 13:25 | bitemyapp | danneu: yeah I'm not buying that should be baked in. |
| 13:25 | bitemyapp | danneu: use environment variables so users can point your app at their datomic instance. |
| 13:26 | coventry | danneu: Could you pull in the datomic depepndency from your code using something like pomegranate? |
| 13:26 | bitemyapp | danneu: This is a good library for that: http://github.com/weavejester/environ/ |
| 13:26 | bitemyapp | coventry: dude. No. |
| 13:29 | danneu | nDuff: yeah, you're right. i'm just trying to arrive at the easiest solution for the end-user |
| 13:31 | lpvb | ,(replace {1 0} (vector-of :int 0xF0)) |
| 13:31 | clojurebot | [240] |
| 13:31 | lpvb | why is that not working |
| 13:31 | coventry | lpvb: What answer are you expecting? |
| 13:31 | lpvb | oh wait I get it now |
| 13:32 | lpvb | I thought the key was the index to replace |
| 13:33 | justin_smith | ,(replace {0 0} (vector-of :int 0xF0)) |
| 13:33 | clojurebot | [240] |
| 13:33 | justin_smith | ok, that I did not expect |
| 13:34 | justin_smith | ,((vector-of :int 0xF0) 0) |
| 13:34 | clojurebot | 240 |
| 13:35 | bitemyapp | justin_smith: what are you even doing that these experiments come to mind? seriously, wtf. |
| 13:35 | justin_smith | bitemyapp: it was lpvb's question |
| 13:35 | Morgawr | I have a static java method that can take 1, 2 or 3 parameters, I want to write a wrapper in clojure, but I can't get it to work with "apply" |
| 13:35 | bitemyapp | lpvb: okay, my question, applied to you. What the fuck? |
| 13:35 | Morgawr | (apply StaticClass/method args) doesn't work |
| 13:35 | lpvb | bitemyapp: ? |
| 13:35 | sritchie | Morgawr: you could write a macro that expands out into all the arities |
| 13:35 | bitemyapp | Morgawr: make a clojure function |
| 13:35 | coventry | "Here's a nickle, kid. Buy yourself your own goddamn repl." :-) |
| 13:35 | llasram | lpvb, justin_smith: `replace` replaces by value, not key |
| 13:35 | lpvb | I know that now |
| 13:36 | llasram | kk |
| 13:36 | noncom | what is the fastest and the most idiomatic way to add N same elements to a vector? |
| 13:36 | sritchie | Morgawr: but I think you need to recreate each one |
| 13:36 | Morgawr | I know I could do that but a one liner feels better, isn't there a way? |
| 13:36 | justin_smith | llasram: the doc string says key |
| 13:36 | mdrogalis | bitemyapp: Possibly relevant for encryption, by the way |
| 13:36 | justin_smith | oh, = key, not at key |
| 13:36 | Morgawr | I mean, I can't use "apply"? |
| 13:36 | justin_smith | never mind |
| 13:36 | sritchie | Morgawr: nope |
| 13:36 | danneu | noncom: conj with repeat? |
| 13:36 | Morgawr | why not? doesn't apply work with java methods? |
| 13:37 | noncom | danneu: is it the fastest? i can think of several ways, but i wonder which is the fastest... |
| 13:37 | danneu | ,(into [1 2 3] (repeat 5 :a)) |
| 13:37 | clojurebot | [1 2 3 :a :a ...] |
| 13:37 | bitemyapp | Morgawr: why would some random Java method implement IFn? |
| 13:37 | Morgawr | bitemyapp: I don't know how apply works, so I don't know why it wouldn't work ^^ |
| 13:37 | bitemyapp | Morgawr: it's not like java libraries are designed with Clojure integration in mind. |
| 13:37 | rasmusto | ,(replace {0xF0 1} (vector-of :int 0xF0)) |
| 13:37 | danneu | noncom: oh. in that case i would just mock up those several ways and bench them |
| 13:37 | clojurebot | [1] |
| 13:37 | bitemyapp | Morgawr: well...learn how Clojure works :) |
| 13:37 | bitemyapp | Morgawr: in particular, Seqable, IFn, etc. |
| 13:38 | Morgawr | I'll go check apply's source |
| 13:38 | bitemyapp | enables you to anticipate what should and shouldn't work, what makes sense, etc. |
| 13:38 | sritchie | to be fair that's what he's trying to do |
| 13:38 | noncom | danneu: yeah, looks liek.. |
| 13:38 | danneu | noncom: oh, you asked for the fastest |
| 13:38 | sritchie | Morgawr: a clojure function is an object, a first class object |
| 13:38 | noncom | yes, speed is the criterium |
| 13:38 | sritchie | that implements IFn |
| 13:39 | coventry | Morgawr: The only way I can think of doing it in one line is uglier than using multiple lines. |
| 13:39 | sritchie | a static method isn't first class, it's defined on a particular class - |
| 13:39 | Morgawr | I see |
| 13:39 | Morgawr | makes sense |
| 13:39 | sritchie | so you have to make a first-class clojure function that delegates through in each arity |
| 13:39 | Morgawr | alright, thanks |
| 13:39 | justin_smith | lpvb: this is what you wanted, I think: |
| 13:39 | justin_smith | ,(assoc (vector-of :int 0xF0) 0 0) |
| 13:39 | clojurebot | [0] |
| 13:40 | lpvb | I know how to use assoc, I thought I could use replace to do a list of assocs at a time though |
| 13:40 | justin_smith | assoc is varargs |
| 13:40 | justin_smith | ,(assoc (vector-of :int 0xF0) 0 0 1 6) |
| 13:40 | clojurebot | [0 6] |
| 13:40 | lpvb | ah I keep forgetting most clojure functions like this have varargs |
| 13:41 | llasram | Morgawr: Not necessarily recommended, but you can use reflection to wrap methods as functions w/ correct arities, then `apply` those functions |
| 13:41 | justin_smith | ,(apply < (range 42)) |
| 13:41 | clojurebot | true |
| 13:41 | Morgawr | llasram: sounds like a lot of work for nothing |
| 13:41 | llasram | Morgawr: https://github.com/llasram/method-fn for a proof-of-concept |
| 13:41 | llasram | haha |
| 13:41 | llasram | Well, depends on what you're trying to do |
| 13:42 | Morgawr | llasram: I was just being lazy |
| 13:42 | danneu | noncom: is (concat [1 2 3] (repeat n :a)) too slow? |
| 13:42 | Morgawr | hoping I could get a simple and elegant one-liner for a java wrapper |
| 13:42 | llasram | I see |
| 13:42 | coventry | As long as we're proposing awkward ideas, there's (eval `(StaticClass/method ~@args)). :-) |
| 13:42 | Morgawr | but it's just a function with 3 different parameter combinations |
| 13:42 | Morgawr | so I can just wrote those, no biggie |
| 13:43 | Morgawr | coventry: that's actually interesting |
| 13:43 | coventry | Morgawr: Yeah, it's interesting, but people will look askance if you do that. |
| 13:43 | justin_smith | eval is a big gun for such a small rabbit |
| 13:43 | noncom | danneu: umm, looks quite fast.. "Elapsed time: 0.08244 msecs" after warm-up |
| 13:44 | noncom | thats faster than with (into) |
| 13:44 | Morgawr | I mean, wouldn't it just possible to do (defmacro wrapped-method [& args] `(Static/Methodname ~@args)) ? |
| 13:44 | danneu | noncom: right, into uses conj for each element. concat does it all at once |
| 13:44 | Morgawr | be possible* |
| 13:44 | llasram | noncom, danneu: Er, `concat` is lazy, so just calling `concat` does almost nothing |
| 13:45 | coventry | Morgawr: You lose function composition that way. |
| 13:45 | Morgawr | mmm.. true |
| 13:46 | noncom | llasram: well, i tried it and it printed the output to the console, so it actualle did evaluate it. however, i wonder, if it did before or after (time) :) |
| 13:46 | danneu | noncom: you can realize it trivially with `count` or `dorun` |
| 13:46 | justin_smith | noncom: if you are wondering what is efficient, use criterium |
| 13:46 | llasram | noncom: If you use criterium for benchmarking, it handles many of these issues |
| 13:47 | justin_smith | also, criterium is very simple to use, so there is no excuse |
| 13:48 | Morgawr | is there any downside in using eval? |
| 13:48 | llasram | Especially if you also use hugod's alembic, because then you can slurp it into any REPL :-) |
| 13:48 | danneu | sometimes you've just gotta grind it out on that dollar menu with (time (dotimes [_ N] ...)) |
| 13:48 | llasram | danneu: 100% in disagreement! |
| 13:48 | justin_smith | Morgawr: it creates a whole environment context, we were using eval in our templates and when we switched to read our performance shot up more than an order of magnitude |
| 13:49 | danneu | ;) |
| 13:49 | justin_smith | danneu: that would make sense if criterium somehow cost money |
| 13:49 | Morgawr | this is just for a simple function (binding to OpenAL) that creates an audio device, it's used just in the initialization of a game engine |
| 13:49 | Morgawr | I'm wondering how lazy I can be |
| 13:49 | danneu | it's nice to have criterium's `bench` and `quick-bench` imported into your util namespace so theyre always handy |
| 13:49 | Morgawr | as in, I know I'm talking about bike shedding atm |
| 13:49 | danneu | quick-bench because time is money |
| 13:50 | Morgawr | but honestly unless there's any security/consistency/stability problem, if it's only just losing a bit of performance, then I'd say that eval looks more elegant |
| 13:50 | Morgawr | unless I'm missing something |
| 13:50 | justin_smith | client data sneaking arbitrary code into the string? |
| 13:50 | justin_smith | hah |
| 13:50 | Morgawr | it's a library, it's not an end-user application |
| 13:51 | Morgawr | as in, other developers call that function |
| 13:51 | Morgawr | if they want to break their own application, it's not my fault D: |
| 13:51 | lpvb | what complexity is concat on two vectors? |
| 13:51 | justin_smith | just covering the bases, mentioning other downsides that may apply :) |
| 13:51 | Morgawr | true true |
| 13:52 | justin_smith | lpvb: they are implemented by narrow hash trees, with something like 7 items on each level iirc |
| 13:52 | coventry | Morgawr: If you want to use eval, you probably actually want something more like (eval (list* StaticClass/method args)), so that it works at runtime. |
| 13:52 | justin_smith | lpvb: http://hypirion.com/musings/understanding-persistent-vector-pt-1 |
| 13:53 | Morgawr | coventry: alright, thanks |
| 13:53 | TimMc | lpvb: O(1), i think |
| 13:53 | coventry | Morgawr: And wash your hands afterwards. |
| 13:53 | TimMc | (It's lazy.) |
| 13:53 | justin_smith | TimMc: no way, it is log something |
| 13:53 | Morgawr | doesn't seem to be working though |
| 13:53 | noncom | danneu, llasram: thanks, i'll check the criterium out! |
| 13:54 | Morgawr | should it be (list* 'StaticClass/metod args) ? |
| 13:54 | Morgawr | with the quote? |
| 13:54 | coventry | Morgawr: Right. |
| 13:54 | Morgawr | ah ok, at least I understand what it does ;) thanks |
| 13:55 | TimMc | justin_smith: concat returns a lazy seq; I'm pretty sure it does nothing involving the elements of input vectors |
| 13:55 | coventry | ,(eval (list* 'System/getProperty '("java.vm.version"))) |
| 13:55 | clojurebot | #<Exception java.lang.Exception: SANBOX DENIED> |
| 13:55 | Morgawr | haha |
| 13:55 | TimMc | lpvb: Concat returns a seq; if you want a vector from a seq you have to call vec on it. If you want to combine two vectors into another vector, the efficient thing is to use clojure.core/into. |
| 13:56 | TimMc | &(into [1 2 3] [4 5 6]) |
| 13:56 | lazybot | ⇒ [1 2 3 4 5 6] |
| 13:56 | justin_smith | TimMc: ok, now I get it |
| 13:56 | TimMc | That should be something like O(n) or O(n log n). |
| 13:56 | noncom | conventry: what is the difference of list* and list? |
| 13:56 | justin_smith | so since concat only returns a seq, you look at the complexity of realizing the seq (if it needs full realization) |
| 13:57 | coventry | noncom: &[(list* 'System/getProperty '("java.vm.version")) (list 'System/getProperty '("java.vm.version"))] |
| 13:57 | justin_smith | realizing a seq will be O(n) for the length you need to realize |
| 13:57 | danneu | I see that `into` uses transients |
| 13:58 | noncom | conventry: sorry i don't get it.. |
| 13:58 | danneu | justin_smith: yeah, i made that mistake too. i didn't think about how concat is a lazy-seq of `cat`s |
| 13:58 | coventry | noncom: list* splices the last argument into the list, like ~@ in a syntax quote. |
| 13:58 | noncom | oh! |
| 13:58 | coventry | ,[(list* 'System/getProperty '("java.vm.version")) (list 'System/getProperty '("java.vm.version"))] |
| 13:58 | clojurebot | [(System/getProperty "java.vm.version") (System/getProperty ("java.vm.version"))] |
| 13:59 | cYmen | Is there a list of clojure user groups somewhere? |
| 13:59 | coventry | Hmm, I could have used juxt, there. :-) |
| 14:00 | justin_smith | coventry: so is what differentiates list* from cons the resulting data type? |
| 14:01 | Morgawr | talking about clojure user groups... anybody from Amsterdam/Netherlands going to wednesday's clojure meeting in Amsterdam? |
| 14:01 | danneu | Speaking of juxt, I often do this: ((juxt :a :b :c) {:a 1, :b 2, :c 3}) -> [1 2 3]. Is there a different way to do that? |
| 14:01 | coventry | justin_smith: It's a series cons under the covers. |
| 14:01 | coventry | ~def list* |
| 14:01 | Morgawr | danneu: vals |
| 14:01 | Morgawr | if you want all of them, of course |
| 14:02 | justin_smith | coventry: ahh, so it is a reverse varargs with the conses in front |
| 14:02 | danneu | My trouble with `cons` is that I don't know what to do with the resulting Cons object |
| 14:02 | cYmen | danneu: the result is a list not a cons object ;) |
| 14:03 | cYmen | well...I guess it could also be a tree |
| 14:03 | cYmen | nevermind ;) |
| 14:03 | danneu | ,(class (cons 1 [2 3])) |
| 14:03 | clojurebot | clojure.lang.Cons |
| 14:03 | justin_smith | ,(map type [(list* 1 [2]) (cons 1 [2])]) |
| 14:03 | clojurebot | (clojure.lang.Cons clojure.lang.Cons) |
| 14:04 | amalloy | danneu: ##(map {:a 1, :b 2, :c 3} [:a :b :c]) |
| 14:04 | lazybot | ⇒ (1 2 3) |
| 14:05 | llasram | justin_smith: Yeah, `list*` returning a `Cons` is kind of brutal |
| 14:05 | Morgawr | ,(vals {:a 1 :b 2 :c 3}) |
| 14:05 | clojurebot | (1 3 2) |
| 14:05 | Morgawr | :V |
| 14:06 | justin_smith | llasram: from an implementation perspective, it is perfectly understandable though - a list is just a cons tacked onto another cons |
| 14:07 | llasram | justin_smith: That's actually not quite true in the Clojure implementation. Clojure's actual persistent list is `Counted` and supports acts as a (counted) stack with `conj`, `peek`, and `pop` |
| 14:08 | justin_smith | oh, interesting |
| 14:09 | llasram | If you just need a seq, `Cons`es work fine, but sometimes you really want a PersistentList |
| 14:09 | justin_smith | ,(pop (into () (list* 1 [2]))) |
| 14:09 | clojurebot | (1) |
| 14:09 | justin_smith | I never though I would need (into ()) |
| 14:09 | llasram | I think then you might as well just ##(apply list 1 [2]) |
| 14:09 | lazybot | ⇒ (1 2) |
| 14:10 | justin_smith | llasram: yeah, probably true |
| 14:10 | llasram | Oh, yeah -- `into` will end up reversing the list |
| 14:10 | danneu | reduces with conj |
| 14:10 | justin_smith | ahh |
| 14:10 | justin_smith | fun! |
| 14:11 | TimMc | list* is awful |
| 14:11 | justin_smith | it seems so! |
| 14:11 | amalloy | TimMc: aw, list* is great! |
| 14:12 | TimMc | The funcionality is nice; the name is not. |
| 14:12 | TimMc | and the doc |
| 14:12 | amalloy | it's much nicer than repeated conses, and it's not like i've ever in my life cared that it doesn't return a List |
| 14:12 | amalloy | if it did, i'd have to stop using it |
| 14:14 | Raynes | TimMc: Don't be so mean to list*. |
| 14:14 | amalloy | (defn all-integers [n] (lazy-seq (list* n (- n) (all-integers (inc n))))), for example, suddenly can't use list* |
| 14:14 | Raynes | He doesn't mean to be different. |
| 14:15 | coventry | What are the drawbacks to list*? |
| 14:15 | mischov | He's just looking for a connection.. :( |
| 14:15 | llasram | coventry: It doesn't actually return a list |
| 14:15 | amalloy | coventry: whenever you use it, you have to listen to someone in irc reminding you it doesn't return a list |
| 14:15 | llasram | heh |
| 14:15 | TimMc | (inc amalloy) |
| 14:15 | lazybot | ⇒ 76 |
| 14:15 | llasram | (inc amalloy) |
| 14:15 | lazybot | ⇒ 77 |
| 14:15 | danneu | haha |
| 14:17 | technomancy | no, it's the other way around |
| 14:17 | amalloy | anyway, it does return a list*, so what's the problem? |
| 14:17 | amalloy | * sequence |
| 14:17 | technomancy | list? is the rubbish one; list* is entirely reasonable |
| 14:17 | TimMc | hrmph |
| 14:17 | technomancy | focusing on concrete types is misguided |
| 14:18 | TimMc | Actually, the problem is memoize. |
| 14:18 | amalloy | yeah, list? is awful. i love to agree with technomancy when he wanders in to say that |
| 14:18 | llasram | I'm sure this will never happen to me again, but I once did want the behavior `pop` documents for "a list", and was surprised the result of `list*` didn't work with it |
| 14:18 | justin_smith | we should have a database of functions in core clojure and everyone's yes or no opinions on them |
| 14:18 | justin_smith | then we could find the winner |
| 14:19 | justin_smith | juxt for president! |
| 14:19 | llasram | ~juxt |
| 14:19 | clojurebot | juxt is the bestest option though if it doesn't weird you out |
| 14:19 | technomancy | whaaat why is pop a c.l.RT method? |
| 14:19 | llasram | Aww, not the one I was hoping for |
| 14:19 | justin_smith | ~juxt |
| 14:19 | clojurebot | juxt is a little hard to grok but it's the best thing ever |
| 14:19 | rasmusto | ~grok |
| 14:19 | clojurebot | grok is a little hard to juxt but it's the best thing ever |
| 14:19 | llasram | lol |
| 14:19 | coventry | It would be pretty handy to have a table of which clojure.core functions suck and why, actually. |
| 14:19 | mdrogalis | Hah |
| 14:20 | ToBeReplaced | ~complement |
| 14:20 | clojurebot | It's greek to me. |
| 14:20 | justin_smith | coventry: we could make a funcation that puts a :sucks and a :rocks metadata on each function |
| 14:20 | technomancy | am I right in recalling that contains? isn't as bad as it used to be? |
| 14:20 | ToBeReplaced | as long as "flatten" is marked with :worst |
| 14:21 | justin_smith | yes! |
| 14:21 | amalloy | technomancy: i forget if it's contains? or get |
| 14:21 | ToBeReplaced | what's wrong with either of those? |
| 14:21 | justin_smith | maybe if we could just inc or dec core functions in irc |
| 14:21 | coventry | justin_smith: I think we should hack the compiler so that it instruments code with calls to lazybot to (inc) and (dec) the author when :sucks and :rocks functions are used. |
| 14:21 | technomancy | ToBeReplaced: contains? is actually contains-key? |
| 14:21 | justin_smith | lol |
| 14:21 | lpvb | how do I coerce the types of record fields, do I just type hint them? |
| 14:21 | technomancy | ToBeReplaced: and it's worse because there's a .contains method that actually does what you'd expect |
| 14:22 | ToBeReplaced | yeah, that doesn't smell fishy to me for some reason |
| 14:22 | technomancy | I think at least now it throws instead of silently returning false |
| 14:22 | ToBeReplaced | throws on what, nil/ |
| 14:23 | justin_smith | non-int key on a sequential type |
| 14:23 | ToBeReplaced | ,(contains? [] :foo) |
| 14:23 | clojurebot | false |
| 14:23 | amalloy | ,(contains? 'q :foo) |
| 14:23 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: contains? not supported on type: clojure.lang.Symbol> |
| 14:24 | justin_smith | but for that case, I think it always threw |
| 14:24 | amalloy | no |
| 14:24 | justin_smith | oh |
| 14:24 | justin_smith | never mind then |
| 14:24 | amalloy | &(contains? 'q :foo) |
| 14:24 | lazybot | ⇒ false |
| 14:24 | ToBeReplaced | amalloy: what's the diff between those two commands? |
| 14:25 | ToBeReplaced | the & vs the , |
| 14:25 | amalloy | did you notice anything different happen when i used them? |
| 14:25 | coventry | &*clojure-version* |
| 14:25 | lazybot | ⇒ {:major 1, :minor 4, :incremental 0, :qualifier nil} |
| 14:25 | coventry | ,*clojure-version* |
| 14:25 | clojurebot | {:interim true, :major 1, :minor 6, :incremental 0, :qualifier "master"} |
| 14:25 | ToBeReplaced | kk sweet |
| 14:30 | TimMc | ToBeReplaced: The bots have different Clojure versions in their sandbox evaluators. |
| 14:30 | Raynes | Funfact: I have 396 public pastes and 395 private pastes. This was not intentional.w |
| 14:31 | Raynes | (on refheap) |
| 14:31 | amalloy | Raynes: really? that number seems way too low |
| 14:32 | amalloy | or do you mean, just pastes you, personally, made |
| 14:32 | Raynes | amalloy: Me of course. |
| 14:32 | cYmen | It says here that the vector returned by subvec shares structure with the original one. Isn't that rather odd considering all the immutabiliy everywhere? |
| 14:32 | Raynes | If Refheap only had 791 pastes, I should probably have given up on it ages ago :P |
| 14:33 | dnolen | cYmen: Clojure data structures generally share structure |
| 14:33 | cYmen | dnolen: But that doesn't matter if I never mutate any... |
| 14:33 | justin_smith | cYmen: that is one of the advantages of immutability, is being able to safely share structure whenever possible |
| 14:33 | justin_smith | in terms of memory usage |
| 14:34 | dnolen | cYmen: structure sharing is how/why Clojure data structures perform well |
| 14:34 | amalloy | well, not so much memory usage as time, justin_smith |
| 14:34 | justin_smith | maybe make that saving graces, making up for the extra mem usage because you don't update in place |
| 14:34 | technomancy | cYmen: what you pasted is not odd, but subvec does have some weirdness in its trade-off between efficiency and possible memory leaks |
| 14:34 | danneu | cYmen: mutability is opt-in. |
| 14:35 | amalloy | usually you just throw away the old version, so the fact that you share structure with it impacts only speed, not space |
| 14:35 | amalloy | of course, you don't *have* to throw it away, which is the point of immutability |
| 14:35 | technomancy | amalloy: except it's a reference to the whole original vector, not just part |
| 14:35 | amalloy | technomancy: i'm not talking about subvec; that's your hobby horse |
| 14:36 | amalloy | just sharing in general |
| 14:36 | technomancy | oh, I didn't bring it up |
| 14:36 | justin_smith | see, more evidence that we need a :sucks or :rocks metadata on every core function |
| 14:36 | technomancy | justin_smith: dunno; I think subvec is more nuanced. needs :perilous. |
| 14:36 | cYmen | so if I go (let [foo [1 2 3] bar (subvec foo 2)] ...) I can screw myself because changes to foo or bar also change the other? |
| 14:37 | technomancy | cYmen: no |
| 14:37 | TimMc | :docs-actually-important |
| 14:37 | technomancy | you can screw yourself up because of a memory leak, but you can't change either vector |
| 14:37 | amalloy | cYmen: it's impossible to change foo or bar |
| 14:37 | amalloy | so that doesn't matter |
| 14:38 | cYmen | so how is immutability opt-in? |
| 14:38 | justin_smith | cYmen: you can use java arrays |
| 14:38 | justin_smith | or java lists |
| 14:38 | danneu | mutability* |
| 14:38 | TimMc | You can change vectors if you do some very naughty things, but you really can't do it by accident. |
| 14:38 | technomancy | cYmen: just try to modify a clojure vector |
| 14:38 | TimMc | cYmen: *Mutability* is opt-in. |
| 14:39 | danneu | cYmen: You can also 'mark' clojure datastructures as "mutable" http://clojure.org/transients |
| 14:39 | justin_smith | it is opt in, in that you can choose what data structures you use |
| 14:39 | amalloy | danneu: that is totally wrong. transients do not make data structures mutable |
| 14:39 | danneu | damn |
| 14:39 | amalloy | they permit the data structures to use mutability as an optimization; they do not allow you to mutate them without restraint |
| 14:40 | technomancy | welllll. not *totally* wrong. |
| 14:40 | technomancy | just misses the point. |
| 14:40 | danneu | yeah, it was too haste a simplification |
| 14:40 | Raynes | amalloy technomancy fight: go! |
| 14:40 | danneu | too dumb* |
| 14:40 | danneu | i really just wanted to share the link |
| 14:40 | nDuff | ...more than that, one can't assume that calculating a mutated version of a transient will change it. |
| 14:40 | nDuff | one simply can't assume that doing so _won't_. |
| 14:41 | cYmen | Where is #clojure-noobs? :) |
| 14:41 | danneu | right hurr |
| 14:41 | danneu | right hurr with me, homie |
| 14:43 | TimMc | Hmm, what's this TransactionalHashMap thingy? |
| 14:43 | justin_smith | technomancy: http://memegenerator.net/instance/42894672 |
| 14:43 | TimMc | public TransactionalHashMap() { this(421); } Nothing like a magic number to spice things up. |
| 14:44 | TimMc | https://github.com/clojure/clojure/blob/clojure-1.5.1/src/jvm/clojure/lang/TransactionalHashMap.java |
| 14:44 | technomancy | justin_smith: it's like you read my mind |
| 14:44 | justin_smith | or maybe your words on irc |
| 14:45 | technomancy | it's another possibility |
| 14:45 | danneu | Question: Some contributors on my project have started bikeshedding about my preference to refer to coordinates as {:x _, :y _} instead of a tuple [x y]. [x y] is only nice if you're always destructuring it. but otherwise, (coords 0) and (coords 1) are heinous to my eyes. |
| 14:46 | justin_smith | danneu: I agree, I even do :x :y :x' :y' for quads |
| 14:46 | danneu | thanks. bro-support. i'll remain adamant |
| 14:46 | justin_smith | then you can just do a {:keys [x y x' y']} and be done with it |
| 14:46 | justin_smith | destructuring ftw |
| 14:47 | TimMc | https://groups.google.com/forum/#!msg/clojure/A9Y9wml49_s/EUF4E43PJRIJ |
| 14:53 | cYmen | Could somebody please explain this to me: Also, in some cases keys can be used as functions of maps. For example, keyword keys can, but string and integer keys cannot. |
| 14:54 | `cbp | ,(:a {:a 1}) |
| 14:54 | clojurebot | 1 |
| 14:54 | cYmen | I apparently have no useful notion of what a keyword is internally. |
| 14:54 | cYmen | Because I am very surprised that it can be looked up in a way that allows using it as a function. |
| 14:54 | cYmen | Wouldn't that require knowing that it is in a map? |
| 14:55 | justin_smith | cYmen: it is an object, that is callable |
| 14:55 | justin_smith | it has the right method to try and look itself up if the arg is a map or struct |
| 14:56 | tbaldridge | cYmen: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java it's pretty simple stuff |
| 14:56 | `cbp | cYmen: here https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java#L24 |
| 14:56 | `cbp | :-( |
| 14:57 | poppingtonic | Hello |
| 14:57 | `cbp | hi |
| 14:58 | poppingtonic | Is ClojureScript One still relevant? I'm working through it, but the instructions in the Getting Started guide aren't working out... |
| 14:59 | poppingtonic | I'm not sure what needs to be fixed |
| 14:59 | tbaldridge | poppingtonic: it was replaced by Pedestal App |
| 14:59 | tbaldridge | poppingtonic: http://pedestal.io/ |
| 15:02 | cYmen | tbaldridge, `cbp: thanks |
| 15:07 | danneu | tbaldridge: it seems like https://github.com/magomimmo/modern-cljs is more of a Clojurescript One surrogate (a ground-up tutorial) |
| 15:08 | tbaldridge | danneu: true, I was just stating that the author of Pedestal App is the same as ClojureScript One. |
| 15:09 | TimMc | cYmen: It's more that keyword-as-function and map-as-function are convenient ways to call get. |
| 15:09 | tbaldridge | Brenton Ashworth dropped ClojureScript one when he started on the Pedestal App code, so one could be considered the spiritual successor of the other. |
| 15:10 | cYmen | TimMc: I totally get map as function but the benefit of allowing to turn the function and the argument around elude me. |
| 15:11 | ToxicFrog | I've actually gotten into the habit of using (:key map) and I'm not sure why. |
| 15:11 | `cbp | cYmen: so you can get the same attribute from many maps using the function `map` and other such things |
| 15:12 | danneu | cYmen: (map :username users) |
| 15:12 | justin_smith | also filtering by key (filter :key [{:key false} {} {:key true} {:key 1}]) |
| 15:12 | cYmen | hm... as opposed to #(% :foo) ?well I mean...why not ..whatever I won't be confused by it any longer! harr! |
| 15:12 | justin_smith | or even something like (filter (comp zero? :key) coll) |
| 15:13 | justin_smith | that gets all items with :key that is 0 |
| 15:13 | justin_smith | very handy |
| 15:13 | danneu | cYmen: there are some other good cases that are just hard to think of on the spot |
| 15:14 | `cbp | like avoiding null pointer exceptions |
| 15:14 | lpvb | is there a table somewhere of clojure data structure complexities |
| 15:14 | danneu | `cbp: that's a good pt i often take for granted |
| 15:15 | danneu | ,(:a nil) |
| 15:15 | clojurebot | nil |
| 15:20 | bja | apparently we can now set! *print-fn* in cljs. Whenever that support landed was a good day. |
| 15:21 | danneu | Is there a good place to manipulate the jvm state like inserting a provider (Security/insertProviderAt (BouncyCastleProvider.) 1) |
| 15:21 | danneu | A central place* |
| 15:21 | lpvb | ,(range \a \z) |
| 15:21 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number> |
| 15:23 | lpvb | ,(map char (range (int \a) (inc (int \z)))) |
| 15:23 | clojurebot | (\a \b \c \d \e ...) |
| 15:23 | poppingtonic | tbaldridge: ok, pedestal is a great starter |
| 15:24 | danneu | lpvb: frankly i like (seq "abcdef...xyz") better |
| 15:27 | TimMc | &(map (comp char (partial + 16r61)) (range 26)) |
| 15:27 | lazybot | ⇒ (\a \b \c \d \e \f \g \h \i \j \k \l \m \n \o \p \q \r \s \t \u \v \w \x \y \z) |
| 15:27 | TimMc | ^ magic numbers like the palindromic 16r61 are just better :-P |
| 15:28 | lpvb | ,16r61 |
| 15:28 | clojurebot | 97 |
| 15:28 | TimMc | 61 is 97 in base (radix) 16 |
| 15:29 | lpvb | I know |
| 15:29 | lpvb | why not just |
| 15:29 | lpvb | ,0x61 |
| 15:29 | clojurebot | 97 |
| 15:30 | TimMc | Because palindromes! |
| 15:30 | lpvb | lol |
| 15:30 | TimMc | Exactly. |
| 15:30 | danneu | isn't it so you can use decimal 26 in the range? |
| 15:30 | danneu | oh |
| 15:31 | danneu | hope a convo starts so thatll get pushed above the fold. |
| 15:32 | TimMc | &(map read-string (for [n (range 10)] (str 1 n \r n 1))) |
| 15:32 | lazybot | ⇒ (1 12 25 40 57 76 97 120 145 172) |
| 15:32 | lpvb | how do I define namespace privte constants? |
| 15:32 | lpvb | (def- x 5) doesn't work |
| 15:33 | lpvb | (defn- x [] 5) is tedious |
| 15:33 | llasram | (def ^:private foo ...) |
| 15:33 | TimMc | defn- is just sugar for defn ^:private |
| 15:34 | TimMc | (Macro sugar, not reader sugar.) |
| 15:35 | TimMc | lpvb: Private vars are overrated; people will argue about this, but you should know that it's still easy to get ahold of private vars from outside of the namespace. |
| 15:35 | lpvb | seems like a def- macro should be included by default |
| 15:35 | lpvb | unless that isn't idiomatic |
| 15:35 | tbaldridge | (inc TimMc) |
| 15:35 | lazybot | ⇒ 52 |
| 15:35 | justin_smith | lpvb: information hiding is not very popular with clojure |
| 15:35 | llasram | I think people decided that having separate private variations for everything was a bad idea |
| 15:35 | tbaldridge | private vars are just wrong, imo |
| 15:35 | llasram | I just use ^:private even for defn |
| 15:35 | danneu | yeah me too |
| 15:35 | llasram | tbaldridge: Er. Why so? |
| 15:36 | mdrogalis | There was a good talk by Stu Halloway about why. Can't remember which one. |
| 15:36 | tbaldridge | llasram: they make code harder to test, and manage imo. It's much better to put your public API in a different ns. Put all the "private" stuff somewhere else. |
| 15:36 | mdrogalis | It was just a slide or two, but he nailed it.. |
| 15:36 | danneu | :private is mostly helpful for me as the developer since a namespace is otherwise an interleave of "public" functions and helper functions |
| 15:36 | TimMc | ,@#'*loaded-libs* |
| 15:36 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve var: *loaded-libs* in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:37 | danneu | Not :private, but the idea of private |
| 15:37 | `cbp | (ns cant.touch.this) |
| 15:37 | TimMc | ,@#'clojure.core/*loaded-libs* |
| 15:37 | clojurebot | #<Ref@1071e40: #{clojure.core.protocols clojure.instant clojure.java.io clojure.repl clojure.string ...}> |
| 15:37 | TimMc | ,clojure.core/*loaded-libs* |
| 15:37 | clojurebot | #<CompilerException java.lang.IllegalStateException: var: clojure.core/*loaded-libs* is not public, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:37 | danneu | in fact, it's hard to scan a clojure namespace for the intended entry-points. |
| 15:38 | lpvb | mdrogalis: can you show me the slides? |
| 15:38 | mikerod | mdrogalis: I'd be interested in these slides |
| 15:38 | TimMc | lpvb: All it does is control what is exported from the namespace when it is refer'd by another. |
| 15:38 | mdrogalis | lpvb: Looking.. Not successful yet. |
| 15:39 | mikerod | I've struggled over the idea of no :private vars |
| 15:39 | mikerod | hard to say it is frowned upon when it is done in clojure.core though right |
| 15:39 | llasram | tbaldridge: I could see that if you're testing private functions. Usually functions I mark as :private I see no value in testing independently |
| 15:39 | logic_prog | we have number? |
| 15:40 | logic_prog | is there a bool? or boolean? |
| 15:40 | `cbp | there is no bool? |
| 15:40 | `cbp | ahem, there is no `bool?` |
| 15:40 | tbaldridge | llasram: I just don't see a reason to restrict code for no apparent reason. Putting private vars into foo.impl.bar is a much better I idea. |
| 15:40 | tbaldridge | llasram: then it's just normal code, why does it have to be special? |
| 15:41 | TimMc | mikerod: clojure.core is not a good example -- there's some weird-ass code in there |
| 15:41 | mikerod | TimMc: fair enough |
| 15:42 | TimMc | It's also supposed to be fairly stable, so minorly bad decisions do not get corrected. |
| 15:42 | logic_prog | wtf |
| 15:42 | logic_prog | there is no bool? |
| 15:42 | mikerod | I have started questioning myself when I want to do a defn- |
| 15:42 | logic_prog | how do I check if a varaible is a bool in java? |
| 15:43 | logic_prog | maybe insanity like (== x (not (not x)) ? |
| 15:43 | `cbp | logic_prog: if by that you mean clojure: (or (false? x) (true? x)) |
| 15:43 | TimMc | &(== true (not (not 5))) |
| 15:43 | lazybot | java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number |
| 15:43 | mikerod | I start thinking *maybe I shouldn't need so many one-off-specific-case private implementation functions* |
| 15:43 | tbaldridge | logic_prog: perhaps instance? |
| 15:43 | TimMc | &(= true (not (not 5))) |
| 15:43 | lazybot | ⇒ true |
| 15:43 | llasram | tbaldridge: I see it mostly as a hint that a function is internal. Putting in a separate namespace gets the same result, but having a separate ns & file seems like a heavier solution programmer-wise than just a :private annotation |
| 15:44 | mikerod | private function needed? `letfn` local binding |
| 15:44 | tbaldridge | llasram: I hear that, I just hate it whenever I decide to tap into someone's library and find out something is private, because they thought they knew more about it than I did. :-P |
| 15:44 | logic_prog | `cbp: nice, thanks |
| 15:44 | mdrogalis | Dang, I can't find it. He was making a point that if you only emit X amount of information, you can only perceive, at most X information |
| 15:44 | tbaldridge | ,(instance? Boolean true) |
| 15:44 | TimMc | I tend to use :private if *most* of my namespace is intended to be public and people should be able to use ns-publics to browse it. |
| 15:44 | clojurebot | true |
| 15:44 | mdrogalis | And private minimizes X |
| 15:44 | tbaldridge | ,(instance? Boolean false) |
| 15:44 | clojurebot | true |
| 15:44 | llasram | tbaldridge: I feel the same way in languages like Java, but I've never had a problem accessing a :private Clojure var when I needed it :-) |
| 15:44 | TimMc | I also make dangerous fns private -- ones that back safer interfaces. |
| 15:45 | mikerod | private functions are sort of a "code smell" of non-reusable code aren't they? :) |
| 15:45 | TimMc | If I have only a couple of API fns in a namespace, I just list them in the namespace's docstring and default to leaving things public. |
| 15:45 | mikerod | I guess not if you are using it all over in a lib of some sort, but you don't wnat others to get involved with it |
| 15:46 | mdrogalis | There are probably more valuable problems you can spend your brain cycles on that something small like this :) |
| 15:46 | mdrogalis | Than* |
| 15:46 | noonian | yeah i think they are mainly used to hide things that aren't part of the public api |
| 15:46 | TimMc | The problem is that namespaces conflate namespacing and APIs. |
| 15:46 | TimMc | APIs/modules |
| 15:48 | mikerod | true |
| 15:50 | dnolen | tbaldridge: it seems it would be possible to improve core.async source map support w/o waiting on that ticket no? but I guess you would need to change core.async macros to pass around line/col info |
| 15:51 | tbaldridge | dnolen: yeah I could use some help on that. I had a patch that passed around line/col info but it doesn't go far enough. |
| 15:51 | dnolen | tbaldridge: ok cool is this in a branch somewhere? |
| 15:52 | tbaldridge | dnolen: from what I can tell, there's a general issue with how metadata is handled in Clojure. I haven't figured it out yet. |
| 15:52 | tbaldridge | dnolen: not yet, I'll try to get it up soon |
| 15:53 | dnolen | tbaldridge: I guess I don't see how this could be true since macros seems to ok w/ source maps for the most part? |
| 15:53 | dnolen | "seem to be ok" |
| 15:55 | bja | has anyone seen: "Uncaught Error: URI file:/robots.txt is invalid for field ppu " out of the browser repl lately? |
| 15:55 | bja | I get it when I attempt to clojure.browser.repl/connect |
| 15:55 | tbaldridge | dnolen: it's been over a month since I tried out this code, so I could have a bug in it. I'll dig into it again and see what I find. |
| 15:57 | dnolen | tbaldridge: I'm happy to contribute here, would give me an excuse to understand the macro stuff |
| 15:58 | mdrogalis | tbaldridge: Do you have a general stance on serialization formats like Thrift and Protocol Buffers? e.g. when is it appropriate? |
| 15:59 | tbaldridge | mdrogalis: not really. I used Fressian the other day and really liked it. |
| 15:59 | tbaldridge | mdrogalis: https://github.com/Datomic/fressian |
| 15:59 | mdrogalis | Fressian doesn't really fall into the same category as those two, does it? |
| 16:00 | mdrogalis | Its self-describing IIRC? |
| 16:03 | tbaldridge | mdrogalis: yeah it is, that's what I default to I guess. I don't have much of a use for contract based serialization. |
| 16:03 | mdrogalis | Hm, alright. Thanks. |
| 16:07 | llasram | mdrogalis: If you're evaluating thrift, protobufs, etc, I've got Clojure integration for Avro I'm quite happy with: https://github.com/damballa/abracad </pitch> |
| 16:55 | danneu | Does anyone have a workflow for frequently running typedclojure type checks? |
| 17:01 | rasmusto | danneu: I've heard this is good: https://github.com/typedclojure/lein-typed |
| 17:01 | rasmusto | haven't used anything but in-line checks personally, so can't tell you more |
| 17:03 | rasmusto | too soon |
| 17:08 | danneu | rasmusto: yeah, i'm trying to roll my own emacs hotkey to check the current ns |
| 17:09 | jtoy | is there a library that finds the difference between a schema and a db adds those changes to the db? |
| 17:09 | jtoy | its not a migrations im looking for, its more auto migration |
| 17:11 | justin_smith | jtoy: http://clojuredocs.org/clojure_core/clojure.data/diff would be a start, if you have to make it yourself |
| 17:11 | justin_smith | just make schema->map and map->schema functions, and use data/diff to find the differences |
| 17:13 | jtoy | justin_smith: do you know of a library that will deal with the lowl levle db stuff ? i also want to write my migration in clojure and not in sql so i can make it db agnotistic |
| 17:13 | justin_smith | hmm, if you don't mind a macro-heavy solution there is korma |
| 17:14 | jtoy | justin_smith: i use it anyway for writing sql, i'll see if i can continue to use it for this part |
| 17:24 | lpvb | ,(vector-of :bool true false) |
| 17:24 | clojurebot | #<NullPointerException java.lang.NullPointerException> |
| 17:24 | lpvb | why is that |
| 17:25 | lpvb | oh |
| 17:25 | lpvb | nvm needs :boolean |
| 17:33 | jtoy | hmm, a lot of work for now |
| 17:41 | justin_smith | jtoy: https://github.com/budu/lobos this actually may help you |
| 17:45 | justin_smith | jtoy: note it has a db analyzer - you could run that on two dbs, then use data.diff on their tables |
| 17:45 | justin_smith | *table-definitions |
| 18:03 | tbaldrid_ | dnolen: my WIP for source map fixes is in meta-fixes (in the core.async repo) |
| 18:03 | clojurebot | You don't have to tell me twice. |
| 18:04 | tbaldrid_ | dnolen: it should work, but it doesn't for some reason. If you run cljsbuild adv it'll spit out a bunch of info at compile time about the metadata it finds. It looks correct but doesn't seem to make it into the source map |
| 18:08 | bitemyapp | (is (= madness?-this-is-sparta blah also))))) |
| 18:08 | bitemyapp | descriptive nomenclature? kinda not really. |
| 18:18 | akurilin | bitemyapp, Korma defaults to RETURNING for every insert/update, correct? |
| 18:21 | bitemyapp | akurilin: I remember changing something about that at some point. might be keys only. |
| 18:22 | bitemyapp | akurilin: I dunno, you tell me. |
| 18:22 | bitemyapp | I've forgotten most of what I've changed in Korma ^_^ |
| 18:22 | bitemyapp | specifically I made it so that bulk inserts would "work okay" by not RETURNING |
| 18:22 | bitemyapp | what I made the default is not within my memory. |
| 18:24 | akurilin | bitemyapp, I remember talking to the PG folks about always using RETURNING even if you don't need the results, and they were revolted by the idea. In practice most of the time you actually benefit from returning that one row you insert/update |
| 18:24 | akurilin | for large updates Korma right now returns either the first or the last one, forgot |
| 18:24 | akurilin | but essentially only 1 row |
| 18:27 | bitemyapp | akurilin: the choices, if I recall were none, keys, and values |
| 18:28 | bitemyapp | how those map to what data actually gets returned is a little obtuse. |
| 18:29 | bitemyapp | akurilin: you'd benefit most from reading the code, by my estimation. |
| 18:29 | bitemyapp | Better than reading tea leaves and guessing. |
| 18:29 | akurilin | bitemyapp, I am actively doing that in parallel to this. |
| 18:31 | bitemyapp | akurilin: you use korma heavily enough that the familiarity should pay dividends. |
| 18:31 | bitemyapp | akurilin: I'm pretty sure you use Korma about 99x more than I do these days. |
| 18:33 | bitemyapp | akurilin: in fact, I'm not really sure when I'll use a SQL database at all again in the future. |
| 18:33 | akurilin | bitemyapp, I am actively doing that in parallel to this. |
| 18:33 | akurilin | oops |
| 18:33 | bitemyapp | akurilin: most of my future database use is slated for Datomic, with some falling over to RethinkDB/Cassandra/HBase/etc |
| 18:33 | akurilin | I was going to say: it's interesting when maintainers stop being consumers. |
| 18:34 | akurilin | Guess it's our job to step up and start tossing some pull requests at you guys. |
| 18:34 | bitemyapp | akurilin: I don't think baranosky would be opposed to you contributing to Korma at all if you decided to learn the codebase. |
| 18:34 | bitemyapp | akurilin: yeah, exactly. |
| 18:35 | bitemyapp | I will say this though, I still think a stripped down "micro-Korma" that wasn't complected with things like connection pooling would be really cool. |
| 18:35 | bitemyapp | but that's not really my "problem" right now, so I'm choosing not to be opinionated about it specifically because I'm not a consumer. |
| 18:35 | bitemyapp | Alex and I are keeping the lights on and accepting PRs. |
| 18:36 | akurilin | bitemyapp, and I appreciate that :) |
| 18:37 | akurilin | Would be curious to find out how many people are activeling using this stuff in production |
| 18:37 | bitemyapp | quite a few, if I had to guess. |
| 18:37 | bitemyapp | not as many as cjj, but they're out there. |
| 18:37 | akurilin | Ok, just making sure I'm not survivor man there. |
| 18:37 | bitemyapp | not that I've taken a census. |
| 18:38 | bitemyapp | HoneySQL is pretty neat, but I'm not convinced it's the right level of abstraction. |
| 18:38 | bitemyapp | concatenating predicates is kind of tedious. |
| 18:39 | akurilin | Sort of related topic: korma exception handler loves to println stuff. I have my own sql exception handling and logging layer, and extra crap in the terminal is confusing in test runs. Is rebinding *out* around each korma db call the way to go to /dev/null it? |
| 18:40 | bitemyapp | akurilin: the logging in Korma is log4j yo. |
| 18:40 | bitemyapp | just configure it. |
| 18:40 | bitemyapp | unless I've missed something. |
| 18:40 | bitemyapp | I mean, you could do that too, but you don't need to. |
| 18:41 | Somelauw | kinda hacky, but i think you can do (define *out* (StringIO.)) to disable println globally |
| 18:41 | akurilin | I'm completely unfamiliar with log4j. Can I specify that I want logging exceptions only for selects for example? |
| 18:45 | akurilin | Warnock's dilemma. |
| 18:49 | bitemyapp | please don't do what Somelauw just said :P |
| 18:50 | bitemyapp | akurilin: I have no idea @ log4j, obviously it would be ideal if you could just dependency inject/AOP the log-fn and handle it yourself. |
| 18:50 | bitemyapp | whiiiiich is why I usually just have a *log-fn* dilly that people can override... |
| 19:01 | bitemyapp | another day, another error arising from an unexpected nil creating a nonsensical error when it blows up in my face somewhere unexpected. Delightful. |
| 19:01 | bitemyapp | technomancy: ^^ grumble grumble. |
| 19:02 | technomancy | bitemyapp: imma write a fuse adapter for github issues in ocaml |
| 19:02 | technomancy | I've Decided. |
| 19:02 | bitemyapp | technomancy: that's pretty brilliant. |
| 19:03 | technomancy | well I haven't done it yet |
| 19:03 | bitemyapp | technomancy: grom is still a thing, now that I've written the error handling for Revise grom and Simonides are my next projects. |
| 19:03 | technomancy | cools |
| 19:03 | bitemyapp | technomancy: I really like the concept in general...you should write it in Haskell instead though :) |
| 19:03 | bitemyapp | I need to shanghai noprompt into helping me with Grom since he wanted it too. |
| 19:04 | technomancy | maybe if I didn't want it to get written quickly I could use haskell |
| 19:04 | bitemyapp | hrm. good point. |
| 19:04 | technomancy | but the web UI is buggin' me and I don't want any yaks in the way |
| 19:04 | technomancy | context: I just started using noscript for conkeror, and its whitelisting doesn't work on github. |
| 19:05 | technomancy | which is mostly a win, but it turns all the icons into stupid unicode-not-found glyphs |
| 19:05 | zeebrah | I would like to have an alias λ for core/fn |
| 19:05 | zeebrah | is there a way to achieve that? |
| 19:06 | technomancy | zeebrah: do it locally in your editor, not on disk |
| 19:06 | zeebrah | technomancy: good idea! |
| 19:07 | bitemyapp | zeebrah: Haskellers have a pretty well established history of doing stuff like that with the glyph replacement stuff Emacs provides. |
| 19:07 | bitemyapp | I forget the proper name for it, #emacs surely knows. |
| 19:08 | technomancy | http://marmalade-repo.org/packages/pretty-mode-plus this one maybe |
| 19:09 | zeebrah | i like how it is assumed i'm using emacs lol :) Light Table but i'll try to figure it out |
| 19:12 | `cbp | emacs live has that by default |
| 19:13 | technomancy | it has issues in a few cases |
| 19:13 | akurilin | Those of you who worked with PG and JDBC, have you ever noticed the driver throwing a SQLException wrapping a PSQLException rather than directly the latter? |
| 19:13 | technomancy | it can affect line-length calculation and in some cases cause wrong indentation |
| 19:13 | akurilin | I think the latter case is there most of the time, but I swear I've seen the former once or twice in certain situations |
| 19:16 | bitemyapp | awwww yissss. Breaking test case that reproduces my problem. |
| 19:16 | akurilin | So the # and the end of a symbol in a macro is there to make sure there isn't accidentally a naming collision once the macro is expanded, avoiding interesting debugging sessions? |
| 19:16 | bitemyapp | akurilin: it's a shortcut for gensym. |
| 19:17 | akurilin | Oh ok, I didn't know its actual name. |
| 19:17 | bitemyapp | ,(gensym 'blah-this-fucking-rocks) |
| 19:17 | clojurebot | blah-this-fucking-rocks31 |
| 19:17 | bitemyapp | ,(gensym 'blah-this-fucking-rocks) |
| 19:17 | clojurebot | blah-this-fucking-rocks60 |
| 19:17 | bitemyapp | ,(gensym 'blah-this-fucking-rocks) |
| 19:17 | clojurebot | blah-this-fucking-rocks89 |
| 19:17 | bitemyapp | ,(gensym 'blah-this-fucking-rocks) |
| 19:17 | clojurebot | blah-this-fucking-rocks118 |
| 19:17 | `cbp | no! |
| 19:17 | bitemyapp | `cbp: wut |
| 19:17 | `cbp | stahp |
| 19:17 | bitemyapp | `cbp: sorry :( |
| 19:18 | bitemyapp | akurilin: it's to avoid the tedium of managing your gensym aliases yourself. |
| 19:18 | bitemyapp | akurilin: which...you had to do in Common Lisp. |
| 19:18 | bitemyapp | it sucked. |
| 19:18 | bitemyapp | a lot of things sucked. This was one of those things. |
| 19:18 | akurilin | bitemyapp, ok but the point was collisions? |
| 19:18 | `cbp | unintentional symbol capture |
| 19:18 | bitemyapp | you dun wanna shadow the users code. |
| 19:18 | bitemyapp | yeah |
| 19:18 | akurilin | There you go. |
| 19:19 | coventry | It doesn't explicitly check for collisions, though, just updates an internal counter each time you call it. |
| 19:20 | akurilin | coventry, I get it, thanks. |
| 19:20 | akurilin | Weird, the docs say it should append _number |
| 19:20 | akurilin | but there's no _ either here or in my repl |
| 19:21 | bitemyapp | akurilin: # appends _ + gensym. |
| 19:21 | akurilin | bitemyapp, ah, got it now. |
| 19:24 | bitemyapp | `cbp: DotA2 tonight? |
| 19:25 | bitemyapp | arrdem: ^^ |
| 19:29 | TEttinger | Defense of the Ancients 3: The Ancients are in a nursing home for senior citizens. Defend them by giving them their applesauce and meds 3 times a day. |
| 19:29 | swarthy | ahhaha |
| 19:32 | bitemyapp | TEttinger: hahahaha, that's pretty good :) |
| 19:34 | akurilin | bitemyapp, I saw the *exec-mode* dynamic var approach Korma does to determine how to execute the queries. Is that a pretty good pattern to follow as opposed to passing options to functions to customize their behavior? |
| 19:34 | bitemyapp | akurilin: no no no no no |
| 19:34 | bitemyapp | akurilin: Korma isn't a good example of many things. |
| 19:34 | bitemyapp | The thing it got right was passing around query maps, but even that was done in a brittle fashion. |
| 19:34 | `cbp | bitemyapp: sure |
| 19:35 | akurilin | (how to learn Clojure: get intimately familiar with other people's code, then forget everything they did) |
| 19:35 | bitemyapp | akurilin: if you want to see *good* code, Revise is a good place to look. |
| 19:35 | bitemyapp | there's some mess due to young the codebase is, but `cbp did a damn good job. |
| 19:36 | bitemyapp | the patterns and design are solid, there's no global/dynamic bullshit. |
| 19:36 | akurilin | bitemyapp, I think the one advantage that approach has is that you can group an unlimited amount of queries under the binding of that dynamic var, without having to do the pure approach for every call. |
| 19:36 | bitemyapp | you pass a connection to execute a query. no global singletons. |
| 19:36 | bitemyapp | akurilin: yuo can solve that problem just with closures...don't make my eyes roll that hard, it hurts :( |
| 19:37 | bitemyapp | there are times when dynamic vars are called for, that wasn't one of them. |
| 19:37 | akurilin | Actually the same pattern was there in noir validation with a dynamic var accumulator of validation errors. |
| 19:37 | swarthy | bitemyapp: I'm about to grab a smoking jacket and some other people's code for reading. What do you think are good clojure libs to learn from? |
| 19:37 | bitemyapp | akurilin: that was a bad fucking idea too. |
| 19:37 | akurilin | bitemyapp, I think it's just the author's style. |
| 19:37 | bitemyapp | akurilin: well it's the same author. |
| 19:38 | bitemyapp | Regardless, it's a bad fuckin' idea. |
| 19:38 | akurilin | bitemyapp, yes, my point. |
| 19:38 | akurilin | bitemyapp, fair enough, point taken. |
| 19:39 | bitemyapp | swarthy: https://github.com/weavejester/hiccup https://github.com/weavejester/environ github.com/bitemyapp/revise/ github.com/bitemyapp/bulwark/ github.com/bitemyapp/blackwater/ |
| 19:39 | bitemyapp | swarthy: if you want scary code: https://github.com/bitemyapp/brambling |
| 19:39 | bitemyapp | swarthy: https://github.com/dakrone/clj-http/ |
| 19:39 | akurilin | bitemyapp, can you expand a bit on the closure pattern? |
| 19:39 | bitemyapp | swarthy: https://github.com/dakrone/cheshire |
| 19:40 | swarthy | bitemyapp: Thanks a bunch! I've used a few of those while learning! Can't wait to dig much deeper. |
| 19:40 | bitemyapp | akurilin: https://github.com/bitemyapp/bulwark/blob/master/src/bulwark/core.clj#L88-L91 |
| 19:41 | bitemyapp | swarthy: heavily optimized and kin da razy but still interesting: https://github.com/aphyr/riemann |
| 19:41 | bitemyapp | riemann is NOT representative of typical Clojure code (this is true for a lot of aphyr and ztellman's stuff) |
| 19:41 | akurilin | bitemyapp, so you're basically being pretty pure there, passing config values around downstream? |
| 19:41 | bitemyapp | questionable libraries are the order of the day for those blokes. |
| 19:41 | bitemyapp | akurilin: pure'ish, there's an atom, but the closure takes precedence. |
| 19:41 | bitemyapp | also the atom isn't dynamic, it's global. |
| 19:42 | akurilin | bitemyapp, to avoid magic? |
| 19:42 | swarthy | bitemyapp: questionable libraries are the order of the day for those blokes. Care to elaborate? |
| 19:43 | bitemyapp | akurilin: to keep it async safe. |
| 19:43 | bitemyapp | akurilin: long story. |
| 19:43 | coventry | Is there ever any reason to use dorun as opposed to doseq? |
| 19:43 | bitemyapp | swarthy: long story, and I'm about to go eat with a friend. |
| 19:43 | swarthy | np I'll be idling here plenty I'll ask again later |
| 19:43 | bitemyapp | swarthy: suffice it to say, Mr. Tellman and Mr. Kingsbury have very different needs from the rest of us mere mortals. |
| 19:43 | akurilin | bitemyapp, mind if I dump that list of libraries you recommended to my tumblr for future reference? |
| 19:43 | swarthy | ah cool! |
| 19:43 | bitemyapp | swarthy: big distributed systems high performance stuff blah blah bvalh |
| 19:43 | bitemyapp | akurilin: go for it. |
| 19:43 | amalloy | coventry: of course. if you already have a lazy sequence that contains side effects, and you want to run them now, rather than run new side effects based on an existing sequence |
| 19:43 | swarthy | that says enough thanks! |
| 19:44 | amalloy | or it can be easier to write (dorun (map foo! xs)) than (doseq [x xs] (foo! x)) |
| 19:44 | coventry | amalloy: Oh, ofcourse. Thanks. |
| 19:49 | coventry | ztellman's sleight and riddley libraries touch clojure's guts in slightly icky ways, but for totally clear and sensible reasons. Reading them with those reasons in mind won't leave any harmful impressions. |
| 19:59 | seangrove | I have a string: "2012-10-07T20:23:56.000+0000", and I would like a timestamp. Can't quite figure out the straightforward way to do this |
| 20:00 | AimHere | If there's nothing inbuilt, you could split it up into bits with re-match and then look at the individual fields |
| 20:00 | amalloy | AimHere: that way lie madness and shattered dreams |
| 20:00 | AimHere | Oh ye of little faith |
| 20:01 | seangrove | AimHere: Going to have to side with amalloy there |
| 20:01 | swarthy | seancorfield: I had to mess with dates recently and I ended up using this: https://github.com/seancorfield/clj-time |
| 20:01 | amalloy | seangrove: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html |
| 20:01 | amalloy | there may be a wrapper in clj-time, but SDF isn't that complicated to use |
| 20:01 | swarthy | swarthy: I also did what amalloy mentions if you won't need to mess with it much. |
| 20:02 | seangrove | I'll check out SDF |
| 20:02 | akurilin | clj time or underlying joda should be able to take care of all of those concerns |
| 20:02 | akurilin | unless it's some odd edge case |
| 20:02 | seangrove | Thanks amalloy and swarthy, and of course AimHere |
| 20:02 | seangrove | akurilin: No, just interop with SFDC, nothing too bad |
| 20:02 | AimHere | So much for adding on the regex problem to all your other problems! |
| 20:04 | swarthy | seangrove: if you haven't already seen it I use clojure-toolbox.com to find libraries for various things |
| 20:04 | akurilin | The full list of Joda's out-of-the-box formats is: http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html |
| 20:04 | akurilin | Wrapped by this guy: https://github.com/clj-time/clj-time/blob/master/src/clj_time/format.clj#L82 |
| 20:08 | jtoy | if I have 2 arrays like [1 2] and [:foo :bar] jow can I join them so i get {:foo 1 :bar 2} ? |
| 20:08 | justin_smith | jtoy: zipmap |
| 20:08 | justin_smith | ,(zipmap [:foo :bar] [1 2]) |
| 20:08 | clojurebot | {:bar 2, :foo 1} |
| 20:09 | jtoy | sweet |
| 20:11 | brehaut | jtoy: to generalize into and map are also useful. zipmap ~== (fn [a b] (into {} (map vector a b))) |
| 20:12 | brehaut | jtoy: which is to say, map is a general purpose zipping function for stitching n sequences together, and into lets you pour a sequence into a collection type |
| 20:12 | jtoy | brehaut: I should use that more but that confuses me more often |
| 20:13 | brehaut | whats confusing about it? |
| 20:13 | justin_smith | ,(apply assoc {} (interleave [:foo :bar] [1 2])) |
| 20:13 | clojurebot | {:bar 2, :foo 1} |
| 20:13 | justin_smith | another option :) |
| 20:15 | jtoy | brehaut: i dont know why i would do map vector |
| 20:15 | jtoy | justin_smith: ye, even more confusing |
| 20:16 | brehaut | jtoy: ok so map takes a function of N arguments and N sequences |
| 20:16 | brehaut | jtoy: it takes items at the same index from all the sequences and passes tehm to the function |
| 20:16 | amalloy | justin_smith: any time you apply assoc, you've probably made a mistake. into is just better for that kind of thing |
| 20:16 | brehaut | jtoy: vector takes N arguments and creates a new vector from it. |
| 20:17 | brehaut | ,(map vector [:a :b] [1 2]) ;; jtoy |
| 20:17 | clojurebot | ([:a 1] [:b 2]) |
| 20:17 | brehaut | jtoy: thats the interstitial datastructure we need to use into to fill a map |
| 20:17 | brehaut | jtoy: conj on a map takes a key value pair as a vector |
| 20:17 | brehaut | jtoy: and into uses conj from memory |
| 20:19 | brehaut | ,(map + [1 2 3] [4 5 6]) ;; jtoy this zips together two sequences by adding the values at each index, as another example of map as zip |
| 20:19 | clojurebot | (5 7 9) |
| 20:25 | jtoy | brehaut: ah I see, I havent used multiple lists with map before |
| 20:35 | zeebrah | When i enable clojure-mode in a cider repl, i can no longer evaluate any expression in the repl. Any way to solve this? |
| 20:36 | coventry | zeebrah: Use nrepl instead. The cider package is not stable yet. |
| 20:36 | justin_smith | don't turn on clojure mode? |
| 20:36 | zeebrah | justicefries: I don't get the font locking then |
| 20:37 | justin_smith | clojure mode and the repl mode are both major modes, the one replaces the other |
| 20:37 | coventry | zeebrah: Oh, you were turning on clojure mode in the repl buffer? It's not meant to be used that way. |
| 20:37 | zeebrah | coventry: yep |
| 20:49 | amalloy | brehaut: into actually uses conj! and transients, by the way |
| 20:49 | amalloy | not observably different, of course |
| 20:49 | brehaut | amalloy: yeah i figured, but that can be brushed under the carpet |
| 20:51 | brehaut | not observable without a timer anyway |
| 20:59 | ddellacosta | if you were going to re-write some Clojure code which uses refs in CLJS, generally speaking, are atoms the most appropriate (only) answer? |
| 21:00 | ddellacosta | I guess the big distinction is between "coordinated" vs. "independent," huh |
| 21:02 | amalloy | ddellacosta: since there are no threads in cljs, atoms are just as good as refs: no swap! ever retries |
| 21:03 | amalloy | you have to make sure you don't split up a dosync block onto different event handlers, or whatever js calls them, but otherwise it's pretty hard to go wrong |
| 21:04 | bitemyapp | ddellacosta: what did you need the coordination refs offer originally? |
| 21:05 | ddellacosta | amalloy, thanks, that's helpful. |
| 21:06 | ddellacosta | bitemyapp: I'm just playing around now playing with FSMs |
| 21:06 | ddellacosta | bitemyapp: I was converting this code to work in CLJS: http://nakkaya.com/2010/06/22/finite-state-machine-implementation-in-clojure/ |
| 21:06 | ddellacosta | bitemyapp: now I'm reviewing how core.async works, since I understand that uses state-machines under the covers |
| 21:07 | bitemyapp | ddellacosta: FSMs are very useful when they fit your problem. |
| 21:08 | ddellacosta | bitemyapp: yep. Specifically I'm managing a validation system which validates as you move from field-to-field, so it seemed like a good approach. And we have a help system we will need to update later on, so I thought I could kill two birds with one stone. |
| 21:08 | ddellacosta | *managing -> re-factoring |
| 21:08 | bitemyapp | ddellacosta: I'm not convinced that code needed a ref though. They're just doing flat ref-sets. |
| 21:08 | bitemyapp | unless you're THAT worried about stale reads. |
| 21:08 | bitemyapp | that's pretty paranoid though. |
| 21:09 | ddellacosta | bitemyapp: yeah, I wasn't quite sure why that code did what it did, although I suppose if it gets accessed in a multi-threaded context it could be a problem, no? |
| 21:09 | bitemyapp | ddellacosta: for contrast, 99% of SQL database access is generating writes that use stale reads that are milliseconds, if not whole seconds, old. A stale read with an atom will be microseconds old and involve only one process whereas my database example might involve hundreds of readers and writers. |
| 21:09 | amalloy | bitemyapp: well, it's over three years old - atoms might not have existed back then? |
| 21:09 | bitemyapp | ddellacosta: if the SQL database scenario isn't biting 99% of users, it's extremely unlikely an atom would. |
| 21:10 | ddellacosta | amalloy: good point |
| 21:10 | bitemyapp | amalloy: aha, good call. I hadn't even noticed. |
| 21:10 | bitemyapp | I wasn't critiquing, just explaining why I don't think stale reads are a big deal most of the time. |
| 21:10 | amalloy | i think atoms were around then, but i'm not really sure |
| 21:11 | bitemyapp | Narullah wrote a lot of good stuff about Clojure. |
| 21:11 | ddellacosta | yeah, really love his blog |
| 21:11 | bitemyapp | I need to update my blog with an updated projects list. |
| 21:11 | bitemyapp | I've added a lot since I last updated it. |
| 21:11 | logic_prog | is there any fringe implementation of clojure on go rather than java? |
| 21:11 | nightfly | javaSCRIPT |
| 21:12 | nightfly | cljs |
| 21:12 | bitemyapp | logic_prog: you'd be better served by explaining your needs. |
| 21:12 | bitemyapp | nightfly: cljs isn't fringe. |
| 21:12 | logic_prog | purely intellectual curiosity |
| 21:12 | nightfly | and feels ashamed for a word earlier |
| 21:12 | logic_prog | to see if someone has a implmentation of clojure that runs on Go (the langauge) rather than the JVM |
| 21:12 | bitemyapp | logic_prog: no, and it's unlikely to happen. |
| 21:12 | logic_prog | nightfly: lol, was wondering how cljs / javascript fit in |
| 21:13 | ddellacosta | oh it's almost the conj isn't it |
| 21:14 | bitemyapp | ddellacosta: hey I'm stuck in SF, so we can suffer together (apart) |
| 21:17 | lpvb | (defn destructuring [{x :x y :y}] ...) |
| 21:17 | lpvb | the problem with ^ is that I lost the name of what's being passed in |
| 21:18 | lpvb | which is a reminder for what should be passed in |
| 21:19 | lpvb | or am I being pedantic? |
| 21:19 | technomancy | logic_prog: the go runtime has no dynamic loading capabilities at all; it's completely unsuitable for interactive development |
| 21:20 | technomancy | (which by extension makes it unsuitable for basically any good development, because good development is interactive) |
| 21:20 | xeqi | lpvb: you can name the arg with :as. {:keys [x y] :as point} |
| 21:21 | lpvb | xeqi: thanks :) |
| 21:25 | coventry | Are there any projects I should look at for examples of extending nrepl.el? Aside from nrepl-discover? |
| 21:25 | technomancy | coventry: lein.el maybe; but that's kinda stalled |
| 21:26 | technomancy | probably ritz |
| 21:26 | brehaut | ddellacosta: what distant clime are you in? |
| 21:26 | coventry | technomancy: Thanks. |
| 21:27 | technomancy | coventry: what's your plan? |
| 21:30 | coventry | technomancy: Well, I was trying to use nrepl-discover, but I need more logic on the elisp side, so I cargo-culted the output of nrepl-discover-command-for and hacked it up a bit (https://www.refheap.com/20753). I'm getting complaints that (".../tst.clj" 1 198) is not a string, which is the result of the (cons fn defun-region) form in that snippet. |
| 21:32 | coventry | technomancy: What I'm really trying to do is write an emacs function which will take the current region, get all the top-level forms which intersect with it, pass that to clojure, and instrument all forms in the region with clojure.tools.trace/trace. |
| 21:32 | coventry | technomancy: I have the clojure side of this written. Just need the emacs integration now. |
| 21:33 | coventry | technomancy: Currently, I'm looking for examples or instructions on how to pass a non-string argument through nrepl-send-op. |
| 21:34 | arrdem | bitemyapp, `cbp : eeeeeh not really Q_Q |
| 21:36 | technomancy | coventry: huh; that should be doable without any elisp if nrepl-discover is working properly |
| 21:37 | ddellacosta | brehaut: I am in Tokyo |
| 21:37 | technomancy | but I haven't tested some of the arg types yet |
| 21:37 | ddellacosta | wishing I could get to conferences more easily. :-( |
| 21:38 | brehaut | ddellacosta: yup totally. its mighty expensive to fly to the US |
| 21:39 | ddellacosta | brehaut: I'm thinking I'll try for Clojure West next year though |
| 21:39 | coventry | technomancy: nrepl-discover is working to the extent that nrepl-discover-command-for is being run with the nrepl/op metadata I put on the clojure fn, but I don't see a way to get the buffer-substring through to the clojure side within the nrepl-discover framework, at least not without saving the buffer to disk first. |
| 21:40 | technomancy | coventry: oh... do you have to send the substring? can't you send the file/positions and do reading server-side |
| 21:40 | technomancy | as long as you force a save before it's invoked |
| 21:40 | technomancy | (you should compile anyway, so that's probably fine) |
| 21:42 | coventry | technomancy: Yeah, I'd rather not have to force a save. The idea is to go in and just change the vars affected by the given region, like C-M-x rather than C-c C-k. |
| 21:43 | coventry | If I have to force a save, I have to ask the user whether it's OK, which slows things down in my experience. |
| 21:44 | coventry | But my more immediate problem is that sending a list as an argument in nrepl-send-op doesn't seem to work. Normally I'd assume it's my fault, but I'm a little more agnostic here since I'm ape-ing untested code. |
| 21:44 | technomancy | hm; maybe adding region-contents as an arg type is a thing we should do |
| 21:45 | technomancy | I gotta take off though; feel free to open an issue |
| 21:45 | coventry | technomancy: region-contents and nrepl-region-for-expression-at-point contents would work here, yeah. |
| 21:46 | coventry | Yeah, I'll open an issue, but may take a bit for me to get to it. |
| 22:11 | lpvb | ,(-> 1 (fn [x] (+ 3 x))) |
| 22:11 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Parameter declaration 1 should be a vector> |
| 22:11 | lpvb | can someone explain why this doesn't work? I don't think I'm understanding -> |
| 22:12 | amalloy | ,(macroexpand-1 '(-> 1 (fn [x] (+ 3 x)))) |
| 22:12 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Parameter declaration 1 should be a vector> |
| 22:12 | amalloy | &(macroexpand-1 '(-> 1 (fn [x] (+ 3 x)))) |
| 22:12 | lazybot | ⇒ (fn 1 [x] (+ 3 x)) |
| 22:12 | beppu | ,(-> [1] (fn [x] (+ 3 x))) |
| 22:12 | clojurebot | #<Exception java.lang.Exception: Unsupported binding form: 1> |
| 22:13 | amalloy | that's a rather unfortunate fallout of the change to fix how -> nests, gfredericks (or was it TimMc who noticed the problem?) |
| 22:14 | lpvb | so how do I accomplish what I intended? |
| 22:14 | amalloy | (+ 3 1) |
| 22:14 | clojurebot | 4 |
| 22:15 | beppu | ,(-> 1 (+ 3)) |
| 22:15 | clojurebot | 4 |
| 22:15 | amalloy | actually i don't understand at all why clojurebot fails to macroexpand that |
| 22:15 | bitemyapp | ,(-> [1] first (+ 3)) |
| 22:15 | clojurebot | 4 |
| 22:15 | bitemyapp | arrdem: DotA2? |
| 22:15 | lpvb | ,(-> {:x 1} (assoc :x 5)) |
| 22:15 | clojurebot | {:x 5} |
| 22:16 | bitemyapp | lpvb: macros operate on code structure, not data. |
| 22:17 | bitemyapp | lpvb: (-> [1] (fn [x] (+ 3 x))) turns into (fn [1] [x] (+ 3 x)) |
| 22:17 | lpvb | I defined a function (defn setm [m k f v] (assoc m k (f (get m v)))) |
| 22:18 | lpvb | and (-> {:x 1 :y 2} (setm :x (fn [x] (+3 x)) :y)) |
| 22:18 | lpvb | does the same error |
| 22:18 | lpvb | shouldn't the macro inject that map after setm |
| 22:20 | arrdem | bitemyapp: neg. homework. |
| 22:20 | lpvb | oh wait it is working |
| 22:21 | lpvb | thanks guys |
| 22:22 | amalloy | ,(macroexpand-1 '(-> 1 (fn [x] (+ 3 x)))) ;; seriously i'm baffled as to why this no longer returns (fn 1 [x] (+ 3 x)). any ideas, guys? a clojurebot issue somehow? |
| 22:22 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Parameter declaration 1 should be a vector> |
| 22:24 | `cbp | bitemyapp: wanna play? |
| 22:24 | `cbp | amalloy: it does return that? |
| 22:24 | amalloy | yeah, it must be clojurebot. hiredman, any idea why clojurebot now expands macros even if they're quoted? eg, ,'(with-open x) throws an exception |
| 22:25 | `cbp | oh but it shouldnt evaluate |
| 22:26 | `cbp | nevermind me :) |
| 22:26 | amalloy | right, `cbp. i'm guessing clojurebot does a dumb clojure.walk/macroexpand-all or something |
| 22:27 | coventry | amalloy: There's no macroexpand-all in clojurebot master. |
| 22:28 | amalloy | coventry: looks like https://github.com/hiredman/clojurebot/blob/master/clojurebot-eval/src/clojurebot/sandbox.clj#L147 to me, a hand-rollwed reimplementation of macroexpand-all |
| 22:29 | coventry | Yep. |
| 22:32 | akurilin | Does anybody know of any neat tools out there that can tell you what the "state" was when an exception happened? As in, I'm thinking of a mix of clojure.tools.trace and an exception handler |
| 22:33 | akurilin | I can write my own, but I'm suspecting this must have been done before. |
| 22:33 | akurilin | So something like: function f blows up with exception e, I want to know what the input was. |
| 22:43 | amalloy | akurilin: slingshot's throw+ automatically includes the in-scope locals into the exception |
| 22:44 | akurilin | amalloy, oh interesting, never heard of slingshot. |
| 22:44 | akurilin | amalloy, strongly recommended? |
| 22:44 | amalloy | meh |
| 22:44 | akurilin | lol... |
| 22:45 | amalloy | although, now i think of it, shouldn't that cause head retention? like, (defn last* [xs] (try (last xs) (catch Exception e (throw+ "broken")))) ought to prevent xs from being GCed, since the throw+ clause will attempt to include xs in the ex-info, right? that sounds bad |
| 22:49 | akurilin | Can you actually list locals in Clojure without having to wrap anything? |
| 22:53 | justin_smith | akurilin: here is code that displays locals in another clojure process: https://github.com/GeorgeJahad/cdt/blob/master/src/cdt/reval.clj |
| 22:54 | justin_smith | as you could imagine, it is a very low level thing |
| 22:54 | akurilin | justin_smith, yeah, definitely looks like serious business. |
| 22:54 | akurilin | thx |
| 22:55 | akurilin | Man, the stuff you can do. |
| 22:55 | justin_smith | akurilin: here is a webapp that connects to another clojure process, and when the remote gets an exception, it lets you examine the stack frame and eval in context: https://github.com/prismofeverything/schmetterling |
| 22:56 | justin_smith | uses clojurescript and websockets |
| 23:00 | echo-area | `defmacro' doesn't work inside (binding [*warn-on-reflection* true] ...). |
| 23:01 | amalloy | echo-area: (binding [*warn-on-reflection* true] ...) doesn't do anything, so that's not a super-compelling complaint |
| 23:01 | echo-area | amalloy: What I wanted to say is that, is it because the context is changed? |
| 23:01 | amalloy | anyway, defmacro needs to be a top-level form, since each top-level-form is compiled as a whole; *warn-on-reflection* is a red herring |
| 23:03 | bitemyapp | `cbp: grabbing a drink with a buddy, then we can. |
| 23:03 | bitemyapp | `cbp: I'll be back soon. |
| 23:04 | akurilin | justin_smith, wow that's awesome, thanks for sharing. What is the advantage of attaching a process to it rather than just dumping the entire context somewhere in a log? |
| 23:04 | akurilin | justin_smith, is there some kind of killer app of evaling within the context? |
| 23:05 | echo-area | amalloy: Why does that binding form not do anything? |
| 23:05 | amalloy | because it sets *warn-on-reflection* at runtime, and *warn-on-reflection* is only meaningful at compile time |
| 23:08 | echo-area | So is it not idiomatic to enclose def's inside such a form? I thought that way the enclosed forms are then compiled with *warn-on-reflection* being true |
| 23:10 | amalloy | that is simply not the case. the entire form is compiled, and then *warn-on-reflection is bound to true, and then the entire form is eval'd |
| 23:11 | echo-area | Oh right, it should be set before loading |
| 23:12 | justin_smith | akurilin: seeing exactly what is going on in each context |
| 23:12 | justin_smith | at the exact moment that the exception occured |
| 23:12 | justin_smith | ie. not only having a log of the things you intended to record, but being able to interactively query status of things you had not thought of beforehand |
| 23:12 | akurilin | justin_smith, any way you can just dump that to disk and reload it later? |
| 23:13 | justin_smith | I think there is a way to dump and reload a vm |
| 23:13 | justin_smith | that would be a java thing I guess |
| 23:13 | echo-area | amalloy: Is it correct that during loading .clj files the forms are compiled one by one, rather than entirely? |
| 23:13 | justin_smith | I think the problem would be that a bunch of things in the dump would refer to stale resources |
| 23:14 | akurilin | justin_smith, my issues are pretty simple for now, but I'm sure that with size I'll need to look into more adult debugging practices |
| 23:14 | justin_smith | ie. some values on a bytecode level refer to open files or streams, or process ids of other processes |
| 23:14 | amalloy | yes |
| 23:14 | justin_smith | akurilin: our use case is sometimes you just get that one bug you cannot reproduce and you just wish you could have had a repl in the context where the answer happened |
| 23:14 | echo-area | I see. Thanks |
| 23:15 | justin_smith | akurilin: complementary to that app I also made a request recorder replayer ring middleware |
| 23:15 | akurilin | justin_smith, yeah, I hear you. Right now my solution is: dump the prod db, load on my machine, repro, but that doesn't scale very well with # of external services and size of db :( |
| 23:16 | justin_smith | which you may find useful if you are using ring, and want to be able to test updated code with a request that is known to have triggered a bug |
| 23:16 | justin_smith | akurilin: also the repro can be odd |
| 23:17 | justin_smith | one particular bug I remember: we were using the default name for the cookie "ring-session", and one of our frontend devs had tried some friend's buggy webapp that created a broken localhost ring-session cookie |
| 23:17 | justin_smith | so the bug was only reproducible on his machine |
| 23:17 | justin_smith | and it wasn't even us, it was a corrupted cookie causing an exception |
| 23:17 | justin_smith | well I guess we learned to handle that better :) |
| 23:17 | akurilin | justin_smith, ah damn, must have been a pain |
| 23:18 | akurilin | I'm also a ring-session cookie kind of guy heh :) |
| 23:18 | justin_smith | classic "error only happens for the one guy who can't read the stack trace" |
| 23:21 | akurilin | justin_smith, a lot of things get much easier once you can see the full stack trace, huh? |
| 23:21 | justin_smith | well, its a first step |
| 23:22 | akurilin | On an unrelated note: how do I replace a fn in a library I don't own? Bitemyapp was saying something about AOT |
| 23:22 | akurilin | but I haven't found anything useful on Google \ |
| 23:23 | `cbp | akurilin: alter-var-root |
| 23:23 | justin_smith | I don't know how aot plays into that |
| 23:24 | justin_smith | I have seen someone actually run their whole app inside a with-redefs foorm |
| 23:24 | justin_smith | lol |
| 23:25 | akurilin | `cbp, the idea is that I do that once at boot and it'll be set for the rest of the app's lifetime? |
| 23:25 | `cbp | akurilin: yeah |
| 23:25 | `cbp | unless theres an evil alter-var-root somewhere in that lib i guess |
| 23:25 | akurilin | so do people end up with a "do stuff at boot" function ? |
| 23:26 | justin_smith | akurilin: yeah, with ring you can register an :init action |
| 23:26 | justin_smith | that way you can make sure you have no stateful events other than var bindings at the top level of any of your code |
| 23:26 | justin_smith | just def the init in each ns, and call all of them from the main ring init |
| 23:27 | justin_smith | that way reloading source doesn't have weird side effects |
| 23:27 | justin_smith | of course without ring you have -main |
| 23:27 | akurilin | justin_smith, what does it mean to def the init in each ns? |
| 23:28 | justin_smith | it is a convention that is useful |
| 23:28 | justin_smith | in each ns you make, if the code needs any initialization, you (defn init [] (initialize this namespace... )) |
| 23:29 | justin_smith | then you call each of these functions from the function you register with ring as your :init |
| 23:30 | akurilin | justin_smith, what if it's some initialization that multiple namespaces need, you still put it up there? |
| 23:30 | akurilin | As long as it's idempotent I guess. |
| 23:30 | justin_smith | you define it in each ns |
| 23:30 | justin_smith | then call them from the init function |
| 23:31 | akurilin | justin_smith, so the initialized thing is defined once per namespace this way? |
| 23:31 | justin_smith | well for the ones that need it, each gets their own |
| 23:31 | justin_smith | really most namespaces don't need an init function |
| 23:32 | justin_smith | just the ones that do things like load config files at boot |
| 23:32 | justin_smith | or set up a db connection pool |
| 23:32 | justin_smith | or create a pool of worker tasks |
| 23:32 | justin_smith | that kind of stateful startup stuff |
| 23:32 | akurilin | Yeah I have stuff like that and logging levels |
| 23:34 | akurilin | justin_smith, well thanks for sharing, that's interesting |
| 23:35 | justin_smith | no problem, hope it proves helpful |
| 23:35 | akurilin | Can I even alter-var-root private vars? |
| 23:36 | akurilin | Guess I'm about to fin dout |
| 23:36 | Raynes | akurilin: Yes. |
| 23:37 | Raynes | Privacy is more of a "Yo, this person thought you should probably not use this." instead of a "GET ON THE GROUND HANDS BEHIND YOUR BACK HANDS BEHIND YOUR BACK DROP THE WEAPON." |
| 23:40 | akurilin | Raynes, well it does seem to be making things a bit trickier. For example, this fn I'm replacing calls another private inside of it, so it's throwing an exception when I try to alter var root it |
| 23:41 | justin_smith | akurilin: (in-ns target-ns) |
| 23:42 | akurilin | justin_smith, that seems to be stateful, can I do the same with rebinding *ns*? |
| 23:42 | akurilin | or at least I only ever used in-ns from a repl |
| 23:43 | justin_smith | hmm |
| 23:43 | justin_smith | yeah, that could be tricky I guess |
| 23:44 | justin_smith | akurilin: http://clojure.org/namespaces |
| 23:44 | justin_smith | "The current namespace, *ns* can and should be set only with a call to in-ns or the ns macro" |
| 23:44 | Raynes | If it throws another private inside it then call the var and not the function, I guess. |
| 23:45 | Raynes | &(#'+ 3 3) |
| 23:45 | lazybot | ⇒ 6 |
| 23:45 | justin_smith | akurilin: you could always just fork the library instead of monkey patching it |
| 23:45 | justin_smith | it may be easier |
| 23:46 | akurilin | justin_smith, that's fair, I need to get used to doing that anyway. |
| 23:46 | akurilin | supposedly pushing stuff to clojars is pretty braindead these days |
| 23:46 | justin_smith | very easy |
| 23:48 | justin_smith | the nice thing to do is if you actually fixed a bug or extended functionality you can issue a pull request |
| 23:48 | akurilin | justin_smith, that's fair. In my case it's more of a flavor thing which I don't want to impose on other folks who might have their own. |
| 23:49 | justin_smith | in that case, you may be yak shaving ;) |
| 23:50 | akurilin | well, korma by convention defaults to FKs being named %table-name%_id, which doesn't work if your naming convention is plural for tables and singular for FKs |
| 23:50 | akurilin | so I'm overriding their fn to compute that to support that case |
| 23:51 | akurilin | and folks name their stuff however they want |
| 23:51 | akurilin | I guess the better option would be to let people define their own table name to fk function |
| 23:51 | akurilin | with a default |
| 23:52 | akurilin | so maybe that'd be a PR |
| 23:53 | akurilin | Welp, there's an inflections library, there you go :D |