#clojure log - Oct 28 2014

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

0:01 justin_smith: fairuz: I'd avoid things like database interaction in the live mode - I think it will try to

0:01 fairuz: and as you edit the code it will likely repeatedly execute the command, which likely isn't what you want?

0:02 fairuz: if you want the advantage of live mode you could make a function that generates the *data* that generates the db action, and then use live mode to look at that data

0:02 and finally have a trivial function that takes that data and plugs it into a db call

0:02 (that you don't use in a live repl, of course)

0:02 *live mode

0:06 fairuz: yeah that's what I realize too

0:07 I made a mistake of trying to connect to the database in live mode

0:07 and it create some files along the way as I type the path

0:07 so need to clean that up :('

0:07 justin_smith: fairuz: having one function that does all the purely argument based logic and has no side effects (only a return value) and another (minimal) one that makes the side effects happen is pretty much the right way to do things in fp

0:08 fairuz: this also makes things like testing much more powerful, and easier to use

0:08 fairuz: justin_smith: ok great. I will slowly trying to adapt fp in my work :)

0:09 justin_smith: in clojure fp style is pretty much best (until performance backs you into a corner)

0:10 and even then, much of clojure is tailored so the fp way to do it will be the way that performs decently

0:15 fairuz: j

0:47 justin_smith: TIL lein beanstalk is broken with clojure 1.7 :(

0:48 sm0ke: feeling adventurous?

0:49 justin_smith: sm0ke: feeling like getting staging deployed and I found out at the last minute that 1.7 breaks my deploy step

0:50 I've been working with 1.7 for the past month, everything was great - until the part where I package it up for AWS

0:50 sm0ke: hurm there is a lein docker builder or something .. but probably too much?

0:50 justin_smith: beanstalk does not use docker

0:51 they run tomcat, you upload a war file

0:51 sm0ke: never used beanstalk, so you dont get a machine?

0:51 justin_smith: you do get one, but its cheaper because things are pre-configured, streamlined

0:51 sm0ke: weird, what if you needed some native libs to be installed?

0:51 justin_smith: has automatic scaling etc. that works because the boxes are generic

0:52 sm0ke: then you don't use beanstalk I guess

0:52 sm0ke: :/

0:52 justin_smith: it's not for everyone

0:52 but if it works for your project, it is simpler and cheaper than a regular aws instance

0:52 sm0ke: aws is awful for long running services imo

0:53 and costly too

0:54 justin_smith: it's not very general or flexible, but it's very plug and play, which is why the client uses it

0:54 I'm just using their preferred stack

0:55 sm0ke: "But it works perfectly on my machine!"

0:55 this sould be printed on a t shirt

0:55 justin_smith: sm0ke: beanstalk actually prevents that - it wasn't that my project wouldn't run on beanstalk, it's that my clojure based deployment / building plugin broke with 1.7

0:56 sm0ke: hurm but building part is done locally right? why did you not see this before?

0:56 justin_smith: sm0ke: because I was not building it

0:57 just running it

0:57 sm0ke: ah

0:57 justin_smith: to deploy, I pack up a war file

0:57 sm0ke: lein ring?

0:57 justin_smith: which is a jar with certain special classes defined

0:57 lein beanstalk, it uses lein ring, but also has its own stuff

0:58 sm0ke: just revert to 1.6 than ? dont tell me you areusing transducers?

0:58 justin_smith: sm0ke: I reverted

0:58 sm0ke: good :D

0:59 justin_smith: I was just griping about a) the process of narrowing down the root cause of my issue

0:59 (which wasted about 45 minutes of my precious time)

0:59 and

0:59 well, mainly just that

1:28 n_blownapart: hi anyone here advocate using lighttable to learn clojure? I know a little ruby but never quite learned how to properly use the repl gem pry.

1:29 justin_smith: n_blownapart: light table is not very actively developed right now

1:29 if you want an IDE I hear nothing but good things about cursive, which is a plugin for intellij idea

1:30 n_blownapart: justin_smith, really? ok, thanks, I heard clojure runs great on lighttable and its a good learning tool but I'm not very experienced with programming.

1:30 justin_smith: OK

1:31 light table is kind of cool, and don't feel like you shouldn't try it out

1:31 it just isn't very actively developed, and hasn't been for a while

1:31 n_blownapart: justin_smith, thanks kindly

1:31 justin_smith: also, especially when you are first learning, you can just use the repl from a terminal

1:32 with the basics of require with :reload and the command line editing keys you can get a lot done

1:32 n_blownapart: also, if you aren't yet, start with lein

1:32 it makes clojure much simpler

1:32 n_blownapart: lein? one sec.

1:33 justin_smith: n_blownapart: lein is our package manager and build tool of choice

1:33 it finds and downloads dependencies, and helps with the automation of building / running your app

1:34 n_blownapart: if you used the "gem" tool just about every time you used ruby (except maybe on production) that is kind of the role lein has with clojure for most of us

1:35 n_blownapart: I'm new to programming. I went through a ruby book and learning linux now. a confused noob still not grasping oop very well.

1:35 justin_smith, ^

1:35 justin_smith: OK

1:36 well that's helpful, because we don't do a whole lot of OOP

1:36 and the hard part for many newcomers to Clojure is expecting to do things the OO way and being confused

1:36 n_blownapart: good advice. thanks justin_smith I'll check out your suggestions.

1:37 justin_smith: n_blownapart: lein is very easy to install, it's just a single file and downloads everything else it needs

1:37 make sure you use 2.x and not 1.x though (your linux package manager may only have 1.x)

1:37 n_blownapart: cool I heard clojure was tough to learn . wish me luck ! justin_smith

1:38 justin_smith: n_blownapart: and don't be afraid to ask questions

1:38 n_blownapart: excellent thanks.

1:38 justin_smith: I think it's easier if you don't know other languages yet - the really hard parts about clojure are how it diverges with many of the mainstream assumptions

1:39 n_blownapart: also, there is a really good tutorial oriented for people who are new to programming

1:39 n_blownapart: http://aphyr.com/posts/301-clojure-from-the-ground-up-welcome

1:39 n_blownapart: no prob. I have no assumptions formed. got it thanks justin_smith !

1:43 justin_smith: n_blownapart: also, I just double checked, that tutorial starts with downloading lein and using it, so it's a great resource right off the bat

3:08 zhcpkl: Anyone have any experience with tess4j?

3:18 fairuz: Hi guys. How to list down all available functions from a library?

3:30 roelof_: hello, why do I get this error message ( Map literal must contain an even number of forms) on this form : http://pastebin.com/HHDpfbL9

3:34 hello, why do I get this error message ( Map literal must contain an even number of forms) on this form : http://pastebin.com/HHDpfbL9

3:35 broquaint: roelof_: I don't think that form is causing that error, there are no map literals in it and it's valid code.

3:35 nhanH: That snippet of code by it self is fine, are you sure the error is not somewhere else?

3:36 roelof_: broquaint: wierd, when I do lein midje I see this error appear

3:36 broquaint: Most odd.

3:38 roelof_: broquaint: yep.that is why i asked here for help

3:39 broquaint: Why do you think it's that piece of code in particular?

3:39 roelof_: broquaint: because that is the last what I have changed

3:42 broquaint: And if you drop that 'lein midje' works ok?

3:43 nhanH: Anyone here familiar with at-at?

3:44 roelof_: broquaint: when I do the same in repl and do (do-a-thing 5) I get a answer and no error message

3:45 very wierd., I deleted the file and did a fresh download from github. Changed it to the script and everything works

3:46 mavbozo: roelof_: i presume you have done 'lein clean'?

3:47 roelof_: mavbozo: nope, just deleted the file and did a git clone command

3:49 m00nlight_: lein deploy will only deploy the jar not the standalone.jar?

3:53 jonathanj: i don't suppose there is Dash (the Mac app) integration with clojuredocs.org? :(

3:54 (that i don't have to generate manually)

4:00 mavbozo: m00nlight_: yes

4:03 m00nlight_: mavbozo: So why the building jar report an error unbound var of function I write in a file and I required in another file?

4:09 mavbozo: m00nlight_: have u try 'lein clean' & 'lein compile'

4:10 m00nlight_: mavbozo: Yes

4:11 foofoobar: Hi. Is there something like tour.golang.org for clojure?

4:16 mavbozo: m00nlight_: you try to build the jar with 'lein jar'?

4:16 m00nlight_: lein uberjar

4:34 ered: foofoobar: did you look at http://www.tryclj.com/

4:34 ?

4:35 foofoobar: ered: yes, it’s very short :/

4:35 ered: ah

4:35 you're looking for something more in depth then?

4:36 foofoobar: ered: yes

4:36 ered: hmm

4:36 foofoobar: The golang tour showed a lot of the go language with examples etc.

4:36 ered: ah wow

4:36 golang tour is a lot more in depth than i remember

4:37 could have sworn tryclj is longer

4:38 hmm

4:38 trying to think of stuff, most of what i learned from initially was reading and following along in my own repl, not on a website

4:39 i bet there's better stuff now though

4:39 reading books*

4:40 clojure wiki links to this article, but it's not interactive like golang tour is http://java.ociweb.com/mark/clojure/article.html

4:41 worst case there you could read through that and install lein so you have your own repl to follow along

4:41 :\ there should definitely be something better though

4:41 foofoobar: okay, thank you.

4:41 I have lein installed (and it’s up to date when running upgrade), but I get the following error when running lein repl: Exception in thread "main" java.lang.IllegalArgumentException: Cannot open <#<Socket Socket[addr=localhost/,port=54060,localport=54080]>> as an OutputStream. (form-init4763471810287640460.clj:1)

4:41 ered: thankfully lein isn't too bad to install, i know go can be a little bit of a hassle to set up the environment

4:42 ah okay

4:42 foofoobar: ah sorry, I was in a wrong directory.

4:42 ered: ah

4:42 foofoobar: Calling it in an empty directory it works

4:42 ered: yeah true

4:43 or in a tiny project directory should be safe too

4:43 the article i linked recommends doing it that way

4:43 foofoobar: ok

4:43 thanks

4:45 irctc: I am currently reading programming clojure 2nd edition and I enjoy it so far..

4:45 ered: irctc: true, i mean i learned from a book too

4:45 but books cost money :)

4:45 irctc: foofoobar, maybe try with this book

4:45 ered: (though a lot of books have online editions)

4:45 (joy of clojure's site is broken atm)

4:45 i really like joy of clojure

4:46 irctc: Ill check that out once I finish with this.

4:46 ered: oh, i originally learned from the o'reilly book

4:46 irctc: The only part I don't like about clojure books is that they tend to be really hefty

4:46 ered: yeah there's... a lot of material

4:46 plus if you get into the rich hickey talks and all that

4:47 i still have clojure in action on my backlog too

4:47 bought it forever ago but still haven't gotten to reading it yet

4:47 irctc: There are other means to obtain electroci copies of the book, if you are really poor and thirsty

4:47 ered: :3

4:47 irctc: oh another one i was following was brave clojure

4:47 that one had a section on setting up emacs which i thought was nice

4:48 irctc: I currently use vim, is there any reason to switch to emacs ?

4:48 I see lots of people using emacs for clojure

4:48 ered: irctc: personal preference mostly

4:48 historically (like 3 years ago) vim was terrible for lisp development

4:48 i know this from personal experience

4:48 common lisp specifically

4:49 that's what got me to switch to emacs in the first place

4:49 i still use evil-mode though

4:49 so vim keybinds and all that

4:49 the login button on manning is an image so it's impossible to find :|

4:50 irctc: ah I see, well i use vim-clojure-static and fireplace and raibow_parentheses plugin and it works fine,

4:50 I can eval in the same buffer

4:50 ered: yeah i hear fireplace is nice now

4:50 it used to be for common lisp, all there was was like slimv and it barely worked

4:50 compared to slime

4:50 in emacs

4:51 okay finally redownloaded joy of clojure, remembered why i liked it

4:51 it has chapters at the end on stuff like clojurescript and core.logic

4:52 irctc: there is also this enormous book called Clojure in small peices :)

4:53 I like the whole literate programming idea

4:53 ered: i know haskell people love it

4:53 irctc: Timothy Daly is the editor :)

4:53 ered: they have that whole .lhs format that's parsed completely different from .hs

4:53 (literate haskell)

4:54 there's the one doc library in clojure that really promotes literate too

4:54 i think that one is marginalia?

4:54 yeah

4:54 https://fogus.github.io/marginalia/

4:54 aztak: are we talking about books? I'm currently working through this one: https://leanpub.com/fp-oo -- recommended :)

4:55 irctc: cool, and clojurescriptone too i think

4:55 ered: neat, that book has an interesting approach

4:55 irctc: http://clojurescriptone.com/documentation.html

4:55 ered: not so useful to me personally but i can see where it comes in handy for coming from heavy OOP world

4:56 hmm

4:56 yeah i haven't done enough clojurescript to say for sure how i'd do it

4:56 i'd like to get into it more though

4:56 irctc: i bought that one too, didn't like it much

4:56 ered: isn't clojurescriptone the one that's big on coupling the server and browser to the same framework?

4:56 irctc: too slow

4:56 ered: or is that pedestal?

4:57 oh, this one is just docs

4:57 nvm

4:57 i am thinking of pedestal

4:57 i will definitely look at this one

4:58 aztak: ered: the interesting thing with the fp-oo book is that you slowly (well) discover that OO is basically FP with implicit scopes :) In that way it's a nice companion to http://www.smashcompany.com/technology/object-oriented-programming-is-an-expensive-disaster-which-must-end

4:59 irctc: isn't pedestal just a web server for clojure..need to check

4:59 ered: aztak: neat

4:59 irctc: Well OO should not be used for storing data into object, it should be storing behaviours.

5:00 ered: my style in OO languages is as "functional" (read: defensive) as i can get away with these days

5:01 irctc: aztak, thanks for the link, I like reading about horrible OO concepts :)

5:02 aztak: irctc: it's a looooong read.. I confess that I didn't read every single word.. but there are some interesting quotes in there.

5:27 sveri: This link took me about 90 minutes to read, however, a text ending with a citation of joel spolsky is almost always worth it :D

6:31 Urza-: Hi, im looking for some information regarding the benefits of clojure (have to give a presentation about it on friday). I've been looking around the web, and have done a couple of tutorials, but the main "why would you actually want to use this language" still eludes me. Any golden tips?

6:31 SagiCZ1: Urza-: how about some of the classic rich hickey presentations?

6:32 aztak: Urza-: functional programming in itself is an argument. Also the 'decomplecting' syntax of Clojure is a big win compared to other FP languages in the JVM imo.

6:33 SagiCZ1: i would focus on the fact that clojure emphazises immutability and pure functions which lead to code that is easier to reason about, also it inherently reduces problems with concurrency

6:34 aztak: http://thecleancoder.blogspot.se/2010/08/why-clojure.html ?

6:34 (that was the first google hit for "why clojure?" ;))

6:34 SagiCZ1: also point out the advantages of JVM as a mature platform which is thouroughly tested, fast and reliable and the ability of using the whole java plethora of open source and/or commercial libraries

6:34 hyPiRion: Urza-: http://www.infoq.com/presentations/Simple-Made-Easy – great talk regardless of whether you adopt Clojure or not

6:35 but Clojure is more or less built around this (simplicity)

6:35 Urza-: ah thanks for the info guys

6:36 rick hickey presentations seem like a good starting point, shame i forgot my headphones today :(

6:36 SagiCZ1: Urza-: you can go through the slides on infoq

6:36 Urza-: ah yeah

6:39 SagoCZ1, why clojure over other FP languages? also what do you mean 'decompleting'?

6:39 err aztak I mean

6:40 justin_smith: Urza-: the term is decomplecting

6:40 reducing complexity

6:40 kungi: Urza-: Mostly because clojure is "modern" and on the JVM. This alone makes it much more valuable for real world use.

6:40 aztak: justin_smith: (sorry - typo)

6:41 justin_smith: aztak: you got it right

6:41 Urza-: I see, most of the tutorials i've done so far have focussed on that aswell. Heres how you you would write program x in java (25 lines), and here it is in clojure (3 lines).

6:41 aztak: ah, sorry for complecting the discussion with noise :) I should have scrolled up and read what I wrote *grin*

6:42 mavbozo: Urza-: "Clojure: the JFDI language" can be a inspiration https://docs.google.com/presentation/d/15-7qFy6URdE7Owi2LitkQI_OHBu1AFWPUwHxgBc-O4E/edit?usp=sharing

6:42 justin_smith: aztak: though I would argue that syntax is only a trivial case of decomplecting in clojure, and it's more about the simle vs. easy philosophy of the lang semantics

6:42 Urza-: however the benefits do seem closely tied to the data structure (lists, vectors, maps)

6:43 justin_smith: *simple

6:43 mavbozo: Urza-: lots of materials, but in the end, depends on your audience

6:44 Urza-: audience consists of junior programmers

6:44 aztak: justin_smith: yeah, true. But to me a simple (and unambigious) syntax is a great selling-point compared to (for example) Scala.

6:44 SagiCZ1: Urza-: yes, because data and its processing is what programming is about.. if you make data easy and efficient you solved many problems of today's languages

6:45 aztak: The language syntax is more complex in Java than in Clojure. But again - have a look at the Simple/Easy video..

6:45 SagiCZ1: aztak: the syntax of clojure has less concepts than any other language i know, but knowing and understanding core functions is not easy at all

6:45 justin_smith: Urza-: I think a big aspect of Clojure's niche is the overlap of default immutability / jvm platform / dynamic typing - those three combined are kind of unique

6:45 mavbozo: Urza-: what languages that most of those junior programmers familiar to?

6:45 justin_smith: Urza-: my employers would not have been able to use Clojure if it was not hosted on the jvm

6:46 Urza-: mostof them have recently completed their java certification (or are still working on it)

6:46 aztak: SagiCZ1: agreed. But at least you can focus on that without spending time on accidental complexity introduced by a big syntax :)

6:46 SagiCZ1: aztak: agreed

6:46 hyPiRion: the Clojure syntax is to some extent more complex. You cannot distinguish function calls and control flow (macros) in Clojure, but you can in Java.

6:47 SagiCZ1: hyPiRion: the question is do you need to distinguish them?

6:48 mavbozo: Urza-: Clojure by Java Programmers by Rich Hickey could be a great starting point http://www.youtube.com/watch?v=P76Vbsk_3J0

6:48 hyPiRion: SagiCZ1: Imagine (foo t (bar x) (bar y)) – bar is a function with side effects (say println). How many times will we see a println in this case?

6:49 I'm not saying it's worse than Java, but it's different.

6:49 mavbozo: Urza-: It's long, more than 2 hours, but because you know your audience's knowledge about java, you can adapt it

6:49 SagiCZ1: hyPiRion: i see your point

6:49 Urza-: yeah good tip, thanks

6:51 justin_smith: hyPiRion: vastly outweighed by Foo.bar(baz) - how exactly has the internal state of baz been pushed around (not an issue in a majority of clojure code)

6:52 Bronsa: justin_smith: that has nothing to do with syntax though

6:53 hyPiRion: justin_smith: I agree, but that hasn't that much to do with syntax

6:53 justin_smith: hyPiRion: right, not a syntax issue!

6:53 a counterbalancing complexity is all

6:53 Bronsa: hyPiRion: we actually have a way to distinguish between macro calls & function calls -- indentation :)

6:54 justin_smith: Bronsa: don't forget syntax highlighting

6:54 haha

6:54 Bronsa: heh

6:55 I was actually quite serious btw, indentation plays a huge semantic role in lisps

6:55 justin_smith: Bronsa: it does, but like highlighting it's not enforced or evaluated by the compiler

6:55 Bronsa: right

6:55 SagiCZ1: justin_smith: what seems complex to me in clojure are the exit points of functions, since there is no return keyword, it is very hard to see for me if i didnt forget to add correct exit path

6:55 hyPiRion: Bronsa: and binding forms. They are quite noticable

6:56 justin_smith: SagiCZ1: but that can be determined by the paren nesting - a macro aware editor program can determine it

6:56 kungi: justin_smith: Does Emacs differentiate between macros and functions when syntax highlighting?

6:56 SagiCZ1: justin_smith: i guess i just have to train my eye to see it

6:57 justin_smith: kungi: no, but it should imho

6:57 mavbozo: btw, talking about indentation, any of you guys using lisp code beautifier

6:57 hyPiRion: kungi: for known macros, not self-defined ones

6:57 kungi: mavbozo: Is there such a thing

6:57 Bronsa: a tools.analyzer backed editor might be able to highlight differently the exit points of a functino

6:57 justin_smith: hyPiRion: oh, yeah, I guess they have a consistent color...

6:58 mavbozo: kungi: c family has code beautifier program

6:58 justin_smith: Bronsa: that would be awesome

6:58 kungi: mavbozo: I know but I haven't found one for clojure

6:58 justin_smith: Bronsa: for example highlighting each "tail" of a form would be great

6:58 kungi: I like the go philosophy in this case. "Use goformat or go ...."

6:58 mavbozo: kungi: agree

6:59 justin_smith: kungi: use the clojure-mode indentor for emacs?

6:59 kungi: justin_smith: I already do, but this does not solve the problem completely.

6:59 justin_smith: we have a clojure lib that does indenting / pretty printing for code though right?

6:59 kungi: agreed

7:00 kungi: justin_smith: I would like to have a tool where I can say: I want my lines to be 100 characters wide => Go and produce nice lisp indetation for me.

7:00 mavbozo: justin_smith: it doesnot fix trailing parenthesis last time i checked

7:00 kungi: Then run on all source files before saving them.

7:01 justin_smith: mavbozo: yeah, it's incomplete and not as bossy as a proper formatter

7:01 it doesn't override any line-break decisions

7:01 only indentation ones

7:02 kungi: A tool to enforce a company wide style would be great

7:02 mavbozo: kungi: c has formatter that let's you choose, say, kernighan-richie style and others that i forgot.

7:03 kungi: mavbozo: I know about indent which helped a lot

7:03 mavbozo: weird, for all those talks about letting machine do our job, but no formatters come from lisp programmers for ~50 years

7:04 dysfun: i don't think i agree. i find that a lot of my clojure has to be manuall reindented to read the easiest

7:04 justin_smith: ,(clojure.pprint/write '(let [a 0 b 1] (+ a b)) :dispatch clojure.pprint/code-dispatch)

7:04 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.pprint>

7:04 dysfun: there's some sort of subconscious logic balancing brevity with ease of reading

7:04 justin_smith: ,(require 'clojure.pprint)

7:04 clojurebot: #<SecurityException java.lang.SecurityException: denied>

7:04 justin_smith: blerg

7:05 mavbozo: won'twork with the bot, but check out what pprint/write does there

7:06 dysfun: speaking of the bot, where's the evaluator source code? i want to see how it's dealing with the securitymanager stuff

7:06 SagiCZ1: why would clojure repl use both of my cores when i didnt design for parallelism anywhere, is it normal?

7:07 justin_smith: SagiCZ1: are you using lein repl?

7:07 or nrepl

7:07 SagiCZ1: lein

7:07 dysfun: lein has to trampoline another instance

7:07 justin_smith: lein repl opens an nrepl process, and also a client of the process

7:07 Bronsa: justin_smith: the issue w/ using t.a for backing an editor is that to be accurate t.a needs to evaluate code

7:08 justin_smith: Bronsa: yeah that could get very messy

7:08 Bronsa: our kingdom for purity and an IO monad, huh

7:08 dysfun: justin_smith: haskell is --> that-a-way

7:08 Bronsa: justin_smith: I know that somebody in the cider team is trying to use it anyway, I've added some hooks that should allow for unevaluated code to be analysed but have no idea how that's working out for them

7:09 justin_smith: dysfun: just pointing out that feature addresses that issue

7:09 Bronsa: justin_smith: the need for evaluating code comes from macros actually

7:09 SagiCZ1: justin_smith: what is a "client of the process" ?

7:09 Bronsa: it's a known "limitation" of lisps

7:09 mavbozo: justin_smith: i tried in in my emacs cider repl and it returns (let [a 0 b 1] (+ a b)) in one line

7:09 justin_smith: is that what you expect?

7:10 justin_smith: SagiCZ1: the thread that reads your input, and then sends it over the network to the one that does the eval part, and then reads the result over the network, and prints it

7:10 SagiCZ1: justin_smith: thank you

7:11 justin_smith: mavbozo: no, that's less than ideal - but try a do form with multiple printlns

7:11 Bronsa: mavbozo: writing a lisp code formatter is not an easy task, because of how little syntax lisp has

7:13 dysfun: Bronsa: writing macros in other language is also not an easy task because of how much syntax they have :)

7:15 SagiCZ1: what is the best way to store timestamps in clojure? just a string? or some sort of long? or java's Date object? i need it to be efficient and reasonably small

7:16 maybe java.sql.Timestamp

7:17 daniel__: SagiCZ1: to store them in a database?

7:17 then yes, java.sql.Timestamp

7:17 SagiCZ1: daniel__: no, just to use them internally

7:17 dysfun: why not just use joda time?

7:18 SagiCZ1: dysfun: i could, so there is no idiomatic clojure way?

7:18 dysfun: well, clj-time is an idiomatic clojure wrapper for joda time

7:19 SagiCZ1: dysfun: sounds greay

7:19 daniel__: i was about to say clj-time and to-sql-date

7:19 SagiCZ1: *great

7:19 justin_smith: SagiCZ1: I usually just use numeric timestamps, but it really depends on what properties you need - I just need offsets between two of them and the numbers suffice for that

7:19 dysfun: the moment i hear someone talking about 'efficient and reasonably small'

7:19 i get a little twitchy

7:20 justin_smith: ,(.getTime (java.util.Date.))

7:20 clojurebot: 1414495153784

7:20 dysfun: data is just data, it can be transformed into various shapes

7:20 the 'efficiency' is in how you manipulate it

7:20 justin_smith: dysfun: cache-line and heap usage are things you know

7:21 dysfun: and have you profiled and discovered there's a problem?

7:21 mavbozo: SagiCZ1: designer of datomic chose java.util.Date. So, I think it suffices for lots of cases

7:21 clgv: :(

7:21 dysfun: and frankly if you're going to be optimising cache lines, why on earth are you programming clojure?

7:22 clgv: then better use clj-time - java.util.Date and the surrounding API is just broken

7:22 justin_smith: dysfun: not saying they are the only things, just saying they are things, and sometimes they matter

7:22 clgv: everything is a thing, right? :P

7:23 justin_smith: clgv: it's an idiom

7:23 perplexa: is anybody here familiar with clj-time? i'm trying to figure out the most elegant way to get a datetime object for the current hour, (t/now) gives me #<DateTime 2014-10-28T11:14:21.597Z>, i get #<DateTime 2014-10-28T11:00:00.000Z> with (t/date-time (t/year (t/now)) (t/month (t/now)) (t/day (t/now)) (t/hour (t/now))) but there must be a more elegant way, maybe (tc/from-long (* (long (/ (tc/to-long (t/now)) 3600000)) 3600000)) - that works, too.

7:23 dysfun: they do indeed. but perhaps something where you actually control memory allocation directly might be a better solution for dealing with cache lines

7:23 perplexa: but i don't know what would be prefered ;x

7:25 justin_smith: dysfun: and also, thinking about it a bit more, they are just criteria for putting your data into a specific shape, which does not contradict your point, in fact it re-enforces it in a way

7:26 dysfun: see for example disruptor - they use the jvm to get high performance cache line usage (by shoving everything into a ring buffer array)

7:27 s/everything/the part that matters/

7:29 dysfun: i'm not saying it can't be done

7:31 see, in perl, if i had a performance problem, i'd just go write a little bit of. Granted, I have to do that more often in perl because standard performance is not nearly as good as clojure. But when performance does become a problem in clojure, it's not nearly as easy to make it run faster

7:31 "little bit of C"

7:31 justin_smith: well, we do have interop, and to re-use my prior example, disruptor outperforms any c++ alternative

7:32 (but that's because of good design, and a smart c++ project could replicate it and out do them, of course)

7:34 dysfun: is there a nice clojure wrapper for disruptor?

7:34 justin_smith: not that I know of

7:34 dysfun: pity. i was looking at immutant, but it all feels a bit "enterprise"

7:34 justin_smith: and it's a pretty niche tool (low latency message queue with a very opinionated architecture)

7:34 dysfun: the app i'm building, well i'd quite like to ship a single config file with it, not about 40

7:34 though embedding something like hornetmq would be awesome

7:36 there's this enormous tendency of java apps to support every config option under the sun, i've noticed :(

7:36 it all confuses my poor little brain

7:36 justin_smith: dysfun: yeah, disruptor is not inter-process, it's for in-process queues

7:36 dysfun: immutant embeds hornetmq if you let it

7:37 justin_smith: hugo duncan code is often good https://github.com/hugoduncan/hornetq-clj

7:37 dysfun: heh, i used ritz for the longest time

7:37 justin_smith: though the typo in the readme is a bad sign...

7:38 hotnetq

7:38 dysfun: yeah, i saw

7:38 they're next to each other. easy to do

7:38 and when i used to work with magento, i never did stop myself from typing 'magneto' and correcting it every tie

7:39 justin_smith: haha

7:39 perplexa: i think i've found the answer to my question :P

7:39 (-> (t/now) (.withMinuteOfHour 0) (.withSecondOfMinute 0) (.withMillisOfSecond 0))

7:39 justin_smith: someone should come out with a magento-killer named Xaiver

7:39 perplexa: unless that massive joda datetime has a better way ;x

7:39 * perplexa keeps looking

7:40 justin_smith: dysfun: or perhaps proeffserX

7:40 dysfun: oh, right, i get you now. the intentional misspelling

7:40 * dysfun has almost finished his first cup of coffee, check back in an hour

7:56 SagiCZ1: justin_smith: yeah i guess plain numbers wouldnt suffice here.. i need to parse various formats of dates from the source data, so i need clj-time.format anyways.. might use the core as well

7:57 mbac: so i have a tick function and a draw function. i want the tick function to update world state that the draw function reads. i guess the tick function also needs to watch an event stream whereas the draw function gets driven by a library timer. do i want to use vars to share the world-state and async to drive the tick function?

7:57 a stm approach seems like inefficient overkill for this, on cursory reading

7:58 justin_smith: mbac: one thing that has worked for me is to have a pure-data representation of world state, and a function that takes a world state, and a series of events since last update, and returns an updated state

7:59 mbac: the result of this calculation can then be fed to a "generate scene" function, the output of that offered to the drawing function

7:59 mbac: sounds elegant, but really i just want a buffer that one function running in a loop can update and the other function running in a loop can read

8:00 the ugly imperative thing is the way forward :P

8:00 justin_smith: mbac: "just" is tricky here, but you can put it in an atom if you like

8:01 mbac: i think atom is what i was looking for. it seems like i would need to alternate buffers to avoid making state-swaps so costly

8:02 SagiCZ1: mbac: i was dealing with similar problems and with many tips from this channel i managed to avoid stm altogether so far.. i basically used what justin_smith just described

8:06 sveri: Hi, are there any advantages that liberator provides over compojure routes?

8:06 justin_smith: sveri: liberator simplifies a bunch of the patterns that you have with a REST service

8:07 sveri: it makes it easy to do a bunch of things that are all possible with compojure, just more tedious

8:07 sveri: justin_smith: so basically it's an abstraction?

8:08 justin_smith: (on the other hand, if what you are doing is not a RESt service, I think liberator would be a pain in the ass)

8:08 sveri: compojure is an abstraction too, they are different abstractions :)

8:08 sveri: I like how this page presents it http://clojure-liberator.github.io/liberator/tutorial/decision-graph.html

8:09 there's a "decision graph" on that page, showing the amount of logic liberator simplifies

8:09 sveri: Hm, I see

8:09 justin_smith: and REST services tend to have common decision trees, deriving from the spec

8:10 so why not have a layer that is formed around that

8:10 sveri: I guess, no one rly implements all that logic if he goes without liberator

8:10 justin_smith: all that said I haven't used liberator yet - but I did a lot of work on another clojure web platform and I like the design from what I have seen

8:11 sveri: but good code should have :)

8:11 sveri: justin_smith: that's the problem with good code, a lot of things should be in there, but, well, I guess you know yourself

8:12 justin_smith: sveri: I like the fact that it makes it simple to handle the error cases with the right response codes, and to describe the status you would present to a client

8:13 sveri: justin_smith: Hm, I guess I just give it a go and see how it works, thank you very much

8:14 justin_smith: sveri: also, unless I am mistaken liberator and compojure are orthogonal - you could plug a resource definition into any router you like, and the docs show using compojure because that is the router most people use

8:15 sveri: for the tool I worked on we ditched compojure because we used a db to describe routes (for internal workflow reasons) and compojure makes data-driven route generation more difficult than it should be

8:16 sveri: justin_smith: yea, I just saw the compojure example

8:17 justin_smith: sveri: oh wow, I am just looking at this for the first time and after years of doing webapps it's making me so happy: http://clojure-liberator.github.io/liberator/tutorial/debugging.html

8:17 dysfun: justin_smith: high praise indeed

8:17 justin_smith: sveri: it is an automatic and smart way to do the ad-hoc stuff I end up doing when debugging a site...

8:18 dysfun: just got done updating all routes on a client site to use textual slugs from the db rather than numeric ids...

8:18 I wish I had that debugging functionality they are showing here while doing that

8:19 dysfun: when I was a kid, at one point my dad jacked up our house to put a new foundation underneath it - it felt kind of like that :)

8:20 dysfun: justin_smith: so what *does* it gie you for all this fancy debugging?

8:20 sveri: justin_smith: yep, that looks rly awesome, one more reason to try it out

8:20 jeffterrell: Wow, that is nice. Just started using Liberator (after doing my last API by hand), and I'm so looking forward to all of this.

8:20 dysfun: just all this X-Liberator-Trace?

8:20 justin_smith: dysfun: and that flow chart

8:21 sveri: I mean, even developers like flow charts!

8:21 mavbozo: justin_smith: my sympathy for dealing with url schema without identifier for machines

8:21 justin_smith: dysfun: what I was doing with way too many logging calls

8:21 mavbozo: the customer is always right, right?

8:21 dysfun: nice to have that integrated, yeah

8:22 might have to steal some of that

8:23 mavbozo: justin_smith: no, but we must live to fight another day

8:24 justin_smith: so, what do you use to make routes as compojure route replacement?

8:25 justin_smith: mavbozo: https://github.com/caribou/polaris it allows creating routes based on functions taking edn data

8:26 mavbozo: using db to govern the routes isn't always a smart choice, but we used it for a particular workflow to some success

8:27 mavbozo: and I can imagine other routes-as-data use cases

8:28 mavbozo: justin_smith: wow, I didn't know that polaris exists. makes me wonder why it does not exist in clojure-toolbox.com cause I use it first to find libraries. At first, I thought you use bidi https://github.com/juxt/bidi

8:29 it seems there are lots more routing libraries out there

8:29 pandeiro: liberator users: is there an easy way to marshall java.sql.Timestamp values in my tables into JSON?

8:30 justin_smith: mavbozo: polaris is part of caribou, which is listed there

8:31 mavbozo: justin_smith: i looked for libraries not frameworks :p

8:32 pandeiro: tables from sql databases?

8:32 justin_smith: mavbozo: there's a gray area :) we aimed to make each part of caribou independently repacible

8:35 pandeiro: mavbozo: yeah, doing it with this way: https://github.com/clojure-liberator/liberator/issues/71#issuecomment-54992507

8:35 dysfun: interesting. that works similarly to something i've written (and not yet released)

8:36 (polaris)

8:36 justin_smith: dysfun: that's a good sign I think :)

8:36 dysfun: if two different people come up with similar looking things, it's generally the case

8:37 justin_smith: dysfun: polaris was made by three of us, after a lot of arguing and speculating and heavy collective design work

8:37 (based on limitations in our previous ad-hoc solution)

8:38 dysfun: arguing is totally necessary

8:39 justin_smith: dysfun: indeed, it's good if you can keep things functional and avoid side effects on the arguments too :)

8:40 dysfun: well a lot of stuff i've been doing really has been making stuff declarative with data

8:40 for various reasons

8:40 justin_smith: dysfun: yup, I was attempting a subtle pun

8:40 but yes

8:41 dysfun: yes, i chose to save you the embarrassment :)

8:41 justin_smith: haha

8:41 (side effects in our case being any damage to the professional or friend relationship of course)

8:42 mavbozo: justin_smith: hohoho

8:42 dysfun: yes. having just gone into business with two friends, this is going to be entertaining

8:43 i can't count how many people have told me not to do this. but i also realised that there was basically no other way of getting the thing off the ground without sacrificing things i didn't want to sacrifice

8:48 mavbozo: pandeiro: i guess there's no easy way because in that link you gave there's a statement that says liberator use clojure.data.json but they do not parametrize data.json's :value-fn

8:49 pandeiro: mavbozo: yep that's the issue; extending the type is easy enough

9:00 justin_smith: pandeiro: you can extend clojure.data.json by extending a type to the JSONWriter protocol

9:01 https://github.com/clojure/data.json/blob/master/src/main/clojure/clojure/data/json.clj#L395

9:01 see how it is done for the built in types, but you can do this from your own namespace for whichever types you like

9:02 (btw this is what I like about protocols)

9:02 pandeiro: justin_smith: yeah the link i posted does exactly that

9:03 i admit i never use protocols or types/records so it feels foreign to me

9:03 but this seems like the ideal use case

9:03 justin_smith: also, instead of (str date) you could use (bean date)

9:03 ,(bean (java.util.Date.))

9:03 clojurebot: {:day 2, :date 28, :time 1414501376263, :month 9, :seconds 56, ...}

9:03 pandeiro: ha nice

9:04 justin_smith: that uses reflection though

9:04 cheaper to grab the fields you care about

9:05 pandeiro: I saw your question regarding an easy way, but did not see that link before

9:05 pandeiro: but to me what's in that link *does* look like an easy way :)

9:05 pandeiro: justin_smith: np thanks for the explanation

9:05 i hadn't found that link when i asked :)

9:07 justin_smith: pandeiro: it's all coming together, perhaps I should have some coffee

9:08 kungi: Why is Java so meh! :-(

9:08 I start to get a real aversion against this builder pattern.

9:11 borkdude: I'm doing java right now, and I feel so bored with ti

9:11 CookedGryphon: justin_smith: be careful with that bean, notice the month

9:11 kungi: borkdude: ti?

9:11 borkdude: it

9:11 kungi: borkdude: I thought ti was some kind of elaborate Java thingy :-)

9:12 borkdude: especially the style that every domain object should have its own class I find perverted

9:12 only as a layer between the database, while not much is happining in these things

9:15 mavbozo: borkdude: I just did some PHP, well, most of my work is in PHP. Same here.

9:15 kungi: Why do i have to politely ask a config class to give me a ConfigBuilder which then builds the config which I can then give the Class I want to instantiate ...

9:20 dysfun: because someone wanted to write way more code than was necessary

9:21 kungi: dysfun: maybe he was payed by lines of code?

9:21 dysfun: i knew a manager that judged progress by numbers of +s in svn diffs per week

9:22 if anything, i'd be inclined to judge it by net negative lines of code without breaking tests

9:22 kungi: dysfun: I know at least one person who would have shown him the middle finger and went away

9:22 dysfun: yeah, i did :)

9:26 kungi: I am currently trying to use metrics-clojure with riemann. I found a riemann reporter and some code showing how it's done. Now this riemann reporter is an AbstractPollingReporter and not the needed ScheduledReporter.

9:38 clgv: dysfun: haha, I encountered something similar where I had to implement a scheduler, it associated configuration object and an associated provider class. in clojure a similar solution just involved one function that needed to be passed as argument

9:39 joshhead: ,(= "(some code)" (str '(some code)))

9:39 clojurebot: true

9:39 joshhead: (= "(some code)" (str '(some code))) This is true in simple cases but not generally. Why?

9:39 Tagged literals, printing issues?

9:40 stuartsierra: joshhead: Could be any number of things.

9:40 whitespace, nonprintable objects, ...

9:41 joshhead: Whitespace is definitely going to cause a difference yeah. But I don't think that will matter for Datomic transaction fns (which is where I wished this would work)

9:41 stuartsierra: compiled functions aren't printable

9:42 joshhead: Hmm like datomic.api/q for example?

9:43 stuartsierra: Any function. Once it's compiled, it's going to print like #<datomic.api.q__4224907>

9:45 joshhead: Maybe I'm confused about the semantics of the single quote. If I quote a list that is a function call, won't I just get a symbol at the head of the list and not the function itself?

9:45 stuartsierra: yes you will

9:46 get a symbol in a list, that is

9:46 joshhead: Hmm okay. If I quote something with a tagged literal, does the handler function get called before it gets quoted?

9:47 stuartsierra: Yes

9:48 Tagged literals are a mess. Don't use them in code if you can avoid it.

9:49 joshhead: stuartsierra would you recommend avoiding #db/fn literals too?

9:49 stuartsierra: joshhead: yes, in code (.clj) files.

9:49 Use d/function or whatever it's called.

9:50 joshhead: all right

9:50 as for the code in tx fn's, I guess string literals are the way to go? Is there an emacs plugin or something to make paredit and indenting work inside strings?

9:51 stuartsierra: joshhead: Clojure code can be quoted

9:51 joshhead: oh d/function will just accept quoted code instead of a string?

9:52 "a string or data containing the code of the body" I guess so

9:52 stuartsierra: yes, quoted string

9:52 I mean quoted literal code

9:52 single-quote

9:53 joshhead: OK cool that is way more convenient than editing strings. Thanks for the tips

10:11 agarman: how do I force (into-array ...) to use a base type?

10:12 clgv: agarman: what is a "base type"?

10:12 agarman: I'm trying (into-array [^Base a ^Base b]), but that doesn't seem to be working

10:12 clgv: in this case my base type is OtpErlangObject

10:12 clgv: sub-types are OtpErlangTuple & OtpErlangPid

10:13 clgv: agarman: why does that matter? for primitives it makes a difference for anything derived from object it doesnt

10:13 Bronsa: agarman: into-array has a 2 arg arity

10:13 (into-array Base [a b])

10:13 ,(class (into-array Object ["foo"]))

10:13 clojurebot: [Ljava.lang.Object;

10:13 Bronsa: ,(class (into-array ["foo"]))

10:13 clojurebot: [Ljava.lang.String;

10:13 clgv: Bronsa: but does that really make any difference for objects?

10:14 agarman: Bronsa: ty ty

10:14 (inc Bronsa)

10:14 lazybot: ⇒ 64

10:14 clgv: power of two :D

10:15 Bronsa: clgv: I guess if your array is heterogeneous you need that

10:15 borkdude: why is it that some developers are fluent in server side languages, but find CSS difficult and are bad at it?

10:15 Bronsa: ,(into-array ["foo" 1])

10:15 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: array element type mismatch>

10:15 stuartsierra: csgv: Java arrays are strongly-typed

10:15 Bronsa: ,(into-array Object ["foo" 1])

10:15 clojurebot: #<Object[] [Ljava.lang.Object;@548719>

10:16 clgv: ,(into-array Object [[] "foo"])

10:16 clojurebot: #<Object[] [Ljava.lang.Object;@c087be>

10:17 clgv: ,(into-array Object [[] {}])

10:17 clojurebot: #<Object[] [Ljava.lang.Object;@1829097>

10:17 clgv: Bronsa: it seems arrays of strings are special, right?

10:17 Bronsa: no?

10:17 clojurebot: no is tufflax: there was a question somewhere in there, the answer

10:17 Bronsa: ,(into-array [1 1])

10:17 clojurebot: #<Long[] [Ljava.lang.Long;@a19cc5>

10:17 Bronsa: ,(into-array [[] []])

10:17 clojurebot: #<PersistentVector[] [Lclojure.lang.PersistentVector;@e44dd3>

10:18 Bronsa: clgv: if you don't give the array type to into-array, it will use the class of the first element

10:18 clgv: Bronsa: so why is it able to use object for the case with a vector and a hashmap?

10:18 Bronsa: clgv: because they are both Objects, while an hashmap is not a persistentvector

10:18 ,(into-array clojure.lang.IPersistentCollection [{} []])

10:18 clojurebot: #<IPersistentCollection[] [Lclojure.lang.IPersistentCollection;@1dbbaab>

10:19 Bronsa: you just need a superclass

10:19 clgv: Bronsa: yeah, but if it looks only at the first element it should choose the vector class

10:19 Bronsa: clgv: but you explicitely gave Object as the array class

10:20 clgv: Bronsa: damn, copied the wrong one. sorry

10:20 ,(into-array [[] {}])

10:20 clojurebot: #<IllegalArgumentException java.lang.IllegalArgumentException: array element type mismatch>

10:20 clgv: ah, that's what I wanted to know

10:21 andrewhr: borkdude: I guess, because browsers are inconsistent? Not that languages are much better though

11:16 jonathanj: hrm, what's a concise way of taking the last item from a vector?

11:17 CookedGryphon: peek

11:17 and most importantly, never ever last

11:17 jonathanj: i was going to say, last seems kind of not good

11:17 is there not something that combines peek and pop?

11:17 borkdude: after my CSS question, I just discovered this podcast : http://dotnetrocks.com/default.aspx?showNum=1053

11:18 Bronsa: jonathanj: no but you can use (juxt pop peek)

11:19 CookedGryphon: jonathanj: why would you want to combine peek and pop? Are you thinking of destructure-last sorts of things?

11:20 jonathanj: CookedGryphon: i want to take the last item from a vector, prepend ":" to it and put it back in the vector

11:20 Bronsa: jonathanj: you can use assoc then

11:20 clgv: jonathanj: peek, pop, conj

11:20 CookedGryphon: sounds more like you want to (update (count coll) (prepend :))

11:20 clgv: or assoc ;)

11:20 Bronsa: (assoc [1 2 3] 2 4)

11:20 ,(assoc [1 2 3] 2 4)

11:20 clojurebot: [1 2 4]

11:21 clgv: get + assoc that is

11:21 CookedGryphon: oh wait, but only if you have clojure 1.7, otherwise you won't have update

11:21 Bronsa: ah yeah, update is definitely better in this case

11:21 (inc CookedGryphon)

11:21 lazybot: ⇒ 4

11:21 jonathanj: hrm, too bad i can't specify a negative index

11:21 Bronsa: CookedGryphon: well update-in works just as fine

11:22 CookedGryphon: yep, only a little clunkier

11:22 Bronsa: ,(let [v [1 2 3]] (update-in v [(count v)] inc))

11:22 clojurebot: #<NullPointerException java.lang.NullPointerException>

11:22 Bronsa: :(

11:22 ,(let [v [1 2 3]] (update-in v [(dec (count v))] inc))

11:22 clojurebot: [1 2 4]

11:22 jonathanj: (dec (count xs)) is kind of yuck

11:23 CookedGryphon: (defn update-last [coll f & args] (apply update-in coll [(dec (count coll))] f args))

11:24 it's a pity nth doesn't support negative indices

11:25 it's something I really like in python

11:25 Bronsa: yeah

11:27 jonathanj: is there a destructuring syntax for the last item in a vector?

11:27 CookedGryphon: nope

11:27 it's been discussed a few times, but generally agreed would get a bit clunky and magical

11:39 the_danko: got a little destructuring question, fellows. motivated by something in brave clojure

11:39 (defn my-first

11:39 [[first-thing]] ; Notice that first-thing is within a vector

11:39 first-thing)

11:39 => (var user/my-first)

11:39 (my-first #{"oven" "bike" "waraxe"})

11:39 UnsupportedOperationException nth not supported on this type: PersistentHashSet clojure.lang.RT.nthFrom (RT.java:857)

11:40 so this destructuring doesn't work on a set it seems?

11:41 stuartsierra: the_danko: that's correct, sequential destructuring doesn't work on non-sequential things like sets.

11:42 the_danko: stuartsierra: thanks!

11:42 stuartsierra: You can call `seq` on the set to get a sequential thing, or just call `first` (which calls `seq`).

11:42 CookedGryphon: you could call seq on it to make it sequential, but you will get an unpredictable element out of it

11:42 clgv: is there something like (gen/subset (range 10)) in test.check?

11:43 ultimately, I need a vector of different elements in "random" order from a given list/set of values

11:44 puredanger: you can use gen/bind and gen/return to creators generators out of generators while applying arbitrary functions

11:45 stuartsierra: Or shuffle and take.

11:45 reiddraper: clgv: there is a 'shuffle' generator on test.check master, but not subset

11:45 clgv: reiddraper: subset would be quite handy as well, since it is pretty general

11:45 reiddraper: clgv: subset should be pretty simple, there's an explanation of writing one with Erlang quickcheck here: http://roberto-aloi.com/erlang/notes-on-erlang-quickcheck/

11:45 CookedGryphon: or perhaps sample, which could work on vectors too

11:45 reiddraper: clgv: but I agree it'd be handy

11:46 dagda1_: is this the right syntax for querySelector in clojurescript (.querySelector js/document "btn.btn-primary")

11:50 pandeiro: How can I deal with this error: #<CompilerException java.lang.IllegalStateException: var: #'ring.middleware.file-info/make-http-format is not public, compiling:(clj_webjars.clj:32:12)>

11:50 dagda1_: yes correct syntax

12:06 sdegutis: Question of the day http://stackoverflow.com/questions/7295016/clojure-method-missing

12:09 clgv: sdegutis: hehe

12:09 sdegutis: I was wondering it myself.

12:09 So I googled it and found the answer.

12:09 clgv: sdegutis: well defmulti comes quite close ;)

12:10 sdegutis: what did you find?

12:10 sdegutis: That in Clojure you use macros instead of method_missing.

12:10 Because Clojure doesn't have a concept of "objects" or "classes".

12:11 Except things like deftype.

12:11 And defmulti and defrecord.

12:11 clgv: how'd you use a macro with similar semantic?

12:11 sdegutis: I don't know yet :)

12:11 I'm still learning how to do Clojure well.

12:11 Idiomatic Clojure is an ever-evolving thing, a moving target.

12:11 technomancy: lifehack: doing clojure well does not involve method_missing functionality.

12:12 s/clojure/programming/

12:12 clgv: hehe

12:12 sdegutis: technomancy: you can't do that my sentence is immutable

12:12 Also this is good for learning http://stackoverflow.com/questions/11662084/why-does-clojure-distinguish-between-symbols-and-vars

12:15 Is dynamic function generation via macros a good practice?

12:18 noonian: sdegutis: i think it depends on the use case and how magical the macro is. defrecord defines new constructor fns and such for the record type defined for example

12:18 sdegutis: So then what is the rule of thumb for deciding when "it depends" applies to a given case?

12:19 kenrestivo: huh. i reach for function composition first... and it's been a few years since i needed to reach past that to macros, unless the library i'm dealing with is already macro-heavy and the only way around is to out-macro the macros.

12:19 arrdem: macros are more or less only for userland compilers and def generation that cannot be achieved by function composition or partial application

12:19 stuartsierra: sdegutis: Always use the fewest, and the simplest, tools available to solve any problem.

12:20 sdegutis: stuartsierra: But that excludes the use of macros, incorrect?

12:20 arrdem: sdegutis: no, it means that macros are appropriate if and only if they are the lowest power tool for the job

12:20 sdegutis: Oh.

12:20 arrdem: sdegutis: if they are not the lowest power tool, use a lower power one

12:21 sdegutis: I am anticipating using a lot more macros soon. That is why I wonder.

12:21 Right now we use almost no macros (except those that Compojure come with).

12:21 stuartsierra: In roughly *decreasing* order of simplicity: data structures, functions, protocols, multimethods, macros.

12:21 sdegutis: That's a good chart stuartsierra. You should tweet it.

12:21 stuartsierra: sdegutis: it's Stuart Halloway's hierarchy, more or less

12:22 sdegutis: stuartsierra: Whatever, if you don't, I will. And I'll take credit.

12:22 (I mean, assuming we don't definitively know who said it.)

12:22 stuartsierra: Sheesh, what is this, publication by blackmail?

12:22 sdegutis: I don't know what that means :)

12:23 stuartsierra: neither do I

12:23 sdegutis: Anyway, I'm starting to not like the explicitness of a typical Compojure app.

12:23 I'm starting to think we should do something more magical like "convention over configuration" and "automatic stuff".

12:24 * technomancy hands sdegutis a pile of leiningen implicit profile bug reports

12:24 sdegutis: Wow, I think every Heroku app is down.

12:24 noonian: lol

12:24 sdegutis: http://speclj.com/ http://joodoweb.com/ http://joyofclojure.com/

12:24 technomancy: not the cool ones https://syme.herokuapp.com/

12:24 sdegutis: Oh, ok.

12:24 kenrestivo: insider trading!

12:24 dbasch: this is up too http://dalai.herokuapp.com/

12:25 wink: 3 with own domains vs 2 with subdomains

12:25 kenrestivo: ok, now is the time to hype up your not-down heroku app.

12:25 wink: point not proven

12:25 everything is a dns problem until proven otherwise

12:26 noonian: sdegutis: Aaron Bedra's talk 'Ready Set Clojure!' might be interesting to you. He walks through writing a simple redis client lib that used macros to generate the fns. At the end he goes a little overboard so you might get a feel for why you might choose to use macros

12:26 sdegutis: http://joodoweb.herokuapp.com/ works

12:26 This is a good thing: http://joodoweb.herokuapp.com/tutorial/basics

12:26 wink: apparently I can mind read

12:27 sdegutis: noonian: Isn't he a Rubyist?

12:27 ered: joyofclojure is back

12:27 sdegutis: Not for me. http://joyofclojure.com/

12:28 noonian: sdegutis: i don't know his background but it wouldn't suprise me; a lot of clojurists come from a ruby background.

12:28 * ered came from some weird combination of other lisps but also ruby and java

12:28 sdegutis: Oh no!

12:28 Well I suppose that's fine.

12:29 I came from Python.

12:29 ered: maybe there's some weird routing thing going on

12:29 * wink refuses to be put into a background category

12:29 ered: joodo's site is down for me

12:29 sdegutis: I like the magical implicitness this library uses, very similar to Rails: http://joodoweb.herokuapp.com/tutorial/basics

12:29 ered: maybe it's heroku dns fail

12:29 technomancy: joy of clojure is on the ancient deprecated stack =\

12:29 ered: i don't mind compojure personally because in other languages i like web frameworks like sinatra or flask

12:29 ah

12:30 wink: the joy of legacy

12:30 sdegutis: technomancy: it's deprecated!?

12:30 technomancy: I was just going to buypurchas it.

12:30 wink: didn't he say "stack"?

12:30 as in "on heroku"?

12:30 ered: the heroku stack, not the book

12:30 if i read that right

12:30 sdegutis: I thought it was more about concepts than APIs, and thus is generally still applicable!?

12:31 Oh.

12:31 Yes, that makes the sense.

12:31 wink: sdegutis: and there should be a 2nd release yea

12:31 of the book

12:31 blargh :)

12:31 s,release,edition,. hell. time to go home

12:31 sdegutis: Good night wink.

12:31 ered: if joyofclojure.com doesn't work for you try http://joyofclojure.herokuapp.com/

12:31 sdegutis: ered: I heard there's going to be a second addition.

12:32 So I'll hold out.

12:32 ered: it should be out already

12:32 sdegutis: Oh.

12:32 With transducers?

12:32 ered: http://www.manning.com/fogus2/

12:32 this is the 2nd edition

12:32 wink: wtf @ naminh

12:32 technomancy: just emailed chouser offering to help

12:33 since he doesn't hang out on freenode any more =(

12:33 ered: my copy doesn't mention transducers

12:33 wink: apparently only one guy named smith wrote one manning book.

12:33 ered: wink: maybe it's like the WGA where they make people change their name if there are collisions? :3

12:33 sdegutis: Also, https://twitter.com/_sdegutis/status/527135858017984512

12:33 wink: ered: hehe

12:34 ered: sdegutis: i forgot where i first read this, but i only ever use macros for 3 cases - with-foo, do-foo, create-foo

12:34 sdegutis: Hmm.

12:34 ered: where in the create-foo case it's to make like 5 related objects

12:34 noonian: didn't stuartsierra say that in this chat?

12:34 sdegutis: I want to start using Macros to design my routing system.

12:35 I think the "composability" style is not working out as greatly as first imagined.

12:35 kenrestivo: sdegutis: let no one's work evade your eyes, plagiarize, plagiarize

12:35 technomancy: don't start with macros =(

12:35 wink: a lot of people have an irrational hatred for macros

12:35 sdegutis: wink: I can see that already!

12:35 noonian: yeah, functions are awesome

12:35 technomancy: start with functions and tough it out for a while so you have a better appreciation for where the pain points are and how macros can help you

12:35 kenrestivo: wink: i didn't until i got stuck using a library that was macro heavy

12:35 wink: I'd love to see something like korma without a macro

12:36 sdegutis: The primary point of macros is to reduce the number of times you have to type (fn [] ...)

12:36 That's what I read.

12:36 wink: write and show me ;)

12:36 ered: imo you just know when you need a macro

12:36 if that makes any sense

12:36 sdegutis: technomancy: I think I'm quite experienced enough with functions by now to know how to use Macros.

12:36 I've used Functions for quite a few years, even Clojure ones.

12:36 wink: hehe

12:36 kenrestivo: someone explained that macros were for creating custom syntax. i should tweet that

12:36 technomancy: sdegutis: you're not experienced in the domain of writing this library that doesn't exist yet though.

12:36 wink: sdegutis: wow, have you ever looked into methods?

12:37 technomancy: neither am I, believe it or not.

12:37 wink: kenrestivo: yeah, that's where I don't see a way arounf

12:37 noonian: i don't usually look to write a macro until i've written the code i want without macros and just want to clean up boilerplate and make it more concise

12:37 sdegutis: technomancy: How are you so confident?

12:37 wink: Yes, I used to use method_missing like a pro.

12:38 wink: sdegutis: wow, that's brave :)

12:40 technomancy: call it a hunch

12:41 sdegutis: We just learned about that on Word Girl. The word you're looking for is "intuition"

12:45 stompyj: I wonder how much money method_missing cost businesses

12:45 sdegutis: Not as much as null

12:45 stompyj: during its reign of terror, in the early rails days

12:45 sdegutis: Which Java still has! :)

12:46 Is there a language that doesn't have nil problems?

12:46 technomancy: lots

12:46 ered: rust

12:46 haskell

12:46 anything with an option type

12:46 technomancy: racket

12:46 erlang

12:46 ered: i think F# has option types too

12:46 technomancy: java has option types

12:46 that's not enough to fix the problem by a long shot

12:46 you have to actually use them =)

12:47 ered: java's option types don't work well iirc

12:47 at least the ones in guava

12:47 they don't play nice with flatmap, so i'm told

12:47 technomancy: they come with the jdk now

12:47 ered: keep forgetting java 8 is a thing

12:47 since iirc a huge chunk of the world is stuck on 6

12:48 sdegutis: so which one?

12:48 i would love to use java

12:48 ive never written it before. it sounds like a lot of fun.

12:49 ered: schema has option types now too but iirc schema's validations are technically optional

12:49 by which i mean only run when you tell them to run

12:49 at least when i remember last using them

12:49 noonian: yeah i think you can annotate the fns so they always run or call them with validation turned on when you want it

12:49 ered: yeah that sounds right

12:50 i want to say it has a performance hit is why it's not on by default

12:50 sdegutis: If you were to write a brand new web app today, what language would you choose?

12:51 technomancy: HTML

12:51 sdegutis: No I mean a dynamic website, the back-end.

12:51 Some examples are: Ruby, Python, Clojure.

12:51 technomancy: DHTML

12:51 the_danko: ha

12:51 sdegutis: No I mean ones that still exist.

12:51 technomancy: the D stands for Dynamic, you know

12:51 ered: CGI? :3

12:51 the_danko: haha

12:51 sdegutis: CGI is an interface not a language.

12:51 noonian: i'm going to go out on a limb here and say a lot of people here might choose clojure

12:51 sdegutis: This isn't that hard, people.

12:52 the_danko: haha

12:52 sdegutis: noonian: you know what they say about assuming

12:52 "don't"

12:52 noonian: i heard it was the brother of all fuckups or something

12:53 sdegutis: wat

12:53 echo -n '' > quine && chmod +x quine && ./quine

12:53 lazybot: -n '' > quine && chmod +x quine && ./quine

12:53 nathan7: that's not much of a quine, is it

12:53 noonian: anyway, a lot of dynamic sites these days are single page js apps talking to api servers

12:53 mavbozo: is HTML a programming language?

12:53 sdegutis: $ ./quine > quine && ./quine

12:54 mavbozo: is DHTML a programming language?

12:54 pandeiro: anyone know why a lib would produce this when I try to require it: #<CompilerException java.lang.IllegalStateException: var: #'ring.middleware.file-info/make-http-format is not public, compiling:(clj_webjars.clj:32:12)>

12:55 mavbozo: pandeiro: make-http-format is private?

12:55 the_danko: i am sorry to interrupt the HTML merriment. i do have a quick question if anyone is feeling game.

12:55 (defn p [x] (println x))

12:55 => (var user/p)

12:55 (map p [1 2 3])

12:55 => (1 2 3 nil nil nil)

12:55 why is there a 1 2 3 in the return from the map?

12:56 i thought that the function p there should always return nil

12:56 why does the println go into the returned list?

12:56 pandeiro: mavbozo: it is private; but that doesn't matter when i run a repl from the lib's project; and i thought you could use fully qualified vars even if not public

12:57 ered: functions you use with map shouldn't have side effects

12:57 also because println returns nil

12:57 hmm

12:57 hang on i'm confused now

12:57 bostonaholic: the_danko: which version of clojure?

12:57 noonian: the_danko: the 1 2 3 just happens to be printing as the repl is printing the return value so it looks like its in the seq returned

12:58 the_danko: (def r (map p [1 2 3])

12:58 )

12:58 => (var user/r)

12:58 (println r)

12:58 (1

12:58 2

12:58 3

12:58 nil nil nil

12:58 ered: what are you trying to do? print each element of the list on its own line?

12:58 the_danko: bostanaholic: 1.6

12:59 ered: i am just trying to learn what is happening here. i stumbled into this example and realized it means i don't know how map works.

12:59 ered: ok, so i am trying to learn clojure and how map works is the answer.

12:59 ered: i'm not sure if this explains it entirely (someone else feel free to jump in), but since println has side effects you don't want to use map

12:59 instead you should use doseq

13:00 noonian: the prints will happen when the map is realized, which at the repl is immediately since the repl is trying to print the return value

13:01 try (def res (map p [1 2 3])) then (do res nil)

13:01 you should just see 1 2 3 nil or something

13:01 the_danko: noonian: AHH! yes. (count r) is 3!

13:02 noonian: thanks!

13:02 noonian: the_danko: np

13:02 pandeiro: why does accessing a fully namespaced private var cause an IllegalStateException when a project is required but not when running a repl within the project itself?

13:06 noonian: i just don't use private anymore :P

13:10 mavbozo: pandeiro: what do you mean by "when a project is required"?

13:10 bacon1989: Does anyone know of some good defmacro exercises I could do to get more familiar with macros?

13:10 mavbozo: pandeiro: is it '(require '[ring.middleware.file-info :refer [make-http-format]])'?

13:25 stompyj: bacon1989: Why do you need exercises? You mean with the semantics of how they work?

13:27 Does anyone here use kafka in clojure? If so, what client are you using? All of them seem a bit out-of-data

13:27 date*

13:36 mindbender1: Is there a function that evaluates `value expr` pairs and returns the first truthy value of expr?

13:36 justin_smith: mindbender1: cond?

13:36 noonian: mindbender1: cond

13:37 justin_smith: ,(cond false 0 nil 1 true 2)

13:37 clojurebot: 2

13:37 noonian: ,(cond nil :falsey :truthy :truthy)

13:37 clojurebot: :truthy

13:38 mindbender1: I want (cond :truthy :falsy :falsy :truthy) => :truthy

13:38 justin_smith: than reverse the args?

13:38 hyPiRion: 2[3~

13:38 justin_smith: *then

13:39 Bronsa: mindbender1: that doesn't make much sense? what would the expr part be there for then?

13:39 justin_smith: mindbender1: wait - what's the logic there?

13:39 mindbender1: I am trying to port a js code but it doesn;t translate easily into reversing.

13:40 sdegutis: ,CLOJURE_VERSION

13:40 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: CLOJURE_VERSION in this context, compiling:(NO_SOURCE_PATH:0:0)>

13:40 mindbender1: e.g....

13:40 Bronsa: ,*clojure-version*

13:40 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

13:40 sdegutis: ,*clojure-version*

13:40 clojurebot: {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"}

13:40 Bronsa: ,(clojure-version)

13:40 clojurebot: "1.7.0-master-SNAPSHOT"

13:40 sdegutis: ,(map identity)

13:40 clojurebot: #<core$map$fn__4341 clojure.core$map$fn__4341@1eb41e5>

13:40 sdegutis: WHOA LOOK A TRANSDUCER

13:41 noonian: mindbender1: everything in clojure is truthy except nil and false

13:41 sdegutis: mindbender1: Clojure is basically Ruby

13:41 Bronsa: sdegutis: what?

13:42 sdegutis: Bronsa: nil and false

13:42 (and nil false)

13:42 noonian: Sgeo: thems fightin words!

13:42 Bronsa: sdegutis: and that.. makes it "basically Ruby"?

13:42 sdegutis: noonian: whoa dude, calm down.. I'm over here

13:42 noonian: sdegutis: opps :P

13:42 sdegutis: You're on the roll today my friend.

13:42 noonian: can't type this morning

13:43 sdegutis: lol the guy who wrote Dash said I was "on the roll" and I was like "lol wat"

13:43 I had to break the news that it's "on a roll" and he took it rather well.

13:44 justin_smith: sdegutis: "on the roll" means like you are like part of the breakfast food conspiracy

13:46 noonian: im on the english muffin this morning

13:47 sdegutis: hi

13:48 mindbender1: switch (e.keyCode) {case "esc": if true {return true;} else {return false} break; case "end": if true {return true;} else {return false;} break; }

13:48 something like that in clojure?

13:49 the return value of the expression determines if it continues

13:50 noonian: ,(let [val "foo"] (cond (= val "bar") "it was bar" (= val "foo") "it was foo" :else nil))

13:50 clojurebot: "it was foo"

13:51 noonian: there are less general ways to do this also, case works if you know your switch values at compile time, and condp if you always use the same predicate

13:51 mindbender1: noonian: sorry the exprs are different for each case

13:52 noonian: ,(let [val "foo"] (cond (#"ar" val) "it contains 'ar'" (= val "foo") "the val is foo"))

13:52 clojurebot: #<ClassCastException java.lang.ClassCastException: java.util.regex.Pattern cannot be cast to clojure.lang.IFn>

13:52 noonian: ,(let [val "foo"] (cond (re-find #"ar" val) "it contains 'ar'" (= val "foo") "the val is foo"))

13:52 clojurebot: "the val is foo"

13:52 noonian: mindbender1: i think you can do everything you want with cond

13:53 justin_smith: mindbender1: that's just a case, where the right hand side of each case is an if

13:53 exactly like in js

13:53 (case "esc" (if true true false) "end" (if true true false))

13:53 is literally that code

13:53 mindbender1: justin_smith: yes and the right hand determines if it keeps going further.

13:54 justin_smith: err (case e.keyCode ...)

13:54 no, the breaks happen after the if

13:54 in that code

13:54 they apply regardless of branch

13:56 noonian: but you can have arbitrary code in the right hand side of cond, you might want to break it into helper functions to keep it readable though

13:56 justin_smith: mindbender1: it is true that we don't have a convenient version of case with fallthrough and early return

13:56 noonian: you can usually refactor that into the top level cond though

13:56 justin_smith: mindbender1: but you can replace return with a promise / deliver combo

13:56 and check the value of the promise at the end

13:59 ,(let [return (promise)] (if false (deliver return 0)) (if nil (deliver return 1)) (if true (deliver return 2)) @return)

13:59 clojurebot: 2

13:59 justin_smith: not as pretty as case with fallthrough / return statements, but capable of the same semantics

14:03 ,(let [return (promise)] (if false (deliver return 0)) (if nil (deliver return 1)) (if true (deliver return 2)) (if :redundant (deliver return 3)) @return) ; for good measure

14:03 clojurebot: 2

14:25 pandeiro: mavbozo: no, the lib in question is clj-webjars, which uses the aforementioned private fn

14:25 when i run a repl in the clj-webjars project, it compiles

14:26 when i require the lib from another project, it doesn't

14:29 justin_smith: pandeiro: do you need to be able to use that private var from another project?

14:29 pandeiro: justin_smith: no, a third party lib is using it

14:29 it seems that it works unless ring (owner of private fn) is also included in deps

14:30 justin_smith: oh - so both the definition and usage are both in 3rd party tools

14:30 weird

14:30 pandeiro: perhaps you get a different version of the code that makes the var private if you explicitly depend on ring?

14:30 pandeiro: justin_smith: just tested that

14:31 clj-webjars depends on ring 1.3.0; even using that version as a dep in my project causes clj-webjars to fail to compile

14:31 maybe i need exclusions

14:32 the_danko: yo fellas, got a little quandry.

14:32 (defn my-partial

14:32 [partialized-fn & args]

14:32 (fn [& more-args]

14:32 (apply partialized-fn (into args more-args))))

14:32 ok so i know that into works differently if the first argument is a list or a vector

14:32 justin_smith: the_danko: that's gonna screw up the arg order

14:32 the_danko: justin_smith: just what i am asking!

14:32 justin_smith: unless you want more-args reversed on the front of the args

14:33 & more-args makes a list, that puts things on the front with into

14:33 lazybot: java.lang.RuntimeException: Unable to resolve symbol: more-args in this context

14:33 pandeiro: exclusions doesn't solve it...

14:33 lesson here is: don't use a lib that uses other lib's private stuff?

14:33 the_danko: justin_smith: so this is an example from brave clojure. ok so doesn't the type of the return from the into statement depend on the type of args?

14:34 justin_smith: not more-args?

14:34 justin_smith: my question is the same as your issue. i can't figure out how the order works.

14:34 justin_smith: the_danko: ahh, right

14:34 args will also be a list

14:34 the order will be each arg appended to the front of the initial

14:34 the_danko: justin_smith: so here args is a rest-param? correct? is that the correct term?

14:35 justin_smith: that is what into does with lists

14:35 the_danko: yes

14:35 ,(into '(0 1 2) 3 4 5)

14:35 clojurebot: #<ArityException clojure.lang.ArityException: Wrong number of args (4) passed to: core/into>

14:35 justin_smith: ,(into '(0 1 2) [3 4 5])

14:35 clojurebot: (5 4 3 0 1 ...)

14:36 justin_smith: the_danko: & args creates a list, into adds each element from mor-args to the front of args

14:37 sdegutis: If you use a font that came with your OS in making an app icon for your closed-source commercial Clojure app, do you have to pay for licensing or something?

14:37 the_danko: justin_smith: sweet, so rest-params is always a list?

14:37 justin_smith: i'll email mr brave clojure about this example

14:37 justin_smith: ,((fn [a & r] (class r)) (range))

14:37 clojurebot: nil

14:37 justin_smith: hmm

14:37 llasram: justin_smith: `apply`?

14:37 justin_smith: ,((fn [a & r] (class r)) 1 2 3 4 5 6)

14:37 clojurebot: clojure.lang.ArraySeq

14:38 justin_smith: the_danko: technically an ArraySeq, but it has the same conj and into behavior as a list

14:39 llasram: ,(apply (class %&) (range))

14:39 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: %& in this context, compiling:(NO_SOURCE_PATH:0:0)>

14:39 llasram: ,(apply #(class %&) (range))

14:39 clojurebot: clojure.lang.ChunkedCons

14:39 llasram: It can be many things

14:39 justin_smith: llasram: good point

14:39 llasram: ,(apply #(class %&) [1 2 3])

14:39 clojurebot: clojure.lang.PersistentVector$ChunkedSeq

14:39 justin_smith: llasram: many things that all have the conj behavior of list :)

14:39 llasram: fair

14:40 the_danko: justin_smith: llasrma: thanks guys. very helpful!

14:47 bacon1989: stompyj: kinda late, but I just like exercises creating macros. I suppose I could just take any clojure.core macros and try and reimplement them my self

14:47 stompyj: bacon1989: fair enough

14:47 bacon1989: i'm going to a point in my project where I think a few macros would simplify things creatly

14:47 mdrogalis: bacon1989: Go implement `let` :)

14:48 justin_smith: bacon1989: use macros to create a C style case statement with fallthrough if you don't invoke (break)

14:48 mdrogalis: Er, I think it was the destructuring code actually. It's pretty wild.

14:48 bacon1989: sounds interesting

14:49 yeah, idk about 'let', i'd assume that would be a monster

14:49 mdrogalis: It happens to be a function https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L4045

14:49 justin_smith: let* is doing the binding part though :)

14:49 bacon1989: yikes

14:50 justin_smith: ,(special-symbol? 'let*)

14:50 clojurebot: true

14:58 justin_smith: mindbender1: a more general approach to your translating case question, btw https://www.refheap.com/92434

15:00 mindbender1: justin_smith: I'm checking it.

15:00 justin_smith: mindbender1: just updated again, refresh

15:01 mindbender1: okay

15:01 justin_smith: mindbender1: you could have any number of those (if-not (realized? return) ...) blocks for further logic that should be skipped if return has been delivered but run otherwise

15:03 mindbender1: of course there is always a clean idiomatic solution, but the possible advantage here is that the code would linearly follow the same sequence read top to bottom

15:04 amalloy: bacon1989: re trying to implement 'let: of course doing all the destructuring from scratch is a nightmare, but you don't have to: you can define let as a macro that expands into fn, which does the same destructuring

15:05 puredanger: there is of course the destructure function

15:05 amalloy: the reason it's a cool exercise is it reminds you that fn is all you really need; if you had fn and macros, you could build all of lisp

15:06 TimMc: And of course macros could be avoided by passing lambdas.

15:06 *most macros, whoops

15:06 amalloy: puredanger: it's pretty rare to need that though, i'd think. i've only used it once

15:06 puredanger: yup

15:07 kanobe_: `

15:07 hiredman: I've been fiddling with a lisp interpreter in emacs lisp (to get csp style concurrency, to avoid callbacks, to write an nrepl client, to shave a yak) they are fun

15:14 amalloy: my one use of destructure, if anyone is curious, since it came up: https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L224-L253

15:14 bodie_: anyone have a preferred testing kit for clojurescript? I was looking at maybe jasmine-cljs or specljs

15:14 justin_smith: amalloy: very cool

15:15 bodie_: specifically I'm working with Om so I don't know if there's something better or worse suited to that

15:15 I'm kinda new to cljs, so any thoughts are welcome :)

15:15 amalloy: justin_smith: version one only supported delaying symbol bindings; at some point i realized i can use destructure to reduce the destructuring cases to N symbol bindings

15:16 justin_smith: looks like a very useful macro

15:17 gfredericks: CSP == "Continuation Stassing Pyle"

15:18 hiredman: continuation stashing program maybe

15:18 bodie_: continuation style passing

15:18 :P

15:19 hiredman: which is basically what it is, to "block" on putting to a channel you basically stash a continuation of the program in the channel, and when someone comes along and takes it restarts the continuation

15:20 csp as in the core.async kind of stuff

15:29 bacon1989: amalloy: thanks, maybe i'll try and reimplement let, and read through the oreilly macros section some more

15:55 sdegutis: What's the prevaling concurrent philosophy on templating engines in Clojure?

15:55 Is Hiccup still the champain?

15:55 justin_smith: concurrent philosophy?

15:55 sdegutis: I mean modern.

15:56 amalloy: contemporary, perhaps

15:56 sdegutis: Oh, contemporary.

15:56 Yes, thank you.

15:56 Does Hiccup still rain supreme?

15:56 xemdetia: rain=reign

15:56 justin_smith: I have never tried hiccup, but I doubt it tastes like champaign

15:57 jeffterrell: Though champagne has been known to incur hiccups.

15:57 cbp: i left the template score list in my other pants

15:57 sdegutis: What is this, criticism our?

15:57 justin_smith: sdegutis: in all seriousness, I use something mustache derived, because the frontend guys don't do clojure and they write the templates

15:57 borkdude: sdegutis who still renders html on the server? ;)

15:58 sdegutis: borkdude: where else do you render it, friend?

15:58 borkdude: sdegutis in javascript

16:00 sdegutis: borkdude: heresy sir!

16:01 That would be slow as heck.

16:01 or, wait.. is it?

16:01 * sdegutis ponders this.............

16:02 borkdude: sdegutis this is what react apps do all the time

16:02 justin_smith: om is faster than the equivelent number of page loads you would need to do to see the same amount of page update

16:02 jeffterrell: I think it's not that bad actually.

16:02 arohner: om is way faster than an HTTP request

16:03 sdegutis: Hmm.

16:03 justin_smith: clearly sdegutis just isn't up to speed with web 2.0

16:03 sdegutis: wait I thought we were at web 3.5 already

16:03 borkdude: 3.11

16:03 justin_smith: sdegutis: some of us are

16:03 sdegutis: just not me? :(

16:03 jeffterrell: Single-page apps like trello.com have a really thin static DOM but a big fat javascript file, and the JS creates the page. Cf. http://blog.fogcreek.com/the-trello-tech-stack/

16:03 borkdude: sdegutis even when not using react it can be feasible to render in js

16:03 sdegutis: look, whatever, my hands are fricken cold in this awesome autumn weather so thats that

16:04 danneu: using a websocket as an event bus with React was a lot cooler until i realized i need to pay Cloudflare $5000/mo for websocket ddos protection

16:04 justin_smith: sdegutis: if you were rendering more in-browser your notebook could be warming your hands!

16:04 sdegutis: but wait, dont you still need to make ajaj calls?

16:04 arohner: sdegutis: only for side-effects

16:04 sdegutis: doesnt that diminish the upside of rendering clientside?

16:04 well also for loading sensitive per-user data

16:05 arohner: GET logic is all client-side

16:05 sdegutis: or something

16:05 we're still using jquery :(

16:05 arohner: but the page still *renders* way faster

16:05 you put up a spinner, and you transfer less data

16:05 pandeiro: sdegutis: if you are dynamically building the initial HTML payload you can stick data in there; otherwise yes, 1 or more ajax calls to get your stuff

16:06 justin_smith: pandeiro: the downside there is for anything that needs to be updatable without a refresh, you can end up duplicating render logic, so even then you end up passing in some json and the javascript that renders it

16:07 borkdude: justin_smith not with react

16:07 pandeiro: justin_smith: (defn get-data [f] (if inlined-data (f inline-data) (get-ajax-data f)))

16:07 justin_smith: borkdude: pandeiro: yes - but you aren't using something like hiccup for this

16:08 pandeiro: justin_smith: what do you mean? why not?

16:08 borkdude: justin_smith you can have hiccup style templating in clojurescript

16:08 pandeiro: you could easily inline data into the server-side hiccup vectors if need be, right?

16:08 borkdude: reagent has it out of the box, om + sablono or non react: crate

16:09 justin_smith: pandeiro: borkdude: OK, I did not realize hiccup templating in cljs was a thing

16:09 borkdude: justin_smith light table uses crate for cljs templating

16:10 justin_smith: or perhaps even worse I knew this once because I actually used it and I totally forgot

16:10 cool

16:10 pandeiro: justin_smith: of course :)

16:11 sdegutis: borkdude, justin_smith, pandeiro: how do you handle clients that disabled JS?

16:11 borkdude: sdegutis haha, you don't

16:11 sdegutis: !?

16:11 pandeiro: the state of the art is doing the client as a SPA with React and rendering it on the server in Java 8's js env -- i know people have started doing that but i'm sure it's still thorny

16:11 clojurebot: CLABANGO!

16:11 justin_smith: sdegutis: this is clearly the downside of doing so much in the client

16:11 pandeiro: sdegutis: yeah that's a different app

16:11 sdegutis: lol clojurebot what the crap?

16:12 justin_smith: !?

16:12 borkdude: pandeiro I rendered a a component to a string yesterday in chrome and then just pasted the initial html in the static html file: works :)

16:12 clojurebot: ! is suddenly

16:12 pandeiro: borkdude: yeah that's something else though

16:13 borkdude: pandeiro what do you mean?

16:13 pandeiro: i'm talking about rendering the string in the jdk's js env, not a browser env

16:13 borkdude: pandeiro what does it matter, it's only for initial page load right?

16:14 sdegutis: true

16:14 pandeiro: borkdude: ah yeah sure, if it's not going to change

16:14 but here's what i was getting at (kinda): http://augustl.com/blog/2014/jdk8_react_rendering_on_server/

16:15 borkdude: 'There's a glaring problem here. If you create React components that invokes 3rd party code, such as jQuery plugins, Bootstrap's JS components, and so on, you're in for trouble."

16:15 a no go for me then

16:15 pandeiro: borkdude: yeah the issue is the missing browser stuff i imagine

16:15 document.getElementById

16:15 localStorage

16:15 that kind of stuff

16:16 sdegutis: What JS lib do you use for rendering HTML?

16:16 justin_smith: sdegutis: web 2.0 has been pretty terrible for accessibility, and the whole concept of browsing the web without js

16:16 sdegutis: I use Hiccup in Clojure right now.

16:16 justin_smith: ... go on

16:16 pandeiro: sdegutis: React is what everyone* is using

16:18 borkdude: sdegutis I know someone who uses crate for non react stuff, but reagent for everything else

16:18 sdegutis: Anyone here comfortable telling how much they make? I'm wondering how much someone who does a job like I do would get paid.

16:18 borkdude: sdegutis but you are just building a simple app without lots of interactivity server side hiccup is fine, just do what works for you

16:19 sdegutis: borkdude: I thought people were using Om for React within Cljs?

16:19 borkdude: sdegutis there are also lots of people using the more minimalistic reagent

16:19 pandeiro: there are at least three React wrappers in cljs

16:19 borkdude: om, reagent, quiescent in descending popularity

16:20 sdegutis: so om is the most popular but reagent is the best?

16:20 borkdude: sdegutis there is no best, it depends

16:20 sdegutis om is very good at undo-able snapshottable apps

16:20 sdegutis provided you aren't using local state

16:21 pandeiro: reagent's api is much more idiomatic for people used to clojure; om has a bunch of new vocabulary

16:21 borkdude: sdegutis you can have the same effect in reagent, but it may require more thinking, because reagent doesn't enforce using only one atom

16:21 sdegutis: oh

16:21 thanks everyone

16:21 borkdude: sdegutis that said, reagent is much simpler to learn, less verbose

16:21 joelt: and there's hoplon which isn't reactjs based.

16:22 sdegutis: so react is the foreseeable future?

16:22 borkdude: sdegutis react changes the clojurescript landscape quite a bit I think, if I'm right

16:22 sdegutis pedestal app development stopped because of om

16:23 sdegutis: wonderful

16:23 joelt: reactjs is fundamentally more "correct" and funcitonal-like

16:24 while on this reactjs thread... has anyone written an HTML -> om/template (or reagent/template) converter?

16:24 sveri: borkdude: you have any sources for this?

16:24 borkdude: sveri on what?

16:24 this requires context, just like in javascript :P

16:24 sveri: borkdude: that pedestal development stopped because of om

16:24 pandeiro: the pedestal thing was mentioned on the pdestal google group

16:25 borkdude: sveri yes, the pedestal-users mailing list

16:25 pandeiro: https://groups.google.com/forum/#!topic/pedestal-users/jODwmJUIUcg

16:26 mr_rm: does anyone know how to tell ring to add app server specific deployment descriptors to the WEB-INF folder?

16:26 justin_smith: mr_rm: put them in your :resource-path

16:26 sveri: borkdude: pandeiro thanks, didn't know that

16:26 justin_smith: mr_rm: wait, that may not be it...

16:28 mr_rm: justin_smith: yes i don't want it in WEB-INF/lib but rather at WEB-INF. alongside web.xml

16:29 i've pored over the docs but just not seeing it

16:29 ssa: hey does anyone know how to *not* require a library in a library i want to depend on

16:29 moquist: borkdude: thx for the om, reagent, quiescent list. I didn't know about the latter two and I'm glad I now do.

16:29 pandeiro: ssa: :exclusions

16:29 justin_smith: pandeiro: that excludes a dep version

16:29 ssa: e.g., A -> B -> C (where -> is a dependency)

16:30 justin_smith: pandeiro: that can't prevent a lib from requiring other clojure code

16:30 TimMc: sdegutis: Hiccup doesn't have anything to help you avoid JS injection attacks, by the way.

16:30 pandeiro: ah yeah of course

16:30 derp

16:30 ssa: justin_smith is right :)

16:30 justin_smith: ssa: provide another version of the namespace and exclude the dep? dunno, at that point why not rewrite the problematic lib

16:30 ssa: yeah, so i have the exclusion, but B will still bail because it tries to find C

16:31 justin_smith: ssa: you can create the ns such that it will be found rather than the other version, but this is a huge hack

16:31 pandeiro: TimMc: hiccup.util/escape-html ?

16:31 ssa: justin_smith: yeah, that's what i was trying to avoid :/

16:31 mr_rm: i tried add :web-content pointing to a folder with WEB-INF under that but it doesn't get included either. so far the only way i found is to manually add the deployment descriptor :\

16:32 technomancy: clojurebot: terminal quirks |are| a long, sad list of historical reasons why paredit's bindings don't work inside a terminal http://catern.com/posts/terminal_quirks.html

16:32 clojurebot: c'est bon!

16:32 ssa: the problematic require is not used anywhere in the lib, which is why i can exclude it

16:32 ohpauleez: This is where I'll jump in and just say - everyone should give Pedestal Service a look when building out web-based services

16:33 ssa: ok, was hoping there was an easy solution, but maybe not!

16:33 justin_smith: mr_rm: the ns in question is pretty small https://github.com/weavejester/lein-ring/blob/master/src/leiningen/ring/war.clj

16:33 mr_rm: any funcitonality you need should be in there - I couldn't see it though

16:33 mr_rm: but I only skimmed

16:34 ssa: sounds like some codomain to monkey patching

16:34 ssa: monkey-surgery?

16:35 mr_rm: justin_smith: yes, sadly, my quick skimming looks like it doesn't do anything extra for other files except "web.xml"

16:35 justin_smith: mr_rm: the ugly way to do it would be to just add the file manually

16:35 mr_rm: it's just a zip file after all

16:35 mr_rm: justin_smith: unfortunately i am forced to deploy this into weblogic and i need to make it prefer my local jars

16:36 TimMc: pandeiro: If you have to call a fn to escape output, you've already lost.

16:36 justin_smith: mr_rm: isn't this what uberwar is for?

16:36 mr_rm: justin_smith: right, i already know that works. it just seems like this is basic functionality and i thought i must be missing something

16:36 sdegutis: TimMc: oh no!

16:36 mr_rm: justin_smith: uberwar will put all the jar files there, that's true. however weblogic has an old version of the jar file in question and it before mine in teh classpath

16:36 justin_smith: mr_rm: weavejester tends to err on the side of leaving features out. On the plus side the things he leaves in tend to be really solid.

16:37 mr_rm: justin_smith: i have to tell weblogic to prefer my classes from WEB-INF/lib

16:37 pandeiro: TimMc: really? can't you predict where user-generated content might show up in your templates?

16:37 TimMc: your gripe is that should be the default?

16:37 justin_smith: mr_rm: maybe it calls for a jar-surgery lib (if we don't have such a thing already)

16:37 TimMc: pandeiro: Exactly.

16:38 technomancy: pandeiro: people make mistakes, unfortunately

16:38 pandeiro: sure makes sense

16:38 TimMc: It's unsafe by default, and we're not getting any reliability upgrades for people any time soon.

16:38 technomancy: better to have the mistake be embarassing than catastrophic

16:38 TimMc: technomancy: That's well-put -- &amp; is not so bad if you compare it to the laternative.

16:39 pandeiro: was the reason against it performance-related or?

16:39 * technomancy glares at *read-eval*

16:39 TimMc: Time to do my yearly check if my old employer's site still has that double-escape bug...

16:39 sdegutis:

16:40 Bronsa: technomancy: which keybindings are you talking about? I use emacs -nw and it all works fine

16:40 pandeiro: Bronsa: C-arrows

16:41 Bronsa: pandeiro: they work fine for me

16:41 pandeiro: Bronsa: xterm?

16:41 Bronsa: i might have unmapped them though

16:41 pandeiro: urxvt

16:41 sdegutis: pandeiro, Bronsa: st

16:41 TimMc: pandeiro: I would assume neglect or complacency. Almost every templating library has this proble, though.

16:41 technomancy: Bronsa: urxvt has a few nonstandard tricks that work locally but not inside tmux/ssh

16:41 Bronsa: sdegutis: what?

16:42 sdegutis: I thought we were randomly naming linux browsers.

16:42 Bronsa: technomancy: ah I don't use tmux/screen

16:42 sdegutis: I mean terminals.

16:42 technomancy: Bronsa: but yeah, it's not a limitation of terminal emulators per se, but rather the standards for representing keycodes across the wire.

16:42 Bronsa: gotcha

16:43 technomancy: isn't there an emacs something to edit files over ssh though? that could be a nice work-around :P

16:43 technomancy: Bronsa: you'd think ... =)

16:43 justin_smith: xterm / rxvt can also hand pointer events to ncurses clients that know how to use them. For obvious reasons this doesn't work over a multiplexer / the wire either

16:43 technomancy: but since Emacs isn't concurrent it's pretty brutal in the presence of network lag

16:43 pandeiro: yeah I still don't see the point of emacs' M-x term

16:44 justin_smith: Bronsa: yeah, tramp is awesome

16:44 mr_rm: justin_smith: actually i do have my own private jar surgery library

16:44 Bronsa: technomancy: .. yeah I notice that when my network drops & erc tries to reconnect

16:44 justin_smith: mr_rm: haha, nice

16:44 sdegutis: I will hold my tongue on the subject of Emacs.

16:44 mr_rm: justin_smith: guess i need that extra step :)

16:44 sdegutis: I will hold it so tightly it will bleed tears.

16:44 joobus: sdegutis: those are blood tears of love right?

16:45 llasram: sdegutis: Your tongue has tears for blood...?

16:45 Gurkenmaster: using emacs over LAN with a forwarded X server works surprisingly well

16:45 sdegutis: I see this channel has never been christened to the concept of hyperbole yet.

16:46 justin_smith: sdegutis: it's less the hyperbole and more the surreality of said hyperbolic image

16:46 sdegutis: justin_smith: whatever I don't know English things I just like mixing things that almost work together but don't quite

16:47 joobus: sdegutis: that's the dumbest thing I've ever heard...

16:47 sdegutis: justin_smith: most fun hobby. try it every day.

16:47 joobus: Sir, you seem to be irate, please do explain why?

16:47 technomancy: finely-tuned nonsense is an art form

16:47 a la Pavement

16:47 sdegutis: I'm glad /someone/g agrees with me

16:48 Did you see I snuck a regular exp in the emphasis?

16:48 justin_smith: technomancy: sdegutis: the Residents have a song with the lyrics "smelly tongues look just like they feel", I like it because if you include the medium of the data it encompasses all five of the primary senses

16:51 sdegutis: joobus: the proper way to express such outspoken disagreement is to challenge someone to a duel with a glove slap

16:51 joobus: please note this for future posterity

16:51 * sdegutis is losing his grip

16:52 TEttinger: get a glove, sdegutis

16:52 gloves can help you grab things, like oven mitts help grab hot things

16:52 fun fact for the day

16:52 * sdegutis trout TEttinger

16:52 sdegutis: Why isn't /trout working

16:53 TEttinger: i use driving gloves to grab the steering wheel

16:53 otherwise i would miss

16:53 justin_smith: sdegutis: most of the world has not caught up to the optional fish-slap extension to the irc protocol

16:53 sdegutis: tricky things those wheels are

16:54 this has been a fun afternoon, thank you all

16:54 justin_smith: sdegutis: even if implemented, the client may only dispense canned tuna at best

16:54 sdegutis: i count it as R&D

16:54 because i learned about react.js

16:54 and got good feedback on it

16:54 justin_smith: related to http 418 ?

16:55 justin_smith: sdegutis: no, that's just silly

16:58 sdegutis: i do a really good Bane voice

17:10 brainproxy: Hi :)

17:23 technomancy: you're a nerd, right?

17:23 SagiCZ1: is there some way to write functiona arguments that the function would accept both [a b c d e] and [a b [c d e]] ? without overloading? some destructuring magic?

17:24 sdegutis: technomancy: I am thinking of getting a foot pedal with a usb hookup, and making it send a "ctrl" key while pressed

17:24 the firmware should be significantly simpler than https://github.com/sdegutis/atreus-firmware

17:25 technomancy: sdegutis: guilty as charged

17:25 sdegutis: wait, are you on a macintosh computor?

17:25 sdegutis: yes

17:25 haha! i like how you slightly spelled computer differently for effect!

17:25 very well done

17:25 technomancy: macintoshes don't support having modifiers pressed on one device affecting keycodes from another device

17:25 thank you

17:25 sdegutis: well im sure i can hack it in

17:26 im a programmer, see...

17:26 technomancy: a what?

17:26 sdegutis: that means i can create anything i can imagine

17:26 * technomancy peers at sdegutis, clearly unconvinced

17:26 sdegutis: watch this

17:26 see? did you see that?

17:27 i created something just now

17:27 technomancy: inconceivable

17:27 sdegutis: oh contrare.

17:28 so im thinking all i have to do is find a big switch and a microcontroller

17:28 then ill be able to use emacs without being in pain all the time! :D

17:29 technomancy: you would probably have to modify your OS's keyboard driver or something

17:29 sdegutis: i have my ways sir

17:29 CGEventTapRef or something

17:29 ill map out every ";" at the hardware level to be Ctrl

17:29 (who uses ; anyway)

17:30 Bronsa: sdegutis: so you don't write comments

17:30 sdegutis: ok fine &

17:30 nobody uses &

17:31 Bronsa: no varargs?

17:31 sdegutis: oops i mean F16

17:31 technomancy: just use the arrow keys

17:31 those are lame

17:31 Bronsa: I use them :(

17:31 sdegutis: thanks everyone for your feedput

17:35 Oh wow, Sticky

17:36 Keys is great!

17:39 SagiCZ1: any ideas for my question?

17:39 TimMc: technomancy: Wait, they don't? So those Kinesis foot pedals are useless on a Mac?

17:40 Bronsa: SagiCZ1: why no overloading?

17:40 SagiCZ1: you can do (fn x ([a [b c]] (x a b c)) ([a b c] (do-stuff)))

17:42 SagiCZ1: Bronsa: its easy with overloading.. i was thinking about the '& more' thing.. if it can be used to recognize that im putting in a collection as 'more' and not wrap it in a list as usual

17:42 technomancy: TimMc: they plug into the keyboad itself; they're not independent deivces

17:43 TimMc: huh

17:44 sdegutis: I actually know how to write the Stick Keys feature on OS X.

17:44 Perhaps I should use that knowledge to build something similar but better, and sell it.

17:47 Bronsa: SagiCZ1: do you have a use case in mind or?

17:54 sdegutis: The website I write gets between 2k and 4k page views per day. I could probably use SQLite3 with WAL and get a significant performance improvement over using Datomic.

17:55 SagiCZ1: Bronsa: my function foo uses & varargs so it is convinient when calling like this (foo 42 "name" :a :c :d ..) instead of (foo 42 "name" [:a :b :c ...]) note that there can be any number of arguments after "name".. another function -bar- uses foo internally and receives :a :b :c .. in the same way as foo but that wraps it in a list so i cant call (foo 42 "name" other-arguments) in this function.. maybe i should just use 'apply' and be d

18:04 the_danko: amigos, i have a little recur question if anyone is feeling bored

18:04 (defn triang ([] (triang 0 1))

18:04 ([presum n]

18:04 (let [newsum (+ presum n)]

18:04 (cons newsum (lazy-seq (recur newsum (inc n)))) ))

18:05 so this doesn't work

18:05 i need to change the recur to triang

18:05 it looks like it is trying to recur to the let []

18:05 and it gets an argument count mismatch

18:06 so recur goes to the closest assignment block, i.e. []?

18:06 maybe i have already answered my own question . . .

18:06 cfleming: the_danko: No, it won't go to the let

18:07 the_danko: The problem is that recur has to be in tail position in your function, and you have it inside a lazy-seq

18:07 the_danko: CompilerException java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 0 args, got: 2, compiling:(/private/var/folders/df/0z098cs56496gxlycxf2688c0000gn/T/form-init5659419162470671422.clj:4:29)

18:07 cfleming: thanks!

18:08 cfleming: the_danko: I'm actually not sure why you're getting that particular error, but recur will definitely not work inside lazy-seq.

18:08 Bronsa: that confusing exception is because lazy-seq wraps the body in a fn

18:08 cfleming: Bronsa: Ah right, of course.

18:09 the_danko: Bronsa: cfleming: ahh. by the body, you mean? (recur newsum (inc n)

18:09 dbasch: the_danko: you’re not in tail position

18:09 Bronsa: ,(macroexpand-1 '(lazy-seq 1))

18:09 clojurebot: (new clojure.lang.LazySeq (fn* [] 1))

18:09 dbasch: you can’t recur from there

18:09 TimMc: Bronsa: Imagine how mcuh worse it would be if lazy-seq's wrapper fn took more than 0 args.

18:10 dbasch: oh, cfleming already said it

18:10 Bronsa: TimMc: yep. it would be useful if there was a primitive that acted like ^:once fn* but did not set a recur point

18:10 macros could use that & error messages could be better

18:10 TimMc: ^:passover

18:11 Bronsa: probably :once would be fine aswell

18:11 the_danko: Bronsa: cfleming: dbasch: thanks a lot! i'll be getting to macros soon and thus will understand then.

18:11 dbasch: the_danko: replace recur by triang and it should work

18:11 cfleming: So I'd like to write a macroexpander that takes a form and expands it step by step

18:12 TimMc: It would be nice if macros and specials highlighted differently from fns.

18:12 Bronsa: TimMc: yeah it doesn't really make any sense to recur a ^:once fn*

18:12 cfleming: sounds like tools.analyzer might help you there

18:12 TimMc: Bronsa: I guess it is only called once, for that matter.

18:12 cfleming: So each time I call it I pass it the results of the previous step, and it will recurse down into the form until it can perform a macroexpand-1, and then return the results of doing the expansion at that point.

18:13 Bronsa: , ((let [a (Long. 2)] (^:once fn* [] (when a (println a) (recur)))))

18:13 clojurebot: 2\n

18:13 cfleming: Bronsa: how would t.a help?

18:13 It's a surprisingly tricky problem - neither Riddley nor tools.macro are well structured to do it.

18:14 Bronsa: cfleming: you want to macroexpand subforms too right?

18:14 cfleming: Bronsa: Right. I'm going to make an interactive macro stepper for Cursive.

18:14 TimMc: Bronsa: freeeaky

18:15 Bronsa: e.g. (let [a (when 1 2)]) => (let* [a (when 1 2)]) => (let* [a (if 1 (do 2))]) cfleming ?

18:15 TimMc: well that's the whole point of ^:once :P

18:15 cfleming: Bronsa: Exactly.

18:16 the_danko: cfleming: boom! go cursive! ha, i am sure i'll get and appreciate what you are suggesting soon.

18:16 Bronsa: cfleming: well t.a.jvm saves all the macroexpansion steps for every expr so if you don't mind macroexpanding everything even if you only need n steps, it should be trivial to use t.a.jvm for that

18:17 TimMc: Bronsa: I was vaguely aware that there was some kind of optimization, but I didn't realize it was that one.

18:17 cfleming: Performance isn't a huge concern, so I could potentially recurse down into the form like tools.macro and just try all the potential expansion points until I find one that actually expands.

18:17 Bronsa: TimMc: it basically tells the compiler "the body is only going to be evaluated once so you're free to clear all the closed over vals"

18:18 s/vals/locals

18:19 cfleming: Bronsa: Yeah, that would be fine - I was thinking about modifying tools.macro to do something like "perform n macroexpand-1's on this form" which would give me what I want.

18:19 But the stateful iteration is quite ugly.

18:19 seangrove: "Languages with static typing that don't need validation (e.g. Om in ClojureScript), and production level compilers will be able to generate these objects inline instead of going through the validation step. This optimization will allow significant performance improvements in React.

18:20 cfleming: Bronsa: Any pointers as to where I should look in the t.a.jvm code?

18:20 seangrove: Om doesn't bring any static typing to the table, does it? Definitely the production-level compiler

18:20 cfleming: the_danko: Hopefully it'll help you understand macros better!

18:20 the_danko: When it's done, that is.

18:20 seangrove: I wonder if they put the Om reference after the wrong point

18:22 Bronsa: cfleming: a bunch of pointers: - t.a's macroexpander is swappable, - if present in a node, :raw-forms holds the macroexpansion steps for the original :form of that node

18:22 cfleming: also passes.jvm.emit-form might help, it's an AST to clojure code compiler

18:23 cfleming: it's late-ish now but if you want I can write a quick POC of how that might work by tomorrow

18:24 cfleming: Bronsa: Ok thanks. It's morning here, I'll see what I can come up with today and if that would be helpful I'll drop you a mail.

18:24 Bronsa: I suspect there's a fairly simple solution in there somewhere, I just haven't seen it yet.

18:25 Bronsa: BTW while I have you, can you see any problems with this? https://github.com/cursiveclojure/cursive/issues/567

18:26 Bronsa: cfleming: the same problems we have for eastwood: you can't attach metadata to everything

18:26 cfleming: Bronsa: I remember some discussion on the mailing list between Ambrose and Andy Fingerhut about this WRT Eastwood and Dynalint

18:27 Bronsa: Right, I guess in the worst case your exclusion scope is too big

18:27 Bronsa: yeah

18:27 cfleming: Bronsa: Ok, I'll investigate that a bit more, thanks.

18:28 Bronsa: Does Eastwood have anything like this now? I should use the same mechanism if so.

18:28 Bronsa: cfleming: no it's still an open question

18:28 cfleming: Bronsa: Ok, thanks.

18:28 Bronsa: cfleming: the only 100% accurate solution is to put the directive in a #_comment before the form to affect but that requires dropping the reader and using a parser

18:29 cfleming: Bronsa: Ok, I can do that trivially in Cursive, thankfully

18:29 Bronsa: Since I'm working from source

18:29 Bronsa: cfleming: well if you can do that than I'd use #_{:suppress [whatever]} syntax

18:31 cfleming: Bronsa: Ok, I'll look into that - that's pretty trivial for me, although it's a little ugly too. I can probably fold it though.

19:04 mr_rm: justin_smith: remember that question i had about WEB-INF/weblogic.xml?

19:04 justin_smith: mr_rm: yeah

19:05 mr_rm: justin_smith: :war-resources-path is the answer. i'm such a retard at times :)

19:05 justin_smith: mr_rm: oh, I thought that was just the same as :resource-path when I looked at it

19:05 mr_rm: good to know!

19:05 wonder if it's worth a pr on the ring docs?

19:05 mr_rm: justin_smith: :resources-path puts stuff on the classpath so it will go under WEB-INF/classes

19:07 mwfogleman: justin_smith: I just found out that the bug I've been having is in core

19:07 justin_smith: http://dev.clojure.org/jira/browse/CLJ-1413

19:07 mr_rm: justin_smith: well it's in there toward the bottom. it would be nice if it mentioned something about app server specific descriptors to give you an easy search. really that's exactly what you need when you're deploying to JEE servers with a lot of special config

19:08 justin_smith: i'll try to tweak it a bit and offer a PR and see

19:09 justin_smith: mwfogleman: weird - so what exactly are the combination of factors that make this happen?

19:11 mwfogleman: justin_smith: in user.clj, trying to require a namespace with a defrecord

19:12 it's nice to know i'm not the only one ;)

19:12 i've felt kind of crazy, especially since fixing the hyphens didn't fix it.

19:12 justin_smith: yeah, the weirdest bugs are the worst when you have less experience with the language

19:13 because you have more reasons to second guess your own code

19:13 mwfogleman: exactly.

19:14 what have you folks been working on in here?

19:16 justin_smith: mwfogleman: some features updates on a client web site

19:16 AeroNotix: mwfogleman: I just wrote a dispatcher/multiplexer thing for Amazon SQS messages

19:16 and a payments system using auth.net

19:16 also, messing with riemann

19:16 justin_smith: they wanted routing to be based on freeform strings from db data rather than unique identifiers (ugh)

19:17 AeroNotix: that sounds so much nicer than messing with routing to pages based on db data

19:17 AeroNotix: justin_smith: it does indeed

19:17 :)

19:18 justin_smith: AeroNotix: has anyone written "core.async for multiple servers" yet?

19:18 mwfogleman: :D

19:18 AeroNotix: justin_smith: I think I saw that some where. "net chan" or something

19:19 it's kind of broken doing that. It's cool that you get the same API n all. But network failures aren't part of the "api" for core.async

19:19 Still, I'd probably use it for certain things

19:19 justin_smith: AeroNotix: my intuition is that once you have the layers on the network in place on both ends, not much else about core.async would have to change

19:19 AeroNotix: justin_smith: I saw a really nice library for using Zookeeper backed atoms

19:20 justin_smith: AeroNotix: it's cool as long as you never use watches

19:20 AeroNotix: justin_smith: why?

19:20 justin_smith: the watches in that lib are pathologically broken

19:20 AeroNotix: the watch api for zookeeper lets you set a watch, but that watch is removed immediately when it is triggered

19:20 AeroNotix: gotcha, noted. I was gonna use it a couple of months ago for a linearly scalable STUN design we ended up not needing

19:20 justin_smith: ah yes, you need to reset the watch. I thought that was very odd.

19:21 justin_smith: AeroNotix: the semantics just do not agree with the clojure semantics, and so things you would expect to work just break

19:21 AeroNotix: justin_smith: yeah, the raw ZK library doesn't make you do that.

19:21 justin_smith: AeroNotix: and the watch resetting could miss changes that happen between trigger and reset ...

19:21 AeroNotix: yupp, it's messed up doing that.

19:21 justin_smith: AeroNotix: but if you just want a reference type over the network, without watches, yeah, that seems to work in my experience

19:22 AeroNotix: justin_smith: I didn't use it in anger. I was just prototyping a couple of designs for scalable STUN.

19:22 Ended up looking at riak_core in the end. Then that project got shit-canned

19:22 and never mind that STUN itself is ridiculously scalable even on a single node.

19:23 I wouldn't mind a proper automation tool written in Clojure for AWS.

19:23 justin_smith: this stun? http://en.wikipedia.org/wiki/STUN

19:23 AeroNotix: justin_smith: yeah

19:24 justin_smith: AeroNotix: I have a multi-part-stream-upload patch for clj-aws-s3 that I mean to resubmit upstream as soon as I have time to clean it up

19:24 AeroNotix: nice!

19:24 What i mean is some kind of declarative way to describe your infrastructure, ec2/elb/sec groups etc

19:24 justin_smith: AeroNotix: I was doing streaming transforms on file data, and decided putting it on my own disk was a waste

19:24 AeroNotix: but in EDN or something

19:25 justin_smith: AeroNotix: ahh, cool

19:25 AeroNotix: and the Clojure library would parse that and make the necessary changes

19:25 justin_smith: yeah if you're in EC2 there's no point putting stuff on your own disk that you want

19:25 that you want to keep*

19:26 justin_smith: yeah - the disk usage was just a temp file - but I was like "why can't I just use an inputstream and an outputstream with my algo in the middle?" so that's what I did, but multi-part-upload that doesn't use files was a pre-req for that

19:27 AeroNotix: Gotcha. I find the java streams stuff a of a crappy API

19:27 You can do a lot of neat stuff with them though

19:27 a of a?

19:27 a bit of a*

19:28 seancorfield: org.clojure/java.jdbc 0.3.6 is coming soon - fixes JDBC-100, JDBC-101, JDBC-102 (all minor stuff)

19:28 justin_smith: AeroNotix: also, the existing multi-part-upload impl in clj-aws-s3 seems to be trying to do parallel upload of chunks - but I intend to benchmark that and prove that there is no situation where out of order chunked upload from a disk (ssd or hd) is faster than linear access

19:28 AeroNotix: from a disk you're probably right

19:29 justin_smith: AeroNotix: and the API demands a File

19:29 so it all seems a bit silly to me :)

19:29 AeroNotix: does seem it

19:29 justin_smith: I guess a File object could be on a ramdisk partition...

19:30 but that seems like a big iff

19:30 AeroNotix: I find those kind of optimizations are often just done for the sake of it

19:30 "optimizations"

19:30 justin_smith: AeroNotix: ;; this is the part where we turn optimization up to 11

19:30 AeroNotix: justin_smith: haha

19:40 Bronsa: cfleming: http://sprunge.us/JLdM?clj this is hackish and totally not efficient, but it should work fine as a POC

19:43 amalloy: Bronsa: i totally don't have the context to comment on the meat of that code, but it seems weird to me that you're writing (concat asts [a]) when asts appears to be a vector throughout the process, and you even do (conj asts a) to append to it in a different spot. is there something i'm missing there?

19:45 Bronsa: amalloy: no, I was doing something else before where asts was a seq rather than a vector and just left it that way

19:46 amalloy: there are other things worse than concat in that code, I just threw it together to see how it might work

19:53 amalloy: Bronsa: it's a feature i'd be happy to have, though, and it's great the analyzer is powerful enough you can throw it together in a short time. i don't really think i need a stepping macroexpansion debugger, because if i write a macro complex enough that i can't do it in my head i'm making a mistake, but i can see this being really useful for someone with less practice

19:54 Bronsa: amalloy: yeah it's definitely something I wish I had when I started learning lisps

19:56 cfleming: http://sprunge.us/KMgD?clj a less inefficient version

19:57 * Bronsa hopes nobody is judging him for that set!

19:59 justin_smith: Bronsa: cfleming: now add colorization so that each expanded form gives its color highlighting to its expansion in the next form down, put it in a box, wrap it in a bow, and bob's your uncle

20:01 lazybot: why not try using MONADS!?

20:02 amalloy: Bronsa: i judged it but found it a reasonable enough approach to not criticize you

20:03 lazybot: thanks, man. good idea

20:03 Bronsa: hah

20:03 (inc lazybot)

20:03 lazybot: ⇒ 31

20:03 amalloy: Bronsa: i set that monad timebomb 24 hours ago and had forgotten all about it. i do enjoy surprising myself with these things

20:05 Bronsa: I just panicked thinking I found a t.a.j bug

20:05 turns out it's just a clojure bug so all is good

20:05 justin_smith: haha

20:05 amalloy: oh yeah?

20:05 justin_smith: "my platform is broken, that's so much better"

20:05 Bronsa: ,'^{:foo (println "foo")} []

20:06 clojurebot: []

20:06 Bronsa: it's CLJ-something in JIRA

20:07 amalloy: Bronsa: http://dev.clojure.org/jira/browse/CLJ-1137? http://dev.clojure.org/jira/browse/CLJ-1017?

20:08 http://dev.clojure.org/jira/browse/CLJ-1235

20:08 http://dev.clojure.org/jira/browse/CLJ-1187, apparently

20:08 Bronsa: http://dev.clojure.org/jira/browse/CLJ-1093 actually

20:09 amalloy: yes, i just got there as well

20:09 Bronsa: what a wild ride

20:09 amalloy: following the chain of "x closed as dupe of Y by Bronsa"

20:10 Bronsa: amalloy: there are a number of similar but slightly different issues related how the compiler handles empty collections

20:10 amalloy: yes. and also how it handles reader meta applied to "runtime" objects vs "compile-time" objects

20:10 Bronsa: yup

20:11 amalloy: personally, i choose to never use ^ to apply metadata to objects i want my program to manipulate, and always use with-meta instead. then ^ is only for information i want to give the compiler, and i avoid such ambiguities

20:11 Bronsa: amalloy: yeah that's a more than reasonable stance

20:12 I've spent a good number of hours trying to come up with a fix for all the edge-cases in the Compiler, then gave up

20:14 amalloy: http://dev.clojure.org/jira/browse/CLJ-1017 is a weird one from bbloom

20:15 bbloom: amalloy: side effects in metadata expressions? psha, who needs those?

20:18 justin_smith: I decided to back up and read up about the general concept of metadata

20:19 it seems that an alternate name for metadata as we use it in clj is metacontent

20:19 bbloom: i've flip flopped on whether or not metadata is a good idea so many times, i've lost track

20:19 justin_smith: (the destinction being according to some that metadata is about data structures / architecture, and metacontent about a particular piece of data)

20:19 bbloom: which i guess means that it's motivated by genuine use cases, but not quite the right solution yet

20:20 justin_smith: bbloom: got any good articles or papers to recommend on the subject?

20:20 bbloom: not really, no

20:20 if you find any, please share

20:20 justin_smith: it seems like there must be at least one good 40 page dissertation on metadata in compiler implementation out there somewhere

20:20 bbloom: there's lots of related stuff, like writing about the "identity crisis" with respect to proxy objects

20:20 i'm sure there's something about alists in CL somewhere

20:22 justin_smith: http://www2.informatik.uni-freiburg.de/~keilr/papers/pos2013-proxy.pdf a paper about the proxy identity crisis in js

20:25 dbasch: that paper confuses schizophrenia and multiple identity disorder

20:25 bbloom: heh

20:26 dbasch: a schizophrenic proxy would be quite strange

20:26 get array -> “here’s the rhinoceros you asked for”

20:26 justin_smith: dbasch: a proxy that fundamentally does not "get* the protocols it is expected to implement

20:26 AeroNotix: dbasch: lots of people confuse the two

20:28 justin_smith: dbasch: body without organs / code without datastructures (?)

20:36 amalloy: dbasch: a rhinoceros is just an array of cells anyway, right?

20:37 dbasch: amalloy: don’t tell that to the next rhinoceros you meet

20:37 especially if it just came through a proxy over the wire

20:39 amalloy: dbasch: incidentally, you caused me to realize that rhinoceros is a word i have no idea how to spell. the first half is super-easy, but after that it seems i'm completely lost

20:41 havenwood: rhinawserous

20:41 justin_smith: cute rhino https://www.youtube.com/watch?v=0bL02GyIsKw

20:42 he tries to pronk like his friend

20:42 mlb-: I've got a list of functions and want to execute them all, is there something cleaner than: (->> fun-list (map (fn [f] (f))) dorun) ?

20:43 justin_smith: (dorun (map #(%) fun-list))

20:43 actually (doseq [f fun-list] (f))

20:43 that's the right way

20:45 gfredericks: I know why I like doseq better. it doesn't create a sequence for no reason.

20:45 dbasch: mlb-: curious about the situation in which you have to execute a bunch of functions with no arguments for side effects

20:45 justin_smith: yup

20:45 TimMc: &(format "lib-%04d" (rand-int 1e4))

20:45 lazybot: ⇒ "lib-1113"

20:46 TimMc: thanks lazybot!

20:46 gfredericks: ^ great lib name

20:46 TimMc: Isn't it?

20:46 You have the best naming scheme.

20:47 justin_smith: ,(format "lib-%s" (java.util.UUID/randomUUID))

20:47 clojurebot: "lib-9ae7bac8-3c4f-4f4a-ade0-ef92fae94649"

20:47 gfredericks: too hard to remember

20:47 dbasch: thx-1138

20:47 gfredericks: doesn't roll off the tongue

20:47 ~lib-1113 is the new hotness

20:47 clojurebot: In Ordnung

20:47 justin_smith: ,(format "lib-%s-jure" (java.util.UUID/randomUUID))

20:47 clojurebot: "lib-9e5e6624-24aa-45e4-8ca8-d9b15fb4c211-jure"

20:47 gfredericks: lol

20:48 TimMc: ha!

20:48 gfredericks: (inc justin_smith)

20:48 lazybot: ⇒ 106

20:49 TimMc: ,(apply str "lib-" (map char (repeatedly 15 #(rand-int 65536))))

20:49 clojurebot: "lib-彖ổ?쑡몀⧹鯏䢭艠ᐑ뤪ﶒ枌"

20:50 gfredericks: oh dear

20:50 justin_smith: ,(lib-彖ổ?쑡몀⧹鯏䢭艠ᐑ뤪ﶒ枌.core/summon-old-one)

20:50 clojurebot: #<ClassNotFoundException java.lang.ClassNotFoundException: lib-彖ổ?쑡몀⧹鯏䢭艠ᐑ뤪ﶒ枌.core>

20:50 TimMc: phew

20:54 justin_smith: TimMc: who am I kidding, it would be a java lib, and I would need to invoke the static AbstractOldOneSummonerFactory method, then use that to do the summoning with

20:54 after inheriting from the proper classes etc.

20:54 TimMc: NoneuclidianAbstractSingletonProxyFactoryBean would *definitely* be involved.

20:55 dbasch: someone should put together a lib to generate clojure library names, all you need is a list of obscure characters from tolkien books and similar

20:55 TimMc: .ia().ia().ia()

20:55 justin_smith: (inc TimMc)

20:55 lazybot: ⇒ 76

20:56 TimMc: All those incantations probably use builder methods.

20:58 dbasch: CamelCaseNamesForJavaClassesWhoCantReadGoodAndWantToDoOtherStuffGoodTooFactory

20:59 nwolfe: Heh, www.classnamer.com gives you some good ones :D

21:49 arrdem: justin_smith: I would totally use a lob with an AbstractOldOneSummonerFactory. Not nearly enough tentacles and too much sanity in my code.

21:49 s/lob/lib/g

21:58 justin_smith: arrdem: the prophecy will be revealed and then it shall come to pass, nyalothep will gaze upon our code and find it unwanting, and his indifference will delete it, and along with it all of the bugs it held. So it shall be.

21:59 arrdem: arrdem: http://www.marlborotech.com/Zalgo.html <- I would use the crap out of a Clojure lib that did that

21:59 justin_smith: arrdem: my buddy patchwork made one

21:59 arrdem: justin_smith: https://www.youtube.com/watch?v=FOHJUrcVdJk

21:59 as long as we're off topic..

22:00 justin_smith: clojars or it didn't happen

22:00 justin_smith: arrdem: I introduced him to zalgo, and he was like, awesome, bam https://github.com/prismofeverything/zalgo

22:00 arrdem: clojars as requested https://clojars.org/zalgo

22:01 arrdem: justin_smith: whelp... I guess Grimoire 0.3.10 is totally gonna have a zalgo mode now

22:07 justin_smith: arrdem: the obvious extension is zalgoize-stacktrace

22:08 when you know clojure too well, and the stacktraces actually seem useful...

22:08 arrdem: AHAHAHA

22:08 justin_smith: for the nostalgia, of course

22:08 arrdem: that would be an amazing cider module

22:08 hum... https://github.com/clojure-grimoire/grimoire/issues/131

22:08 should this be a feature? I'm torn

22:08 I should fix it, since it's broken, but should it be a feature.

22:09 justin_smith: offline mode is a good thing

22:09 celwell: Hi, how can I test a coll to determine if all the value in it are equal?

22:09 gfredericks: (apply = coll)

22:09 celwell: ah, nice

22:11 works well thanks

22:12 arrdem: justin_smith: so my thing with the "offline" build is that you can totally clone Grimoire and run it locally

22:12 justin_smith: as time goes by the static HTML build makes less and less sense

22:12 justin_smith: hmm

22:21 bbloom: how do people feel about crazy language embeddings, such as https://github.com/pallet/stevedore ?

22:25 justin_smith: bbloom: woah, how well does that actually work?

22:26 bbloom: justin_smith: *shrug* i guess that's the real question

22:26 i've seen it in use, and my initial reaction is horror

22:26 justin_smith: yeah, can't say just from the source / unit tests, would have to use it

22:26 bbloom: but then i realize i'm writing cljs, which is basically the same idea

22:26 so i'm not sure where the horror comes from

22:26 or how to characterize it

22:27 justin_smith: bbloom: I think my default horror comes not from the act of translation (which we know can be done well) but from the known pitfalls of half-assed or overambitious translation

22:28 bbloom: justin_smith: yeah, i guess that's it

22:28 justin_smith: bbloom: but it takes real usage or significant examples to know which is going on (unless you are a language-converting tool master of some sort I guess)

22:29 bbloom: so i mention stevedore b/c i experienced it in a production system, but i'm actually more interested in other metaprogramming/cross-compiling tasks

22:29 justin_smith: bbloom: it's like - if my buddy says "I'm gonna jump out the second story window, it's gonna be awesome", I am going to try to stop him. But if a guy at the circus jumps from an equivalent height, I kind of figure he has that under control

22:29 bbloom: justin_smith: heh, intersting analogy

22:30 i have a far-far-far from complete version of https://github.com/Constellation/escodegen in clojure built on my Fipp library

22:30 justin_smith: of course this means rich hickey = evel knevil

22:31 bbloom: fascinating - what's the use case for that, js as compiler backend?

22:31 bbloom: yeah

22:32 i wanted to do a compile to js language and i wanted to implement the compiler in clojure

22:32 but i was hand crafting ast nodes like {:head :if :test {...} :then {...} :else {....}} and it was just veeeerbose compared to (if a b c)

22:33 so i started to create a ns of factory methods and an elaboration pass that basically macroexpands things like "foo" in to things like {:head :string :value "foo"}

22:33 but after using this for 20 minutes, i immediatley got annoyed that the factory syntax didn't cover a corner case and i got annoyed

22:34 hence my question about stevedore, etc

22:34 justin_smith: out of left field thought seeing those ast data structures: I wonder how useful it would be if a tool like t.a.jvm transformed clojure code into a "normalized" form where each symbol is replaced by a map with a :value key or something similar alongsize the metadata (with a reverse translation available as well, of course)

22:35 bbloom: i'm not sure i follow

22:35 justin_smith: folks were talking about how many bugs there are in metadata handling

22:36 so what about a transformation of clojure code into a form where the data is embedded in a map with the metadata

22:36 this would be inefficient

22:36 but it could also be a more explicit form where the metadata is now regular data, and is part of the printed representation etc.

22:37 it's total speculation, probably not actually useful

22:38 bbloom: the other frustrating thing is that these little embedded languages never compose

22:38 stevedore is basically lexical macro

22:39 justin_smith: well, that two way transformation thing would fix that, but I guess you need to design in a very particular way for the translation to be reliably two-way

22:40 bbloom: how does a two way transformation help?

22:40 justin_smith: bbloom: it's composible when you bring it back into the common format

22:40 then transform to the other one, doing the operations native to that format?

22:40 maybe this is silly

22:41 bbloom: what's the common format?

22:41 justin_smith: bbloom: haha, I guess that's the problem, I assumed such a thing would just be natural

22:41 bbloom: when your meta language and your object language are both a lisp, things are easy

22:42 justin_smith: bbloom: having to do with what I was talking about above, a normalized, extremely explicit (if less efficient) form

22:42 bbloom: but then metadata (or in older lisps, plists) kind of complicate that

22:43 bbloom: i'm not worried about metadata at all

22:43 justin_smith: OK

22:44 bbloom: i'm worried about constructing syntax trees and emitting code with minimal mental gymnastics of an incomplete translation and an idiosyncratic factory library

22:48 justin_smith: yeah, I was going off on a tangent tying this to the previous discussion

22:48 bbloom: but I think the benefits of lispyness are undeniable for what you want to do

22:49 bbloom: well, unfortunately, js is not a lisp :-P

22:49 i don't particularly want to invent a js-in-clojure embedding just to write a compiler for another language to that intermediate language

22:50 justin_smith: bbloom: if we had a single reliable two way transformation that did not lose information, between ecmascript and something lispy, other tools could leverage that

22:50 bbloom: but i guess that's what i really do have to do if i don't want to write ASTs long form

22:50 the other idea is to go all the way on concrete syntax

22:51 implement a js parser too, extend it with an unquote operation

22:51 basically like js* in the cljs compiler, if you're familiar

22:51 justin_smith: right, I've seen it (though not looked at the impl)

22:51 bbloom: is that parsing js, or embedding js in the output?

22:52 bbloom: i'm saying you'd basically parse a variant of js that supports an operator like #{...clojure code here....}

22:52 and then define a syntax-quote style operator that takes a string

22:53 justin_smith: ahh, so the inverse

22:53 bbloom: (let [x 2 y 3] (js "console.log(#{x} + #{y})")) would produce a JS AST with 2 and 3 substituted in

22:53 you'd still need an "elaboration" pass that returns something like {:head :binop :left 2 .... in to something like {:head :binop :left {:head :number :value 2 .....

22:55 justin_smith: that makes it almost sound like a kind of templating or string interpolation

22:55 cfleming: justin_smith: (re: macroexpansion a couple of hours ago) that's my plan - single step macro expansion, and highlight what's changed in each one.

22:55 bbloom: syntax-quote is templating :-P

22:56 cfleming: justin_smith: The bow would be a nice touch though.

22:56 bbloom: but yeah, the idea is to basically make js-syntax-quote by adding interpolation to a js grammar

22:56 justin_smith: cfleming: very nice

23:00 bbloom: justin_smith: i think i realize what my big objection to something like stevedore is though

23:00 justin_smith: do tell

23:00 bbloom: speaking concretely, stevedore tries to make shell look like clojure

23:00 mimicking another language is the problem

23:00 not translation

23:00 b/c when the embedded object language mimicks the metalanguage, you get in to an uncanny valley sort of situtation

23:01 where it doesn't look or feel right

23:01 the closer it gets w/o being the metalanguage, the stranger it seems

23:01 justin_smith: bbloom: another way to put it maybe is syntactic translation (trivial) vs. semantic (nearly impossible to get right)

23:01 bbloom: but stevedore doesn't try to put clojure semantics in to your shell

23:02 other than some superficial stuff like namespacing locals or whatever

23:02 it is mostly a syntactic translation

23:02 justin_smith: bbloom: I would assume it at least gets the three parts of an if right, etc.

23:02 but that's the semantics that overlaps

23:03 bbloom: cljs is a major semantic AND syntactic shift from js, but it's not so awkward b/c cljs looks like clj and works like clj, rather than looking sorta like clj and working sorta like js

23:03 that's the problem w/ stevedore and many other embeddings, i think

23:03 looking sorta like the meta language and working mostly like the object language

23:03 justin_smith: bbloom: that uncanny valley thing is also why I find trailing parens in a lisp / sticking ones in a non-lisp so annoying - I can read faster when there are no ambiguous clues about which language type I am looking at

23:03 bbloom: hm

23:04 coffeescript for example looks like something totally different and works exactly like js

23:04 no uncanny valley

23:04 justin_smith: right

23:05 bbloom: amusingly, this exists: https://github.com/Gozala/wisp

23:07 sx: Are there popular lisps besides clojurescript which compile to javascript?

23:07 bbloom: sx: i don't know how popular it is, but there's http://common-lisp.net/project/parenscript/

23:07 sx: bbloom: thx checking it out

23:08 justin_smith: sx: I am sure someone has made a scheme -> js compiler. I mean it has to have happened.

23:08 sx: justin_smith: true. i guess I said "popular" since the underlying languages undergo changes and it is not always easy for a compiler to keep up

23:08 justin_smith: :)

23:09 sx: it looks like parenscript latest release is more than two years old. so unlikely to support new ecmascript features

23:09 justin_smith: sx: scheme has the advantage of having standards, on that front, and tools that verify compliance to said standards

23:10 ahh, features in the target language

23:10 that's different, yeah

23:10 sx: yeah in this case

23:11 justin_smith: so, this exists https://github.com/jashkenas/coffeescript/wiki/list-of-languages-that-compile-to-js

23:11 sx: justin_smith: sweet. thats what i was just about to google for..

23:12 justin_smith: clojure-like, scheme-like, other are the lisp subheadings :)

23:12 sx: yes a lot more than I expected. good stuff

23:13 bbloom: justin_smith: i probably should have checked that list, there's likely something i could use :-)

23:13 justin_smith: sx: it would be nice to have a version of that page annotated with project activity levels, adoption rates

23:14 TEttinger: Ki looked good, justin_smith -- uses clojurescript data structures but can be used as js macros within js code

23:14 sx: yes I am looking at Ki now.. caught my eye too

23:14 TEttinger: so you have stuff like map, filter, apply, -> with a different name

23:14 justin_smith, yeah, I have https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS bookmarked

23:15 it used to reside at http://altjs.org , but I think it's been taken

23:15 yep

23:18 bbloom: justin_smith: https://github.com/krisajenkins/yesql embodies the parser approach, only they don't have a particularly sophisticated parser (they just look for questions, mostly)

23:19 maybe better to call it the "interpolation" approach

23:19 justin_smith: bbloom: yeah, another kind of macro that looks a lot like templating

23:19 right, interpolation is the word

23:20 bbloom: i think i like this approach much better than what i started to do

23:20 b/c what i started to do basically amounts to designing both an AST as an "API" aaaaand a language as embedded in clj

23:20 then also implementing a code generator for that language w/ a js backend

23:20 justin_smith: bbloom: what I like about yesql is it isn't a hinderance to someone who knows some actual sql

23:20 bbloom: unlike so many sql interaction libs

23:21 bbloom: yeah, my goal isn't to make the prettiest programs ever that all feel perfectly uniform

23:21 my goal is nicely formatted js compiler output w/o breaking my desk via head banging in trying to generate precisely the js i want

23:21 any embedding of js is going to be the uncanny valley thing

23:25 ok, but that involves a parser too ... of some kind

23:25 heh, a task for another day

23:28 joshhead: sx: lispyscript looks pretty cool. I think it keeps mostly javascript semantics but with different syntax and macro support

23:28 no idea who uses it

23:29 justin_smith: joshhead: an amazing thing with lisp is you can find a small obscure thing and even though it is not popular you can actually do stuff with it

23:29 joshhead: I made some cool things with lush, which nobody here has likely heard of

23:30 TEttinger: justin_smith, the lisp shell?

23:30 am I confusing it with fish?

23:30 justin_smith: (a lisp that compiles to c, with an emphasis on linear algebra, dsp, and the ability to do things without gc)

23:30 TEttinger: the lisp one

23:30 TEttinger: oh yeah, that sounds familiar

23:30 justin_smith: though I think the shell part is misleading here

23:31 TEttinger: fish is an array programming language IIRC

23:31 justin_smith: there is also a shell called fish

23:31 statements which are totally absurd out of context for 100, alex

23:31 bodie_: what is a cursor?

23:31 justin_smith: bodie in om?

23:32 bodie_: yeah

23:32 I'm reading the swannodette breakdown on it, and it just made it worse

23:32 I want to either not understand it at all, or actually understand it, lol

23:32 justin_smith: IIRC the general concept is it tracks a place for update, but deeper than that I can't help you

23:32 bodie_: yeah, I think it's a reference to a location

23:33 .... I think

23:33 but he refers to lenses and zippers and I think my brain exploded

23:33 puredanger: first poll done by Rich on what people wanted in Clojure (Sept 2008): https://groups.google.com/d/msg/clojure/BUlpZTDMvQ0/ko-5Q7mtoDAJ

23:33 justin_smith: bodie_: a lense is named after the fact that it can be a microscope or a telescope

23:34 bodie_: hm

23:34 justin_smith: bodie_: it lets you insert a value into a nested place, or extract one out, with the same abstract construct

23:34 joshhead: justin_smith: do you think obscure projects are more likely to be useful if they leverage a lisp? :)

23:35 justin_smith: joshhead: that is my theory but I cannot prove it

23:36 joshhead: often the problem with these small obscure things is they are incomplete

23:36 joshhead: a lisp self-evidently contains the tools to round itself out as needed, within your program

23:39 TEttinger: puredanger, it's somewhat entertaining that almost everyone mentions error messages. have there been any improvements other than core.typed?

23:40 hiredman: there have been many

23:41 puredanger: sure, every release makes improvements to error messages

23:41 TEttinger: I mostly just infer what the error message probably means from experience, and look for whatever line numbers are in my code

23:41 justin_smith: bodie_: OK, I am reading the docs, and yeah it is like a lens

23:41 clojurebot: In Ordnung

23:41 hiredman: https://github.com/clojure/clojure/commit/b8181b7e424230b8d43008f86d03645dbef8edb0 is maybe the most recent commit that improves error messages

23:41 puredanger: if y'all would just stop making errors, this wouldn't be an issue

23:41 joshhead: bodie_: An om cursor has an interface similar to an atom. you can dereference it you get dome value, and you can apply a function to it to update the value

23:42 justin_smith: bodie_: or very similar to the way you can use the same path in get-in / assoc-in / update-in

23:42 bbloom: puredanger: the part that stands out to me is map-same

23:42 justin_smith: bodie_: I can go into more detail about any of that if you like

23:42 bbloom: ,(defn map-same [f coll] (into (empty coll) (map f coll)))

23:42 clojurebot: #'sandbox/map-same

23:42 bbloom: ,(map-same inc [1 2 3 4])

23:42 clojurebot: [2 3 4 5]

23:42 puredanger: hiredman: look at https://github.com/clojure/clojure/blob/master/changes.md for error message changes

23:42 bbloom: but he didn't try lists!

23:42 ,(map-same inc '(1 2 3 4))

23:42 clojurebot: (5 4 3 2)

23:42 bbloom: :-(

23:43 i've encountered that problem several times

23:43 joshhead: bodie_: but the data that an atom references actually lives lives at a path in an atom or another cursor. when you update the curso, the changes are reflected in the atom as well

23:43 puredanger: bbloom: heh

23:44 bbloom: seems like it might be possible to create a sort of concat-ing lazy seq thing

23:45 but of course stack overflows would strike

23:55 numberten: does anyone know why the implemention of core/pmap adds 2 to the number of availableprocessors? https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L6465

23:56 justin_smith: numberten: perhaps related to the fact that the agent thread pool multiplies by 2 and adds 42

23:56 bodie_: justin_smith, joshhead, thanks for that, didn't see your responses :)

23:56 bbloom: numberten: first, regarding pmap...

23:56 ~pmap

23:56 clojurebot: pmap is not what you want

23:57 bbloom: numberten: second, the reason it adds 2 is probably purely heuristic for dealing with the operating system scheduler

23:57 bodie_: justin_smith, if you could tell me which docs you're looking at for cursors, that's probably the best I could get. I assume clj home

23:58 thanks again fellas

23:58 numberten: bbloom: alright thanks

23:58 bbloom: really, if you had exactly the same number of threads as processors, you'd want that, but other threads are running on the machine, so in reality 1-to-1 doesn't work out quite right

23:58 i'd imagine 2 just happens to work for some cases (maybe not even *many* cases)

23:58 joshhead: bodie_: good luck

23:58 numberten: i see

23:59 bbloom: but pmap is horribly broken since lazy seq chunking and other such changes to clojure... but it was always more of a cool demo than a useful function

23:59 puredanger: N + 2 is the perfect number of threads

23:59 for all values of N

Logging service provided by n01se.net