2013-05-10
| 00:04 | djwonk | I want to wrap function calls to handle a SQLException. I'd like to do it without writing a macro if possible. |
| 00:05 | djwonk | `apply` gets me part of the way there, but not completely |
| 00:06 | djwonk | but since `try` is a special form, is it reasonable to think I can create a custom try that is not a macro? |
| 00:07 | darrickw | djwonk: do you want to wrap the function so that you can call it later but the wrapper handles the exception? |
| 00:08 | djwonk | darrickw: not sure I understand your question. I want the wrapper to contain the try/catch |
| 00:08 | djwonk | I mean… to abstract out the try/catch |
| 00:09 | djwonk | I don't think I need to wrap the original function (possibly exception-causing function) to call it later |
| 00:09 | darrickw | Ok so you want to do the wrapping in place where you call the function then? |
| 00:11 | darrickw | You just need a regular function to do that |
| 00:11 | djwonk | darrickw: sounds about right |
| 00:12 | darrickw | (defn a-wrapper [the-fn-to-wrap & args] (try (apply the-fn-to-wrap args) (catch TheException ex (do-something ex)))) |
| 00:12 | darrickw | something like that could do it |
| 00:13 | darrickw | then you call it like this: (a-wrapper the-fn arg1 arg2) |
| 00:13 | djwonk | darrickw: thanks |
| 00:13 | djwonk | I'm running into a double apply situation with jdbc/create-table, but I can figure it out |
| 00:19 | gdev | djwonk:) what database are you using? |
| 00:55 | n_b | sis there a way to break out of a doseq? |
| 01:00 | technomancy | n_b: doseq has a :while clause; it should stop once that is fasy |
| 01:00 | technomancy | falsy |
| 01:01 | n_b | Ah, didn't see that! That's perfect, thanks technomancy |
| 01:01 | n_b | Same clauses as for, always forget |
| 01:02 | technomancy | there are a lot |
| 01:09 | amalloy | doseq doesn't necessarily do what you want, there, if you're iterating through multiple sequences |
| 01:11 | amalloy | eg, (doseq [a (range 5) b (range 10) :while (< b a)] (...)) doesn't abort the entire doseq. it stops going through b, and starts up with the next a. ##(for [a (range 5) b (range 10) :while (< b a)] [a b]) |
| 01:11 | lazybot | ⇒ ([1 0] [2 0] [2 1] [3 0] [3 1] [3 2] [4 0] [4 1] [4 2] [4 3]) |
| 01:12 | amalloy | unintuitive, but much more useful than the alternative. anyway, n_b, technomancy: just a thing to keep in mind |
| 01:12 | technomancy | nutty |
| 01:13 | gdev | the more you know ...* |
| 01:13 | n_b | Ah, interesting |
| 01:14 | n_b | Fortunately I'm only going through one seq, but I'm sure I'll get bitten by that somewhere down the line and come back here to be reminded of it |
| 01:14 | n_b | better go write that down |
| 01:17 | amalloy | technomancy: not actually nutty at all. if you want a "global" stop parameter, you can just (doseq [[x y] (take-while keep-going? (for [x xs, y ys] [x y]))] ...) or something similar, whereas if doseq/for had a global-stop built in instead, you couldn't easily get the current behavior |
| 01:19 | gdev | I know I should be using jdbc library to batch update my database, but I was doing a doseq to create my update statements, I wonder if thats why the database had to parse each statement instead of pulling it straight from cache like is supposed to happen with bind variables |
| 01:19 | technomancy | amalloy: I suppose so, but it'd be really easy to write code that does a lot more checks than it looks like |
| 01:19 | technomancy | though I suppose the correctness isn't affected |
| 01:44 | muhoo | what's the new latest-jdbc-approved, non-deprecated method of doing a couple jdbc operations inside a transaction? |
| 01:44 | gdev | nice, looks like I don't need to pull an all-nighter; company bbq canceled due to weather, will get a lot of alone time at the repl tomorrow. |
| 01:45 | muhoo | i've seen examples or using transaction, but that's deprecated, and haven't gotten my brain around the new db-transaction replacement |
| 01:45 | muhoo | looking for an example somewhere |
| 01:48 | gdev | muhoo:) the sql dsl that he wrote i thought was what replaced transaction |
| 01:48 | muhoo | the dsl is optional, i think. |
| 01:49 | muhoo | i'm using honeysql and i like that way better. but it still uses jdbc as transport |
| 01:49 | muhoo | there's a function db-transaction*, looks like what replaced it, but the usage is kinda weird. |
| 01:50 | muhoo | the macro wants bindings, but i'm not a bindings kind of guy, i like passing db handles in explicitly instead of with-foo-earmuffs stuf |
| 01:50 | muhoo | anyway, i think i got it, it just looks ugly to me. |
| 01:52 | mthvedt | what can cause "abstractmethoderror: null" |
| 01:52 | gdev | muhoo:) can you post what you got on refheap? I always like seeing different ways to do things |
| 01:53 | muhoo | gdev: it's a one-liner: (jdbc/db-transaction* db-handle #(do (i have to) (do it this way weird))) |
| 01:53 | gdev | also, honeysql gets my vote for best name of a sql dsl library |
| 01:54 | muhoo | works, just feels dirty. the macro version feels dirtier, because it expects bindings like the old transaction macro used to. ain't no thing. |
| 01:54 | muhoo | and db-do-commands may be the right way |
| 01:56 | muhoo | i'm a total honeysql fanboi now. i only wish it did update! and insert! but i guess i can submit! patches! at some point |
| 01:56 | gdev | muhoo:) i'm still struggling to get batch updates to act right, so it's better to feel dirty when your stuff works than to feel dumbfounded even though your code is pertty |
| 01:59 | muhoo | this stuff is just weird. the jdbc library looks like it kind of grew organically |
| 02:00 | muhoo | didn't devn write a tool that would search github for all instances of a function or identifier and deliver a bunch of code examples of its usage in the wild? |
| 02:01 | gdev | wow a truly global usage search huh |
| 02:02 | muhoo | it was a very cool idea, and he had something working IIRC |
| 02:03 | muhoo | oh, here's the docs i was looking for: https://github.com/clojure/java.jdbc/tree/master/doc/clojure/java/jdbc |
| 02:04 | gdev | one of those says "using sql" is that referring to the optional dsl or the core library? |
| 02:05 | muhoo | aha! (j/db-transaction [t-con db] (something t-con) (something-else t-con)) very nice |
| 02:05 | muhoo | THAT is what i was looking for. |
| 02:06 | muhoo | i think the binding is unnecessary, but whatevs |
| 02:06 | muhoo | redndant, why bind db to t-con, why not just use db? |
| 02:07 | gdev | muhoo:) have you read the clojure data analysis cookbook? |
| 02:08 | muhoo | no, link? |
| 02:09 | gdev | http://www.amazon.com/Clojure-Data-Analysis-Cookbook-Rochester/dp/178216264X |
| 02:12 | muhoo | hmm. did you like it? |
| 02:14 | gdev | Yeah, I like what I've read so far and I typically don't like cookbooks |
| 02:29 | gdev | okay, now that my phone has some charge i can load the kindle app and see what the book says about jdbc transactions |
| 02:42 | gdev | looks like the book is only concerned with reading data from the database. makes sense I guess, it's a book about analysis not database programming. That would probably be a book on its own |
| 03:26 | muhoo | ,doc empty? |
| 03:26 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.repl/doc, compiling:(NO_SOURCE_PATH:0:0)> |
| 03:26 | muhoo | ,(doc empty?) |
| 03:26 | clojurebot | "([coll]); Returns true if coll has no items - same as (not (seq coll)). Please use the idiom (seq x) rather than (not (empty? x))" |
| 03:27 | muhoo | ,(doc not-empty?) |
| 03:27 | clojurebot | Pardon? |
| 03:27 | muhoo | aha! y you not named not-empty? |
| 03:27 | muhoo | ,(doc not-empty) |
| 03:27 | clojurebot | "([coll]); If coll is empty, returns nil, else coll" |
| 03:27 | muhoo | i think that's the first naming inconsistency i've found in clojure |
| 03:29 | esmo_ | it's not a predicate (doesn't return a boolean) |
| 04:02 | muhoo | interesting. actually docstring says that not-empty isn't the same as (not (empty?)), and it says |
| 04:02 | muhoo | Please use the idiom (seq x) rather than (not (empty? x)) |
| 04:03 | muhoo | so i guess, that |
| 08:20 | pellis | hi all, i'm looking for a way to mount ring handlers on urls (no need for routing, just mounting handlers) |
| 08:20 | pellis | anyone bumped into how to do this? |
| 08:21 | weavejester | What's the difference between routing and mounting ring handlers on urls? |
| 08:23 | pellis | weavejester, well i don't want to waste cycles on a routing matcher that checks my http method, or tries a regex against it |
| 08:24 | pellis | just /v1/api goes to handlerfoo, /v2/api goes to handlerfoo-2 |
| 08:24 | weavejester | So you could just use a case statement |
| 08:25 | weavejester | Or, I guess in this case you want to match against a prefix? |
| 08:25 | weavejester | So... |
| 08:25 | pellis | yes |
| 08:25 | pellis | i'm looking for the equivalent of rack-mount from ruby world |
| 08:26 | weavejester | (cond (.startsWith (:uri request) "/v1/api") (handler request) ...) |
| 08:26 | weavejester | But that's probably overkill |
| 08:26 | weavejester | You could just use Compojure. Regexs are fast enough. |
| 08:26 | pellis | ok |
| 08:27 | weavejester | (routes (ANY "/v1/api" [] handlerfoo) (ANY "/v2/api" [] handlerfoo-2)) |
| 08:29 | pellis | weavejester, is that compojure? |
| 08:30 | weavejester | pellis: Yep |
| 08:30 | pellis | I'm wondering how much overhead in performance will that take |
| 08:30 | weavejester | pellis: Let me run some numbers for you, as I'm curious myself |
| 08:30 | rasputnik | hi all, i need to filter a seq of maps by testing keys - what functions should i be looking at? |
| 08:31 | pellis | i might sound to you like the naive hysteric premature optimizer - but I assure you i'm not. this specific project needs to be carefully handled with LOCs unfortunately. |
| 08:31 | rasputnik | # it's a map of ssl keys and i want to return those with an expiry date less than a given number of days |
| 08:32 | pellis | weavejester, I chose Clojure because it won over Go and Node.js, (however didn't test it against the newer Go betas and RCs that are not famously performant) |
| 08:34 | pjstadig | rasputnik: something like (filter (fn [key] (< (get-exp-days key) the-date)) keys) |
| 08:34 | ucb | ,(doc filter) |
| 08:34 | ucb | rasputnik: ^ |
| 08:34 | clojurebot | "([pred coll]); Returns a lazy sequence of the items in coll for which (pred item) returns true. pred must be free of side-effects." |
| 08:34 | pjstadig | or if you want to be fancier (filter #(< (get-exp-days %) the-date) keys) |
| 08:35 | rasputnik | pjstadig, ucb : cheers both. |
| 08:35 | weavejester | pellis: Okay, I'm just writing out a quick benchmark. Should be a few minutes. |
| 08:36 | pellis | weavejester, cool! |
| 08:51 | weavejester | pellis: Both approaches look to be about the same speed. There's maybe a microsecond between them, but I'd guess hotspot is doing a good job at optimising things out. |
| 08:51 | weavejester | pellis: I'll give you my REPL logs in a gist |
| 08:51 | pellis | weavejester, thanks, very nice of you ! |
| 08:53 | weavejester | Huh, gists aren't working... |
| 08:54 | pellis | yes, i think they have a security bug |
| 08:54 | pellis | i thought i'm the only one. looks like a redirect loop, and then some blurb about login/authentication errors |
| 08:54 | weavejester | pellis: https://www.refheap.com/paste/14390 |
| 08:55 | pellis | might also be stale cookies |
| 08:55 | redline6561 | lam |
| 08:55 | redline6561 | ahem, excuse me |
| 08:56 | pellis | weavejester, that's very useful. i think - when you'll see a bigger difference will be with big urls |
| 08:56 | pellis | weavejester, for example /api/v1?<some 1000 characters> |
| 08:56 | pellis | unless regex are smart enough to not glob when it's just "*" |
| 08:57 | weavejester | pellis: Anything after ? is the query string and not matched, but regexes are pretty optimised. |
| 08:57 | pellis | well then /api/v1/foo/<some 1000 chars> |
| 08:58 | weavejester | pellis: I suspect that you'd still see little difference. But lets try it :) |
| 08:58 | pellis | weavejester, you might be surprised, most websites can be ddos'ed with just very big urls. |
| 08:58 | pellis | especially if you have double captures like v1/*foo*bar |
| 08:59 | pellis | if you're not building-in protection, then you're limited to browser's 8k characters at the url. but anyone smart enough can just not use the browser and bombard you with 50k of url string |
| 09:00 | pellis | plus, i've seen such attacks live in production 3 years ago :) |
| 09:00 | juhu_chapa | Hi all. Is there anything like a blocking queue in clojure? |
| 09:01 | weavejester | juhu_chapa: Typically you can just use the Java blocking queues |
| 09:03 | juhu_chapa | :D |
| 09:07 | vijaykiran | mu4e |
| 09:10 | weavejester | pellis: Looks like the URL length does affect the time. My guess is because Compojure is capturing the * part in a matching group, whereas the .startsWith can just discard it. |
| 09:10 | pellis | weavejester, yes, like i suspected :) |
| 09:11 | weavejester | pellis: With a URL of length 1000, it's a difference of 4us to 40us |
| 09:11 | pellis | weavejester, i guess this is the conceptual difference between mount and route - O(1) vs O(n) |
| 09:11 | weavejester | weavejester: I suspect that if Compojure *wasn't* capturing it the wildcard, that we wouldn't see a difference. |
| 09:13 | weavejester | pellis: Well, it doesn't have to be that way. I've been toying around with the idea of just discarding *, as if you really wanted it, you'd give it a name. |
| 09:13 | pellis | weavejester, i understand |
| 09:13 | weavejester | pellis: But given the implementations at the moment, yes, you're correct. |
| 09:15 | pellis | ok, so I'll opt for your first suggestion - thanks for the help :) |
| 09:54 | learner | Hello Gurus. A newbie question here. I have a huge lazy sequence (say 2 or 20 Million strings). Among all, I am interested in finding only one particular string position (just need a rough value). I can use loop, recur updating an atom (count). But it's slow. Since I don't need exact position, I can use Threads. But I am not sure how to. Any hints? |
| 09:57 | AimHere | That sounds like you want to crack open a book on algorithms |
| 09:58 | AimHere | First find the most efficient known way of doing it, then worry about the details of which bits are threaded and whether to use recur or whatever later |
| 10:00 | learner | AimHere: Yes, may be I should go and read algorithms. Wondering if I can find any help from the community who experienced similar problems. |
| 10:01 | pppaul | learner sorted? |
| 10:02 | learner | pppaul: No, not sorted. But fixed size strings |
| 10:03 | pppaul | brute force + memoize :) |
| 10:04 | pppaul | you can use partition + map indexed |
| 10:04 | AimHere | My naive guess as to how to do it would be to check the first character of all strings - then you discard all the nonmatches and you've a considerably smaller set to sift through for the second pass, and the second character |
| 10:04 | AimHere | Basically sieve it |
| 10:05 | pppaul | you can put this data in a mem datomic and use it's fulltext search |
| 10:05 | pppaul | index the strings first [{:index 0 :body "my string"}] |
| 10:05 | learner | pppaul: Yeah, brute force is the only way. And memorize may not be required because all strings are fixed size, unique. I am thinking of kicking off some 20 threads (fixed) on collection each taking one string and comparing with the String I want. If found, update atom flag. If flag=true no more new threads should be created. But not sure how to do that! |
| 10:07 | pppaul | learning, make this problem constant time, or fit it into pmap, or fit it into reducers |
| 10:07 | edbond_ | learner, you need map-indexed |
| 10:07 | pppaul | personally, i would use constant time lookup |
| 10:07 | pppaul | map-indexed + groupby |
| 10:07 | edbond_ | pppaul, he needs only index of that string |
| 10:08 | pppaul | ? |
| 10:08 | AWizzArd | Anyone here who has a K10, K20 or K20x? |
| 10:08 | edbond_ | ,(first (drop-while nil? (map-indexed (fn [i x] (if (> x 10) [i x])) (range 30)))) |
| 10:08 | clojurebot | [11 11] |
| 10:08 | pppaul | ? |
| 10:09 | edbond_ | first is index, second is value |
| 10:09 | edbond_ | change (> x 10) (= x "lookup-string") |
| 10:10 | learner | pppaul: edbond: AimHere: Ex:- I have a sequence something like ('abc 'cba 'aaa 'bbb 'bca 'ccc 'bac 'cab...............) I want to find the index of 'ccc which is 5. If I can find a program which gives me 4 or 6 is also fine as I don't need exact index. But I need to be sure that string exist + I need rough index. And the sequence in reality is so huge |
| 10:10 | pppaul | ,(first (group-by :body (map-indexed #(hash-map :index %1 :body %2) ["lalal" "bababa"]))) |
| 10:10 | clojurebot | ["lalal" [{:index 0, :body "lalal"}]] |
| 10:10 | dnolen | learner: if you have a lazy sequence and a trivial computation I'm skeptical using thread will help. |
| 10:11 | pppaul | i don't think that 20 mil is a lot |
| 10:11 | dnolen | you could put the whole thing in memory but that will take time at it seems like ~1GB for say a vector + whatever memeory those strings take up. |
| 10:12 | pppaul | i have gigs coming out my wazoo |
| 10:12 | learner | dnolen: My problem is to go and do some more validations with the string I find. Once I find the string, I have some other checks to do. I was just trying give an example so that everybody understands what I need |
| 10:12 | dnolen | learner: when you say slow, how slow is your current solution? |
| 10:13 | dnolen | learner: your explanation leaves out to many details. if you actually have an expensive computation, *maybe* pmap could help |
| 10:13 | pppaul | reducers! |
| 10:14 | pppaul | i don't even know what i'm talking about anymore |
| 10:14 | pppaul | put the data in a DB and let it do the hard work |
| 10:14 | learner | edbond_: Your example is perfect. But it does sequentially. It may take couple of days to complete the processing of the lazy queue I have. so looking for thread style |
| 10:15 | learner | pppaul: ha ha. Sorry If I have confused you |
| 10:15 | dnolen | learner: what is the source of the data? can you not partition it ahead of time? |
| 10:15 | pppaul | learner, pmap has helped me, but it gets tricky if you don't want to work on the whole set |
| 10:16 | learner | dnolen: if I process the lazy sequence (which has millions of strings & combinations) sequentially. I guess it may take 3 or 4 days on a dev machine |
| 10:16 | pppaul | learner, put this stuff in lucene or something |
| 10:17 | dnolen | learner: is your guess based on how slow your code is on a small data set? |
| 10:17 | pppaul | learner pmap isn't going to help you |
| 10:17 | pppaul | 4 days is nuts |
| 10:18 | pppaul | learner look into storm |
| 10:18 | learner | dnolen: My guess is based on how big dataset is. Source is https://github.com/clojure/math.combinatorics combinations |
| 10:19 | learner | pppaul: Yes lucene option is cool. But how can I extract out from lazy sequence and put it into lucene. Sequentially? Hmm no. Is there any way I can run fixed number of threads to do it |
| 10:19 | pppaul | learner your problem hasn't been described well enough |
| 10:19 | dnolen | learner: are you saying you're going to use math.combinatorics? |
| 10:20 | pppaul | to me, it sounded like you have your data, and it's static |
| 10:20 | pppaul | but now it sounds like you are generating your data in real time |
| 10:20 | pppaul | what the fuck are you doing? |
| 10:20 | edbond_ | learner, if you can load whole sequence in memory you can partition and process in parallel |
| 10:20 | dnolen | for 20,000,0000 strings over 4 days, this means you can only process ~58 strings per second, this seems absurd unless the processing of those 58 strings is very complex. |
| 10:20 | learner | pppaul: I am doing a little research project |
| 10:21 | pppaul | learner that doesn't help me understand your problem |
| 10:22 | pppaul | seriously, i don't have a clue what your problem is, cept that you believe that you need to optimize some calculation you are doing |
| 10:22 | pppaul | that's really not enough to go on |
| 10:22 | pppaul | there are a million ways to solve such a problem, you need to be much more specific |
| 10:23 | pppaul | the less specific you are the more of our time you are wasting |
| 10:24 | dnolen | learner: anyways based on the small amount of information given, I assume the processing each string is expensive, perhaps pmap+partition will work for you. |
| 10:25 | pppaul | it would help a lot if you could tell us if these 20million strings is your total dataset, or if this is the dataset per calculation |
| 10:25 | learner | pppaul: To keep it short. I will have a fixed string (generated dynamically). For now say it is "clojure" and when I have the word I will know the length. I have to generate various combinations using combinatorics and run through it until I hit the word I want. Kind of Brute force. But I need to get the possible range (that's the tricky thing). Since I need only rough index of the word, I can use threads. |
| 10:25 | learner | pppaul: I need to find out how I can do it in clojure/scala/groovy & plain java |
| 10:26 | pppaul | hmm |
| 10:27 | learner | pppaul: I am a completely newbie and learning lot of stuff while implementing the suggestions you guys are offering |
| 10:28 | pppaul | hack the combinatorics thing to put indices on it's output, then send this job out to a bunch of computers via storm |
| 10:29 | pppaul | well, i guess you don't need to hack the combinatorics thing |
| 10:29 | pppaul | you just need to have 100s of computers working on this to get it fast if you think it'll take 4 days for 1 computer to finish the calculation |
| 10:29 | learner | pppaul: Are you talking about this ? https://github.com/nathanmarz/storm |
| 10:29 | pppaul | yes |
| 10:30 | learner | pppaul: Thanks. I will give a try |
| 10:30 | pppaul | if you are dealing with completely lazy sequences then this should be easy |
| 10:30 | learner | pppaul: It's a lazy sequence |
| 10:31 | pppaul | storm should work fine, and it has a good development/testing story |
| 10:32 | pppaul | i would be very interested to see this working when you are done with it |
| 10:37 | devn | muhoo: http://getclojure.org is what you were thinking of. it's getting some love today. adding the ability for users to create ratings on examples |
| 10:40 | gdev | devn:) that's awesome, I was just talking to someone at work about that...*puts on aluminum helmet to keep devn out of his head* |
| 10:40 | gdev | (inc devn) |
| 10:40 | lazybot | ⇒ 6 |
| 11:03 | rbxbx | devn: heh, getclojure doesn't like it when you pass an empty string |
| 11:03 | rbxbx | looks like it's coming along nicely though :) |
| 11:10 | jtoy_ | is there a more idiomatic way to write this? (map (fn [x] ((meta x) :target )) data ) |
| 11:11 | dakrone | (map (comp :target meta) data) |
| 11:11 | bbloom | or (map #(-> % meta :target) data) |
| 11:12 | jtoy_ | thanks, i havent seen comp before |
| 11:12 | ToxicFrog | ,(doc comp) |
| 11:12 | clojurebot | "([] [f] [f g] [f g h] [f1 f2 f3 & fs]); Takes a set of functions and returns a fn that is the composition of those fns. The returned fn takes a variable number of args, applies the rightmost of fns to the args, the next fn (right-to-left) to the result, etc." |
| 11:13 | jtoy_ | is comp basically the opposite direction of -> ? |
| 11:14 | bbloom | jtoy_: you can think of it that way, but comp is a function, -> is a macro |
| 11:15 | bbloom | jtoy_: (comp x y) is (x (y …)) and (-> x y z) is (z (y x)) |
| 11:15 | justin_smith | with comp you would not provide the other args to the functions unless you create lambdas |
| 11:15 | justin_smith | with -> you don't need to create the lambdas manually |
| 11:16 | jtoy_ | right , i see, ill try with comp for now |
| 11:49 | matko | Question: should I be using ! in my function names for functions that alter state (through swap!, send, alter, etc)? |
| 11:55 | noidi_ | matko, "Use the bang! only for things not safe in an STM transaction." http://dev.clojure.org/display/design/Library+Coding+Standards |
| 11:55 | matko | thank you, I just found that too. so that means I should do it if I use swap!, but not any of the other ones |
| 11:56 | matko | but not for every destructive operation |
| 11:56 | matko | is there another obvious way to point out that my functions are destructive? |
| 12:00 | bbloom | destructive ops aren't safe to use in STM :-P |
| 12:00 | noidi_ | unless they're idempotent |
| 12:00 | bbloom | true |
| 12:00 | noidi_ | e.g. emptying a mutable collection is destructive but idempotent |
| 12:01 | matko | anything wrapped in a (dosync) is safe to call from within a transaction though, right? |
| 12:01 | bbloom | i don't think that idempotence is sufficent though, since a transaction can permanently fail |
| 12:01 | matko | and anything send to an agent is only run on successful completion of a transaction |
| 12:01 | bbloom | generally, if you have a library that is all mutable ops, then you don't really need ! on every single function |
| 12:02 | bbloom | if you have 1 destructive evil op in a sea of 100 others… then i say stick a ! on it, naming guidelines are guidelines for a reason, right? |
| 12:04 | matko | right, sounds good |
| 12:31 | gdev | j/ #probablywrong |
| 12:31 | gdev | derp |
| 12:31 | gdev | j/ dislexics_anonymous |
| 12:31 | gdev | doh >_< |
| 12:37 | learner | pppaul: I will let you know after trying storm. Thanks for your continued help |
| 12:47 | moquist | (class y) returns 'clojureql.core.RTable. (prn y) outputs "SELECT * FROM sometable". What I want in my code is that SQL string, because I need to send it somewhere else; I can't query directly. How does 'prn get the string representation of an object? |
| 12:48 | moquist | Google has not helped me with this yet; looking at https://github.com/LauJensen/clojureql/blob/master/src/clojureql/core.clj has also not yielded an answer so far. |
| 12:48 | justin_smith | moquist: str? |
| 12:48 | moquist | Sorry -- (str y) returns "clojureql.core.RTable@567ae64a" |
| 12:49 | justin_smith | (with-output-to-string (prn y)) ? |
| 12:49 | justin_smith | that should return the string prn would have printed |
| 12:49 | justin_smith | sorry |
| 12:49 | justin_smith | with-out-str |
| 12:49 | justin_smith | ,(with-out-str (prn :a)) |
| 12:49 | clojurebot | ":a\n" |
| 12:50 | justin_smith | ahh! |
| 12:50 | justin_smith | ,(prn-str :a) |
| 12:50 | clojurebot | ":a\n" |
| 12:50 | justin_smith | seems like a common enough usage to have its own fn |
| 12:50 | weavejester | I've just been testing Clojure binary serialization libraries, and was quite impressed with deep-freeze, until I discovered it was serializing the data wrong :) |
| 12:50 | moquist | justin_smith: yes! That's more like it. Thanks! |
| 12:53 | Wild_Cat` | weavejester: aren't there Clojure libs for BSON or msgpack? |
| 12:54 | weavejester | Wild_Cat`: I wanted something that would retain all the Clojure data structures |
| 12:54 | hiredman | weavejester: fressian? |
| 12:54 | weavejester | hiredman: No Clojure library for that, unless you count the stuff in the tests |
| 12:55 | hiredman | weavejester: :/ |
| 12:55 | dnolen | a good small example of using core.logic's featurec http://stackoverflow.com/questions/15821718/how-do-i-de-structure-a-map-in-core-logic |
| 12:56 | weavejester | https://www.refheap.com/paste/14401 |
| 12:57 | weavejester | There's not much to choose between Nippy and Carbonite. |
| 12:57 | weavejester | Nippy seems to have the more straightforward API, though |
| 13:10 | mpenet | +1 for Nippy, it's really a gem. |
| 13:14 | devn | rbxbx: could you make an issue on the repo? |
| 13:24 | rbxbx | devn: sure. |
| 13:36 | devn | rbxbx: and then could you fix it and submit a PR? ;) |
| 13:37 | rbxbx | devn: ... probably. |
| 13:37 | rbxbx | devn: especially if you wanted to pair :p |
| 13:37 | devn | rbxbx: yeah, you got time this afternoon? |
| 13:37 | rbxbx | devn: I jest. It's probably low-hanging enough that I could tackle it alone. |
| 13:37 | rbxbx | and no, not really. Maybe this evening though. |
| 13:37 | devn | rbxbx: there's other stuff I could use a second pair of eyes on |
| 13:38 | rbxbx | Some of us have to work on Fridays :p |
| 13:38 | devn | ha! the solution as I'm sure you're aware is to simply quit your job. |
| 13:38 | rbxbx | sshhh, my co-workers are in here. |
| 13:39 | gfredericks | so I like "C-u C-x C-e", which writes the result to the buffer. What's the most straightforward way to get that to pprint to the buffer instead? |
| 13:40 | devn | rbxbx: if you're interested in helping out I'd like to rip out the hiccup templates and use laser or something instead. I have some really nice comps for the site and I want to just tell them to make me the static version and then i can just do transforms on what they hand me. |
| 13:41 | rbxbx | devn: maybe. I'm a bit over-extended right now :| |
| 13:41 | devn | also, it needs ratings. because if you search for comp the top result is (comp comp comp comp comp comp ...) -- not exactly the most useful or idiomatic example |
| 13:41 | rbxbx | right, we'd discussed this before. |
| 13:42 | rbxbx | I looked into that... but I didn't understand nearly enough of anything :) |
| 13:42 | devn | yeah i know i know, everyone is busy. either way, talk to you later, im off to go hack on that. |
| 13:43 | rbxbx | devn: cheers sir :) |
| 14:12 | devn | Where does the foo-1 naming pattern come from for reduce functions? |
| 14:12 | ToBeReplaced | what do people do when they want (need?) try-let (or try-catch-else)? |
| 14:16 | bbloom | ToBeReplaced: where "else" is "run this only if an exception is not thrown"? |
| 14:16 | bbloom | devn: what foo-1 things are you talking about? |
| 14:16 | ToBeReplaced | yeah, presumably using a value from the try |
| 14:17 | bbloom | ToBeReplaced: i prefer to avoid exception handling in my primary code paths. i'd wrap up functions that can fail and have them return maps or keywords or whatever that describe their result |
| 14:17 | ToBeReplaced | java doesn't support it... you can hack it by storing a boolean and using the finally clause, but that's gross |
| 14:18 | technomancy | I don't get it; why would you need a separate else clause? |
| 14:18 | bbloom | (defn get-foo [x] (try (.getFoo x) (catch Exception e :error))) |
| 14:19 | bbloom | technomancy: http://stackoverflow.com/questions/855759/python-try-else |
| 14:19 | ToBeReplaced | yeah that link will explain better than me :) |
| 14:20 | bbloom | ToBeReplaced: like i said: just avoid having exception handling logic bleed into your normal logic |
| 14:20 | technomancy | huh |
| 14:20 | ToBeReplaced | yeah seems like the way to go |
| 14:20 | bbloom | ToBeReplaced: if you need to handle an error case at the site of the error, it's not really exceptional, is it? |
| 14:21 | bbloom | a wrapper function that returns {:status some-keyword, :result some-value} will do the trick |
| 14:21 | ToBeReplaced | bbloom: that's the general perspective, yeah, so i tend to agree with you -- hence why it doesn't seem to come up often in clojure |
| 14:22 | ToBeReplaced | in python the etiquette is very much "try and ask for forgiveness"... there's less overhead in try-except than an if-statement if you rarely hit the exception |
| 14:23 | bbloom | ToBeReplaced: well the reason they recommend that is b/c they have embraced exceptions for control flow…. ie StopIteration exceptions! |
| 14:23 | bbloom | ToBeReplaced: if you "look before you leap" you have a race condition |
| 14:24 | bbloom | golang has it right: if you have error cases, use status codes. if you don't know what to do: panic & abort an entire process at a prompt/barrier/watever-you-want-to-call it |
| 14:24 | ToBeReplaced | right |
| 14:29 | technomancy | o_O |
| 14:33 | Glenjamin | error codes: exceptions you can ignore |
| 14:34 | tieTYT2 | current thing I'm dealing with: http://stackoverflow.com/questions/16488423/reducing-a-sequence-into-a-shorter-sequence-while-calling-a-function-on-each-adj |
| 14:35 | weavejester | What does everyone think of having a deref-able type initialized from a no-argument function? |
| 14:35 | weavejester | Kinda like a derived reference |
| 14:36 | bbloom | weavejester: do you mean a thunk? like ##(doc delay) ? |
| 14:36 | lazybot | ⇒ "Macro ([& body]); Takes a body of expressions and yields a Delay object that will invoke the body only the first time it is forced (with force or deref/@), and will cache the result and return it on all subsequent force calls. See also - realized?" |
| 14:36 | ohpauleez | weavejester: Why not use a promise that you pass into the initializing function? |
| 14:36 | weavejester | bbloom: Yes, but one that's tied to another ref, so the result isn't cached. |
| 14:36 | ohpauleez | ah |
| 14:37 | bbloom | oh, like a pointer to a pointer? |
| 14:37 | Glenjamin | allowing you to use @foo instead of (bar) ? |
| 14:37 | matthavener | tieTYT2: how is that different from a reduce? |
| 14:37 | weavejester | Glenjamin: Right |
| 14:37 | Glenjamin | why not just call the function? :p |
| 14:37 | weavejester | I'm not convinced it's a hugely good idea, but here's my use-case |
| 14:38 | weavejester | I have a world data structure that represents the state of a game world |
| 14:38 | bbloom | ,@(clojure.lang.Delay. (fn [] :done)) |
| 14:38 | matthavener | tieTYT2: (reduce mystery-fun (first coll) (rest coll)) |
| 14:38 | tieTYT2 | matthavener: apparently it is, I'm using reduce |
| 14:38 | clojurebot | :done |
| 14:38 | weavejester | And I have an scene data structure that represents what the user can see |
| 14:39 | weavejester | So I connect the world to the scene with a watch. When the world changes, the scene alters as well. |
| 14:39 | matthavener | tieTYT2: and if you only want the 'last' of the retval of 'mystery-fun' just wrap it in a function that calls (last) on the retval |
| 14:39 | trptcolin | is it expected in cljs that if you extend a protocol to js/Object, a fresh (js-obj) will have key/value pairs? i guess i expected the data for protocol implementations to live elsewhere. |
| 14:39 | tieTYT2 | matthavener: since mystery-fun returns a sequence, won't the result of the reduce be a sequence of sequences of sequences...? |
| 14:39 | matthavener | tieTYT2: sure, but like i said, you can wrap mystery-fun in a 'last' if you only care about the last |
| 14:40 | weavejester | So I can handle this with a set of world->scene functions |
| 14:40 | tieTYT2 | matthavener: how do I keep the butlast of it? |
| 14:40 | weavejester | Or I could populate the scene with references to the world, and deref-all the scene |
| 14:40 | weavejester | Kinda a push/pull approach |
| 14:40 | matthavener | tieTYT2: i'm not sure what you mean by that, specifically "keep the 'butlast' of what you've got so far" |
| 14:40 | dnolen | trptcolin: you don't want to extend to js/Object, extend-type object |
| 14:40 | matthavener | tieTYT2: what do you mean by "what you've got so far" ? |
| 14:41 | bbloom | weavejester: yeah, this is a hard category of problems that i've been thinking about a lot: how to synchronize two views of the same data |
| 14:41 | trptcolin | dnolen: awesome, thanks |
| 14:41 | weavejester | bbloom: I'm glad I'm not the only one thinking about this :) |
| 14:41 | tieTYT2 | ok let's say calling (mystery-fun o1 o2) returns [o1 o2]. What I want to do next is compare [o1 (mystery-fun o2 o3)] and flatten that |
| 14:41 | patchwork | bbloom: You have both views depend on the same data source? |
| 14:42 | tieTYT2 | see how the o1 is still in the result? that what I mean by keeping what you've got so far |
| 14:42 | bbloom | patchwork: more accurately, i have a document translation |
| 14:42 | patchwork | the two views don't need to know about each other, updates flow from the data source |
| 14:42 | matthavener | tieTYT2: i think i see, you can just make your reduction a tuple |
| 14:42 | ohpauleez | weavejester: Is is possible (or advantageous) for the "scene" to be a function that takes the world and produces a slice? |
| 14:42 | bbloom | patchwork: it's one way: you have some source value & it is transformed to some view of it and chagnes to the source value need to be reflected efficently in the view |
| 14:42 | ohpauleez | rather than a data structure of the slice |
| 14:42 | dnolen | trptcolin: generally true for all the real JS languages natives |
| 14:43 | trptcolin | gotcha, i was extrapolating to assume that just now :) |
| 14:43 | tieTYT2 | matthavener: and the first part is a sequence that grows? |
| 14:43 | weavejester | ohpauleez: Maybe… at the moment it's an atom, which seems like it's a little more transparent I guess. |
| 14:43 | weavejester | Plus the UI isn't necessarily dependent on the world. |
| 14:43 | ohpauleez | and then the watcher can deliver a future, that you can deref when you need to use the "scene" slice |
| 14:44 | weavejester | I'm experimenting with a Leiningen-like profiles approach |
| 14:45 | matthavener | tieTYT2: https://www.refheap.com/paste/14402 |
| 14:45 | weavejester | But… Hum… I'd like to deal with data rather than function composition. |
| 14:45 | ohpauleez | at the end of the day you're dealing with data |
| 14:45 | ohpauleez | the slice you get back is data |
| 14:46 | weavejester | Or do I? I could have a bunch of middleware-like functions I compose that generate the final app data structure. |
| 14:46 | ohpauleez | right |
| 14:46 | ohpauleez | yes |
| 14:46 | ohpauleez | and so you start modeling it as core game data, and ways to derive your various game states |
| 14:46 | ohpauleez | and build it intoa dataflow |
| 14:47 | tieTYT2 | matthavener: hm, what if r is a sequence with a count of 1? |
| 14:48 | matthavener | tieTYT2: then (rest r) is empty |
| 14:48 | tieTYT2 | matthavener: also, you're not doing anything with sofar. Is that intentional? |
| 14:48 | weavejester | I might have to change the way I handle events... |
| 14:48 | tieTYT2 | you're passing the first element into mystery-fun, not the last |
| 14:48 | matthavener | i guess? i'm only trying to implement what you're describing |
| 14:49 | matthavener | yeah i suppose you should replace 'rest' with 'butlast' and 'first' with 'last' |
| 14:50 | weavejester | At the moment I have: {:type :button, :on-click (fn [event] …}} |
| 14:50 | weavejester | But maybe it should be: {:type :button, :state :clicked} |
| 14:51 | weavejester | Maybe my problem is the way I'm mixing event handlers in with my data structure. |
| 14:51 | ohpauleez | weavejester: In a system of flows, C2-event or pub/sub fits well (in my experience). So yes, i'd make that change |
| 14:51 | bbloom | weavejester: i've been trying to come up with something clojure-y for UI handling for months. it's hard :-) hopefully i'll have something cool to show soon… we'll see |
| 14:51 | ohpauleez | then let anyone who wants to know about the "click" subscribe and do something |
| 14:51 | ohpauleez | passing more data back into the bus, or down through the flow |
| 14:51 | weavejester | bbloom: It is hard! I think I've changed it twice already :) |
| 14:52 | kephale | weaverjester: if you don't mind my asking, are you talking about a 3D rendered world? |
| 14:52 | weavejester | I tried maintaining an event bus and a data structure, but it didn't really worlk well. |
| 14:52 | kephale | weavejester* |
| 14:52 | weavejester | kephale: Yep. |
| 14:53 | weavejester | kephale: I basically have a (run-app (atom …)) function that's at the core of this framework/game I'm building. |
| 14:53 | kephale | weavejester: ok, is yours open source? i'm at alpha/beta with my 3d simulator which has a modified penumbra under the hood |
| 14:54 | weavejester | kephale: No, but I'll probably open-source bits of it later. It's using jMonkeyEngine. |
| 14:54 | ohpauleez | weavejester: What was the issue you ran into with the bus? |
| 14:55 | kephale | weavejester: ok cool, i'll look for you later to chat more. I thought about jMonkey but didn't like sticking to their API. currently i have a ODE + penumbra working pretty well together |
| 14:55 | kephale | including some of the UI handling |
| 14:56 | kephale | gotta run for now… "brevis" on github |
| 14:56 | hiredman | bbloom: have you played with pedestals model (not sure what to call it) at all? I guess event sourcing? |
| 14:56 | kephale | ciao |
| 14:57 | bbloom | hiredman: pedestal kinda stops short at the view layer |
| 14:57 | hiredman | bbloom: sure |
| 14:57 | bbloom | hiredman: i haven't studied it too deeply, but it just feels a little heavyweight |
| 14:58 | bbloom | hiredman: i need to study it a bit more, but i'm coming at it from a pretty different angle |
| 14:58 | weavejester | ohpauleez: I was getting a problem reconciling the the event bus with my data structure. Like… say I have a FPS counter. I have to have something that subscribes to the event bus to catch each :tick event, but also I need to pass it the atom representing the application. |
| 14:58 | weavejester | ohpauleez: It felt like I was dealing with two systems, when I really wanted one. |
| 14:58 | gdev | bbloom:) the documentation explains that it was developed to handle hard problems that other lighter frameworks dont do well |
| 14:58 | weavejester | I'm beginning to think I don't actually need events... |
| 14:59 | hiredman | bbloom: I write a little thing in it, and I ended like the sort of event transforming stuff, but not the rendering.cljs bits |
| 14:59 | hiredman | wrote a |
| 14:59 | hiredman | ended up liking |
| 14:59 | hiredman | :/ |
| 14:59 | bbloom | hugod: ok there is a fip 0.3.0 release now |
| 14:59 | bbloom | technomancy: should i backup my gpg key? heh |
| 14:59 | gdev | mentioning Pedestal in the IRC triggers an alarm at Relevance so someone who knows more about it should be in here in 5..4..3..2...outOfBoundsException |
| 15:00 | ohpauleez | haha |
| 15:00 | weavejester | Just encode events in the state. Like instead of having a :tick event, have a counter that we watch for changes. |
| 15:00 | bbloom | gdev: i dunno what those "harder problems" are. i think even pretty basic UIs are pretty damn hard with the nightmare that is html/css/js for apps instead of for docs |
| 15:01 | technomancy | bbloom: yeah, but not in a network-attached location |
| 15:01 | bbloom | technomancy: i don't think i have any non-network attached locations… at least not any that wouldn't be destroyed in the same fire that destroys my laptop :-P |
| 15:01 | gdev | bbloom:) don't shoot the peanut gallery ;) |
| 15:01 | technomancy | bury an SD card in your back yard =) |
| 15:01 | hugod | bbloom: thanks! hope the gpg experience wasn't too painful |
| 15:01 | bbloom | technomancy: i live in NYC… what's a back yard? |
| 15:02 | bbloom | hugod: the docs were surprisingly helpful. good job technomancy & team! |
| 15:02 | technomancy | bbloom: hmm... do you have community gardens over there? =) |
| 15:02 | bbloom | hiredman: the rendering bit of course is gonna suck no matter what b/c it's html & css :-P |
| 15:02 | hiredman | weavejester: pedestal seems to go the other way, you do everything has events and transforms of events, and behind the scenes it tracks the state that events ultimately alter or are a result of |
| 15:02 | gdev | bbloom:) it's like a park but it's attached to your house and has less hobos and dead hookers buried in it |
| 15:03 | rkneufeld | gdev: sorry, I was out for coffee ;) |
| 15:03 | bbloom | technomancy: what happens if i lose my key? i just can't publish new software? |
| 15:03 | bbloom | technomancy: (i know what happens if it is stollen) |
| 15:03 | bbloom | technomancy: or do i just have to make a new key & people need to trust whoever that asshole future brandon claims to be |
| 15:04 | ohpauleez | hiredman weavejester: I'm of that same school of thought. I'd embed fragments of state within the events. Build the entire state from the whole stream of events (which may produce new events), and take a view on the final state withe by slicing or by subscription |
| 15:04 | bbloom | hiredman: what did you like about the event transforming bits? |
| 15:04 | bbloom | hiredman: you didn't find that to be a bit onerous ? |
| 15:05 | bbloom | technomancy: also, should i check in pom.xml and/or pom.xml.asc ? |
| 15:05 | weavejester | hiredman ohpauleez: I think I definitely want to go one way or the other. My current implementation is suffering from being a bit of both. |
| 15:05 | tomoj | when I found the square root example, I stopped looking at pedestal for the day |
| 15:05 | ohpauleez | yes, it's hard to do both - it's like double book keeping |
| 15:05 | tomoj | but maybe it's only onerous for trivial apps? |
| 15:06 | hiredman | bbloom: it was onerous, but I liked that it is a small set of primitives |
| 15:06 | bbloom | hiredman: yeah, i'm just not convinced that it's sane to expose those primitives to users... |
| 15:06 | bbloom | tomoj: i'm looking at the sqrt example now… wutdafaq? |
| 15:06 | ohpauleez | bbloom: Why not? |
| 15:06 | tomoj | you should be sure to look at the new one |
| 15:07 | tomoj | https://github.com/pedestal/pedestal/blob/master/app/test/clj/io/pedestal/test/app.clj#L476 |
| 15:07 | tomoj | the version 1 models are even wackier |
| 15:07 | bbloom | ohpauleez: because it means hand coding a complex static topology that implies your information hierarchy |
| 15:08 | tomoj | my guess was that the plan was to do something like core-async and compile out to those primitives from a more accessible representation |
| 15:08 | bbloom | i don't think it is reasonable to assume that your view state will every be large enough to justify virtualizing it |
| 15:08 | ohpauleez | I agree that means hand coding the static topology, but how does it imply the information hierarchy |
| 15:08 | bbloom | sure, you can have a list view that would have 1000000 items in it, you'd want to virtualize that. but that's the exeception, not the rule. & you can only show a few hundred bits of information at once if any human has a hope of reading it |
| 15:09 | bbloom | with that in mind, i think it makes sense to reify the view state into a single tree value, rather than some transient virtual tree thing |
| 15:09 | tomoj | :( |
| 15:10 | bbloom | ohpauleez: the virtual tree is (most often, not not necessarily) isomorphic to your view hierarchy |
| 15:10 | bbloom | allow me to be clear: i have not studied pedestal in detail, so i'm somewhat talking out of my ass from what i recall from the clojure/west presentation |
| 15:11 | bbloom | i expect i will get some first hand experience with it soon, but my initial reaction was "why would i want a VIRTUAL tree?" |
| 15:11 | weavejester | I think I'm going to represent my game as a function that transforms frame_n -> frame_n+1 |
| 15:11 | tomoj | either way, it's a tree of places, right? |
| 15:11 | ohpauleez | weavejester: I think that's smart |
| 15:11 | tomoj | (or a place with a tree in it, I'd argue these are isomorphic..) |
| 15:11 | bbloom | weavejester: conceptually, that's what you want. the trick is doing that efficiently :-) |
| 15:12 | tomoj | I for one would not like to write a function frame_n -> frame_n+1 |
| 15:12 | weavejester | That's kinda what I'm doing anyway, just with an atom instead. |
| 15:12 | bbloom | tomoj: you don't WRITE that function. you generate it from a description of the behavior of the world :-) |
| 15:12 | weavejester | I have a bunch of aggressively cached functions in the background that map a data structure into a 3D world. |
| 15:12 | tomoj | yeah, right :) |
| 15:13 | noncom | weavejester: that will surely be _the way_ when we have quantum computers and it will be the most natural thing to do - change state at once! |
| 15:13 | weavejester | Well, the function frame_n -> frame_n+1 would be the result of composing a bunch of smaller functions. |
| 15:13 | weavejester | Although composed functions are a little opaque. |
| 15:13 | Pupnik- | the thing that unsettles me with that weavejester is you have to pass around some sort or gigantic data structure |
| 15:14 | tomoj | frame_n -> frame_n+1 still seems sorta weird to me, where is the information about the length of time that passed between frames, and who uses that info, how? |
| 15:14 | weavejester | Pupnik-: So? |
| 15:14 | bbloom | weavejester: you compose a data structure & your next-frame function is an abstract machine which accepts current-frame and program-to-transform-frame |
| 15:15 | weavejester | tomoj: Well, I guess to be more accurate it would be frame_n+1(with no change) -> frame_n+1(with change) |
| 15:16 | weavejester | tomoj: You start out with a frame that contains the time, what keys were pressed, etc, then use that information to update the system… although… time between frames would be difficult to incorporate into that. |
| 15:16 | noncom | so its like state_n+1 = state_n + delta. what is delta? |
| 15:16 | tomoj | ah right, so basically like requestAnimationFrame, the current time is being passed in to each next-frame call |
| 15:17 | weavejester | Currently I have a tick event, like: {:type :tick, :tbf 0.0215} |
| 15:17 | weavejester | Where tbf is the time between frames, so I can use it to calculate position from velocity and so forth. |
| 15:17 | tomoj | eventually I guess any answer will boil down to that, but I want to completely eliminate it from the part of the code I usually look at |
| 15:18 | tomoj | just because of the nightmares I've had working with (bad, so this may be unfair) code that deals with that info |
| 15:19 | bbloom | http://blogs.msdn.com/b/shawnhar/archive/2007/07/25/understanding-gametime.aspx |
| 15:19 | bbloom | ^^ really good info about game time steps |
| 15:19 | tomoj | I guess a whole lot of the nightmare was the unrestricted mutation involved |
| 15:20 | weavejester | Maintaining a fixed game step time sounds difficult. |
| 15:21 | weavejester | And often you want to change position in time with your draw steps |
| 15:21 | weavejester | Okay, so if option 1 is to go fully functional, option 2 is to go fully event based. I'm not sure exactly what that would look like, though. |
| 15:22 | tomoj | so what's option 1? I've been trying to discover it :P |
| 15:23 | Foxboron | So, i got some time on my hands. Is there any Clojure projects wich could use a clojure newb for bug hunting? |
| 15:23 | weavejester | tomoj: I guess at each game tick, deliver some static datastructure about the current game state, and use it to generate a new data structure. |
| 15:24 | tomoj | hmm |
| 15:24 | tomoj | I was thinking the atom there that you swap! every tick makes it not 'fully functional' |
| 15:24 | tomoj | but it's basically the same as an iterate seq? |
| 15:25 | noncom | i have a question: i have a function that accepts {:keys [key-1 key-2.....]}. and i want to execute a separate action for each key, if it is not nil. so i do a bunch of lines like `(if key-1 (action-1 ...))` and for each key. is there any way to automate it? |
| 15:25 | weavejester | tomoj: Oh yeah, it's not fully functional at the moment. I'd do away with the atom if I went with this approach. |
| 15:25 | tomoj | no, it's not an iterate seq because information about user events etc magically shows up |
| 15:25 | noncom | its an io monad? |
| 15:26 | weavejester | tomoj: Yeah, the user events magically showing up is concerning me. |
| 15:26 | weavejester | tomoj: Do I need two data structures? (fn [previous-frame events] …) |
| 15:26 | weavejester | Or is that just another way of thinking about an event bus |
| 15:27 | noncom | weavejester: what are you trying to acheive after all? |
| 15:27 | weavejester | noncom: I don't know anymore :) |
| 15:27 | weavejester | noncom: I guess to get a good way of representing a 3D application with data. |
| 15:27 | weavejester | noncom: So a data-driven 3D app. |
| 15:28 | noncom | yeah i read that in the jmonkey thread |
| 15:29 | noncom | weavejester: so wahts the problem with making it data-driven? you want to eliminate state and mutations???\ |
| 15:29 | tomoj | (reduce next-frame initial-frame input-events) ? |
| 15:29 | weavejester | Currently it's an atom, but I'm mixing in :on-click events and stuff, which is probably bad. My model resembles a HTML DOM, in that it's data that can be mutated, and you can attach :on-blah events to elements. |
| 15:30 | weavejester | tomoj: Hum... |
| 15:30 | weavejester | tomoj: Interesting. |
| 15:30 | tomoj | just extrapolating from your suggestion |
| 15:30 | weavejester | noncom: I don't want to eliminate state and mutation - just constrain them. |
| 15:30 | tomoj | I don't know what you're trying to achieve either :) |
| 15:31 | weavejester | Fundamentally in any functional language, you want to reduce mutation to a minimum. |
| 15:31 | weavejester | Ideally, you have one function that hides all the mutation, and everything else is functional. |
| 15:32 | weavejester | So I guess that's my goal |
| 15:33 | tomoj | so you have input and output? |
| 15:33 | tomoj | or just output? |
| 15:33 | weavejester | tomoj: Input and output |
| 15:33 | weavejester | Which I guess is the root of the problem |
| 15:33 | weavejester | As I have input -> events |
| 15:33 | weavejester | output -> atom |
| 15:34 | weavejester | I'm dealing with input using an event bus, and then swapping an atom for output. |
| 15:34 | weavejester | I need to go one route or the other, I think. |
| 15:35 | noncom | weavejester: i don't really see a problem here |
| 15:35 | tomoj | there's basically two operations, obtain and render? |
| 15:35 | tomoj | @ and whatever that thing rich was talking about is called |
| 15:36 | tomoj | maybe conj! if that got broken out of transients |
| 15:36 | weavejester | noncom: What do you mean? |
| 15:37 | noncom | weavejester: are you trying to realize how to acheive that theoretically or how to code it in clojure? |
| 15:37 | weavejester | noncom: Coding it in Clojure |
| 15:37 | noncom | oh, i see then |
| 15:37 | noncom | i thought you were more after finding some theoretical basis for that |
| 15:38 | tomoj | bbloom: is a non-virtual tree just a map? |
| 15:38 | Pupnik- | weavejester, you have some good options for gamedev with clojure, like libgdx or slick2d |
| 15:39 | weavejester | Pupnik- I'm already using jMonkeyEngine behind the scenes. The internals aren't the issue so much. |
| 15:39 | Pupnik- | there just seemed to be a lot of fuss over frame time which is almost always provided by a lib if you use one |
| 15:40 | weavejester | Pupnik-: Oh, I can get the time frame easily. I'm just trying to find the right way to model it. |
| 15:40 | weavejester | Is it a series of asynchronous events? |
| 15:40 | weavejester | Or a functional transformation of frames? |
| 15:40 | noncom | this is a matter of POV |
| 15:41 | bbloom | tomoj: yeah, a map of maps of maps |
| 15:41 | n_b | On testing, the clojure.test is the community preferred option, right? |
| 15:42 | noncom | weavejester: is the only problem you have left is how to handle user input more functionally? is everything else (if there is no user input) already fully functional? |
| 15:43 | weavejester | noncom: I guess the issue is the amount of references I'm currently passing around... |
| 15:43 | ucb | n_b: clojure.test is the standard, but there are others like midje which are interesting to explore |
| 15:44 | weavejester | Okay, simple example: you click a box and it turns red. |
| 15:44 | tomoj | hey, great, I already have a red box |
| 15:44 | weavejester | So if the box mutates, maybe you put it in a ref. Does that mean all objects in your scene are refs? |
| 15:44 | tomoj | but no user input yet |
| 15:44 | n_b | ucb: I've seen people complaining about midje in here before, and while I don't know specifics I thought it was worth asking about before I go about open sourcing some stuff |
| 15:45 | Pupnik- | weavejester, you don't need mutation to turn your box red |
| 15:45 | weavejester | Do I have an event like: {:type :click :object (ref my-box)} |
| 15:45 | weavejester | Pupnik-: Can you elaborate? |
| 15:46 | ucb | n_b: I've used (and still use) midje with no complaints; but YMMV, it all depends on what you want and need really :) |
| 15:46 | noncom | weavejester: so, you *do not* have your world fully functionaly developing on each frame, you rely on pure state where possible? |
| 15:47 | Pupnik- | its state is part of the 'game state' that is re-generated each frame through the (new-state) function |
| 15:47 | weavejester | noncom: Currently the world is a ref, and the current application state is a ref. |
| 15:48 | weavejester | Pupnik-: Right, so alternatively, I could represent the box like: {:shape :box, :state :clicked} |
| 15:48 | weavejester | And then have a function that iterates through the world looking for clicked boxes and turning them red. |
| 15:48 | Pupnik- | well, ultimately you will need to tell your renderer what to do |
| 15:49 | weavejester | However… that sounds expensive. |
| 15:49 | Pupnik- | but your clojure code can be immutable |
| 15:49 | Pupnik- | watch some videos about clojure data structures :) |
| 15:49 | Pupnik- | of course, maybe it will be too much at 60fps |
| 15:49 | Pupnik- | I havent tried making a game yet, but i will soon |
| 15:49 | dnolen | weavejester: why not just thread the world state through the game? I liked ztellman's early experiments along those lines with penumbra |
| 15:49 | weavejester | Pupnik-: I am acquainted with Clojure data structures :) |
| 15:50 | Pupnik- | it shouldn't be too bad, its jmonkey that will do the rendering |
| 15:51 | weavejester | dnolen: Hm... |
| 15:51 | weavejester | I guess I need to clear my mind on this. |
| 15:52 | weavejester | Thanks everyone for listening to me ramble |
| 15:52 | weavejester | You've made me understand I'm really confused, and don't have a clear plan |
| 15:52 | dnolen | user events can go into a queue and you can assoc them onto the world state before calling into the main handler |
| 15:52 | weavejester | So… the first step to enlightenment is complete. |
| 15:53 | noncom | :D |
| 15:53 | weavejester | dnolen: Yeah, I was thinking about that. But doesn't that, I don't know, taint the world a little... |
| 15:53 | dobladez | Emacs question: to show eldoc messages, emacs expands and shrinks the "echo area", which is quite annoying. Anybody knows how to fix that? |
| 15:54 | noncom | weavejester: there is a need for a clear view i think |
| 15:54 | dnolen | weavejester: http://github.com/mjg123/pacman/blob/gh-pages/src/pacman/core.cljs#L321 |
| 15:54 | dobladez | I tried customizing option 'Eldoc Echo Area Use Multiline', but it doesn't seem to make a difference |
| 15:54 | Pupnik- | you can't keep the world state compeltely pure, it will always need to read things like frame time |
| 15:55 | Pupnik- | well, not always maybe your game doesnt care about that |
| 15:55 | Pupnik- | but usually |
| 15:55 | tomoj | huh? |
| 15:55 | tomoj | "world state" and "frame time" seem very disconnected, semantically, to me |
| 15:55 | Pupnik- | if you need to run a physics simulation, you need frame time |
| 15:56 | tomoj | if you describe the equations of the system being simulated, does the frame time play a role? |
| 15:57 | weavejester | I currently want to keep the app (i.e. what the user sees) separate from the world (i.e. what the server simulates) |
| 15:57 | weavejester | The app contains the UI, the 3D scene, the HUD, and so forth. |
| 15:57 | weavejester | An event might trigger a change in the world, or a change in the app. |
| 15:58 | tomoj | oh right, frame time clearly has nothing to do with the world in your case, since you might have multiple views of the same world running at different framerates? |
| 15:58 | tomoj | or just not in sync frame-by-frame with eachother anyway |
| 15:58 | Pupnik- | tomoj, it will be server tick rate in this case |
| 15:58 | tomoj | yeah, right |
| 15:58 | Pupnik- | since the server will run the simulation |
| 15:58 | tomoj | but still, does it show up in the equations? if not, I don't want to write it in my code :) |
| 15:58 | weavejester | tomoj: Yes. The world is potentially external (although there will be a local copy), the app is internal. |
| 15:58 | pandeiro | is there an easy way to use long-polling with jetty? |
| 15:59 | Pupnik- | unless you use a fixed time-step (which will cause the entire simulation to slow down if you can't hit your target), you need frame time or very strange things happen |
| 16:00 | weavejester | Currently an event will trigger a function, which can update the app or update the world, or both. |
| 16:00 | weavejester | But currently I'm taking a HTML DOM-like approach, and assigning event handles by adding :on-click attributes to the app. |
| 16:01 | weavejester | Which is leading to a circular dependency. |
| 16:01 | ztellman | weavejester: I wrote this ages ago about writing a "functional" game: http://ideolalia.com/creating-a-simple-game-in-clojure/index.html |
| 16:01 | tomoj | you need frame time somewhere, but I want it in the background, not in my world data/logic |
| 16:01 | ztellman | basically callbacks are pure functions on the world state, except for the display callback, which only performs side-effects |
| 16:02 | noncom | i think that user input is not something separate from the world. user input is an object of the world which has some interactions with other objects. however, it is not transperent for any object of the world - them can't see inside it. that is how i see it - it simply is an object of the world. and it's behavior inside the world is no different from other objects. |
| 16:03 | weavejester | ztellman: I've separated out internal state (like whether a UI window is displayed) from external state (like where the player is in the world) |
| 16:03 | tomoj | asteroids is a great example |
| 16:03 | weavejester | ztellman: Currently both are refs an event handler can update. |
| 16:03 | tomoj | source link is dead, new one https://github.com/ztellman/penumbra/blob/master/test/example/game/asteroids.clj |
| 16:03 | ztellman | weavejester: any reason to not have them just be entries in the same block of state? |
| 16:03 | ztellman | tomoj: I'll fix that, thanks |
| 16:04 | tomoj | I do not envy the people why find github links with "master" in their only promising search result - irc logs |
| 16:04 | tomoj | who. |
| 16:05 | tomoj | almost feels like it should be a redirect.. |
| 16:05 | tomoj | with a 'copy link to master' button with a red exclamation point and a tooltip.. |
| 16:05 | weavejester | ztellman: Well, the world can be updated over the network. I guess I could buffer network events per frame, but… that seems to be doing the job of a ref and dosync. |
| 16:06 | ztellman | weavejester: ah, ok, all my callbacks were in response to in-process events |
| 16:06 | ztellman | makes sense to differentiate |
| 16:06 | gfredericks | how can I run clojure.test tests without leiningen? |
| 16:07 | weavejester | ztellman: Clojure's refs provide a nice way of taking a per-frame snapshot of a changing data structure. |
| 16:07 | tomoj | bbloom: did you coin 'virtual' in the context of pedestal? |
| 16:07 | bbloom | tomoj: i'm speaking from memory. i think they called it a logical tree |
| 16:08 | ztellman | weavejester: yeah, if you look at the post I linked to, there were multiple concurrent processes updating the blob of state |
| 16:08 | ztellman | checking for collisions, checking if the exhaust should be emitted, etc |
| 16:08 | ztellman | all interacting with an atom |
| 16:08 | mikerod | Is this expected behavior of `flatten`? |
| 16:09 | tomoj | suppose you break the state up into a bunch of little atoms/refs |
| 16:09 | mikerod | ,(flatten (java.util.Collections/unmodifiableList [1])) |
| 16:09 | clojurebot | () |
| 16:09 | mikerod | (flatten (seq (java.util.Collections/unmodifiableList [1]))) |
| 16:09 | weavejester | ztellman: Maybe I'm looking at the wrong thing… what do your callbacks look like? |
| 16:09 | mikerod | ,(flatten (seq (java.util.Collections/unmodifiableList [1]))) |
| 16:09 | clojurebot | (1) |
| 16:09 | ztellman | the callbacks are registered at https://github.com/ztellman/penumbra/blob/master/test/example/game/asteroids.clj#L384 |
| 16:10 | ucb | gfredericks: you mean in a repl? |
| 16:11 | tomoj | instead of (assoc state :foo (foo' foo)) you have (swap! state/foo foo') say |
| 16:11 | tomoj | what did you lose? |
| 16:11 | weavejester | ztellman: Is the world state internal to the app? So the callbacks never see it directly? |
| 16:11 | gfredericks | ucb: sure |
| 16:11 | gfredericks | ucb: I'm debugging why my tests hang and thought I would rule out or implicate leiningen |
| 16:12 | ztellman | weavejester: notice that each of the callbacks have a 'state' parameter |
| 16:12 | ucb | gfredericks: there's (run-tests...) |
| 16:12 | ztellman | and they return a modified state |
| 16:12 | ucb | ,(doc run-tests) |
| 16:12 | clojurebot | Excuse me? |
| 16:12 | ucb | bleh |
| 16:12 | mikerod | ,(= (flatten (seq (java.util.Collections/unmodifiableList [1]))) (flatten (java.util.Collections/unmodifiableList [1]))) |
| 16:12 | clojurebot | false |
| 16:12 | technomancy | bbloom: I don't think losing your key needs to be handled differently from having it compromised |
| 16:12 | weavejester | ztellman: The {:dim *dim*} - is that the initial state? |
| 16:12 | weavejester | ztellman: So (app/start callbacks initial-state) ? |
| 16:13 | technomancy | basically before it's lost you generate a revocation cert; if it's lost/compromised you publish that with the date it was lost |
| 16:13 | bbloom | technomancy: which assumes i don't lose the revocation cert.... |
| 16:13 | technomancy | heh, yep. some people recommend printing it out and filing it. |
| 16:14 | technomancy | this is why we give keys an expiry date =) |
| 16:14 | bbloom | technomancy: i think i'm just gonna assume my key is safe-enough w/ my full drive encryption & not really worry all that much if i lose it. |
| 16:14 | technomancy | to limit the damage that can be done if it's compromised and can't be revoked |
| 16:14 | bbloom | technomancy: i know security people hate when smart folks say stuff like that :-) |
| 16:15 | bbloom | can i add a comment to my key w/ a link to these IRC logs, so that anyone who is trying to decide whether or not to trust me can make a judgement call? :-) |
| 16:15 | tomoj | it's basically a manual state monad, right? so what is lost if you just use state? |
| 16:15 | technomancy | bbloom: it's a big step up from not doing any signing =) |
| 16:15 | tomoj | (fn [state] (foo (update-state state) (update-state state))) becomes difficult? |
| 16:15 | technomancy | bbloom: checking a pom or pom .asc in usually isn't a great idea. using signed git tags is though. |
| 16:16 | bbloom | technomancy: signed git tags? |
| 16:16 | tomoj | ..I guess everything becomes difficult? |
| 16:16 | technomancy | bbloom: just use the -s arg to git tag |
| 16:16 | bbloom | technomancy: release management is a PITA….. stupid software… heh |
| 16:16 | weavejester | tomoj: Updating a state via a return value doesn't seem particularly tricky. |
| 16:17 | technomancy | bbloom: brb; screw this going back to rubygems, etc =) |
| 16:17 | bbloom | technomancy: ha |
| 16:17 | bbloom | technomancy: i mean, lein has to wait for the JVM to start, soooo who cares if rake takes 45 seconds to initialize? |
| 16:17 | ztellman | weavejester: sorry, stepped away for a second. Yes, that's correct. |
| 16:18 | linuxos | clojure uses just long for storing integers. even for small counters? |
| 16:18 | tomoj | well I'm imagining if you move the state ops down into all the leaves where you update a state map during an epoch. then everything is tricky, right? cus you're just in normal-java-variable land |
| 16:19 | tomoj | so with a state map and (fn [state] state'), inside an epoch you're in sane-functional-land? but if you look at the program across many epochs, do you have to start using mutation-land reasoning again? |
| 16:20 | Pupnik- | its the time slice approach |
| 16:21 | Pupnik- | the progress of time is represetned by a series of immutable states |
| 16:21 | clojurebot | c'est bon! |
| 16:21 | chessguy | salutations and other such pleasantries |
| 16:21 | weavejester | Pupnik-: Well, really, that's always the case |
| 16:22 | Pupnik- | weavejester, except normally those states are modified in place and you lose access to the old ones |
| 16:22 | Pupnik- | if you wanted to know a players velocity was 5 seconds ago |
| 16:22 | Pupnik- | you cant check |
| 16:22 | weavejester | ztellman: It seems that by changing the state through a callback, you lose some of the control a ref would give you. |
| 16:23 | weavejester | Pupnik-: Yeah, that's the main difference |
| 16:23 | tomoj | Pupnik-: how do you gain that ability? |
| 16:23 | tomoj | if you just have an atom with the current state, you don't have that ability, do you? |
| 16:23 | ztellman | weavejester: by only using callbacks, it gives the game loop more control over when these things happen |
| 16:23 | Pupnik- | no |
| 16:23 | ztellman | which I found to be useful |
| 16:24 | Pupnik- | or at least, i dont think so |
| 16:24 | ztellman | that may or may not prove true for you |
| 16:24 | Pupnik- | i know much more about how games work than about clojure |
| 16:26 | tomoj | I guess pedestal addresses this by making the current state a view of an append-only collection? |
| 16:26 | linuxos | clojure is dealing with longs as default .. is this to make it simple with no conversion back and forth despite greater memory consumption? |
| 16:26 | tomoj | (also datomic..) |
| 16:28 | linuxos | "Clojure 1.3 constructs a new Long around |
| 16:28 | linuxos | an int instead, because rich has decided he prefers longs and doubles |
| 16:28 | linuxos | to ints and floats. |
| 16:28 | linuxos | " |
| 16:29 | weavejester | brb food |
| 16:30 | tomoj | if you have (fn [state] state') that could just be a vector of all the states, except you probably don't want to keep them _all_ around in memory. in pedestal you have to turn recording on and the app itself has no access to the past? |
| 16:30 | tomoj | ..other than whatever it actively remembers in the state |
| 16:32 | tomoj | we have one nice solution already for deciding what needs to be remembered and automatically remembering it for those who need it - GC |
| 16:44 | jtoy_ | anyone know of a simpel library that will do cross validtion for me in clojure? |
| 16:48 | tomoj | jtoy_: I don't, but it shouldn't be too hard - if you have a (fn evaluate [train validation]), you can just do something maybe like this: https://www.refheap.com/paste/69451ef5033f9ec6c7743bb5b |
| 16:48 | tomoj | for k-fold |
| 16:48 | augustl | thinking of moving from lein-ring and war files to self contained jetty. Does lein-ring support that, or do I have to make my own "lein run" namespace where I start jetty myself etc? |
| 16:49 | tomoj | well you'd want to compute n from k |
| 16:51 | technomancy | augustl: it's easiest just to add ring-jetty-adapter and a 5-line -main defn |
| 16:55 | augustl | technomancy: I'll miss the auto reloading :) |
| 16:55 | augustl | probably easy to pull that in manually too, I guess |
| 16:55 | technomancy | augustl: nrepl |
| 16:56 | jtoy_ | tomoj: ok, I can try that, i've never written my own cross-fold library as I dont know 100% of the steps, but should be farily easy |
| 16:56 | augustl | technomancy: ah good, another reason for our one remaining IntelliJ dev to switch ;) |
| 16:59 | tomoj | jtoy_: oh wait, looks like incanter has it |
| 16:59 | tomoj | "simple"? not sure |
| 17:03 | owengalenjones | anyone ever see this https://www.refheap.com/paste/14406 |
| 17:04 | jtoy_ | tomoj: if I understand properly, the whole algorithm is just cut into k slices, train on k-1 and test against k and do that for all combinations and then average the results? |
| 17:04 | tomoj | yeah |
| 17:04 | ucb | owengalenjones: I don't think :1 is a valid keyword |
| 17:05 | owengalenjones | ucb: (keyword? :1) => true :) |
| 17:06 | ucb | owengalenjones: ugh :) |
| 17:06 | ucb | I honestly thought it wasn't a valid keyword :) |
| 17:06 | arohner | ,(keyword "foo "bar") |
| 17:06 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading string> |
| 17:06 | arohner | ,(keyword "foo bar") |
| 17:06 | clojurebot | :foo bar |
| 17:06 | owengalenjones | O_o |
| 17:07 | arohner | ,(keyword ":foo") |
| 17:07 | clojurebot | ::foo |
| 17:08 | gfredericks | ucb: you've really exposed my tendency to not put the smallest amount of effort into figuring things out for myself |
| 17:08 | ucb | gfredericks: I'm a sinner as well :) |
| 17:17 | kathy1 | Holaaa |
| 17:19 | jtoy_ | tomoj: evaluate in your example just means call my function? |
| 17:41 | satch5150 | hi all, I am trying to figure out how to use cli from tools.clj; it all seems pretty staight forward, except I do not know how to use :parse-fn patterns; could someone point me to some appropriate documentation for that ? |
| 18:22 | tomoj | jtoy_: right |
| 18:22 | tomoj | which returns your metric on the validation data after training |
| 18:34 | Apage43 | man, going back and forth between emacs and vim recently, as I can get stuff done a bit faster w/ clojure in emacs, but still like vim for C and friends |
| 18:35 | Apage43 | in emacs when I'm whacking out one of these intricate incantations I feel like one wrong move could annihilate an entire civilization. I've already deleted files by fat-fingering a couple of them. |
| 18:36 | Apage43 | in vim the worst I'll do is delete some of the file I'm working on, which is easy enough to undo |
| 18:38 | ohpauleez | Apage43: Why not use fireplace in vim? |
| 18:39 | tomoj | does pedestal's :continue violate the epochal time model? |
| 18:39 | Apage43 | I do. It's fantastic as far as those things go, and I like it better when I'm working on some things. |
| 18:39 | ohpauleez | fireplace + paredit + surround makes for a pretty competent setup |
| 18:39 | ohpauleez | ahh cool |
| 18:39 | tomoj | or it just makes the epochs sub-transaction? |
| 18:39 | Apage43 | what it doesn't handle very well is when I am evaling expressions that might get stuck in a loop and I need to kill them |
| 18:40 | ohpauleez | Apage43: It'll timeout and drop it |
| 18:40 | ohpauleez | but you'll have to restart the jvm - as you would in emacs too |
| 18:40 | Apage43 | it does that and frees up my vim session yeah, but my nrepl sessions typically is still hung |
| 18:40 | hiredman | tomoj: continue is just a loop |
| 18:40 | ohpauleez | right, I guess I always have my repl instance running in another tmux pane or window |
| 18:41 | Apage43 | nrepl.el C-c c-c will actually .stop the thread |
| 18:41 | Apage43 | which even works some of the time |
| 18:41 | ohpauleez | ahh gotcha |
| 18:41 | Apage43 | same as what Ctrl-C does in lein repl/reply |
| 18:41 | tomoj | hiredman: oh, yes, I was thinking each transaction was doing multiple messages despite having just read that each message gets a transaction |
| 18:41 | Apage43 | of course emacs still barfs all over the place if I accidentally eval something that prints too much |
| 18:43 | tomoj | hmm "It returns a sequence of messages which will be processed within the same transaction." what? |
| 18:44 | arrdem | Apage43: really? I've seen the colors and formatting go bad, but I've never seen emacs actually break |
| 18:45 | tomoj | I've sometimes felt like I wanted something like :continue in datomic |
| 18:46 | Apage43 | arrdem: I tend to have bad luck if I throw a (println) in a fast loop. It doesn't crash, it just moves -very slowly- while I try to kill the evaluation |
| 18:46 | Apage43 | and sometimes it's just faster to kill emacs and bring it all back up |
| 18:46 | linuxos | can i get a long unsigned in clojure? |
| 18:46 | tomoj | for like installing a bunch of schema tx-datas which maybe depend on each other but still being able to fail the entire thing (i.e. one transaction) if something goes wrong in a later tx-data |
| 18:47 | tomoj | but I suspect there is a very good reason datomic doesn't allow this.. |
| 18:47 | bbloom | linuxos: you can't get an unsigned anything in java |
| 18:47 | Apage43 | most of this isn't an issue for the majority of the time. I only tend to eval expressions that are freezing and printing way too much if I'm debugging :P |
| 18:47 | arrdem | Apage43: is there a better logging lib than good ol' println? |
| 18:47 | hiredman | tomoj: you can think of the queue being (ref []) and processing the queue as being something like (dosync (loop [] (when (seq @queue) (do (do-stuff-with-qeueu-contents) (recur))) |
| 18:48 | Apage43 | probably |
| 18:48 | hiredman | and what happens is there is a watch on the queue ref, so if put something in it runs the processing transaction there |
| 18:48 | Apage43 | I'd specifically like something that will just not print if the receiving end can't take it. like .offer on a queue or something. |
| 18:49 | hiredman | and with the processing transaction you can alter the intransaction value of the queue ref, which results in more messages that are processing in the transaction |
| 18:49 | tomoj | ok, yeah |
| 18:49 | hiredman | (I haven't looked at how it is actually implemented, some kind of atom thing) |
| 18:49 | tomoj | datomic does not allow any intransaction stuff |
| 18:49 | arrdem | Apage43: looks like timbre and clojure/tools.logging are the options |
| 18:50 | arrdem | and they're both pretty srs bizness logging |
| 18:50 | hiredman | well, you can have transaction functions |
| 18:50 | tomoj | right but they only get the pre-transaction db as input |
| 18:50 | tomoj | so that there can be no causality between datoms within a transaction |
| 18:52 | tomoj | though you can make a txfn that takes an entire tx-data and runs it with datomic.api/with, then use that to decide what to expand to, if you're OK with some overhead |
| 18:53 | tomoj | app.clj and dataflow.clj seem delightfully simple in any case |
| 18:53 | shriphani | hi. I am looking for good data visualization libraries in clojure. I've found incanter so far. Are there any others that are particularly recommended? |
| 18:57 | tomoj | hiredman: so under normal circumstances when the queue watcher fires, the queue is always going just have the one message in it? |
| 18:58 | hiredman | tomoj: yeah, and you could add some kind of fanciness to ensure that sort of thing |
| 19:14 | lynaghk` | Does anyone know if ruby has something akin to "pr-str"? |
| 19:15 | gfredericks | lynaghk`: #inspect I think is it |
| 19:16 | gfredericks | $findfn pos? [-1 2 -3 4 -5] [[2 4] [-1 -3 -5]] |
| 19:16 | lynaghk` | gfredericks: ohh, awesome. thanks! |
| 19:16 | lazybot | [] |
| 19:20 | hyPiRion | ,((juxt filter remove) pos? [-1 2 -3 4 -5]) |
| 19:20 | clojurebot | [(2 4) (-1 -3 -5)] |
| 19:20 | hyPiRion | ~amalloy |
| 19:20 | clojurebot | amalloy is <amalloy> just use juxt, it'll be great |
| 19:21 | gfredericks | turned out I wanted group-by anyways |
| 19:21 | gfredericks | but prior to that I did recall the olde Amalloy Adage |
| 19:22 | irctc305 | I have a map that I want to concat to a list of maps -> (concat [{:a 2}] {:b 3 :h 5} [{:c 4}]) |
| 19:22 | irctc305 | However the above adds the map as a map entry ({:a 2} [:b 3] [:h 5] {:c 4}) |
| 19:23 | irctc305 | How can I just add a map to a list of maps at the start and end ? |
| 19:24 | gfredericks | (concat [some-map] a-list-of-maps [some-other-map])? |
| 19:25 | hiredman | (concat [{:a 2}] {:b 3 :h 5} [{:c 4}]); one of these three args is not like the others |
| 19:25 | gfredericks | one of these args just doesn't belong |
| 19:26 | benkay | hey y'all, a question about loading data from the filesystem: |
| 19:27 | benkay | I just wrote a public key to disk using (spit "testpub.pem" (clj-crypto/public-key keypair)), but when I (clj-crypto/as-public-key (slurp "testpub.pem")) the crypto lib blows up not knowing how to convert the string back into a public key |
| 19:27 | irctc305 | thanks for the pointer, just enclosing the second arg as a vector solves it ! now all args are of the same type |
| 19:28 | benkay | is there an obvious thing i'm missing about what i'm trying to do here? |
| 19:29 | hiredman | never heard of clj-crypto |
| 19:29 | benkay | bouncycastle wrapper |
| 19:29 | hiredman | but my guess is you are doing character io using bytes |
| 19:29 | hiredman | spit is not the way to go for reliable io |
| 19:29 | benkay | would that look like nonsense when I open the file? |
| 19:29 | hiredman | have you actually looked at the contents your .pem? |
| 19:29 | benkay | oh yeah, it's just a string. |
| 19:30 | benkay | <RSAPublicKeyImpl ... |
| 19:30 | hiredman | just a string? |
| 19:30 | hiredman | ah |
| 19:30 | gfredericks | not a very good public key |
| 19:30 | hiredman | you haven't even gotten to io yet |
| 19:30 | hiredman | (clj-crypto/public-key keypair) is just returning a key object |
| 19:30 | hiredman | you'll need to do some more work to get actual bytes |
| 19:30 | hiredman | spit is just calling toString on the object |
| 19:31 | benkay | sounds like you're suggesting writing the bytes to disk and then reading them back off? |
| 19:32 | gfredericks | yeah for crypto stuff you'll want to use bytes not strings |
| 19:32 | benkay | thanks gfredericks, hiredman |
| 19:33 | benkay | is there something like spit that writes bytes? |
| 19:33 | hiredman | forget spit |
| 19:34 | hiredman | go look at the code for clj-crypto or the java docs for bouncy castle |
| 19:34 | hiredman | figure out what it is that clj-crypto returns |
| 19:34 | hiredman | figure out how to turn that in to bytes |
| 19:35 | hiredman | by the time you are done I imagine you will be ready to ditch clj-crypto because you will be comfortable using bc directly |
| 19:36 | hiredman | you will most likely need the javax.crypto java docs too |
| 19:36 | hiredman | http://docs.oracle.com/javase/6/docs/api/java/security/interfaces/RSAPublicKey.html |
| 19:39 | Apage43 | if you have some type of Key, .getEncoded is on the Key interface (for java.security.Key) which gets you bytes |
| 19:42 | amalloy | (inc hyPiRion) |
| 19:42 | lazybot | ⇒ 14 |
| 19:48 | shriphani | hi I have a question about enlive. How do I do [:div.class_name] only class_name has a space in it... |
| 19:49 | benkay | thanks Apage43! |
| 20:03 | weavejester | May I ask what everyone uses for note-taking? I usually use emacs and a text or markdown file… |
| 20:04 | tieTYT2 | google drive? |
| 20:04 | technomancy | weavejester: org-mode |
| 20:04 | tieTYT2 | or a program on my cell phone called AK notepad |
| 20:04 | weavejester | technomancy: I was hoping someone would say that :) |
| 20:05 | technomancy | weavejester: I basically use org like outline-mode though |
| 20:05 | weavejester | technomancy: I know org-mode can be used for todos and time-keeping, but does it have anything for note-taking over a text file? |
| 20:05 | hiredman | weavejester: what do you want for note-taking? |
| 20:05 | technomancy | weavejester: the ability to collapse outlines is the main thing I use it for |
| 20:05 | hiredman | what are the component features of note-taking for you |
| 20:06 | hiredman | org-mode tables are like be able to embed little spreadsheets, but the formulas can be in elisp |
| 20:06 | weavejester | hiredman: Something to act as an external memory while I'm trying to solve a problem that's too large for me to hold all possible paths in my head reliably. |
| 20:07 | hiredman | weavejester: yeah, but you asked for features over a text file, org-mode has 1e100 features |
| 20:08 | technomancy | literally the largest lisp file on my hard drive |
| 20:08 | technomancy | probably the largest non-autogenerated lisp file on github |
| 20:08 | hiredman | you can do org-capture which pops up a little buffer you type in to, then saves each little note as a bullet point in a larger file of todos |
| 20:08 | tieTYT2 | i really liked haskell's pattern matching. Clojure was created after haskell but I believe RH was aware of it. Anyone know the decision to leave it out of clojure? |
| 20:08 | weavejester | hiredman: Well, I don't really know what features I'd want, without know which ones there are... |
| 20:08 | bbloom | i just use a text file in vim |
| 20:08 | bbloom | i have a directory called notes & there are about 20+ files in there |
| 20:08 | hiredman | org-mode lets you create a list of times with various todo status and sort the lists based on the todo status |
| 20:08 | technomancy | tieTYT2: the official story is that pattern matching is closed, while predicate dispatch is open. |
| 20:09 | bbloom | i mostly never read them lol |
| 20:09 | technomancy | tieTYT2: I don't really buy that though |
| 20:09 | weavejester | tieTYT: There's core.match, so pattern matching is only left out of the core language |
| 20:09 | scottj | weavejester: btw, org-mode was originally for note-taking. the other things came later. |
| 20:09 | technomancy | core.match has issues =\ |
| 20:09 | hiredman | org-mode will renumber your lists for you if you put an element in the middle of a numbered list |
| 20:09 | tieTYT2 | technomancy: I don't know what either of those mean |
| 20:09 | tieTYT2 | what do you mean by closed? |
| 20:09 | tieTYT2 | weavejester: let me check that out |
| 20:09 | technomancy | tieTYT2: compare it to cond vs defmulti |
| 20:09 | technomancy | tieTYT2: cond only works on values known up-front; defmulti can be extended after the fact |
| 20:10 | tieTYT2 | so cond is called "closed"? |
| 20:10 | technomancy | yeah |
| 20:10 | technomancy | tieTYT2: note that I do not find this justification persuasive at all |
| 20:10 | hiredman | you cannot extend a pattern match or a cond with rewriting the original code, but you can extend defmultis from new code without touch the old code |
| 20:11 | tieTYT2 | why can't you have both? |
| 20:11 | bbloom | you can only be open or closed with respect to something…. cond is closed to adding cases at runtime |
| 20:11 | tieTYT2 | I never thought of defmulti as an answer to pattern matching. I always thought of destructuring as an answer to pattern matching |
| 20:12 | technomancy | tieTYT2: I only brought up defmulti as an example to explain closed/open |
| 20:12 | tieTYT2 | technomancy: ohh |
| 20:12 | clojurebot | technomancy is to blame for all failures |
| 20:12 | technomancy | you can certainly have both |
| 20:12 | hiredman | org-mode has org-babel which lets you put in little snippets of code (properly hilighted using the mode of your choice) and then execute the code and insert the result right in place in the document |
| 20:12 | technomancy | clojurebot: you're one to talk |
| 20:12 | clojurebot | Huh? |
| 20:12 | bbloom | tieTYT2: pattern matching is desructuring plus ordered choice. i think that the ordered choice bit is the bit that rich doesn't like |
| 20:12 | weavejester | Has anyone made much use of watches on refs? |
| 20:12 | hiredman | I use them for a debugging a lot |
| 20:13 | tieTYT2 | bbloom: what's the downside to that? |
| 20:13 | amalloy | weavejester: i've watched a couple of atoms, but not for very good reasons |
| 20:13 | bbloom | tieTYT2: consider a complex cond block… you can't re-order statements without considering logical implications of the conditions/predicates |
| 20:14 | bbloom | tieTYT2: for example if you had (cond (pos? x) :pos (even? x) :even) then what you reeaaaly mean is not :even, but :negative-and-even |
| 20:15 | weavejester | I think I'm going to try and use watches in place of an event queue. |
| 20:15 | bbloom | if you re-order the clauses, you are changing the meaning. that's not true of multimethods for example |
| 20:15 | tieTYT2 | true |
| 20:16 | bbloom | pattern matching is most useful when you want to do exhaustive case analysis. like in haskell where you have algebraic data types |
| 20:16 | bbloom | in which case, you really want a switch b/c that lets you reorder the clauses |
| 20:16 | bbloom | i've seen some haskell code that makes some pretty subtle assumptions based on the order of patterns. i can be confusing |
| 20:16 | tieTYT2 | in my mind, he chose destructuring instead of pattern matching. But it sounds like everyone here is saying he didn't want pattern matching because it can complicate things |
| 20:16 | tieTYT2 | and destructuring is not related |
| 20:16 | bbloom | he said that in a talk at one point |
| 20:17 | tieTYT2 | bbloom: the one on simple made easy? |
| 20:17 | tieTYT2 | yeah I noticed that, but I didn't understand why |
| 20:17 | bbloom | he said something to the effect that pattern matching complects name binding and ordered choice while remaining closed to adding cases at runtime |
| 20:17 | bbloom | destructuring, as implemented in clojure, is closed with respect to adding new pattern types |
| 20:18 | tieTYT2 | he says that, but I don't see him giving an alternative |
| 20:18 | tieTYT2 | or something better |
| 20:18 | bbloom | so the "better" thing is predicate dispatch |
| 20:18 | bbloom | but predicate dispatch is still somewhat of an open research problem |
| 20:18 | tieTYT2 | eg: cond? |
| 20:19 | tieTYT2 | or defmulti? |
| 20:19 | bbloom | *shrug* cond is just so simple & so often useful that you kinda gotta have it |
| 20:19 | tieTYT2 | for me: http://stackoverflow.com/questions/5671627/what-is-predicate-dispatch |
| 20:20 | bbloom | the real hard part of predicate dispatch is determining logical implication |
| 20:20 | tieTYT2 | i never thought of using multimethods this way |
| 20:20 | tieTYT2 | wouldn't it be frowned upon to use it when you could use pattern matching? |
| 20:20 | tieTYT2 | i've been told it's pretty slow |
| 20:20 | bbloom | it's only really slow when dispatching on the java type hierarchy |
| 20:20 | bbloom | it's reasonably fast otherwise |
| 20:20 | bbloom | not as fast as protocols & simple branches, but still pretty quick |
| 20:21 | tieTYT2 | i see. I've written two small programs that use multi methods and they both dispatch on symbols |
| 20:21 | bbloom | see http://homes.cs.washington.edu/~mernst/pubs/dispatching-ecoop98-abstract.html |
| 20:21 | tieTYT2 | or contents of a string |
| 20:23 | tieTYT2 | thanks |
| 20:24 | tieTYT2 | i had this function that needed to do different things depending on the count of the sequence passed in. I didn't consider a multimethod as a good choice to implement that |
| 20:25 | bbloom | tieTYT2: if the count only falls into a fixed set of cases, like 0, 1, 2, or N… then case is the way to go |
| 20:25 | bbloom | or cond even |
| 20:25 | tieTYT2 | yeah that's pretty much what I ended up doing |
| 20:25 | bbloom | a multimethod is useful when you want other folks to be able to add cases |
| 20:25 | tieTYT2 | yeah I don't have that situation |
| 20:25 | bbloom | you need to ask the question "do i need open dispatch?" |
| 20:25 | bbloom | if the answer is no, choose something simpler |
| 20:25 | tieTYT2 | whereas pattern matching is useful even if you don't need open dispatch |
| 20:26 | tieTYT2 | it would have been good in this situation. I think a case/cond was more complicated than pattern matching would have been |
| 20:27 | bbloom | so i agree that pattern matching is sometimes useful, but i think it's attractive syntax means that people tend to use it by default and that means creeping complexity in logical ordering of predicates |
| 20:27 | bbloom | fewer branching constructs in your code is generally easier to understand & pattern matching inherently adds one branch point per pattern |
| 20:27 | tieTYT2 | perhaps you're right. I only used haskell for 1-2 months so I wouldn't have discovered that by then I think |
| 20:29 | bbloom | i think pattern matching is absolutely a more concise notation for a lot of common patterns in code. however, i've found that prefer making an explicit decision between if, cond, case, when, etc. my code may be a couple lines longer, but it's easier to read & refactor. but that's just my opinion |
| 20:29 | tieTYT2 | but IME, the pattern matching reduces your overall code so it makes up for that issue |
| 20:31 | technomancy | I agree |
| 20:31 | technomancy | I would use core.match if it didn't break AOT |
| 20:32 | tieTYT2 | that's an intimidating restriction |
| 20:32 | tieTYT2 | i'm not experienced enough to knwo if I need that |
| 20:32 | pjstadig | meh |
| 20:32 | pjstadig | AOT is kinda broken already |
| 20:32 | clojurebot | In Ordnung |
| 20:32 | pjstadig | ~AOT |
| 20:32 | clojurebot | AOT is kinda broken already |
| 20:32 | pjstadig | haha |
| 20:32 | technomancy | pjstadig: not for libraries obvs |
| 20:33 | technomancy | I mean I wouldn't use it for libs |
| 20:33 | technomancy | but I always AOT before deployment |
| 20:33 | technomancy | (not on my own box of course) |
| 20:34 | hiredman | someone could just fix core.match |
| 20:35 | hiredman | ugh, the jira issues doesn't have a reproducable case |
| 20:35 | tieTYT2 | http://clojuredocs.org/clojure_core/clojure.core/for I really think the ordering of the two examples for ; Demonstrating difference between :when and :while should be swapped |
| 20:35 | hiredman | ah, this other issue has a reproducable case |
| 20:36 | tieTYT2 | is it always fixable? |
| 20:38 | hiredman | other languages have pattern matching, proving pattern matching can be done ona turing machine, clojure is turing machine equiv, so clojure can do pattern matching, so it is fixable |
| 20:38 | hiredman | qed |
| 20:38 | hiredman | it just may mean embedding a haskell or ml compiler in a clojure macro |
| 20:39 | bbloom | heh. |
| 20:43 | hiredman | the core-futures stuff is inspiring in that regard, the macro turns clojure code in to some kind of traditional compiler formalism (SSA, CPS, ANF) does its thing on the formalism, then regenerates clojure code from the formalism |
| 20:44 | tieTYT2 | this is over my head |
| 20:44 | hiredman | which makes sense for more complicated macros that are really source to source compilers |
| 20:48 | amalloy | i haven't looked at core-futures myself, but i heard it was SSA, from someone who was puzzled that it wasn't CPS |
| 20:49 | hiredman | someone showed that cps and ssa are equivalent, but cps is used a lot for functional languages |
| 20:52 | hiredman | the guile guy had a blog post a few years ago |
| 20:53 | hiredman | http://wingolog.org/archives/2011/07/12/static-single-assignment-for-functional-programmers/ |
| 21:18 | qbg_ | hiredman: Do you have link describing core-futures? |
| 21:22 | hiredman | http://dev.clojure.org/display/design/Async+blocks |
| 21:24 | qbg_ | nice |
| 21:24 | tomoj | really more core-async |
| 21:25 | tomoj | core-futures will I think be replaced |
| 21:25 | tomoj | or maybe they'll stick with it, but I remember a note somewhere saying "this is temporary, TODO decide on future implementation" or something |
| 21:27 | tomoj | delightfully there is only one small spot in core-async that depends on core-futures |
| 21:27 | dnolen | tomoj: i believe they are two distinct and necessary pieces |
| 21:27 | tomoj | indeed |
| 21:28 | tomoj | I just mean "Async blocks" and the work on the relevance branch is more about core-async than core-futures |
| 21:28 | tomoj | oh but the branch is called core-futures, heh |
| 21:28 | tomoj | «Note: the implementation of futures should be considered in "draft" phase, it will change radically before an alpha is released.» |
| 21:32 | qbg | that is beautiful |