#clojure log - Feb 01 2016

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

0:00 lockdown: scottj: gonna give it a try some day, my mba with 4gb doesn't like it, used eclipse on other machines

0:03 it can do a repl without lein, I wonder it does it, is it referring to the network repl introduced in 1.8?

0:03 +how

0:04 justin_smith: lockdown: clojure.jar plus capturing stdin/stdout?

0:04 lockdown: also, you can use lein to calculate classpath and cache it, and use that to launch clojure.jar

0:04 lockdown: justin_smith: prolly

0:05 rhg135: that feature is great for cljs

0:05 arrdem: I have a script somewhere for doing just that.. use lein to compute the classpath, cache it and never boot lein again unless project.clj changes. gives you a really fast repl start.

0:05 rhg135: before the other IDEs got nREPL usable for cljs

0:06 that's what fast trampoline is no?

0:06 lockdown: justin_smith: oh nice

0:06 justin_smith: arrdem: btw if you use lein trampoline and turn on LEIN_FAST_TROMPOLINE in the shell lein does that for you

0:07 lockdown: code formatting, that one must be hard for clojure

0:07 arrdem: lockdown: clj-fmt and clojure-mode do a pretty good job

0:09 lockdown: arrdem: does it follow some guide? don't see anything in the clj-fmt repo

0:10 arrdem: lockdown: it aims to be configurable, but I think that bozhidar's guide dominates

0:12 https://github.com/bbatsov/clojure-style-guide link in case you can't find it

0:14 lockdown: thanks

1:25 athinggo2ngon: I am relatively new to Clojure, and I am having a hard time reading the following. I wanna know if it's due to the poor quality of the code.

1:25 http://pastebin.com/NxtnMT8t

1:27 opqdonut: yeah I would've used some helper functions / local variables there

1:28 also if you don't know as-> that's going to throw you off a bit

1:28 also, I think a for would look better instead of that map

1:29 Bronsa: athinggo2ngon: that code isn't even valid

1:29 opqdonut: yeah it's actually missing the parameter vector

1:30 should be something like (defn get-lookup-datasources [xforms]

1:32 justin_smith: even worse, it uses flatten

1:33 opqdonut: :P

1:51 Raynes: Sup peeps. Who manages the new Clojure website?

1:54 While I appreciate the reference to tryclj.com, I haven't maintained it in literally years and probably won't for at a minimum 3 months. It's old, broken in mysterious ways a lot, and I have generally completely ignored reported issues. It might not be worth being on there unless someone wants to help me out with maintaining and updating it (I can work with you a bit, just busy with other things most of the time, you'd be given admin on the repo) or

1:54 wait on my completely detached ass to return from the void.

1:55 justin_smith: Raynes: I think contacting cognitect or the clojure-dev mailing list would get you in touch with the right person

1:56 Raynes: I'll hit the clojure-dev mailing list methinks, since I'm also asking for help.

1:57 domgetter: Raynes: Thanks for the awesome website :)

1:57 Raynes: The one with the ancient Clojure version and half-broken sandbox? You're welcome good sir.

1:58 :p

1:58 Guys I'm so deep in Python I feel like a mouse.

1:58 Gonna have to get some hython or something

1:58 princeso_: what is the reason one can not pass macros as arguments?

1:59 Raynes: Because they're not functions.

1:59 They're things that expand to code.

2:01 They are... speshul, to put it gently.

2:04 Bronsa: Raynes: just open a ticket over https://github.com/clojure/clojure-site/issues

2:04 princeso_: i suspected that maybe it was because they cannot be recompiled every time you call them with diferent parameters. is that right?

2:04 Raynes: Bronsa: Damn son you is on it.

2:04 Bronsa: princeso_: macros are of no use at runtime

2:11 Raynes: Bronsa: https://github.com/clojure/clojure-site/issues/55

2:11 Commented

2:12 amalloy: princeso_: that is one way of describing it, which seems reasonably correct

2:12 Raynes: amalloy: Hello darkness, my old friend.

2:14 Also you guys I really need a Clojure Python port.

2:14 Like a week ago.

2:14 Get it done.

2:14 :p

2:14 justin_smith: Raynes: how close is pixie to being the right thing?

2:15 amalloy: aren't there a number of bad clojure borts to python?

2:15 justin_smith: I guess it can't do python interop at runtime (directly at least)

2:15 amalloy: like Hy or something

2:15 clearly you have to make your own, Raynes

2:15 Raynes: With all this time I have

2:15 Hell, I'm running late being on irc right now.

2:16 Bronsa: enough talking, let's start building this already

2:17 Raynes: justin_smith: You just told me about it. From first glance pypy scares me.

2:17 I don't work in this environment and know little about it.

2:17 I am now enterprisey as fuck, sorry guys.

2:17 Worth looking into though.

2:18 Noted and thank you kind sir

2:20 justin_smith: No python 3.5 interop is a nogo

2:21 justin_smith: hy uses python's mutable types, and its assoc mutates maps

2:22 Raynes: I need it's libraries.

2:22 justin_smith: fair enough

3:26 breezeli: hi all!what mean is the keyword" :blastoff!"

3:31 MasseR: breezeli: it's not a keyword

3:31 It's just a symbol

3:31 No wait, clojure terminology :foo is a keyword, sorry

3:32 But anyways, it's just a user defined keyword like :foo or :bar

3:32 breezeli: it like a strng

3:32 string

3:33 maybe

3:33 MasseR: (keyword "blastoff!")

3:33 > (keyword "blastoff!")

3:33 breezeli: look like!

3:34 (defn countdown

3:34 [x]

3:34 (if (zero? x)

3:34 :blastoff!

3:34 (do (println x)

3:34 (recur (dec x)))))

3:34 this example

3:35 Bronsa: breezeli: please don't paste long snippets in IRC

3:35 breezeli: ok,sorry

4:26 renl: hi I was wondering if I wanna search some text in a big text file do I have to reread the entire file everytime i need to do a search since there is no variables to store the read content

4:27 MasseR: renl: you can always save the contents to a variable

4:28 renl: i thought there is no variables in clojure? im super noob at this

4:28 MasseR: Ah I see what you mean

4:28 There are variables, they are (by default) immutable

4:28 (def foo "foo")

4:28 Creates a 'variable'

4:28 as well as (let [foo "foo"] foo)

4:29 renl: so if i (def mystr (slurp "bigfile"))

4:29 MasseR: Exactly :)

4:29 renl: do i get the string in the file or do i just define the slurp command

4:30 MasseR: Former

4:30 renl: as in everytime i access mystr am i reading the file again?

4:30 oh ok

4:30 thanks

4:30 and when does this (def ....) kick in? the moment i run the script?

4:31 MasseR: I'm not actually sure. Clojure is lazy, but I'm not sure if it's only datastructures that are lazy

4:31 But basically the def kicks in when that line is read

4:32 renl: ok thanks :)

4:32 MJB47: it reads the file when a) the function enclosing the def is called or 2) if it is at the root scope of a namespace, when the namespace is called

4:33 ridcully_: ,(doc delay)

4:33 clojurebot: "([& body]); Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?"

4:34 renl: @MJB47 so if i have multiple functions enclosing the def do i read the file everytime or only the first time?

4:34 MJB47: everytime i believe

4:34 unless you memoise it

4:50 J_Arcane: ... '() is not nil?

4:51 opqdonut: it's not

4:51 ,(next (list 1))

4:52 J_Arcane: Which means, apparently, that you can't trust if-let if the result can return '()

4:52 clojurebot: nil

4:52 opqdonut: ,(rest (list 1))

4:52 clojurebot: ()

4:52 J_Arcane: ...

4:52 Rick77: Hi! Is there any special notation to specify that a method accepts a vector instead of a map? Something that doesn't require me to add ^clojure.lang.PersistentArrayMap?

4:58 tumbleweeds rolling in wind... :)

5:00 tdammers: why is it important for the argument not to be a map?

5:00 or any other kind of collection, for that matter

5:01 Rick77: I would like to pass the result of a function to java, just for safekeeping, and I would like for java to know the argument type. I figured out it would matter, but now that you are asking I'm not so sure...

5:01 tdammers: ah, interop...

5:01 jellytux: Hi, I wanna start learning clojure

5:01 Rick77: to be honest I was also just curious if there is a way: some algorithms work with specific kind of collections and not other, what if I would like my function to be called only with maps?

5:02 jellytux: does clojure run within JVM?

5:02 I don't fancy java :(

5:02 Rick77: jellytux, yes, it does

5:02 MJB47: yes, bugt clojurescript and clojureCLR dont

5:02 tdammers: jellytux: yes, normally it does; there's clojurescript that targets JavaScript as a backend, and it's theoretically possible to use other backends, but I am not aware of any

5:02 MJB47: however i would like to point out that java != JVM

5:02 Rick77: oops, ehm, yes, as MJB47 said :)

5:02 tdammers: right, CLR

5:03 Rick77: I'd probably settle for restricting my function to map-like things using preconditions

5:03 Rick77: tdammers, DBC like stuff, then?

5:04 sounds good to me

5:04 tdammers, thank you!

5:04 tdammers: Rick77: was thinking of this: http://blog.fogus.me/2009/12/21/clojures-pre-and-post/

5:07 Rick77: tdammers: didn't even knew that existed... thank you! (I'm still in the process of learning clojure, but since there is no way to take it without having something practical to do with it, I'm going with what I have :) )

5:07 tdammers: np

5:07 Rick77: thanks!

5:08 jellytux: may I use vim as my editor? I don't know whether JVM implies Eclipse :(

5:08 MJB47: most people use emacs or vim for clojure

5:09 for IDE, i believe cursive (intellij) is used

5:09 i dont think many people use eclipse

5:10 luma: this is from the latest State of Clojure survey: http://static1.squarespace.com/static/5372821be4b0aefc6719057e/t/56a7dc8d3b0be343e82ef921/1453841550679/?format=1000w

5:11 jellytux: MJB47: awesome!

5:24 dysfun: luma: that's quite interesting. i expected more light table even though i don't like it

5:25 jellytux: Sorry for asking again, but is it advised to learn Java before Closure?

5:25 MJB47: it helps, but isnt necessary

5:25 dysfun: jellytux: it's really not necessary

5:25 jellytux: it seems to use Java String objects

5:25 and many other things from Java

5:25 dysfun: yes, because it's a bit silly to create your own basic types when java has them

5:25 it makes working with java stuff a nightmare

5:26 what clojure brings you by default is a bunch of useful functions for working with (mostly) collections and a means of interoping with java

5:26 ridcully_: but it helps alot to know the underlying bit and bobs. e.g. know what a classpath is, how classes are loaded etc.

5:27 dysfun: tbh i think even that's abstracted away by build tools adequately

5:27 ridcully_: yes, but when things blow up, you will have to look into this

5:28 dysfun: jellytux: the best advice i can offer is if you find yourself using a java type, you can google its long name (e.g. java.lang.String) and google will show you the oracle page for that class

5:28 but it's rare i drop to the java interface. there are some good reasons to with strings occasionally (performance)

5:29 and if you are familiar with java and you know a given class solves your proboem, you can just use that

5:29 there are an awful lot of libraries that wrap java to put a nicer interface on it though

5:29 see e.g. http://www.clojure-toolbox.com/

5:30 also i recommend http://conj.io/ as a useful tool for finding relevant functions while you're learning

5:30 jellytux: I think I am gonna try learning haskell instead, I don't wish to have anything to do with Java

5:30 a language should stand on its own

5:30 hopefully Haskell does

5:30 dysfun: like haskell uses llvm as a backend?

5:30 jellytux: dysfun: I don't know

5:30 TEttinger: or C-- before that

5:30 dysfun: it seems like an odd reason to pick a tool

5:30 domgetter: Haskell uses wizards and time machines

5:31 dysfun: i don't use clojure when i need something to start up very quickly, but otherwise it's a fantastic environment

5:31 TEttinger: if you want a language that stands on its own, there's... assembly

5:31 dysfun: and every library i could ever want at my fingertips

5:31 TEttinger: there's sorta JS

5:31 jellytux: dysfun: what do you use if you want to start up quickly?

5:31 dysfun: one of the reasons i don't program haskell is that i don't have every library i could ever want at my fingertips

5:32 depends. c++, c or haskell depending

5:32 TEttinger: LuaJIT here

5:32 dysfun: or perl

5:32 if you don't have massive performance requirements, perl can be brilliant

5:33 but startup time isn't everything

5:33 being able to launch something and forget about it and not be bothered by having to worry about it falling over, that's a nice thing to have

5:33 jellytux: I want to learn a functional language

5:33 TEttinger: if it's text-processing heavy I usually prefer the really excellent JVM regular expression lib, and I don't really understand the sigil mess in perl

5:34 dysfun: it's pretty straightforward. $one_thing, @list_of_things, %map_of_things

5:35 $list_of_things[0], $map_of_things{'a_key'} # still talking about one item, so $, [] and {} say you're talking about a list or a map

5:35 the corresponding list ops are @foo[1..5], @map{'a','b'}

5:35 TEttinger: oh yeah, that stuff is simple

5:36 it's when they start packing on punctuation that I glaze over

5:36 jellytux: TEttinger: which language are you discussing?

5:36 TEttinger: perl

5:36 dysfun: the thing clojure taught me was that syntax dosn't matter

5:36 TEttinger: 6 for me

5:36 dysfun: perl6 is mad, i'm not defending it

5:36 perl5 on the other hand is an excellent tool

5:36 TEttinger: ah ok

5:36 MJB47: dysfun: interesting, clojure taught me the opposite lol

5:36 jellytux: is it similar to PHP?

5:36 TEttinger: perl?

5:37 jellytux: yes

5:37 dysfun: php was derived from perl but somehow they made it really shit

5:37 TEttinger: PHP is a much less capable language that everything

5:37 MJB47: i find the compactness/expressiveness of clojure/s expression syntax to be incredible

5:37 ridcully_: perl is the only language i have to run over to the book shelf to search the cookbooks for things like list in maps

5:37 dysfun: it's not forgiving to newbies, i'll grant. but that problem is you not knowing how to wield it properly

5:38 TEttinger: I haven't tried perl 5. I was trying the grammar stuff in perl6 and it's pretty... black magic opaque

5:38 dysfun: yeah, don't get me started

5:38 i speak out against perl 6 a lot. i'm er... 'infamous' in the perl community

5:38 TEttinger: hehe

5:39 dysfun: that's one thing clojure has over perl

5:39 TEttinger: I really have found clojure much more readable now that I've stuck with it

5:39 initially it was hard to read

5:39 dysfun: nobody wants to write C to glue into the jvm, but with perl it's just achievable enough you go for it

5:39 ridcully_: perl was my go to lang for all adminy stuff. i only use it for oneliner nowadays. i have not even looked at 6

5:39 dysfun: tbh i don't actually write perl any more

5:40 and i haven't spoken at a perl conf in 4 years i think

5:40 jellytux: what kind of programs do you write in clojure?

5:40 dysfun: right now i'm writing a restful webservice for example

5:41 jellytux: could I get a sneakpeek?

5:41 dysfun: what, you mean some code?

5:41 jellytux: dysfun: yeah

5:41 dysfun: it's going to be open source, so i don't see why not

5:41 jellytux: cool

5:41 dysfun: oh actually, i can show you some of the templating stuff i pushed yesterday

5:42 jellytux: git?

5:42 dysfun: yeah

5:42 https://github.com/irresponsible/wildebeest/blob/master/src/wildebeest/html_string.cljc

5:42 TEttinger: I write clojure mainly for one-liner stuff these days but sometimes, for jobs that would be really complex text handling in an imperative language, I write a few paragraphs of clojure and it does the equivalent of pages of java

5:43 dysfun: i just like simple libraries and having macros to eliminate repetitive typing

5:43 TEttinger: absolutely

5:43 I love the seq stuff

5:43 jellytux: wow, even though I've never coded in clojure before, it really looks strikingly familiar

5:43 dysfun: it's nice, but you often pay for it

5:43 TEttinger: especially the conveniences relating to seqs, re-seq , line-seq

5:43 jellytux: very readable

5:44 dysfun: jellytux: well i've been writing clojure for 2 or 3 years now, so that's what it can be, not what you'll write while you're learning

5:44 TEttinger: yeah, it's common for beginners to over-use "mutable" types like atoms and refs when there are ways to avoid them

5:44 dysfun: and obviously while i'm making lots of changes, it's not very neat and tidy :)

5:45 which reminds me, i need to finish porting midje to cljs

5:45 jellytux: I coded a bit in Rust, and stumbled upon that problem myself

5:45 tdammers: TEttinger: depends on the beginner ;)

5:45 dysfun: heh, i actually prefer c++ over rust

5:46 modern c++ that is. c++11/14

5:46 jellytux: I prefer both :D

5:46 dysfun: gotta say i was pleasantly surprised

5:46 i've been doing a lot of c++ (desktop client) work recently and modern c++ is much more enjoyable than old skool c++

5:47 i was also surprised to enjoy it so much after doing so much clojure

5:48 tdammers: modern C++ feels a lot like Haskell to me, in many ways

5:48 dysfun: maybe once you decide syntax doesn't matter and just go with the way the language encourages, you attain enough enlightenment to not care and just write code :)

6:02 jeaye_: ,{:a :b (when true {:c :d})}

6:02 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

6:02 jeaye_: Is something like that possible?

6:02 Where some expression within a map literal can return a new key-value pair for the map.

6:03 Sure, I can wrap it in a let, destructure, etc, but I'm wondering if some inline way of doing this exists.

6:03 MJB47: i think because if it was (when false ...) it would return nil

6:03 and obviously you cant have {:a :b nil}

6:03 jeaye_: mmm

6:03 MJB47: might be possible with a macro?

6:04 ridcully_: ,(cond-> {:a :b} true (assoc :c :d))

6:04 clojurebot: {:a :b, :c :d}

6:04 jeaye_: ,(doc cond->)

6:04 clojurebot: "([expr & clauses]); Takes an expression and a set of test/form pairs. Threads expr (via ->) through each form for which the corresponding test expression is true. Note that, unlike cond branching, cond-> threading does not short circuit after the first true test expression."

6:05 jeaye_: ridcully_: Neat! Thanks.

6:21 daveau: hi all. Is there a standard way to convert a sequence of numbers (could be bytes or ints e.g. [255 -11]) to a string (e.g. like using (apply str (map char [255 -11])) but char -11 fails) ?

6:21 I can do (String. (byte-array [255 -11])) - but seems wrong. Just wondering, is there a more clojury way of doing this?

6:28 jeaye: ,(apply str [1 2 3 4 -11])

6:28 clojurebot: "1234-11"

6:29 jeaye: daveau: What output are you expecting? -11 isn't a valid char.

6:29 MJB47: he said -11 should fail

6:29 daveau: sorry. -11 should not fail

6:29 MJB47: oh i missread

6:29 my bad

6:29 jeaye: daveau: Ok, what do you expect -11 to output?

6:30 daveau: i can't copy in the character, but an extended ascii/utf-8 character

6:31 so [255 -11

6:31 *so [255 -11] would be a two character string.

6:31 jeaye: So you're expecting these to be multi-byte UTF8 chars?

6:32 daveau: no, a string with two single utf8 chararacters.

6:32 same output as (String. (byte-array [255 -11]))

6:33 this works, i just thought I was doing it wrong...

7:00 jeaye: Raynes: ping

7:16 jonathanj: ,(conj {:a :b} (when true {:c :d}))

7:16 clojurebot: {:a :b, :c :d}

7:17 jonathanj: ,(conj {:a :b} (when false {:c :d}))

7:17 clojurebot: {:a :b}

7:24 jeaye: jonathanj: Nice!

7:24 Even simpler.

7:25 Actually, not much simpler in practice. http://dpaste.com/15QFTC7

7:25 Simpler to understand, I think.

7:26 Ah, typo

7:26 Better http://dpaste.com/041YQ1W

7:31 ridcully_: another option would be `merge` - which basically is a conj, but "sounds" better

7:35 jeaye: I'm currently seeing an issue with Raynes' fs lib, where touch doesn't properly set the modification date.

7:36 (fs/touch "meow" (+ (System/currentTimeMillis) 3600000))

7:36 Should be an hour in the future

7:47 Unfortunately, the modification time remains the creation time.

7:47 Ah, only when creating.

7:48 If the file already exists, it behaves as expected.

7:48 Raynes: ^^

11:47 irctc: Where are clojure jobs?

11:47 I need one.

11:55 * Kamuela points to The Cloud

12:03 kwladyka: irctc i guess in USA and UK ;)

12:14 Kamuela: kwladyka: where? lol

12:15 kwladyka: Kamuela i guess in the Internet. Anyway there are much more job offer in Clojure then in east europe.

12:15 cortexman: is there a way to get this REPL version of fib working in a loop? https://gist.github.com/brianmingus/58fa0ac88161abdbb52e

12:16 justin_smith: cortexman: would make more sense to do it as a lazy-seq, but yes

12:17 cortexman: justin_smith, i can't get it to work. seems that it can't access *1 and *2 inside a loop

12:17 justin_smith: those are special repl values, you have to change that part

12:17 cortexman: i'm trying to use those.

12:17 justin_smith: ,((fn fib [a b] (lazy-seq (cons (+ a b) (fib b (+ a b))))) 0 1)

12:18 clojurebot: (1 2 3 5 8 ...)

12:18 justin_smith: cortexman: those are only useful in the repl

12:18 they literally are defined only by the repl

12:19 the above lazy-seq uses arguments to hold the last two results

12:19 I know it doesn't look the same, but it's the same flow

12:20 it would be easier to read using loop maybe, but then you need to decide when it stops

12:20 MJB47: i get the feeling cortexman is doing it as an exercise, and not for actual code :P

12:21 cortexman: yah

12:21 justin_smith: well, exercise or not, *1 or *2 are not going to be helpful outside of the repl

12:24 Shayanjm: I'm building a 'distributed application' (i.e: 4 separate applications, all communicating via a few redis queues)

12:24 are there any best practices on how to structure these types of applications in Clojure? Should they be compiled as a single jar and run with options? Or should they be 4 distinct applications (4 jars)?

12:25 justin_smith: Shayanjm: how distinct are the servers?

12:25 Shayanjm: justin_smith: they're 4 components to a whole, essentially. There's something that generates a lot of data that then needs to be processed/consumed by the other components

12:26 justin_smith: Shayanjm: no harm in sharing the same codebase and having a different -main for each

12:26 Shayanjm: then you can launch with java -cp uber.jar clojure.main this-main.ns

12:26 Shayanjm: Cool, I'm assuming there are no performance impacts unless I load a bunch of stuff I shouldn't inside those -mains

12:27 maybe just start up performance impairment

12:27 but not run time, right?

12:27 justin_smith: Shayanjm: the perf impact would come with loading, if you don't load the other namespaces they won't have much effect

12:27 not even startup, if you don't load them

12:27 Shayanjm: Awesome

12:27 also, on that note - any best practices on the actual distribution architecture?

12:28 justin_smith: Shayanjm: clojure doesn't eagerly load every namespace it could (though you probably already know this)

12:28 Shayanjm: logging, lots and lots of logging

12:28 Shayanjm: i.e: is it efficient to be running like 4 of the same clj processes at a time as 'workers'?

12:28 justin_smith: otherwise you'll have no idea what is happening when things break (and during dev things will break)

12:28 Shayanjm: or should that be handled by threading inside one such process?

12:28 justin_smith: Shayanjm: that really depends on the job!

12:29 is it network bound, cpu bound, memory bound?

12:29 Shayanjm: ah sweet, so the same tradeoffs as the rest of the programming world :)

12:29 was just wondering re: overhead of running multipleinstances of the JVM

12:29 justin_smith: right - but if you use threads, use real thread pools. Claypoole is a great lib for this

12:29 Shayanjm: sweet, thanks

12:29 justin_smith: Shayanjm: it's not helpful to have more than one jvm on a box, but it's very helpful to have more boxes

12:30 during dev you probably want more jvms on one box just so you can control them all

12:30 Shayanjm: Yeah

12:30 but production should be 1 jvm per box with multiple threads?

12:31 justin_smith: Shayanjm: consider kafka - I know you mentioned redis, but kafka has some nice properties (including the fact that the message queue doubles as a log which is great when things go bad)

12:31 Shayanjm: oooh that does sound nice

12:31 justin_smith: Shayanjm: exactly. And backpressure / pool sizes to keep within the limits of that box.

12:31 Shayanjm: yeah I'm not sold on redis by any means, it just seemed like an easy solution

12:31 justin_smith: kafka plus transit for encoding the messages has been awesome in my distributed app

12:31 Shayanjm: fantastic, I'll probably just throw all of those into like a config.clj or something

12:32 what type of message encoding have you needed?

12:32 justin_smith: I just blindly throw data into transit mostly

12:32 and get regular clojure out the other end

12:32 Shayanjm: lmao awesome

12:33 that sounds ideal tbh

12:33 i'm going to look at kafka + transit

12:33 justin_smith: it's worth it, yeah

12:33 Shayanjm: thanks justin_smith

12:34 justin_smith: one bonus of kafka being a log based queue: when boxes fall over, other boxes can easily grab the messages those boxes were handling

12:34 Shayanjm: np! this is like most of the hard stuff with the app I've been working on, so there's lots I could say about it :)

12:35 Shayanjm: justin_smith: I had to do something similar in an earlier application, but it wasn't quite as distributed as this

12:35 I could get away with throwing everything into a single queue and consuming from STDIN/STDOUT

12:35 but this particular application will need some level of performance guarantees + searchable history

12:36 so +100 for kafka :) Thanks again for the suggestions

12:36 Will probably be back to pick your brain later tho

13:36 justin_smith: I don't know why it took me this long to do it, but I just made an uberjar with clojure 1.8. plus pomegranate for resolving deps (and a helper function that automatically adds clojars to the repos). If your list of deps is fairly short this seems like the ideal thing for clojure with any deps you might need usable in a script

13:37 I would have used alembic (which is slightly friendlier) but it bails out if it can't find a project.clj

14:06 Shayanjm: justin_smith: which kafka wrapper do you use?

14:07 justin_smith: Shayanjm: clj-kafka, but I mostly use kafka directly (since it's a scala / java project) and just use a few of their helper functions

14:07 Shayanjm: gotcha

14:17 justin_smith: another one off question... What's the overhead of a read against Kafka? i.e: if I want to verify that the data in question is not actually a duplicate of something (recently) previously processed, would that verification step be better done by keeping an up-to-date atom in memory than against kafka itself?

14:21 l1x: hey guys

14:21 who can you override this? https://github.com/damballa/abracad/blob/master/src/clojure/abracad/avro/util.clj#L5

14:22 justin_smith: Shayanjm: Kafka ensures that a given consumer only gets each message once, I've never seen any issue with this. For a cluster I just make sure all servers are in the same consumer group, and that way each message will go to one server.

14:23 Shayanjm: justin_smith: Right, my specific usecase is in scraping. Between scraping intervals I can't guarantee that the site in question has infact changed

14:23 and I don't want to be spinning the wheels more than necessary

14:25 l1x: justin_smith: strictly speaking with 8.x if the consumer crashes before it could commit the offset that caused the crash it will receive it again

14:25 justin_smith: l1x: aha, that makes sense - there's no such thing as "exactly once" in distsys after all

14:26 l1x: but in practice I've found this a small enough concern compared to other bugs introduced by my own code that it's pretty far down the list

14:29 l1x: yeah theory vs practice :)

14:35 blake_: So, I'm about to move my server-side rendering to client-side with reagent.

14:35 Where previously I sent the client HTML, I'm now going to send a data structure.

14:35 And I'm going to make a reagent function that renders that structure, as it would've been in the HTML.

14:36 Every time there's a change, the server sends a new structure, and the client renders it.

14:36 And this will be faster because...React compares the renderings, not the data structure. And in fact isn't even aware of the data structure (except, I guess, as an atom whose state changes).

14:36 Is that about right?

14:36 justin_smith: sounds about right, though sometimes it's easier to just send the differences and merge them on the frontend

14:37 blake_: err, that last part - react compares the data structures not the rendered result, so you have that backward

14:37 blake_: Hmm. Not sure I'm going to know what the differences are.

14:37 justin_smith: blake_: for immutable data, the comparison is especially fast

14:37 blake_: look at the code that changed the data?

14:37 blake_: though that doesn't work in all apps of course

14:38 blake_: justin_smith: Heh. It's POI. So sorta a black box, though I do have some code to test dependencies. (Which wasn't easy to get.)

14:38 justin_smith: But the structure comes from the server side, and must, so how is the data immutable.

14:38 I mean, if I'm swapping out the whole structure every time?

14:38 justin_smith: OK in that case it probably won't be incremental updates then (most apps would have some kind of incremental change)

14:39 blake_: Well, they are incremental in fact, but not to me. Or not easily to me. So...will it really be faster?

14:39 justin_smith: blake_: just like in any other usage of an atom, the atom is mutable, the data inside is immutable

14:40 blake_: So, let's say my data structure is a list of the words in a dictionary.

14:40 justin_smith: blake_: the key is that react can quickly go through the data structure, if it knows it changed, and figure out which subkeys are equal (no need to update) and which are no longer equal (need update)

14:40 blake_: Which I've retrieved from the server.

14:40 And then I ask the server for the list again, and it's exactly the same but for one new word.

14:41 justin_smith: blake_: OK

14:41 blake_: With regular Clojure, I'm using the same underlying reference. The tree shares actual branches.

14:41 But here I'm getting the list from the server--it's essentially a copy.

14:42 justin_smith: blake_: if the list is rendered as a list (eg in a table or ul), react will ask you to put a unique key on each item (which can be the word itself), that way it knows what needs update in the list and what is unchanged

14:42 it doesn't need to be the same Object, having the same structure suffices (though having the same object is faster of course)

14:45 blake_: OK, the key thing...that's probably what I'm missing.

14:45 But it does seem like it's comparing the rendered form to me. Not the actual rendered form on-screen but the underlying DOM. Which maybe calling a "rendering" is confusing. =P

14:46 justin_smith: no, the point of react is to touch the dom as little as possible

14:46 blake_: But it does this by having a shadow DOM, right?

14:47 justin_smith: so it has the dom (what the browser actually renders), the input data (not shaped like the dom at all), your components (which take input data and render something shaped like the dom) and the last version of the input data

14:47 it compares the last version of the input data to the new version of the input data. Where they differ, it updates the shadow dom, and that is propagated to the dom

14:48 it doesn't need to compare anything to the dom, because the dom won't have changed

14:48 and in fact if you change the dom yourself, react just throws an error and says "you broke it"

14:49 more or less

14:49 (for those parts of the dom it actually watches / updates)

14:49 blake_: Well, sure.

14:50 justin_smith: blake_: so nothing gets compared to the dom, it compares the data to the new data, that decides which components are re-rendered, and that updates the shadow-dom

14:51 blake_: OK, so in my case, I'll need a table rendering but also a cell rendering, so that it can update the individual cells rather than the whole table every time, I'm thinking.

14:52 justin_smith: blake_: sure, if you put the right :key metadata on the cells, it should be able to handle that intelligently (at least that's how it works in reagent, which is the wrapper I have experience with)

14:52 blake_: justin_smith: Reagaent has been the most approachable for me.

14:53 justin_smith: blake_: it basically uses the :key to know the difference between "cells changed order" and "cells changed value"

14:53 blake_: And I was planning on have the server send vectors (rows) of maps (cells), where the contents of each cell are style and value.

14:54 justin_smith: makes sense - then you could key on style and reagent should be able to do the rest

14:54 blake_: Well, I was going to key on the cell address. Could I key on the style if the style is shared between more than one cell?

14:55 justin_smith: oh, then you do need to key on the address I guess

14:56 blake_: Yeah, a lot of style sharing. The styles are in the CSS, which is generated for the whole thing up front. Though thinking about, I'll probably have to have local overrides.

14:59 Are Reagent components atomic?

15:01 Shayanjm: amalloy_: strong work on ring-buffer, super helpful

15:01 really nice to use too - works exactly as you would expect it to

15:15 spuz: is it possible to desctructure the parameter of an anonymous function?

15:17 scottj: spuz: not in #() literals, but in (fn [...]) yes

15:17 Glenjamin: ,((fn [[a b c]] (str a b c)) ['y 'e 's])

15:17 clojurebot: "yes"

15:18 spuz: scottj, thanks scottj. I was thinking about #() literals specifically

15:18 is there a name for #() vs fn ?

15:18 Glenjamin: function shorthand, i guess

15:18 scottj: spuz: anonymous function literal and fn

15:18 spuz: thanks

15:19 scottj: spuz: #(let [[a b] %] ...)

15:21 spuz: #(let [[arg1 [arg2-a arg2-b]] %&] ...)

15:21 Glenjamin: although i'd argue at that point (fn) is preferrable

15:21 scottj: Glenjamin: agreed

15:24 Bronsa`: everytime I need to write more than one % I switch to fn

15:41 adam____: hey how do I make a function which takes a map but requires that the map which is being passed in has certain keys?

15:41 like is there a way to catch that at compile time?

15:41 or can people pass in whatever and then if the map doesnt have the key it will just give me nil

15:48 base698_: it's probably one line. use keys

15:49 and contains?

15:49 Adam ^^^

15:53 rcassidy: aw, he left.

15:53 ,(defn key-stuff [{:keys a b}] (str a b))

15:54 clojurebot: #<RuntimeException java.lang.RuntimeException: Map literal must contain an even number of forms>

15:54 rcassidy: ,(defn key-stuff [{:keys [a b]}] (str a b))

15:54 clojurebot: #'sandbox/key-stuff

15:54 rcassidy: ,(key-stuff {:a "hi" :c "nope"})

15:54 clojurebot: "hi"

16:11 Somelauw: Why does core.matrix have both mul and emul? https://mikera.github.io/core.matrix/doc/clojure.core.matrix.html

16:20 amalloy: i'm glad to hear that, Shayanjm

16:22 justin_smith: yeah, you can't enforce keys of the input to a function at compile time because you don't know the keys of the input at compile time

16:27 olieidel: i'm having problems joining the clojurians slack channel. it says already invited but i never got any email. is this a common problem?

16:29 amalloy: irc is secretly where all the cool kids hang out anyway

16:33 justin_smith: ~irc

16:33 clojurebot: irc is only for opionfests

16:33 justin_smith: ~slack

16:33 clojurebot: slack is where all the cool kids went.

16:34 blake_: clojurebot is committed to the lie.

16:34 amalloy: opionfests, huh?

16:35 hiredman: that quote should be attributed

16:35 -- rhickey

16:35 justin_smith: amalloy: like oktoberfest but much sleepier, I imagine

16:35 amalloy: well rich probably spelled it right. or did he not?

16:35 hiredman: no idea

16:53 gfredericks: tcrawley: I bet you were hoping somebody would ask a question about immutant 1.1.4

16:53 can I be that somebody for you?

16:53 * jcrossley3 slides to the edge of his seat

16:55 Shayanjm: If I have a collection like '([1 2 3] [4 5 6] [7 8 9]) - how do I combine all the elements in the collection to result to [1 2 3 4 5 6 7 8 9]?

16:55 is there a nice idiomatic way to do it?

16:55 justin_smith: Shayanjm: apply concat

16:56 ,(apply concat '([1 2 3] [4 5 6] [7 8 9]))

16:56 Shayanjm: justin_smith: you are my hero today

16:56 clojurebot: (1 2 3 4 5 ...)

16:56 justin_smith: Shayanjm: with great knowledge of clojure trivia comes great responsibility

16:57 Shayanjm: also, if you preferred a vector, reduce into would work there too

16:57 ,(reduce into '([1 2 3] [4 5 6] [7 8 9]))

16:57 clojurebot: [1 2 3 4 5 ...]

16:57 justin_smith: but reduce into will not do what you want if the first item fails to be a vector

16:57 ,(reduce into '((1 2 3) [4 5 6] [7 8 9]))

16:57 clojurebot: (9 8 7 6 5 ...)

16:57 Shayanjm: ah

16:57 justin_smith: so apply concat is in that sense more general

16:58 Shayanjm: that makes sense

16:58 amalloy: justin_smith: reduce into []

16:58 justin_smith: amalloy: oh, true

16:58 amalloy: i would never count on the first to be a vector, really

16:58 justin_smith: ,(reduce into [] '((1 2 3) [4 5 6] [7 8 9]))

16:58 clojurebot: [1 2 3 4 5 ...]

16:58 tcrawley: gfredericks: I'm all ears!

16:59 amalloy: it's been a long time since i used reduce's 2-argument flavor for real code

16:59 justin_smith: amalloy: I guess 3 arg is almost always better, since you would usually know what kind of structure you are building

16:59 Shayanjm: Is there any significant difference between (into [] (apply concat ...)) vs. (reduce into [] ...)?

17:00 justin_smith: Shayanjm: yes, the reduce into does less work

17:00 Shayanjm: awesome

17:00 justin_smith: Shayanjm: since with concat you build a strucure of one type, then empty it into a structure of another type (vs. simply filling a structure of the type you wanted from the start)

17:01 Shayanjm: That makes sense

17:01 I really should do some research on these actual implementations

17:04 gfredericks: tcrawley: I'm wondering how difficult and/or impossible it is to have various web apps deployed at the root with different ports to differentiate them

17:05 tcrawley: that's only possible if you 1) run multiple immutant 1.x processes, or b) deploy apps that start their own webservers within the container on other ports (i.e. jetty, immutant 2, etc)

17:06 both are !good options

17:06 iii) use a proxy in front of immutant that maps ports to context paths

17:06 gfredericks: tcrawley: ACK thanks

17:06 tcrawley: my pleasure!

17:07 gfredericks: tcrawley: does immutant 2 support this better?

17:08 tcrawley: yes, with immutant 2, you can start up multiple undertow servers on different ports, but since you have different apps, it would probably be better to run each as a separate process, on a different port

17:08 if you deploy Immutant 2 apps to WildFly, you're back in the same situation as Immutant 1

17:08 gfredericks: oh gotcha okay cool ACK ACK

17:08 we can't inc people anymore can we

17:09 (inc tcrawley)

17:09 amalloy: you can (dec lazybot) though

17:09 gfredericks: ,(def karma (atom {}))

17:09 amalloy: in memoriam

17:09 clojurebot: #'sandbox/karma

17:09 gfredericks: ,(swap! karma update 'tcrawley (fnil inc 0))

17:09 clojurebot: {tcrawley 1}

17:09 tcrawley: ha

17:13 gfredericks: ~immutant |runs on| wildflower

17:13 clojurebot: You don't have to tell me twice.

17:19 WorldsEndless: For interop purposes I need to un-lazy a seq, but doall doesn't seem to work

17:19 (type texts)

17:19 clojure.lang.LazySeq

17:19 turbo-tenure.users> (type (doall texts))

17:19 clojure.lang.LazySeq

17:20 hiredman: the type of the seq there has nothing to do with if it has been forced

17:20 why do you think you need a non-lazy seq for interop?

17:20 WorldsEndless: I'm trying to call a java function upon the array, but it isn't an array but a lazy seq (at least, that's how I'm interpreting the error)

17:21 hiredman: seqs (lazy or not) are not arrays

17:22 WorldsEndless: Ah. That would be it

17:22 hiredman: if you need an array, you need to make one and copy the data from the seq you have in to one, there are some functions for this kind of thing, they generally have "array" in the name

17:22 WorldsEndless: t-oarray

17:48 spuz: is there an equivelant of java.util.List.indexOf for vectors?

17:49 justin_smith: ,(.indexOf [:a :b :c] :b) ; yes

17:49 clojurebot: 1

17:49 justin_smith: ,(instance? java.util.List []) ; spuz - furthermore

17:49 clojurebot: true

17:50 justin_smith: so it has an equivalent to indexOf because it is a List so it has indexOf

17:50 spuz: justicefries, thanks is that the recommended way to find elements in a vector?

17:50 because it seems it wouldn't work in clojurescript as it relys on java interop

17:50 justin_smith: spuz: if you want to know the index of the equal item, sure

17:51 spuz: true

17:51 amalloy: you usually don't want to know about indexes

17:51 spuz: i want to find the index because i need to find neighbours (this is for a soduku solver)

17:53 Malnormalulo: Is a vec here representing a row/column?

17:53 spuz: yes

17:53 hiredman: a vector is like a data structure that indexes entries by a single key, which is a number which is the index, what you want is a datastructure that indexes entries multiple ways, so you can look up entries via an index, and lookup indices via an entry

17:53 justin_smith: spuz: alternatively you could have a bimap from number to position

17:53 Malnormalulo: Maybe you need to rethink your data structure. It's a sparse matrix -- should you have all those empty cells?

17:54 justin_smith: Malnormalulo: well eventually you would want to fill the sudoku

17:54 spuz: Malnormalulo, there are no empty cells, just incomplete cells

17:54 Malnormalulo: Yes, but the constraints of sudoku mean you can just as easily map this the other way

17:55 Number in the cell as key, location as value.

17:55 justin_smith: ideally you map both, which is why I mentioned bimap

17:55 spuz: Malnormalulo, interesting

17:55 Malnormalulo: a bimap would also be useful, yeah

17:56 spuz: I'll think about using a bimap

17:56 Glenjamin: sudoku is actually a trimap

17:56 justin_smith: spuz: I don't know if it's in a lib anywhere, but there is this https://gist.github.com/semperos/3835417

17:56 Glenjamin: [x, y, z] => boolean

17:56 justin_smith: Glenjamin: oh?

17:57 Glenjamin: https://hal.archives-ouvertes.fr/hal-00641973/document

17:58 Malnormalulo: by trimap do you mean an omnidirectional map between sets of three related values, or a map where the key is a tuple of three values?

17:58 Glenjamin: i should dig out my old sudoku visualiser and put it on github

17:58 oh, i might have used the wrong term, i meant the latter

17:58 hiredman: ,(doc clojure.set/index)

17:58 clojurebot: Excuse me?

17:58 hiredman: ,(require clojure.set)

17:58 clojurebot: #error {\n :cause "clojure.set"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.ClassNotFoundException: clojure.set, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.ClassNotFoundException\n :message "clojure.set"\n :at [java.net.URLClassLoader$1 run "URLClassLoader.java" 366]}]\n :trace\n [[java....

17:58 hiredman: ,(require 'clojure.set)

17:58 clojurebot: nil

17:58 hiredman: ,(doc clojure.set/index)

17:58 clojurebot: "([xrel ks]); Returns a map of the distinct values of ks in the xrel mapped to a set of the maps in xrel with the corresponding values of ks."

17:58 amalloy: i think i might be some kind of mutant. i was in the middle of recording a keyboard macro in emacs, and suddenly my fingers started trying to use vimkeys instead

17:58 Glenjamin: oh, yeah, trimap isn't the right term

17:59 justin_smith: Glenjamin: yeah, the idea with bimap is it's one data structure where you can look up value and get position (if any) and look up position and get value (if any) without linear scans

17:59 Malnormalulo: Yeah, here "bimap" is just meaning that the key and value each can be used to uniquely retrieve the other

17:59 justin_smith: right

17:59 Malnormalulo: shorthand for "bidirectional map"

17:59 justin_smith: Glenjamin: but now I really want to see a problem elegantly solved with a trimap

17:59 spuz: "We have fully clarified the symmetry relationships that exist between Naked, Hidden and Super-Hidden Subset rules (the latter being classically known as XWing, Swordfish, Jellyfish, Squirmbag and other existent or non existent "fishy patterns")"

17:59 oh man what did i get into here?

17:59 Glenjamin: basically sudoku can be visualised as a cube

18:00 and then you can view the same puzzle from a different side

18:00 and see an equivalent puzzle

18:00 Malnormalulo: that makes sense

18:00 Glenjamin: treat each cell as a set of possible answers

18:00 a solved cell is a set of size 1

18:01 Malnormalulo: That's hardcore combinatorial optimization, though. I suspect the problem here is less about deduping and more about just solving the thing.

18:03 (though I'm totally reading that paper later because heck yeah hardcore combinatorial optimization)

18:04 spuz: Glenjamin, that's pretty interesting. thinking of a soduku solution as 81 points in a 9x9x9 3d cube kind of makes sense

18:05 Glenjamin: when you "rotate", boxes become rows, rows become columns etc

18:05 Malnormalulo: Huh, under that model it's not unlike the n-queens problem

18:05 Glenjamin: it's NP-Complete, so equivalent to a bunch of stuff when generalised

18:05 (i did my dissertation on sudoku)

18:06 Malnormalulo: Well, yeah. But usually the equivalence isn't so easy to see :P

18:07 Glenjamin: my favourite one is bin-packing

18:07 spuz: Glenjamin, but what advantage does rotation give you? You can always solve a puzzle without rotation

18:07 Glenjamin: because it makes me feel like i'm solving some really complex puzzle whenever i go shopping

18:08 spuz: it gives you a fresh perspective (literally), so your eyes get another look

18:08 some of the heuristic-based techniques are easier to spot than others

18:08 spuz: yeah i can see that

18:08 Malnormalulo: iiiiiiinteresting

18:08 Glenjamin: brute-force-wise norvig's approach is pretty much the way to go

18:09 backtracking search with constraint propagation

18:09 Malnormalulo: Oh man, I can almost remember what that means

18:09 (I need to review my into to AI course)

18:09 spuz: well i'm coming at this just trying to impelement my own algorithm, but I've heard the core.logic solutions can be much faster than norvigs algorithm

18:10 Glenjamin: you should end up with the same algorithm with core.logic - but expressed differently

18:10 spuz: i wonder why the performance would be different, let me see what i found earlier...

18:12 Here we go: https://news.ycombinator.com/item?id=4325746

18:13 "Norvig's hard one that takes 188 seconds in Python takes ~60ms (in clojure)"

18:13 obviously python vs clojure is not a fair comparison of the two algorithms

18:13 Glenjamin: i would expect that to be the runtime, rather than the alg

18:13 will have a read

18:14 > It's actually pretty simple. Most of the performance is from Clojure, the purely functional design which gives us backtracking "for free", and the random access nature of the constraint store.

18:15 yeah, aiui it's the same alg, but with an optimised general constraint propagation + backtracking search system

18:16 weird that i recalled all this pretty quickly after all this time

18:16 funny what sticks

18:19 Malnormalulo: I keep meaning to go back and re-implement the basic discrete search algorithms so I remember them better. At this point I'm probably going to have to relearn them entirely

18:21 arry: Hi! How come lein uberjar with :aot :all doesn't compile all dependencies? I've excluded sources from uberjar, and it tells me that ring/middleware/multipart_params/temp_file__init.class isn't in the jar. (and it isn't)

18:21 justin_smith: arry: do you explicitly require its namespace in your code?

18:23 arry: ring is pulling some sneaky runtime bullshit https://github.com/ring-clojure/ring/blob/1.4.0/ring-core/src/ring/middleware/multipart_params.clj#L75 if you add an explicit requirement for that namespace in your code that will fix it

18:24 arry: I didn't require it explicitly

18:24 justin_smith: arry: right - look at my link, load-var requires the thing at runtime, aot has no way to know you needed it

18:24 so if you require it yourself that should fix the issue

18:25 it's ring'

18:25 s fault not yours

18:25 arry: nice, thanks

18:25 it's cool to get help within 2 minutes of posting the question :D

18:26 justin_smith: heh, glad I could help

18:27 arry: is there a way to avoid recompiling sources that haven't changed? I've run `lein uberjar` for maybe 10th time today, with no code changes, and it gets tiring that it takes 5 minutes to compile everything

18:28 justin_smith: arry: do you have a reason to run uberjar other than deploying?

18:28 arry: sure

18:28 to test the deployment :D

18:28 i package the app, see if it works, it doesn't, i change stuff and repackage

18:29 justin_smith: just saying it's easier to run a repl and just incrementally integrate your code updates in the repl

18:29 and interact with the app locally

18:29 arry: it works in the repl, but deployment options differ. For example, clojurescript stuff is different

18:30 justin_smith: arry: that's why one also compiles cljs in the repl (figwheel makes this easier but you can also compile from the repl and it does incremental building nicely)

18:30 or you can use the cljsbuild plugin for continuous auto-building

18:31 arry: yes, it does work in the figwheel and in the repl. But for production it has to be run with advanced compilation, and Figwheel choked on it when I changed the options to something other than :none

18:32 Another reason is that I try to trim uberjar size: it contains ridiculous amount of needless cruft - whole Bootstrap release package, Rhino, etc

18:32 justin_smith: yeah, figwheel can't do advanced, but the bugs caused by aot / advanced compilation (neither of which play nicely with incremental dev) are rare and eventually predictable

18:33 but really no, I don't think there's a way to use lein uberjar that caches better than the current implementation, though perhaps there's room to make a better incremental jar building tool?

18:33 s/implementation/default - I am sure you could hack lein to do better caching

18:34 arry: I wish it were so. I tried to look in Leiningen source but it was so functional and pure that I didn't understand where stuff happens

18:34 justin_smith: arry: did you get as far as the uberjar plugin?

18:34 arry: I think so

18:34 justin_smith: arry: perhaps boot would be more to your taste

18:35 arry: yes, that's an option; and I seem to remember they had something about incremental compilation in a recent news item

18:36 though to be honest my priority is to get my site to public, so I have only time for complaining instead of fixing the infrastructure stuff :)

18:49 amalloy: whining-driven development

19:29 bcoburn: the thing in Clojure where I maps/vectors are also functions is amazing. Might be the feature I'd miss most if I switched back to Common Lisp

20:10 pilne: clojure is much fun

20:11 although i've been intrigued by prolog lately

20:11 Guest71828-: it is not very safe to use a computer as administrator for general tasks. protip.

20:13 but minikanren (core.logic) is something i've been reading up to on as well

20:55 BRODUS: i have a project where i need to create a simple tasks that starts a server and runs grunt watch, i know I could create a plugin to do this, but that seems overkill, does leiningen have another way to do this?

20:55 or do people normally write a shell script in this case?

20:56 justin_smith: BRODUS: lein-shell can make an arbitrary shell command into a lein task https://github.com/hyPiRion/lein-shell

20:56 but if you are going to leave it running that means lein will have to stay running too of course

20:57 BRODUS: hmm, shell script it is

20:57 but thanks for the link,

21:53 Kamuela: Does it make sense to design programs or think in terms of every outermost function is the one with side effects?

21:57 LucidTortoise: Ilearned something today. The iPad is way to small to serve a second screen.

21:58 Well, it is great as long as you use any resolution below retina.

21:58 Then you can actually read text!

23:24 jkl: Gh

Logging service provided by n01se.net