2015-08-29
| 00:02 | gfredericks | ,(inc 41) |
| 00:02 | clojurebot | 42 |
| 01:01 | neoncontrails | Why does this happen? |
| 01:01 | neoncontrails | ,(defn recursive-last [s] (if (seq (rest s)) (recursive-last (rest s)) s)) |
| 01:01 | clojurebot | #'sandbox/recursive-last |
| 01:01 | neoncontrails | ,(recursive-last '(3 4 5)) |
| 01:01 | clojurebot | (5) |
| 01:01 | neoncontrails | Ooh that's not what my REPL says. Hooray! |
| 01:13 | neoncontrails | So I notice that 4clojure.com doesn't seem to allow continuation-passing style |
| 01:14 | neoncontrails | In the absence of which... how does one solve a problem like https://www.4clojure.com/problem/19#prob-title ? |
| 01:16 | neoncontrails | ,((fn [x] (nth x (- (count x) 1))) [1 2 3]) |
| 01:16 | clojurebot | 3 |
| 01:18 | neoncontrails | There must be an equivalent expression that fits within the parameters of the question |
| 01:55 | ashwink005 | can anyone guide me as to how to build a web app using clojure, PostgreSQL, and HTML? |
| 01:55 | ashwink005 | any good online resource |
| 01:59 | ashwink005 | helloo |
| 01:59 | ashwink005 | can anyone guide me as to how to build a web app using clojure, PostgreSQL, and HTML? |
| 02:06 | wasamasa | http://www.parens-of-the-dead.com/ |
| 02:06 | wasamasa | and don't worry, nobody will hold your hand unless you've paid them to :> |
| 02:08 | ashwink005 | wasamasa: I mean a basic web app that reads, edits docs |
| 02:08 | ashwink005 | nothing too fancy |
| 02:08 | wasamasa | you would be surprised |
| 02:08 | wasamasa | especially if you're thinking along the lines of google docs |
| 02:09 | ashwink005 | no no I just want a wiki kinda project. Simply allow user to create an entry, update one etc. |
| 02:09 | ashwink005 | this look way to scary |
| 02:10 | wasamasa | such is programming |
| 02:10 | ashwink005 | lol thanks anyways :) |
| 02:10 | wasamasa | the skill of breaking down a problem into small enough chunks to turn them into something the machine can understand |
| 02:11 | neoncontrails | wasamasa: well *I* appreciate the link, I'm adding this to my todo list ;) |
| 02:11 | wasamasa | neoncontrails: you're welcome |
| 02:11 | wasamasa | neoncontrails: it's by magnars which I've originally known for the videos from http://emacsrocks.com/ |
| 02:45 | myguidingstar | ddellacosta, I am looking at your friend-interactive-form-tutorial |
| 02:45 | myguidingstar | but i can't login |
| 02:45 | ddellacosta | myguidingstar: hah, was just working on some oauth2 fixups |
| 02:45 | myguidingstar | I've updated stuff https://github.com/myguidingstar/friend-interactive-form-tutorial |
| 02:46 | ddellacosta | myguidingstar: what is the error you are getting? |
| 02:47 | ddellacosta | myguidingstar: also, this is pretty freaking old, not sure how much things have changed with the recent versions of friend? |
| 02:47 | ddellacosta | whoops, didn't mean to make that a question...haha |
| 02:47 | ddellacosta | myguidingstar: anyways, tell me what exception/error/wrong behavior you are experiencing and I'll see what I can suggest |
| 02:47 | myguidingstar | after entering user+pass, the page still says I didn't log in |
| 02:49 | myguidingstar | friend seems a black box to me :) |
| 02:49 | ddellacosta | myguidingstar: which page, which user, etc.? |
| 02:49 | ddellacosta | myguidingstar: it is a bit tough to wrap your head around. :-/ |
| 02:50 | myguidingstar | I just use http://localhost:3000/login with user/pass pairs defined in source code |
| 02:50 | ddellacosta | myguidingstar: and then, what url is not working for you? |
| 02:51 | myguidingstar | after press 'login' button, I get redirected to "/" with a non-logged-in welcome |
| 02:52 | ddellacosta | myguidingstar: and if you try going to /authorized for example, does that redirect you back to /login ? |
| 02:52 | myguidingstar | and /authorized says that I've not logged in |
| 02:52 | ddellacosta | myguidingstar: does /authorized say "This page can only be seen by authenticated users." ? |
| 02:53 | myguidingstar | hey wait, does that mean I'm authenticad? |
| 02:53 | myguidingstar | then I think it works |
| 02:53 | ddellacosta | myguidingstar: yeah. I suppose that's a bit confusing--probably should say something like "if you see this you have authenticated successfully" |
| 02:53 | myguidingstar | =))) |
| 02:53 | ddellacosta | haha, yep. :-) |
| 02:53 | ddellacosta | sounds like |
| 02:54 | myguidingstar | sorry for the wrong report |
| 02:54 | ddellacosta | myguidingstar: not at all--you've pointed out something confusing in the tutorial. |
| 02:54 | ddellacosta | myguidingstar: would you do me a big favor and create an issue for that? Something like "the message on the authenticated page is not clear" or something |
| 02:55 | myguidingstar | I'll make a PR for that |
| 02:55 | ddellacosta | myguidingstar: cool, thanks! |
| 02:58 | myguidingstar | ddellacosta, I think after logging in, username should be shown in messages |
| 02:59 | myguidingstar | how do I do that? |
| 03:00 | ddellacosta | myguidingstar: you will have to dig into the session to get that information out |
| 03:01 | myguidingstar | oh, I thought that's friend's stuff |
| 03:01 | ddellacosta | myguidingstar: well, it is, but friend stores that in the session |
| 03:02 | myguidingstar | in users: {"admin" {:username "admin" |
| 03:02 | myguidingstar | :password (creds/hash-bcrypt "password") |
| 03:02 | myguidingstar | :roles #{::admin}}} |
| 03:03 | myguidingstar | is the first 'admin' friend's so-called identity? |
| 03:03 | ddellacosta | myguidingstar: I'm not sure I know what you are asking--what are you referring to when you say "friend's so-called identity?" |
| 03:04 | ddellacosta | myguidingstar: friend does story a value in the session it calls "identity:" https://github.com/cemerick/friend/blob/7d286dffcb865c20e9a9c1465dba4f2c5ced7cab/src/cemerick/friend.clj#L64-L68 |
| 03:05 | ddellacosta | myguidingstar: you probably want to use this: https://github.com/cemerick/friend/blob/7d286dffcb865c20e9a9c1465dba4f2c5ced7cab/src/cemerick/friend.clj#L92-L102 |
| 03:05 | myguidingstar | cool, thanks |
| 04:05 | neoncontrails | ,(#(sort > %) '(79 8 92 1 30)) |
| 04:05 | clojurebot | (92 79 30 8 1) |
| 04:06 | neoncontrails | ,((fn [x] (first #(sort > x))) '(79 8 92 1 30)) |
| 04:06 | clojurebot | #error {\n :cause "Don't know how to create ISeq from: sandbox$eval52$fn__53$fn__54"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Don't know how to create ISeq from: sandbox$eval52$fn__53$fn__54"\n :at [clojure.lang.RT seqFrom "RT.java" 535]}]\n :trace\n [[clojure.lang.RT seqFrom "RT.java" 535]\n [clojure.lang.RT seq "RT.java" 516]\n [clojure.lang.RT first "RT.java" 661]\n... |
| 04:07 | neoncontrails | How do you take the first of this? Assuming the call must be tucked inside the S-expr |
| 04:07 | justin_smith | neoncontrails: for starters that doesn't need to be an anonymous function |
| 04:07 | amalloy | uh, don't you just mean (first (sort > x))? |
| 04:08 | justin_smith | ,((fn [x] (first (sort > x))) '(79 8 92 1 30)) |
| 04:08 | clojurebot | 92 |
| 04:08 | justin_smith | ,((fn [x] (apply max x)) '(79 8 92 1 30)) |
| 04:08 | clojurebot | 92 |
| 04:09 | neoncontrails | Ah, I see now. I was overthinking it |
| 04:46 | ashwink005 | what does the :refer and :all keyword mean? |
| 04:50 | oddcully | ashwink005: http://conj.io/store/v1/org.clojure/clojure/1.7.0/clj/clojure.core/require/ |
| 04:50 | oddcully | ``:refer takes a list of symbols to refer from the namespace or the :all keyword to bring in all public vars. |
| 04:50 | ashwink005 | thanks :) |
| 06:30 | darth10 | anyone got an idea on the #= reader macro? |
| 06:31 | darth10 | i cant seem to find much in the docs |
| 06:42 | Rurik | (defn my-first [[first-thing]] first-thing) will give the first thing in the vector |
| 06:43 | Rurik | but what if I want to get the second thing |
| 06:49 | Rurik | got it |
| 06:50 | Rurik | (defn my-second [[_ second]] second) |
| 06:51 | expez | darth10: it's used to eval code at read time |
| 06:54 | expez | ,(read-string "(+ 1 1)" |
| 06:54 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 06:54 | expez | ,(read-string "(+ 1 1)") |
| 06:54 | clojurebot | (+ 1 1) |
| 06:55 | expez | ,(read-string "#= (+ 1 1)") |
| 06:55 | clojurebot | #error {\n :cause "EvalReader not allowed when *read-eval* is false."\n :via\n [{:type java.lang.RuntimeException\n :message "EvalReader not allowed when *read-eval* is false."\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]\n :trace\n [[clojure.lang.Util runtimeException "Util.java" 221]\n [clojure.lang.LispReader$EvalReader invoke "LispReader.java" 1100]\n [clojure.lang.LispRe... |
| 06:55 | expez | ,(binding [*read-eval* :just-do-it] (read-string "#= (+ 1 1)")) |
| 06:55 | clojurebot | 2 |
| 07:04 | Novel2 | I hear you guys are very helpful |
| 07:04 | Novel2 | I hope you know about autohotkey |
| 07:06 | oddcully | if you think the question is relevant to clojure, please ask the question |
| 07:06 | oddcully | ~ask |
| 07:06 | clojurebot | The Ask To Ask protocol wastes more bandwidth than any version of the Ask protocol, so just ask your question. |
| 07:07 | Novel2 | it's not clojure, I'm just desperate for help |
| 07:07 | Rurik | (let [bindings* ] exprs*) |
| 07:07 | Rurik | what does the * means here |
| 07:07 | Rurik | mean |
| 07:07 | expez | Rurik: 0 or more |
| 07:07 | oddcully | Rurik: many bindings |
| 07:07 | Novel2 | I want to trigger a autohotkey script when gpodder downloads something |
| 07:07 | Rurik | ah, thanks |
| 07:08 | oddcully | Novel2: well you might have luck here, but it's OT after all |
| 07:08 | Novel2 | fingers crossed :) |
| 07:11 | Rurik | can anyone explain how I am supposed to use let |
| 07:12 | oddcully | ,(let [n 5 square (* n n)] (print square)) |
| 07:12 | clojurebot | 25 |
| 07:15 | Rurik | got it |
| 07:15 | Rurik | so the part after the bindings gets evaluated |
| 07:15 | wasamasa | well, not really |
| 07:15 | Rurik | no? |
| 07:15 | clojurebot | no is tufflax: there was a question somewhere in there, the answer |
| 07:15 | wasamasa | depends on what you mean with "after the bindings" |
| 07:17 | wasamasa | let is a macro which means its evaluation rules are... different |
| 07:17 | wasamasa | Novel2: isn't autohotkey windows software? |
| 07:19 | Novel2 | yup |
| 07:20 | wasamasa | head over to ##windows |
| 07:21 | Rurik | http://www.braveclojure.com/do-things/#4_2__let |
| 07:21 | Rurik | I don't understand what he is trying to do here |
| 07:21 | TEttinger | Rurik: have you used def yet? |
| 07:21 | Rurik | yes |
| 07:21 | TEttinger | not sure how far in you are |
| 07:22 | TEttinger | ok |
| 07:22 | TEttinger | def creates a "global-like" name that you can use for some value. like (def pi-kinda 3.14) |
| 07:23 | Novel2 | ty |
| 07:23 | TEttinger | but let creates "local" names that you can use for its values, in the section after the square brackets |
| 07:25 | TEttinger | and the names created with let, which are technically called bindings... (because "naming" things means it seems permanent, but let bindings are only bound to a value for a short part of the program) |
| 07:25 | TEttinger | the bindings no longer exist after the let's last ) ends |
| 07:26 | TEttinger | this is useful when you have let inside a function, and you do not, really, you never want to def inside a function just to give a name |
| 07:27 | TEttinger | because def inside a function would still be global, and could cause problems if you have two defs with the same name... or call a function that has (def foo "bar") in it twice. |
| 09:31 | gfredericks | does anybody know how *assert* is intended to be used in libraries? |
| 09:33 | gfredericks | in particular so each namespace can default to on or off, but still provide customizability |
| 09:51 | quique_ | does anyone have a hint how to change the default print behaviour of cider? i'd like to avoid printing out infinite and very large data structures - which happens quite often out of purpose |
| 09:52 | Bronsa | ,*print-length* |
| 09:52 | clojurebot | 5 |
| 09:52 | Bronsa | ,(doc *print-length*) |
| 09:52 | clojurebot | "; *print-length* controls how many items of each collection the printer will print. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum number of items of each collection to print. If a collection contains more items, the printer will print items up to the limit followed by '...' to represent the remaining items. The root binding is... |
| 09:52 | Bronsa | ,(doc *print-depth*) |
| 09:52 | clojurebot | Gabh mo leithscéal? |
| 09:52 | Bronsa | ,(doc *print-level*) |
| 09:52 | clojurebot | "; *print-level* controls how many levels deep the printer will print nested objects. If it is bound to logical false, there is no limit. Otherwise, it must be bound to an integer indicating the maximum level to print. Each argument to print is at level 0; if an argument is a collection, its items are at level 1; and so on. If an object is a collection and is at a level greater than or equal to th... |
| 09:55 | quique_ | perfect thanks, that's what i was looking for |
| 10:15 | namra | can someone recommend some introductory books into game development? |
| 10:16 | genzler | so I have a list like [[1] [[1 1 1] [3] [1 2]] – basically, [[[a] [b]] [[x] [y]]– what's the easiest way to make combinations like [[a x] [a y] [b x] [b y]] – like a cartesian product basically |
| 10:17 | quique_ | @namra check the play-clj library, if you are interesetd in clj game development |
| 10:18 | namra | quique_: thanks i know about that and saw oakes talk, great take. |
| 10:18 | namra | talk |
| 10:18 | quique_ | i agree on that :-) |
| 10:19 | namra | but i'm looking for a general intro, about some techniques and to get some ideas on how to structure it |
| 10:22 | gfredericks | genzler: your first list is rather confusing |
| 10:22 | gfredericks | it has numbers at different levels |
| 10:23 | gfredericks | my guess is that wasn't intentional? |
| 10:24 | genzler | gfredericks: yeah, I think it should be [ [[1]] [[1 1 1] [3] [1 2]] ] |
| 10:24 | genzler | does that sound better? |
| 10:25 | genzler | combo/cartesian-product kinda works, it gives me: (([1 1 1] [1]) ([3] [1]) ([1 2] [1])) |
| 10:26 | lambda-smith | Hm... so you can't use Java static function like this? (map Integer/parseInt '("1" "2")) |
| 10:26 | Bronsa | lambda-smith: correct |
| 10:26 | genzler | but what I want is [[1 1 1 1] [3 1] [1 2 1]] |
| 10:26 | gfredericks | genzler: normally a cartesian product doesn't require so many levels, you just need two collections |
| 10:27 | lambda-smith | I had to do it like this instead: (map #(Integer/parseInt %) '("1" "2")) is this a correct way of doing this? |
| 10:27 | genzler | gfredericks: I sorta want a cartesian product over vectors that would eventually join internal elements |
| 10:27 | gfredericks | genzler: if you took the result from combo/cartesian-product and passed it to (map (fn [[a b]] (into a b)) ____) would that do what you want? |
| 10:27 | genzler | it would be yes |
| 10:27 | genzler | I was wondering if there was a shortcut |
| 10:27 | gfredericks | probably not |
| 10:28 | gfredericks | seems pretty specialized |
| 10:28 | genzler | yeah |
| 10:33 | gfredericks | Bronsa: ping |
| 10:34 | Bronsa | gfredericks: pong |
| 10:34 | gfredericks | Bronsa: I'm writing an email to clojure-dev about *assert* and wanted to clarify how compile-flag-style-dynamic-vars get used |
| 10:35 | gfredericks | the fact that you call set! on them implies they have a thread-local binding, but I don't know where the thread-local binding gets set |
| 10:35 | gfredericks | which I only care about because I'm trying to verify my assumption that set! at the top level of a file only changes the var for that file |
| 10:36 | Bronsa | gfredericks: look at clojure.main/with-bindings |
| 10:37 | gfredericks | ah hah, I knew there must be a whitelist somewhere; I grepped for *assert* and that line came up but I accidentally overlooked it |
| 10:37 | gfredericks | Bronsa: thanks! |
| 10:38 | gfredericks | haha I like the stale docstring |
| 10:38 | Bronsa | gfredericks: AFAIK set! ing *assert* is not a per-file/per-namespace local change |
| 10:39 | gfredericks | Bronsa: well presumably if it's not then neither is set!ing anything else in this whitelist? |
| 10:40 | gfredericks | er... |
| 10:40 | Bronsa | gfredericks: not necessarily, I don't recall if RT.load/Compiler.load bind any dyn var |
| 10:40 | gfredericks | I was assuming that this would have to be involved in calling require but I doubt anything in clojure.main could play that role |
| 10:40 | gfredericks | alright well I'm gonna run a test project to find out at least |
| 10:41 | Bronsa | gfredericks: looking at RT.load I see that at least warn-on-reflection and unchecked-math get bound |
| 10:41 | Bronsa | meaning set!ing them is not per-file/per-namespace local but at least load-local |
| 10:42 | gfredericks | oh okay, so there's a different whitelist |
| 10:42 | Bronsa | like, if you have (require 'foo) and you have (set! warn-on-reflection true) (ns foo (:require [bar])) .. |
| 10:42 | Bronsa | both foo and bar will have w-o-r true |
| 10:42 | Bronsa | but the top-ns won't |
| 10:42 | gfredericks | right |
| 10:43 | Bronsa | otoh set!ing assert to true in foo should make assert true in the top ns too since there's no dynamic boundary in place |
| 10:43 | gfredericks | yep, just confirmed that set! with *assert* is leaky |
| 10:44 | gfredericks | so why did *assert* have a thread-local binding in the first place? |
| 10:45 | gfredericks | the thing in clojure.main I guess? |
| 10:45 | gfredericks | yeah |
| 10:45 | gfredericks | Bronsa: okay I think that sets me straight, thanks again |
| 10:46 | Bronsa | yes |
| 10:46 | Bronsa | np |
| 10:46 | gfredericks | (inc Bronsa) |
| 10:46 | lazybot | ⇒ 121 |
| 11:06 | sdegutis | Bronsa: Isn't (set! *warn-on-reflection* true) only good for the thread you're calling it on? |
| 11:06 | sdegutis | Don't you have to use alter-var-root instead? |
| 11:08 | gfredericks | sdegutis: it's normally used when compiling, which is single-threaded |
| 11:08 | sdegutis | Oooh good point. |
| 11:09 | sdegutis | Where should it be set, maybe in :injections? |
| 11:09 | gfredericks | or rather, you *do* only want it to change for the thread you're calling it on |
| 11:09 | sdegutis | Btw I'm using clojure.test along with clojure-tests-mode + Cider (in Emacs) and it's AWESOME. |
| 11:09 | gfredericks | sdegutis: normally you see (set! *warn-on-reflection* true) at the top level of the top of a file, and the intention is to only change it while compiling that file, and it works perfectly for that |
| 11:10 | gfredericks | if you want to enable it for your whole project & libraries that's a different use case |
| 11:11 | sdegutis | gfredericks: ahhh |
| 11:14 | gfredericks | leiningen has a feature specifically for that I think, and it might just boil down to :injections |
| 11:15 | sdegutis | Wow clojure-mode has improved a lot over the past 2 years. |
| 11:38 | sdegutis | gfredericks: ah, found it -- leiningen has a :global-vars key that can be used in the :test profile etc |
| 11:38 | gfredericks | right |
| 11:43 | sdegutis | I don't understand this reflection warning: |
| 11:43 | sdegutis | "call to static method abs on java.lang.Math can't be resolved (argument types: java.lang.Number)." |
| 11:43 | gfredericks | sdegutis: what does the call look like? |
| 11:43 | gfredericks | Math/abs can take double/float/int/long so it has to be able to figure out which of those you want |
| 11:43 | sdegutis | ,(-> 50 (- 33) (Math/abs)) |
| 11:43 | sdegutis | That. |
| 11:43 | clojurebot | 17 |
| 11:44 | sdegutis | I thought java.lang.Number is already statically resolved? |
| 11:44 | gfredericks | sdegutis: your code has literals in it exactly like that? |
| 11:44 | sdegutis | Nope, |
| 11:44 | gfredericks | okay that's an important difference for reflection purposes |
| 11:44 | sdegutis | 50 is gotten from clojure.core/frequences |
| 11:45 | gfredericks | you could e.g. pass through (long) before Math/abs and that should make it go away |
| 11:45 | sdegutis | Ah nice, thanks. |
| 11:46 | gfredericks | (defn long-abs [^long x] (Math/abs x)) ;; ← should also not reflect |
| 11:46 | sdegutis | Ah nice. |
| 11:47 | gfredericks | I think the error msg was trying to tell you that the only thing it could tell about the arg to Math/abs was that it was a java.lang.Number and that wasn't enough to pick a particular impl |
| 11:47 | Rurik | what does ^long do? |
| 11:48 | gfredericks | it's a type hint, which the compiler uses for compiling interop and occasionally for compiling the code to use primitives |
| 11:48 | gfredericks | virtually never necessary except for performance |
| 11:49 | Rurik | ah, the java long type? |
| 11:49 | gfredericks | yeah, the primitive type in this case |
| 11:49 | gfredericks | (i.e., not java.lang.Long) |
| 11:52 | sdegutis | gfredericks: thanks a ton |
| 11:53 | gfredericks | np |
| 11:58 | sdegutis | How can you type-hint a binding inside (let)? |
| 11:58 | sdegutis | Can you just do this? |
| 12:00 | sdegutis | ,(let [a [1 2 3], z (map long a), [_ ^:long b] z] (= b 2)) |
| 12:00 | clojurebot | true |
| 12:01 | sdegutis | Neat. |
| 12:01 | gfredericks | it'b be ^long instead of ^:long |
| 12:01 | sdegutis | Oops. |
| 12:01 | gfredericks | but that test doesn't tell you if it works or not |
| 12:01 | sdegutis | ,(let [a [1 2 3], z (map long a), [_ ^long b] z] (= b 2)) |
| 12:01 | clojurebot | true |
| 12:01 | sdegutis | Oh right. |
| 12:01 | sdegutis | ,(binding [*warn-on-reflection* true] (let [a [1 2 3], z (map long a), [_ ^long b] z] (= b 2))) |
| 12:01 | clojurebot | true |
| 12:01 | sdegutis | ,(binding [*warn-on-reflection* true] (let [a [1 2 3], z (map long a), [_ b] z] (= b 2))) |
| 12:01 | clojurebot | true |
| 12:01 | gfredericks | I think the best way to experiment is to set *warn-on-reflection* to true at your repl and play with things |
| 12:01 | sdegutis | :'( |
| 12:01 | gfredericks | sdegutis: that binding doesn't work either |
| 12:01 | gfredericks | (set! ...) at the repl should help |
| 12:02 | sdegutis | ,(set! *warn-on-reflection* true) |
| 12:02 | clojurebot | #error {\n :cause "Can't change/establish root binding of: *warn-on-reflection* with set"\n :via\n [{:type java.lang.IllegalStateException\n :message "Can't change/establish root binding of: *warn-on-reflection* with set"\n :at [clojure.lang.Var set "Var.java" 221]}]\n :trace\n [[clojure.lang.Var set "Var.java" 221]\n [sandbox$eval125 invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$eval125 invo... |
| 12:02 | sdegutis | Welp, clojurebot isn't useful here. |
| 12:02 | sdegutis | Thanks again gfredericks |
| 12:03 | gfredericks | np |
| 12:04 | sdegutis | Hmm this doesn't warn, gfredericks. |
| 12:04 | sdegutis | (let [a [1 2 3], [_ b] a] (= b 2)) |
| 12:04 | sdegutis | I just set warning to true. |
| 12:05 | gfredericks | there's no interop involved |
| 12:05 | gfredericks | so no reflection needed |
| 12:05 | sdegutis | Hmmmmm.... |
| 12:05 | gfredericks | try calling (Math/abs b) or something |
| 12:06 | sdegutis | ,(binding [*warn-on-reflection* true] (let [a (map #(Math/abs %) [1 2 3]), [_ b] a] (= b 2))) |
| 12:06 | clojurebot | true |
| 12:06 | sdegutis | Well it works in my repl :D |
| 12:06 | sdegutis | Thanks! |
| 12:07 | gfredericks | sdegutis: the binding call is a runtime thing so it's not having any effect |
| 12:07 | sdegutis | And yeah, this style of type-hinting works: (let [a [1 2 3], [_ ^long b] a] (Math/abs b)) |
| 12:07 | sdegutis | It stops the warning. |
| 12:07 | gfredericks | right |
| 12:08 | sdegutis | gfredericks: very true, my example was wrong |
| 12:08 | sdegutis | (the first one) |
| 12:08 | sdegutis | I'm surprised Clojure lets it work inside destructuring. |
| 12:08 | sdegutis | Woo! Time to fix a million reflection errors. |
| 12:09 | sdegutis | gfredericks: An incorrect type-hint has absolutely no effect on the running code, right? |
| 12:09 | gfredericks | yeah, the let macro preserves the metadata when it expands |
| 12:09 | gfredericks | sdegutis: 99% of the time yes |
| 12:09 | gfredericks | well depends on if by "effect" you meant just correctness or also performance |
| 12:10 | gfredericks | obviously you can have worse performance if you screw up the type hinting and thereby get reflection |
| 12:10 | gfredericks | you can also get incorrect code if the type-hint successfully causes the compiler to compile to the wrong interop method |
| 12:10 | sdegutis | I meant like introducing bugs. |
| 12:10 | gfredericks | trying to think of way to demonstrate that |
| 12:10 | sdegutis | Yeah that's what I had in mind. |
| 12:11 | Bronsa | gfredericks: invalid type hints are also not always ignored |
| 12:11 | sdegutis | Like if I type-hinted .replace on some obscure PDF type rather than String or whatever. |
| 12:11 | gfredericks | ,(defn make-bigint [s] (BigInteger. s)) |
| 12:11 | clojurebot | #'sandbox/make-bigint |
| 12:11 | gfredericks | ,(make-bigint "42") |
| 12:11 | clojurebot | 42 |
| 12:11 | gfredericks | ,(defn make-bigint [^bytes s] (BigInteger. s)) |
| 12:11 | clojurebot | #'sandbox/make-bigint |
| 12:11 | gfredericks | ,(make-bigint "42") |
| 12:11 | clojurebot | #error {\n :cause "java.lang.String cannot be cast to [B"\n :via\n [{:type java.lang.ClassCastException\n :message "java.lang.String cannot be cast to [B"\n :at [sandbox$make_bigint invokeStatic "NO_SOURCE_FILE" -1]}]\n :trace\n [[sandbox$make_bigint invokeStatic "NO_SOURCE_FILE" -1]\n [sandbox$make_bigint invoke "NO_SOURCE_FILE" -1]\n [sandbox$eval95 invokeStatic "NO_SOURCE_FILE" 0]\n [san... |
| 12:12 | gfredericks | ^ like that |
| 12:12 | Bronsa | http://dev.clojure.org/jira/browse/CLJ-1674 |
| 12:12 | gfredericks | the first one reflected, the second one crashed |
| 12:30 | Stalkr_ | I'm considering playing around with Clojure(Script) and emacs seems to be the superior editor between emacs and Vim. I have been using Vim for a few years though. Anyone recommend switching to emacs for Clojure with Evil mode? |
| 12:33 | sdegutis | I wonder if it also works in doto |
| 12:36 | wasamasa | Stalkr_: feel free to give it a try |
| 12:36 | Deraen | Stalkr_: I hear Spacemacs is quite good: https://github.com/syl20bnr/spacemacs But I use Vim myself, works fine in my opinion. |
| 12:36 | wasamasa | Stalkr_: be aware though that even with vim keybindings, emacs is a much more complex beast than vim |
| 12:37 | wasamasa | Stalkr_: so, while the IDE-style extensions are quite impressive, you will run into problems you'd have never encountered with vim :P |
| 12:38 | Deraen | Vim also has access to (some of) the same IDE-style extensions that Emacs has |
| 12:39 | Stalkr_ | Never heard about Spacemacs. I will have to give emacs/Spacemacs a shot, just wanted to hear others opinion :-) |
| 12:39 | Bronsa | Stalkr_: if you're not set to use either vim or emacs I'd suggest trying cursive |
| 12:39 | Stalkr_ | That's a JetBrains IDE right? |
| 12:39 | Bronsa | https://cursiveclojure.com/ |
| 12:40 | Bronsa | it's built in top of intellij, yes |
| 12:42 | Stalkr_ | Ahh, thought it was from JetBrains too. I like to stay away from IDEs unless it is Java, C# or related but can't hurt to give it a try (y) |
| 13:51 | red_rev | Hey all. I want to learn clojure. Can anyone point me to an IDE for GNU/Linux? |
| 13:52 | justin_smith | red_rev: for a full IDE experience I'd go with cursive |
| 13:52 | justin_smith | red_rev: there are good bindings for emacs and vim too though |
| 13:52 | red_rev | Awesome1 Thanks. |
| 13:53 | red_rev | any tips for Switching over from OO based languages? |
| 13:53 | justin_smith | red_rev: what lang are you coming from? |
| 13:54 | justin_smith | RE: IDE I'd also suggest learning how to look up docs and reload namespaces in the repl - if nothing else just to realize none of it is magic and most of it is done with regular clojure features |
| 13:56 | justin_smith | red_rev: one of the most interesting differences between OO and FP is that good OO hides ugly stuff deep under class interfaces, and good FP pushes the ugly stuff outward to the interface -- this is even a clue about how to use them together nicely |
| 13:57 | sdegutis | Can you type hint a Java list? |
| 13:58 | sdegutis | ^java.util.List<some.Thing> like that? |
| 13:58 | justin_smith | sdegutis: generics don't exist |
| 13:58 | justin_smith | ^List is all you need |
| 13:58 | sdegutis | Oh. |
| 13:58 | sdegutis | So then I have to type-hint ^some.Thing when I take an item out? |
| 13:58 | justin_smith | sdegutis: well, generics kind of exist, but only inside the java compiler, which we don't use |
| 13:58 | justin_smith | sdegutis: yes, because the vm does not enforce anything about generics |
| 13:59 | sdegutis | wompwomp |
| 13:59 | gratimax | sdegutis: are you doing this for java interop? |
| 13:59 | red_rev | Justin_smith I've programmed mostly in python and Java |
| 13:59 | sdegutis | gratimax: yeah, using Stripe's Java SDK. |
| 13:59 | sdegutis | Just adding type hinting for it. |
| 13:59 | sdegutis | The new magit rocks btw. |
| 14:00 | gratimax | you might want to wrap it lightly in java classes that take clojure collections instead of lists |
| 14:01 | gratimax | I personally do that for java interop just so that it stays mostly clojure datastructures, even if under the hood it's not |
| 14:02 | sdegutis | Ahh nice idea. |
| 14:04 | Bronsa | gratimax: clojure collections already implement many java collection interfaces |
| 14:04 | gratimax | that's true |
| 14:07 | gratimax | I guess I should have elaborated, I meant more that it takes clojure collections with maps, etc. that get converted to the equivalent java objects |
| 15:25 | justin_smith | ,(defn youngest-datable [age] (+ 7.0 (/ age 2))) |
| 15:25 | clojurebot | #'sandbox/youngest-datable |
| 15:25 | justin_smith | ,(clojure.string/join "," (map (juxt identity, youngest-datable) (range 50))) |
| 15:25 | clojurebot | "[0 7.0],[1 7.5],[2 8.0],[3 8.5],[4 9.0],[5 9.5],[6 10.0],[7 10.5],[8 11.0],[9 11.5],[10 12.0],[11 12.5],[12 13.0],[13 13.5],[14 14.0],[15 14.5],[16 15.0],[17 15.5],[18 16.0],[19 16.5],[20 17.0],[21 17.5],[22 18.0],[23 18.5],[24 19.0],[25 19.5],[26 20.0],[27 20.5],[28 21.0],[29 21.5],[30 22.0],[31 22.5],[32 23.0],[33 23.5],[34 24.0],[35 24.5],[36 25.0],[37 25.5],[38 26.0],[39 26.5],[40 27.0],[41 2... |
| 15:37 | TimMc | justin_smith: "Asking for a friend." |
| 15:37 | justin_smith | TimMc: it's a classic formula, I find the results for lower inputs hilarious |
| 15:37 | TimMc | up :-) |
| 15:37 | TimMc | *yup |
| 15:37 | justin_smith | "if you are an infant, the youngest person you can date is 7" |
| 15:51 | TimMc | I wonder if there is an age that most people agree on as a lower bound for inputs to that formula. |
| 15:52 | justin_smith | TimMc: very likely 14 |
| 15:52 | TimMc | or if it just gets progressively more absurd |
| 15:52 | justin_smith | ,(youngest-datable 100) |
| 15:52 | clojurebot | #error {\n :cause "Unable to resolve symbol: youngest-datable in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: youngest-datable in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve... |
| 15:53 | justin_smith | ,(defn youngest-datable [age] (+ 7.0 (/ age 2))) |
| 15:53 | clojurebot | #'sandbox/youngest-datable |
| 15:53 | justin_smith | ,(youngest-datable 100) |
| 15:53 | clojurebot | 57.0 |
| 15:53 | justin_smith | yeah, I think that aproximation could be improved |
| 15:56 | justin_smith | like any two people over 80 should be able to date, I see no reason a 500 year old and a 100 year old wouldn't get along just fine |
| 16:00 | diyfupeco | .(youngest-datable 42) |
| 16:00 | diyfupeco | ,(youngest-datable 42) |
| 16:00 | clojurebot | 28.0 |
| 16:00 | diyfupeco | ^ That is wrong, sorry guys. :D |
| 16:00 | justin_smith | yeah, I didn't make the formula up - now I wonder where it comes from... |
| 16:01 | gfredericks | justin_smith: you say that just because you can't relate to either of them |
| 16:01 | gfredericks | wait till you're 100 and I think you'll change your mind about the 500yo's |
| 16:01 | justin_smith | haha |
| 16:02 | justin_smith | "Elijah Muhammad (1897-1975) said that the ideal age of a man's wife was half his age, plus seven." |
| 16:03 | diyfupeco | Very subjective view. |
| 16:03 | gfredericks | ideal != youngest-allowable |
| 16:03 | diyfupeco | :D |
| 16:03 | justin_smith | gfredericks: yeah, he was brought up as an outlier |
| 16:03 | diyfupeco | Well, that would be 14 in Germany I think, no matter what age. |
| 16:03 | justin_smith | http://www.onehalfplusseven.com/home/about-the-half-your-age-plus-seven-rule |
| 16:03 | TimMc | wait wait wait, this is the Nation of Islam guy? |
| 16:03 | justin_smith | yeah |
| 16:03 | TimMc | fascinating |
| 16:05 | justin_smith | "Although the origin of the rule is unclear, it is sometimes considered to have French origin.[20] There is no scientific evidence to support the rule."\ |
| 16:05 | justin_smith | https://en.wikipedia.org/wiki/Age_disparity_in_sexual_relationships#The_.22half-your-age-plus-seven.22_rule |
| 16:05 | TimMc | I can't believe someone registered a domain for that. |
| 16:05 | diyfupeco | :D |
| 16:05 | justin_smith | oldest citation is 1901 |
| 16:06 | justin_smith | and yeah, the version from 1901 was "ideal age" - not lower limit |
| 16:06 | justin_smith | ideal age for bride of course |
| 16:06 | TimMc | Interesting that as the two people age, they can only transition from "unacceptable" to "acceptable". |
| 16:07 | diyfupeco | You know what the problem is? That we are measuring age in years and not experience. |
| 16:07 | justin_smith | if only our popular understanding of aging was more nuanced, the range could narrow or expand following some polynomial |
| 16:08 | justin_smith | husband who is her age minus 7 * 2, not that anybody cares what is ideal for her in 1901 anyway :) |
| 16:08 | diyfupeco | TimMc: income = age * 1.500+ |
| 16:09 | diyfupeco | (Was that to sexist?) |
| 16:09 | TimMc | probably |
| 16:09 | TimMc | also you didn't specify units |
| 16:09 | diyfupeco | :( |
| 16:10 | diyfupeco | I am terrible at this. |
| 16:10 | justin_smith | wait, "income = age * 1.5" could approximate us hourly wages in dollars ... |
| 16:10 | justin_smith | no, starts too high |
| 16:10 | TimMc | way too high if you're doing years and dollars |
| 16:11 | justin_smith | yeah |
| 16:11 | diyfupeco | I was thinking in € |
| 16:11 | diyfupeco | and over a year |
| 16:11 | justin_smith | oh, where . is american , |
| 16:12 | diyfupeco | Yes. :D |
| 16:14 | justin_smith | OK how about simplest formula that would approximate height by age |
| 16:15 | diyfupeco | I can't follow. |
| 16:15 | justin_smith | eg f(age) ~= average height |
| 16:16 | justin_smith | with bonus for exceeding accuracy or simplicity (ideally both) |
| 16:17 | TimMc | Next you need a metric for "simplicity". |
| 16:17 | justin_smith | we'll know it when we see it |
| 16:26 | diyfupeco | Hm, I could provide data about age samples but not about height :D |
| 16:28 | diyfupeco | Hm, what I do wonder though if sexuality matters. |
| 16:29 | justin_smith | ,(defn age->inches [age] (+ 30.0 (* (min age 17) 2.41))) ; matches this chart for white boys pretty well http://halls.md/chart/BoysHeightWhite.gif |
| 16:30 | clojurebot | #'sandbox/age->inches |
| 16:31 | diyfupeco | justin_smith: What about conditions which lead to dwarfism (I hope this is a politically correct term in english)? |
| 16:32 | justin_smith | haha, the term is fine and yeah of course a formula accounting for dwarfism would be much different |
| 16:34 | diyfupeco | Well, in german the same term translated is not ok. :D |
| 16:34 | justin_smith | like you would need an input for chromosomes or something |
| 16:34 | diyfupeco | Hm. |
| 16:35 | diyfupeco | If we had chromosome input we could just find the perfect match, since some studies found that we search for the genetical opposite. |
| 16:36 | justin_smith | I'm sure we'd have mapping from various chromosome sets to charts like the above but with much narrower distribution ranges, and then a near-linear function (through the range of growth ages) for each chromosome set |
| 16:36 | justin_smith | sorry, I'm not sure, I just suspect |
| 17:14 | arkh | anyone used raynes/conch before? I've going over the code for a while now and I just can get e.g. the following last function to work: https://www.refheap.com/6617/raw |
| 17:14 | arkh | *I've been |
| 17:14 | arkh | *can't |
| 17:14 | arkh | also, can't type |
| 17:15 | gfredericks | arkh: I've used it a few times |
| 17:15 | justin_smith | I've used it, but ended up just using ProcessBuilder directly |
| 17:16 | arkh | does the last function in the above refheap look like it should still run? |
| 17:16 | arkh | sorry, probably tough to say just be eyeballing it |
| 17:16 | justin_smith | arkh: you have an "unbuffer" program on your path? |
| 17:17 | arkh | I don't - I ended up doing a (let-programs ..) instead with the path to ssh specified |
| 17:17 | arkh | I should have mentioned that |
| 17:17 | arkh | it was the one change I amde |
| 17:17 | arkh | *made |
| 17:19 | arkh | (let-programs [p "/bin/cat"] (let [proc (p "stuff")] ... ) returns with a non-zero error code, too |
| 17:20 | arkh | with matching parens of course |
| 17:20 | fierycatnet | Is there a way to read from stdio and return these values in a vector/list form? ex: 1 2 3 is entered and it returns [1 2 3]. So far I can only get it to return "1 2 3" as a string or "1 2 3" as a persistent vector. |
| 17:20 | justin_smith | arkh: and you have a file called "stuff" in the current directory? |
| 17:21 | arkh | oh |
| 17:21 | arkh | I don't! |
| 17:21 | arkh | ok - echo works |
| 17:21 | justin_smith | fierycatnet: ##(mapv read-string (clojure.string/split #" " "1 2 3")) maybe? |
| 17:21 | lazybot | java.lang.ClassCastException: java.lang.String cannot be cast to java.util.regex.Pattern |
| 17:21 | justin_smith | erp |
| 17:22 | justin_smith | fierycatnet: ##(mapv read-string (clojure.string/split "1 2 3" #" ")) maybe? |
| 17:22 | lazybot | ⇒ [1 2 3] |
| 17:22 | justin_smith | it really depends on how much you trust the input source and what you really want to do with the data coming in I guess |
| 17:23 | fierycatnet | justin_smith: that might just work, i'll play with it, thanks. It's just for an exercise, nothing critical. |
| 17:23 | justin_smith | fierycatnet: perhaps you could string/split each line of input and work with the strings - that's less error-prone |
| 17:27 | fierycatnet | I think I've tried similar code before but I only used map instead of mapv, I guess there is a significant difference between the two? I was getting errors when I tried regular map function. |
| 17:28 | justin_smith | fierycatnet: I only used mapv because you specified the result being in a vector |
| 17:28 | justin_smith | other than that (and mapv not being lazy, because vectors are not lazy) they are the same |
| 17:28 | arkh | any thoughts on the following use of conch? https://www.refheap.com/108955 |
| 17:28 | fierycatnet | I was doing something wrong then |
| 17:29 | justin_smith | arkh: are you getting the output from stderr? |
| 17:30 | justin_smith | arkh: because iirc the prompts from ssh before connecting will be on stderr |
| 17:30 | justin_smith | arkh: may be easier to interact with a less tricky interactive program first (eg. cat or ed) |
| 17:31 | arkh | I'm able to get non-persistent programs to run, like cat |
| 17:31 | justin_smith | so next step would be interactive but less tricky (ed is a good one, as is bc) |
| 17:31 | arkh | when I run the above (from refheap) I get this to my console: rwaters@localhost's password: |
| 17:31 | arkh | hmm |
| 17:31 | justin_smith | that sounds like an expected output... |
| 17:31 | arkh | yeah, I could try bc |
| 17:32 | arkh | it is expected, but I can't seem to hook into it at all |
| 17:32 | arkh | I can't grab (:stderr proc), etc. |
| 17:32 | justin_smith | well, you need to get a handle to proc stdin from conch right |
| 17:32 | arkh | eventually |
| 17:32 | justin_smith | I think :seq true is incompatible with the kind of interaction you want |
| 17:33 | arkh | oh |
| 17:33 | justin_smith | :seq is for nice packaged output of non-interactive stuff iirc |
| 17:33 | justin_smith | arkh: what I found is that I could make a ProcessBuilder, launch that, get stdin, stdout, stderr from the resulting process, and interact with those via .read and .write and .flush |
| 17:34 | justin_smith | and it was simpler for me than using conch was |
| 17:34 | justin_smith | ymmv of course, I often find clojure libs that wrap some java libs are just a pain in the ass |
| 17:34 | arkh | sure - I might do that too |
| 17:35 | justin_smith | but maybe you just need to find some alternative for the :seq option |
| 17:35 | justin_smith | something that lets you be more interactive, though I suspect that will involve .read and .write and .flush calls |
| 17:35 | arkh | I've been looking into https://github.com/ronniedong/Expect-for-Java which uses jsch (same as clj-ssh) and some nice java.nio non-blocking, selectable channels but thought conch would be a faster way to get to the end goal (if I could just get it to work) |
| 17:36 | arkh | I was a little concerned with how futures are used in conch but I guess the threads would be returned to clojure's thread pool with the process exits |
| 17:37 | justin_smith | that's how futures work, yeah. And they use an expandable pool. |
| 17:37 | arkh | oh - I thought it was fixed; good to know |
| 17:37 | justin_smith | agents have two pools, a fixed send pool and expandable send-off pool, futures share the latter |
| 17:38 | arkh | ok. And core.async has its own fixed thread pool? |
| 17:38 | justin_smith | yup |
| 17:38 | arkh | cool |
| 17:38 | justin_smith | 2*nprocs+42 |
| 17:40 | arkh | thanks for your help |
| 17:46 | justin_smith | no problem, best of luck! |
| 18:42 | TimMc | justin_smith: nprocs/2+7 ;-) |
| 19:58 | python476 | hi |
| 20:00 | python476 | noob question: (.. (new JFrame) getContentPane add (new JLabel "wat")) fails saying `add` can't be found |
| 20:01 | justin_smith | python476: I'm thinking add needs some arg |
| 20:02 | python476 | justin_smith: aight, I'll look into it |
| 20:03 | justin_smith | python476: my suspicion is (.. (new JFrame) getContentPane (add (new JLabel "wat))) |
| 20:03 | python476 | justin_smith: right, I just tried that, so ..nooby |
| 20:03 | python476 | thanks |
| 20:03 | justin_smith | the better version of that is (.. (Jframe.) getContentPane (add (JLabel. "wat"))) |
| 20:07 | amalloy | i suspect (doto (JFrame.) (-> (.getContentPane) (.add (JLabel. "wait")))) is better still, because you surely need to return the jframe |
| 20:08 | amalloy | you can use .. if you want, but i think -> reads better basically all the time even if it's more characters |
| 20:08 | python476 | amalloy: also more readable |
| 20:08 | python476 | hehe |
| 20:08 | python476 | but I'm not comfy with the subtle difference between . .. -> and such |
| 20:08 | python476 | I was experimenting |
| 20:09 | amalloy | doto and -> go together like peanut butter and jelly, for java interop |
| 20:35 | mdeboard | Hi, how might I simplify this sexpr: (json/read-str (:message (json/read-str js :key-fn key->keyword)) :key-fn key->keyword) |
| 20:35 | mdeboard | That is, is there some kind of "reduce" call I can use? I know I can write a function to do so |
| 20:36 | mdeboard | some specialized function, just asking out of curiosity |
| 20:36 | amalloy | you have a string representing json object that contains a field whose value is a string representing another json object? |
| 20:36 | amalloy | (i heard you like json) |
| 20:37 | mdeboard | Yeah, it's like {"Message" "{\"foo\" : \"bar\"}"} |
| 20:37 | mdeboard | Yeah I'm processing AWS events |
| 20:37 | mdeboard | this is what they do :( |
| 20:37 | justin_smith | (let [rd #(json/read-str % :key-fn key->keyword)] (-> js rd :message rd)) |
| 20:37 | TEttinger | (inc justin_smith) |
| 20:37 | lazybot | ⇒ 292 |
| 20:37 | TEttinger | (inc amalloy) |
| 20:37 | lazybot | ⇒ 296 |
| 20:37 | mdeboard | Ok that's basically what I was thinking justin_smith , thanks |
| 20:37 | TEttinger | (inc yo dawg) |
| 20:37 | lazybot | ⇒ 1 |
| 20:37 | mdeboard | It just vaguely looks like a reduce |
| 20:38 | mdeboard | Didn't know if there was some higher order deal |
| 20:38 | amalloy | mdeboard: if you had more layers, it would be worth making a reduce out of it |
| 20:38 | mdeboard | Yeah, just curious |
| 20:38 | Bronsa | looks more like a prewalk than a reduce to me |
| 20:39 | amalloy | (reduce (fn [m f] (f (json/read-str m :key-fn key->keyword))) s [:message identity]) |
| 20:41 | amalloy | Bronsa: that wastes a lot of effort on a json object with high branching factor where you only care about one deep path |
| 20:41 | Bronsa | ah, risght |
| 20:46 | arrdem | gfredericks: just saw your ML post... I think the "real" anwer is that `ns` should automate that for you, but it'll never happen |
| 20:47 | agumonkey | any emacs user ? emacsconf 2015 is on |
| 20:47 | agumonkey | http://www.twitch.tv/emacsconf , also #emacsconf |
| 20:55 | justin_smith | gfredericks: perhaps your own macro, which uses the value of *gfredericks-assert* |
| 20:57 | arrdem | I mean... what we really need is compiler support for the JVM assert stuff |
| 20:58 | justin_smith | also, related, I have a pet peeve about code that changes behavior if *assert* is turned off (beyond just halting and catching fire of course) |
| 20:58 | justin_smith | arrdem: would that solve gfredericks issue though? |
| 20:58 | Bronsa | arrdem: there's no assert support in the jvm |
| 20:59 | arrdem | Bronsa: I thought there was a JVM flag to disable Java asserts |
| 20:59 | arrdem | obviously no assert instr |
| 20:59 | Bronsa | arrdem: it just uses an internal field |
| 21:00 | justin_smith | arrdem: there is definitely a flag for the jvm yeah see this convo https://groups.google.com/forum/#!topic/clojure/B9ba-ExZGzI |
| 21:01 | arrdem | justin_smith: Bronsa is as usual correct, just uses the AssertTest.$assertionsDisabled field |
| 21:01 | arrdem | so there's a java.lang.AssertTest class or something that holds the on/off bit |
| 21:01 | rhg135 | Is there any data structure that supports near constant time retrieval of a random element and no duplicates. A set would fulfill the latter but not the former |
| 21:09 | gfredericks | justin_smith: yeah having to rewrite the whole assert/*assert* thing does kind of suggest that it's not covering all the use cases :P |
| 21:15 | amalloy | rhg135: i think you would do it by taking the data structure that is currently used for sets, and adding to each node a count of how many items are in each of its subtrees, and use that to weighted-choose which branch to go down |
| 21:17 | rhg135 | Sounds like it'd require a lot of code, amalloy, guess it'll have to be O(n) for now |
| 21:17 | justin_smith | amalloy: would that interact weirdly with structural sharing? |
| 21:17 | amalloy | justin_smith: i don't think so. you should still only have to rebuild the path back to the root, right? |
| 21:17 | justin_smith | rhg135: what about a tuple with set and vector, and only inserting in the vector if the item isn't in the set yet |
| 21:17 | justin_smith | amalloy: fair point, yeah |
| 21:18 | amalloy | justin_smith: the problem with a set/vector pair is that you can't remove stuff from the middle of the vector |
| 21:18 | justin_smith | yeah, not cheaply at least, but he didn't mention removal :P |
| 21:18 | amalloy | oh. i misread retrieval |
| 21:19 | amalloy | yeah if you never take anything out, a set/vector pair is fine |
| 21:20 | justin_smith | and even if he does occasional removals, it's still better than O(n) insertion which was the other interem plan |
| 21:20 | justin_smith | *interim |
| 21:20 | rhg135 | Yeah, I don't plan on removal, justin_smith |
| 21:20 | rhg135 | even than it'd be uncommon |
| 21:21 | justin_smith | so yeah, I think that pair of set/vector is the easiest thing, and will perform decent enough |
| 21:21 | rhg135 | my other plan was keep a set and do an O(n) conversion to a vector |
| 21:21 | rhg135 | on demand for retrievals |
| 21:22 | rhg135 | how would a set/vector pair work though? |
| 21:22 | arrdem | so if you want "only once" insertions, what name are you trying to retrieve these things by? |
| 21:23 | rhg135 | name? |
| 21:23 | justin_smith | rhg135: for conj you check set membership, if absent conj to both, for presence / lookup you just use the set, for random selection use the vector |
| 21:23 | arrdem | which is not unique? I'm just wondering if you're overthinking a {name -> T{:name = name}} structure of some sort |
| 21:26 | rhg135 | I'm sorry, arrdem, my brain is not cooperating. |
| 21:27 | arrdem | All good I have no idea what you're actually trying to do and may have proposed something nonsensical |
| 21:28 | rhg135 | I'm basically hava a structure of {vector x} where x is a structure where I can get items out randomly quickly and has no duplicates |
| 21:32 | rhg135 | what interfaces do I have to implement then? |
| 21:32 | Bronsa | all of them! |
| 21:32 | arrdem | lol |
| 21:33 | arrdem | wait but which are interfaces and which are implementation details... |
| 21:33 | rhg135 | brb |
| 21:34 | Bronsa | rhg135: IPersistentMap, IPersistentSet, IObj probably |
| 21:34 | justin_smith | Bronsa: what about the one for nth? |
| 21:34 | justin_smith | I forget which one that is even |
| 21:34 | Bronsa | IEditableCollection if you want to be fancy |
| 21:34 | justin_smith | for rand-nth he needs to support nth |
| 21:35 | Bronsa | wait, he wants set+vector semantics |
| 21:35 | justin_smith | yeah |
| 21:35 | Bronsa | then IPersistentVector, IPersistentSet, IObj |
| 21:35 | Bronsa | justin_smith: nth is Indexed |
| 21:35 | justin_smith | aha |
| 21:35 | Bronsa | which is a super interface of IPersistentVector |
| 21:37 | Bronsa | ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (merge ifs (map supers ifs))) |
| 21:37 | clojurebot | #{clojure.lang.IPersistentSet clojure.lang.IPersistentVector clojure.lang.IObj (#{clojure.lang.IPersistentCollection clojure.lang.Counted clojure.lang.Seqable} #{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.Associative clojure.lang.Indexed clojure.lang.Reversible ...} #{clojure.lang.IMeta})} |
| 21:37 | Bronsa | ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (apply merge ifs (map supers ifs))) |
| 21:37 | clojurebot | #{#{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.Associative clojure.lang.Indexed clojure.lang.Reversible ...} clojure.lang.IPersistentSet clojure.lang.IPersistentVector #{clojure.lang.IMeta} #{clojure.lang.IPersistentCollection clojure.lang.Counted clojure.lang.Seqable} ...} |
| 21:37 | Bronsa | ,(let [ifs #{clojure.lang.IPersistentVector clojure.lang.IPersistentSet clojure.lang.IObj}] (apply merge ifs (mapcat supers ifs))) |
| 21:37 | clojurebot | #{clojure.lang.IPersistentStack clojure.lang.Sequential clojure.lang.IPersistentSet clojure.lang.Associative clojure.lang.IPersistentVector ...} |
| 21:37 | justin_smith | nice |
| 22:05 | rhg135 | Seems like a lot of work for little gain |
| 22:08 | amalloy | rhg135: yes, i would suggest not actually deftyping this up, but just writing a couple functions that manipulate a tuple in the ways you actually need |
| 22:09 | amalloy | you can look at the source for amalloy/ordered if you want to see all the nonsense you have to implement to be a good citizen; it's another deftype around a set and a vector |
| 22:09 | rhg135 | Good to know I'm not just being lazy, amalloy |
| 22:10 | amalloy | you only really need to make a deftype if you want to be able to pass these things to oblivious other functions that will operate on them like ordinary collections |
| 22:10 | justin_smith | great point, you can just get away with a pair of items and a few functions otherwise |
| 22:13 | rhg135 | Hmm |