#clojure log - May 15 2014

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

0:01 dgleeson: l1x: makes sense

0:01 devn: l1x: https://gist.github.com/anonymous/d4dad5ff47ae7e92f7a5

0:02 i've logged to make sure I'm hitting :started.

0:03 ddellacosta: devn: was just going to ask--so started definitely is happening, huh?

0:03 devn: if I inc pending in a different place, outside of the condp, right before i add the listener

0:03 everything works

0:03 but it's just weird, and i can't figure out why the hell this would be happening

0:04 it's like the atom is "warming up" or something

0:04 but then again, that might be the s3 transfer manager?

0:04 it boots up its own thread pool

0:05 oh no. im a terrible liar.

0:06 :started apparently is not getting hit now on the first go-round

0:06 i wonder why that's the case...

0:08 it's weird because i re-eval the ns, run a fn in the REPL, see that :started isn't hit. so then i was thinking well it must be something like the upload completed too quickly, but if I wait for awhile and do another, they forever after hit the :started event

0:08 it's just after i re-eval, the very first upload, and no others

0:49 arrdem: ,#inst

0:49 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

0:52 amalloy: devn: i speculate that the :started event never fires at all, on any events; you just get one :failed

0:54 try doing some logging instead of, or in addition to, just munging a number around

0:55 Raynes: amalloy: I wrote the lein plugin.

0:55 amalloy: You should try it.

1:25 bjeanes: man trying to write an oauth1 workflow for friend...

1:26 keep spinning my wheel

1:26 s

1:52 lds: hello

2:41 TerranceWarrior: is it possible to make a c++ interface to unrealengine from clojure?

2:51 danielcompton: Is there a more efficient/idiomatic way to write https://gist.github.com/danielcompton/1c741fcac42424433943 ?

2:52 I'm wanting the values of a map sorted by key, (map second) seems like a bit of a hack

3:00 mange: danielcompton: would (map val) work better for you? (->> m (sort-by key) (map val)) seems like it would be clearest.

3:01 ,(->> {:c :d, :a :b} (sort-by key) (map val))

3:01 clojurebot: (:b :d)

3:02 AimHere: So use 'val' instead of 'second'?

3:03 mange: It's pretty much the same thing, it just reads a bit more naturally, maybe.

3:07 danielcompton: mange: Thanks, that's better

3:08 Because you're mapping over a MapEntry, not a vector so val works too?

3:09 AimHere: I probably should go back and do some more Rosalind problems sometime!

3:09 bjeanes: am I crazy or is `lein ring server` suppressing stdout?

3:09 mange: danielcompton: Yeah, each of your seq elements is a MapEntry, so you can use key and val for readability.

3:11 Actually, key and val should be slightly more performant, too, but probably not by too significant an amount.

3:16 danielcompton: mange: because they're operating directly on the mapentry?

3:18 mange: Yeah. first/second call seq on their argument (if it's not already a seq), so that will have to do some work (allocation, in particular), whereas key/val just call .getKey/.getValue directly.

3:40 Glenjamin: you can also use an actual sorted map

3:40 ,(into (sorted-map) {1 :a 3 :b 2 :c})

3:40 clojurebot: {1 :a, 2 :c, 3 :b}

3:41 mange: He's using frequencies, so he can't control the map type.

3:54 DEA7TH: what is the typical way to do something with the numbers from 1 to 1000, use range (1 1001)? use some sort of a loop?

3:56 numberten: what sort of thing?

3:57 danielcompton: Glenjamin I thought about rewriting frequencies to use a sorted map, which would be faster?

3:57 numberten: DEA7TH: (range 1001) gives you the numbers

3:58 rather 1 1001

3:59 i think the typical way of using them varies on what you're using them for

3:59 mange: danielcompton: sorted maps don't support transient/persistent! at the moment, so that might end up being slower than frequencies and sorting.

4:00 danielcompton: What would be the best way to benchmark it? Criterium?

4:01 amalloy: danielcompton: a map sorted by its vals is, i believe, a priority queue

4:01 there are implementation of those hanging around in clojure somewhere, i'm fairly sure

4:01 mange: amalloy: he's looking to sort by key.

4:02 amalloy: oh, i see. isn't that just vals?

4:02 in a sorted map?

4:02 i see that's been covered too

4:04 numberten: is there an idiomatic way to pass around a configuration structure?

4:04 or rather to handle configuration

4:06 danielcompton: amalloy, I was wanting to get the values from frequencies sorted by key and I'm trying to work out which would be faster, re implementing frequencies to use a sorted map, or converting the map after.

4:06 dbasch: danielcompton: do you really need to optimize it?

4:06 danielcompton: dbasch not really,

4:07 dbasch I'm wanting to learn more about building performant clojure, so this seemed like a simple example

4:07 DEA7TH: numberten: I want to sum over some of the numbers from 1 to 1000

4:07 dbasch: danielcompton: you may look into the option of using a java TreeMap

4:07 DEA7TH: numberten: Project Euler, problem 1. I'm learning Clojure

4:08 (btw I know there's a better way to solve it)

4:08 dbasch: just for completeness

4:08 danielcompton: dbasch Now we're talking

4:08 Is criterium the best way to benchmark this?

4:09 numberten: DEA7TH: folds/reductions are the go-to higher order function for taking a structures of values and turning them into a single value (sum)

4:10 dbasch: danielcompton: I don’t know a better way than criterium

4:11 danielcompton: I did a similar comparison once when I was trying to build an inverted index. Persisten structures < transients < java hashmap in terms of performance

4:12 danielcompton: dbasch what was the order of performance between each? Order of magnitude each time?

4:12 dbasch: danielcompton: no, it was the same order of magnitude

4:12 using a hashmap was maybe twice as fast as a persistent map

4:13 but it was a very specific case, not sure I’d generalize from that

4:18 numberten: DEA7TH: I guess you could also use the fact that '+' takes an arbitrary number of arguments as well and just (apply + (range 1 1001))

4:19 but that doesn't abstract the problem really. and relies on implementation details in the function you're trying to apply to the collection

4:34 danielcompton: Here's my early results https://gist.github.com/danielcompton/4b1a59054a40a89c19ec

4:36 Glenjamin: mange / danielcompton / amalloy - clojure.data.avl seems to be a decent sorted-map implementation that supports transients and other neat stuff

4:37 and then depending on your use-case, you can use https://github.com/ztellman/immutable-int-map and then (reducers/fold) will give you multicore speedup

4:39 numberten: is there a built in function for this: (foo {:a 1 :b 2} {:a 0 :b 0 :c 0}) => {:a 1 :b 2 :c 0}

4:39 so update all values in map 2 from those given in map 1

4:39 Glenjamin: ,(doc merge-with)

4:39 clojurebot: "([f & maps]); Returns a map that consists of the rest of the maps conj-ed onto the first. If a key occurs in more than one map, the mapping(s) from the latter (left-to-right) will be combined with the mapping in the result by calling (f val-in-result val-in-latter)."

4:39 numberten: many thanks

4:40 Glenjamin: oh, in fact that's just (merge map-2 map-1)

4:41 numberten: even simpler

4:59 danielcompton: So using a custom sorted-frequencies implementation is slightly faster https://gist.github.com/danielcompton/4b1a59054a40a89c19ec#file-dna-frequencies-the-second

4:59 Now for the tree map

5:17 DEA7TH: How do I break this code into multiple lines: (reduce + (filter #(= 0 (* (mod % 3) (mod % 5))) (range 1000)))

5:17 I suppose that's too much for a single line?

5:19 danielcompton: DEA7TH you can use a threading macro -> and ->> to break this up and make it more readable

5:19 DEA7TH: more generally, is there a way to split function arguments into multiple lines

5:20 neena: DEA7TH: The function arguments can span multiple lines.

5:21 danielcompton: DEA7TH https://www.refheap.com/85517

5:22 DEA7TH: ->> reverses the order?

5:24 quizdr: What is the best clojure approach to connecting to a websockets? I see that both Jetty and http-kit can do this, but it would be an either-or choice, not the two in combination, right?

5:25 neena: DEA7TH: It inserts the result of the previous form in the last position of each form.

5:27 DEA7TH: Also, you might want to use zero? instead of (= 0 ...)

5:27 clgv: ,(macro-expand '(->> (range 100) (filter even?)))

5:27 clojurebot: #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: macro-expand in this context, compiling:(NO_SOURCE_PATH:0:0)>

5:27 clgv: ,(macroexpand '(->> (range 100) (filter even?)))

5:27 clojurebot: (filter even? (range 100))

5:27 clgv: DEA7TH: ^^

5:33 pepijndevos: I use gen-class to subclass a class with a main, how do I get that main to actually work?

5:33 $ lein run -m neo4j.server

5:33 Exception in thread "main" java.lang.Exception: Cannot find anything to run for: neo4j.server

5:42 DEA7TH: ehh, can I invoke a function which is declared in code below? it doesn't seem to work

5:43 emlyn: pepijndevos: have you added a (defn -main [...] ...)? Also you don't need gen-class for lein run

5:43 pepijndevos: emlyn, I did not, but I just want to call super's main

5:45 pbw: quizdr: that's something I'd like to take a look at. AFAIK http-kit doesn't do https. Is that true? It would mean that for a general solution you need some other server element in the mix.

5:45 emlyn: pepijndevos: not sure, but I think you'll have to add a -main and call that explicitly

5:45 pepijndevos: emlyn, how do I refer to the super's main?

5:46 emlyn: pepijndevos: not done that before but I expect (super/-main ...)

5:46 pepijndevos: I tried :exposes-methods {main super-main}

5:46 but I get Unable to resolve symbol: super-main in this context

5:51 emlyn: pepijndevos: I'm not sure, but if you can put a minimal example on refheap I can take a look

5:51 pepijndevos: this is my current file https://www.refheap.com/85518

5:51 quizdr: pbw ah that's good to know.

5:52 pepijndevos: emlyn, it requires org.neo4j.app/neo4j-server "2.1.0-M01"

5:56 What if I used a proxy and no gen-class. Just a main method that calls main on the proxy

6:00 emlyn: pepijndevos: sorry I'm a bit out of my depth, not sure what to suggest...

6:00 pepijndevos: hmmm, ok thanks for thinking along :)

6:04 I can't even figure out how to call the main of the proxy I made

6:05 proxy creates an instance already it seams

6:10 emlyn: pepijndevos: have you tried (proxy-super main) in the proxy?

6:11 pepijndevos: emlyn, I'm not even overriding main now

6:13 the problem is that I need to call a static method on an instance

6:13 clgv: pepijndevos: -main is a static method, there is no such thing as inheritance of static methods

6:13 pepijndevos: (. (Integer. 3) (parseInt "42", 10))

6:13 clgv: pepijndevos: you'll have to write your own main if you want to start that particular class

6:14 pepijndevos: what should that main look like?

6:15 clgv, I have 2 versions: https://www.refheap.com/85518 https://www.refheap.com/85520

6:17 clgv: pepijndevos: well you will have to replicate whatever the super class does in its main

6:17 pepijndevos: what?! why?

6:17 clgv: pepijndevos: since its a static method

6:18 pepijndevos: so?

6:18 clgv: pepijndevos: you want to run it with your derived class right?

6:18 pepijndevos: yes

6:18 clgv: so actually you are trying to extens dome features of that CommunityNeoServer?

6:18 *extend

6:19 pepijndevos: no, just providing a different config

6:19 http://components.neo4j.org/neo4j-server/milestone/apidocs/org/neo4j/server/CommunityBootstrapper.html

6:19 like this https://github.com/jexp/neo4j-in-memory-server/blob/master/src/main/java/org/neo4j/server/inmemory/InMemoryBootstrapper.java

6:19 clgv: pepijndevos: ok. so what exactly does that predefined main do and how would you use it in java?

6:20 forget the java. how would you use it?

6:20 danielcompton: Glenjamin mange amalloy Here's the results https://gist.github.com/danielcompton/4b1a59054a40a89c19ec the TreeMap was 4-5 times faster than a map, sorted-map or avl

6:20 pepijndevos: I don't know... it starts the server. I just want to do what it did... start the server, but instead use my method to create the server instance.

6:21 clgv: pepijndevos: (CommunityNeoServer/-main "my" "args" ...) will run that main

6:21 pepijndevos: if you cant specify the actual server class via configuration that will not work

6:22 pepijndevos: I don't get it... why can't I subclass the bootstrapper, overwrite a method and call the inherited main?

6:22 clgv: pepijndevos: because static methods are not inherited

6:23 they are just static. method of the class instead of methods of an object instance

6:23 pepijndevos: but it is listed here as an inherited method http://components.neo4j.org/neo4j-server/milestone/apidocs/org/neo4j/server/CommunityBootstrapper.html

6:23 clgv: but it is also listed as static

6:24 if they didnt change java 8 significantly there is no inheritance for static methods

6:25 pepijndevos: grmph....

6:26 ahaha, main actually calls start

6:26 http://grepcode.com/file/repo1.maven.org/maven2/org.neo4j.app/neo4j-server/1.7.2/org/neo4j/server/Bootstrapper.java#Bootstrapper.main%28java.lang.String[]%29

6:27 clgv: pepijndevos: he well, then you could have saved some time ;)

6:29 pepijndevos: aaaarg.... but my problem still exists

6:30 org.apache.commons.configuration.ConfigurationException: Cannot load a configuration from a directory

6:30 clgv: sounds like wrong parameter or something

6:31 pepijndevos: yea...

6:32 i'm just not 100% certain where it's getting its config from, so I created that subclass to explicitly give it a config.

6:32 but it's still looking in the wrong places it seems

6:36 anyway, thanks for the help

6:38 martinklepsch: when I start a very long running function from the repl is there a way to put that in the background (kind of like detaching it from the repl)?

6:45 Glenjamin: you can run it with (future)

6:47 clgv: martinklepsch: yes, future is the way to go

6:48 martinklepsch: so when I run (future (pmap ...)) on a remote repl and then disconnect it'll continue to run?

6:48 I also thought that future would work but I thought it might be bound the the repl session

6:50 Glenjamin: erm, you'll have no way to get the result value unless you (def) it i think

6:50 but it should probably keep running

6:51 not sure if GC would kick in

7:02 clgv: martinklepsch: as Glenjamin said you need to bind that future to a variable otherwise its result will be lost

7:45 martinklepsch: Glenjamin, clgv, if I bind that to a var and then end the repl session, wont that var be lost?

7:48 clgv: martinklepsch: no, if the REPL process is not shotdown that will work

7:49 "shot down" :P

7:51 martinklepsch: clgv, ok so if I start the remote repl using tools.nrepl.server I should be good to go I gues

7:51 that's cool then. thanks!

7:51 clgv: it is also pretty easy to try ;)

8:06 Glenjamin: lein repl :headless

8:06 lein repl :connect

8:06 if you disconnect but leave the headless one running, you can acheive what you describe

8:09 clgv: Glenjamin: I think he is going to embed an nrepl in his application

8:10 mskoud: running a Clojure server this this project alias :aliases {"up" ["pdo" "cljsbuild" "auto" "dev," "ring" "server-headless"]}. But print does not show up on the console. Or rather, there are no repl, so no output. How can i start this with a repl?

8:14 phillord: Is there anyway to have Clojure generate a static data member -- I need a single, unchanging value which I can access as fast as possible -- In java, I'd use a static final public. Not sure how to replicate this in Clojure

8:15 opqdonut: (def +constant+ 17)

8:15 now that :dynamic is no longer the default for vars, vars like that are pretty fast

8:16 Bronsa: you can use (def ^:const my-constant 23)

8:16 this way it will get inlined

8:16 opqdonut: oh right, there's that too

8:16 and a type hint is probably apropos if the value is an object

8:17 phillord: I'm finding about a 4x difference between accessing a static final in java and accessing a var

8:18 opqdonut: did you try :const?

8:18 phillord: working on that

8:18 benchmarks take a while:-)

8:19 opqdonut: and if you're doing something _with_ the value, type hints will help. a java field is typed so there's no reflection going on as opposed to the value of a var

8:19 phillord: ok, will test both of these

8:20 opqdonut: are you using *warn-on-reflection* btw?

8:20 if you're optimizing clojure code it's the first thing to do

8:26 phillord: curiously, :const causes an AbstractMethodError -- rather unexpected

8:26 clgv: phillord: ^:const is the way to go here ^^

8:31 phillord: ah, okay, so worked out the abstract method error -- not quite sure how ^:const is working, but it calls "count" on the object and I haven't implemented it, hence the abstract method error.

8:32 which is a bit worrying because I wonder what it is going to inline -- well I guess I need to read the compiler code to find out

8:36 justin_smith: phillord: :const only works for primitive types

8:37 not objects

8:39 phillord: really?

8:40 I'm struggling to find the documentation for :const

8:52 clgv: phillord: http://clojure-doc.org/articles/language/namespaces.html#constant-vars

8:52 not much there though

8:58 phillord: no, that doesn't describe anything at all! Well, if all else fails, write some code and decompile it!

9:02 clgv: phillord: usually you get a "can not embed in code" exception when you specify :const for the wrong value

9:03 * phillord nods

9:04 phillord: I am guessing it works with lists and such like

9:05 yep -- so lists get inlined to a specific implementation

9:05 public final class core$const_string_list extends AFunction

9:05 {

9:05 public static final AFn const__0;


9:05 static {

9:05 const__0 = (AFn)RT.vector(new Object[] { "const-list-elem" });

9:05 }


9:05 public Object invoke() {

9:05 return core$const_string_list.const__0;

9:05 }

9:05 }

9:06 okay, well, now I know how it works anyway! Not what I need, unfortunately

9:09 Bronsa: phillord: next time use a pastebin please

9:10 * phillord nods

9:10 phillord: realised that after I had done it

9:10 beamso: has anyone done the basic om tutorial lately?

9:11 when rendering the first list, i was expecting a ul with 4 li childen. i'm getting a ul with the single child

9:11 clgv: phillord: it works for clojure values that have literal representations I guess

9:12 phillord: yep, but it doesn't preserve type, it would appear -- it's using a vector above, but in clojure it's a list

9:12 Bronsa: phillord: I'm curious btw, what decompiler did you use?

9:12 phillord: procyon

9:12 https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler

9:13 I've run it over clojure.core and my own library (tawny.owl) and it does both just fine. I haven't found anyother which doesn't crash

9:13 I should write a lein plugin at some point, come to think of it

9:14 Bronsa: phillord: hmm, really? we were just talking about it a few weeks ago, clojure produces some bytecode that's not possible to translate to java

9:15 I guess I'll try and see how it deals with that

9:15 phillord: Oh, it's possible to translate into Java just fine

9:15 it just wont run correctly

9:16 it's not the bytecodes anyway -- Clojure pushes locals onto the stack, then deletes the locals, then pops their values of the stack

9:17 there's no way to access the stack in Java, which is why it doesn't work. But if you just want to read the Java, rather than the javap byte code translator, it's fine.

9:19 clgv: phillord: you can use luyten as procyon frontend

9:19 though the latest and best has no release last time I checked

9:20 phillord: more interested in just producing a dump of Java files, to be honest -- it's what I normally do

9:59 quizdr: is it possible to provide a defaults map for nested map destructuring? For example, I get nil for this: (let [{{g :a h :b} :hhh :or {g 666 h 777}} m] [h]) -- assume map "m" does not have a key :hhh

10:02 justin_smith: ,(let [{{g :a h :b :or {g 666 h 777}} :hhh } {}] [h]) quizdr

10:02 clojurebot: [777]

10:02 justin_smith: you just need to put the :or in the right place

10:02 quizdr: ah, the :or goes on the same "level" as the variable you are defining

10:02 justin_smith: the binding of :h parallel to :hhh is not the same as the one inside it

10:03 because having both keys present would be valid, and you need to be able to bind either

10:03 quizdr: right, got it

10:03 (inc justin_smith)

10:03 lazybot: ⇒ 43

10:03 justin_smith: also, pedantry, it's not a "variable" :) it's a binding

10:03 quizdr: i knew that as I was typing it, but couldn't remember the proper term.

10:03 was hoping no one would notice, but I should know better than to expect that in this room :)

10:04 justin_smith: np, like I said, it's a pedantic point, but the more we use the right terms, the less often people try to do things like use def to update values inside a let :)

10:04 quizdr: now, to be fair, I've seen many cases of top level lets having defn or def, so that many functions could share the same closure.

10:04 what do you think?

10:05 (let [...] (defn ...) (defn ...) etc...)

10:05 justin_smith: quizdr: that's usually a sign someone has scheme experience

10:06 clojure's community tends to be fairly anti-information-hiding

10:06 quizdr: it's quite nifty, also helpful to put defn inside a macro to create many named functions based on certain runtime details

10:06 justin_smith: it's possible, and in those cases you are actually messing with variables

10:07 the distinction I was trying to make was bindings vs. vars

10:07 trap_exit: what is the down side of using _keyword arguments_ for all functions?

10:07 justin_smith: trap_exit: they don't compose as well as opts maps do

10:07 trap_exit: i.e. instead of (defn foo [cat dog blah] ... ) we do (defn foo [{:keys cat dog blah}] ... ) ?

10:07 quizdr: justin_smith understand

10:07 trap_exit: justin_smith: can you explain in more detail?

10:07 justin_smith: how do they not compose ?

10:08 justin_smith: oh, that is an opts map

10:08 trap_exit: oh sorry

10:08 I am confusing terms.

10:08 justin_smith: I thought you meant the [& {:keys [...]}] thing

10:08 trap_exit: What is the downside of using opts maps for everything?

10:09 quizdr: trap_exit are you asking the downside versus say variable arity to define "optional" parameters?

10:09 justin_smith: trap_exit: some extra gc churn, and less clarity about missing args at runtime (nils instead of wrong arg count error)

10:09 also you end up with a bunch of calls to merge replacing partial

10:10 I think it's a little uglier too

10:10 also, it prevents the arg-count polymorphism that clojure would do for you otherwise

10:11 pbw: If I have a function that produces an infinite lazy seq from an integer argument - (repeat n) for example, and a vector of integers, say (def ints [1 2 3]), how can I create a corresponding vector of references to the lazy seqs?

10:11 quizdr: justin_smith do you generally advocate multiple aririty instead unless a specific reason exists?

10:11 trap_exit: quizdr, justin_smith: no, not about optinal arguments

10:11 I mean for all arguments, I don't want to do [arg1-name arg2-name arg3-name] ...

10:11 and instead do {:arg1-name ... :arg2-name ... .:arg3-name ... }

10:11 justin_smith: trap_exit: understood - just saying that this eliminates the helpfulness of multiple arity overloading

10:11 trap_exit: basically to force myself to remember the names of arguments instead of the order

10:12 justin_smith: hmm, I've actually never used that feature

10:12 justin_smith: but now that you mention it, I suddenly find it useful

10:12 i.e. a helper "iterative" version of a function togerhe with the real function

10:12 i.e. (reverse lst) (reverse lst iter-results) ... rather than reverse + reverse-helper

10:12 cemerick : !

10:12 justin_smith: it is often used for the (recur) using impl, or for optional arguments

10:13 quizdr: trap_exit no need to remember the name or order of args if your code editor shows you the format of the function arguments as you right them (i.e. emacs typically does)

10:13 trap_exit: quizdr: true

10:14 justin_smith: quizdr: now if emacs showed you the arg destructuring, it would make an args map at least as convenient I guess

10:15 though you probably do not want to be using args maps inside tight loops

10:16 peterdon`: ,(#(case % 1 true false) 1) ; is it possible to prevent magic numbers in a case form?

10:16 clojurebot: true

10:16 peterdon`: I would like to write something like (#(case % any-constant-symbol-with-value-1 true false) 1)

10:17 quizdr: justin_smith yes, hence why one would not have that advantage over the other

10:22 justin_smith: peterdon`: if it was :const I could imagine that being possible - dunno if it is currently supported though

10:23 peterdon`: I tried this: (def ^:const any-constant-symbol-with-value-1 1)

10:23 ..doesn't work'

10:24 justin_smith: ,(do (def ^:const x 44) (case 44 x true false))

10:24 clojurebot: false

10:24 justin_smith: peterdon`: I think the trick is that at the time that case is compiled the value must be bound

10:26 peterdon`: justin_smith: it looks like there are no real constants in Clojure

10:27 justin_smith: peterdon`: no, not quite I don't think - I just tried my above without the ^:const and it still worked - it's just that the value has to be resolvable at compile time I think

10:27 peterdon`: justin_smith: I would assume that the result is true

10:28 justin_smith: oh crap, there's that too :)

10:28 ,(do (def ^:const x 44) (case 'x x true false))

10:28 clojurebot: true

10:29 justin_smith: haha, it is just matching on the symbol x

10:29 don't mind me...

10:29 cbp: is const actually documented anywhere

10:30 it's not in here http://clojure.org/special_forms#def

10:32 phillord: I looked for :const documentation earlier -- couldn't find it

10:35 justin_smith: phillord: consider that (defmacro +my-magic-number+ [] 42) causes calls to (+my-magic-number+) to be resolved at compile time

10:36 it's a hack, but it does do the right thing (except I think case needs resolution at read time, which is hard / weird)

10:38 peterdon`: so I should probably use cond instead of case

10:39 clgv: peterdon`: case needs compile time constants. symbols are not resolved

10:40 agarman: ,(do (def ^:const x 44) (case x 44 true false))

10:40 clojurebot: true

10:40 agarman: nvm me

10:42 cbp: ah so :const removes the call to getRawRoot

10:42 agarman: yes

10:43 cbp: ,(do (def ^:const x 1) (defn foo [] (inc x)) (print (foo)) (def x 2) (print (foo) x))

10:43 clojurebot: 22 2

10:45 justin_smith: ,(do (def ^:const x 1) (defn foo [] (inc x)) (println (foo)) (def x 2) (println (foo) x)) slightly clearer imho

10:45 clojurebot: 2\n2 2\n

10:46 justin_smith: cbp: so what happens there is the new def replaces the old one for new resolution, but foo still sees the old x

10:47 correct?

10:47 cbp: yes

10:50 martinkl_: is there some convention in naming lazy/non-lazy things?

10:51 waynr: martinkl_: don't know off top of my head but you might find an answer here https://github.com/bbatsov/clojure-style-guide

11:01 stuartsierra: martinkl_: In Clojure itself, there is no convertion, but in general anything that *can* be lazy *is* lazy.

11:07 phillord: there is an anti convention -- anything with "do" is not lazy:-)

11:13 So, consider this code -- http://pastebin.com/1Zmf8iSH -- In my hands, the former is 4x faster than the later

11:14 Now, I could achieve parity here by creating a dump piece of Java code with a static final data member and I'd be away

11:15 but I don't *think* I can do this in Clojure

11:17 clgv: phillord: well call of a static property versus a variable deref. try (let [o System/out] (bench o)) ;)

11:18 justin_smith: the solution: define everything inside a giant let block!

11:18 phillord: exactly, that would work well

11:19 justin_smith: of course this would cause annoyance if you wanted to change bindings at runtime - but then they shouldn't be const, should they

11:19 clgv: phillord: is system/out really a proper example for the kind of constants you want?

11:20 cbp: println is too slow for us!

11:20 phillord: example no, it's just a handy static final constant in Java

11:21 I presume that it gets inlined at JIT so returning System/out is about as fast as it gets

11:22 exemplar in the sense that yes it's something without a necessary read syntax -- I can't just inline at compile time

11:22 and :const doesn't work for that reason and for another

11:23 it's not that important -- after all, what's a few nanoseconds between friends...

11:26 clgv: phillord: I mostly needed constants for numbers and such which worked well with ^:const

11:35 phillord: In my case, I need it for an empty data structure -- and I am at a disadvantage, because clojure.core cheats:-)

11:36 ah well, I will worry about it tomorrow!

11:41 xcthulhu: Hey! I was wondering if anyone has had any experience with using trapperkeeper and compojure, and could give me some advice about which to use?

11:44 vilmibm: xcthulhu: they work together.

11:44 if that's what you want.

11:44 xcthulhu: Oh, sweet

11:45 I’ll just use compojure then until my app gets complicated enough to need trapperkeeper

11:45 vilmibm: you can make a compojure app and then use (add-ring-handler) to register it :)

11:45 sure. on its own trapperkeeper is just the service framework + some high level services

11:46 you definitely want something like compojure to actually create your routes, and then use add-ring-handler to hang them off a context path (which might just be "/")

12:03 {blake}: OK, I have a collection of (a (b c) (c b)) (b (a c) (c a)), etc., and I want to turn this into ((a b c)(a c b)(b a c)(b c a)...(etc). I know there's an easy way to do this but I've forgotten what it is.

12:04 ssideris: you mean flatten?

12:04 justin_smith: definitely not flatten

12:04 {blake}: No. Take the first element and concat it with the nested collections.

12:05 I thought there was an easy way to do it. I mean, like, a built-in function.

12:05 Or a slight variant on a built-in. But i guess that describes nearly everything in Clojure.

12:06 justin_smith: ,(for [[prefix & suffixes] '((a (b c) (c b)) (b (a c) (c a))) suffix suffixes] (conj suffix prefix))

12:06 clojurebot: ((a b c) (a c b) (b a c) (b c a))

12:07 ssideris: oh ok

12:07 {blake}: justin_smith: I was trying to avoid "for". =P

12:08 justin_smith: {blake}: maybe there is something awesome in a lib like flatland/usefull

12:08 {blake}: (I'm doing a permutations thing and "haven't learned" for yet. So if I can use "for" my solution doesn't make sense.)

12:08 justin_smith: but if you don't find it, there is that

12:09 a for can be translated into nested maps

12:09 hiredman: mapcats

12:09 justin_smith: oh, yeah, right :)

12:09 {blake}: justin_smith: Ah!!! Yeah...that's what I gotta grasp.

12:10 mapcat...

12:10 Two collections? First and rest?

12:11 justin_smith: (mapcat (fn [[p & s]] (map #(conj % p) s)) '((a (b c) (c b)) (b (a c) (c a)))) the translation

12:11 ,(mapcat (fn [[p & s]] (map #(conj % p) s)) '((a (b c) (c b)) (b (a c) (c a)))) oops

12:11 clojurebot: ((a b c) (a c b) (b a c) (b c a))

12:13 CookedGryphon: So I just upgraded to the latest core.async, and I've found a *load* of places where I hadn't actually imported <!.... but it was working anyway without any errors or issues at runtime

12:13 what's that about?

12:13 (and the newest core.async correctly reports them as errors where it didn't before)

12:13 justin_smith: CookedGryphon: maybe because of the way the go macro expands what is inside it?

12:13 it does some complex stuff

12:14 CookedGryphon: must be, but I'm sure I saw some errors where I hadn't imported it before...

12:14 {blake}: Thanks, guys!

12:15 ghadishayban: CookedGryphon: latest core.async relies on a different analyzer and gives better error reporting in general (line numbers, etc)

12:16 CookedGryphon: yeah, i get that, but what was going on before to make it work at all, and why wasn't it causing any other issues

12:17 ghadishayban: lots of magic

12:18 we used to treat <! >! exceptionally

12:19 dnolen_: i have basic feature expressions working on CLJ side with a *read-suppress* thing for unreadable forms.

12:19 dnolen_: working on updating r0man's cljs patch to do the same

12:20 dnolen_: ghadishayban: cool!

12:20 CookedGryphon: ghadishayban: fair enough, it's nice to have decent error messages back. Turns out I wasn't recuring from a tail position in about 80% of cases...

12:21 ssideris: wow, does that mean that features are coming soon?

12:22 although cljx is much better than it used to be

12:23 ghadishayban: ssideris: i'll be put it in JIRA and the rest is up to the process

12:24 CookedGryphon: is this going to be a cljs only thing? Or more general. For example I am currently using cljx to compile alternative function versions for jvm java vs android vs clojurescript

12:24 ghadishayban: seems like discussion about approaches hasn't been terribly active lately, so I'll take the path of least resistance

12:25 integrated into the reader (both CLJ + CLJS, maybe tools.reader), basically duplicating Common Lisp feature exprs

12:26 CookedGryphon: sounds good, will the features be pre-defined, or arbitrary? If so, how do you select which features to include

12:26 ghadishayban: patch looks like #+clojure :foo #+clojurescript :foojs

12:26 environment will bind a set

12:27 CookedGryphon: sounds perfect, and like it would be a drop in replacement for cljx more or less (if you're not using the function transformation feature)

12:28 ghadishayban: r0man did all the heavy lifting, just added handling of forms like #+clojurescript #js {:what :ever} not bombing when read in an env not supporting the tagged literals

12:38 CookedGryphon: is there a way to do global dependency excludes?

12:39 i.e. almost all my libraries depend on some version of clojure or other, but clojure-android depends on clojure-jb instead

12:39 how do i stop the other things bringing in their own version without putting an exclude on each of them

12:42 never mind, found it, just :exclusions at the top level

12:44 ampharmex: <ampharmex> here is a challenge I devised: given 7 9 8 7 6 5 4 3 2 5 6 7 3 4 2 4 5 8 7 = 476 Goal: find out what mathematical operators (minus, multiply, divide, add) satisfy that solution (476)

12:44 <ampharmex> Order of operation is variable.

12:44 <ampharmex> 4^18 * 18! is a non optimal approach.

12:44 <ampharmex> Some example output:

12:44 <ampharmex> (7 + (9 + (8 + (7 + (6 + (5 + (4 + (3 + (2 + (5 + (6 + (7 + (3 - (4 + (2 * (4 * (5 - (8 * 7)))))))))))))))))) = 476

12:44 <ampharmex> A dynamic programming approach may suffice.

12:44 <ampharmex> e.g dp[i][j][k] = Can I make the number k using the numbers a[i ... j].

12:45 technomancy: ampharmex: use a for comprehension to express every possible combination plus a :when clause for what it needs to evaluate to, then just take the first element of that seq

12:46 ampharmex: technomancy, If I want to make X with the numbers A[i ... j], then I find a position v such that A[i ... v - 1] can make Y, A[v ... j] can make Y', and either Y + Y', Y * Y', Y - Y', or Y / Y' is equal to X.

12:46 ihodes: technomancy: hmm, that's pretty complex… just with + - / * you get a quarter of a trillion things to try, no?

12:47 with that particular sequence

12:47 technomancy: ihodes: I was thinking of how to do it in a one-liner =)

12:48 ampharmex: That is how you compute A[i][j][X].

12:48 technomancy: maybe mapreduce it over a cluster if you need an answer promptly, you know

12:48 ampharmex: If you want to find some sequence that does, then in A[i][j][X] you store the position at which you split (v) and the operator you chose.

12:49 _Every_ expression that you can form using the numbers in A[i ... j] is of the form (Y) op (Y'), where Y is an expression obtained from A[i ... v - 1], Y' is an expression obtained from A[v ... j], and op is either +, -, *, or /.

12:49 If I'm trying to find several, I'll store the several v, but that (since the number of answers is already exponential) will be exponential in space and time. :)

12:53 eraserhd: Is there a persistent vector-like collection that has a decent `splice`? e.g. insert-element(s) / remove-element(s)

12:54 "decent" meaning sub-linear.

12:55 BobSchack: eraserhd I think this is what you want https://github.com/clojure/core.rrb-vector

12:56 justin_smith: eraserhd: some kind of persistent redblack tree?

12:56 BobSchack: jynx, and you actually had the sauce

12:56 (inc BobSchack)

12:56 lazybot: ⇒ 1

12:56 BobSchack: wooo!

12:56 eraserhd: BobSchack, justin_smith: Thanks!

12:57 ampharmex: technomancy, a 1 liner? :o

13:03 technomancy: ampharmex: (first (for [ops (permutations [+ - * /] (count numbers)) :when (= x (reduce (fn [v [n o]] (o v n)) 0 (map vector numbers ops)))] ops))

13:03 ampharmex: technomancy, does it work?

13:03 technomancy: no

13:04 but something a lot like it probably would

13:04 you have to get permutations from a contrib lib or something; dunno if that's cheating

13:04 bjeanes: wrote first clojure in like 8 months

13:04 man i miss it

13:05 technomancy: bjeanes: oh, what'd you write?

13:05 bjeanes: a half-functional OAuth1 workflow for Friend

13:06 because Trello does OAuth1 (but very very very badly)

13:06 technomancy: cool

13:06 bjeanes: it's half-functional because Trello doesn't look at or even care if you signed your messages

13:06 because... computers.

13:07 ampharmex: technomancy, is it a dynamic programming solution?

13:08 technomancy, have you tested it?

13:08 technomancy: ampharmex: not sure what the strict definition is. it just defines the search space using a lazy seq and picks the first matching element.

13:08 I haven't tested it or seen whether it even compiles

13:09 ampharmex: technomancy, dp[i][j][k] = Can I make the number k using the numbers a[i ... j].

13:09 technomancy, The code is the usual dynamic programming solution, with a range of [-500, 1000]

13:28 Glenjamin: bjeanes: that sounds crazy, did you report it to them?

13:29 bjeanes: i tweeted at them last night

13:29 but i found this out at like 1am

13:29 so i went to bed roughly exactly after that in case I was insane

13:29 Glenjamin: heh

13:30 bjeanes: really their API is *not* OAuth... they just use part of OAuth1 to send you a token back

13:30 Glenjamin: i've done oauth1 via clj-oauth, but not with friend

13:30 bjeanes: then you just use your app key and their raw token in the query string

13:30 Glenjamin: ah

13:30 bjeanes: and boom authenticated

13:30 Glenjamin: yeah I am using clj-oauth internally

13:32 I never needed to use https://github.com/mattrepl/clj-oauth/blob/master/src/oauth/client.clj#L77 to authenticate against Trello

13:32 #lol

13:37 technomancy: "OAuth-inspired API product"

13:40 TimMc: "Inspired by a true API"

13:40 "Made with real OAuth"

13:41 stompyj: “Now with extra OAuth"

13:41 bjeanes: hah

13:41 their api has made more than a few questionable decisions

13:41 technomancy: I was thinking along the lines of "cheese-inspired food product"

13:41 bjeanes: well... the api didn't make the decisions

13:42 technomancy: now I really want a grilled cheese sandwich. thanks.

13:42 TimMc: cheese-food-product

13:42 Glenjamin: bjeanes: as i understand it, the web ui only interacts via the api

13:43 and they keep back-compat

13:44 TimMc: I can't believe I used to eat Kraft singles.

13:44 bjeanes: I believe that is the case. Web UI powered by API is a good way to dog food I guess

13:44 it also means that their API allows auth with sessions

13:44 which *is* questionable

13:44 TimMc: (Note the entire lack of the word "cheese" in the branding.)

13:45 justin_smith: TimMc: "cheese food product"

13:46 kind of like how php is a "language interpreter program" - just calling it a language would be giving it too much credit

13:47 bjeanes: aren't all interpreters language interpreter programs?

13:47 gtrak: java is a DSL for turning XML into stacktraces.

13:48 justin_smith: bjeanes: well there are defined languages as such, I guess how defined they are can be a little fuzzy

13:49 arrdem: gtrak: haha

13:50 justin_smith: bjeanes: the interpreter for php is basically a bunch of imperative steps that run as they read tokens from the file, there is no parser or grammar or whatever (theoretically there is one, but it is complected with the execution)

13:50 bjeanes: anywya, I was mostly just making a joke

13:50 bjeanes: heh

14:10 bridgethillyer: I have a question from the book Clojure Programming. In Chapter 3 on Collections, there is this note:

14:11 “NOTE: Your own functions will get this behavior for free if you are building them on top of others’ sequence functions. If you use lazy-seq then it is your responsibility to call seq on your arguments to maintain this convenient characteristic of seq.”

14:12 I think I’m having a reading comprehension problem

14:12 Does this mean I have to call seq on things I’m passing to lazy-seq?

14:13 Jaood: bridgethillyer: it means some functions calls seq on their arguments

14:14 bridgethillyer: and return a lazy-seq for you

14:14 technomancy: needing to call lazy-seq directly is *extremely* rare

14:14 I'm surprised it's mentioned that early in the book

14:15 bridgethillyer: Well, it’s a “Note,” so it’s not central to the point there

14:15 Jaood: bridgethillyer: take a HoF like map for example, it will call seq on the automatically for you

14:16 *on the collection

14:16 llasram: bridgethillyer: What's the "this behavior" the note refers to?

14:16 Jaood: that's what you get for free I guess

14:17 bridgethillyer: jaood: That makes sense. I can see in the map implementation where it calls seq on the coll argument

14:19 llasram: The behavior is basically what jaood just described - some functions call seq on their arguments, so that, for example, you can use a String with map

14:19 ambrosebs: Bronsa: how do I get the line/col number of the left hand side of a :let binding?

14:21 Bronsa: ambrosebs: you mean line/col of (let [>this< init] ..) ?

14:21 ambrosebs: yes

14:21 a :binding rather

14:21 Bronsa: uhm it should be in :env as always

14:22 arrdem: yeah if it exists should be in env... doesn't look like :binding has an associated meta.

14:22 ambrosebs: ok, seems like a :binding inherits the same coordinates as the :let

14:22 arrdem: Bronsa: silly patches incoming, I noticed some English typos in reading t.a

14:23 ambrosebs: yep, that's the intended behavior

14:23 bridgethillyer: I’m still confused about what the Note is telling me to do when I call lazy-seq (which I would rarely do - thanks technomancy)

14:23 Bronsa: arrdem: ouch

14:24 ambrosebs: you mean it has the same line/column info of the outer let expression? that shouldn't be the case

14:24 arrdem: Bronsa: shrug. it's like two typos. no big deal.

14:24 ambrosebs: Bronsa: ok, I'll play a little more.

14:25 amalloy: bridgethillyer: what behavior is the book saying you'll get for free? it's hard to answer otherwise

14:25 Bronsa: ambrosebs: I'm assuming the form is read by tools.reader btw, no idea what happens with line/column info when read from the repl

14:25 arrdem: Bronsa: do you have a favorite way to play with t.a trees? I'm using folding and a 10kline clojure mode buffer atm and while it works it's a bit of a mess.

14:26 bridgethillyer: The behavior it refers to (if I’m reading it correctly) is that some functions call seq on their arguments, so that, for example, you can use a String with map

14:26 Bronsa: arrdem: I've got `:injections [(set! *print-level* 10) (set! *print-length* 10)]` in my profiles.clj.

14:26 amalloy: i think you can completely ignore that note. you'd have to try very hard to *not* do what it seems to be suggesting

14:27 Bronsa: arrdem: then I just (-> ast :node :inner-node whatever ..) to explore it

14:27 bridgethillyer: amalloy: Ok, thanks. That’s my gut read of it. I just thought there might be something I was missing.

14:28 amalloy: you can always ask cemerick. clojure programming is his, right?

14:29 bridgethillyer: Good point. Ask for some book support.

14:29 ambrosebs: Bronsa: ah no not using tools.reader here.

14:29 cemerick: bridgethillyer: feel free to shoot me an email

14:30 arrdem: Bronsa: setting print bounds is a good idea... I wound up hacking the print-method of atoms so that I can actually pprint the entire tree without killing Cider

14:30 bridgethillyer: cemerick: will do

14:30 cemerick: bridgethillyer: hi, BTW :-)

14:30 bridgethillyer: cemerick: hi back at you

14:32 Bronsa: arrdem: yeah, I remembered about print-level/length only after killing slime/emacs one too many times

14:34 ambrosebs: that's probably it. the source-info pass just tries to find line/column info on the :form's meta or defaults to the outer node info

14:34 ambrosebs: Bronsa: I was trying to avoid creating a file to test this stuff out of laziness.

14:36 Bronsa: ,(-> '(let [a 1]) second first meta)

14:36 clojurebot: nil

14:36 ambrosebs: Bronsa: works perfectly with t.reader

14:36 thans

14:36 thanks

14:38 I'm spitting out a map of file coordinates to types.

14:38 works great

14:38 Bronsa: ambrosebs: you can use (comp t.r/read-string t.r.rt/indexing-push-back-reader print-str) if you don't want to use a fileI guess

14:38 ambrosebs: Bronsa: sweet, hoping you had a snippet.

14:40 sdegutis: Is there an alternative to doing (#'my-function) in order for changes made while my server is running to take effect without restarting it?

14:41 amalloy: Bronsa: i've never had to use print-level/print-depth in slime: C-c C-c generally succeeds in aborting an overlarge print, i think

14:41 sdegutis: I'm storing the functions in a map and storing the map in a var using alter-var-root. This is the root of all my problems.

14:42 Bronsa: amalloy: belive me, I panic C-c C-c'ed like a mad man when it happened

14:42 amalloy: hahaha

14:43 ambrosebs: Bronsa: gives me UnsupportedOperationException count not supported on this type: IndexingPushbackReader clojure.lang.RT.countFrom (RT.java:556)

14:43 Bronsa: amalloy: the only thing that worked was killing the jvm, waiting for slime to print all of it and then M-x slime-repl-clear-buffer

14:43 ambrosebs: well I didn't try it :) one sec

14:44 ambrosebs: Bronsa: oh should be tr/read ?

14:44 Bronsa: ... yeah sorry

14:44 srruby: How do I sort a vector of vectors of numbers: [ [ 3 2 1] [ 3 0 2] [3 1 2] ---> [ [ 3 0 2] [ 3 1 2] [ 3 2 1]] ?

14:45 Bronsa: user=> (-> ((comp t.r/read t.r.rt/indexing-push-back-reader print-str) '(let [a 1])) second first meta)

14:45 {:end-column 9, :end-line 1, :column 7, :line 1}

14:45 ambrosebs: yep ^

14:45 ambrosebs: Bronsa: I tried core/read which confused me further :)

14:45 nice!

14:46 dbasch: srruby: do you want to sort them as if they represented decimal numbers?

14:47 srruby: dbash: No. I want a multi-level sort. First level by first item, etc

14:47 dbasch: srruby: so essentially yes :)

14:47 srruby: dbasch: OK. :)

14:48 dbasch: srruby: one easy way: create a function to-decimal like this

14:48 amalloy: aren't vectors comparable to each other? you should just be able to call sort

14:48 llasram: Yeah

14:48 ,(sort [ [ 3 2 1] [ 3 0 2] [3 1 2]])

14:48 clojurebot: ([3 0 2] [3 1 2] [3 2 1])

14:49 llasram: Not sure what the problem is?

14:49 amalloy: it won't work if you have lists instead, or if your vectors aren't all the same length

14:49 llasram: There is some (IMHO) weirdness that they sort by length first

14:49 srruby: Thanks all!

14:49 sdegutis: Is this going to be a negative performance hit?

14:49 Or in some other way will it be very dangerous?

14:50 dbasch: srruby: yeah, if they are all the same length you’re set

14:50 sdegutis: I am doing this: {:delete #'my-delete, :create #'my-create, :read #'my-read} and then later I do ((:create my-map) arg1 arg2).

14:51 This way when I reload the web server, it sees my changes.

14:51 srruby: dbasch: What threw me is that I tried (sort > [ [ 3 2 1] [ 3 0 2] [3 1 2]]) and I got an error

14:51 dbasch: they are not numbers

14:52 srruby: let sort use compare instead of providing a function

14:52 amalloy: right, if you wanted to sort them in backwards order (ie, the order > would use), you can use (comp - compare)

14:52 since compare is the default comparator, and if you negate it you get the opposite ordering

14:53 sdegutis: I want to stop storing them in a map, but they represent a third party service (i.e. Stripe).

14:53 You see? I want to hot-swap them out at init-time and test-time. That's the reason they're grouped together in a var.

14:54 Changing this to an object with real methods will not make any difference: this object is stored in the var instead.

14:55 arrdem: Bronsa: this is guaranteed to be the reach set of vars by definition of the :children vector, right? (->> (ast < forms >) (ast/nodes) (map :var) (filter identity) (into #{}))

14:57 Bronsa: arrdem: yeah. btw (map :var) (filter identity) is (keep :var)

14:57 Jaood: mnb.m,.,mn.

14:58 arrdem: Bronsa: noted. thanks!

14:58 TimMc: Jaood: Cleaning your keyboard?

14:59 arrdem: Bronsa: for generality would you write that as an analyzer pass that creates var reach set metadata on each node recursively upwards?

14:59 'cause then it fits with the rest of your passes rather than being some "run at root" weirdness.

15:03 Bronsa: arrdem: meh. either the ast/nodes approach or using a postwalk works just as fine if all you need is the reach set of the analyzed form

15:03 Jaood: TimMc: ;) - was lagging and mistakenly pressed enter and hitting random keys

15:04 s/and/after/

15:04 arrdem: Bronsa: kk. probably gonna do it anyway just to use update-children for the first time.

15:04 Bronsa: arrdem: I don't think you need update-children for this

15:06 arrdem: honestly I'd go with the snippet you just pasted, it's going to be shorter than the approach using postwalk/update-children

15:08 sdegutis: What are some alternatives?

15:27 nbeloglazov: technomancy: ping, seems like I did break quil repo on clojars

15:47 dgleeson: anyone in here using cursive? I'm curious if there is an easy way to reload the repl with changes made to the clj files?

15:51 zeeshanlakhani: dgleeson: Tools > REPL > Load file in REPL. and yeah. bind to key for

15:51 great justice

15:52 Shayanjm: Hi all, completely new to Clojure and trying to dive right in. Wanted to install leiningen via Brew -- am I right in assuming that 2.3.4 is the latest release?

15:53 scottj: Shayanjm: yes, note top of this file https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein

15:54 Shayanjm: good call, thanks

15:54 sdegutis: Why was it that the solution to my Clojure problem came from #clojure-social and not #clojure? :P

15:55 gtrak: the offtopic has become on-topic.

15:55 we should tell people off-topic if they start talking about clojure too hard.

15:56 AimHere: Or we could just rename this channel #clojure-antisocial and start being nasty to people

15:57 arrdem: for K people and 2 channels what is the optimal distribution of conversations so as to ensure the highest content rate on both channels?

15:59 dgleeson: zeeshanlakhani: weird, that's grayed out for me

16:00 does that mean I don't have something set up correctly?

16:00 oh it's because I didn't have focus on the file correctly

16:00 DOH

16:00 cool!!

16:03 zeeshanlakhani: dgleeson: yay!

16:03 technomancy: nbeloglazov: what's up?

16:04 nm; I see the issue

16:11 sdegutis: arrdem: that kinda knowledge gets jobs

16:23 sandbags: Can anyone sign into refheap.com? I'm getting an uncaught ReferenceError in the JS ... is refheap still a thing?

16:23 arrdem: Raynes: ^

16:24 sdegutis: I just use gists

16:24 arrdem: sdegutis is also a terrible person

16:24 sandbags: sdegutis: yeah i could use a gist but i thought it being clojure an all

16:24 arrdem: sandbags: just don't use pastebin and nobody will care

16:25 technomancy: wow, paste.lisp.org is still a thing

16:25 it supports haskell but not clojure ._.

16:25 sandbags: well i'm tweeting this so i want a little bit o'class

16:25 arrdem: technomancy: we're not a real lisp, right?

16:25 sdegutis: technomancy: that's all #macdev uses

16:25 don't tell them I sent you

16:26 technomancy: I used to use this for elisp because you could do M-x lisppaste-buffer and a bot would announce it in the #emacs channel

16:26 kinda cool

16:26 sdegutis: technomancy: yeah that feature broke a while ago iirc

16:26 technomancy: yeah, which is probably why I haven't seen anyone use it this decade

16:27 anyway I only paste using my elisp-powered paste site so there

16:29 sdegutis: Why not write it in Clojure?

16:29 * sdegutis ducks

16:29 arrdem: sdegutis: you haven't finished your emacs in clojure port, that's why

16:29 technomancy: sdegutis: because elisp is simple yet powerful

16:30 sdegutis: technomancy: boom got em

16:31 arrdem: ∀T≠C++ claim T is simple yet powerful

16:32 sdegutis: arrdem: my emacs is written in Lua

16:35 hyPiRion: arrdem: let T be any DSL written on top of C++

16:36 arrdem: hyPiRion: my qualifier should have been more explicit... C++ ⊄ T

16:37 sandbags: i don't know if refheap magically healed itself, or someone answered my cry but it's working again ... thank you clojure gods

16:37 hyPiRion: arrdem: there you go

16:38 arrdem: I suppose it should be ⊈ not


16:41 scottj: technomancy: does scpaste-region ever not syntax highlight the region for you, when it's highlighted in the buffer?

16:41 technomancy: scottj: haven't seen that

16:41 the only problem I've seen is hl-line-mode and idle-highlight showing when they shouldn't

16:41 scottj: technomancy: do you use color-theme.el, that might be it

16:41 technomancy: I used to, but not any more

16:42 scottj: technomancy: ok, no worries I'll let you know if I ever figure it out

16:52 jarosti: (clojure.string/replace "somelatex\nwithnewline" #"\n" "\\newline") -> How do I get a backslash to remain in the result?

16:53 hiredman: ,"\\"

16:53 clojurebot: "\\"

16:53 dbasch: ,(clojure.string/replace "somelatex\nwithnewline" #"\n" "\\\newline")

16:53 clojurebot: "somelatex\newlinewithnewline"

16:53 hiredman: ,"\"

16:53 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

16:54 johncash: is there a way to declaratively define base conditions for a loop rather than using if/when? sort of like haskell style.

16:54 technomancy: johncash: core.match I guess

16:55 johncash: ive been on a journey to avoid branching logic where possible

16:55 technomancy: thnx

16:55 Glenjamin: is there a way to get lein to tell me the profiles and their dependencies? `lein with-profile test repl` leaves me with no nRepl in this project

16:56 technomancy: Glenjamin: unfortunately that's a bit opaque right now

16:56 but you probably want `lein with-profile +test repl`

16:56 Glenjamin: i feel vindicated in my confusion at least

16:56 jarosti: dbasch: (print (s/replace "somelatex\nwithnewline" #"\n" "\\\newline\n"))

16:56 somelatex

16:56 ewline

16:56 withnewline

16:56 technomancy: or `lein with-profile base+test repl`

16:57 err `lein with-profile base,test repl`

16:57 Glenjamin: i ended up doing with-profile base,dev,user,test :D

16:57 technomancy: same thing, yeah

16:57 Glenjamin: kept guessing until it worked

16:57 xeqi: are you around at all?

16:57 technomancy: I think a better design would be to allow every task to have two implicit profiles; one provided by the task and one overridable by the user

16:57 as long as the mechanism for such a thing is standardized it would allow for much better transparency

16:58 Glenjamin: the + vs , thing seems reasonable

16:58 dbasch: jarosti: maybe you want (clojure.string/replace "somelatex\nwithnewline" #"\n" "\\\\newline")

16:58 xeqi: Glenjamin: surprisingly I am atm, but rarely normally

16:58 jarosti: dbasch: thanx

16:58 Glenjamin: being able to do lein show-profiles :tree might help

16:59 xeqi: i've pushed a few updates to peridot recently, including passing tests on 1.6

16:59 nullptr: ,(clojure.string/replace "x" #"x" "\\")

16:59 clojurebot: #<StringIndexOutOfBoundsException java.lang.StringIndexOutOfBoundsException: String index out of range: 1>

16:59 Glenjamin: about to do the same kerodon, including merging some PRs

16:59 technomancy: Glenjamin: most task-specific profiles are not declarative though

16:59 which we need to fix

16:59 Glenjamin: will you be able to publish clojar updates soonish?

16:59 johncash: i heard rumour that `use` is deprecated now, is that founded?

16:59 Glenjamin: technomancy: i didn't follow that last bit i'm afraid

17:00 xeqi: Glenjamin: awesome, I can tonight. or you could tell me your clojars name and I can give you permissions

17:00 Glenjamin: glenjamin on clojars, i hope i didn't lose my pgp key :)

17:02 xeqi: Glenjamin: done

17:02 Glenjamin: tyvm

17:02 are you still using peridot/kerodon at all?

17:03 nullptr: ,(clojure.string/replace "x" #"x" (clojure.string/re-quote-replacement "\\")) ; jarosti

17:03 clojurebot: "\\"

17:04 stompyj: is that react petehunt?

17:04 petehunt: yessir

17:04 or ma'am

17:04 Glenjamin: technomancy: do you mean that some profiles only work with +profile ?

17:05 stompyj: petehunt: haha, do you guys have a clojure stack @ fb? or just interested in the language?

17:05 technomancy: Glenjamin: no, I mean that some tasks merge profiles inside their defn, which is not introspectable

17:05 Glenjamin: oh

17:06 i see

17:06 gtrak: their next php compiler is actually a set of clojurescript regexes.

17:06 petehunt: stompyj: no clojure @ fb, but a lot of FP in mainstream languages

17:07 stompyj: petehunt: ahhh ok, very cool. I get pinged by fb recruiters from time to time and if you had clojure, I’d ping back. heh :)

17:07 Glenjamin: gtrak: there actually is a clojure-like lisp that compiles to PHP :o http://pharen.org/

17:07 stompyj: One of the best pieces of steak i’ve had in NYC was @ FB’s offices

17:07 heh

17:08 petehunt: stompyj: haha, the food here is excellent

17:08 stompyj: fact

17:08 xeqi: Glenjamin: not really. haven't had much time for clojure recently, and I've been impressed by liberator for api + om/react for ui

17:08 so less html, more cljs

17:08 gtrak: oh man.. I'm getting enough edge-cases lately by just trying to learn html, thankfully react/om is a respite.

17:08 dgleeson: So I have a vector, I want to turn it into a formatted string that I will be putting on syslog. I have this https://gist.github.com/whodevil/2b11a1fc21da95bd33f1, but it is returning lazyseq... Any ideas?

17:09 gtrak: amortize pain with occasional good tech, that's my secret to success.

17:09 petehunt: stompyj: yeah no clojure, but hacklang.org is nice

17:10 we are probably one of the better “big companies” if you like FP, despite the fact that we don’t use functional languages directly. a lot of the core abstractions are FPish

17:10 dbasch: Linkedin and Twitter do use Clojure

17:10 arrdem: do we have a standard fixed point combinator? I don't remember.

17:11 stompyj: petehunt: very interesting. maybe I will follow up with them at some point

17:11 dbasch: of course Twitter is big on Scala, but that doesn’t mean most people use it in functionaly style

17:11 functional

17:11 wackyvorlon: I've been playing with overtone and clojure lately, and using this bit of example code: https://www.refheap.com/85538

17:11 stompyj: I love LinkedIn’s infrastructure, that’s another place I’d cnosider

17:11 wackyvorlon: What does it mean when you call #'player2?

17:11 gtrak: #' is a var, that's usually an indicator of repl-convenience.

17:11 dbasch: stompyj: LinkedIn has a good culture of open-sourcing stuff

17:11 petehunt: yeah i don’t know too much about their codebase

17:12 i just can speak confidently that we use FP techniques all over the frontend

17:12 nullptr: linkedin has cool backend tech, yet somehow i encounter more "this doesn't work" bugs on their site vs. any other of the "majors"

17:12 technomancy: petehunt: how much of that is just an inevitable consequence of operating at scale?

17:12 wackyvorlon: gtrak: How is it different from using (player2)? This in an apply-by.

17:12 technomancy: literally no other way to do it =)

17:12 nullptr: https://twitter.com/derekslager/status/448839597410115584

17:13 petehunt: i mean there are probably ways to do it without immutability etc

17:13 gtrak: wackyvorlon: my guess is overtone needs to serialize something? vars are serializable.

17:13 petehunt: but it would suck and require a lot more people.

17:13 dbasch: nullptr: certainly not more than on Twitter

17:13 gtrak: maybe..

17:13 stompyj: nullptr: agreed. I’m more of a back-end data guy tho, so right in my wheelhouse.

17:13 petehunt: the fact you guys acknowlege immutability is important is amazing, tbh

17:13 wackyvorlon: gtrak: Basically it is using recursion with a delay, and the idea is that using #' lets you modify the code, reevaluate, and it keeps recursing with the new code.

17:13 gtrak: ah, yea, that makes sense.

17:14 dbasch: can’t speak for any front-end stuff at LinkedIn, I worked in the deepest depths of the backend

17:14 gtrak: wackyvorlon: essentially, vars provide an IFn implementation that delegates through a deref.

17:14 petehunt: stompyj: the front end eng team here is basically using our (fairly large these days) soapbox to push an FP agenda

17:15 publicly

17:15 it already won out internally

17:15 most people are obsessed with syntax though

17:15 so need to pick your battles

17:16 gtrak: clojure makes me actually *annoyed* at syntax.

17:16 nullptr: he said, in a lisp channel...

17:16 wackyvorlon: gtrak: Ahh! Okay, so basically functions are variables, and deref makes it use the latest value of the variable which implements IFn(i.e. the interface for a function)?

17:16 gtrak: I get uncomfortable when I see it now, it wasn't like that before.

17:16 petehunt: hey i am on your side nullptr

17:16 stompyj: petehunt: that’s awesome

17:17 gtrak: wackyvorlon: yes.

17:17 wackyvorlon: gtrak: Awesome! Thanks, much appreciated:) Also, that is exceedingly cool.

17:17 gtrak: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Var.java#L374

17:18 wackyvorlon: Bah, stupid netsplit...

17:18 I take it java doesn't have varargs?

17:19 amalloy: wackyvorlon: one minor detail: functions are not variables, they're immutable values. rather, when you define a function, with def or defn, you also create a var (variable) that points to the function's definition

17:19 gtrak: java does, but they're an illusion, it's just an array as far as the jvm's concerned.

17:19 wackyvorlon: amalloy: So sort of like having a void pointer in C.

17:19 gtrak: that's probably what Rich Hickey was going for ;-)

17:20 how do we give void pointers better semantics so you'll use them more?

17:20 wackyvorlon: gtrak: That makes sense. Void pointers have always struck me as a hack.

17:21 gtrak: I was kind of joking, but it works.

17:21 amalloy: i'm not sure what the analogy is there, wackyvorlon. a var is indeed a bit like a void pointer, i guess, but so are most things in clojure: references are untyped, and can point at anything

17:21 well, not "most things in clojure". that was way wrong. most *references* in clojure

17:22 sdegutis: What's a good use-case for Clojure's deriving functionality?

17:22 wackyvorlon: amalloy: Void pointers are used as a means of pointing to a memory address when you load an object with dlopen().

17:22 amalloy: void pointers are used for like a million things

17:22 wackyvorlon: dlsym() gives you the memory address of the code, which you dump into a void pointer, and call with syntax like *(foo);

17:23 It's been a while since I used it.

17:23 That is the speicific application of void pointers I'm thinking of:)

17:23 amalloy: wackyvorlon: i don't think that's a particularly useful frame of reference for understanding vars, but if it helps you, then go for it

17:23 sdegutis: mostly it's used as a way to say "look, you can do inheritance!"

17:24 wackyvorlon: I think I'm used to lower-level stuff, so I tend to think in terms of memory addresses.

17:24 Glenjamin: sdegutis: grouping stuff together in multimethod implementations?

17:24 gtrak: sdegutis: friend uses it for access control.

17:25 user roles

17:27 wackyvorlon: after having used java for a while, clojure had a very C-like feel to me, which I think was not intended.

17:27 sdegutis: derive/parents/isa?/ancestors/descendents look fun, I just can't find any problems they're suitable for (where plain old functions and data aren't)

17:27 gtrak: I can't imagine how Clojure feels like C

17:28 amalloy: sdegutis: i have found one use-case for derive in my ~four years of clojure

17:28 gtrak: it's hard to describe. minimal I guess is the word.

17:28 maybe it's just I was a noob when I used C last, and I was a noob at clojure.

17:28 sdegutis: Glenjamin: ah yes, that could make a ton of sense, it could act as the "state" for a multimethod!

17:28 hyPiRion: gtrak: Have you played around with scheme?

17:28 gtrak: a little bit

17:29 Glenjamin: i did it here, but i am unsure if it was worth it: https://github.com/Frozenlock/kerodon/blob/cde0feee8f178757891e4dc552f756194c389925/src/kerodon/impl.clj#L270

17:29 sdegutis: Glenjamin: like {:kind ::person :name "me" ...}

17:29 arrdem: meh... scheme was a waste of three months between SCIP and using Clojure.

17:29 hyPiRion: I feel the scheme/c analogy fits better, at least for me

17:30 sdegutis: With a multimethod that switches off on (isa? ::base-whatever)

17:30 wackyvorlon: It's been quite an adjustment to go from stuff like C to clojure.

17:30 gtrak: there's no 'Clojure for C programmers' video.

17:30 amalloy: sdegutis: https://github.com/ninjudd/depot/blob/develop/src/depot/pom.clj#L8-L23 let me reuse the multimethod implementation for two different dispatch values that i wanted to treat similarly (as a generic "list of whatever")

17:30 sdegutis: arrdem: scheme is pretty cool, just also not practical for real-world anything

17:30 arrdem: I guess due to minimality Scheme is more "c in sexprs" than clisp is...

17:31 s/clisp/CL/g

17:31 Glenjamin: oh, neat - my example is almost identical to amalloy's \o/

17:31 sdegutis: amalloy: ahh ok

17:32 amalloy: Glenjamin: wait, https://github.com/Frozenlock/kerodon/blob/cde0feee8f178757891e4dc552f756194c389925/src/kerodon/impl.clj#L275, really? i thought it was supposed to be: checked="checked"

17:33 the w3c even says so, at http://www.w3.org/TR/html-markup/input.checkbox.html

17:33 Glenjamin: <input type="checkbox" checked="checked" name="foo" value="123"> => foo=123

17:33 <input type="checkbox" checked="checked" name="foo"> => foo=on

17:34 sdegutis: HTML is so lax it's not even funny.

17:34 Glenjamin: that form parsing code was a nightmare to write

17:35 see https://github.com/xeqi/kerodon/blob/master/test/kerodon/unit/impl.clj#L56 onwards for checkboxes

17:36 currently trying to remember the passphrase for key i used once a year ago to push to clojars :(

17:40 sdegutis: I determined a way to solve my problems using multi-methods and shared state.

17:41 You see, there will be a single variable called "live?" which will default to false, and two sets of methods that switch off based on this value.

17:42 There will also be a variable for one of the "implementations" which stores its state, although I don't like this work-around.

17:44 ,*ns*

17:44 clojurebot: #<Namespace sandbox>

17:45 sdegutis: (let [x (def foo)] (= x (clojure.lang.Var$Unbound. #'sandbox/foo))

17:45 ,(let [x (def foo)] (= x (clojure.lang.Var$Unbound. #'sandbox/foo))

17:45 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

17:45 sdegutis: Find Never mind.

17:48 Bronsa: ,(let [x (def foo)] (= x (clojure.lang.Var$Unbound. #'sandbox/foo)))

17:48 clojurebot: false

17:48 Bronsa: sdegutis: ^

17:48 sdegutis: Othanks

17:50 whodidthis: whats a cool way to conj x amount of nil to a vector

17:50 clojurebot: Cool story bro.

17:52 dbasch: ,(concat [1] (repeat 3 nil))

17:52 clojurebot: (1 nil nil nil)

17:53 turbofail: ,(reduce conj [1] (repeat 3 nil))

17:53 clojurebot: [1 nil nil nil]

17:53 martinklepsch: I'm using flatten around pmap, is that something people do or do I lose pmaps parallelism doing that?

17:54 egghead: oh can I play

17:54 ,(apply conj [1] (repeat 3 nil))

17:54 clojurebot: [1 nil nil nil]

17:54 whodidthis: o la la

17:55 amalloy: into, guys. into

17:55 hyPiRion: (inc amalloy)

17:55 lazybot: ⇒ 106

17:55 amalloy: ,(into [1] (repeat 3 nil))

17:55 clojurebot: [1 nil nil nil]

17:59 turbofail: ,`[1 ~@(repeat 3 nil)]

17:59 clojurebot: [1 nil nil nil]

18:00 amalloy: turbofail: that's okay, but it doesn't really use the existing vector

18:00 turbofail: ,`[~@[1] ~@(repeat 3 nil)]

18:00 clojurebot: [1 nil nil nil]

18:00 turbofail: of course that doesn't either

18:01 Glenjamin: what does the "promote" button do in clojars?

18:01 turbofail: i'm just going for silly points

18:04 shriphani: Hi, I am a bit stumped with some java interop here. I have a lib from maven where the docs and poking around with java show me a public method. However clojure thinks it is private (and so does reflection). Can someone help shed light on this ?

18:05 amalloy: shriphani: it could be a public method of a non-public class

18:05 technomancy: Glenjamin: it's an unfinished feature of clojars; you can ignore it

18:05 Glenjamin: aww

18:05 shriphani: amalloy nope

18:05 amalloy: in which case you can't call it via reflection, you have to type-hint it as some public interface that contains the method you want to call

18:05 Glenjamin: i got all excited and clicked it, but nothing happened :)

18:05 shriphani: it is a public class

18:06 amalloy: are you sure? be more specific: what maven artifact are you having trouble with and where are its docs? do you have a code sample that fails but you think should work?

18:07 shriphani: sure. this lib: http://mvnrepository.com/artifact/net.sourceforge.htmlcleaner/htmlcleaner , version 2.8. The method in question in HtmlCleaner/getInnerHtml

18:07 is*

18:08 amalloy, specifically: (import (org.htmlcleaner HtmlCleaner)) to import said class

18:10 amalloy: so you have some HtmlCleaner object h, and you're calling (.getInnerHtml h some-tag-node)?

18:10 shriphani: yep

18:11 justin_smith: shriphani: are you shure you are getting the version of the dep you think you are? it could be that the package changed in scope

18:11 amalloy: *shrug* should work. you could be getting a different version, as justin_smith says

18:11 shriphani: justin_smith, I removed the repo and ran lein deps again

18:11 justin_smith: (between the source/docs you are looking at and the version your program is using)

18:11 shriphani: but what version did it give you?

18:11 did you check?

18:11 shriphani: and I have 2.8 specified in project.clj which is the latest version

18:11 and it downloaded 2.8

18:11 justin_smith: OK

18:12 amalloy: well, i don't think what you're describing should be possible. if you create a gist or a git repo or something with minimal failing code for someone else to repro, maybe it will make sense

18:24 shriphani: amalloy: https://gist.github.com/shriphani/fa1bea3267389e47b7f7

18:24 thats my 3 files.

18:24 well one of those is a repl output but yeah

18:25 amalloy: shriphani: .clean doesn't return the cleaner object

18:25 so when you call .getInnerHtml on the result of process-page, it's some random other object, not a cleaner at all

18:26 sdegutis: How do you solve the require-order problem when you have a defmulti with defmethods in different namespaces?

18:27 amalloy: you can tell from the exception message, which says "No matching field found: getInnerHtml for class org.htmlcleaner.TagNode" - note it's not talking about the class HtmlCleaner at all, which is the class you thought you were using

18:27 sdegutis: Do you have the namespace with the defmulti in it just require the namespaces with the defmethods in dem?

18:30 shriphani: amalloy: this is what reflection spits out. getInnerHtml is private: https://gist.githubusercontent.com/shriphani/fa1bea3267389e47b7f7/raw/81375dab6fee4e610f8ab8f754fd26c4ae03d2d6/gistfile1.txt

18:31 amalloy: no, it clearly says public, right there in that table you ilnked me to

18:32 but even if it didn't, the error message you get is clearly unrelated to access levels on HtmlCleaner, because you're *not using one at all*

18:32 shriphani: ok nvm. yeah I see it now. that was stupid of me.

20:11 arrdem: so when iw clojure.core/print-method not bound so that clojure.lang.RT.print() will use its formatter?

20:11 just trying to read into the boot process here.

20:24 cespare: Is there a word for #( )

20:24 Jaood: fn ?

20:24 danielcompton: anonymous function?

20:24 arrdem: +1 anonymouse function

20:24 cespare: i mean that specific form

20:25 (fn ...) is also an anonymous function

20:25 Jaood: function literal

20:25 danielcompton: Anonymous function literal

20:25 darn Jaood beat me to it

20:26 cespare: ok thx

20:26 Jaood: :)

20:40 trap_exit: is there a way to cache the result of a cond pair? i.e. when I do (cond t1 e1, t2 e2, t3 e3) ... there is a sub expression x1 used in both t1+e1; x2 used in both t2 + e2; x3 used in both t3 + e3. Now, I only want to evaluate x1, x2 x3 once -- and I only want to eval x2 if t1 fails; and I only want to eval x3 if t1 + t2 fails. Is there a way to do this?

20:41 amalloy: trap_exit: you can let-bind a delay

20:41 arrdem: trap_exit: you could write a helper function and memoize it, but that's the only builtin wa.y

20:41 trap_exit: amalloy arrdem: damn, both of these are crazy ways

20:41 but both very clever

20:41 I'd never have thought of using a delay / memoization

20:42 amalloy: (let [x1 (delay (...))] (cond @x1 (inc @x1)))

20:42 trap_exit: decisions decisions

20:42 * arrdem defers to amalloy and reads the fine manual

20:42 trap_exit: I like the delay way better

20:42 amalloy: are you available for consulting?

20:42 amalloy: trap_exit: you can even wrap it up in a clever macro if you want

20:42 trap_exit: ergh

20:42 writing cljs code

20:42 debugging macros painful

20:43 amalloy: trap_exit: no. but i answer questions for free in #clojure and on stackoverflow when i feel like it

20:43 trap_exit: but this use of delay is badass

20:43 oh

20:43 amalloy: https://github.com/flatland/useful/blob/develop/src/flatland/useful/utils.clj#L224 if you want it to look prettier, trap_exit

20:43 trap_exit: here's adubmass ideas

20:43 why does SO not hcarge peopl e$9.99 / month ?

20:43 I'd pay $9.99 / month

20:43 to have the ability to fucking ignore dumbass users

20:43 knowing that every time they create a new account, it costs them $9.99 / month

20:44 okay, this let delay

20:44 amalloy: that's a brilliant idea. why don't you start a competing company and drive them to bankruptcy while you rake in millions?

20:44 trap_exit: just got it to work

20:44 is completely badass

20:45 amalloy: I'm seriously considering doing so

20:45 but have not ifgured out a way to get initial users

20:45 locks: or just pull a Quora

20:45 and go bankrupt because the UX is ass

20:45 trap_exit: well, Quora solves a different problem

20:45 "how to raise $80M without doing anything"

20:46 turbofail: that's a pretty important problem

20:46 dbasch: 7-minute abs

20:47 turbofail: eventually we're going to have to solve that problem for everyone as the need for labor decreases

20:47 amalloy: oh wow, i forgot i made let-later work even for values you're destructuring. that's pretty clever, if i do say so myself

20:48 trap_exit: amalloy: got pat younger-amalloy on the back

21:15 rpaulo: I see

21:15 oops, wrong window

21:36 quizdr: rpaulo there are no wrong windows. just windows. the window did nothing wrong. it is not wrong.

21:53 danielcompton: Are there any recommendations for test naming conventions?

21:53 https://github.com/bbatsov/clojure-style-guide didn't have any

22:19 Frozenlock: Uhh... I'm getting a weird error with friend/authenticated. When the user isn't authenticated, it redirects to "/login", but on port 80 even if it's over ssl

22:22 kenrestivo: are you using a front end proxy like nginx?

22:31 Frozenlock: kenrestivo: I am

22:32 but I'm setting the x-forwarded-proto AND overwriting the :scheme as https

22:32 pbw: /part

22:35 danielcompton: I'm trying to create prepared statements using alia/cassandra. I'm having trouble working out the clojuresque way of writing this, as the call to prepare the statement requires a connection to the database. So I don't know how to write it so that the first time the function is called the statement is prepared and the rest of the time it is cached.

22:36 memoize didn't seem appropriate

22:37 kenrestivo: frozenLock: i don't remember anywhere in friend checking :scheme before forwarding to /login. but it's been a while

22:38 Frozenlock: So it's just forwarding to 80? o_O

22:38 kenrestivo: if so, bug should be filed

22:38 Frozenlock: My lazy side wanted to avoid checking the source :-(

22:38 kenrestivo: it's forwarding to /login, no scheme specified, whatever was used for the request, is ring's default

22:39 and if you're proxying through nginx, http not https is what arrived at ring

22:40 dbasch: Frozenlock: why don’t you just rewrite all http requests to https on nginx?

22:41 Frozenlock: dbasch: that's already what I'm doing. rewrite ^ https:....

22:41 friend redirects to https://my-site/login:80

22:42 dbasch: a search for 80 in the source shows https://github.com/cemerick/friend/blob/94a62e46fd08fbc602a340ce03b784f54d718dcc/src/cemerick/friend/util.clj#L21

22:42 zerokarmaleft: Frozenlock: I think I patched that

22:43 Frozenlock: zerokarmaleft: Yes I saw your issue, which was even more confusing me :-/

22:44 Oh I wonder if I disordered my middlewares

22:52 Doesn't seem to be that. Grrrr

23:14 White_Flame: Hi, long-time Lisp user looking at some Clojure source code. I cannot for the life of me figure out how to load a clojure project into a repl and call things interactively. Is there a good beginner tutorial that covers that? Most just type in commands at the repl

23:14 instead of load source code from existing files

23:15 I do have a running repl, from apt-get clojure

23:15 dbasch: White_Flame: are you using leiningen?

23:15 White_Flame: no, just straight clojure-repl

23:15 dbasch: install leiningen and go from there

23:16 White_Flame: is it not worth the effort to get this running as is?

23:16 scottj: White_Flame: nope, almost everyone uses leiningen almost all the time

23:16 dbasch: no, leiningen is by far the best way

23:16 Frozenlock: leiningen powaaaa

23:18 White_Flame: so I've got that running. To be clear, is it fetching its own installation of clojure, or does it use what's installed on my system already?

23:19 beamso: fetching unless you're clojure install was linked to your local maven repository

23:19 scottj: White_Flame: in general though you make sure the src directory or jar is on the classpath and then you require the namespace.

23:19 dbasch: White_Flame: you don’t need an “installation” of clojure

23:19 each project uses its own version of clojure as declared in the project.clj dependency

23:19 White_Flame: well, there's already a clojure.jar somewhere, and who knows how the clojure-repl command finds it

23:20 so it's "installed", at least as far as an apt-get install is concerned

23:20 dbasch: White_Flame: yes, there is one. You just don’t need it

23:20 once you use leiningen you can disregard it

23:23 Frozenlock: godfuckingdamnit

23:23 zerokarmaleft: you did patch it, but for the snapshot version

23:23 Not the current release :-(

23:24 White_Flame: ok thanks, I'm up and running

23:25 zerokarmaleft: Frozenlock: I suppose you could ping cemerick and ask him to cut a new release

23:25 Frozenlock: Indeed

23:26 It would feel weird to run production code with a snapshot :-p

23:26 zerokarmaleft: I ran a local 0.2.0 with just that fix

23:28 technomancy: who was the PDX clojure group person who was thinking about doing a lein hack night?

23:29 Frozenlock: technomancy: hey, nice interview with Sasha! I love your batcave :-p

23:30 TerranceWarrior: Hey White_Flame.

23:31 White_Flame: hey

23:31 TerranceWarrior: White_Flame: Remember me?

23:31 technomancy: Frozenlock: haha thanks

23:31 always fun to hack your actual surroundings

23:32 White_Flame: The name's familiar...

23:32 TerranceWarrior: I was on Stealthnet and we were talking about program analysis to get debug information from previous lines in a monitor of 6510 disassembly.

23:32 White_Flame: Ah, yes

23:33 TerranceWarrior: White_Flame: in the far past we also discussed effecient div code on a 6510 as me with another handle. have many, forgotten which.

23:33 having many that is

23:34 White_Flame: i too have recently bitten the clojure bug.

23:34 White_Flame: Well, I'm actually porting from clojure, not using clojure at the moment ;)

23:34 TerranceWarrior: White_Flame: ?!

23:34 Frozenlock: zerokarmaleft: You don't have it clojars? ... You mean 'really' local? :-/

23:35 White_Flame: Porting FROM clojure? To what?

23:37 White_Flame: Common Lisp

23:37 TerranceWarrior: Lisp is going to die without nonmutability. even #lisp ers where having a sessions saying that last night.

23:38 Frozenlock: I'm used to see CL->CLJ, not the other way around!

23:38 technomancy: racket seems to be adapting somewhat gracefully

23:38 gko: Emacs + Cider + Leiningen is awsome.

23:38 White_Flame: TW: There are lots of immutability libraries in CL as well

23:38 I tend to use strongly functional code

23:39 gko: Especially since the 0.7.0 doesn't seem to freeze Emacs anymore.

23:39 TerranceWarrior: White_Flame: that means it's all a matter of code and impl. one lock it's somewhat foobars and two.. two can make a deadlock. thats two!

23:39 technomancy: but racket seems to be better about breaking from tradition where it makes sense

23:40 White_Flame: TW: I've been doing concurrent programming for, well, a very long time. It's not hard to never have those problems

23:40 TerranceWarrior: long is relative.

23:40 implementation is fact.

23:41 thousands of hits a second a 2014 reality.

23:41 White_Flame: I really don't have much interest in language religion, regardless of whether it's the one I'm using or others'

23:42 Frozenlock: Yeah, stop fighting, elisp is clearly the best.

23:42 White_Flame: and thousands of hits per second has been a reality for a very long time

23:43 TerranceWarrior: long= relative and very long = very relative! ;)

23:43 technomancy: Frozenlock: it's great; in elisp it's guaranteed that mutable strings will cause no concurrency bugs, because there is no concurrency

23:43 TerranceWarrior: being as though very relative doesn't mean 'very relative'.

23:44 White_Flame: okay, let's say 15 years? banking systems have always been huge data processors, regardless of the web catching up in volume

23:44 TerranceWarrior: (++ technomancy)

23:44 Frozenlock: technomancy: Isn't this supposed to change?

23:44 White_Flame: technomancy: Works for node.js ;)

23:44 technomancy: Frozenlock: it's been discussed for a long time... I'm sure it will be a long time before it changes

23:45 White_Flame: (and then they get weird with process pools)

23:45 technomancy: White_Flame: as much as I like to make fun of JS, they amazingly got strings right

23:45 undoubtedly by accident

23:45 TerranceWarrior: with banks realtime usually isn't an issue. it's stuff like reports that need optimization.

23:45 ya know?

23:46 White_Flame: 2014 brings no new requirements, just other interesting options to implement them in

23:46 technomancy: if there are any new requirements, they might be around scaling *down*, not up

23:47 writing code for small devices that are getting ridiculously cheap

23:47 White_Flame: yep, and it's nice living with today's compiler & vm technology, instead of the C focus of yesteryear

23:47 to get all that stuff fast & small

23:48 sjy: White_Flame: what was the last year that brought new requirements? :)

23:48 White_Flame: sjy: I shall decline to respond ;)

23:49 but scalability, responsiveness, and maintainability have always been with us, in need & options in the solution space

23:50 sjy: yeah just curious if you were making the point that on one level requirements never really change, or saying that 2014 was special

23:50 White_Flame: I'm saying that 2014 isn't special, in response to TerranceWarrior

23:50 TimMc: TerranceWarrior: Yeah, it's funny how banking is often used as an example of the need for realtime, concurrent, distributed algorithms... but in reality it's all batched. :-P

23:50 technomancy: clusters where machines go down and get replaced every day is new-ish

23:51 White_Flame: technomancy: what's "new"? people doing it, or the average startup reaching for things off the shelf?

23:51 because I was certainly doing clusters with individual machine downtime in the 90s

23:52 and of course, that far predated my work

23:53 dbasch: Imagine a Beowulf cluster of ring servers

23:53 White_Flame: My network's a star configuration, you insensitive clod!

23:54 technomancy: White_Flame: a few weeks ago I replaced a whole cluster of 44 machines with brand new ones in an hour just to do a trivial-ish deploy

23:54 maybe that was possible in the 90s but you would have had to have been at nasa or something

23:55 White_Flame: nah, it's all been open a mainstay of open source

23:55 -open

23:55 just different architectures connecting to different services

23:55 technomancy: the need for fault-tolerance in data centers has risen a lot

23:56 because virtualization makes things cheap, and cheap things aren't reliable

23:56 TerranceWarrior: technomancy: 43.80 seconds per machine? not bad!

23:56 White_Flame: hmm, virtualization on a nice box, vs a bunch of really crap cheap single-OS boxes...

23:57 TerranceWarrior: opps 1.3 seconds i mean.

23:58 oh whatever, meds talking.

Logging service provided by n01se.net