2016-04-06
| 00:00 | Lewis | amalloy: sorry im multitasking. My fault |
| 00:01 | Lewis | ,(doc next) |
| 00:01 | clojurebot | "([coll]); Returns a seq of the items after the first. Calls seq on its argument. If there are no more items, returns nil." |
| 00:02 | Lewis | (next [ 1 2 3 4]) |
| 00:02 | Lewis | ,(next [ 1 2 3 4]) |
| 00:02 | clojurebot | (2 3 4) |
| 00:04 | Lewis | ,(not [1 2 3]) |
| 00:04 | clojurebot | false |
| 00:05 | Lewis | (not []) |
| 00:05 | Lewis | ,(not []) |
| 00:05 | clojurebot | false |
| 00:05 | Lewis | ,(doc not) |
| 00:05 | clojurebot | "([x]); Returns true if x is logical false, false otherwise." |
| 00:06 | Lewis | wow I don't think today. I've been working all day it might not help |
| 00:06 | Lewis | i even for got what not* was lol |
| 00:35 | dorian | hey can anybody tell me why lein-bin keeps trying to put the generated binary into a target/base+system+user+dev (which doesn't exist)? |
| 00:40 | dorian | oh i see, boilerplate made :target-path "target/%s" which presumably gets formatted in something |
| 00:40 | tolstoy | Yeah, I always delete that line. Can't remember what it messed up for me. |
| 00:41 | dorian | i kiiiinda understand what it's doing, i just don't understand why the dir doesn't get made |
| 02:14 | Lewis | ,(doc max) |
| 02:14 | clojurebot | "([x] [x y] [x y & more]); Returns the greatest of the nums." |
| 02:14 | Lewis | ,(doc max-key) |
| 02:14 | clojurebot | "([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is greatest." |
| 05:43 | ulrichschinz | hey there, I'm learning clojure and plain around... i dont understand why this is not working, mybe someone can explain.... |
| 05:43 | ulrichschinz | (reduce (fn [aggr field] (if field (when (:pn field) (println (:pn field)) (conj aggr (:pn field))))) [] column)) |
| 05:43 | ulrichschinz | returns nil |
| 05:43 | ulrichschinz | whereas column is a vec of maps |
| 05:43 | ulrichschinz | println prints the right thing |
| 05:44 | ulrichschinz | but it returns nil, i would expect to get a vec of str-entries |
| 05:51 | Kneiva | ulrichschinz: println returns nil |
| 05:51 | ridcully | ulrichschinz: field is most likely always true, so this branch always gives you nil |
| 05:51 | ridcully | ulrichschinz: either the when gives you nil or the print |
| 05:52 | Glenjamin | one way to help with debugging, is to extract the function outside the reduce, and try it with different values to see if it does what you expect |
| 05:52 | ridcully | or use doto |
| 05:59 | ulrichschinz | ok |
| 06:00 | ulrichschinz | so println inside a reduce always results in a nil? |
| 06:02 | ulrichschinz | same thing without println returns nil as well |
| 06:06 | ridcully | a println always returns nil |
| 06:56 | aptablips | Hi. Quick Clojure question: How do you do an inexact numerical comparison? For example, I'd like this to come out true: (= (+ 0.1 0.2) 0.3) |
| 07:06 | tdammers | aptablips: not a clojure specific question really; you can't do that with floats in any language |
| 07:06 | tdammers | what you want is "epsilon comparison" |
| 07:06 | tdammers | i.e., compare against a tiny range |
| 07:07 | gon__ | one way (= (+ 0.1M 0.2M) 0.3M) |
| 07:07 | dmsnell | (< (- 0.3 (+ 0.1 0.2)) epsilon) |
| 07:07 | dmsnell | ^^^ really need absolute value |
| 07:07 | dmsnell | but I wrote that to clarify |
| 07:07 | dmsnell | where epsilon is small |
| 07:08 | jaaqo | (= (+ (rationalize 0.1) (rationalize 0.2)) (rationalize 0.3)) |
| 07:08 | tdammers | also note that because floating-point precision decreases with growing absolute values, there is no single "ideal" epsilon; you have to pick one that works well enough for your domain |
| 07:10 | dmsnell | fun fact, JavaScript just introduced this as a language construct -> Number.EPSILON |
| 07:10 | dmsnell | "the difference between one and the smallest value greater than one that can be represented as a Number." |
| 07:10 | tdammers | which makes it suitable for numbers between -1 and 1 |
| 07:11 | tdammers | or actually not |
| 07:11 | Glenjamin | ,2.220446049250313e-16 ; the value in my version of firefox |
| 07:11 | clojurebot | 2.220446049250313E-16 |
| 07:11 | tdammers | ,(+ 1.0 2.220446049250313E-16 -2.220446049250313E-16) |
| 07:11 | clojurebot | 1.0 |
| 07:11 | tdammers | \o/ |
| 07:12 | tdammers | ,(+ 1.0 2.220446049250313E-16) |
| 07:12 | clojurebot | 1.0000000000000002 |
| 07:12 | tdammers | ,(+ 1.0 2.220446049250312E-16) |
| 07:12 | clojurebot | 1.0000000000000002 |
| 07:12 | tdammers | ,(+ 1.0 2.2204460492503E-16) |
| 07:12 | clojurebot | 1.0000000000000002 |
| 07:12 | tdammers | hmm |
| 07:14 | cwgem|mac | Is there something like this ( https://github.com/liebke/cljr ) that's not 6 years old? It seems like I have to create a temp lein project just to automate package downloads and install. |
| 07:14 | dmsnell | tdammers: -1 to 1 is very useful for floating-point numbers |
| 07:14 | tdammers | dmsnell: agree. |
| 07:17 | Glenjamin | ,(def epsilon 2.220446049250313E-16) |
| 07:17 | clojurebot | #'sandbox/epsilon |
| 07:17 | Glenjamin | ,(< (- 0.3 (+ 0.1 0.2)) epsilon) |
| 07:17 | clojurebot | true |
| 07:17 | MJB47 | i think if i saw that code in a project |
| 07:18 | MJB47 | i would become angry |
| 07:18 | dmsnell | MJB47: Clojure is a LISP, so this would normally be a macro if needed |
| 07:18 | MJB47 | i mean it works |
| 07:18 | MJB47 | but holy magic number batman |
| 07:18 | Glenjamin | i'd probably do something like (float= x y) |
| 07:18 | dmsnell | (~= (+ 0.1 0.2) 0.3) |
| 07:19 | MJB47 | ye i more meant the def than anything :P |
| 07:19 | Glenjamin | oh, i'd have added a docstring i expect, better than a bare use in-place :D |
| 07:20 | MJB47 | sure but |
| 07:20 | MJB47 | 3E-16 |
| 07:20 | MJB47 | would be better (with a comment) |
| 07:20 | MJB47 | imo |
| 07:21 | MJB47 | or 2E-16 |
| 07:21 | MJB47 | w/e |
| 07:22 | dmsnell | MJB47 that value is specifically chosen to be "the smallest value for which two floats could be different" |
| 07:22 | MJB47 | i know |
| 07:22 | dmsnell | so in that sense, it's a "discrete" value and changing it to look better for a human would disturb its mathematical value |
| 07:23 | MJB47 | but that also means you need to explain why that is the case to every intern that comes through |
| 07:23 | dmsnell | like PI, why not PI=3? |
| 07:23 | MJB47 | or have a mother of all comments |
| 07:23 | dmsnell | it _is_ surprising this doesn't appear to be baked into Clojure, I'll give you that |
| 07:23 | MJB47 | w/e im just nitpicking |
| 07:31 | someone1 | hi |
| 07:31 | someone1 | Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath. |
| 07:31 | someone1 | what error is this? |
| 07:31 | someone1 | clojure is in my classpath |
| 07:35 | mavbozo | someone1, did you try to run clojure repl? |
| 07:41 | someone1 | mavbozo: no, use clojure from jython |
| 07:49 | dysfun | you probably want clojure.lang.RT |
| 07:49 | dysfun | and clojure.lang.* generally |
| 07:57 | prohobo | we need some closure |
| 09:29 | TimMc | someone1: clojure.core is a Clojure namespace, not a Java package. See above advice. |
| 09:29 | TimMc | hmm, looking again, I'm not even sure what exactly you did to provoke that |
| 09:31 | jondot | what's the best way to contact rich hickey? |
| 09:31 | Empperi | sacrifice your soul to the lambda god |
| 09:31 | someone1 | TimMc: I think its a classloader problem |
| 09:31 | Empperi | really, I'm guessing it's not that easy to just contact him - except he hangs around here every now and then |
| 09:32 | TimMc | someone1: What did you do to get that error? |
| 09:32 | TimMc | It will be very hard to help you without that info. |
| 09:32 | Empperi | although less recently, guess he got to be a too big a celebrity |
| 09:32 | Glenjamin | most reliable way is to work in the same office as him afaik |
| 09:32 | Empperi | when he was a normal programmer kinda guy he used to be here too :) |
| 09:33 | jondot | yes i remember when he was here |
| 09:33 | jondot | but seriously then, is there any way to contact him? we'd like to get him to speak on a keynote for a conference |
| 09:34 | Glenjamin | i'd suggest probably cognitect is your best port of call for that |
| 09:34 | someone1 | TimMc: https://nopaste.me/view/c5826bad#mXhyfNTGjnIRRfhTg9W7qUMi4gDzGbHS |
| 09:35 | TimMc | someone1: That's a big block of base64 |
| 09:35 | someone1 | should I feel proud that I talked with Rich in 2008 over IRC? :D |
| 09:35 | jondot | someone1: yes! |
| 09:35 | Glenjamin | someone1: http://clojure.org/reference/java_interop#_calling_clojure_from_java |
| 09:37 | someone1 | Glenjamin: is this somehow build in in JRuby? Because with JRuby, all works like expected |
| 09:38 | someone1 | builtin* |
| 09:38 | Empperi | jondot: yeah, contact cognitec |
| 09:38 | Glenjamin | no idea i'm afraid |
| 09:38 | Empperi | with luck you *might* get him as a speaker |
| 09:38 | Empperi | be prepared though to not get him unless your conference is a big one |
| 09:38 | jondot | Empperi: you think that's impossible? |
| 09:38 | Empperi | he is kinda busy, he chooses the conferences |
| 09:38 | jondot | right |
| 09:38 | Empperi | so definitely not impossible |
| 09:39 | Empperi | but that is a very real possibility that he refuses |
| 09:39 | jondot | sure i can understand |
| 09:39 | Empperi | but if your conference isn't totally insignificant you should be able to get someone from cognitec as a speaker |
| 09:39 | jondot | you think info@congnitect.com is good? or should i use a better email for such a cold call? |
| 09:39 | someone1 | best way is to build a competitive lisp language and take his market shares |
| 09:39 | Empperi | they do have a lot of brilliant guys after all |
| 09:39 | jondot | that's true |
| 09:40 | Empperi | Rich Hickey is the Big Gun and the most wanted speaker, so there's a lot of demand for him |
| 09:40 | jondot | damn. |
| 09:41 | Empperi | I personally haven't tried to get him as a speaker but I do know some people who did :) |
| 09:41 | Empperi | it was one of the largest software conferences in Finland which was centered around clojure that year, didn't interest mr Hickey |
| 09:41 | Empperi | not significant enough |
| 09:41 | Empperi | I totally understand though |
| 09:42 | Empperi | but they did get Stuart there and he was awesome |
| 09:45 | jondot | Empperi: so i have something close. Stockholm |
| 09:46 | jondot | any other notable speakers you think of? clojure isn't a focus, but someone with a mind-opening point of view like Rich |
| 09:46 | Empperi | JFokus would definitely be big enough for Mr Hickey :) |
| 09:46 | Empperi | I really like David Nolen's talks |
| 09:46 | Empperi | dnolen: your welcome for the compliment |
| 09:46 | Empperi | ;P |
| 09:47 | dnolen | Empperi: ha! thx :) |
| 09:47 | jondot | dnolen: ah! |
| 09:47 | jondot | dnolen: would it be appropriate to approach you on this perhaps? :) |
| 09:48 | Empperi | Om Next style is the future of web development and would definitely be a "mind-opening" kinda of talk |
| 09:49 | Empperi | I personally am trying to do something similar to Om Next but in a slightly different way for different usage scenarios |
| 09:49 | Empperi | I'll talk about it later if I get it to something properly working :) |
| 09:49 | jondot | yep, we love Om, didn't realize dnolen is here |
| 09:50 | someone1 | jondot: me neither |
| 09:50 | Empperi | suprisingly large portion of significant Clojure people are here or have been here |
| 09:50 | someone1 | he destroyed pedestal |
| 09:50 | dnolen | jondot: if you're looking to get in touch with anyone at Cognitect yes I would use that email. |
| 09:50 | someone1 | little joke |
| 09:51 | jondot | dnolen: I mean, get in touch with you :) |
| 09:52 | someone1 | just watched a talk from him, first comment "Many different interesting ideas, however Clojure looks so strange and difficult to parse." |
| 09:52 | dnolen | jondot: sure send me an email https://github.com/swannodette. Note I may or may not respond for various reasons yadda yadda. |
| 09:52 | someone1 | the last part in the sentence is really true :))))))) |
| 09:53 | jondot | dnolen: thanks :) |
| 09:55 | sdegutis | I wrote a bunch of macros. :( |
| 09:55 | ToxicFrog | yay macros |
| 09:55 | someone1 | at least you can |
| 10:11 | sdegutis | But I did :/ |
| 10:19 | sdegutis | Well, it's done. |
| 10:26 | sdegutis | https://gist.github.com/sdegutis/4112dd4989fe7be17326d57d57b3ca6b |
| 10:26 | sdegutis | ,(defmacro some-let [bindings body] (let [[x y & rest] bindings] `(if-let [~x ~y] ~(if (empty? rest) body `(some-let ~(vec rest) ~body))))) |
| 10:26 | clojurebot | #'sandbox/some-let |
| 10:26 | sdegutis | ,(some-let [a 1, b (inc a), c (inc b)] [a b c]) |
| 10:26 | clojurebot | [1 2 3] |
| 10:26 | sdegutis | ,(some-let [a (prn :a!), b nil, c (prn :b!)] [a b c]) |
| 10:26 | clojurebot | :a!\n |
| 10:27 | sdegutis | Very handy. I may use this every day. |
| 10:27 | Glenjamin | multi-clause if-let? |
| 10:28 | sdegutis | Glenjamin: similar, yeah |
| 10:28 | sdegutis | Glenjamin: it's basically a nested if-let |
| 10:28 | sdegutis | Glenjamin: it'll short-circuit and return nil if any of the bindings are nil along the way |
| 10:30 | Glenjamin | i imagine useful has something similar, although the api docs appear to have gone missing |
| 10:30 | sdegutis | It should probably use when-let though rather than if-let |
| 10:30 | sdegutis | Glenjamin: I looked in amalloy_'s useful and didn't see anything like it |
| 10:32 | Glenjamin | similar-ish to cond-> i guess, but more flexible with how you use the args |
| 10:34 | sdegutis | Glenjamin: im not seeing how some-let is similar to cond-> |
| 10:35 | Glenjamin | well i was thinking you'd often chain values as you went with some-let |
| 10:37 | sdegutis | Glenjamin: the purpose I created it for was so that I can create bindings that are based on other bindings, but short-circuit if any are nil |
| 10:38 | Glenjamin | right, that's sort of what cond-> does, but without the bindings |
| 10:39 | Glenjamin | similar sort of "drilling down" effect |
| 11:09 | sdegutis | Glenjamin: ah |
| 11:50 | sdegutis | back |
| 11:53 | sdegutis | Good morning. Is there a built-in way to create a record that conforms to a protocol purely by its keys? |
| 11:53 | sdegutis | ,(do (defprotocol Foo (bar [this])) (defrecord RealFoo [bar] Foo) (bar (RealFoo. "foo"))) |
| 11:54 | clojurebot | #error {\n :cause "sandbox.RealFoo.bar()Ljava/lang/Object;"\n :via\n [{:type java.lang.AbstractMethodError\n :message "sandbox.RealFoo.bar()Ljava/lang/Object;"\n :at [sandbox$eval68 invokeStatic "NO_SOURCE_FILE" 0]}]\n :trace\n [[sandbox$eval68 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval68 invoke "NO_SOURCE_FILE" -1]\n [clojure.lang.Compiler eval "Compiler.java" 6927]\n [clojure.lang.C... |
| 11:54 | sdegutis | I'd like to be able to do something like that. |
| 11:54 | sdegutis | Kind of like Ruby's #attr_accessor or whatever it's called. |
| 11:54 | sdegutis | Or must I write my own macro to do this? |
| 11:55 | sdegutis | The problem I'm trying to solve is to have some kind of type-safety on keys on what is currently just a map. |
| 11:55 | sdegutis | I end up typing (:email-service env) and hoping I didn't make a typo, and writing a unit test if I need to prove that I didn't. |
| 11:56 | sdegutis | Whereas I'd like to just have it fail at compile-time if it's not a valid key, like (env/email-service env) |
| 11:56 | sdegutis | I suppose I can just create functions that are the keys, such as (do (ns myapp.env) (def email-service :email-service)) |
| 11:56 | sdegutis | Then I can access env/email-service knowing for sure it's legit. |
| 11:57 | sdegutis | Okay, thanks, I'll do that. |
| 11:57 | sdegutis | Good morning justin_smith. |
| 12:00 | Lewix | ,(conj nil 0) |
| 12:00 | clojurebot | (0) |
| 12:01 | sdegutis | how are you luma |
| 12:01 | Lewix | ,(conj '(1) 0) ;; added in the most natural way ok? |
| 12:01 | clojurebot | (0 1) |
| 12:01 | Lewix | ,(conj '(0) 1) ;; added in the most natural !? no way |
| 12:01 | clojurebot | (1 0) |
| 12:03 | Lewix | so no matter what it adds it after the number in this instance |
| 12:03 | Lewix | (class '(:foo)) |
| 12:03 | Lewix | ,(class '(:foo)) |
| 12:03 | clojurebot | clojure.lang.PersistentList |
| 12:04 | Glenjamin | Lewix: conj always adds in the most efficient way |
| 12:04 | Glenjamin | ,(doc conj) |
| 12:04 | clojurebot | "([coll x] [coll x & xs]); conj[oin]. Returns a new collection with the xs 'added'. (conj nil item) returns (item). The 'addition' may happen at different 'places' depending on the concrete type." |
| 12:04 | Glenjamin | that's not very helpful |
| 12:09 | sdegutis | wow I guess everyone else is productive today |
| 12:09 | sdegutis | well that's good I suppose |
| 12:17 | justin_smith | I'm much more productive now that I only IRC on the mobile (which I have connected to a bluetooth kvm) |
| 12:19 | sdegutis | justin_smith: nice |
| 12:19 | sdegutis | justin_smith: on one hand I really enjoy socializing in #clojure (anything more than that is too much socialization for me) |
| 12:19 | sdegutis | justin_smith: on the other hand, I feel bad like I'm dragging everyone else here's productivity down with me |
| 12:19 | sdegutis | justin_smith: so its good to see you're being more productive with a clever solution |
| 12:41 | sdegutis | Phew, we're a lot less stringly-typed now. |
| 12:53 | tolstoy | For some reason, I rarely have an issue with fat-fingered keywords, etc, etc. |
| 12:53 | tolstoy | Not sure why. |
| 12:53 | tolstoy | I used to. |
| 12:54 | tolstoy | I bet I use maps (and so on) in a much more temporary way than I used to. |
| 12:54 | tolstoy | Like Clojure has taught me to be the designer it prefers. |
| 12:59 | spieden | i habitually use the cursive keyword completion and check the "find usages" popup |
| 12:59 | spieden | also use namespaced keywords much more lately |
| 13:00 | spieden | keyword indexing can lag behind though it seems |
| 13:01 | spieden | cfleming: should that be the case? |
| 13:02 | tolstoy | I imagine another technique is that outside a concern, the data blobs are largely opaque. |
| 13:03 | tolstoy | (create-email {:to "blah" :from "blah" :smtp "whatev"}) |
| 13:03 | tolstoy | Then (email/send email "nub@example.com"). |
| 13:03 | tolstoy | So, it's only in the email namespace I ever have to track keywords or worry about types more complicated than strings. |
| 13:04 | spieden | tolstoy: do you use prismatic plumbing's fnk, et al? |
| 13:05 | tolstoy | Nope. |
| 13:06 | tolstoy | I'm guessing most of the problems I work on are pretty simple. |
| 13:07 | tolstoy | I do read a config.edn and validate it with schema, then just assume it's valid when I pass a sub-map to a component. |
| 13:07 | tolstoy | When I get data from a websocket (say), I use schema to validate it. |
| 13:07 | tolstoy | But those are the two pain points. |
| 13:08 | spieden | tolstoy: i like the fnk destructuring forms a lot |
| 13:08 | tolstoy | I think if it were all painful to me, I'd just move on to a Haskell of some sort. |
| 13:08 | spieden | .. but yeah, schemas for the entrypoints of data |
| 13:09 | tolstoy | Esp. if other people are going to use it. |
| 13:09 | tolstoy | I've had people send me a JSON doc that was just wrong, but get a cryptic error back and just assume I was a crappy programmer and start digging around in my code. |
| 13:10 | tolstoy | Maybe I am a crappy programmer! |
| 13:10 | tolstoy | But a nice "missing key" error sure cuts down on people having to be disappointed in me. ;) |
| 13:11 | sdegutis | tolstoy: we all are |
| 13:12 | tolstoy | Yeah. It's never my fault your lib doesn't work! You clearly don't know what you're doing! ;) Oh, wait. Sorry. <--- programmer mindset |
| 13:14 | sdegutis | tolstoy: what do you use instead of maps now? |
| 13:15 | tolstoy | I use maps like everyone else, for the most part. |
| 13:15 | sdegutis | yeah but how is that? |
| 13:15 | tolstoy | I'm just trying to piece together why I don't get into as much trouble with them anymore. |
| 13:16 | sdegutis | tolstoy: I've started passing around an "env" map that has keys like :email-service, :env-name, :host-name, :db-connection, stuff like that which changes based on environment |
| 13:16 | sdegutis | I pass it to all my (defn routes [env] [...]) functions, which just return a vector of compojure routes, that capture the env via lexical scope |
| 13:16 | tolstoy | Well, for instance, I like websockets. So, I get a message like [:some/thing {:map "of stuff"}]. Then I destructure, and validate the map, then call a function based on the first word in the tuple, and then the map is over. |
| 13:16 | sdegutis | and they pass it to whatever functions need to send emails or change the DB, etc |
| 13:17 | sdegutis | tolstoy: ahh I see |
| 13:17 | tolstoy | The map is just good for that message, not meant to represent a domain object. |
| 13:17 | sdegutis | right |
| 13:17 | sdegutis | hmm yeah I use it for inter-function communication sometimes too |
| 13:18 | tolstoy | I don't think I do that much any more (just evolved to be that way), which I'm guessing is why things seem smoother for me. |
| 13:19 | tolstoy | Lately, I get a message in [:topic msg-map] and I've been casting it to a record (map->SaveUser msg-map). |
| 13:19 | sdegutis | tolstoy: ah |
| 13:19 | tolstoy | Then I have protocols for that. |
| 13:19 | sdegutis | thanks for ur feedback |
| 13:19 | tolstoy | (if (satisfies? IMutate msg) (protcol/mutate msg db) ...) |
| 13:20 | tolstoy | Also, (when (satisfied? Validatable msg) (protocols/validate! msg)) and so on. |
| 13:20 | sdegutis | tolstoy: I've found protocols & records to be very handy, but only for services which could change depending on whether you're in a test environment (i.e. deftest), development, or production, such as EmailService, LiveEmailService, and MemoryEmailService |
| 13:20 | tolstoy | Then I have a single file "validate" that handles that concern for all (or most) messages. |
| 13:21 | tolstoy | sdegutis: That's what I use them for too. I have a Publisher component, for instance (def record) which I can re-instantiate with different topics. But they all implement the send! protocol. |
| 13:22 | sdegutis | hmm interesting |
| 13:22 | tolstoy | sdegutis: The advantage of converting a message or data item to a record is you can hang protocols on it. No matter what the message is, you can call "validate" on it, for instance. |
| 13:22 | sdegutis | tolstoy: do you work on a clojure app full time btw? |
| 13:23 | tolstoy | I'm freelance at the moment, so, yes and no: quick and dirty apps, for the most part. |
| 13:23 | sdegutis | tolstoy: hmm interesting, re: "validate" & protocols |
| 13:23 | sdegutis | tolstoy: not sure I fully understand, but.. |
| 13:23 | tolstoy | sdegutis: It's overkill on a small app, but starts to work out well (I think) for a big app. |
| 13:25 | sdegutis | hmm |
| 13:25 | tolstoy | Think of a validate namespace (myapp.lib.validate ...), and then (extend-protocol Validatable m/UserCreate (validate [_] ...) m/UserEdit (validate [_] ...) m/AccountDelete (validate [{:keys [id auth]}] ...)). All your "validation" is in that one file, and dispatched based on the type of message. |
| 13:26 | sdegutis | tolstoy: ahh, that's an interesting way to do it |
| 13:26 | tolstoy | With a web socket, there's just one end point, so instead of a giant case statement for each type of message, I have a "process!" function that tests which protocol a given message implements, then invokes the right function. |
| 13:27 | tolstoy | All the database query stuff is in one file, the database mutate in another, all based on the type of message. |
| 13:27 | tolstoy | Downside: Stuff starts to get spread out. You have to edit four files for ever new message you want to process. |
| 13:28 | tolstoy | Upside: your one file isn't 1000 lines long. ;) |
| 13:28 | tolstoy | Oy. |
| 13:28 | tolstoy | ANYWAY, what I don't do is pass maps from one component to another, to seems. ;) |
| 13:28 | sdegutis | tolstoy: I see this making a lot of sense when you have a single entry-point into the system |
| 13:28 | tolstoy | Yeah. |
| 13:29 | sdegutis | tolstoy: in our case we handle them on a case-by-case basis, for better or worse, since we just use plain-jane HTTP |
| 13:29 | sdegutis | unrelated, there should be a one? function |
| 13:29 | sdegutis | ,(defn one? [x] (= 1 x)) |
| 13:29 | clojurebot | #'sandbox/one? |
| 13:29 | sdegutis | ,(map (juxt neg? pos? zero? one?) (range 10)) |
| 13:29 | clojurebot | ([false false true false] [false true false true] [false true false false] [false true false false] [false true false false] ...) |
| 13:30 | tolstoy | Heh. We already have zero?. So, zero? one? a-few? a-lot? tons? webscale? |
| 13:30 | sdegutis | I too often wanna check if there's only one item in a collection. |
| 13:30 | sdegutis | Like, 4 times so far.. |
| 13:30 | sdegutis | so that's about.. once per year |
| 13:31 | rcassidy | several? |
| 13:31 | tolstoy | a-scosh? |
| 13:31 | tolstoy | smidgen? |
| 13:32 | TimMc | (defn big-data? [n] (< 40 n)) |
| 13:32 | sdegutis | haha |
| 13:32 | TimMc | If you don't think 40 is a big number, I challenge you to eat 40 hot dogs in a sitting. |
| 13:33 | sdegutis | TimMc: thats an interesting way to look at it |
| 13:33 | sdegutis | TimMc: I would have done (> n 40) |
| 13:33 | TimMc | sdegutis: Yeah but then your number line is backwards. :-P |
| 13:34 | TimMc | <---39-40-41---n---> |
| 13:35 | sdegutis | TimMc: interesting |
| 13:53 | bendlas | hi, are there read-cond flags for cljs macros? |
| 14:05 | TMA | actually, 40 was established as value of infinity in ancient middle east |
| 14:25 | sdegutis | ha |
| 14:33 | ane | well, it's more than 39 |
| 14:41 | rcassidy | http://www.therobotsvoice.com/wp-content/uploads/2011/03/lexluthorcakes.jpg |
| 14:59 | jjmalina | rcassidy where is that from |
| 15:02 | TimMc | So many! |
| 15:02 | TimMc | TMA: Seems implausible. :-) |
| 15:10 | TMA | TimMc: it does: https://en.wikipedia.org/wiki/40_%28number%29#In_religion |
| 15:16 | Empperi | you must have edited that page just before pasting the link, spent the last hour typing that stuff in |
| 15:16 | Empperi | lmao |
| 15:17 | TimMc | TMA: Eh, that's not infinity, that's "large number" |
| 15:26 | TMA | TimMc: that's nitpicking :) the English word "forever" is too understood as a "long time" not as "infinite time" in day-to-day contexts; likewise "infinite" is "too large number to count" -- “It seemed like forever ago, like we've had this brief but still infinite forever. Some infinities are bigger than other infinities.” ― John Green, The Fault in Our Stars |
| 15:31 | rcassidy | jjmalina: http://knowyourmeme.com/memes/lex-luthor-took-forty-cakes |
| 15:33 | gganley | Hi, I'm starting a project that needs a connection to an IRC server. I've never made a program that uses the network this way but I've worked on a lot of Cisco routers so I have plenty of knowlage of the protocol itself. I'm just looking for some advice on how to start in network programming. it doesnt have to be clojure specific but i would like if it was |
| 15:36 | Empperi | you insist on doing the IRC stuff yourself? |
| 15:36 | Empperi | or do you want to use a library for that |
| 15:41 | gganley | in my mind its a good learning opertunity but I'm not opposed to using a library |
| 15:42 | Empperi | this is an old java library but it works for irc communication http://www.jibble.org/pircbot.php |
| 15:42 | Deraen | gganley: You could take a look at https://github.com/Raynes/irclj for IRC impl |
| 15:43 | Deraen | Aleph might also be interesting if you want to do async TCP/UDP stuff |
| 15:45 | gganley | I just found aleph also |
| 15:46 | gganley | it uses the manifold library which im havent heard of |
| 15:51 | ane | manifold is great |
| 16:10 | asdf12z_ | if i have a program (server) running using clojure, and i repl into it to update some code, will it crash if my updated code throws? is there a way to make it just fallback |
| 16:10 | ane | depends if it's the main thread |
| 16:54 | Lewis | what does it mean to thread an expression through a variable number of forms? |
| 16:55 | ridcully | ,(-> 1 inc inc inc) |
| 16:55 | clojurebot | 4 |
| 16:56 | luma | ,(-> 1 (+ 2) (* 3) (+ 4)) |
| 16:56 | clojurebot | 13 |
| 16:56 | luma | ,(+ (* (+ 1 2) 3) 4) |
| 16:56 | clojurebot | 13 |
| 16:56 | luma | those forms are the same thign |
| 16:59 | yottabyte | is it difficult to add a clojure class to a java web application and have it work with other java classes |
| 17:00 | rcassidy | the double arrow threads in last position so you can do things like |
| 17:00 | hiredman | depends what you mean |
| 17:00 | amalloy | yottabyte: it's easier to instead use a clojure function (or functions), and write a java wrapper class that acts as a facade for it |
| 17:00 | rcassidy | ,(->> "abcdef" (.toUpperCase) (take 3) (reverse)) |
| 17:00 | clojurebot | (\C \B \A) |
| 17:00 | hiredman | clojure doesn't have something called a 'class' |
| 17:00 | yottabyte | amalloy: can you show me an example of that? |
| 17:01 | amalloy | https://github.com/amalloy/thrift-gen |
| 17:10 | jbrhbr | hey guys. i've been trying to learn clojure and have been doing some of those codewars kata. i have a solution that's mathematically correct but i think i'm getting an ob1 error due to precision rounding or something with respect to sqrt's behavior with bigints. would anyone mind taking a look at what i have and letting me know if you see anything funny? https://gist.github.com/jerryhebert/ecf54d3c33faa0c0c4d9a19efd5d1199 |
| 17:11 | jbrhbr | trying to avoid writing it some other way since this one is basically just a math problem |
| 17:12 | jbrhbr | the issue is (find-nb 10252519345963644753026N) yields the solution 450010N, but verifying 450010N yields 10252519345963644753025N (off by 1) |
| 17:13 | luma | Math/sqrt takes and returns a double |
| 17:14 | luma | that's where a precision error probably comes fro |
| 17:14 | jbrhbr | yeah |
| 17:15 | jbrhbr | it's all i can see too, i guess i was just hoping it was overloaded for bigints or something |
| 17:15 | luma | nope |
| 17:16 | jbrhbr | i'm honestly surprised it's this close if it isn't doing something near-correct tho |
| 17:16 | rcassidy | you might just need to implement bigint sqrt logic yourself |
| 17:19 | jbrhbr | it's actually producing the correct value for 20250148500407250495000225N, somehow. guess i'll have to poke around some more |
| 17:20 | jbrhbr | and that one is way more than 64bits |
| 17:21 | jbrhbr | thanks for the input |
| 17:33 | jbrhbr | i discovered this today: (number? (Math/sqrt -1)) => true |
| 17:33 | jbrhbr | i'm sure there's a good reason for it but NaN being a number is pretty funny :p |
| 17:36 | rhg135 | ,(Math/sqrt -1) |
| 17:36 | clojurebot | NaN |
| 17:36 | hiredman | you may be confusing math with computers |
| 17:37 | rhg135 | I is dissapoint. that's i/j |
| 17:38 | hiredman | ,(type NaN) |
| 17:38 | clojurebot | #error {\n :cause "Unable to resolve symbol: NaN in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: NaN in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: NaN in this conte... |
| 17:38 | hiredman | ,(type Double/NaN) |
| 17:38 | clojurebot | java.lang.Double |
| 17:38 | hiredman | ,(supers (type Double/NaN)) |
| 17:38 | clojurebot | #{java.lang.Comparable java.io.Serializable java.lang.Number java.lang.Object} |
| 17:38 | jbrhbr | a NaN type could be its own class that isn't a number, for less language asymmetry |
| 17:40 | hiredman | NaNs exist as part of floating point standards, so just don't do floating point |
| 17:40 | hiredman | jbrhbr: and then the return type of Math/sqrt is either double or whatever NaN is |
| 17:41 | jbrhbr | sure |
| 17:41 | hiredman | and of course, Math/sqrt doesn't return an Object anyway, it returns primitive |
| 17:41 | jbrhbr | i'm not denying there are good explanations |
| 17:42 | jbrhbr | but the english "not-a-number is a number" is funny |
| 17:42 | jbrhbr | that seems like a jvm oddity to me though |
| 17:42 | hiredman | it isn't it is built right in the hardware |
| 17:43 | jbrhbr | it's a design choice |
| 17:43 | jbrhbr | alternative: raise an exception when your function is cornered into making a weird type choice |
| 17:44 | amalloy | jbrhbr: seems like a pretty reasonable alternative is: "follow the IEEE spec everyone else follows" |
| 17:46 | hiredman | the fp spec folds nan values and floating point valus in to the same bit space, the fpu instructions all take those bit patterns and produce them |
| 17:47 | jbrhbr | amalloy: that spec doesn't define a language type system |
| 17:47 | jbrhbr | sorry if i offended you guys, it was meant to be a joke |
| 18:09 | aptablips | Hi. Quick Clojure question: How do you do an inexact numerical comparison? For example, I'd like this to come out true: (= (+ 0.1 0.2) 0.3) |
| 18:09 | TEttinger | good ol' epsilon. |
| 18:09 | TEttinger | aptablips: arguably the simplest way for those exact numbers is |
| 18:10 | aptablips | You mean I should just compare with the absolute value of the difference? |
| 18:10 | TEttinger | ,(= (+ 1/10 2/10) 3/10) |
| 18:10 | clojurebot | true |
| 18:10 | aptablips | Well, those exact numbers are only an easy illustration. My app needs floating point. :) |
| 18:10 | TEttinger | yeah, sadly |
| 18:11 | TEttinger | the ratios are a pretty useful concept, though they need more numeric tower support |
| 18:12 | aptablips | Hmm, well, googling for "clojure epsilon" just turned this up: https://crossclj.info/doc/avenir/0.2.0/avenir.math.html#_approx%3D |
| 18:12 | TEttinger | I was just going to do |
| 18:12 | aptablips | (defn approx= "Approximate equality test within epsilon ( *default epsilon* 1e-6)" {:added "0.2.0"} ([x y] (approx= x y 1e-6)) ([x y epsilon] (< (abs (- x y)) epsilon)))\ |
| 18:13 | TEttinger | ok you got it :) |
| 18:13 | aptablips | Well, the formatting got messed up. But it does exactly what one would expect. |
| 18:13 | aptablips | Thanks! (I only just started Clojure a couple days ago.) |
| 18:14 | TEttinger | cool. there's a few neat things you might not have seen yet in regards to those floating point things |
| 18:14 | TEttinger | ,1M |
| 18:14 | clojurebot | 1M |
| 18:14 | TEttinger | ,0.0001M |
| 18:14 | clojurebot | 0.0001M |
| 18:14 | TEttinger | ,0.00000000000000000000000001M |
| 18:14 | clojurebot | 1E-26M |
| 18:15 | aptablips | BigDecimal, then? How is it on performance? I need this thing to run super-fast. |
| 18:52 | sdegutis | Hello! |
| 18:52 | sdegutis | How are you this evenign? |
| 18:53 | sdegutis | Hello justin_smith how are you? |
| 18:53 | tolstoy | Avoiding his phone, apparently. ;) |
| 18:53 | sdegutis | Good day TEttinger how is your status thus far? |
| 18:53 | TEttinger | is good. |
| 18:53 | sdegutis | tolstoy: Good evening kind sir, what is your state now? |
| 18:54 | sdegutis | TEttinger: I am glad to hear this. |
| 18:54 | tolstoy | Wrapping protocols around defrecords. Like any other day. |
| 18:54 | sdegutis | tolstoy: Adds up. |
| 18:54 | sdegutis | I have found that a few glasses of alcohol increases my ability to concentrate and thus my productivity. |
| 18:55 | sdegutis | However, it decreases my ability to hit the correct keys on the keyboard, which seems to neutralize at least some of the productivity benefit. |
| 18:55 | sdegutis | (Since I have to backspace quite often.) |
| 18:55 | sdegutis | Also, it increases my ability and will to DANCE!!! |
| 18:55 | sdegutis | I am sciencing alcohol. |
| 18:56 | sdegutis | Especially to Bon Iver, which is a homonym for the French phrase for "good winter", which I suppose is due to it sounding very much like winter when I listen to them. |
| 18:57 | sdegutis | :) |
| 19:03 | sdegutis | amalloy_: I'm not sure if you're aware of it, but your IRC nick often changes between amalloy_ and amalloy. |
| 19:03 | sdegutis | amalloy_: At least N times per hour, where N is roughly a unit. |
| 19:05 | sdegutis | Yeah, like that. |
| 19:11 | amalloy | have you also noticed that i am never signed out of irc? |
| 20:06 | cfleming | spieden: I've noticed that too, but I haven't had time to investigate. |
| 20:06 | cfleming | All the other indexes update pretty much immediately, but that one lags for some reason. |
| 21:20 | sdegutis | amalloy: yes |
| 21:31 | amalloy | i will give you a hint, sdegutis: those two phenomena are closely linked |
| 21:31 | sdegutis | amalloy: it wasn't a mystery for me to solve, requiring hints |
| 21:31 | sdegutis | amalloy: it's a "feature" you may want to consider disabling |
| 21:32 | sdegutis | bbl renting The Usual Suspects |
| 21:32 | amalloy | i could. i think it's nice for people to know that i'm not actually here by looking at my nick |
| 21:43 | sdegutis | amalloy: that would be cool, if it were always accurate, but in my experience those things are often very inaccurate |
| 22:03 | TimMc | Some channels kick people for changing their nick as an afk indicator. |
| 22:03 | TimMc | (which just raises the question: who doesn't ignore nick changes?!) |
| 22:29 | machinewar | if I do doseq over a sequence of maps with possibly nested maps, willl it visit every key? |
| 22:30 | machinewar | http://www.chrisumbel.com/article/clojure_xml_parsing_xml-seq I'm reading this and can't understand how I can get to every nested key in the sequence as in first example it does! |
| 22:46 | TimMc | machinewar: It will only "visit" the maps themselves. |
| 22:48 | TimMc | machinewar: Ah, I think I see your confusion -- you'd be iterating over a seq of all the XML nodes. I think you're confusing maps with keys with XML nodes maybe? |
| 22:48 | TimMc | Not sure what your goal is. |
| 22:54 | justin_smith | machinewar: look at what xml-seq outputs for that example file |
| 22:55 | justin_smith | machinewar: https://gist.github.com/noisesmith/5e277b89e2c6cb7c00525378a74a721d |
| 22:55 | justin_smith | that should make it clear how doseq found the nested tags |
| 22:55 | justin_smith | output is from loading a copy of the data in that post |
| 22:56 | justin_smith | xml-seq is a tree walk |
| 22:56 | justin_smith | it returns each node, until it hits all the leaves |
| 22:57 | machinewar | justin_smith: ahhh wow |
| 22:57 | machinewar | what a function! |
| 22:58 | machinewar | i'm stilll getting the hang of this whole functional thing, and its insane how powerful some of these standard library functions are |
| 22:58 | justin_smith | also, they combine in really powerful ways, yeah |
| 22:59 | machinewar | thanks for pointing that out |
| 22:59 | TimMc | I should... not be trying to answer questions, and go to bed. :-P |
| 22:59 | machinewar | TimMc: thanks to you too |