2014-01-12
| 00:00 | Tolstoy | Set up a project, serve out an index.html page, then use cljsbuild to play with clojurescript. |
| 00:02 | Tolstoy | With cljsbuild, I don't think you even need a clojure server side. |
| 00:04 | kanja | cljsbuild is something to check out then |
| 00:13 | ddellacosta | kanja: definitely *don't* start with pedestal if you want to use cloact. Do something like create a new cljs project with David Nolen's mies template, then add cloact. lein new mies my-project-name |
| 00:15 | kanja | @ddellacosta mies? I'll try that - thanks for the tip! |
| 00:16 | bitemyapp | kanja: if you want an easy shake-n-bake way to go for Clojure web dev backends check out luminus. It's essentially a template for common-case Ring and Compojure stuff. |
| 00:17 | kanja | @bitemyapp Awesome, thanks! |
| 00:21 | Tolstoy | I kinda get the feeling that ClojureScript is a nice little secret weapon. |
| 00:22 | ddellacosta | kanja: np |
| 00:28 | egghead | clj is a very fun web stack these days, most recently i've been playing with liberator, compojure, cljs-http, & om |
| 00:29 | egghead | cljs http in particular, interacting with http (ring) the same way on client and server is very nice :) |
| 00:30 | benzap | so typically, do you write the cljs files the same way you would write a clj file |
| 00:30 | benzap | and then it generates the proper js file when it's requested? |
| 00:31 | egghead | usually you compile a cljs app into a single js file including all deps, with a single entry point |
| 00:32 | benzap | so the deps can be just pure javascript? |
| 00:32 | benzap | like, i could include jquery |
| 00:33 | egghead | mhmm, you can and there is a cljs wrapper for making it more idiomatic in clj |
| 00:33 | benzap | alright cool |
| 00:33 | noonian | but there are better options than jquery in cljs imo |
| 00:33 | benzap | i'm just trying to learn clojure for now, but i'm really interested in compjure with clostache |
| 00:34 | egghead | noonian: I agree |
| 00:35 | benzap | there's always better options than jquery ;) |
| 00:35 | egghead | benzap: cljs is built on top of the google closure js library, so there are some nice libs wrapping googles stuff |
| 00:35 | benzap | ah ok |
| 00:35 | benzap | I was wondering why a lot of the examples had goog in it |
| 00:54 | ddellacosta | benzap: Self-promotion, but I recommend checking out my article on dom libs here if you want to know more: http://davedellacosta.com/cljs-dom-survey |
| 01:33 | bitemyapp | arrdem: ring ring |
| 01:37 | bitemyapp | arrdem: http://i.imgur.com/oO2SSs1.jpg |
| 01:37 | bitemyapp | arrdem: rat dota. |
| 03:45 | shock_one | Is there something like haskell's flip in clojure, which flips function's parameters? (a -> b -> c) -> b -> a -> c |
| 03:46 | noonian_ | you could write it pretty easily |
| 03:47 | shock_one | I understand, but it would be silly if there is a built-in function. |
| 03:48 | noonian_ | i don't think there is a built in one |
| 03:49 | shock_one | Thank you. |
| 04:32 | Guest68185 | looking at tarsnap-keymgmt i was thinking of leaving a key on the server with just -w (so if hacked an attacker couldnt delete archives), however does -w give the ability to rewrite/overwrite hence with a tiny bit more work causing the same effect of -d? |
| 04:33 | Guest68185 | sorry wrong room |
| 04:46 | Raynes | ifesdjeen: Hi. |
| 05:46 | quizdr | nice |
| 07:21 | indiana | hello all |
| 07:21 | indiana | why println "hello" "world" produce "hello world" - not "helloworld"? |
| 07:22 | hyPiRion | because println and print makes spaces between the arguments given |
| 07:23 | indiana | how i can print it without whitespaces? |
| 07:23 | hyPiRion | use (str ...) first, then println |
| 07:23 | hyPiRion | so ##(println (str "hello" "world")) |
| 07:23 | lazybot | ⇒ helloworld nil |
| 07:23 | indiana | thanks man :) i am new in clojure |
| 07:24 | hyPiRion | no problems, hope you enjoy it :) |
| 07:26 | indiana | do you have any experience with java in web applications? do you like more using clojure for web applications? |
| 07:27 | hyPiRion | I haven't used Java for web applications, but I've done some work in Clojure and I think it's good for that purpose. |
| 07:28 | indiana | I'm java programmer and i try clojure now. I hope that i will be happy with clojure :) |
| 07:30 | hyPiRion | ah. The hardest part from a Java-background is that you'll have to learn how to program without mutation (and the parentheses), but when you finally manage to work with just immutability, it's really satisfying |
| 07:33 | locks | hyPiRion: the parens are the same, they’re just on the outside ;) |
| 07:33 | locks | immutability is doing my head in though |
| 07:34 | locks | being used to Ruby et al |
| 07:35 | alew | so I have these nested error checks that go about 7 ifs/if-lets deep |
| 07:35 | alew | is there a better way to format it so that they aren't so nested? |
| 07:35 | hyPiRion | locks: yeah, that's why I put the parens in parens (heh). They are a bit scary and unknown at first, but when you've worked just a little bit with them, stuff gets so much easier |
| 07:35 | alew | every failed check evalulates to a single statement that returns an error message |
| 07:36 | hyPiRion | alew: a cond perhaps? |
| 07:37 | locks | hyPiRion: I think it was stuart that demonstrated in a talk that Clojure actually had less parens than a Java example |
| 07:37 | locks | hyPiRion: granted it was probably a cherry picked example, but it’s always entertaining busting myths |
| 07:38 | alew | I also need to have binding lets some ways down |
| 07:38 | alew | I'll probably just write a let-cond |
| 07:38 | alew | or something |
| 07:39 | hyPiRion | ah, bindings. |
| 07:39 | alew | would be simple otherwise |
| 07:40 | hyPiRion | yeah, I think actually making a cond-let would be fair there. |
| 07:41 | alew | someone made this http://clojuredocs.org/clojure_contrib/clojure.contrib.cond/cond-let |
| 07:41 | alew | but I want to have conditionals and optional let bindings on each condition |
| 07:41 | alew | a cond with both if and if-let options |
| 07:45 | hyPiRion | well, hm. |
| 07:46 | hyPiRion | A cond takes a single branch only. How would a let binding in a cond work? |
| 07:47 | alew | like how if-let works |
| 07:47 | hyPiRion | alright |
| 07:48 | alew | (let-cond (testexpr) "error 1!" [a (non-nil-operation)] "error 2!" :else "success!") |
| 07:48 | alew | maybe something like this? |
| 07:49 | hyPiRion | I'd guess you would use a in the "error 2!" statement |
| 07:50 | alew | if a is nil, then "error 2!" is returned |
| 07:50 | alew | otherwise it continues on |
| 07:50 | alew | oh yeah, that's weird.. |
| 07:50 | alew | hrm |
| 07:50 | hyPiRion | just (not) the thing |
| 07:51 | alew | the a, in this case? |
| 07:51 | hyPiRion | well, the (non-nil-operation) |
| 07:55 | alew | I guess it's a let-not-cond :P |
| 07:55 | alew | beacuse it only evals the statements if the test expression is false |
| 07:58 | hyPiRion | well, here's a cond-let anyway https://www.refheap.com/22921 |
| 07:58 | alew | did you just write this? |
| 07:58 | alew | awesome |
| 07:58 | hyPiRion | yeah |
| 07:59 | alew | oh nice, using the if and if-let |
| 07:59 | hyPiRion | it's not that hard if you just know how to utilize the already existing macros |
| 08:00 | alew | https://www.refheap.com/22922 |
| 08:00 | alew | pretty easy to make the cond-let-not |
| 08:01 | DerGuteMoritz | uncond-let :-) |
| 08:01 | alew | need to add a check for a default case |
| 08:01 | alew | doublepluscond-let |
| 08:02 | DerGuteMoritz | the default case shouldn't need special handling, it's just :else expr, no? |
| 08:02 | hyPiRion | DerGuteMoritz: yeah |
| 08:02 | DerGuteMoritz | so a regular if branch |
| 08:02 | alew | in this case it does |
| 08:02 | alew | because of the switch |
| 08:03 | alew | you want to eval the expression for the last clause if it is true |
| 08:03 | alew | or I guess you could just pass nil |
| 08:06 | alew | I fucking love macros |
| 08:07 | DerGuteMoritz | there's nothing cooler than a macro *sing* |
| 08:08 | alew | Great book |
| 08:18 | alew | well, the uncond-let looks pretty ugly when there are tons of statements in it |
| 09:14 | benzap | So I ran the lein help, and it's not being nice |
| 09:15 | benzap | the examples don't seem to work |
| 09:15 | benzap | any ideas? |
| 09:27 | JoltinJoe | join eclipse |
| 09:29 | sandbags | benzap: what does "not being nice" and "don't seem to work" actually mean for you? |
| 09:40 | benzap | sandbags: sorry, I should give specifics |
| 09:40 | benzap | I ran lein help tutorial |
| 09:40 | benzap | followed the tutorial |
| 09:41 | benzap | the first part that didn't work was |
| 09:41 | benzap | (user/clojurefocs pprint) |
| 09:41 | benzap | while in lein repl |
| 09:41 | benzap | i called each of the functions before that |
| 09:42 | benzap | so everything should be imported |
| 09:42 | benzap | (i think) |
| 09:42 | benzap | if you grep lein help tutorial at line "user=> (require 'my-stuff.core)" |
| 09:42 | benzap | you should be where I started executing commands |
| 09:43 | benzap | it's unclear why it fails |
| 09:43 | sandbags | (user/clojuredocs pprint) works for me |
| 09:43 | sandbags | without doing anything else |
| 09:43 | benzap | i'm going to try it again, one sec |
| 09:44 | sandbags | that "f" in clojurefocs was that a c&p error? or did you type that in the repl? |
| 09:44 | benzap | would also like to point out that i'm on emacs |
| 09:44 | benzap | with windows |
| 09:44 | benzap | and eshell |
| 09:44 | benzap | so it might even be my side |
| 09:45 | sandbags | but beyond that saying "didn't work" (again above) isn't useful to anyone trying to help you... if things fail please gist exactly what you ran and the output |
| 09:46 | benzap | so when I type (user/clojuredocs pprint) |
| 09:46 | benzap | i get CompilerException java.lang.RuntimeException: No such var: user/clojuredocs, compiling:(C:\Users\benzap\AppData\Local\Temp\form-init9134492706436301542.clj:1) |
| 09:46 | benzap | is this a dependency? |
| 09:47 | sandbags | i'm not sure |
| 09:47 | sandbags | it's not clear to me where the clojuredocs function is coming from |
| 09:47 | sandbags | i definitely have it here |
| 09:48 | benzap | that's strange |
| 09:48 | benzap | the second one I tried that gave me trouble |
| 09:48 | sandbags | here's my ~/.lein/profiles.clj => https://gist.github.com/mmower/b531456f82d7f842a9e4 |
| 09:48 | sandbags | possibly it's coming out of there somewhere |
| 09:49 | benzap | mine doesn't have anything in it |
| 09:49 | sandbags | puzzling, i don't see the function in the clojure docs in Dash |
| 09:50 | benzap | other than :java-cmd |
| 09:50 | benzap | and an empty :plugins area |
| 09:50 | benzap | i'll copy yours and see |
| 09:50 | sandbags | i think it might require someone with more clojure experience if that doesn't fix it |
| 09:51 | benzap | maybe the second problem is a configruation issue |
| 09:51 | benzap | i'm trying the uberjar example |
| 09:51 | benzap | it compiles the uber jar |
| 09:51 | benzap | I created the ./my/stuff.clj file and put the necessary stuff inside |
| 09:51 | benzap | called lein uberjar |
| 09:51 | benzap | used their project.clj file |
| 09:52 | benzap | and when I call java -jar my-stuff**....jar |
| 09:52 | benzap | it gives me the error... |
| 09:52 | benzap | oh my |
| 09:52 | benzap | I actually just solved that problem |
| 09:52 | benzap | haha |
| 09:53 | benzap | there's a standalone, and a non-standalone |
| 09:53 | benzap | i was trying the non, which probably didn't have the necessary dependencies :S |
| 09:54 | benzap | i'm going to add your plugins and see if pprint works |
| 10:22 | Morgawr | I wish I knew scheme so I could port this http://yinwang0.wordpress.com/2013/11/04/scheme-benchmarking/ to clojure |
| 10:37 | ro_st | dnolen: been playing with om today, finally. very, very cool! |
| 10:37 | indiana | do you use https://github.com/weavejester/hiccup in production? What do you think about that? |
| 10:38 | ro_st | indiana: we use it in production. works great |
| 10:39 | indiana | for view layer in java application? |
| 10:39 | ro_st | err no |
| 10:39 | ro_st | for a clojure app |
| 10:39 | indiana | i want to use it for view layer in spring mvc application |
| 10:40 | ro_st | gosh. good luck |
| 10:40 | indiana | thanks |
| 10:45 | kzar | Are lighttable plugins explained anywhere yet? |
| 10:50 | indiana | ro_st: what is "gosh" shortcut? |
| 11:06 | pepijndevos | I forgot. What is the idiom for naming an internal function that does the work for the public one? name* or name' or something else? |
| 11:07 | locks | name* according to a podcast I heard the other day |
| 11:07 | Bronsa | pepijndevos: name* |
| 11:08 | hyPiRion | locks: cognicast or some other podcast? |
| 11:08 | pepijndevos | I think Python does _, Haskell does ' so that leaves * for clojure... |
| 11:09 | locks | hyPiRion: ruby rogues, I think |
| 11:09 | locks | can’t remember how exactly it came into the conversation |
| 11:09 | hyPiRion | Hm, I was hoping for a new Clojure podcast =/ |
| 11:10 | locks | sorry to disappoint |
| 11:22 | deadghost | is there a generally recommended beginner clojure book? |
| 11:23 | deadghost | I'm going through http://www.clojurebook.com/ and am only barely following along because I already know some CL and coded some clojure |
| 11:24 | deadghost | something I can recommend to my friends without scaring the bejesus out of them |
| 11:24 | logic_prog_ | is cljx the right layer to insert type checking / linting code ? |
| 11:24 | hansel-han | benzap: braveclojure (website) |
| 11:25 | arkh | deadghost: maybe this? I haven't read it but others have had good things to say about itL http://www.braveclojure.com/ |
| 11:26 | hansel-han | on a similar subject, i've found that clojure is a rewarding language to teach in person |
| 11:26 | deadghost | everything is better in person |
| 11:27 | deadghost | especially when you might need to set up emacs |
| 11:27 | hansel-han | exactly |
| 11:28 | sandbags | deadghost: Clojure in Action was a pretty good starting point for me, after that Joy of Clojure, Programming Clojure, and O'Reilly Clojure Programming were much easier to cope with |
| 11:29 | deadghost | did you actually read all five |
| 11:29 | hansel-han | yeah, joy of clojure is pretty good. |
| 11:29 | xeqi | hyPiRion: what would you want to hear on a new clojure podcast? |
| 11:29 | hyPiRion | xeqi: Clojure stuff in general. Anything Clojure, really. |
| 11:30 | seubert | is clojure in action outdated? |
| 11:30 | xeqi | hyPiRion: have any equivalents from other languages for comparison? |
| 11:30 | hyPiRion | I wouldn't mind Cognicast coming out more often either, but I guess there's a limit on how much they can do. |
| 11:30 | sandbags | not really, although there is a MEAP 2nd edition |
| 11:30 | seubert | ah didn't see that |
| 11:30 | hyPiRion | xeqi: Well, there's Mostly Erlang |
| 11:31 | sandbags | i'm not sure if CiA (or, indeed, any of those books) are strictly beginner books ... i think any of them would require previous experience |
| 11:31 | sandbags | so depends who your target audience is |
| 11:32 | deadghost | sandbags, I'm going through o reilly clojure right now and barely keeping up |
| 11:32 | deadghost | would it be worthwhile to read the other books afterwards |
| 11:32 | sandbags | for me, yes |
| 11:33 | sandbags | i've not finished them all, i tend to dip in as i process new bits and pieces |
| 11:33 | sandbags | I find the O'Reilly book had the steepest learning curve |
| 11:33 | deadghost | I'm trying to set a rule for myself |
| 11:33 | deadghost | for every hour of reading |
| 11:33 | deadghost | at least 2 hours of coding |
| 11:33 | sandbags | i got wrong-footed by the Programming Clojure book, because I expected something like their Programming Ruby |
| 11:33 | sandbags | now i've more experience i am finding it a much better read |
| 11:34 | locks | joy of clojure 2ED got an update yesterday fwiw |
| 11:35 | locks | deadghost: http://videos.lispcast.com/ |
| 11:37 | arkh | people talk about how that light turns on in your head - learning a lisp or functional language for the first time (coming from an imperative and OO background). It was that way for me when I was first learning clojure. It's natural now but a little frustrating at the beginning without a teacher of some kind. |
| 11:37 | sandbags | for my money Erlang was a much easier functional programming language to get wet in |
| 11:38 | deadghost | common lisp: a gentle introduction is one of my favorite books |
| 11:40 | deadghost | I never really bought into OOP so it wasn't a difficult transition |
| 11:40 | deadghost | OOP is just doesn't feel right to me |
| 11:41 | deadghost | and k&r demonstrated that state and side effects can be messy |
| 11:42 | deadghost | biggest hurdle for me was emacs really |
| 11:43 | locks | use light table xP |
| 11:43 | deadghost | does it have vim keybindings |
| 11:43 | locks | yes |
| 11:43 | sandbags | yes |
| 11:43 | locks | and emacs |
| 11:43 | sandbags | it's not vim |
| 11:44 | sandbags | but it has a reasonably useful subset |
| 11:44 | sandbags | and a dash or paredit |
| 11:44 | sandbags | s/or/of/ |
| 11:44 | corecode | yey emacs |
| 11:44 | deadghost | is it worthwhile if I'm already on emacs |
| 11:44 | sandbags | depends how much you like and want to use emacs i guess |
| 11:44 | locks | it has a bunch of neat tricks under its sleeve |
| 11:45 | locks | especially if you do cljs |
| 11:50 | hansel-han | How do you develop a mental concept of datomic in such that you can have a mental model of performance impact for adding another query to a view? |
| 11:52 | arkh | hansel-han: I think of datomic queries as cheap as long as the data is present in memory over what you'd like to query |
| 11:52 | hansel-han | That was a poor question. What happens when you call the same datomic query three times in a row from a peer? |
| 11:52 | arkh | hansel-han: if it fits in memory than it will be an in-memory query, no round trip |
| 11:53 | arkh | (if the data it's querying over fits in memory ...) |
| 11:53 | hansel-han | arkh: thanks. that's pretty much what's happening in MySQL/Postgres too, right? |
| 11:53 | arkh | without round trips to a "database server", your queries can become smaller and more numerous without the downside of round-trip overhead |
| 11:54 | logic_prog | what are the semantics of clojure/spit when a file can not be written (i.e. disk full, invalid file name, file read only) |
| 11:54 | logic_prog | http://clojuredocs.org/clojure_core/clojure.core/spit is surprisingly weak on documentation |
| 11:55 | hansel-han | Actually, I'm wrong about MySQL/Postgres. You still query the DB and tie it up. It just might have your data in memory. |
| 11:55 | arkh | well, outside of round trip issues w/ mysql and postgres, datomic also offers treating query results like traditional data structures you might ordinarily have to create with a traditional db |
| 11:56 | andyf | logic_prog: They are the same as the semantics of the underlying Java calls. That is a methamatician's answer, because it is 100% accurate and completely useless by itself :-) |
| 11:56 | arkh | so you don't necessarliy have to go through the exercise of copying query results into a data structure you can then use in your program |
| 11:56 | logic_prog | andyf, nah, a mthematica would be something like: |
| 11:56 | logic_prog | the semantics of spit are eaxctly the same as the semantics of spit |
| 11:56 | andyf | But seriously, if you really want to know, start with (source spit) and look up Java methods you find |
| 11:58 | arkh | one of the tricky things for me with datomic was how it returns results as a 'set'. Turns out you can finagle fetching results in insert order though |
| 11:59 | andyf | logic_prog: And if you feel super-motivated after that, consider beefing up ClojureDocs at least a little bit, even if it is only links to the relevant Java pages that describe the error cases. |
| 11:59 | hansel-han | arkh: how? right now i sort-by :thing/uid with code every time |
| 11:59 | arkh | the other tricky thing is indexing overhead - with my test data, on a vm (on a laptop) I maxed out at 9000 "rows" per second? I was hoping for more ... |
| 12:00 | logic_prog | andyf: nope, definitely not that motivated |
| 12:00 | logic_prog | andyf: I think you mistaken me for a future-clojure-contributor |
| 12:00 | andyf | logic_prog: CloureDocs is much easier to modify than the process for Clojure contribution. |
| 12:01 | arkh | hansel-han: when you do that, you're taking the set and making a sorted-set over it, which is fine if your query result isn't large. The cost of doing that on a large result set can be prohibitive, though |
| 12:01 | hansel-han | arkh: agreed. i'm just not sure how else to do it |
| 12:03 | cjfrisz | Is marmalade known to corrupt package contents? |
| 12:03 | corecode | i'm having difficulties converting from a mutable to immutable mindset |
| 12:03 | hansel-han | corecode: example? |
| 12:03 | arkh | hansel-han: totally cool if the cost for you isn't too high. I don't think there's a better way to fetch results easily. The other way is to use the lower level stuff like seek-datoms |
| 12:03 | corecode | specifically, i want to implement something that is a bit like a graph, with nodes and edges |
| 12:03 | cjfrisz | I just tried installing troncle, and troncle.el is full of garbage characters when use the package installer or download it straight off the site |
| 12:04 | cjfrisz | Evidence suggests that the version on github _isn't_ full of garbage, though |
| 12:04 | corecode | when you add a new edge, that will change the data of multiple elements |
| 12:04 | corecode | some of which might not even be in lexical scope |
| 12:05 | arkh | hansel-han: there's a chance I was using datomic incorrectly, too - I probably needed to think of creative ways to do more queries over filtered data instead of one big query over the lot of it |
| 12:06 | andyf | corecode: In the immutable mindset, adding a new edge means creating a new graph with that new edge. The old graph is still there without it, too. |
| 12:08 | andyf | corecode: It can be made more efficient than a complete copy by using structural sharing, which you would get if a graph was, say, a map with one key :nodes having a set of nodes, and another key :edges that was a map from nodes to neighboring nodes. A new graph with a new edge is mostly the same as the old one, except for a new set of nodes for one or two nodes in the :edges map. |
| 12:09 | corecode | andyf: sure, but if some code contains a reference to a node, that will diverge |
| 12:09 | hansel-han | arkh: i use d/datoms all the time, but i'm not sure what d/seek-datoms actually does from its docstring |
| 12:10 | andyf | corecode: So you want a graph where some code can hold a reference to a node, and later when that code gets, say, all edges incident to that node, it gets the latest set of edges, not merely the set that existed when it saved that reference? |
| 12:10 | kzar | dnolen: Having a quick look at React + om today and I was curious about something. Would it be possible to have the components built automatically from a HTML template similar to something like AngularJS uses? |
| 12:11 | arkh | hansel-han: I haven't used it before but I think it allows you to iteratively retrieve results in index order instead of unpredictable set order |
| 12:11 | corecode | andyf: i think so, yes |
| 12:12 | kzar | dnolen: Like a complete HTML template with bindings like {{ example }} and have Om create the components and watch a ref or similar with the page's state for changes. |
| 12:12 | corecode | andyf: i'm toying with the idea to implement a DSL |
| 12:12 | andyf | corecode: That is certainly possible to implement in Clojure, but it does sound like a mutable graph, and looking at your original comment, I think I understand it better now :-) |
| 12:13 | corecode | ok |
| 12:14 | andyf | corecode: If you are asking "should I implement my graph as mutable or immutable", then that is a harder question to answer. Not sure I could help you a lot answering it. |
| 12:14 | arkh | hansel-han: see also 'datoms' in the clojure api |
| 12:16 | kzar | dnolen: Then you could just create a HTML template in a style that's common in other frameworks, maintain a ref with the page's state and have Om worry about the binding. It would be super easy to use and it would be more of a drop in replacement. As it is I can't use it for now, I think convincing guys to rewrite HTML templates in Lisp would not go down well. (That said I could be completely missing the point.) |
| 12:17 | edw | seubert: There's a new edition of Clojure In Action in the works. I have the "advanced access" edition. |
| 12:17 | edw | seubert: Strike that. There's a new ed. of Joy of Clojure in the works. Sorry about that. |
| 12:18 | edw | (Both Manning Publications?) |
| 12:24 | michaniskin | kzar: http://hoplon.io may interest you |
| 12:29 | seubert | edw: looks like there are new editions of both! |
| 12:38 | jonathanj | hello! |
| 12:39 | jonathanj | i'm busy working my way through "Clojure for the brave bold and true" exercises |
| 12:39 | jonathanj | i'm wondering if someone can suggest how to format this in a more readable manner: http://hastebin.com/lugoviriko.lisp |
| 12:39 | kzar | jonathanj: FYI usual extension is clj |
| 12:40 | jonathanj | *shrug* hastebin made that up, not me |
| 12:40 | kzar | Could you give an example of using the function? |
| 12:41 | Morgawr | why the "and"? |
| 12:42 | jonathanj | (validate {:name (not nil?)} {:name "Chuck"}) |
| 12:42 | jonathanj | Morgawr: well that's a follow-up question |
| 12:43 | jonathanj | Morgawr: i'd like to and all the results together, ie. all the validators return a truth |
| 12:43 | jonathanj | i thought i could do (apply and (map ...)) but apparently not |
| 12:43 | Morgawr | you can't apply and because and is a macro |
| 12:43 | Morgawr | http://stackoverflow.com/questions/9218044/in-clojure-how-to-apply-and-to-a-list |
| 12:43 | Morgawr | you can use every? |
| 12:44 | jonathanj | where does `every` come from? |
| 12:44 | jonathanj | oh |
| 12:44 | Morgawr | it's 'every?' with the question mark :P |
| 12:45 | jonathanj | hrm, except that the guide hasn't talked about `every?` yet, so i'm wondering what they had in mind |
| 12:46 | noonian | ,(doc every?) |
| 12:46 | clojurebot | "([pred coll]); Returns true if (pred x) is logical true for every x in coll, else false." |
| 12:46 | noonian | ,(every? int? [1 2 3]) |
| 12:46 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: int? in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 12:46 | noonian | ,(every? integer? [1 2 3]) |
| 12:46 | clojurebot | true |
| 12:46 | noonian | ,(every? integer? [1 2 3 4.0]) |
| 12:46 | clojurebot | false |
| 12:47 | andyf | Bronsa: ping |
| 12:47 | jonathanj | so any suggestions on formatting this code more readably then: http://cljbin.com/paste/52d2d492e4b0797b6a30cd3b ? |
| 12:49 | cjfrisz | jonathanj: http://cljbin.com/paste/52d2d4fde4b0797b6a30cd3c |
| 12:49 | cjfrisz | jonathanj: that's the community-accepted formatting |
| 12:49 | andyf | jonathanj: There is room for personal taste here, but in that code I would probably put the (fn ...) args on the same line as (fn, but the body of the function on the next line. Then the same with the record, auto-indented by whatever editor you use that has auto-indenting |
| 12:50 | andyf | jonathanj: What cjfrisz said :) |
| 12:50 | noonian | hmm, why the and? |
| 12:50 | hansel-han | jonathanj: in general, newline a function's arguments. |
| 12:50 | noonian | https://www.refheap.com/22964 |
| 12:50 | cjfrisz | jonathanj andyf: though I respectfully disagree with the community standard formatting quite often :-) |
| 12:50 | hansel-han | noonian: that's what i do |
| 12:51 | Arjunax | How can I easily figure out (at the REPL), whether something is a function or a macro? |
| 12:51 | michaniskin | (map (fn [[k v]] ...) coll) --> (for [[k v] coll] ...) |
| 12:51 | noonian | just evaluate it |
| 12:51 | noonian | ,+ |
| 12:51 | clojurebot | #<core$_PLUS_ clojure.core$_PLUS_@edf7e4> |
| 12:51 | noonian | ,and |
| 12:51 | clojurebot | #<CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and, compiling:(NO_SOURCE_PATH:0:0)> |
| 12:51 | jonathanj | noonian: thanks, i think that's nice |
| 12:52 | noonian | macro's throw an error when evaluated, functions don't because they are first class values |
| 12:52 | Arjunax | ohh okay, cool |
| 12:52 | noonian | jonathanj: thanks :) |
| 12:52 | Arjunax | thanks |
| 12:52 | andyf | Arjunax: also (:macro (meta #'and)) |
| 12:53 | noonian | np |
| 12:53 | Arjunax | :) |
| 12:54 | jonathanj | michaniskin: thanks |
| 12:54 | cjfrisz | jonathanj: If you've got more style questions, here's the style guide https://github.com/bbatsov/clojure-style-guide |
| 12:55 | jonathanj | cjfrisz: thanks |
| 12:57 | cjfrisz | jonathanj: I found it pretty thorough, but I'm not a huge fan of all the suggestions |
| 12:57 | cjfrisz | I.e. cemerick and I both disagree with the "Align vertically function arguments." point |
| 12:58 | jonathanj | cjfrisz: some guidance like "put the body on a different line to the arguments" made a lot of sense |
| 12:58 | noonian | i try to align arguments unless the some are k/v pairs then i put the pair on one line |
| 12:58 | kzar | jonathanj: http://hastebin.com/qapoforimu.lisp << I had a quick go at writing it |
| 12:58 | noonian | some exceptions when things are like doto where the first argument is special |
| 12:59 | hansel-han | i think in most cases, if you don't align fn arguments vertically, then it's jarring because you're putting emphasis on the first argument (like that filter example) |
| 12:59 | cjfrisz | noonian: your way seems to be the majority opinion, but I dislike it as a matter of personal taste |
| 12:59 | michaniskin | the only thing about formatting that is a no-go for me is when indentation isn't right, like when eclipse is misconfigured and produces mixed tabs/spaces |
| 13:00 | cjfrisz | noonian: likely because the scheme mode I was given in college did it a different way :-p |
| 13:00 | noonian | cjfrisz: what do you prefer? |
| 13:00 | kzar | ,(:jonathanj {:jonathanj "Keys can be used like functions to access values."}) |
| 13:00 | clojurebot | "Keys can be used like functions to access values." |
| 13:00 | michaniskin | other than indentation clojure syntax is so simple i don't really care |
| 13:00 | hansel-han | clojure is my first lisp and the indentation of other lisp code that i come across often feels arbitrary. like every programmer just does whatever. |
| 13:01 | cjfrisz | noonian: I prefer always using two spaces indented from the enclosing s-expression for arguments on new lines |
| 13:01 | jonathanj | how can require something like clojure.string from the REPL? |
| 13:01 | noonian | even if there are some args on the same line as the fn> |
| 13:01 | michaniskin | (use 'clojure.string) |
| 13:01 | steerio | (require '[clojure.string :as s]) |
| 13:02 | cjfrisz | noonian: yes |
| 13:02 | noonian | cjfrisz: i do that when put first arg on next line |
| 13:02 | steerio | jonathanj: the difference is that unlike in the (ns) form here you need to quote it |
| 13:02 | jonathanj | thanks |
| 13:02 | jonathanj | steerio: why is that? |
| 13:02 | noonian | but thats actually where i'm most inconsistent, sometimes i only use one space when i'm wrapping some forms in something like first |
| 13:02 | steerio | jonathanj: so you can require the result of an expression, i guess. |
| 13:02 | jonathanj | steerio: i'm still getting to macros, but i don't fully understand why |
| 13:03 | bbloom | cjfrisz: i vertically align arguments when they are *arguments*, but i 2 space indent subforms when they are code blocks |
| 13:04 | steerio | jonathanj: in fact require is a function, so when you call it, parameters get evaluated first |
| 13:04 | cjfrisz | bbloom: I only recently realized that's how almost all lispers do it outside of Indiana University |
| 13:04 | steerio | jonathanj: (require clojure.string) would look for the value of a var called clojure.string |
| 13:05 | bbloom | cjfrisz: the real issue is the threading macros! i feel that is a 2 space indent situation, but every damn indenter everywhere aligns args to -> and ->> |
| 13:05 | bbloom | grr :-P |
| 13:05 | cjfrisz | bbloom: I agree by way of thinking just about everything should be 2 space indent :-) |
| 13:05 | steerio | jonathanj: just like, say, (println clojure.string) would |
| 13:05 | noonian | hmm, i like aligning args with -> |
| 13:06 | hansel-han | not aligning will make code feel like a codeblock to me. imo the first arg to -> isn't that special. |
| 13:06 | bbloom | cjfrisz: the way i like to think of it is that i want to push "goals" to the left margin |
| 13:06 | noonian | its just the first form, only thing special is it doesn't have something threaded in imo |
| 13:06 | cjfrisz | Although I like 'if,' 'and,' and 'or' to be aligned on the first argument |
| 13:07 | bbloom | cjfrisz: lol precisely the opposite of clojure style |
| 13:07 | cjfrisz | bbloom: indeed |
| 13:07 | cjfrisz | Again, I didn't realize I had minority opinion until I started looking at common lisp and racket modes recently |
| 13:08 | steerio | in fact with a language based on S-expressions, we could have it rendered to everyone according to their taste |
| 13:08 | steerio | provided that they can express that taste programmatically |
| 13:08 | steerio | why do we even store it in text? |
| 13:08 | bbloom | steerio: not really. we still have comments which are not in the AST :-) |
| 13:09 | steerio | bbloom: can be solved easily |
| 13:09 | andyf | not everyone's tastes can be expressed programmatically |
| 13:09 | michaniskin | (comment "i am a comment!") |
| 13:09 | bbloom | ";" should be infix for "add metadata to the preceding form" and ";;" to the next form :-) |
| 13:10 | steerio | michaniskin: exactly. if it's namespaced, there shall be no problems. it'd never be actually executed, the compiler would ignore it, editors would render them as s ; Foo |
| 13:10 | michaniskin | it's also an s expr, which is key for formatting with simple tools |
| 13:11 | michaniskin | once you depart from sexprs things get complicated |
| 13:11 | andyf | michaniskin: At least in current Clojure versions, (comment) blocks return nil, so depending upon where you put them they can change the meaning of your program |
| 13:12 | michaniskin | andyf: true, but #_"i am a comment" is problematic because it's not an sexpr |
| 13:13 | steerio | if i was to invent a non-text source code format, i'd add another form for this, which would be truly ignored |
| 13:13 | steerio | whenever the reader encounters it, it'd just ignore it |
| 13:13 | michaniskin | a reader pass that prepreocesses sexprs |
| 13:13 | michaniskin | like |
| 13:13 | steerio | though editors would display ; Foo |
| 13:13 | michaniskin | (#_ "this is a comment") |
| 13:14 | andyf | I wonder why this often-reinvented idea has never taken off? Seems like there would be a reason. Perhaps simply "not enough benefit for the initial switch-over trouble"? |
| 13:15 | michaniskin | why do reader macro forms not use sexpr syntax? i must be missing something |
| 13:15 | bbloom | andyf: because humans type things with keyboards |
| 13:16 | bbloom | it's pretty much that simple :-) |
| 13:16 | michaniskin | like why don't we write (# {1 2 3}) instead of #{1 2 3} |
| 13:16 | michaniskin | this would be way easier to make tooling around |
| 13:16 | bbloom | michaniskin: why don't we write (string \x \y \z) instead of "xyz" ? |
| 13:17 | michaniskin | bbloom: because strings are not really collections |
| 13:17 | bbloom | michaniskin: at some point, you have to have some syntax |
| 13:17 | michaniskin | it's still syntax because the reader would read that as a set, not a seq |
| 13:17 | bbloom | ok fine, why do we write [5 10 15] instead of (read-time-vector 5 10 15] |
| 13:18 | bbloom | michaniskin: go install Mathematica and play with FullForm |
| 13:18 | bbloom | what you want has / can be done |
| 13:18 | michaniskin | i mean why not in clojure? |
| 13:19 | hyPiRion | because it's easier for humans to read. |
| 13:19 | michaniskin | i understand that we want [1 2 3] and not (read-time-vector 1 2 3) |
| 13:19 | bbloom | b/c the syntax & reader was developed adhoc with the goal of being LL(1) instead of maintaining canonical tree form |
| 13:19 | michaniskin | but we have a limited set of punctuation on keyboards |
| 13:20 | Bronsa | andyf: pong |
| 13:20 | michaniskin | so if maps use {} then we need something else, like (# {}) for sets, or #{} |
| 13:20 | michaniskin | what i don't understand is what's the problem with (# {})? |
| 13:20 | michaniskin | an extra set of parens and a space? |
| 13:20 | bbloom | michaniskin: it would have to be primitive |
| 13:20 | bbloom | michaniskin: a macro can't do it |
| 13:21 | michaniskin | the reader would read (# {}) as (clojure.lang.PersistentSet. 1 2 3) |
| 13:21 | michaniskin | or whatever |
| 13:21 | michaniskin | it would read that in as a set |
| 13:21 | bbloom | michaniskin: that doesn't work b/c (some-macro (# 1 2 3)) would get a list instead of a set |
| 13:21 | michaniskin | as it should |
| 13:21 | andyf | Bronsa: Just noticing some Eastwood behavior I hadn't investigated fully before, and see if you knew the issue. When a source file has (set! *warn-on-reflection* true), I often see reflection warnings from Eastwood when it evals forms that macro-expand to things containing (.nth ...), like a doseq macro. 'lein check' gives no reflection warnings, though. |
| 13:22 | michaniskin | (# {1 2 3}) would be a set |
| 13:22 | andyf | Bronsa: I'm trying to figure out the difference in what gets eval'd in each case, but perhaps you already know. |
| 13:22 | bbloom | michaniskin: you're missing what i'm saying, maybe i'm not explaining clearly |
| 13:22 | hyPiRion | michaniskin: what's wrong with the current way of writing sets, though? |
| 13:22 | bbloom | michaniskin: it's a phasing issue |
| 13:22 | michaniskin | just like when you pass #{1 2 3} to a macro, you don't get a symbol # followed by a misformed map |
| 13:23 | michaniskin | bbloom: because source code isn't a tree |
| 13:23 | michaniskin | bbloom: that makes editor tooling complicated |
| 13:23 | michaniskin | bbloom: you now need to invent "false trees" |
| 13:23 | bbloom | michaniskin: no no, it's just that the reader combines two phases |
| 13:23 | bbloom | there is no "false trees" |
| 13:23 | bbloom | the syntax is already a tree, but we skip a step w/ the reader |
| 13:23 | michaniskin | bbloom: how do you edit #{1 2 3} structurally? |
| 13:24 | Bronsa | andyf: might be emit-form forgetting to attach some :tag metadata, I'll look into that |
| 13:24 | michaniskin | say you want to make that into a map |
| 13:24 | andyf | Bronsa: Want a ticket with a short example? |
| 13:24 | bbloom | michaniskin: you can easily imagine a new namespace called clojure.syntax |
| 13:24 | michaniskin | bbloom: the editor needs to treat #{1 2 3} as (# [1 2 3]), basically |
| 13:24 | bbloom | michaniskin: and you can write a parser that produces a tree of lists where things like #{1 2 3} get translated to (clojure.syntax/set 1 2 3) |
| 13:24 | bbloom | michaniskin: but then you need to do something the reader does: convert syntax to data types |
| 13:25 | bbloom | michaniskin: that has to happen BEFORE macros |
| 13:25 | michaniskin | bbloom: of course, but now we're reverse engineering the clojure reader, which isn't formally specified |
| 13:25 | bbloom | michaniskin: (mac #{}) will call the function backing mac with a set, not with a list |
| 13:25 | hyPiRion | michaniskin: who says the editor does? That sounds a bit strange |
| 13:25 | Bronsa | andyf: sure, thanks |
| 13:25 | bbloom | michaniskin: ignore the editor, ignore the clojure implementation of the reader |
| 13:25 | bbloom | michaniskin: a reader in general combines two phases: parsing and evaluation of syntax forms |
| 13:26 | bbloom | michaniskin: you can write a function that walks [:some [:tree] [:like :this] [:set 1 2 3]] and turns :set nodes in to PersistentHashSet objects |
| 13:26 | bbloom | michaniskin: the clojure reader is simply doing that during parsing b/c the compiler has no need for the unresolved tree |
| 13:27 | michaniskin | bbloom: you're missing my point |
| 13:27 | michaniskin | bbloom: suppose foo is a macro, right? somewhere you call (foo #{1 2}). what does foo see? a set. why? because the reader read the #{1 2 3} form at the call site |
| 13:28 | bbloom | michaniskin: the macro sees a set b/c that's what a macro is defined to do |
| 13:28 | bbloom | michaniskin: i can invent a new type of "macro" that sees pre-reader-evaluation forms |
| 13:28 | michaniskin | bbloom: same thing with this: (foo (# [1 2 3])). the reader would read (# [1 2 3]) at the call site |
| 13:28 | michaniskin | and foo would see a set |
| 13:29 | andyf | Bronsa: Woah. It isn't even deterministic. I get about 50% of the time in a short example. WIll mention in the ticket. |
| 13:30 | gtrak | is there a built in way to get cider to send nrepl a 'complete' message? |
| 13:30 | bbloom | michaniskin: if it helps to think in terms of types, you've got an AST tree type and an Any type. A "parser" returns AST. A reader returns "Any". Macros are functions of Any -> Any. You could create "syntax macros" that operate on AST -> AST |
| 13:30 | bbloom | michaniskin: eval operates on Any, not on AST |
| 13:31 | michaniskin | bbloom: you could do any number of things. my question was what's wrong with (# [1 2 3]) syntax instead of #{1 2 3}, operationally? i don't buy the argument that one set of parens is a burden |
| 13:32 | coventry | Have most people switched over to cider.el at this point? |
| 13:32 | bbloom | michaniskin: lol oh, that's you're argument? you're actually arguing that you'd rather less syntax? |
| 13:32 | bbloom | michaniskin: syntax, it turns out, is useful to humans :-P |
| 13:32 | michaniskin | bbloom: i would prefer (# [1 2 3]), because my editor could then show me #{1 2 3} if that's what i like |
| 13:32 | michaniskin | bbloom: but the editor itself could be far, far simpler |
| 13:33 | michaniskin | especially since the clojure reader is not formally specified anywhere as far as i know |
| 13:33 | noonian | but then if our editor doesn't have that support we are soul |
| 13:33 | michaniskin | noonian: but your editor would, because it wouldn't be black magic |
| 13:33 | noonian | out of luck |
| 13:34 | michaniskin | displaying quirky syntax is a job for an editor, not a reader, imho |
| 13:34 | bbloom | michaniskin: you're still conflating parsing and reading; syntax and semantics |
| 13:35 | michaniskin | bbloom: lol ok man |
| 13:35 | bbloom | michaniskin: i don't see how having a more uniform grammar would help your editor in any interesting way if your editor is already operating at the AST level |
| 13:35 | hyPiRion | michaniskin: then I don't get why you don't have issues with [] and {}. With only one set of delimiters to consider, an editor will be vastly more simple. |
| 13:37 | michaniskin | hyPiRion: because [] and {} can be edited the same way as (), basically |
| 13:37 | hyPiRion | michaniskin: so can #{}, unless you've hardcoded that delimiters must be 1 char for start and stop |
| 13:38 | michaniskin | hyPiRion: it's not that simple |
| 13:38 | michaniskin | hyPiRion: consider #{1 |2 3} |
| 13:38 | michaniskin | where the point is at the | |
| 13:38 | Bronsa | andyf: ... guess what. I got bitten again by clojure silently ignoring :tag |
| 13:38 | michaniskin | i want to delete the 2 and convert the set into a map. how to do? |
| 13:39 | michaniskin | hyPiRion: clearly, that set would need to be structured as (# [1 2 3]) |
| 13:39 | hyPiRion | michaniskin: clearly? I don't see any argument for why that is. |
| 13:39 | andyf | Bronsa: Pardon me for a moment while I continue to be stunned at the speed at which you find such things :-) |
| 13:39 | clojurebot | Huh? |
| 13:40 | noonian | wont #{1 2 3} get re-written as (set 1 2 3) or something by the reader? |
| 13:40 | michaniskin | bbloom: the AST is not that you print to the source file, btw. you print things that can be read by the reader |
| 13:40 | michaniskin | bbloom: once you have the AST you've lost reader macro info |
| 13:40 | Bronsa | andyf: http://sprunge.us/aEIV?diff this should do it. Let me double-check for a minute and then I'll push the fix |
| 13:40 | hyPiRion | michaniskin: #{1 2 3} can just be modified in the same way as a list, vector and map can be. |
| 13:41 | bbloom | michaniskin: (def reader (comp eval-reader-literals parse)) |
| 13:41 | michaniskin | hyPiRion: how do you delete the # there? |
| 13:41 | hyPiRion | michaniskin: same way as you replace a {, [ or (, by removing it |
| 13:41 | bbloom | michaniskin: no, that's not true. that's only true of clojure's current reader b/c clojure's compiler doesn't need that info & so they combined the parser & parse-time evaluator |
| 13:41 | andyf | Bronsa: Would the place you've found this explain the nondeterminism of results, too? |
| 13:42 | Bronsa | no idea about that |
| 13:42 | michaniskin | bbloom: your argument is similar to the argument that scala macros are as awesome as clojure macros |
| 13:43 | bbloom | michaniskin: scala's macros are fundamentally different from clojure's macros |
| 13:43 | bbloom | michaniskin: scala macros operate on the AST, clojure's macros operate on Any |
| 13:43 | michaniskin | bbloom: you can have a hyper-complex AST representation, yes, but it isn't better than having sexps |
| 13:43 | andyf | Bronsa: OK, in my debugging I have pprint'ed every form given to clojure.core/eval in Eastwood's analyze-file, with metadata included, and I have two runs where one gives the warning, and the other does not, but the pprint'ed forms are identical. |
| 13:44 | bbloom | michaniskin: you've having two arguments at once: 1) editing at the text level is hard regex fu and 2) something about sexps all the way down |
| 13:44 | Bronsa | andyf: oh, that's it then. |
| 13:44 | Bronsa | sometimes the type hint is a Symbol, sometimes it's a Class |
| 13:44 | Bronsa | when it's a Class, the Compiler ignores the hint |
| 13:45 | bbloom | michaniskin: i'm saying 1) regex fu works just fine for me in vim land, but you can operate at the AST level if you want to make that easy & in that case, the syntax doesn't matter 2) you can have sexps all the way down if you just separate parsing from evaluating. see Mathematica |
| 13:45 | andyf | But why would it sometimes be a Symbol, and sometimes a Class, when I'm analyzing the same source file? |
| 13:45 | michaniskin | bbloom: so specifically why is #{1 2 3} better than (# [1 2 3])? |
| 13:45 | bbloom | michaniskin: because humans like syntax |
| 13:45 | michaniskin | bbloom: so the parens |
| 13:45 | michaniskin | that's all i was looking for |
| 13:45 | Bronsa | andyf: oh. in the same form? weird. |
| 13:45 | steerio | and you'd mix reader macros with macro calls |
| 13:46 | steerio | the two are different animals |
| 13:46 | michaniskin | steerio: no, you can't name a macro # |
| 13:46 | steerio | i mean if your idea was implemented, which implies that you can |
| 13:46 | michaniskin | steerio: the two methods are equivalent, i think, operationally |
| 13:46 | andyf | Bronsa: Yeah, I made the one-file project described in the latest TANAL ticket, ran Eastwood multiple times with the extra pprint'ing just before eval, and gotten identical results on 2 runs except for the Reflection warning in one, none in the other. |
| 13:46 | michaniskin | it's just a matter of taste, apparently |
| 13:46 | Bronsa | :/ |
| 13:46 | steerio | michaniskin: well no, because your example is a nonexistent form |
| 13:46 | andyf | The pprint'ing doesn't show whether it is a symbol or a class, so your explanation could still be correct. |
| 13:47 | bbloom | michaniskin: yes, the parens... but that's why i lead by saying something like (clojure.syntax/string \x \y \z), hell even then (clojure.syntax/string (clojure.syntax\char ..... |
| 13:47 | steerio | ,(# [1 2 3]) |
| 13:47 | clojurebot | #<RuntimeException java.lang.RuntimeException: Reader tag must be a symbol> |
| 13:47 | andyf | or maybe the pprint'ing would distinguish between Symbol and Class? |
| 13:47 | Bronsa | andyf: I'm positive that the bug is caused by that, still no idea why it doesn't happen every time |
| 13:47 | michaniskin | steerio: i meant if the reader read that as a set |
| 13:47 | steerio | gtg |
| 13:47 | Bronsa | no, symbols and classes prints the same unfortunately |
| 13:47 | michaniskin | steerio: it would require a different reader |
| 13:47 | steerio | though i'd love to continue this |
| 13:47 | steerio | maybe sometime |
| 13:48 | andyf | Bronsa: The pprint'ed form I see contains this sub-form that causes the reflection warning: (.nth ^clojure.lang.IChunk chunk_4449 o_4451) |
| 13:48 | Bronsa | andyf: can you try and see if it's still non-deterministic if you move the doseq out of the defn? |
| 13:48 | andyf | sure |
| 13:51 | jonathanj | steerio: ah, good point |
| 13:52 | andyf | Bronsa: yes it is still nondeterministic with a doseq at the top level of the source file, not inside a defn |
| 13:53 | Bronsa | no idea. I'll investigate a bit |
| 13:56 | Bronsa | andyf: I pushed the fix and updated eastwood to use the new SNAPSHOT |
| 13:57 | Bronsa | andyf: just another theory, can you ensure *warn-on-reflection* is actually true both times? |
| 14:04 | andyf | Bronsa: Need to go for a while. Will look into it more later today. |
| 14:05 | Bronsa | ok, thanks |
| 14:58 | pepijndevos | waaaaiiit... > < >= <= only work on numbers? What about other comparables? |
| 15:00 | pjstadig | pepijndevos: surprise! |
| 15:03 | bbloom | ,(< [5] [10]) |
| 15:03 | clojurebot | #<ClassCastException java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number> |
| 15:03 | bbloom | huh. |
| 15:04 | bbloom | ,(compare [5] [10]) |
| 15:04 | clojurebot | -1 |
| 15:04 | bbloom | ,(compare [10] [5]) |
| 15:04 | clojurebot | 1 |
| 15:04 | bbloom | pepijndevos: pjstadig: i did not realize :-P |
| 15:05 | hyPiRion | ,(= [[10] [5]] (sort [[10] [5]])) |
| 15:05 | clojurebot | false |
| 15:05 | hyPiRion | ,(= [[5] [10]] (sort [[5] [10]])) |
| 15:05 | clojurebot | true |
| 15:05 | pepijndevos | now have a look at subseq, and be amazed. |
| 15:05 | bbloom | ,(doc subseq) |
| 15:05 | clojurebot | "([sc test key] [sc start-test start-key end-test end-key]); sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for which (test (.. sc comparator (compare ek key)) 0) is true" |
| 15:06 | pepijndevos | &(subseq (sorted-set \a \b \c \d \d) > /b) |
| 15:06 | lazybot | java.lang.RuntimeException: Invalid token: /b |
| 15:06 | pepijndevos | &(subseq (sorted-set \a \b \c \d \d) > \b) |
| 15:06 | lazybot | ⇒ (\c \d) |
| 15:17 | bbloom | has anybody tried a breadth-first traversal with clojure.zip ? |
| 15:17 | bbloom | seems quite tricky... |
| 15:23 | pjstadig | hmm yeah |
| 15:23 | pjstadig | just DFS for me |
| 15:39 | kristof | Are takes from async channels guaranteed atomic? |
| 15:39 | kristof | Meaning two processes can't take from the channel and end up with the same item |
| 15:40 | kristof | Or is taking and putting ALSO an asynchronous process and the channel itself decides which consumer gets what item? :) |
| 15:40 | kristof | I'm sorry if there's some fundamental misunderstanding I'm showing, here |
| 15:44 | arkh | kristof: it looks like those operations are made atomic through explicit locks, e.g. https://github.com/clojure/core.async/blob/master/src/main/clojure/clojure/core/async/impl/channels.clj |
| 15:44 | arkh | kristof: a given item could only be take!'n once |
| 15:44 | kristof | arkh: I thought you were going to link to Rich Hickey's buffer code because I thought that would be where the logic lies but I suppose not |
| 15:45 | kristof | arkh: Do you think there would be a performance benefit to making channels themselves be asynchronous as well, letting the channel be |
| 15:45 | kristof | well I guess I'm thinking of actors |
| 15:45 | kristof | the channel could be an agent that sends the next item to the process (whose name is known to the agent already) and so no explicit locking is necessary at all |
| 15:46 | kristof | But then the channel itself would not be so lightweight, would it? Hrm. Oh well :) |
| 15:46 | arkh | kristof: but then how are agents already coded? : ) I think it acquires a lock, too |
| 15:47 | kristof | arkh: Do they? Nothing actually accesses an agent's state besides the agent itself, I thought, so locking would be keeping nothing out. |
| 15:47 | kristof | But I am probably wrong in this regard |
| 15:48 | arkh | kristof: as far as whether it'd be more efficient to put that into an async process (like a go block, etc.) I think that takes me out of my depth - I'd just be speculating |
| 15:49 | kristof | arkh: Huh? Go blocks use channels, so implementing channels in terms of go blocks doesn't make much sense. :) Anyway, I'm out of my depth, too, I was just wondering about the implementation of channels |
| 15:50 | bbloom | pjstadig: give breadth first a try, turns out it's actually hard :-P |
| 15:50 | arkh | kristof: I could be wrong but I believe concurrent operations on agents are aligned single-file through through speculative lock, simliar to atoms, i.e. attempt exclusive access to a given thing and then verify nothing else tried to do the same. The difference between and atom and an agent is what happens in the code after the lock is verified to be ok |
| 15:50 | bbloom | pjstadig: http://www.eecs.usma.edu/webs/people/okasaki/icfp00.ps <- general functional breadth-first numbering. not w/ a zipper |
| 15:51 | kristof | So I guess all real concurrency involving shared state relies on locks at least on some level of abstraction? |
| 15:51 | bbloom | pjstadig: very trick |
| 15:51 | bbloom | y |
| 15:51 | arkh | kristof: sorry, I meant like a go block in style but not in code |
| 15:51 | bbloom | pjstadig: whoops, bad url |
| 15:51 | bbloom | http://www.cs.tufts.edu/~nr/cs257/archive/chris-okasaki/breadth-first.pdf there |
| 15:52 | arkh | kristof: I though clojure mvcc mostly revolved around speculative locks w/ retries |
| 15:52 | arkh | kristof: even agents - it's just the meat of your code doesn't run until things are verified |
| 15:53 | kristof | brb while I learn what a speculative lock is |
| 15:59 | arkh | kristof: I should have said "stm" instead of "mvcc" back there |
| 16:00 | kristof | arkh: I'm sorry, I thought those were synonymous. |
| 16:02 | arkh | kristof: in a general sense, a speculative lock is one where code attempts to make a change to something (presumbaly shared and) mutable and it checks to make sure nothing else changed it at the same time. If not, the change (or transaction) is committed, if something else modified it concurrently, then the operation or transaction is retried until it |
| 16:02 | arkh | succeeds. Technically clojure won't retry forever and will error out if there happens to be too much contention. I've never seen that though - I doubt it's common! |
| 16:04 | kristof | So a speculative lock tries, checks, then commits or retries. |
| 16:04 | arkh | kristof: oh .. it looks like STM is the problem category and MVCC is how clojure solves it |
| 16:04 | kristof | And STM is just large-scale manipulation of speculative locks. |
| 16:06 | arkh | mvcc seems to be about speculative locks and keeping old values of ref types around until such time as nothing refers to the value and it'll be gc'ed |
| 16:06 | fredyr | kristof: arkh: I've found this page very helpful in understanding more about the clojure stm, http://java.ociweb.com/mark/stm/article.html |
| 16:07 | arkh | fredyr: nice! |
| 16:08 | fredyr | you might like this one too: https://github.com/tvcutsem/stm-in-clojure |
| 16:09 | kristof | arkh: According to the link fredyr just sent, there's nothing inherently about actors that needs to include locks in the implementation, which is what I suspected. I will look up the implementation of agents in Clojure, though, and find out. |
| 16:10 | mercwithamouth | does anyone have any good enfocus projects besides chatter-box on github? |
| 16:15 | arkh | kristof: is there any way to do safe concurrency without some kind of lock/mutex/etc. or forcing changes to be single-threaded? |
| 16:16 | arkh | kristof: it looks like agents are ultimately managed by this: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/LockingTransaction.java |
| 16:16 | kristof | arkh: Concurrency is only unsafe when there's shared state between threads. An actor, as far as I can tell, always operates within a single thread, so there's never any unsafeness. |
| 16:17 | arkh | kristof: isn't that parallelism instead of concurrency though? : ) |
| 16:18 | kristof | arkh: Maybe, if you want to look at it that way. But then that's the reason why actors are so cool: because you're not ever forced to deal with shared state. |
| 16:18 | kristof | Then again, isn't an actor's mailbox shared state? ............... |
| 16:19 | arkh | maybe the mailbox is managed by a single event/dispatch thread .... I know zero about actors! |
| 16:19 | kristof | I'm not smart enough for this :( |
| 16:20 | arkh | I'm having fun trying to stretch what little I know! |
| 16:22 | kristof | arkh: The agent.java code in the tree never imports locking transaction. How did you come to that conclusion? |
| 16:23 | dgrnbrg | How can I express core async in one pithy sentence to an audience that learned about the epochal model of time 1 slide before? (for http://flausenhaus.org/lambda/ ) |
| 16:24 | egghead | in all my use of clj i've never needed agents |
| 16:24 | dgrnbrg | "Communicate by sending messages over channels" is what i'm thinking, but I feel like that doesn't capture the awesomeness of alt! |
| 16:25 | kristof | egghead: Timothy Baldridge said last night (or the night before) that he's never really used STM in a way that it didn't get replaced by core.async code or agents when he refactored. To each their own, but some people like transactions! |
| 16:25 | kristof | dgrnbrg: Epochal model of time doesn't really have much to do with understanding core.async in my opinion. The best way to put it would be to use the consumer/producer analogy. |
| 16:26 | arkh | kristof: taking an agent operation like 'send', for example, ends up calling .dispatch on clojure.lang.Agent. dispatch calls dispatchAction which, at the beginning of its operation, calls LockingTransaction.getRunning() |
| 16:26 | egghead | consumer producer / pubsub doesn't do justice to core.async :p |
| 16:26 | dgrnbrg | kristof: I know that the epochal model of time doesn't have much to do with core.async, which is why I'm not sure how to express it |
| 16:27 | dgrnbrg | we don't really have time to go over core.async in the class, but I'd like to be like "yo, this is a powerful, cool model, and here's a 30 second teaser" |
| 16:28 | locks | I liked how in dnolen’s presentation |
| 16:28 | egghead | reading and writing to channels kind of captures what it is to be async, time independent, but you get to write it as if it were sync :) |
| 16:29 | kristof | dgrnbrg: There are really two cool parts to core.async in my opinion. The first is the ability to take two processes and let them run at the same time and talk to each other. The second cool thing is the go macro, which takes benign sequential looking code and smashes it all together into a state machine. |
| 16:29 | locks | he went from not accepting repeated sequential keys to not accepting repeated keys ever |
| 16:30 | dgrnbrg | kristof: I feel like those aren't compelling features of core.async, since you can do that with threads and java.util.concurrent |
| 16:31 | dgrnbrg | alts! and user-space threading are the novel parts of core.async, but they're not so easy to explain unless you've written code without them |
| 16:31 | kristof | dgrnbrg: not the state machine stuff? |
| 16:31 | dgrnbrg | the state machine stuff only exists so that the user-space scheduler can exist |
| 16:31 | kristof | That's what I was talking about |
| 16:31 | dgrnbrg | since you can accomplish the same thing with threads + blocking calls, and that scales to thousands of processes |
| 16:32 | dgrnbrg | "processes", aka threads |
| 16:32 | kristof | hmmm |
| 16:32 | egghead | alts! is really cool because it is explicit non-determinism |
| 16:34 | egghead | but >! is not the same sort of thing as regular communication between threads or agents |
| 16:34 | egghead | it's got transactional semantics |
| 16:35 | afhammad | what does it mean when a function is prefixed with ->, for example something/->dothis |
| 16:35 | arkh | I like this project's extension of core.async: https://github.com/tonsky/net.async |
| 16:36 | AimHere | afhammad, -> and ->> are just macros for making code more readable in some cases |
| 16:36 | dgrnbrg | egghead: you can get that using java.util.concurrent.LinkedBlockingQueue, if you want the blocking channel semantics |
| 16:36 | dgrnbrg | egghead: and you can get a more powerful version of an unbuffered channel using an exchanger: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html |
| 16:36 | AimHere | afhammad, the idea is that instead of (foo (bar (baz (wibble x))))), you write (-> x (wibble) (baz) (bar) (foo)) |
| 16:37 | AimHere | Or something to that effect |
| 16:37 | egghead | dgrnbrg: ah yes, but now you have blocked threads ;) |
| 16:37 | afhammad | AimHere: is that always the case? what about: services/->Services |
| 16:37 | egghead | *not* the same as how core.async puts threads to sleep inside their state machines |
| 16:37 | dgrnbrg | egghead: threads are quite scalable--a 24 core machine can easily handle thousands of threads |
| 16:38 | egghead | 'parking' or w/e |
| 16:38 | dgrnbrg | the OS is quite effective at parking native threads |
| 16:38 | AimHere | afhammad, ->Services is a different symbol from -> and so I don't know what that's all about, probably defined in the project somewhere else |
| 16:39 | dnolen | dgrnbrg: I think the fact that core.async was designed w/ ClojureScript in mind from the start is pretty compelling. |
| 16:39 | dnolen | dgrnbrg: but maybe your audience is mostly concerned with server-side affairs |
| 16:39 | dgrnbrg | they're a mix |
| 16:40 | dgrnbrg | that is a good point, however--I'm going to mention the JS support, because that is pretty awesome |
| 16:40 | egghead | i think core.async is a nice async lib, but I think it is a better example of why macros are so cool |
| 16:41 | egghead | macros let clojure borrow all the good ideas from other langs :) |
| 16:43 | edw | egghead: <http://poseur.com/java-scheme>. |
| 16:44 | egghead | edw: :) |
| 16:44 | edw | Some hairy macroage in there. |
| 16:45 | edw | Writing macros is the only intellectual activity where I feel actual, literal nausea when things get real. |
| 16:46 | edw | Staring into the abyss so others needn't. |
| 16:51 | edw | Speaking of... May need a macro to introduce arbitrary search depth for a cascalog graph app. Hand-writing n-level transitivity is ugly and tedious. |
| 18:39 | gtrak | 80% of the way to a cljs autocomplete lib, analogous to clojure.complete :-) |
| 18:40 | gtrak | I'm hoping someone will help me with the emacs part. |
| 18:41 | bitemyapp | egghead: macros aren't the only way :) |
| 18:42 | gtrak | the interaction between nrepl, austin, piggieback, ac-nrepl and clojure-mode is.. a bit hairy. |
| 18:43 | gtrak | like.. I think I'll have to disable ac-nrepl, since it actually evals code instead of just sending over a "complete" op. |
| 18:44 | bitemyapp | ac-nrepl lags too much for me to use. |
| 18:44 | gtrak | all this effort because I was trying to build something with om and got fed up with looking at github :-) |
| 18:45 | gtrak | bitemyapp: do you have autocomplete through ritz or something else? |
| 18:45 | gtrak | I noticed that's one thing that actually uses a 'complete' nrepl op |
| 18:45 | gtrak | and I'm modeling the ensuing piggieback integration after that. |
| 18:45 | bitemyapp | gtrak: I use the dumb Emacs AC. It's annoying. |
| 18:46 | bitemyapp | gtrak: uh, in Clojure anyway. I have smarter tooling elsewhere. |
| 18:46 | gtrak | blah blah blah haskell |
| 18:46 | bitemyapp | I didn't say it. |
| 18:46 | gtrak | not today :-) |
| 18:46 | bitemyapp | all you bro./ |
| 18:46 | clojurebot | I don't understand. |
| 18:46 | bitemyapp | oh shush up bot. |
| 18:47 | gtrak | not having autocomplete wasn't a problem before, since I wasn't learning a bunch of new libraries. |
| 18:48 | gtrak | or writing my own for everything. |
| 18:48 | gtrak | rather, I _was_ writing my own. Hopefully once this infra is in place, it won't be too hard to get M-. going. |
| 18:49 | bitemyapp | gtrak: you know what helps even more for reading code you didn't write? |
| 18:49 | bitemyapp | gtrak: I give ya two guesses. |
| 18:49 | gtrak | printing it? |
| 18:49 | amalloy | eyeglasses |
| 18:49 | bitemyapp | gtrak: types. |
| 18:50 | gtrak | hahaha |
| 18:50 | bitemyapp | amalloy: only if you want >80 columns. |
| 18:50 | gtrak | I use reading glasses occasionally, different focus lengths helps with eyestrain over the course of a week. |
| 18:50 | bitemyapp | gtrak: but 4rlz though. Made up that type signature of the fly: http://www.haskell.org/hoogle/?hoogle=Ord+a+%3D%3E+%5Ba%5D+-%3E+a |
| 18:51 | gtrak | ah, that is pretty cool actually, but that means I have to use haskell. |
| 18:52 | bitemyapp | that would appear to be the tradeoff. |
| 18:52 | gtrak | still, I end up reading all the code of every lib I use, anyway, tooling just helps me jump around quickly. |
| 18:52 | bitemyapp | gtrak: oh sure, but the types still help: http://hackage.haskell.org/package/base-4.6.0.1/docs/src/Data-List.html#maximum |
| 18:52 | bitemyapp | gtrak: :browse in ghci dumps the types and fn names of the module you passed. |
| 18:53 | bitemyapp | gtrak: so it's pretty easy to get a 1,000 km overview that way and then start diving into the code. |
| 18:53 | gtrak | one day :-) |
| 18:53 | gtrak | it's been on my list for about 3 years, never the top item.. |
| 18:53 | bitemyapp | gtrak: well, if you ever want a jump-start, advice, ideas, etc. - ping me. |
| 18:54 | bitemyapp | gtrak: it's a learning process very amenable to hammock time. |
| 18:54 | gtrak | yea, that's a good feeling. |
| 18:56 | gtrak | for now I'm just trying to hack stuff out as fast as possible in clj/cljs. |
| 18:56 | gtrak | because of the 'reach' aspect. |
| 18:58 | bitemyapp | gtrak: I gotcha. Reach? |
| 19:00 | gtrak | yea.. baltimore's mobile/web/rails folks mostly, with some java for govt contractors, we just started a real clojure meetup, which is still pretty esoteric, but it's getting better. With cljs, I can hopefully show up at hackathons and impress :-). |
| 19:01 | bitemyapp | gtrak: I've been doing a mixture of tool building, benchmarking, dev-ops automation, and web stuff in Haskell with Fay on the frontend for JS. |
| 19:01 | gdev | well I've been meaning to reduce my Haskell naivete |
| 19:01 | bitemyapp | wish the day job leveraged more of it, but my current project at work is hyper Python-specific. |
| 19:01 | gtrak | that sounds fun, you're in the west coast, yea? |
| 19:01 | bitemyapp | gtrak: Yay Area, I live in SF. |
| 19:01 | bitemyapp | gtrak: trying to get the fack out of here. |
| 19:01 | gtrak | yea... the tech scene here is really indy. |
| 19:01 | gtrak | in comparison. |
| 19:01 | bitemyapp | indie? |
| 19:01 | gtrak | yea, I guess :-) |
| 19:02 | gtrak | I never try to spell that. |
| 19:02 | bitemyapp | I'm just unclear on what it's meant to mean. |
| 19:02 | gtrak | little, mostly low-profile startups |
| 19:02 | gdev | bitemyapp, have you used Haskell with Datomic? |
| 19:03 | gtrak | but it's a close-knit group. |
| 19:03 | edw | Philly is like that: a lot of small companies that call themselves start-ups but are actually just basically mom-and-pop internet companies run by twenty/thirty-something hipsters. |
| 19:04 | gtrak | edw: it's probably not so different, I'd guess philly was bigger. |
| 19:04 | bitemyapp | gdev: I'm all-up-ons with Datomic at work but I haven't had time to poke around with hEdn in Haskell yet. |
| 19:04 | bitemyapp | gdev: my Haskell projects are mostly PGSQL at the moment because esqueleto is RIDIC. |
| 19:04 | gtrak | baltimore has the DC influence, a lot of folks commute there and back. |
| 19:04 | bitemyapp | gdev: regardless, it'd mean going over a proxy like berossus to talk to Datomic. |
| 19:04 | gtrak | so, clojure realistically will interest someone here, haskell I'd be on my own, I'm afraid. |
| 19:06 | gdev | bitemyapp oh, damn, I was hoping to find something that Clojure-the-language would let you do that Haskell-the-language couldn't ;) |
| 19:06 | edw | gtrak: Philly may be similar in that the 212-215 and 202-215 thing is practical. And the 215 has banks and pharmas. So there's the bimodal distribution of companies split betweem the aforementioned and people sucking corporate cock. |
| 19:06 | gtrak | b/c the higher-skilled ruby folks are starting to be more open-minded, and I see hadoop and big-data influencing things, which implies JVM. |
| 19:06 | bitemyapp | gtrak: learn it for the epiphany, same reason people learned Lisp for the last couple decades. Offer still stands for my time. |
| 19:06 | gtrak | bitemyapp: I hope to take you up on it sometime. |
| 19:06 | bitemyapp | Makes sense re: Hadoop, but I strongly suspect you could still put something together. |
| 19:07 | bitemyapp | gdev: nice try! Haskell has best-in-the-industry parser libraries. Something like edn wasn't going to stop anybody. |
| 19:07 | locks | parsec is kinda good |
| 19:07 | bitemyapp | attoparsec too. |
| 19:09 | kanja | is there a way with cider to see a specific line of code where an error occurred? |
| 19:09 | gtrak | kanja: stacktraces have file-and-line info generally |
| 19:09 | kanja | Something like "ArityException Wrong number of args (0) passed to: PersistentVector clojure.lang.AFn.throwArity (AFn.java:437)" is informative, but it would be great if I could jump right to the fn call that caused the error |
| 19:10 | edw | kanja: And if they don't, it may be because you "C-x X-e"'d and didn't "C-c C-k". |
| 19:10 | gdev | bitemyapp, ha, that was my first and last attempt too, life is too short for PLT trolling |
| 19:10 | amalloy | kanja: (1) the full stacktrace already contains that information, if you'd pasted it to refheap or something; (2) you have code that looks like (x) when you just want x |
| 19:10 | gtrak | it's not easy to jump into java, eclipse has a roundabout way of implementing it, though, involving downloading the source artifacts from maven. |
| 19:11 | bitemyapp | gdev: http://www.youtube.com/watch?v=asgiNZrcJ44 |
| 19:11 | kanja | @edw - yeah that I did do. |
| 19:12 | bitemyapp | gdev: watch with audio. |
| 19:12 | gdev | bitemyapp, yeah that's how I feel lol |
| 19:12 | kanja | but I'm also getting the error at run time rather than load |
| 19:12 | kanja | so c-c c-k works, but then (myfun someargument) in cider fails |
| 19:13 | gdev | bitemyapp, if I'm ever in your area or if you're ever in San Antonio I'll totally pair with you on some Haskell hacking |
| 19:14 | bitemyapp | gdev: Sure! I'm more likely to be in Austin or Seattle when I'm not in SF in the near future though. I've paired with others over the internet successfully though. |
| 19:15 | bitemyapp | gdev: learning how to pair remotely is a useful skill regardless. |
| 19:15 | bitemyapp | paired with others over the internet for Haskell and for day-job stuff both. |
| 19:16 | gdev | bitemyapp that's true, well just name the time and the project and add me to skype ha |
| 19:16 | gdev | or I'll add you because I bet I can guess your skype name |
| 19:17 | bitemyapp | gdev: I've got a *list*. I'm working on rewriting bitemyapp.com (1) so that I can post a benchmarking project (2). I've also got grom (3) and other projects. |
| 19:17 | bitemyapp | gdev: you won't. |
| 19:17 | bitemyapp | my skype name is ancient and eldritch, nobody could ever guess it. |
| 19:18 | bitemyapp | gdev: I'm not bitemyapp on Skype. I am on github/twitter though. |
| 19:20 | bitemyapp | I might need to fix hEdn if it's implemented based on the spec (4) or possibly write my own library (5). |
| 19:25 | bitemyapp | I'm always up for plain ole tutorials too. |
| 19:28 | gdev | yeah that might be about my level at the moment |
| 19:29 | bitemyapp | gdev: there are some prereqs involved. The idioms in Haskell are varied and rich but require building blocks like mathematics. |
| 19:29 | bitemyapp | emphasis "like". |
| 19:30 | bitemyapp | gdev: Once 80% of this makes sense http://www.haskell.org/haskellwiki/Typeclassopedia you'll be a long way already. |
| 19:32 | gdev | bitemyapp yeah I have a lot of homework to do |
| 19:35 | gdev | had a problem so I thought I would log on to IRC, now I have a mountain to climb |
| 20:23 | logic_prog | in clojure.core.async, is there a way to say: "close this channel if I have not received anythin gfrom it in 5 minutes" ? |
| 20:23 | logic_prog | i.e., there's a timer on the channel |
| 20:23 | logic_prog | then after every message, the timer gets set to (current time + 5 minutes) |
| 20:25 | amalloy | logic_prog: every time you try to take from it, use alts! to also take from a 5-minute timeout channel, right? and close the main channel if you got a message from the timeout instead? |
| 20:26 | logic_prog | so I create a _new_ channel on every take-mejssage via <! ? |
| 20:26 | logic_prog | that seems sorta expensive |
| 20:26 | amalloy | the usual caveats apply: i don't actually use core.async, so alts! may not quite the right function |
| 20:26 | logic_prog | or are channels that cheap? |
| 20:26 | amalloy | sure, why not? |
| 20:26 | logic_prog | maybe I shoud write the code + benchmark it |
| 20:26 | logic_prog | rather than use imaginary optimizations |
| 20:27 | amalloy | yeah, i would be quite surprised if making a channel were much more expensive than receiving from one |
| 20:27 | bitemyapp | amalloy: sounds fine to me. |
| 20:27 | amalloy | like, in js the code for creating a timeout channel has got to be something like: allocate a Channel object; setTimeout(5000, function () {write to the channel}) |
| 20:28 | bitemyapp | logic_prog: don't pre-optimize or anticipate from a position of obscurity. Proceed with the clean and simple thing and wait for performance problems to arise. |
| 20:28 | logic_prog | bitemyapp: you are wise |
| 20:28 | logic_prog | i'm procrastinating with these imaginary perfomrnace bottlenecks |
| 20:28 | amalloy | a popular pastime |
| 20:28 | amalloy | i prefer to procrastinate by answering questions in #clojure |
| 20:29 | testcloj | l |
| 20:29 | edw | There's beene a lot of yak shaving going on today. |
| 20:29 | edw | s/beene/been/ |
| 20:29 | testcloj | cl |
| 20:29 | testcloj | (map #(into {} [[1 2]]) [:a :b :c]) didn't give result of {1 2, 1 2, 1 2}? instead it throws error |
| 20:29 | testcloj | why it doesn't work? |
| 20:30 | amalloy | #(into {} [[1 2]]) is a function of zero arguments, and you passed it one |
| 20:30 | amalloy | you could instead use (constantly {1 2]), for example |
| 20:30 | edw | It's a function of zero arguments because your #(...) form contains no percent signs. |
| 20:32 | amalloy | it also looks sorta like you imagine this starting with an empty map and mutating it three times, rather than starting with three distinct empty maps and conjing to each (not mutating) |
| 20:35 | testcloj | great, thx. this works: (map #(let [a %] into {} [[1 2]]) [:a :b :c]) |
| 20:38 | testcloj | but the result is [[1 2]] [[1 2]] [[1 2]] instead of {1 2} {1 2} {1 2} , since I used into {}, the result should have a map, correct? |
| 20:40 | hyPiRion | testcloj: you need to wrap it in a paren first |
| 20:41 | hyPiRion | ,(map #(let [a %] (into {} [[1 2]])) [:a :b :c]) |
| 20:41 | clojurebot | ({1 2} {1 2} {1 2}) |
| 20:41 | hyPiRion | vs |
| 20:41 | hyPiRion | ,(map #(let [a %] into {} [[1 2]]) [:a :b :c]) |
| 20:41 | clojurebot | ([[1 2]] [[1 2]] [[1 2]]) |
| 20:48 | testcloj | Thanks hyPiRion, but why wrap in a paren make a differnce? I am a newbie to cljure, might be a stupid quesiotn |
| 20:52 | bitemyapp | logic_prog: careful with words like that, the rabble might get angry and toss you off a cliff. |
| 21:00 | logic_prog | I need to setup something (probably not using clojure, but it's part of a clojure web app) to do a key/value store which supports (1) authentication and (2) expiring urls |
| 21:00 | logic_prog | i.e. my clojure app authenticates "hey, you have access to object XYZ, go fetch it from y other server" |
| 21:00 | logic_prog | then the other server looks at the certificate for "give me XYZ", authenticates it, and returns it |
| 21:01 | logic_prog | what is the easiest way to setup this "k/v store" with authentication + expiring urls |
| 21:01 | bitemyapp | logic_prog: so, you want a CMS with an ACL? |
| 21:01 | logic_prog | acl = access control list, yes |
| 21:01 | logic_prog | cms = contant management system ? |
| 21:01 | bitemyapp | content |
| 21:01 | logic_prog | basically I want something like riak, or hbase + authentication |
| 21:01 | logic_prog | it's for hosting static constant |
| 21:01 | logic_prog | i.e. think instangram / snapchat hosting of photos |
| 21:03 | logic_prog | ideally, this k/v store responds over http |
| 21:05 | bitemyapp | logic_prog: static content? you want riak, not HBase. |
| 21:05 | bitemyapp | logic_prog: HBase is *not* made for static content yo. |
| 21:05 | bitemyapp | logic_prog: Riak with the Bitcask backend specifically. |
| 21:06 | logic_prog | sorry, I meant hdfs |
| 21:06 | logic_prog | riak + authentication would make me happy |
| 21:06 | CaptainLex | Does anyone have any shoreleave experience? Is there a way to add middleware to a specific remote? |
| 21:07 | logic_prog | http://docs.basho.com/riakcs/latest/cookbooks/Authentication/ looks like what I want |
| 21:07 | logic_prog | query string optimiations |
| 21:09 | Janiczek | hi, when using Emacs + CIDER (nREPL), is it somehow possible to print the results of C-M-x (interactive eval) to the repl and not to the "Messages" statusbar row at the bottom? possibly with the evaluated form, so that it behaves as if I copy-pasted it to the REPL? (sorry for the probably wrong naming of things) |
| 21:18 | arohner | stupid core.async question. I want to give someone a channel, and take messages from it and do stuff with them. It makes perfect sense to me using threads, but how does that work with go blocks? |
| 21:18 | arohner | are go blocks values? (i.e. if I don't return the go block, will it still work?) |
| 21:19 | ToBeReplaced | janiczek: i don't know it well enough to give you a definitive answer. however, you could always type *1 in the repl after (C-Z, *1 Enter) |
| 21:20 | ToBeReplaced | arohner: go blocks return channels that yield the result of the body -- you could create a channel, pass it to a producer, then go or go-loop all you want |
| 21:21 | ToBeReplaced | arohner: you don't have to return a ref to the block; it won't be GC'd until its work is done |
| 21:21 | arohner | aha. there's the magic |
| 21:22 | Janiczek | ToBeReplaced: thanks, if I won't figure it out, at least this is nice :) |
| 21:28 | bitemyapp | ddellacosta: Keep coming back to this to see how many of the solutions youy understand: http://www.willamette.edu/~fruehr/haskell/evolution.html |
| 21:28 | bitemyapp | ddellacosta: it's also just a nice joke. |
| 21:28 | ddellacosta | bitemyapp: ha, bookmarked that a few weeks ago |
| 21:28 | bitemyapp | well there you go. :) |
| 21:29 | ddellacosta | bitemyapp: I think because of my Clojure experience, I started on the folder, and then used the more Haskell-y recursive solutions. But some of the later ones are mind-blowing to me. |
| 21:29 | ddellacosta | *foldr |
| 21:30 | bitemyapp | ddellacosta: folds/catamorphisms are generally the wiser way to go. Recursions are seen as relatively low-level but they yield some beautiful code in some cases. |
| 21:30 | bitemyapp | ddellacosta: a learning exercise is translating relatively obvious recursive implementations of tree operations to folds. |
| 21:30 | ddellacosta | bitemyapp: I rather like the simplicity and elegance of the recursions, most definitely |
| 21:30 | bitemyapp | ddellacosta: the compiler can do more to help you out if you use things like foldr though. |
| 21:30 | ddellacosta | bitemyapp: gotcha, good to know! |
| 21:31 | bitemyapp | recursion is you basically telling GHC, "I got this." |
| 21:32 | coventry | Janiczek: Use cider-eval-expression-at-point-in-repl from https://github.com/halgari/clojure-conj-2013-core.async-examples#usage |
| 21:39 | Janiczek | coventry: wow, that is exactly what I had in mind. thanks! |
| 21:47 | seangrove | Oh man, if only the cljs compiler were a person, I could throttle it |
| 21:47 | seangrove | So tired of seeing "java.lang.RuntimeException: java.lang.OutOfMemoryError: Java heap space" right before trying to push to production |
| 21:53 | bitemyapp | seangrove: funny, I get that almost every time I use Scala. |
| 21:53 | bitemyapp | then I remember to jack up my Xmx into the stratosphere. |
| 21:54 | seangrove | Looks like it's a combination of several things, but maybe updating Java will help |
| 21:57 | seangrove | Hrm, added :jvm-opts ^:replace ["-Xms1024m" "-Xmx1024m" "-server"] to the project and it passed this time. Let's see if it break again in the next hour... |
| 22:02 | `cbp | does anyone have a cljs + node lein template around |
| 22:03 | bitemyapp | `cbp: node? |
| 22:03 | `cbp | bitemyapp: yea |
| 22:03 | bitemyapp | `cbp: node? |
| 22:03 | `cbp | wat :( |
| 22:03 | bitemyapp | son, I am disappoint. |
| 22:03 | arrdem | there are things that Javascript should not do... |
| 22:04 | `cbp | i need to make desktop app and im not about to learn swing |
| 22:04 | bitemyapp | `cbp: first you abandon me to randos on DotA2. Now you're using node for anything other than cat pictures? |
| 22:04 | bitemyapp | ohhhhhhh |
| 22:04 | bitemyapp | I has answer. |
| 22:04 | `cbp | bitemyapp: I always invite you on dota :( |
| 22:04 | `cbp | you seemed away today |
| 22:05 | bitemyapp | `cbp: oh, sorry. I've been hacking today. Still want to play? |
| 22:05 | `cbp | nope :p time to figure out cljs + node |
| 22:05 | `cbp | + node-webkit |
| 22:05 | bitemyapp | `cbp: http://book.realworldhaskell.org/read/gui-programming-with-gtk-hs.html |
| 22:06 | bitemyapp | `cbp: you could also use Fay with node-webkit >:) |
| 22:06 | bitemyapp | arrdem: doters? |
| 22:06 | arrdem | bitemyapp: lemme finish figuring out when and where my classes start tomorrow then sure. |
| 22:06 | bitemyapp | arrdem: oh exciting. What are you taking? |
| 22:07 | arrdem | bitemyapp: the only interesting things are a graduate compilers class and the honors undergrad algos class. |
| 22:08 | kanja | I've got a single item list that contains a map and a map and I want to join the two together - why do I get "ClassCastException clojure.lang.PersistentArrayMap cannot be cast to java.util.Map$Entry clojure.lang.APersistentMap.cons (APersistentMap.java:42)" when calling (conj mapList map) and not (conj map mapList) |
| 22:11 | amalloy | i don't really believe that's what happens, kanja (conj some-list anything) always works |
| 22:11 | amalloy | whereas (conj some-map any-list) always fails, in the manner you describe |
| 22:12 | bitemyapp | kanja can't conj |
| 22:12 | bitemyapp | say it out loud. |
| 22:13 | kanja | http://pastebin.com/AZUh0CUM |
| 22:13 | kanja | @alalloy ^ |
| 22:14 | kanja | err http://pastebin.com/dhdcHgz6 is a little clearer |
| 22:15 | kanja | UG dur, revered the arguments to the function |
| 22:17 | bitemyapp | so, in a blazing show of total predictability, amalloy was right again? |
| 22:18 | gfredericks | clojurebot: amalloy |was| right again in a blazing show of total predictability |
| 22:18 | clojurebot | Roger. |
| 22:19 | amalloy | aw |
| 22:19 | arrdem | bitemyapp: well... looks like I'll be able to go work out daily before classes if I stop staying up to 2am. |
| 22:19 | arrdem | bitemyapp: decisions decisions. |
| 22:20 | bitemyapp | arrdem: I think you can fit both if we just cut it off a game earlier. Doters? |
| 22:21 | arrdem | bitemyapp: this is probably true. rebooting. |
| 23:07 | andyf | Bronsa: Clojure itself uses tags of type java.lang.Class, according to my testing. Does that imply it is a bug that tagOf() returns null when given such a tag? |
| 23:14 | Bronsa | andyf: who knows. I'd say yes. |
| 23:17 | amalloy | andyf: do you have an example of a function that uses a tag like that? |
| 23:18 | andyf | In Clojure, I think just about any tag like ^long will do, but give me a minute and I will point at a particular one. |
| 23:19 | mischanix | I asked my girlfriend if she likes Lazy Seqs. She didn't think it was funny. |
| 23:22 | amalloy | she was probably mad you pronounced seq wrong |
| 23:24 | mischanix | I don't think I'll ever be able to read 'seq' as 'seek'. |
| 23:24 | andyf | amalloy: I may have been a bit hasty. There are tags ^Object where 'Object' is a java.lang.Class while compiling Clojure itself, and test.generative uses some S-expressions as tags, but not long that I can see. |
| 23:25 | andyf | amalloy: My extra debug print doesn't give me file name or line #s, so it will take a while longer to track down where those ^Object tags are. |
| 23:25 | amalloy | andyf: that's usually a symptom of a careless macro |
| 23:26 | dbasch | I'm trying to extend a java class that has a protected constructor with no arguments via hen-class, and I get this error "Exception in thread "main" java.lang.NoSuchMethodError: com.google.bitcoin.core.NetworkParameters: method <init>()V not found" |
| 23:26 | dbasch | don't know why |
| 23:26 | amalloy | eg, (defmacro foo [x] (with-meta x {:tag Object})) |
| 23:26 | dbasch | gen-class that is |
| 23:27 | dbasch | any thoughts? |
| 23:27 | amalloy | andyf: looks like there's one in the definition of 'case |
| 23:31 | amalloy | that's the only one i can see, in fact |
| 23:31 | andyf | amalloy: Maybe one buried in defrecord somewhere? I'm guessing from some debug print output, haven't seen it yet. |
| 23:32 | amalloy | maybe. it's pretty hard to follow what goes on in deftype |
| 23:34 | amalloy | it looks right, though. on-interface starts as 'MyType, and the code that uses that tag is `(. ~(with-meta target {:tag on-interface}) ...) |
| 23:36 | andyf | I believe all of the cases I saw when compiling the latest Clojure occurred in defrecord, or in test.generative tags-that-are-general-forms |
| 23:43 | amalloy | wow, what on earth is test.generative doing with these :tag forms |
| 23:45 | testcloj | anybody did the question of http://www.4clojure.com/problem/156? one of it is (= (__ 0 [:a :b :c]) {:a 0 :b 0 :c 0}), I can't figure it out after thinking it for a long time |
| 23:46 | andyf | amalloy: Nicola started a thread on clojure-dev asking about that, and created a ticket to eliminate the property where such tags are visible 'outside' of test.generative |
| 23:46 | andyf | "Question about :tag" from mid-Dec |
| 23:47 | amalloy | andyf: it looks to me like tag->gen has a serious, although probably unrelated, bug as well |
| 23:47 | amalloy | the intent is that you can use arbitrary forms as tags, right, to specify your own generators? |
| 23:48 | amalloy | but...it removes all quotes from those forms before evaluating them. if i tag it like ^{:tag (repeat 10 'a)}, it mangles that into (repeat 10 a) |
| 23:48 | andyf | amalloy: I haven't learned, myself. Just passing along pointers to the conversations I've seen. |
| 23:51 | amalloy | last june the rss feeds for the clojure and clojure-dev mailing lists stopped working in my email client, so i haven't really read anything since then. on the whole that's worked out fairly well for me, but it does mean i haven't seen that conversation :P |
| 23:52 | andyf | direct link to the thread: https://groups.google.com/forum/#!topic/clojure-dev/hRZFuaiB_50 |