#clojure log - Nov 11 2013

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

0:10 arrdem: TimMc: trash-cli is quite nice... thanks!

0:19 `cbp: bitemyapp: give me your steam id sometime ;)

0:20 arrdem: `cbp: starcrafts?

0:20 `cbp: arrdem: only broodwar

0:27 arrdem: `cbp: aw.. bitemyapp and I've been playing when I have access to an sc2 capable box.

0:27 bitemyapp: my main games lately have been starcraft 2 and LoL. I'll play DotA2 if somebody invites me.

0:28 `cbp: arrdem: maybe ill get it once i remember my damn blizzard password :P

0:28 * arrdem should really try and learn dota2

0:29 bitemyapp: arrdem: DotA2 is available for Linux.

0:29 arrdem: if you played that, you wouldn't need the other boxen.

0:29 arrdem: why not install Steam and see how it goes?

0:29 arrdem: M-x pacman -S steam

0:34 oh right. now I remember why I didn't have steam on linux....

0:34 bitemyapp: arrdem: ?

0:34 arrdem: there's a Kerbal Space Program build for linux.

0:35 bitemyapp: arrdem: well install steam, I'm really curious if DotA2 works.

0:35 arrdem: bitemyapp: installed and installing..

0:35 bitemyapp: I like DotA2 quite a bit, better than LoL in most respects and would like to play it if possible.

0:37 arrdem: I know a bunch of people who favor d2 over LoL I've just never gotten into d2

0:37 technomancy: kerbal sounds nuts (in a good way)

0:37 bitemyapp: arrdem: it's like any other MOBA. It's somewhere in between HoN and LoL in design principle.

0:38 the pacing and design of DotA2 is a lot better though. Much more balanced and interesting game.

0:38 `cbp: dota2 works kinda crappily on my macbook air

0:38 not like its a machine meant for gaming

0:38 not that*

0:38 bitemyapp: :(

0:38 `cbp: (i play on a pc though)

0:39 bitemyapp: I keep thinking about getting a gaming PC so that I don't have to play on a mac.

0:39 `cbp: it should be pretty affordabe to build one :P

0:39 arrdem: bitemyapp: if you do don't just build a gaming box. build a multihead dev box with enough power to play games.

0:40 bitemyapp: arrdem: I have a Thinkpad for work, what specifically are you angling for with your recommendation?

0:42 arrdem: bitemyapp: I got a 3x 23" monitor desktop with more than reasonable specs out of a research position freshman year

0:42 bitemyapp: I don't want a ton of hardware.

0:42 just a machine that can game.

0:42 arrdem: shrug. I don't mind the metal, and I don't know enough about portable gaming boxes to comment.

0:43 technomancy: any machine can game; you just have to pick the games right

0:43 arrdem: my perception is that there's a significant price and power primium, but I know some people who are happy with theirs.

0:43 * technomancy pats his copy of DOOM II tenderly

0:44 arrdem: technomancy: that's more of an operating system than a game...

0:44 technomancy: don't get me started on nethack

0:46 arrdem: bitemyapp: it's gonna take a bit to get dota2 downloaded.. I'll let you know what happens tomorrow.

0:47 bitemyapp: arrdem: okiedokie.

0: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.

0:49 bitemyapp: swarthy: have you played dungeon crawl stone soup?

0:49 swarthy: bitemyapp: I have that one was fun as well, I need to fire that one up again soon.

0:50 bitemyapp: I like roguelikes a lot partly because of the ephemerality

0:50 I was really pleased to see the indie game scene learn from the genre and incorporate it into new ideas.

0:50 I really like 2d games too.

0:51 swarthy: Yeah, making a word out of ascii or bland tilesets is amazing fun.

0:51 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.

0:51 Other than making up and 'playing a role' d&d was so simple.

0:51 bitemyapp: I like 2d pixel based graphics too.

0:52 swarthy: Bastion is really cool. 3d but locked into isometric.

0:52 So it has this cool 2d feel.

0:54 bitemyapp: I really liked that.

0:55 john2x: ooh roguelikes. I love Brogue. It's so pretty, considering it's ASCII "graphics"

0:55 justin_smith: nethack is my jam

0:56 I want to port nethack.el to clojure

0:56 make clojure nethack bots

0: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.

0:57 makers*

0:58 bitemyapp: swarthy: oh damn, I really liked Dredmor, what game is that?

1:00 ohhh clockwork empires.

1:00 yeah that's been long coming

1:00 justin_smith: one of these weekends I will play amnesia: a machine for pigs some more

1:00 works great on my linux system

1:01 (no wine, native support)

1:01 bitemyapp: justin_smith: yeah, indie folk are pretty good about mac and linux support.

1: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.

1:02 bitemyapp: that's partly why I'm struggling with whether or not I want a dedicated gaming machine.

1:02 I would consider outsourcing that to consoles, if consoles had the kind of games I like.

1:02 arrdem: bitemyapp: wait 12 months see what happens with steambox, re-evaluate.

1: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

1:03 bitemyapp: arrdem: that was one option I was considering.

1:03 justin_smith: but people at work would think I was just slacking

1:03 bitemyapp: justin_smith: that's a good idea.

1:03 justin_smith: I usually take a walk or make tea to accomplish the same thing.

1:03 justin_smith: heh, maybe healthier :)

1:04 bitemyapp: I suppose so.

1:04 The real point is to empty my mind.

1:04 justin_smith: I keep my instrument by my desk, so I can stop and play if I am home

1:04 yeah

1:04 playing an instrument is good for that

1: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.

1:05 Technology is too good to get any real work done.

1:05 * justin_smith starts a nethack game since the subject came up, and boom, _

1:05 justin_smith: alter right next to me on the first level, first room

1:05 *altar

1:06 bitemyapp: arrdem: http://i.imgur.com/tOTISJF.jpg

1:07 arrdem: bitemyapp: nice

1:15 muhoo: wait, did thrown? get removed from the language since these docs? http://clojuredocs.org/clojure_core/clojure.test/is

1:16 it isn't in clojure.test ns public vars AFAICT

1:25 coventry: muhoo: I've used thrown? relatively recently. It's a method of the assert-expr multimethod.

1:33 mindbender1: Please can somebody delete the page at http://en.wikipedia.org/wiki/Communicating_sequential_processes?

1:33 justin_smith: why?

1:33 clojurebot: why is startup slow is busy compiling the `for` macroexpansion

1:34 mindbender1: justin_smith: because of http://en.wikipedia.org/wiki/Communicating_sequential_processes#Examples

1:35 How does that represent the objectives of CSP?

1:35 Boring!

1:36 justin_smith: /ignore mindBender1

1:39 bitemyapp: mindbender1: you just got plonked old school style son, you should consider that a Sign (TM)

1:40 justin_smith: bitemyapp: my classic newb mistake, typing a space before the / that made it a command

1:40 muhoo: coventry: CompilerException java.lang.RuntimeException: Unable to resolve symbol: thrown? in this context, compiling:(/tmp/form-init1896962088566288833.clj:1:771)

1:42 maybe i don't understand multimethods then. i thought the symbol would resolve. pretty sure i've been able to (doc some-multimethod) before

1:56 arrdem: bitemyapp: dota2 is totally playable

1:56 now bed

1:57 bitemyapp: arrdem: awesome, catch you later.

2:18 amalloy: muhoo: clojure.test/assert-expr is a multimethod that dispatches on first

2:18 it has a defmethod for the symbol 'thrown?

2:18 but there is no multimethod named thrown? anywhere

3:26 muhoo: oh! duh. then thrown? isn't a function, it's the firt arg to (is

3:26 (is thrown? (expr....)) not (is (thrown? (expr....)))

3:28 amalloy: no, it's (is (thrown? ...))

3:28 but it's still not a function

3:28 muhoo: now i have to go look at the source of assert-expr

3:29 amalloy: 'is is a macro that uses the assert-expr multimethod to decide how to expand

3:29 it passes assert-expr the first symbol in the list you're expanding

3: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?

3:32 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

3:32 or do I have to bake it myself

3:37 muhoo: amalloy: thanks, just looked at it, saw where the dispatch is. neat.

5:33 sm0ke: i just copied my project to a new one a changed namespaces

5:34 now lein repl fails with Unable to resolve symbol create: is in this context

5:34 i doesnt give anything useful in stack trace

5:35 oh wow i misspelled a namespace

5:46 wtf is :ssl :yes!!!11} in

5:46 posta wiki

5:46 postal*

5:46 cant he just use a straight :yes!

5:59 CookedGryphon: sm0ke: you can just use true

5:59 that annoyed me too

5:59 i think it's just anything truthy

6:01 sm0ke: CookedGryphon: thanks i thought that so

6:01 funny that author would give such contrived example

6:01 CookedGryphon: send a pull request chganging the docs? It genuinely put me off using postal for a while

6:02 sm0ke: hehe yea i will do that

6:02 CookedGryphon: I only used it as a last resort, and functionally it's the best I've tried

6:02 sm0ke: CookedGryphon: do you seem to have used html formatting in your mails?

6:02 any easy way to do that?

6:02 CookedGryphon: yeah

6:02 sm0ke: tell me

6:02 CookedGryphon: one second, i'll find it

6:04 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"]]])}]

6:05 that was probably too long to type inline, sorry, should have done a refheap

6:05 sm0ke: awesome sauce

6:05 i am copying that

6:10 CookedGryphon: just wondering whats that :alternative?

6:10 fallback from clients which dont have html

6:10 for*

6:13 CookedGryphon: I can't remember, I think so yes. It's in the README

6:13 you can do attachments, multipart and all sorts in that format

6:13 sm0ke: ok thanks

7:00 ambroseb_: only 20 hours left in the Typed Clojure dev campaign. Don't miss out! ;) http://www.indiegogo.com/projects/typed-clojure

7:01 rstandy: hello Clojure community

7:01 ambroseb_: rstandy: hello there

7:01 Jarda: ambroseb_: why should I care about typed clojure

7:02 rstandy: I'm sorry to ask a possible flame war starting question, but, what framework do people use in Clojure when developing webapps?

7:02 justin_smith: rstandy: not a flame-invoking question at all

7:03 rstandy: well, then this is a really neat community :-)

7:03 ambroseb_: Jarda: it's AFAIK the only way to make strong static claims about Clojure code.

7:03 cark: rstandy: i only use ring, but it's not a full featured framework

7:03 justin_smith: liberator, pedastel, Luminous are popular

7:04 CookedGryphon: I tend to avoid frameworks and use the small libraries i need

7:04 justin_smith: there have been flames about the design of Noir in the past, but even the autor of noir depricated it :)

7:04 gwillickers: rstandy: i just started too, i went with compojure

7:04 ambroseb_: Jarda: prevents you from misusing null, *really* helps using plain maps.

7:04 gwillickers: which sits atop ring

7: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...

7:04 ambroseb_: Jarda: and it's just a library, sprinkle it where you want.

7:05 cark: rstandy: most frameworks are based on ring, you c&n't go wrong by learning that

7:05 Jarda: I'm using compojure for routing, haven't felt the need for anything else than compojure+ring

7:05 rstandy: justin_smith: "the right one" being that which is popular enough to give me documentation, great community to ask, ecc.

7: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

7:05 noidi: Jarda, +1

7:05 CookedGryphon: you can swap out smaller components when a better library comes along

7: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

7:05 noidi: we've been happily using ring + compojure + stencil for templating

7:06 justin_smith: CookedGryphon: yeah, start with ring and compojure, most things should modularly combine with those

7:06 inc CookedGryphon

7:06 Jarda: I use hickup templates, haven't really looked into alternatives

7:06 justin_smith: (inc CookedGryphon)

7:06 lazybot: ⇒ 1

7:06 justin_smith: there we go

7:06 rstandy: wow so many choices

7:06 gwillickers: i went hiccup too, no complaints

7:06 justin_smith: rstandy: they are made of modular parts, mostly

7:06 Jarda: anything that builds on top of ring is fine as long as they do not try to hide ring

7:07 justin_smith: yeah

7:07 rstandy: any commercial site I can see to have an idea of what I can accomplish with which framework?

7:07 justin_smith: it is not so much "frameworks" you get with clojure as 'sets of libs that work together'

7:07 cark: there are some frameworks

7:07 rstandy: justin_smith: right, I understand it's one of the objectives of Clojure too

7:07 cark: medestal maybe ?

7:07 rstandy: justin_smith: this is so good

7:07 cark: pedestal*

7: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

7: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

7:08 rstandy: Jarda: very true! I used Weblocks from CL, which is very nice, but forced me again to work its way

7:09 cark: ah there was hunchentoot in CL ... nothing else was need"ed, and so easy to use !

7:09 justin_smith: pedastel is a more "total solution" top to bottom design (for better and/or worse)

7:10 CookedGryphon: a rule of thumb I have found from experience - avoid anything which requires you to use a defblah macro

7:10 rstandy: ok, so pedestal force you to model in its way

7:10 justin_smith: CookedGryphon: you are trying to get inced by me again aren't you?

7:10 CookedGryphon: usually means they are doing something unidiomatic which isn't going to compose or play nice with other things down the line

7:10 justin_smith: very good advice

7:11 CookedGryphon: :)

7:11 rstandy: looking for compojure

7:11 cark: i think the defXXXX thing isn't too bad as long as there is a functional interface as well

7: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

7:13 rstandy: so for example, if I need a webapp with session management and login/registration, what can I use to start very fast?

7:13 justin_smith: rstandy: there are ring middlewares for session and auth

7:13 friend is great for auth

7:14 I did a kind of roll-my-own but plan to upgrade to friend

7:14 ring-session for session management

7:14 rstandy: justin_smith: thanks! looking for friend right now

7:14 justin_smith: https://github.com/cemerick/friend

7:14 http://clojuredocs.org/ring/ring.middleware.session/wrap-session

7:17 rstandy: thank you very much guys, very helpful!

7: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

7:19 so that a frontend guy who does no clojure could use the cms interface to define the page he needs

7:19 and it is messy integrating routes created as data in a db with a defroutes model

7:20 rstandy: looking for all of this libraries

7:20 justin_smith: rstandy: that is what lein templates are good for

7:21 it basically copy/pastes a sane default app setup, complete with requiring the right deps

7:23 https://clojars.org/search?q=lein-template

7:24 for anything that defines a foo/lein-template you should be able to run lein new foo

7:26 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

7:27 sadly clojars has not been auto-indexing quite right, because I know of others that exist that are not on that results page

7:37 sm0ke: what a mess i am unable to send mails with postal

7:37 justin_smith: there is a good postmark lib for clojure

7:37 sm0ke: it says {:code 0, :error :SUCCESS, :message message sent} but i dont get no mail

7:38 CookedGryphon: odd, spam?

7:38 justin_smith: sm0ke: the reason people use postmark, is email providers use whitelists

7:38 CookedGryphon: what sort of account are you sending from sm0ke

7:38 sm0ke: nothing in spam too

7: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

7: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)

7: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

7:39 sm0ke: CookedGryphon: yes me too

7:39 i am using a gmail accout

7:39 CookedGryphon: all the appropriate gmail options set?

7:39 sm0ke: why would postal be so cruel to give success message

7:40 CookedGryphon: it's not suspicious about the sending and asking for a captcha on the web interface is it?

7:40 sm0ke: CookedGryphon: i guess so .. everything he has in docs

7:40 CookedGryphon: i mean on the gmail site itself

7:40 imap and smtp aren't on by default

7:40 sm0ke: i am using smtp settings only

7:40 CookedGryphon: but presumably you wouldn't then get a success message

7:40 sm0ke: i only need to send

7:41 justin_smith: sm0ke: does mail within localhost work?

7:41 sm0ke: hmm i guess i need only sendmail installed on my machine right?

7:41 justin_smith: postal should be doing what sendmail does already

7:42 sm0ke: i think it uses a mail agent underneath

7:42 CookedGryphon: you don't need anything set up locally to send with a gmail account

7:42 justin_smith: CookedGryphon: the reason I suggested localhost testing, is that eliminates a bunch of weird variables

7:43 CookedGryphon: yeah, introduces a load more though to have a working local mailserver

7:43 sm0ke: hmm weird i jusr installed ssmtp and everything fails now

7:43 justin_smith: sm0ke: what os are you using? a normal linux os will set up local mail (for system messages to administrator)

7:43 sm0ke: i get {:code 1, :error nil, :message nil}

7:43 ubuntu 12.04

7:43 justin_smith: yeah, ubuntu already has mail out of the box

7:44 sm0ke: eee

7:44 justin_smith: that is how root gets messages about system status stuff

7:44 with a normal install

7:44 err... maybe I was wrong

7:45 debian does this, but ubuntu may not

7:45 postfix sets it up though

7:45 sm0ke: i have postfix

7:45 ssmtp stopped it though

7:45 and now i get errors

7:45 rightfully*

7: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 ""})

7:46 are you doing exactly the same?

7:47 justin_smith: sm0ke: you can test local mail by using mail or mutt, it should just install and work

7:47 CookedGryphon: so you are able to use the postal lib with gmail?

7:47 CookedGryphon: yeah

7:47 wait, sorry, user and pass, not username and password

7:47 sm0ke: hmm weird

7:48 CookedGryphon: i rename them on teh way in so my config is consistent

7:48 guns: I use postal with smtp.gmail.com; works well. Maybe the machine sm0ke is hitting is failing

7:48 sm0ke: i am using ^{:user "... " :pass "**"} ..with that meta sign

7:48 weird thats what the doc mentions

7:48 CookedGryphon: yeah, don't know what on earth that's about

7:48 teh docs need editing

7:48 makes far more sense to just send settings then message

7:49 sm0ke: hmm let me try your version

7:49 CookedGryphon: i was including a :from in the message too

7:49 gmail might need that

7:49 sm0ke: yup i have that already

7:51 CookedGryphon: hmm, there's a pull request to fix the docs from 2 years ago...

7:58 sm0ke: some progress, i get com.sun.mail.smtp.SMTPSendFailedException: 530-5.5.1 Authentication Required. now

7:58 justin_smith: sounds like its time to fork it just to get better docs

7:58 lol

7:58 sm0ke: weird though

8:04 CookedGryphon: hey it worked

8:04 actually it needs :user and :pass

8:04 not :username and :password

8:04 i think main problem was with the meta sign

8:06 bye for now

8:17 tim___: dnolen: ping

8:26 gtuckerkellogg: forcer, with the simple setup, elpy-shell-send-region-or-buffer only seems to work for me with an active region

8:27 justin_smith: gtuckerkellogg: wrong channel?

8:27 gtuckerkellogg: justin_smith, indeed!

8:28 * gtuckerkellogg backs out slowly

8:29 justin_smith: this here city slicker thinks he can use INDENTATION instead of PARENTHESIS as God intended

8:29 get 'im boys

8:29 noidi: :D

8:33 tbaldridge: ~guards

8:33 clojurebot: SEIZE HIM!

8:33 mdrogalis: Heh

8:33 gtuckerkellogg: lol

8:53 hyPiRion: ~gourds

8:53 clojurebot: SQUEEZE HIM!

9: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?

9: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

9:29 terom: the spec is simple enough http://json-rpc.org/wiki/specification

9:30 oh, I see that version 2 is a bit more complex http://www.jsonrpc.org/specification

9:37 rstandy: just another newbie question: is there some in production web app or site developed in clojure?

9:37 justin_smith: I have deployed a few

9:37 (my company, I did the clojure part on the backend)

9:38 there is an out of date list on clojure.org somewhere

9:38 soundcloud

9:38 rstandy: justin_smith: wow, can I see of them (those which are publicly available)

9:38 justin_smith: http://corp.zinio.com/ the only evidence of clojure is how fast it loads

9:38 I guess

9:39 http://weareinstrument.com/work/featured/the-build this one is pretty awesome actually

9:39 rstandy: justin_smith: souncloud.org is simply wonderful!

9: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

9:40 http://thebuildfilm.com/ be sure to see this, the actual site that last blog post was about

9:40 flash-like ui in html5

9:41 with clojure backend, of course

9:42 almost forgot this one: done in clojure + clojurescript http://onenorthpdx.com/

9:42 rstandy: justin_smith: by backend you mean that clojure builds the html pages or not?

9:42 justin_smith: it handles the cms

9:42 it serves all the data

9:42 handles the requests

9:42 renders templates

9:42 rstandy: justin_smith: ok, got it

9:43 justin_smith: resizes images for your screen resolution (caching existing resizes)

9:43 rstandy: justin_smith: thank you very much for the info man

9:43 justin_smith: with that last one (one north) the whole UI is built in clojurescript using core.async to handle events

9:44 rstandy: justin_smith: wow

9:44 justin_smith: awesome sites!

9:44 justin_smith: thanks, that's mostly because we have awesome designers

9:44 and very meticulous frontend devs that can realize those designs

9:45 but it helps that I can make sure the pages load fast and get the right data too :)

9:45 rstandy: justin_smith: is your backend donwlodable free software? :-)))

9:45 justin_smith: rstandy: it is open source, we will be announcing and publicising it soon

9:46 rstandy: justin_smith: this is very interesting!!! Will you email the clojure ml?

9: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

9:46 yeah, I think that is the plan

9:47 rstandy: justin_smith: exciting news, I hope to be productive with clojure pretty soon, I want to push it in my workplace

9: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

9:48 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)

9:48 rstandy: justin_smith: nice, what was your language and environment before clojure

9:48 justin_smith: huge selling points!

9:48 justin_smith: I got hired to do clojure

9:49 before that they were using ruby

9:49 but server costs and reliability sucked

9:49 rstandy: justin_smith: dream job for me :D

9:49 justin_smith: before that php

9:49 rstandy: it is very nice

9:49 rstandy: justin_smith: yeah, ruby sucks in many ways

9:49 justin_smith: are you coming from CL+Emacs

9:49 +Slime?

9: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

9:50 yeah, common lisp / scheme / ocaml

9:50 definitely emacs no matter what, but that's the tool not the medium :)

9:51 rstandy: justin_smith: yeah, any advice/tip for an CL+Emacs+Slime developer approaching clojure?

9:51 justin_smith: actually I was not even a professional programmer before jumping into this, I was just fascinated by algorithms and functional programming

9:51 hmm

9:51 get cider

9:51 which is the update to nrepl.el

9:52 use paredit, after a few days learning it it is indespensible

9:52 rstandy: justin_smith: yeah! Wonderful mode I already use in CL

9:52 justin_smith: and (source fn) (doc fn) are your friends :)

9:53 oh, and throw (ns-publics ns) in the mix too

9:53 rstandy: justin_smith: I installed cider, and I'm starting to explore clojre through it, but I miss the Slime Inspector

9:53 justin_smith: we are working on a cdt web frontend

9:53 I have not had much luck with ritz

9:54 rstandy: justin_smith: so a Slime-like inspector is still missing in clojure

9: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

9:54 nDuff: ...well, there _is_ ritz

9:55 ...if you're willing to go through the pain to set it up.

9:55 justin_smith: rstandy: theoretically ritz can do that stuff, I have not had luck with it

9:55 rstandy: justin_smith: will check that then

9:55 * nDuff has done that, once, to prove that it was possible... and hasn't bothered again.

9: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

9:55 rstandy: justin_smith: ok, sometimes do you miss some CL and Slime features when using clojure (sorry for so many questions)?

9:55 justin_smith: yeah, for sure

9:56 like the step debugging etc.

9:56 rstandy: justin_smith: just trying to understand what I'll miss and what I'll gather with clojure

9:56 justin_smith: but, with immutible data structures and a more strictly functional approach, I find invasive debugging less neccessary

9:56 I can do a lot just by verifying each function produces the right output for the expected input

9:57 also I often miss static checks and currying from ocaml

9:58 rstandy: justin_smith: man your answers are really useful for me, many thanks!

9: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

9:58 https://github.com/noisesmith/groundhog

9:58 rstandy: justin_smith: wow, nice

9:59 justin_smith: I need to update that readme, the latest is 0.4

9:59 *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 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 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 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 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 how does one iterate in clojure?

10:08 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 how do you @ clojurebot to somebody?

10:09 (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 though cursive looked nice if you want a java style IDE experience

10:13 shoshin: Morgawr doesn't seem to work though. :/

10:13 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 and nrepl?

10:14 justin_smith: rstandy: cider or nrepl

10:14 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 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 not even in the editor

10:15 rstandy: justin_smith: sorry for the silly question

10:15 justin_smith: np

10:15 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 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 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 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 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 (like in debian's aptitude)

10:20 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 napper: what kind of manipulations?

10:22 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 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 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 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 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 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 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 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 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 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 * seangrove has a hard time wrapping his head around consumer stuff

10:45 justin_smith: angry birds does well with holiday editions

10:46 "$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 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 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 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 TheLastProject: https://www.refheap.com/20719

11:06 that is not yet correct, but I think it is easier to read

11:06 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 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 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 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 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 s/print/println

11:17 justin_smith: TheLastProject: https://www.refheap.com/20719

11:17 edited, I think closer to what you want

11:17 using amalloy_'s suggestion to use apply

11:18 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 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 Err...

11:20 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 Oh...

11:20 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 () is not for grouping in clojure

11:21 ever

11:21 it can make a literal list, or apply a function

11:21 that's it

11:21 TheLastProject: Okay, I need to get that in my head

11:21 But now I wonder how to "group" it then because otherwise it will complain about having too many arguments, hmm...

11:21 * TheLastProject thinks

11:22 justin_smith: what you want is to construct the string so it matches your lookup table

11:22 ,(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 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 ,[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 You people call it a vector

11:25 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 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 ,(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 * TheLastProject tries to grasp that idea

11:27 justin_smith: so I assign a with the value 2

11:27 I assign _ with the value nil (returned by print)

11:27 the reason to do it there is I can then look at things as I construct them

11:27 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 s/third/second/

11:29 Oh man, such a headache, heh...

11:29 I'm not used to coding this way

11:30 It's interesting, but it's... different

11:30 justin_smith: TheLastProject: nthrest

11:30 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 Thank you SO much justin_smith

11:31 justin_smith: very nice, can I see the final result?

11:32 no problem, glad I could help

11:32 TheLastProject: Of course

11:32 justin_smith: https://www.refheap.com/20722

11:32 faust45: is it possible assign metadata to types ?

11:33 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 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 Makes more sense

11:35 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 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 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 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 we use cdt for that

11:40 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 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 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 Got it!

11:42 * TheLastProject goes AFK to eat dinner

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 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 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 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 all the functionality, including changing remote definitions, is in cdt

11:48 napper: right

11:49 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 but I couldn't make any sense of ritz

11:53 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 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 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 https://github.com/prismofeverything/schmetterling repo

11:56 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 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 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 i take it you've seen that before?

12:00 justin_smith: no, but it's something that could be a disaster

12:00 full control of your app's state

12:00 and full access and introspection

12:00 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 (vector-of :int & elements)

12:01 ,(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 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 ,(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 s/note/not

12:09 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 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 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 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 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 * technomancy strokes beard

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 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 they generate the same kind of thing under the hood

12:24 then you can have a final data member in the class itself

12:24 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 I was looking at it, it seemed like you would only be able to define one :static key?

12:46 sorry

12:46 not :static

12:46 it's :state

12:46 or are these two separate things?

12:46 http://clojuredocs.org/clojure_core/clojure.core/gen-class

12:46 dobry-den: gen-class OO in clojure is fun

12:47 feels like some newfangled OO language

12:47 tbaldridge: for certain definitions of fun

12:47 dobry-den: ^

12:48 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 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 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 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 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 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 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 ,((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 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 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 ,(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 ,(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 haha

13:41 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 so I can just wrote those, no biggie

13:43 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 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 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 unless I'm missing something

13:50 justin_smith: client data sneaking arbitrary code into the string?

13:50 hah

13:50 Morgawr: it's a library, it's not an end-user application

13:51 as in, other developers call that function

13:51 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 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 &(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 ~def list*

14:01 Morgawr: danneu: vals

14:01 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 well...I guess it could also be a tree

14:03 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 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 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 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 * 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 * TimMc ducks

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 then we could find the winner

14:19 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 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 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 (on refheap)

14:31 amalloy: Raynes: really? that number seems way too low

14:32 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 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 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 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 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 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 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 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 one simply can't assume that doing so _won't_.

14:41 * technomancy searches for a "call a function; data structure changes... you can't explain that" gif

14:41 cYmen: Where is #clojure-noobs? :)

14:41 danneu: right hurr

14:41 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 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 destructuring ftw

14:46 * `cbp always destructures never not destructures

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 Because I am very surprised that it can be looked up in a way that allows using it as a function.

14:54 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 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 :-(

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 I'm not sure what needs to be fixed

14:59 tbaldridge: poppingtonic: it was replaced by Pedestal App

14:59 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 that gets all items with :key that is 0

15:13 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 ,(: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 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 why not just

15:29 ,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 oh

15:31 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 (def- x 5) doesn't work

15:33 (defn- x [] 5) is tedious

15:33 llasram: (def ^:private foo ...)

15:33 TimMc: defn- is just sugar for defn ^:private

15:34 (Macro sugar, not reader sugar.)

15:35 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 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 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 is there a bool? or boolean?

15:40 `cbp: there is no bool?

15:40 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 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 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 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 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 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 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 "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 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 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 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 haven't used anything but in-line checks personally, so can't tell you more

17:03 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 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 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 oh

17:25 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 jtoy: note it has a db analyzer - you could run that on two dbs, then use data.diff on their tables

17:45 *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 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 akurilin: I dunno, you tell me.

18:22 I've forgotten most of what I've changed in Korma ^_^

18:22 specifically I made it so that bulk inserts would "work okay" by not RETURNING

18:22 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 for large updates Korma right now returns either the first or the last one, forgot

18:24 but essentially only 1 row

18:27 bitemyapp: akurilin: the choices, if I recall were none, keys, and values

18:28 how those map to what data actually gets returned is a little obtuse.

18:29 akurilin: you'd benefit most from reading the code, by my estimation.

18:29 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 akurilin: I'm pretty sure you use Korma about 99x more than I do these days.

18:33 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 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 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 akurilin: yeah, exactly.

18:35 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 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 Alex and I are keeping the lights on and accepting PRs.

18:36 akurilin: bitemyapp, and I appreciate that :)

18:37 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 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 HoneySQL is pretty neat, but I'm not convinced it's the right level of abstraction.

18:38 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 just configure it.

18:40 unless I've missed something.

18:40 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 Warnock's dilemma.

18:49 bitemyapp: please don't do what Somelauw just said :P

18:50 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 whiiiiich is why I usually just have a *log-fn* dilly that people can override...

19:01 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 technomancy: ^^ grumble grumble.

19:02 technomancy: bitemyapp: imma write a fuse adapter for github issues in ocaml

19:02 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 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 * bitemyapp nods

19:04 technomancy: context: I just started using noscript for conkeror, and its whitelisting doesn't work on github.

19:05 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 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 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 akurilin: it's to avoid the tedium of managing your gensym aliases yourself.

19:18 akurilin: which...you had to do in Common Lisp.

19:18 it sucked.

19:18 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 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 Weird, the docs say it should append _number

19:20 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 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 akurilin: Korma isn't a good example of many things.

19:34 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 there's some mess due to young the codebase is, but `cbp did a damn good job.

19:36 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 akurilin: yuo can solve that problem just with closures...don't make my eyes roll that hard, it hurts :(

19:37 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 Regardless, it's a bad fuckin' idea.

19:38 akurilin: bitemyapp, yes, my point.

19:38 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 swarthy: if you want scary code: https://github.com/bitemyapp/brambling

19:39 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 swarthy: heavily optimized and kin da razy but still interesting: https://github.com/aphyr/riemann

19:41 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 akurilin: pure'ish, there's an atom, but the closure takes precedence.

19:41 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 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 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 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 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 unless it's some odd edge case

20:02 seangrove: Thanks amalloy and swarthy, and of course AimHere

20:02 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 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 ,(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 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 justin_smith: ye, even more confusing

20:16 brehaut: jtoy: ok so map takes a function of N arguments and N sequences

20:16 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 ,(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 jtoy: conj on a map takes a key value pair as a vector

20:17 jtoy: and into uses conj from memory

20:19 ,(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 not observably different, of course

20:49 brehaut: amalloy: yeah i figured, but that can be brushed under the carpet

20:51 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 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 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 bitemyapp: I'm just playing around now playing with FSMs

21:06 bitemyapp: I was converting this code to work in CLJS: http://nakkaya.com/2010/06/22/finite-state-machine-implementation-in-clojure/

21:06 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 *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 unless you're THAT worried about stale reads.

21:08 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 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 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 cljs

21:12 bitemyapp: logic_prog: you'd be better served by explaining your needs.

21:12 nightfly: cljs isn't fringe.

21:12 * nightfly fully parsed logic_prog's question now

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:13 * ddellacosta sobs from far across the globe

21:14 bitemyapp: ddellacosta: hey I'm stuck in SF, so we can suffer together (apart)

21:15 * ddellacosta nods in mutual recognition of our sad state

21:17 lpvb: (defn destructuring [{x :x y :y}] ...)

21:17 the problem with ^ is that I lost the name of what's being passed in

21:18 which is a reminder for what should be passed in

21:19 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 (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 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 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 technomancy: I have the clojure side of this written. Just need the emacs integration now.

21:33 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 as long as you force a save before it's invoked

21:40 (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 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 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 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 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 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 and (-> {:x 1 :y 2} (setm :x (fn [x] (+3 x)) :y))

22:18 does the same error

22:18 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 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 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 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 I can write my own, but I'm suspecting this must have been done before.

22:33 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 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 as you could imagine, it is a very low level thing

22:54 akurilin: justin_smith, yeah, definitely looks like serious business.

22:54 thx

22:55 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 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 `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 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 at the exact moment that the exception occured

23:12 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 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 akurilin: also the repro can be odd

23:17 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 so the bug was only reproducible on his machine

23:17 and it wasn't even us, it was a corrupted cookie causing an exception

23:17 well I guess we learned to handle that better :)

23:17 akurilin: justin_smith, ah damn, must have been a pain

23:18 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 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 I have seen someone actually run their whole app inside a with-redefs foorm

23:24 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 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 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 just def the init in each ns, and call all of them from the main ring init

23:27 that way reloading source doesn't have weird side effects

23:27 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 in each ns you make, if the code needs any initialization, you (defn init [] (initialize this namespace... ))

23:29 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 As long as it's idempotent I guess.

23:30 justin_smith: you define it in each ns

23:30 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 really most namespaces don't need an init function

23:32 just the ones that do things like load config files at boot

23:32 or set up a db connection pool

23:32 or create a pool of worker tasks

23:32 that kind of stateful startup stuff

23:32 akurilin: Yeah I have stuff like that and logging levels

23:34 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 Guess I'm about to fin dout

23:36 Raynes: akurilin: Yes.

23:37 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 or at least I only ever used in-ns from a repl

23:43 justin_smith: hmm

23:43 yeah, that could be tricky I guess

23:44 akurilin: http://clojure.org/namespaces

23:44 "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 &(#'+ 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 it may be easier

23:46 akurilin: justin_smith, that's fair, I need to get used to doing that anyway.

23:46 supposedly pushing stuff to clojars is pretty braindead these days

23:46 justin_smith: very easy

23:48 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 so I'm overriding their fn to compute that to support that case

23:51 and folks name their stuff however they want

23:51 I guess the better option would be to let people define their own table name to fk function

23:51 with a default

23:52 so maybe that'd be a PR

23:53 Welp, there's an inflections library, there you go :D

Logging service provided by n01se.net