2015-04-12
| 00:46 | lexi-lambda | Are any of Trammel, clojure-contracts, or core.contracts commonly used? |
| 00:47 | LaVidaPortland | Not that I've seen, but I'm pretty new to clojure. |
| 00:48 | lexi-lambda | What is the usual way of ensuring preconditions, then? |
| 00:48 | lexi-lambda | I.e., if I have a function that requires a string, what's the idiomatic way to guard against something else getting passed in? |
| 00:50 | LaVidaPortland | Not sure, but what about using type hints for that scenario? |
| 00:50 | lexi-lambda | Of course, the usual Java approach for non-type-based preconditions would be if (n < 0) throw something;, but that seems like clutter compared to a good contracts system. |
| 01:31 | nuwanda_ | lexi-lambda: you could use :pre to test the args type |
| 01:48 | justin_smith | hell, I've seen "if we're counting the number of elements in a linked list, and this is the last element, throw something" in java |
| 01:51 | adu | justin_smith, wut |
| 01:51 | justin_smith | adu: it was in the .length method for LinkedList in an old openjdk |
| 01:51 | justin_smith | hell, it may still be there |
| 01:59 | adu | justin_smith, there is no length method for LinkedList |
| 01:59 | adu | justin_smith, did you mean size()? |
| 02:06 | justin_smith | adu: clearly I misremembered |
| 04:08 | Fare | is there a disassembler to look at the JVM bytecode produced by clojure? |
| 04:10 | TEttinger | Fare: javap should be included with your JDK |
| 04:10 | TEttinger | http://www.theserverside.com/news/1363881/The-Working-Developers-Guide-to-Java-Bytecode |
| 04:11 | Fare | I'd like to see how much better the code is than a naive interpreter... and maybe convince colleagues to rely on that technology instead of reinventing it, badly |
| 04:12 | TEttinger | oh wow |
| 04:16 | Fare | wow? |
| 04:19 | TEttinger | Fare, it's just that seems like a very bad idea to try to make your own interpreter from scratch when you already have a repl for clojure that actually does benefit from the JIT |
| 04:20 | TEttinger | unless it adds some very much-needed features |
| 04:20 | sveri | ambrosebs: ping |
| 04:20 | Fare | well, the interpreter is not exactly for clojure |
| 04:20 | TEttinger | ah |
| 04:20 | Fare | but I'm writing a compiler in clojure targetting clojure |
| 04:20 | TEttinger | could it be written as an internal DSL? |
| 04:21 | Fare | not sure what you mean. |
| 04:21 | Fare | The source language is some python-like language |
| 04:22 | TEttinger | internal DSL as in, a domain specific language that's made with macros or whatever but ends up, once macroexpanded, as perfectly viable source in another language (hopefully clojure) |
| 04:22 | TEttinger | ah |
| 04:22 | Fare | and it has to integrate into a java application. |
| 04:22 | TEttinger | ah. |
| 04:23 | TEttinger | sounds like "fun" |
| 04:23 | Fare | "indeed" |
| 04:23 | TEttinger | the compiler sounds like the best option by far |
| 04:23 | Fare | duh |
| 04:25 | TEttinger | if you can maybe figure out a way to compile in separate units of code (like a method that corresponds to a single form in clojure), you could call your compiler on such a unit of code and pass it in to a running clojure repl |
| 04:26 | Fare | coming from CL, I really enjoy the clojure data model and its concurrency model. I think its paucity of control structures sucks, though. |
| 04:26 | Fare | it's a survivable suckiness, especially with higher-order functions, but still. |
| 04:27 | Fare | I understand that direct integration with the substrate language "justifies" this paucity, but it still hurts. |
| 04:27 | TEttinger | so they type in, myFoo = "bar"<hits enter> then your compiler compiles that to your clojure equivalent, say, (def myFoo (atom "bar")), thrusts it into the repl, and runs it |
| 04:27 | Fare | basically |
| 04:28 | TEttinger | I haven't had any issues with a lack of control structures tbh |
| 04:28 | Fare | though a compiler is only interesting if the compiled files are cached. |
| 04:28 | Fare | if it were a run-once kind of thing, the interpreter would make more sense. |
| 04:28 | TEttinger | right, this might have to be a separate thing huh |
| 04:28 | TEttinger | having macros does make control structures fairly convenient to work with though |
| 04:29 | Fare | yes, macros and higher-order functions help survive that. |
| 04:29 | TEttinger | I'm not sure if you mean something different from doseq, for, loop/recur, etc. |
| 04:30 | Fare | and you can emulate delimited continuations in userland. But then, you can't interact well with other people's code, and pay a hefty price in performance. |
| 04:32 | Fare | compared to CL's loop's, its lexical block/return, or (yuck) tagbody/go, clojure is a bit poor. But yes, it does make it up in other ways. |
| 04:33 | Fare | handler-bind is also a big thing I miss from CL. Not obvious how you'd do it on the JVM though |
| 09:29 | sobel | justin_smith: btw i found my emacs package issue. melba repo had to be manually added. |
| 10:12 | sobel | d'oh. calling System/exit affects my repl. |
| 10:22 | justin_smith | you don't say? |
| 10:24 | justin_smith | sobel: System/exit is how I usually shut down my vm |
| 10:31 | justin_smith | $mail Fare many people use no.disassemble to read the clojure bytecode output, and also the bytecode is generated with a lib called asm |
| 10:31 | lazybot | Message saved. |
| 10:42 | matthavard | I'm using the byte-streams library (https://github.com/ztellman/byte-streams) to read a file into a byte array. In my file, foo.html, there is a character/byte that has a value of 0x92 (146 decimal), which I have verified using a hex editor, but if I do `(map int (to-byte-array (java.io.File. "foo.html")))`, the integer at the corresponding position of the character is -110 |
| 10:43 | justin_smith | matthavard: there are no unsigned bytes in java |
| 10:44 | matthavard | Hah yeah I just thought about that. It overflows to -100 |
| 10:44 | justin_smith | ,(- 146 127) |
| 10:44 | matthavard | *-110 |
| 10:44 | clojurebot | 19 |
| 10:45 | justin_smith | matthavard: yeah. The no unsigned thing makes java stuff with bytes a little painful sometimes. |
| 10:45 | justin_smith | it's the same 8 bits... |
| 10:46 | justin_smith | there's probably a good trick for taking a byte and returning the int you would get for those 8 bit values, with all other bits being 0 |
| 10:46 | justin_smith | ,(bit-and -128 256) |
| 10:46 | clojurebot | 256 |
| 10:46 | matthavard | ,(bit-and -128 -110) |
| 10:46 | clojurebot | -128 |
| 10:47 | afhammad | can someone take a look at this compile time error for me, its probably something silly https://www.refheap.com/99531 |
| 10:47 | justin_smith | ,(bit-and -110 256) |
| 10:47 | clojurebot | 256 |
| 10:47 | justin_smith | ergh |
| 10:47 | justin_smith | oh, two's complement |
| 10:47 | justin_smith | ,(bit-and (bit-xor -110 256) 256) |
| 10:47 | clojurebot | 0 |
| 10:47 | justin_smith | anyway, I bet there is some trick, maybe after I wake up more |
| 10:51 | justin_smith | ,(defn uns [b] (if (pos? b) b (dec (* -1 (bit-xor b 255))))) |
| 10:51 | clojurebot | #'sandbox/uns |
| 10:51 | Uruviel | Hey! I'm using the Buddy wrap-access-rules. Currently I have a seq of rules like [{:uris ["/projects/:project-id"] :handler owns-project?}], but when inspecting the request map in owns-project? the project-id is not in the params (it's empty, in fact) |
| 10:51 | justin_smith | ,(uns -110) |
| 10:51 | clojurebot | 146 |
| 10:51 | justin_smith | matthavard: ^ |
| 10:51 | Uruviel | is there a way to make buddy-auth parse out the params? |
| 10:52 | justin_smith | matthavard: definition for "uns" is up there if you scroll up a little |
| 10:57 | matthavard | thanks justin_smith |
| 10:57 | matthavard | uns for un-sign? |
| 10:57 | justin_smith | haha, yeah |
| 10:57 | justin_smith | terrible name |
| 10:58 | justin_smith | but better for a one liner |
| 10:58 | matthavard | ha it's great. |
| 10:58 | matthavard | ,(uns -110) |
| 10:58 | clojurebot | #error{:cause "Unable to resolve symbol: uns in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: uns in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: uns in this context", :at [clojure.l... |
| 10:59 | justin_smith | matthavard: clojurebot unloads definitions fast |
| 10:59 | matthavard | ,(sandbox/uns -110) |
| 10:59 | clojurebot | #error{:cause "No such var: sandbox/uns", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: No such var: sandbox/uns, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "No such var: sandbox/uns", :at [clojure.lang.Util runtimeException "Util.java" 221]}], :trace [[clojure.... |
| 10:59 | justin_smith | ,(defn uns [b] (if (pos? b) b (dec (* -1 (bit-xor b 255))))) |
| 10:59 | clojurebot | #'sandbox/uns |
| 10:59 | matthavard | ,(uns -110) |
| 10:59 | clojurebot | 146 |
| 10:59 | matthavard | ha awesome |
| 10:59 | justin_smith | with a little extra fiddling, it could take an optional bit-count arg |
| 10:59 | justin_smith | to work on shorts, ints, longs |
| 11:02 | justin_smith | hmm, shorts and ints is easy, longs is tricky... |
| 11:04 | matthavard | Is there a way to read 0x92 as a unicode character and get the correct value? 0x92 is unicode for some weird right quote thing, and I'm trying to convert all non-ascii characters to html entities like "’" |
| 11:06 | matthavard | like (let [c (int (unicode (get-char-from-file-somehow)))]) |
| 11:07 | TEttinger | matthavard: ##(char 0x92) |
| 11:07 | lazybot | ⇒ \ |
| 11:07 | TEttinger | matthavard: ##(char 0xa2) |
| 11:07 | lazybot | ⇒ \¢ |
| 11:10 | justin_smith | matthavard: if you convert the byte-array to string, and map int across the string |
| 11:11 | justin_smith | when you create the string, there is an optional encoding arg (with clojure it defaults to utf-8 which is almost always the right thing in my experience) |
| 11:12 | matthavard | That would not be the standard str function would it? |
| 11:12 | TEttinger | ,(def some-bytes (byte-array (vec "hello"))) |
| 11:12 | clojurebot | #error{:cause "java.lang.Character cannot be cast to java.lang.Number", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Number, compiling:(NO_SOURCE_FILE:0:0)", :at [clojure.lang.Compiler$StaticMethodExpr eval "Compiler.java" 1696]} {:type java.lang.ClassCastException, :message "java.lang.Character cannot... |
| 11:12 | justin_smith | matthavard: String |
| 11:12 | justin_smith | ,(get-bytes "hello") |
| 11:12 | clojurebot | #error{:cause "Unable to resolve symbol: get-bytes in this context", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Unable to resolve symbol: get-bytes in this context, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "Unable to resolve symbol: get-bytes in this contex... |
| 11:13 | justin_smith | ,(.getBytes "hello") |
| 11:13 | clojurebot | #object["[B" "[B@41e6be86"] |
| 11:13 | TEttinger | there we go |
| 11:13 | justin_smith | ,(String. (.getBytes "hello")) |
| 11:13 | clojurebot | "hello" |
| 11:13 | TEttinger | ,(String. (.getBytes "hello\u0092")) |
| 11:13 | clojurebot | "hello" |
| 11:13 | TEttinger | ,(String. (.getBytes "hello\u00a2")) |
| 11:13 | clojurebot | "hello¢" |
| 11:13 | TEttinger | there we go |
| 11:13 | justin_smith | and you can map int on that |
| 11:13 | justin_smith | to get the int values of each char (not byte) |
| 11:14 | TEttinger | ,(map int (String. (.getBytes "hello\u0092"))) |
| 11:14 | clojurebot | (104 101 108 108 111 ...) |
| 11:14 | TEttinger | ,(map int (String. (.getBytes "hey\u0092"))) |
| 11:14 | clojurebot | (104 101 121 146) |
| 11:14 | justin_smith | and the circle is complete! |
| 11:14 | matthavard | So how do I get from file object to string? |
| 11:15 | justin_smith | matthavard: we just showed you how to get from byte-array to string |
| 11:15 | matthavard | oh oops |
| 11:15 | justin_smith | you can already get byte-array from a file |
| 11:15 | justin_smith | there is also slurp |
| 11:15 | justin_smith | that directly gives a string from a file |
| 11:16 | TEttinger | (doc slurp) |
| 11:16 | clojurebot | "([f & opts]); Opens a reader on f and reads all its contents, returning a string. See clojure.java.io/reader for a complete list of supported arguments." |
| 11:16 | TEttinger | the arguments can include an encoding |
| 11:16 | mbac | has some helpful fellow done the work of writing their own clojure photo gallery generator? |
| 11:18 | matthavard | justin_smith: So theoretically (map int (String. (to-byte-array (java.io.File. "foo.html")))) should work? |
| 11:18 | matthavard | and/or TEttinger |
| 11:18 | TEttinger | (map int (slurp "foo.html")) |
| 11:18 | justin_smith | matthavard: or (map int (slurp "foo.html")) |
| 11:18 | TEttinger | :D |
| 11:19 | justin_smith | heh |
| 11:20 | matthavard | And you were saying there's a way to set the encoding with that? Because that's giving me 65533 for bytes larger than 127 |
| 11:20 | justin_smith | (slurp "foo.html" :encoding "something") |
| 11:21 | justin_smith | matthavard: supported encodings are http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html |
| 11:21 | justin_smith | ~supported encodings is http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html |
| 11:21 | clojurebot | A nod, you know, is as good as a wink to a blind horse. |
| 11:21 | justin_smith | ~supported encodings |
| 11:21 | clojurebot | supported encodings is http://docs.oracle.com/javase/8/docs/technotes/guides/intl/encoding.doc.html |
| 11:21 | TEttinger | ~supported |
| 11:21 | clojurebot | I don't understand. |
| 11:32 | film42424 | I have a code style question. |
| 11:34 | film42424 | I really want to add default vars to a record, but I want to be able to introspect those, so reify doesn't seem like a good option. I ended up with something like this: https://github.com/film42/rinok/blob/f5ea4c666be270e327c83582e07d2067ba05bc09/src/rinok/engine.clj#L63-L68 |
| 11:34 | film42424 | I'm sure the whole thing could be more idiomatic, so maybe there's a larger problem |
| 11:34 | film42424 | Would love any kind of insight |
| 11:35 | justin_smith | film42424: the normal thing is to just create a function that manages your defaults, and not use the constructor directly |
| 11:35 | justin_smith | which looks like what you are doing |
| 11:35 | film42424 | yeah, I just mocked it to look like a standard record constructor |
| 11:36 | justin_smith | well, you actually replaced the automatically generated constructor function |
| 11:36 | film42424 | since won't actually take any args, I always know what to give it. Just seems awful to override the constructor |
| 11:36 | film42424 | yeah |
| 11:36 | justin_smith | see also map->MatchingEngine |
| 11:36 | justin_smith | which is also automatically generated |
| 11:38 | film42424 | Oh wow, I didn't know about map->MatchingEngine |
| 11:41 | silasdavis | hello clojure, I'm failing to bind the dynamic vars *client-id* and *client-secret* in https://github.com/mochify/hiroba/blob/master/src/mochify/hiroba/rest.clj |
| 11:42 | silasdavis | I think i've just forgotten how to clojure |
| 11:42 | silasdavis | I've set globar-vars in my project.clj |
| 11:42 | silasdavis | also used binding |
| 11:42 | silasdavis | i'm using fully-qualified name |
| 11:42 | silasdavis | how should I be setting these? |
| 11:42 | matthavard | TEttinger, justin_smith: Update, looks like any of the ISO8859_* encodings work! |
| 11:43 | TEttinger | woo! |
| 11:43 | matthavard | Just went down the list and tried them one by one haha |
| 11:45 | film42424 | silasdavis: What happens if you actually set them in your shell? |
| 11:47 | film42424 | Oh I guess that's not how environ works |
| 11:55 | mbac | luminus is pretty shiny |
| 11:58 | noncom|2 | mbac: true |
| 11:58 | Uruviel | https://github.com/funcool/buddy/issues/31 |
| 12:28 | mbac | is the .html template format in luminus the same as the one in python django? |
| 12:29 | mbac | Selmer is a templating language similar to Django and Rails templates. If you're familiar with Django or similar templating languages you should feel right at home. |
| 12:29 | mbac | awesome! |
| 12:29 | mbac | this framework is filling me with entrepreneurial zeal |
| 12:30 | sobel | haha |
| 12:30 | sobel | that is hilarious/familiar |
| 12:44 | tomjack | I think Selmer's readme could use a "why?" section |
| 12:47 | justin_smith | tomjack: like why use Selmer when there's Integer/MAX_VALUE other options? |
| 13:01 | tomjack | well, I don't go in for those questions too much, I mostly look at the thing itself |
| 13:02 | tomjack | basically "why would I (Clojure programmer) want to use Django-inspired templates?" |
| 13:03 | justin_smith | tomjack: in my experience there is a very productive collaboration when you have a front-end person who knows html,css,js and a back end person who does clojure,devops and the selmer template is where the two meet |
| 13:04 | tomjack | yeah, I kind of imagined that's what it's meant for |
| 13:04 | justin_smith | so it needs to comprehensible and powerful for the frontend person to get their stuff done, while also providing access to what the backend can provide |
| 13:04 | justin_smith | *needs to be |
| 13:04 | tomjack | like "for when you're forced to use something like Django-inspired templates" |
| 13:04 | justin_smith | haha |
| 13:05 | justin_smith | more like, when the front end folks don't know any clojure, but sure |
| 13:06 | tomjack | but if the author would use these templates when writing an entire project on their own, I'd also like to hear why. but it's also fine to have a readme which assumes the reader already wants X, so doesn't explain why one might want X |
| 13:08 | _1_guddu | hy |
| 13:09 | _1_guddu | dm3 |
| 13:31 | dwysocki | I'm having a problem that's probably just ignorance on my part |
| 13:31 | dwysocki | I'm using miner/tagged to save a record to a file in EDN format |
| 13:31 | dwysocki | When I parse it from the file, it properly resolves the type, with the fully-qualified namespace |
| 13:31 | dwysocki | but then the type is no longer considered equal its non-fully qualified form |
| 13:31 | dwysocki | so (= Foo my-ns/Foo) is false |
| 13:31 | dwysocki | I'm not really sure what to do at this point |
| 13:32 | dwysocki | it's causing my multimethods to fail to recognize the type |
| 13:38 | tomjack | that doesn't make sense to me |
| 13:38 | tomjack | either (identical? Foo my-ns/Foo) or not |
| 13:38 | tomjack | if not, why not? |
| 13:38 | tomjack | if not, you have two different Foo and it's getting the wrong one? |
| 13:40 | tomjack | actually.. |
| 13:40 | tomjack | what is even my-ns/Foo |
| 13:40 | justin_smith | dwysocki: did you run defrecord twice? |
| 13:40 | justin_smith | reloading files that contain defrecord can lead to this sort of thing |
| 13:40 | justin_smith | if you have instances created with the prior defrecord before the reload |
| 13:41 | justin_smith | tomjack: because they mention a tagged reader I would assume a defrecord or maybe deftype |
| 13:41 | dwysocki | defrecord should only be run once |
| 13:41 | tomjack | defrecord doesn't define a var |
| 13:41 | tomjack | well, not that var |
| 13:42 | tomjack | if it's the class my-ns.Foo, then it should be the same class as Foo, or else the problem is that there are two Foo :) |
| 13:42 | dwysocki | I made a CLI that starts a separate instance of my program each time |
| 13:43 | dwysocki | so I can do `my-program write | my-program read` |
| 13:43 | justin_smith | tomjack: the issue with re-running defrecord has nothing to do with vars. It's that you get two different classes with the same name. |
| 13:43 | tomjack | sure, I didn't expect it was a re-running defrecord issue |
| 13:43 | tomjack | just "(= Foo my-ns/Foo)" doesn't make sense |
| 13:44 | justin_smith | ahh, that is looking at a var |
| 13:44 | justin_smith | right |
| 13:44 | dwysocki | actually, it might be a re-running defrecord issue |
| 13:44 | dwysocki | I'm running my program from a jar |
| 13:45 | dwysocki | and it's spinning up twice |
| 13:45 | dwysocki | the first time writes something in EDN to stdout |
| 13:45 | dwysocki | the second time reads it from stdin |
| 13:45 | justin_smith | dwysocki: with defrecord my-ns/Foo shouldn't even get created (though my_ns.Foo should) |
| 13:46 | tomjack | it shouldn't matter.. I suggest taking a look at some instances which don't work with your defmethods, and comparing their classes to instances which do work. |
| 13:46 | dwysocki | it actually is my_ns.Foo, sorry |
| 13:46 | dwysocki | although |
| 13:46 | dwysocki | when it's written to stdout, it uses hyphens |
| 13:46 | dwysocki | oddly |
| 13:47 | dwysocki | but when it's read, they've been replaced with underscores |
| 13:47 | justin_smith | does the tagged literal with hyphens get reloaded properly? |
| 13:47 | dwysocki | it looks like it does |
| 13:47 | justin_smith | one thing you could test is whether a single instance can generate the string for the edn, and then read it and get the same result back |
| 13:47 | dwysocki | that's a good idea |
| 13:48 | justin_smith | eliminating variales yo |
| 13:48 | dwysocki | yup |
| 13:51 | tomjack | hmm |
| 13:51 | tomjack | hypothesis: you're getting miner.tagged/TaggedValue |
| 13:52 | tomjack | try it with a namespace that doesn't have hyphens :) |
| 13:52 | justin_smith | dwysocki: and if that works, next step is double checking that the reading side has loaded the ns that defines that record |
| 13:52 | dwysocki | no, i'm not getting miner.tagged/TaggedValue |
| 13:52 | dwysocki | that was my first thought |
| 13:52 | tomjack | ah, missed this: https://github.com/miner/tagged/blob/master/src/miner/tagged.clj#L87 |
| 13:52 | dwysocki | I'm testing whether (= (class x) (class (parsed-x))) right now |
| 13:53 | dwysocki | oh fuq |
| 13:53 | dwysocki | it's not = |
| 13:53 | tomjack | too bad he has to munge classnames :( |
| 13:54 | dwysocki | I'm wondering now whether I should just write the map to a file, and assume it's always that type |
| 13:54 | tomjack | not =, but has the same name? |
| 13:54 | dwysocki | yeah, looks like the same name |
| 13:55 | justin_smith | dwysocki: that's weird |
| 13:55 | justin_smith | so (not= x (read-string (pr-str x))) |
| 13:56 | dwysocki | precisely |
| 13:56 | justin_smith | that's messed up |
| 13:56 | justin_smith | what about (= (read-string (pr-str x)) (read-string (pr-str (read-string (pr-str x))))) |
| 13:56 | tomjack | gotta be a defrecord-multiple-times error? |
| 13:57 | dwysocki | ooh, I'll try that one |
| 13:57 | justin_smith | if that's a yes, then yeah my initial hunch about multiple defrecord loads is probably it |
| 13:58 | justin_smith | if it's a no, that is maybe a defrecord bug? |
| 13:58 | dwysocki | it's false :\ |
| 13:58 | dwysocki | unless I mistyped |
| 13:58 | justin_smith | sounds like a bug in either the printing or reading side of records... |
| 13:58 | justin_smith | weird! |
| 13:59 | dwysocki | or this library I put my trust in |
| 13:59 | tomjack | if you run (class (read-string (pr-str x))) over and over, do you get a different class every time? |
| 13:59 | justin_smith | tomjack: oooh, good call |
| 13:59 | tomjack | that would be nuts |
| 13:59 | tomjack | I can't imagine how.. |
| 13:59 | dwysocki | maybe I'm just doing something stupid |
| 14:00 | dwysocki | wouldn't be the first time |
| 14:00 | dwysocki | nor the last |
| 14:00 | justin_smith | "programmer's program does not work, but only because they did something stupid, news at 11" |
| 14:01 | dwysocki | history in the making |
| 14:03 | dwysocki | huh |
| 14:03 | dwysocki | so when I encode it the second time and on |
| 14:03 | dwysocki | the type is miner.tagged.TaggedValue |
| 14:03 | dwysocki | but not the first |
| 14:03 | tomjack | miner/tagged has this lovely 'feature' that the record tags are handled by the default tag reader, and there is a global fallback |
| 14:03 | justin_smith | dwysocki: what's the repo for miner? |
| 14:04 | dwysocki | https://github.com/miner/tagged |
| 14:04 | tomjack | apparently there is some problem with the round-tripping of the record class/factory info for you |
| 14:04 | tomjack | so the record handlers fail and it defaults to TaggedValue, confusingly printed with the same (or almost the same?) tag? |
| 14:05 | justin_smith | dwysocki: and you are using the reader that miner provides? |
| 14:05 | dwysocki | yes |
| 14:05 | dwysocki | so |
| 14:06 | dwysocki | I override print-method on my record type to call (tag/pr-tagged-record on this w) |
| 14:06 | dwysocki | but if it's not seeing that the types are the same |
| 14:06 | dwysocki | it's going to default to the standard print-method |
| 14:07 | dwysocki | which prints the type as my_ns.Foo, instead of my_ns/Foo |
| 14:07 | dwysocki | and that's why the 2nd iteration and on are all of type TaggedValue |
| 14:08 | dwysocki | I think I've spent too long on this problem :P I should just give up and save a standard map |
| 14:08 | tomjack | I suspect the functionality there, which could have been easily added to Clojure core, wasn't added for a very good reason :) |
| 14:08 | dwysocki | and parse it into my record, which is almost trivial |
| 14:08 | dwysocki | this was supposed to be the easy part of what I did this weekend, lol |
| 14:10 | dwysocki | I think I'll actually just use the built-in edn reader, and inspect the tag |
| 14:10 | dwysocki | there are only 2 types I ever expect to see |
| 14:11 | justin_smith | dwysocki: a :type key added to a map should do it |
| 14:12 | dwysocki | yup |
| 14:12 | dwysocki | damned type systems |
| 14:13 | justin_smith | serialization is hard |
| 14:13 | dwysocki | I thought I'd finally found a case where a defrecord would be sensible |
| 14:13 | dwysocki | probably could have just added a :type key |
| 14:13 | justin_smith | my primary usage of defrecord has been in combination with protocols |
| 14:14 | dwysocki | I've just been using it with defmethods |
| 14:14 | dwysocki | that do slightly different things on my 2 types |
| 14:14 | justin_smith | it's easy to convert those to look at a :type tag |
| 14:14 | justin_smith | of course |
| 14:14 | dwysocki | yeah |
| 14:14 | dwysocki | I realize that now haha |
| 14:15 | dwysocki | ugh, I don't want to change all this code now |
| 14:53 | dwysocki | welp, I'm finally record-free |
| 15:41 | wagjo | ,(clojure-version) |
| 15:41 | clojurebot | "1.7.0-master-SNAPSHOT" |
| 16:18 | Shayanjm | For anyone who's interested, here's the (spherical) haversine formula implemented in clj: https://gist.github.com/shayanjm/39418c8425c2a66d480f |
| 16:19 | the-kenny | Shayanjm: you might want to pull out some more stuff like (Math/sin (/ dlon 2)) into the let. There's also Math/exp |
| 16:19 | Shayanjm | the-kenny: Very good call |
| 16:19 | Shayanjm | one min, refactoring |
| 16:20 | dwysocki | also, newlines |
| 16:20 | Shayanjm | dwysocki: I don't ever know where to break lines in big mathy implementations :\ |
| 16:20 | dwysocki | I would do it for the arguments to the initial + |
| 16:21 | dwysocki | so I don't have to scroll :P |
| 16:22 | dwysocki | and when I say "initial +", I guess I mean "the only +" |
| 16:33 | zirman | I've been trying to understand y combinator. I had a version that computed factorial that I reworked it into a different form. Is it still essentially a y combinator? Thanks. |
| 16:33 | zirman | function y(y) { |
| 16:33 | zirman | return function (n) { |
| 16:33 | zirman | return n === 0 ? 1 : n * y(y)(v)(n - 1); |
| 16:33 | zirman | } |
| 16:33 | zirman | } |
| 16:33 | zirman | y(y)(5); |
| 16:34 | zirman | oops |
| 16:34 | zirman | this is what I meant |
| 16:34 | zirman | function y(y) { |
| 16:34 | zirman | return function (n) { |
| 16:34 | zirman | return n === 0 ? 1 : n * y(y)(n - 1); |
| 16:34 | zirman | } |
| 16:34 | zirman | } |
| 16:34 | zirman | y(y)(5); |
| 16:38 | Frozenlock | zirman: refheap.com |
| 16:38 | oddcully | your javascript made dnolen timeout |
| 16:39 | zirman | sorry |
| 16:39 | dwysocki | haha, I've encountered yet another serialization issue |
| 16:39 | dwysocki | how do you serialize Double/NEGATIVE_INFINITY? |
| 16:39 | dwysocki | because it's getting output as -Infinity, and parsed as a symbol |
| 16:40 | zirman | https://www.refheap.com/99541 |
| 16:51 | dwysocki | I suppose the -Infinity issue is taken care of in tools.reader |
| 17:12 | LaVidaPortland | zirman, that's some strange looking clojure. :) |
| 17:12 | sandbags | cfleming: ping ... don't suppose you're an Overtone user? |
| 17:13 | cfleming | sandbags: Pong... no, I'm not. I think I know the next question, though :) |
| 17:13 | TEttinger | sandbags, I'm curious about Overtone, does something in the livecoding break in Cursive? |
| 17:13 | TEttinger | I have only used at-at from Overtone, which is definitely nice |
| 17:14 | sandbags | cfleming: i just tweeted a screenshot of some code in cursive |
| 17:14 | sandbags | cfleming: it works but cursive seems unhappy |
| 17:14 | cfleming | TEttinger sandbags: It's not the live coding, it's the way the symbols are generated: https://github.com/cursiveclojure/cursive/issues/774 |
| 17:14 | cfleming | sandbags: Yeah overtone makes Cursive sad |
| 17:15 | sandbags | so if i pull in overtone.core will that fix things? |
| 17:15 | sandbags | oh wait, i see, no |
| 17:16 | cfleming | sandbags: There's some hope that I might be able to fix that using stub generation, but that requires more time than I have right now. |
| 17:16 | cfleming | sandbags: However stub generation is also required for datomic to work nicely, so I'll do it at some point. |
| 17:16 | sandbags | okay so basically overtone is too-much-voodoo |
| 17:16 | sandbags | i mean, it's not a problem as is |
| 17:16 | cfleming | More or less, yeah |
| 17:16 | sandbags | it works |
| 17:17 | sandbags | oh one thing i could really use, is there a way to write a macro to send to the REPL? |
| 17:17 | cfleming | sandbags: Sure, you could just turn off the unresolved symbols warning. |
| 17:17 | sandbags | i wrote a macro but of course it's just inserting wherever the cursor has focus |
| 17:17 | cfleming | sandbags: https://github.com/cursiveclojure/cursive/issues/85 |
| 17:18 | zirman | LaVidaPortland: not clojure but it has closures |
| 17:18 | cfleming | (which is a polite way of saying no) |
| 17:18 | sandbags | cfleming: yeah, awkward |
| 17:19 | cfleming | sandbags: You could fudge a macro if you assign a Cmd-number sequence to the REPL toolwindow - then you could start your macro with that key, which will jump to the REPL toolwindow. |
| 17:19 | sandbags | but in that don't you say that will close it if the REPL is already open? |
| 17:19 | cfleming | It'll close it if that toolwindow is already selected |
| 17:20 | cfleming | So if you're in a normal editor it will do what you want |
| 17:20 | sandbags | right, i think because i am switching back and forth that's likely to be annoying too often |
| 17:21 | cfleming | sandbags: Ok. I'll look into fixing that issue, it's been open for ages and it's a popular request. |
| 17:21 | sandbags | i'd hoped IDEA was a little more controllable |
| 17:21 | sandbags | but the macros look pretty rubbish |
| 17:21 | cfleming | sandbags: It'll be post-Clojure/West though. |
| 17:21 | nicferrier | could a lein project generate more than one main class? |
| 17:21 | nicferrier | if I just put gen-class in the ns decl does that make it a main? |
| 17:21 | sandbags | cfleming: would it be possible to script IDEA in Clojure(Script) using Cursive at some point? |
| 17:22 | sandbags | i mean it's Java... |
| 17:22 | cfleming | sandbags: Yeah, I'm planning that |
| 17:22 | sandbags | nice |
| 17:23 | sandbags | do you get any support from JetBrains... actually do you work for JetBrains? :) |
| 17:24 | cfleming | nicferrier: Sure - you can only have one per ns AFAIK, but you can have many namespaces with main functions, no problem. I think you can only specify one in project.clj to work with lein run, though |
| 17:24 | nicferrier | cfleming: right. thanks. |
| 17:25 | cfleming | sandbags: No, I don't, but they're fairly helpful. I have one mole there who helps a lot because he's a Clojure fan, and they're more helpful in general as Cursive gets more popular. |
| 17:25 | sandbags | so, labour of love |
| 17:25 | sandbags | impressive what you've done |
| 17:26 | sandbags | i was cautiously happy with LightTable but since i managed to get Cursive installed I've not looked back |
| 17:26 | cfleming | Well, you're going to have to pay for it at some point :) |
| 17:26 | sandbags | sure, sure, we all gotta eat :) |
| 17:26 | oddcully | cfleming: but it will be part of ultimate? like all the other languages? |
| 17:26 | sandbags | god knows what i've paid for this hobby over the years |
| 17:27 | cfleming | oddcully: Sadly, no - that would require some sort of deal with JetBrains. It's not out of the question, I suppose, but it's unlikely to be any time soon. |
| 17:28 | oddcully | ok, so all the other ones are actually done by JB i assume? |
| 17:28 | cfleming | Or are open source, right. |
| 17:28 | cfleming | But there are only a couple of decent open source ones - it's a huge amount of work. |
| 17:28 | sandbags | ye gods the overtone code is a bit complex ... i think i am goign to have to find my supercollider book to grok this stuff |
| 17:29 | oddcully | i only have python installed additional to the jvm ones. i guess that is from them (pycharm i guess) |
| 17:31 | cfleming | oddcully: Right, that's from them. The core Python support is actually open source now, but the framework and web support is not. |
| 17:32 | sandbags | Good opportunity for them to rewrite IDEA in Clojure :) |
| 17:33 | cfleming | sandbags: Ummmm.... that's unlikely to happen :-). They'll probably write more of it in Kotlin at some point I assume. |
| 17:34 | sandbags | Damned NIH :) |
| 17:38 | arrdem | are there any good composable regex DSLs for Clojure? |
| 17:38 | arrdem | I'm just realizing that I have a few productions that are repeated a _lot_ |
| 17:43 | TEttinger | arrdem: that seems like... a very odd idea |
| 17:43 | arrdem | TEttinger: why? |
| 17:43 | TEttinger | regexes are already a dsl, and I have no idea how you would compose them |
| 17:44 | TEttinger | do you mean this-followed-by-this? |
| 17:44 | arrdem | yep, or this as a group in a new production |
| 17:44 | TEttinger | I wonder... #(str #"(\w+)\1\1") |
| 17:45 | TEttinger | I wonder... ##(str #"(\w+)\1\1") |
| 17:45 | lazybot | ⇒ "(\\w+)\\1\\1" |
| 17:45 | TEttinger | hm |
| 17:45 | TEttinger | ,(re-pattern (str #"(\w+)\1\1")) |
| 17:45 | clojurebot | #"(\w+)\1\1" |
| 17:45 | scottj | TEttinger: have you seen rx in emacs? https://github.com/clojure-emacs/clojure-mode/blob/master/clojure-mode.el#L966-L983 |
| 17:45 | TEttinger | not an emacs user |
| 17:45 | TEttinger | cfleming is my lord and savior |
| 17:46 | TEttinger | woaah scottj that looks outrageously verbose |
| 17:47 | cfleming | arrdem: ztellman's automat, maybe? |
| 17:47 | TEttinger | that ztellman |
| 17:47 | TEttinger | always with the useful libs |
| 17:47 | cfleming | arrdem: or you could wrap a dsl around this: http://www.brics.dk/automaton/index.html |
| 17:47 | scottj | TEttinger: there are shorter names for a lot of the things. like instead of zero-or-one you can use optional or opt |
| 17:47 | TEttinger | ah ok |
| 17:47 | arrdem | cfleming: heh nice one |
| 17:48 | scottj | TEttinger: or one-or-more can be 1+ |
| 17:48 | sveri | cfleming: sandbags I heard one of the kotlin developers talk last year about it. He said that more and more teams are switching to kotlin at JB. Most interesting fact for me was that the teams are free to choose their language they want to code in |
| 17:49 | sandbags | looks like YAOOPL |
| 17:49 | cfleming | sveri: Really? I'm surprised - basically all their code is in Java, except for the Scala and Kotlin plugins, which have a fair amount of their respective langs. |
| 17:49 | cfleming | sveri: And a lot of groovy in builds and tests |
| 17:50 | sveri | cfleming: He was coding in C# before he started working on kotlin, thats what he said |
| 17:50 | sveri | I guess there are a lot of teams doing different things beside Intellij |
| 17:51 | cfleming | sveri: Interesting - he was probably working on resharper, I guess, and I think they have some .NET profiling tools too |
| 17:51 | sveri | cfleming: Yea, could be, that sounds reasonable |
| 17:52 | cfleming | But yeah, they have a ton of products now. |
| 17:52 | sandbags | so complicated |
| 17:52 | sveri | sandbags: the java interop was pretty hard to understand the last time I looked at it, maybe one year ago |
| 17:52 | cfleming | sandbags: It's not so bad actually, takes a bit of getting used to, like anything I guess |
| 17:53 | cfleming | I'd use it for Android development, I think |
| 17:53 | cfleming | At least until arrdem finally finishes OxCart |
| 17:53 | sveri | :D |
| 17:53 | arrdem | cfleming: oxcart is dead. you may get oxlang evetually |
| 17:54 | sveri | cfleming: I tried that and gave up after some hours guessing how to integrate the java android api into kotlin code |
| 17:54 | cfleming | arrdem: I shall wait for it patiently. |
| 17:54 | arrdem | cfleming: just for that you're buying first at clj/w |
| 17:54 | cfleming | sveri: Oh, bummer. I'd say Java 8 but that's no good either. |
| 17:54 | cfleming | arrdem: Ok, ok.... |
| 17:54 | sveri | cfleming: does not work ion Android yet IIRC |
| 17:54 | sveri | I mean Java 8 |
| 17:55 | cfleming | sveri: Right, it doesn't. |
| 17:56 | sandbags | anyone here used JavaFX ... i've been looking at fn-fx but i can't tell if JavaFX is actually a useful thing to build on |
| 17:57 | cfleming | sandbags: tbaldridge seems to love it, I've never used it myself |
| 17:57 | sandbags | assuming tbaldridge is actually going to continue to work on fn-fx anyway (much like React for JavaFX) |
| 17:57 | cfleming | sveri: https://github.com/orfjackal/retrolambda should work for most of the interesting Java 8 stuff, that's nice. |
| 17:57 | sandbags | my last Java GUI experience was Swing in about 2001 so i'm kind of at sea |
| 17:57 | cfleming | sandbags: seesaw? |
| 17:58 | sandbags | i did take a look at that but... it didn't grab m |
| 17:58 | sandbags | e |
| 17:59 | sandbags | it's not like i remember anything useful about swing at this point anyway |
| 17:59 | sveri | cfleming: sounds interesting...but I guess I cannot use this at work as you need JDK 8 to compile the code and all our build systems must run JDK 7 |
| 17:59 | oddcully | mine was AWT... i have the 1.1 oreilly book to prove it |
| 17:59 | oddcully | never finished it |
| 18:00 | cfleming | sveri: He recommends using JDK 8 for dev, but JDK 7 for builds/testing to make sure you catch any problems. |
| 18:01 | sveri | cfleming: "Use JDK 8 to compile your source code." that won't work for us I guess |
| 18:03 | sandbags | right, time for sleep ... thx again cfleming |
| 18:04 | Shayanjm | Ok now the opposite - "reverse haversine" implementation: https://gist.github.com/shayanjm/644d895c1fad80b49919 |
| 18:04 | Shayanjm | any criticism is more than welcome -- still haven't fully figured out how to write thing in a clojuric way I think |
| 18:07 | cfleming | Shayanjm: That looks fine to me |
| 18:08 | cfleming | Shayanjm: One thing is that the official Clojure lib guidelines recommend not destructuring in your arglists - I actually quite like that though, since it appears in doc popups and so on, and documents the shape of the map you're expecting. |
| 18:09 | Shayanjm | cfleming: that was my reasoning for doing the destructuring |
| 18:09 | cfleming | Shayanjm: I think it's ok, I wouldn't worry about it |
| 18:09 | Shayanjm | Sweet thanks for the input :) |
| 18:10 | oddcully | and R should be some const (maybe for gist sake here dome otherwise) |
| 18:10 | oddcully | s/dome/done/ |
| 18:11 | Shayanjm | good point cfleming |
| 18:12 | cfleming | Shayanjm: All credit for that goes to oddcully :) |
| 18:12 | Shayanjm | oops, oddcully *** tabbed the wrong name |
| 18:17 | oddcully | is there a way to import java stuff :as ? Like with all that Math/ stuff going on there to alias that to m/ ? |
| 18:18 | Shayanjm | oddcully: Yeah honestly I definitely should've done that |
| 18:18 | Shayanjm | I'll probably refactor with that in there once I finish testing @ scale |
| 18:18 | Shayanjm | it'll be part of the whole "tear down the duct tape" process prior to open sourcing |
| 18:19 | cfleming | oddcully Shayanjm: No, you can't do that - you need the class/method syntax |
| 18:19 | Shayanjm | cfleming: use as m wouldn't work? |
| 18:20 | cfleming | oddcully Shayanjm: The best you could do is wrap them in a function. |
| 18:20 | Shayanjm | orly |
| 18:20 | cfleming | Shayanjm: No, Math is a class, so you import it, not use it |
| 18:20 | Shayanjm | Ahh right |
| 18:20 | oddcully | ok, was just wondering, because searches/grimoire did not show anything |
| 18:20 | TEttinger | $google java 7 Math |
| 18:20 | lazybot | [Math (Java Platform SE 7 ) - Oracle Documentation] http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html |
| 18:21 | cfleming | Actually, Math you don't have to import because it's in java.lang, but if it were in another package you'd have to import it, and import has nothing like :as |
| 18:21 | oddcully | i only wanted to alias it ;) |
| 18:21 | TEttinger | ,(def M Math) |
| 18:21 | TEttinger | curious |
| 18:21 | clojurebot | #'sandbox/M |
| 18:21 | oddcully | ok, is found nothing, because it does not exist |
| 18:22 | TEttinger | ,(M/sqrt 4) |
| 18:22 | clojurebot | #error{:cause "No such namespace: M", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: No such namespace: M, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyze "Compiler.java" 6535]} {:type java.lang.RuntimeException, :message "No such namespace: M", :at [clojure.lang.Util runtimeException "Util.java" 221]}], :trace [[clojure.lang.Util ru... |
| 18:22 | TEttinger | ,(.sqrt M 4) |
| 18:22 | clojurebot | #error{:cause "No matching method found: sqrt for class java.lang.Class", :via [{:type java.lang.IllegalArgumentException, :message "No matching method found: sqrt for class java.lang.Class", :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]}], :trace [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53] [clojure.lang.Reflector invokeInstanceMethod "Reflector.java"... |
| 18:22 | oddcully | TEttinger: this means no, right? |
| 18:22 | TEttinger | hm |
| 18:23 | oddcully | thanks anyway, bbl |
| 18:23 | oddcully | (inc cfleming) |
| 18:23 | lazybot | ⇒ 15 |
| 18:23 | oddcully | (inc TEttinger) |
| 18:23 | lazybot | ⇒ 49 |
| 18:23 | TEttinger | thx |
| 18:24 | cfleming | Ahh, sweet karma |
| 18:24 | TEttinger | ,(def M #'Math) |
| 18:24 | clojurebot | #error{:cause "Expecting var, but Math is mapped to class java.lang.Math", :via [{:type clojure.lang.Compiler$CompilerException, :message "java.lang.RuntimeException: Expecting var, but Math is mapped to class java.lang.Math, compiling:(NO_SOURCE_PATH:0:0)", :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6732]} {:type java.lang.RuntimeException, :message "Expecting var, but Math is mapped t... |
| 18:24 | TEttinger | ,(def M Math) |
| 18:24 | clojurebot | #'sandbox/M |
| 18:24 | TEttinger | ,(.sqrt #'M 4) |
| 18:24 | clojurebot | #error{:cause "No matching method found: sqrt for class clojure.lang.Var", :via [{:type java.lang.IllegalArgumentException, :message "No matching method found: sqrt for class clojure.lang.Var", :at [clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53]}], :trace [[clojure.lang.Reflector invokeMatchingMethod "Reflector.java" 53] [clojure.lang.Reflector invokeInstanceMethod "Reflector.jav... |
| 18:25 | TEttinger | dog-at-keyboard.jpeg |
| 18:25 | cfleming | TEttinger: Can't do it, sorry |
| 18:26 | cfleming | I'd actually like to be able to do that, especially when you want to import two classes with the same name |
| 18:39 | arrdem | I guess I'd refactor that to use unit tagged values and define my own sin/cos/tan etc, but this is left as an exercise for another barber |
| 18:39 | arrdem | as-is it's fine tho |
| 18:40 | Shayanjm | thanks yo |
| 18:58 | ticking_ | dnolen: hey, this looks liek abug in core.match, should I fill an issue? (match [[1 2 3]] [([h & r] :as a)] a) -> [1] |
| 19:04 | ticking_ | additionally, does it grant its own issue, or should I just add it as a comment on http://dev.clojure.org/jira/browse/MATCH-93 ? |
| 19:06 | dnolen | ticking_: just add it to the ticket as additional case via comment, I believe sritchie may have found a similar issue w/ :as. |
| 19:07 | ticking_ | dnolen: k, I'll do :) |
| 19:07 | dnolen | ticking_: no idea when I'll have time to look at though, so patch very welcome. |
| 19:07 | ticking_ | dnolen: I'll look into it :) |
| 19:07 | dnolen | I've maxed out on Clojure OSS contribution |
| 19:07 | ticking_ | dnolen: yeah, I was already wondering how you handled all that TBH |
| 19:09 | ticking_ | dnolen: so thanks for all the good work :) |
| 19:44 | TEttinger | cfleming: I'm pretty proud of my first real macro |
| 19:44 | clojurebot | Excuse me? |
| 19:44 | TEttinger | also my first nested macro |
| 19:45 | TEttinger | ,(defmacro import-alias [new-name imported] `(defmacro ~new-name [f# & body#] `(. ~'~imported ~f# ~@body#))) |
| 19:45 | clojurebot | #'sandbox/import-alias |
| 19:45 | TEttinger | ,(import-alias mmm Math) |
| 19:45 | clojurebot | #'sandbox/mmm |
| 19:45 | TEttinger | ,(mmm sqrt 4.0) |
| 19:45 | clojurebot | 2.0 |
| 19:45 | TEttinger | it doesn't use a / of course |
| 19:46 | TEttinger | (inc amalloy) ; for writing an excellent blog post on macros-in-macros |
| 19:46 | lazybot | ⇒ 257 |
| 19:46 | justin_smith | ,(mmm PI) ; delicious |
| 19:46 | clojurebot | 3.141592653589793 |
| 21:02 | Shayanjm | 6 hours and 8.4k requests later, my algo works and I now have a pretty comprehensive list of every restaurant in Austin TX ranked by popularity/foot-traffic :) |
| 21:06 | justin_smith | nice! |
| 21:06 | justin_smith | Shayanjm: is this just a data crunching thing, or do you have a frontend too? |
| 21:07 | Shayanjm | justin_smith: purely data crunching thing right now |
| 21:07 | Shayanjm | would be really cool to have a UI |
| 21:07 | Shayanjm | but I'd love to show off the implementation before it's super polished, since really it's a showcase of efficient hexagonal circle packing |
| 21:07 | justin_smith | Shayanjm: maybe incanter? |
| 21:07 | Shayanjm | justin_smith: Yeah I could do that - but at the scales i'm dealing with, just plotting is a HUGE issue |
| 21:07 | justin_smith | oh, nice, screenshot? |
| 21:07 | Shayanjm | sec i've got a few laying around |
| 21:08 | Shayanjm | justin_smith: http://puu.sh/gQUd9/3e76116348.png |
| 21:09 | Shayanjm | example at a reasonable scale |
| 21:09 | Shayanjm | i think the dimensions on that was something like 3km radius bounding 50m radius circles |
| 21:09 | justin_smith | looks like something that some opengl might help with - maybe cljs with 3.js or webgl? |
| 21:10 | Shayanjm | Yeah, tons of really cool stuff. Ideally i'd like to overlay on a map |
| 21:10 | Shayanjm | probably like a v2 thing tho |
| 21:10 | Shayanjm | what's really cool is that it can generate packings at even incredibly unreasonable scales |
| 21:10 | Shayanjm | http://puu.sh/gTuqz/dcd5406b74.png (in progress HUGE circle packing) |
| 21:10 | Shayanjm | something like 750k 5km circles being packed into a circle with radius 5M KM |
| 21:11 | justin_smith | so all these circles are identical in size, right? |
| 21:11 | Shayanjm | which, for reference, is bigger than the surface area of most planets in our solar system |
| 21:11 | Shayanjm | yeah |
| 21:11 | Shayanjm | one of the requirements for the implementation |
| 21:11 | Shayanjm | identical in size, no overlap |
| 21:11 | Shayanjm | this is specifically for API optimization |
| 21:11 | justin_smith | I bet there is some really good math for optimal packing of unit circles |
| 21:11 | Shayanjm | you want the minimum # of requests to some geo-bound API while still maximizing coverage |
| 21:11 | Shayanjm | justin_smith: yeah, circle packing is a still unsolved problem |
| 21:11 | justin_smith | ahh |
| 21:12 | Shayanjm | hexagonal packing is considered the most trivially optimal solution |
| 21:12 | justin_smith | http://mathworld.wolfram.com/CirclePacking.html |
| 21:12 | Shayanjm | but is by no means 'the' solution (as you can tell by the gaps) |
| 21:12 | justin_smith | yeah, that looks like what wolfram is saying too |
| 21:12 | Shayanjm | yeah, something like .906 average coverage |
| 21:12 | Shayanjm | unfortunately to get other packing configurations you pretty much have to brute force it |
| 21:12 | justin_smith | I didn't realize it was still an open thing, that's cool |
| 21:12 | Shayanjm | but for hexagonal packings specifically, I think I came up with a pretty clever implementation which is pretty fast |
| 21:13 | Shayanjm | 30 seconds to generate 750k lat/long pairs on a macbook pro |
| 21:13 | Shayanjm | (to cover that bigger-than-a-planet area) |
| 21:13 | Shayanjm | so generating the points isn't even the bottleneck anymore - it's doing stuff with that data that takes forever. |
| 21:14 | Shayanjm | i'll be opening the project really soon so I would love any criticism at all |
| 21:14 | justin_smith | yeah, and then you have some questions to answer before you can get a fast solution - what kind of lookup should be optimized, neighbors vs. absolute position... |
| 21:14 | Shayanjm | Yeah exactly, there were a few ideas that I was throwing around |
| 21:14 | Shayanjm | with hexagonal packing the neighbors 'dumb way' is just generating 6 surrounding circle for each circle you generate |
| 21:15 | Shayanjm | which, obviously, would get hella computationally intensive as you have a bigger and bigger bounding area |
| 21:15 | justin_smith | eg. quad trees are amazing for fast lookup, but are kind of sad for traversing neighbors |
| 21:15 | Shayanjm | Yeah. the iterative solution was very very complicated |
| 21:15 | Shayanjm | and required tons of dynamic shit which just wasn't worth it |
| 21:15 | justin_smith | right |
| 21:15 | Shayanjm | so the implementation I settled with is fairly simple |
| 21:16 | Shayanjm | the gist is that you can split that hexagonal packing into 6 triangles |
| 21:16 | Shayanjm | if you figure out how to generate a triangle, you can just rotate those points 6 times |
| 21:16 | Shayanjm | which seems fairly obvious, but interestingly enough the triangle you have to generate resembles pascal's triangle |
| 21:17 | Shayanjm | each 'new number' in pascal's triangle (i.e: 1 _2_ 1) is a new distance from the center point that you have to manage if you were to generate the solution iteratively |
| 21:17 | Shayanjm | so as you generate more and more layers, you have to keep track of more and more distances from the center point, therefore you have an indefinite number of vars you have to keep track of iteratively |
| 21:17 | justin_smith | oh, of course |
| 21:17 | Shayanjm | instead, you can just generate the next-layer neighbors for each circle |
| 21:18 | Shayanjm | and take the set of those returned points |
| 21:18 | Shayanjm | because each distance to the next circle is only ever going to be 2 * circle's radius |
| 21:18 | justin_smith | Shayanjm: my hunch is that this sort of graph is not good for the standard graph algorithm optimizations (because it is so densely connected and uniform) |
| 21:18 | Shayanjm | and the bearing from each circle will only ever be 0 degrees or 60 degrees (each circle in the triangle has exactly 2 'next layer neighbors') |
| 21:18 | Shayanjm | yeah probably justin_smith |
| 21:19 | Shayanjm | i'm still trying to figure out if this is even a 'good' implementation |
| 21:19 | Shayanjm | it seems so, because the packing points are generated pretty damn fast |
| 21:19 | Shayanjm | and it mitigates the bottleneck to API rate limits |
| 21:19 | Shayanjm | in any case, i think it's a pretty cool project and hopefully someone can use it if they ever want to canvas huge areas using circle packing |
| 21:20 | Shayanjm | the lat/long coordinate generation is pretty accurate too - in line with the assumptions that most popular GIS APIs use (i.e: google maps) |
| 21:21 | justin_smith | Shayanjm: depending on what you are trying to do with the data, isn't there a variant / alternative to packing where instead of ensuring no overlaps, you ensure no uncovered area and minimize total count given that constraint? |
| 21:21 | justin_smith | Shayanjm: I ask this not really fully comprehending what you are doing |
| 21:22 | Shayanjm | justin_smith: yeah, that's theoretically "the seed of life" |
| 21:22 | Shayanjm | I think |
| 21:22 | Shayanjm | the packing would end up looking something like this: https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSaSaPEOU1riyviI1pSqLqPlC6Ed6wK50jjXW01jftN7ngvz7nfF1GNrA |
| 21:22 | justin_smith | oh, interesting |
| 21:22 | Shayanjm | justin_smith: the usecase is this: imagine you wanted to get data on every business in your city. Or even bigger - every business in your state |
| 21:23 | justin_smith | Shayanjm: isn't that cetner circle redundant there? |
| 21:23 | Shayanjm | unfortunately if you just ask google: "Get me every business in 5km from my point" it'd only return at most like 20 results, because it limits the return despite having a huge upper bounding radius |
| 21:23 | justin_smith | ahh, OK |
| 21:24 | Shayanjm | justin_smith: Nah that's why it's called the "seed of life". It's a pattern that occurs naturally where you have a single entity, put 6 points around it separated by 60 degrees each |
| 21:24 | Shayanjm | and draw circles with centers at those points |
| 21:24 | Shayanjm | and it overlaps 100% |
| 21:24 | Shayanjm | if you removed the center circle, you'd end up with my pattern |
| 21:24 | justin_smith | and if you shrink all the circles, you get a standard hex packing, right? |
| 21:24 | Shayanjm | Yup |
| 21:24 | justin_smith | cool |
| 21:25 | Shayanjm | even more interesting: if you make each circle so small it becomes a point |
| 21:25 | Shayanjm | you can get the trivially-optimal electron coverage for a sphere |
| 21:25 | Shayanjm | of some given radius |
| 21:25 | justin_smith | Shayanjm: I just got a job doing some graph / big data stuff, so I'm finding it useful to exercise some semi-related brain muscles |
| 21:25 | Shayanjm | Yeah, I work in financial tech so I love working on projects like this |
| 21:25 | Shayanjm | before Fintech, I was in Health IT doing predictive modeling for patient outcomes |
| 21:26 | Shayanjm | so weird off-the-wall data projects are my bread and butter |
| 21:26 | justin_smith | cool - I love this kind of stuff because what "normal people" find "intuitive" is so much less a factor |
| 21:26 | justin_smith | haha |
| 21:27 | Shayanjm | hahahaha yup |
| 21:27 | Shayanjm | @ day job I have to write pretty dumb code so everyone else can quickly understand & get up to speed |
| 21:27 | justin_smith | "we know that's how it really works, but we don't understand it, so can you present us with something totally inaccurate that we understand?" |
| 21:27 | Shayanjm | on these types of projects, I can sit and think about a problem for 3 hours and implement like 2 (dense, but clever) lines |
| 21:27 | Shayanjm | lolol yup precisely |
| 21:27 | justin_smith | "oh, and we are going to complain if it's ever wrong, even though we asked for a thing that is wrong" |
| 21:27 | Shayanjm | hahahahaha exact same tension w/ me @ work |
| 21:28 | Shayanjm | I tend to want to optimize for the general solution that will _always_ work |
| 21:28 | Shayanjm | it describes the problem accurately, and delivers a solution in a format that is true to the problem domain |
| 21:28 | Shayanjm | but then I end up having to rewrite it in a dumb breakable way because no one can quickly read it and fully grok it |
| 21:29 | Shayanjm | justin_smith: I'll be writing a blog post outlining what I did in this project, but I think I'm going to take it in a different direction |
| 21:30 | Shayanjm | instead of going over the technicalities of the project, I think I'm going to write something along the lines of: "How to take an idea from Point A to Point B when the bottleneck is a lack of domain knowledge" |
| 21:30 | Shayanjm | and using this specific project as an example/springboard |
| 22:24 | fellipebrito | Do you guys use cljs for something? If yes, how do you guys test it? I've found clojure pretty good at tests, but cljs makes me a little confuse. |
| 22:25 | LaVidaPortland | I'm just starting to learn clojure, so I haven't done anything with cljs yet. Sorry! |
| 23:43 | Bruce_Wayne | anyone know the best library when dealing with passing params in a url? |
| 23:43 | justin_smith | Bruce_Wayne: use ring wrap-params |
| 23:44 | Bruce_Wayne | having trouble with params that have a & |
| 23:44 | Bruce_Wayne | won’t pass in the url |
| 23:44 | justin_smith | can you give an example? |
| 23:44 | Bruce_Wayne | Wagner & Sons |
| 23:44 | XorSwap | Batman? |
| 23:44 | Bruce_Wayne | a string such as that is a paramater I need to pass in the url |
| 23:44 | justin_smith | yeah, that's not a valid syntax in a URL param, you need to escape it |
| 23:44 | Bruce_Wayne | but it won’t accept the & symbol |
| 23:45 | justin_smith | that's a limitation of how URL parameters work |
| 23:45 | Bruce_Wayne | justin_smith: exactly, so how can I escape it? |
| 23:45 | arrdem | justin_smith: cemerick and some other people have lighter weight url parsing and forging libraries |
| 23:45 | justin_smith | oh, for generating such a thing? there's a library that does URL encoding, sorry |
| 23:45 | Bruce_Wayne | yep! |
| 23:45 | Bruce_Wayne | what’s the library? |
| 23:46 | justin_smith | arrdem: lighter weight than wrap-params? |
| 23:46 | justin_smith | Bruce_Wayne: checking |
| 23:46 | Bruce_Wayne | thank you! |
| 23:46 | arrdem | justin_smith: isn't that part of ring's routing infra? |
| 23:46 | justin_smith | it's a middleware, I thought he was serving requests |
| 23:46 | arrdem | justin_smith: when doing the lib-grim url crap I found a few things that were _just_ url parsing/generating |
| 23:46 | arrdem | maybe he is |
| 23:46 | arrdem | Bruce_Wayne: the hell are you doing so we can arm you accordingly |
| 23:47 | arrdem | don't want to give you bad advice now do we :P |
| 23:47 | Bruce_Wayne | I am passing params through a url, then populating a form with those params on the other end |
| 23:47 | Bruce_Wayne | so I need to take the param |
| 23:47 | Bruce_Wayne | encode it for the url |
| 23:48 | Bruce_Wayne | then decode it back to the original to prepopulate the form |
| 23:48 | justin_smith | Bruce_Wayne: with jvm 1.7+ use (URLencoder/encode str "UTF-8") |
| 23:48 | justin_smith | for 1.6 I'm not sure |
| 23:48 | Bruce_Wayne | ok, and how can I decode the params on the other end? |
| 23:49 | justin_smith | wrap-params does it if you have a ring server on the other end |
| 23:49 | arrdem | justin_smith: aw come on man [cemerick/url "RELEASE"] |
| 23:49 | justin_smith | arrdem: it's a single static method, you don't need a lib for that |
| 23:49 | arrdem | justin_smith: the lib is literally defn wrappers around that single static method lol |
| 23:50 | justin_smith | anotehr static method to decode (URLDecoder/decode str "UTF-8") |
| 23:50 | justin_smith | Bruce_Wayne: as long as you can use 1.7, use those two, I'd say |
| 23:51 | Bruce_Wayne | justin_smith: Thank you |
| 23:52 | justin_smith | haha |