2014-05-15
| 00:01 | dgleeson | l1x: makes sense |
| 00:01 | devn | l1x: https://gist.github.com/anonymous/d4dad5ff47ae7e92f7a5 |
| 00:02 | devn | i've logged to make sure I'm hitting :started. |
| 00:03 | ddellacosta | devn: was just going to ask--so started definitely is happening, huh? |
| 00:03 | devn | if I inc pending in a different place, outside of the condp, right before i add the listener |
| 00:03 | devn | everything works |
| 00:03 | devn | but it's just weird, and i can't figure out why the hell this would be happening |
| 00:04 | devn | it's like the atom is "warming up" or something |
| 00:04 | devn | but then again, that might be the s3 transfer manager? |
| 00:04 | devn | it boots up its own thread pool |
| 00:05 | devn | oh no. im a terrible liar. |
| 00:06 | devn | :started apparently is not getting hit now on the first go-round |
| 00:06 | devn | i wonder why that's the case... |
| 00:08 | devn | 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 |
| 00:08 | devn | it's just after i re-eval, the very first upload, and no others |
| 00:49 | arrdem | ,#inst |
| 00:49 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 00:52 | amalloy | devn: i speculate that the :started event never fires at all, on any events; you just get one :failed |
| 00:54 | amalloy | try doing some logging instead of, or in addition to, just munging a number around |
| 00:55 | Raynes | amalloy: I wrote the lein plugin. |
| 00:55 | Raynes | amalloy: You should try it. |
| 01:25 | bjeanes | man trying to write an oauth1 workflow for friend... |
| 01:26 | bjeanes | keep spinning my wheel |
| 01:26 | bjeanes | s |
| 01:52 | lds | hello |
| 02:41 | TerranceWarrior | is it possible to make a c++ interface to unrealengine from clojure? |
| 02:51 | danielcompton | Is there a more efficient/idiomatic way to write https://gist.github.com/danielcompton/1c741fcac42424433943 ? |
| 02:52 | danielcompton | I'm wanting the values of a map sorted by key, (map second) seems like a bit of a hack |
| 03:00 | mange | danielcompton: would (map val) work better for you? (->> m (sort-by key) (map val)) seems like it would be clearest. |
| 03:01 | mange | ,(->> {:c :d, :a :b} (sort-by key) (map val)) |
| 03:01 | clojurebot | (:b :d) |
| 03:02 | AimHere | So use 'val' instead of 'second'? |
| 03:03 | mange | It's pretty much the same thing, it just reads a bit more naturally, maybe. |
| 03:07 | danielcompton | mange: Thanks, that's better |
| 03:08 | danielcompton | Because you're mapping over a MapEntry, not a vector so val works too? |
| 03:09 | AimHere | I probably should go back and do some more Rosalind problems sometime! |
| 03:09 | bjeanes | am I crazy or is `lein ring server` suppressing stdout? |
| 03:09 | mange | danielcompton: Yeah, each of your seq elements is a MapEntry, so you can use key and val for readability. |
| 03:11 | mange | Actually, key and val should be slightly more performant, too, but probably not by too significant an amount. |
| 03:16 | danielcompton | mange: because they're operating directly on the mapentry? |
| 03: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. |
| 03:40 | Glenjamin | you can also use an actual sorted map |
| 03:40 | Glenjamin | ,(into (sorted-map) {1 :a 3 :b 2 :c}) |
| 03:40 | clojurebot | {1 :a, 2 :c, 3 :b} |
| 03:41 | mange | He's using frequencies, so he can't control the map type. |
| 03: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? |
| 03:56 | numberten | what sort of thing? |
| 03:57 | danielcompton | Glenjamin I thought about rewriting frequencies to use a sorted map, which would be faster? |
| 03:57 | numberten | DEA7TH: (range 1001) gives you the numbers |
| 03:58 | numberten | rather 1 1001 |
| 03:59 | numberten | i think the typical way of using them varies on what you're using them for |
| 03:59 | mange | danielcompton: sorted maps don't support transient/persistent! at the moment, so that might end up being slower than frequencies and sorting. |
| 04:00 | danielcompton | What would be the best way to benchmark it? Criterium? |
| 04:01 | amalloy | danielcompton: a map sorted by its vals is, i believe, a priority queue |
| 04:01 | amalloy | there are implementation of those hanging around in clojure somewhere, i'm fairly sure |
| 04:01 | mange | amalloy: he's looking to sort by key. |
| 04:02 | amalloy | oh, i see. isn't that just vals? |
| 04:02 | amalloy | in a sorted map? |
| 04:02 | amalloy | i see that's been covered too |
| 04:04 | numberten | is there an idiomatic way to pass around a configuration structure? |
| 04:04 | numberten | or rather to handle configuration |
| 04: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. |
| 04:06 | dbasch | danielcompton: do you really need to optimize it? |
| 04:06 | danielcompton | dbasch not really, |
| 04:07 | danielcompton | dbasch I'm wanting to learn more about building performant clojure, so this seemed like a simple example |
| 04:07 | DEA7TH | numberten: I want to sum over some of the numbers from 1 to 1000 |
| 04:07 | dbasch | danielcompton: you may look into the option of using a java TreeMap |
| 04:07 | DEA7TH | numberten: Project Euler, problem 1. I'm learning Clojure |
| 04:08 | DEA7TH | (btw I know there's a better way to solve it) |
| 04:08 | dbasch | just for completeness |
| 04:08 | danielcompton | dbasch Now we're talking |
| 04:08 | danielcompton | Is criterium the best way to benchmark this? |
| 04: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) |
| 04:10 | dbasch | danielcompton: I don’t know a better way than criterium |
| 04:11 | dbasch | 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 |
| 04:12 | danielcompton | dbasch what was the order of performance between each? Order of magnitude each time? |
| 04:12 | dbasch | danielcompton: no, it was the same order of magnitude |
| 04:12 | dbasch | using a hashmap was maybe twice as fast as a persistent map |
| 04:13 | dbasch | but it was a very specific case, not sure I’d generalize from that |
| 04: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)) |
| 04:19 | numberten | but that doesn't abstract the problem really. and relies on implementation details in the function you're trying to apply to the collection |
| 04:34 | danielcompton | Here's my early results https://gist.github.com/danielcompton/4b1a59054a40a89c19ec |
| 04:36 | Glenjamin | mange / danielcompton / amalloy - clojure.data.avl seems to be a decent sorted-map implementation that supports transients and other neat stuff |
| 04:37 | Glenjamin | 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 |
| 04: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} |
| 04:39 | numberten | so update all values in map 2 from those given in map 1 |
| 04:39 | Glenjamin | ,(doc merge-with) |
| 04: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)." |
| 04:39 | numberten | many thanks |
| 04:40 | Glenjamin | oh, in fact that's just (merge map-2 map-1) |
| 04:41 | numberten | even simpler |
| 04:59 | danielcompton | So using a custom sorted-frequencies implementation is slightly faster https://gist.github.com/danielcompton/4b1a59054a40a89c19ec#file-dna-frequencies-the-second |
| 04:59 | danielcompton | Now for the tree map |
| 05:17 | DEA7TH | How do I break this code into multiple lines: (reduce + (filter #(= 0 (* (mod % 3) (mod % 5))) (range 1000))) |
| 05:17 | DEA7TH | I suppose that's too much for a single line? |
| 05:19 | danielcompton | DEA7TH you can use a threading macro -> and ->> to break this up and make it more readable |
| 05:19 | DEA7TH | more generally, is there a way to split function arguments into multiple lines |
| 05:20 | neena | DEA7TH: The function arguments can span multiple lines. |
| 05:21 | danielcompton | DEA7TH https://www.refheap.com/85517 |
| 05:22 | DEA7TH | ->> reverses the order? |
| 05: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? |
| 05:25 | neena | DEA7TH: It inserts the result of the previous form in the last position of each form. |
| 05:27 | neena | DEA7TH: Also, you might want to use zero? instead of (= 0 ...) |
| 05:27 | clgv | ,(macro-expand '(->> (range 100) (filter even?))) |
| 05:27 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: macro-expand in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 05:27 | clgv | ,(macroexpand '(->> (range 100) (filter even?))) |
| 05:27 | clojurebot | (filter even? (range 100)) |
| 05:27 | clgv | DEA7TH: ^^ |
| 05:33 | pepijndevos | I use gen-class to subclass a class with a main, how do I get that main to actually work? |
| 05:33 | pepijndevos | $ lein run -m neo4j.server |
| 05:33 | pepijndevos | Exception in thread "main" java.lang.Exception: Cannot find anything to run for: neo4j.server |
| 05:42 | DEA7TH | ehh, can I invoke a function which is declared in code below? it doesn't seem to work |
| 05:43 | emlyn | pepijndevos: have you added a (defn -main [...] ...)? Also you don't need gen-class for lein run |
| 05:43 | pepijndevos | emlyn, I did not, but I just want to call super's main |
| 05: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. |
| 05:45 | emlyn | pepijndevos: not sure, but I think you'll have to add a -main and call that explicitly |
| 05:45 | pepijndevos | emlyn, how do I refer to the super's main? |
| 05:46 | emlyn | pepijndevos: not done that before but I expect (super/-main ...) |
| 05:46 | pepijndevos | I tried :exposes-methods {main super-main} |
| 05:46 | pepijndevos | but I get Unable to resolve symbol: super-main in this context |
| 05:51 | emlyn | pepijndevos: I'm not sure, but if you can put a minimal example on refheap I can take a look |
| 05:51 | pepijndevos | this is my current file https://www.refheap.com/85518 |
| 05:51 | quizdr | pbw ah that's good to know. |
| 05:52 | pepijndevos | emlyn, it requires org.neo4j.app/neo4j-server "2.1.0-M01" |
| 05:56 | pepijndevos | What if I used a proxy and no gen-class. Just a main method that calls main on the proxy |
| 06:00 | emlyn | pepijndevos: sorry I'm a bit out of my depth, not sure what to suggest... |
| 06:00 | pepijndevos | hmmm, ok thanks for thinking along :) |
| 06:04 | pepijndevos | I can't even figure out how to call the main of the proxy I made |
| 06:05 | pepijndevos | proxy creates an instance already it seams |
| 06:10 | emlyn | pepijndevos: have you tried (proxy-super main) in the proxy? |
| 06:11 | pepijndevos | emlyn, I'm not even overriding main now |
| 06:13 | pepijndevos | the problem is that I need to call a static method on an instance |
| 06:13 | clgv | pepijndevos: -main is a static method, there is no such thing as inheritance of static methods |
| 06:13 | pepijndevos | (. (Integer. 3) (parseInt "42", 10)) |
| 06:13 | clgv | pepijndevos: you'll have to write your own main if you want to start that particular class |
| 06:14 | pepijndevos | what should that main look like? |
| 06:15 | pepijndevos | clgv, I have 2 versions: https://www.refheap.com/85518 https://www.refheap.com/85520 |
| 06:17 | clgv | pepijndevos: well you will have to replicate whatever the super class does in its main |
| 06:17 | pepijndevos | what?! why? |
| 06:17 | clgv | pepijndevos: since its a static method |
| 06:18 | pepijndevos | so? |
| 06:18 | clgv | pepijndevos: you want to run it with your derived class right? |
| 06:18 | pepijndevos | yes |
| 06:18 | clgv | so actually you are trying to extens dome features of that CommunityNeoServer? |
| 06:18 | clgv | *extend |
| 06:19 | pepijndevos | no, just providing a different config |
| 06:19 | pepijndevos | http://components.neo4j.org/neo4j-server/milestone/apidocs/org/neo4j/server/CommunityBootstrapper.html |
| 06:19 | pepijndevos | like this https://github.com/jexp/neo4j-in-memory-server/blob/master/src/main/java/org/neo4j/server/inmemory/InMemoryBootstrapper.java |
| 06:19 | clgv | pepijndevos: ok. so what exactly does that predefined main do and how would you use it in java? |
| 06:20 | clgv | forget the java. how would you use it? |
| 06: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 |
| 06: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. |
| 06:21 | clgv | pepijndevos: (CommunityNeoServer/-main "my" "args" ...) will run that main |
| 06:21 | clgv | pepijndevos: if you cant specify the actual server class via configuration that will not work |
| 06:22 | pepijndevos | I don't get it... why can't I subclass the bootstrapper, overwrite a method and call the inherited main? |
| 06:22 | clgv | pepijndevos: because static methods are not inherited |
| 06:23 | clgv | they are just static. method of the class instead of methods of an object instance |
| 06:23 | pepijndevos | but it is listed here as an inherited method http://components.neo4j.org/neo4j-server/milestone/apidocs/org/neo4j/server/CommunityBootstrapper.html |
| 06:23 | clgv | but it is also listed as static |
| 06:24 | clgv | if they didnt change java 8 significantly there is no inheritance for static methods |
| 06:25 | pepijndevos | grmph.... |
| 06:26 | pepijndevos | ahaha, main actually calls start |
| 06:26 | pepijndevos | 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 |
| 06:27 | clgv | pepijndevos: he well, then you could have saved some time ;) |
| 06:29 | pepijndevos | aaaarg.... but my problem still exists |
| 06:30 | pepijndevos | org.apache.commons.configuration.ConfigurationException: Cannot load a configuration from a directory |
| 06:30 | clgv | sounds like wrong parameter or something |
| 06:31 | pepijndevos | yea... |
| 06:32 | pepijndevos | i'm just not 100% certain where it's getting its config from, so I created that subclass to explicitly give it a config. |
| 06:32 | pepijndevos | but it's still looking in the wrong places it seems |
| 06:36 | pepijndevos | anyway, thanks for the help |
| 06: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)? |
| 06:45 | Glenjamin | you can run it with (future) |
| 06:47 | clgv | martinklepsch: yes, future is the way to go |
| 06:48 | martinklepsch | so when I run (future (pmap ...)) on a remote repl and then disconnect it'll continue to run? |
| 06:48 | martinklepsch | I also thought that future would work but I thought it might be bound the the repl session |
| 06:50 | Glenjamin | erm, you'll have no way to get the result value unless you (def) it i think |
| 06:50 | Glenjamin | but it should probably keep running |
| 06:51 | Glenjamin | not sure if GC would kick in |
| 07:02 | clgv | martinklepsch: as Glenjamin said you need to bind that future to a variable otherwise its result will be lost |
| 07:45 | martinklepsch | Glenjamin, clgv, if I bind that to a var and then end the repl session, wont that var be lost? |
| 07:48 | clgv | martinklepsch: no, if the REPL process is not shotdown that will work |
| 07:49 | clgv | "shot down" :P |
| 07:51 | martinklepsch | clgv, ok so if I start the remote repl using tools.nrepl.server I should be good to go I gues |
| 07:51 | martinklepsch | that's cool then. thanks! |
| 07:51 | clgv | it is also pretty easy to try ;) |
| 08:06 | Glenjamin | lein repl :headless |
| 08:06 | Glenjamin | lein repl :connect |
| 08:06 | Glenjamin | if you disconnect but leave the headless one running, you can acheive what you describe |
| 08:09 | clgv | Glenjamin: I think he is going to embed an nrepl in his application |
| 08: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? |
| 08: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 |
| 08:15 | opqdonut | (def +constant+ 17) |
| 08:15 | opqdonut | now that :dynamic is no longer the default for vars, vars like that are pretty fast |
| 08:16 | Bronsa | you can use (def ^:const my-constant 23) |
| 08:16 | Bronsa | this way it will get inlined |
| 08:16 | opqdonut | oh right, there's that too |
| 08:16 | opqdonut | and a type hint is probably apropos if the value is an object |
| 08:17 | phillord | I'm finding about a 4x difference between accessing a static final in java and accessing a var |
| 08:18 | opqdonut | did you try :const? |
| 08:18 | phillord | working on that |
| 08:18 | phillord | benchmarks take a while:-) |
| 08: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 |
| 08:19 | phillord | ok, will test both of these |
| 08:20 | opqdonut | are you using *warn-on-reflection* btw? |
| 08:20 | opqdonut | if you're optimizing clojure code it's the first thing to do |
| 08:26 | phillord | curiously, :const causes an AbstractMethodError -- rather unexpected |
| 08:26 | clgv | phillord: ^:const is the way to go here ^^ |
| 08: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. |
| 08:32 | phillord | 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 |
| 08:36 | justin_smith | phillord: :const only works for primitive types |
| 08:37 | justin_smith | not objects |
| 08:39 | phillord | really? |
| 08:40 | phillord | I'm struggling to find the documentation for :const |
| 08:52 | clgv | phillord: http://clojure-doc.org/articles/language/namespaces.html#constant-vars |
| 08:52 | clgv | not much there though |
| 08:58 | phillord | no, that doesn't describe anything at all! Well, if all else fails, write some code and decompile it! |
| 09:02 | clgv | phillord: usually you get a "can not embed in code" exception when you specify :const for the wrong value |
| 09:04 | phillord | I am guessing it works with lists and such like |
| 09:05 | phillord | yep -- so lists get inlined to a specific implementation |
| 09:05 | phillord | public final class core$const_string_list extends AFunction |
| 09:05 | phillord | { |
| 09:05 | phillord | public static final AFn const__0; |
| 09:05 | phillord | |
| 09:05 | phillord | static { |
| 09:05 | phillord | const__0 = (AFn)RT.vector(new Object[] { "const-list-elem" }); |
| 09:05 | phillord | } |
| 09:05 | phillord | |
| 09:05 | phillord | public Object invoke() { |
| 09:05 | phillord | return core$const_string_list.const__0; |
| 09:05 | phillord | } |
| 09:05 | phillord | } |
| 09:06 | phillord | okay, well, now I know how it works anyway! Not what I need, unfortunately |
| 09:09 | Bronsa | phillord: next time use a pastebin please |
| 09:10 | phillord | realised that after I had done it |
| 09:10 | beamso | has anyone done the basic om tutorial lately? |
| 09:11 | beamso | when rendering the first list, i was expecting a ul with 4 li childen. i'm getting a ul with the single child |
| 09:11 | clgv | phillord: it works for clojure values that have literal representations I guess |
| 09: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 |
| 09:12 | Bronsa | phillord: I'm curious btw, what decompiler did you use? |
| 09:12 | phillord | procyon |
| 09:12 | phillord | https://bitbucket.org/mstrobel/procyon/wiki/Java%20Decompiler |
| 09:13 | phillord | 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 |
| 09:13 | phillord | I should write a lein plugin at some point, come to think of it |
| 09: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 |
| 09:15 | Bronsa | I guess I'll try and see how it deals with that |
| 09:15 | phillord | Oh, it's possible to translate into Java just fine |
| 09:15 | phillord | it just wont run correctly |
| 09:16 | phillord | it's not the bytecodes anyway -- Clojure pushes locals onto the stack, then deletes the locals, then pops their values of the stack |
| 09:17 | phillord | 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. |
| 09:19 | clgv | phillord: you can use luyten as procyon frontend |
| 09:19 | clgv | though the latest and best has no release last time I checked |
| 09:20 | phillord | more interested in just producing a dump of Java files, to be honest -- it's what I normally do |
| 09: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 | justin_smith | 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 | quizdr | (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 | quizdr | 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 | quizdr | what do you think? |
| 10:05 | quizdr | (let [...] (defn ...) (defn ...) etc...) |
| 10:05 | justin_smith | quizdr: that's usually a sign someone has scheme experience |
| 10:06 | justin_smith | 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 | justin_smith | 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 | trap_exit | 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 | trap_exit | 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 | justin_smith | also you end up with a bunch of calls to merge replacing partial |
| 10:10 | justin_smith | I think it's a little uglier too |
| 10:10 | justin_smith | 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 | trap_exit | I mean for all arguments, I don't want to do [arg1-name arg2-name arg3-name] ... |
| 10:11 | trap_exit | 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 | trap_exit | justin_smith: hmm, I've actually never used that feature |
| 10:12 | trap_exit | justin_smith: but now that you mention it, I suddenly find it useful |
| 10:12 | trap_exit | i.e. a helper "iterative" version of a function togerhe with the real function |
| 10:12 | trap_exit | i.e. (reverse lst) (reverse lst iter-results) ... rather than reverse + reverse-helper |
| 10:12 | trap_exit | 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 | justin_smith | 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 | peterdon` | ..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 | justin_smith | ,(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 | justin_smith | don't mind me... |
| 10:29 | cbp | is const actually documented anywhere |
| 10:30 | cbp | 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 | justin_smith | 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 | justin_smith | 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 | phillord | So, consider this code -- http://pastebin.com/1Zmf8iSH -- In my hands, the former is 4x faster than the later |
| 11:14 | phillord | 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 | phillord | 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 | phillord | I presume that it gets inlined at JIT so returning System/out is about as fast as it gets |
| 11:22 | phillord | exemplar in the sense that yes it's something without a necessary read syntax -- I can't just inline at compile time |
| 11:22 | phillord | and :const doesn't work for that reason and for another |
| 11:23 | phillord | 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 | phillord | 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 | vilmibm | if that's what you want. |
| 11:44 | xcthulhu | Oh, sweet |
| 11:45 | xcthulhu | 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 | vilmibm | sure. on its own trapperkeeper is just the service framework + some high level services |
| 11:46 | vilmibm | 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 | {blake} | I thought there was an easy way to do it. I mean, like, a built-in function. |
| 12:05 | {blake} | 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 | justin_smith | 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 | {blake} | mapcat... |
| 12:10 | {blake} | 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 | justin_smith | ,(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 | CookedGryphon | what's that about? |
| 12:13 | CookedGryphon | (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 | justin_smith | 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 | ghadishayban | we used to treat <! >! exceptionally |
| 12:19 | ghadishayban | dnolen_: i have basic feature expressions working on CLJ side with a *read-suppress* thing for unreadable forms. |
| 12:19 | ghadishayban | 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 | ssideris | 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 | ghadishayban | 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 | ghadishayban | 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 | CookedGryphon | i.e. almost all my libraries depend on some version of clojure or other, but clojure-android depends on clojure-jb instead |
| 12:39 | CookedGryphon | how do i stop the other things bringing in their own version without putting an exclude on each of them |
| 12:42 | CookedGryphon | 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 | <ampharmex> Order of operation is variable. |
| 12:44 | ampharmex | <ampharmex> 4^18 * 18! is a non optimal approach. |
| 12:44 | ampharmex | <ampharmex> Some example output: |
| 12:44 | ampharmex | <ampharmex> (7 + (9 + (8 + (7 + (6 + (5 + (4 + (3 + (2 + (5 + (6 + (7 + (3 - (4 + (2 * (4 * (5 - (8 * 7)))))))))))))))))) = 476 |
| 12:44 | ampharmex | <ampharmex> A dynamic programming approach may suffice. |
| 12:44 | ampharmex | <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 | ihodes | 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 | ampharmex | _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 | ampharmex | 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 | eraserhd | "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 | justin_smith | BobSchack: jynx, and you actually had the sauce |
| 12:56 | justin_smith | (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 | technomancy | but something a lot like it probably would |
| 13:04 | technomancy | 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 | bjeanes | 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 | bjeanes | 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 | bjeanes | because... computers. |
| 13:07 | ampharmex | technomancy, is it a dynamic programming solution? |
| 13:08 | ampharmex | 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 | technomancy | 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 | ampharmex | 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 | bjeanes | but i found this out at like 1am |
| 13:29 | bjeanes | 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 | bjeanes | Glenjamin: yeah I am using clj-oauth internally |
| 13:32 | bjeanes | I never needed to use https://github.com/mattrepl/clj-oauth/blob/master/src/oauth/client.clj#L77 to authenticate against Trello |
| 13:32 | bjeanes | #lol |
| 13:37 | technomancy | "OAuth-inspired API product" |
| 13:40 | TimMc | "Inspired by a true API" |
| 13:40 | TimMc | "Made with real OAuth" |
| 13:41 | stompyj | “Now with extra OAuth" |
| 13:41 | bjeanes | hah |
| 13:41 | bjeanes | 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 | bjeanes | 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 | Glenjamin | 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 | bjeanes | it also means that their API allows auth with sessions |
| 13:44 | bjeanes | 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 | justin_smith | 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 | justin_smith | 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 | bridgethillyer | “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 | bridgethillyer | I think I’m having a reading comprehension problem |
| 14:12 | bridgethillyer | 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 | Jaood | bridgethillyer: and return a lazy-seq for you |
| 14:14 | technomancy | needing to call lazy-seq directly is *extremely* rare |
| 14:14 | technomancy | 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 | Jaood | *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 | bridgethillyer | 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 | ambrosebs | 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 | arrdem | 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 | Bronsa | 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 | Bronsa | 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 | ambrosebs | thans |
| 14:36 | ambrosebs | thanks |
| 14:38 | ambrosebs | I'm spitting out a map of file coordinates to types. |
| 14:38 | ambrosebs | 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 | Bronsa | 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 | Bronsa | {:end-column 9, :end-line 1, :column 7, :line 1} |
| 14:45 | Bronsa | ambrosebs: yep ^ |
| 14:45 | ambrosebs | Bronsa: I tried core/read which confused me further :) |
| 14:45 | ambrosebs | 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 | llasram | ,(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 | sdegutis | 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 | sdegutis | 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 | dbasch | 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 | amalloy | 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 | sdegutis | 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 | sdegutis | 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 | arrdem | '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 | Jaood | 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 | Bronsa | 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 | zeeshanlakhani | 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 | gtrak | 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 | dgleeson | does that mean I don't have something set up correctly? |
| 16:00 | dgleeson | oh it's because I didn't have focus on the file correctly |
| 16:00 | dgleeson | DOH |
| 16:00 | dgleeson | cool!! |
| 16:03 | zeeshanlakhani | dgleeson: yay! |
| 16:03 | technomancy | nbeloglazov: what's up? |
| 16:04 | technomancy | 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 | technomancy | 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 | sdegutis | 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 | technomancy | 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 | technomancy | anyway I only paste using my elisp-powered paste site so there |
| 16:29 | sdegutis | Why not write it in Clojure? |
| 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:38 | arrdem | ⊄ |
| 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 | technomancy | 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 | johncash | 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 | technomancy | 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 | jarosti | somelatex |
| 16:56 | jarosti | ewline |
| 16:56 | jarosti | withnewline |
| 16:56 | technomancy | or `lein with-profile base+test repl` |
| 16:57 | technomancy | 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 | Glenjamin | 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 | technomancy | 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 | Glenjamin | 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 | technomancy | 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 | Glenjamin | 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 | petehunt | 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 | Glenjamin | 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 | stompyj | 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 | xeqi | 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 | petehunt | 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 | dbasch | 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 | petehunt | 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 | stompyj | 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 | petehunt | publicly |
| 17:15 | petehunt | it already won out internally |
| 17:15 | petehunt | most people are obsessed with syntax though |
| 17:15 | petehunt | 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 | wackyvorlon | 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 | gtrak | 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 | amalloy | 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 | wackyvorlon | It's been a while since I used it. |
| 17:23 | wackyvorlon | 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 | amalloy | 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 | gtrak | user roles |
| 17:27 | gtrak | 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 | sdegutis | 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 | gtrak | 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 | arrdem | 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 | amalloy | 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 | Glenjamin | <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 | Glenjamin | see https://github.com/xeqi/kerodon/blob/master/test/kerodon/unit/impl.clj#L56 onwards for checkboxes |
| 17:36 | Glenjamin | 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 | sdegutis | 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 | sdegutis | 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 | sdegutis | ,*ns* |
| 17:44 | clojurebot | #<Namespace sandbox> |
| 17:45 | sdegutis | (let [x (def foo)] (= x (clojure.lang.Var$Unbound. #'sandbox/foo)) |
| 17:45 | sdegutis | ,(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 | egghead | ,(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 | shriphani | is* |
| 18:08 | shriphani | 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 | justin_smith | shriphani: but what version did it give you? |
| 18:11 | justin_smith | did you check? |
| 18:11 | shriphani | and I have 2.8 specified in project.clj which is the latest version |
| 18:11 | shriphani | 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 | shriphani | thats my 3 files. |
| 18:24 | shriphani | well one of those is a repl output but yeah |
| 18:25 | amalloy | shriphani: .clean doesn't return the cleaner object |
| 18:25 | amalloy | 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 | amalloy | 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 | arrdem | 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 | cespare | (fn ...) is also an anonymous function |
| 20:25 | Jaood | function literal |
| 20:25 | danielcompton | Anonymous function literal |
| 20:25 | danielcompton | 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 | trap_exit | but both very clever |
| 20:41 | trap_exit | 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 | trap_exit | I like the delay way better |
| 20:42 | trap_exit | 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 | trap_exit | writing cljs code |
| 20:42 | trap_exit | 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 | trap_exit | 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 | trap_exit | why does SO not hcarge peopl e$9.99 / month ? |
| 20:43 | trap_exit | I'd pay $9.99 / month |
| 20:43 | trap_exit | to have the ability to fucking ignore dumbass users |
| 20:43 | trap_exit | knowing that every time they create a new account, it costs them $9.99 / month |
| 20:44 | trap_exit | 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 | trap_exit | is completely badass |
| 20:45 | trap_exit | amalloy: I'm seriously considering doing so |
| 20:45 | trap_exit | but have not ifgured out a way to get initial users |
| 20:45 | locks | or just pull a Quora |
| 20:45 | locks | and go bankrupt because the UX is ass |
| 20:45 | trap_exit | well, Quora solves a different problem |
| 20:45 | trap_exit | "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 | rpaulo | 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 | danielcompton | 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 | Frozenlock | 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 | danielcompton | 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 | kenrestivo | 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 | Frozenlock | 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 | Frozenlock | Oh I wonder if I disordered my middlewares |
| 22:52 | Frozenlock | 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 | White_Flame | instead of load source code from existing files |
| 23:15 | White_Flame | 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 | dbasch | 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 | White_Flame | 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 | dbasch | once you use leiningen you can disregard it |
| 23:23 | Frozenlock | godfuckingdamnit |
| 23:23 | Frozenlock | zerokarmaleft: you did patch it, but for the snapshot version |
| 23:23 | Frozenlock | 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 | Frozenlock | 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 | technomancy | 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 | TerranceWarrior | having many that is |
| 23:34 | TerranceWarrior | 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 | Frozenlock | 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 | White_Flame | 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 | TerranceWarrior | implementation is fact. |
| 23:41 | TerranceWarrior | 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 | technomancy | undoubtedly by accident |
| 23:45 | TerranceWarrior | with banks realtime usually isn't an issue. it's stuff like reports that need optimization. |
| 23:45 | TerranceWarrior | 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 | technomancy | 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 | White_Flame | 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 | White_Flame | 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 | White_Flame | because I was certainly doing clusters with individual machine downtime in the 90s |
| 23:52 | White_Flame | 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 | technomancy | 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 | White_Flame | -open |
| 23:55 | White_Flame | just different architectures connecting to different services |
| 23:55 | technomancy | the need for fault-tolerance in data centers has risen a lot |
| 23:56 | technomancy | 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 | TerranceWarrior | oh whatever, meds talking. |