2015-02-03
| 01:11 | Mr0rris0 | :D |
| 01:17 | vas | Hi, i'm using CIDER to play with compojure and enlive. Compojure is in my :dependencies but is not "on the classpath" within cider.. any ideas as to why? (works in external shell) |
| 01:25 | tomjack | did you kill and start a new CIDER JVM after adding to :dependencies? |
| 01:25 | tomjack | if so, how are you starting CIDER? cider-jack-in? from a buffer visiting a file? which file? |
| 01:26 | tomjack | (it should be a .clj file inside the project in question) |
| 01:27 | vas | tomjack: you are a genius |
| 01:27 | clojurebot | Huh? |
| 01:28 | vas | tomjack: i was not starting it from a .clj in the project... that was an awesomely simple fix haha. thanks |
| 01:29 | tomjack | C-h f cider-jack-in |
| 01:32 | tomjack | (the cryptic doc there means you can do `C-u C-c M-j` (when it's bound) or `C-u M-x cider-jack-in` to get it to ask you what project you want) |
| 01:38 | vas | tomjack: those are very useful. thank you. how does one "bind" something like `C-c M-j to cider-jack-in? |
| 01:48 | tomjack | it's bound in cider itself I think |
| 01:48 | tomjack | you just have to be in _some_ .clj file already |
| 01:48 | tomjack | (otherwise cider bindings aren't in effect) |
| 01:49 | tomjack | maybe (global-set-key (kbd "C-c j") 'cider-jack-in) |
| 01:49 | tomjack | (in ~/.emacs.d/init.el in case that is not clear) |
| 01:50 | justin_smith | also C-c <char> for any single symbol on the keyboard is reserved by emacs for user specific stuff |
| 01:51 | tomjack | ..unofficially :( |
| 01:51 | justin_smith | sure, but only shitty elisp modes steal those keys, so if you override their bindings, it's their own fault :) |
| 01:51 | tomjack | I thought org-mode did? |
| 01:52 | justin_smith | OK, shitty or grandfathered in non-shitty :) |
| 01:53 | justin_smith | tomjack: I just checked in an org mode buffer |
| 01:53 | tomjack | maybe it only takes minor-mode-reserved bindings, which I just learned about |
| 01:53 | justin_smith | looks like they use some C-c char, but not a-zA-Z |
| 01:54 | tomjack | https://lists.gnu.org/archive/html/emacs-orgmode/2014-01/msg01141.html |
| 01:54 | tomjack | :) |
| 01:55 | tomjack | I think I agree with Bastien, org-mode is not a major mode, it's a monster mode |
| 01:55 | justin_smith | haha |
| 01:56 | vas | does anybody know how to play with enlive snippets? |
| 01:57 | justin_smith | tomjack: "Don't define C-c letter as a key in Lisp programs. Sequences consisting of C-c and a letter (either upper or lower case) are reserved for users; they are the only sequences reserved for users, so do not block them." https://www.gnu.org/software/emacs/manual/html_node/elisp/Key-Binding-Conventions.html |
| 01:57 | justin_smith | tomjack: so that gives us 52 decent C-c bindings that modes can't steal (major or minor) |
| 01:58 | tomjack | yes, I never really realized how valuable that is, until I just had flashbacks of trying to decide on a binding |
| 02:02 | ddellacosta | vas: what are you trying to do in particular w/Enlive? |
| 02:08 | vas | ddellacosta: so i've got deftemplate down, i'm trying to understand how i can grab a chunk of my html page and, defining it as a snippet, duplicate the chunk |
| 02:09 | ddellacosta | vas: I'm not sure about defining a snippet dynamically, assuming I'm understanding you right |
| 02:09 | ddellacosta | vas: but have you checked out clone-for? https://github.com/cgrand/enlive/wiki/Table-and-Layout-Tutorial,-Part-4:-Duplicating-Elements-and-Nested-Transformations |
| 02:09 | ddellacosta | vas: sounds like it may do what you need, if you are trying to repeat something |
| 02:09 | ddellacosta | vas: tell me if I'm way off-base here |
| 02:14 | vas | ddellacosta: very helpful actually. |
| 02:14 | ddellacosta | vas: great! |
| 02:25 | julianleviston | Not to start a war of editors, but am I missing much using SublimeText and not something lovelier? |
| 02:26 | julianleviston | I’ve attempted to look at paredit for SublimeText a couple of times, but it just didn’t work out well for me. Am I better off using vim or emacs or something? |
| 02:26 | rhg135 | Not at all |
| 02:26 | julianleviston | It’s often struck me that editing text is stupid. |
| 02:26 | julianleviston | And editing forms would be much more sensible… which is what paredit is for, right? |
| 02:26 | rhg135 | It is for programming |
| 02:27 | tomjack | julianleviston: I was going to say "yes, paredit" before you mentioned it.. but I drank the kool-aid |
| 02:29 | tomjack | I think every language I use that is not Clojure is regularly noticeably irksome for lack of good structural editing |
| 02:30 | julianleviston | I was watching timothy baldride’s tutorial before… and it looked like he knew what he was doing... |
| 02:30 | julianleviston | and he was using paredit. |
| 02:30 | tomjack | of course, I still use them.. |
| 02:30 | julianleviston | tomjack: oh no doubt. I wouldn’t even consider talking about this unless it was a lisp |
| 02:30 | julianleviston | tomjack: course. |
| 02:31 | tomjack | so I guess my answer is, yes, you are missing something, but no, you are not necessarily better off :) |
| 02:31 | julianleviston | tomjack: which editor to use tho? |
| 02:31 | julianleviston | a nice one with a buffer and whatnot... |
| 02:32 | tomjack | dunno, "not necessarily" here indicates my ignorance with regard to you (which is much greater than my ignorance with regard to myself, which itself is quite large) |
| 02:32 | tomjack | good luck :) |
| 02:33 | julianleviston | what do you use? :) vim? |
| 02:36 | justin_smith | I use emacs with vi key bindings |
| 02:36 | justin_smith | best of both worlds |
| 02:38 | julianleviston | ah ok. |
| 02:38 | julianleviston | what is tim using here? https://tbaldridge.pivotshare.com/media/core.async-episode-1-pipelines/9025/feature |
| 02:39 | justin_smith | no preview :( |
| 02:39 | julianleviston | efpm… huh? |
| 02:39 | julianleviston | I don’t understand... |
| 02:39 | justin_smith | I can't watch it without paying |
| 02:40 | julianleviston | yeah you can. the first one. |
| 02:40 | justin_smith | and I don't feel like paying money to see what editor he is using :) |
| 02:40 | justin_smith | I watched one of his before |
| 02:41 | julianleviston | you don’t heav to pay for the first |
| 02:41 | justin_smith | it's not my first |
| 02:41 | justin_smith | like I said |
| 02:42 | justin_smith | it sits there, not paying, with a donate button lit up |
| 02:42 | julianleviston | weird. not for me. |
| 02:42 | justin_smith | how many of his videos have you watched? |
| 02:42 | hellofunk | julianleviston: i think tbaldridge uses Cursive in some of his videos |
| 03:08 | julianleviston | justin_smith: just the free one. |
| 03:08 | julianleviston | justin_smith: core async pipelines. |
| 03:08 | julianleviston | hellofunk: thanks. |
| 03:09 | julianleviston | hellofunk: I find editors a necessary pain. |
| 03:09 | julianleviston | haha I sound so whiney :) |
| 03:18 | hellofunk | julianleviston: the editor situation for Clojure is a bit of an uphill climb, there is a learning curve regardless of the editor you choose. If I had to do it all over again, and had it been available when I started out, I'd have used Cursive, no doubt. But it's hard to break all the habits I've learned using emacs in my workflow. |
| 03:25 | julianleviston | hellofunk: I don’t mind learning things. For example, 6 months ago I decided to use Colemac in addition to Qwerty…. and that’s what I’m typing on now. |
| 03:25 | julianleviston | I’ll take a look at cursive, thanks. |
| 03:26 | julianleviston | Intellij? |
| 03:26 | julianleviston | Is it not slow and clunky bloatware? |
| 03:26 | julianleviston | I guess not. |
| 03:29 | julianleviston | I’m probably just wary because of eclipse. |
| 03:32 | ianhedoesit | ,(dotimes [n (count ["a1" "b2" "c3"])] (str "&ids=" (get ["a1" "b2" "c3"] n))) |
| 03:32 | clojurebot | nil |
| 03:32 | ianhedoesit | I think I know why that doesn't give me what I want, but I don't know how to do it correctly. |
| 03:33 | julianleviston | ianhedoesit: I think you just want join, don’t you? |
| 03:34 | julianleviston | ianhedoesit: what are you trying to end up with? |
| 03:34 | julianleviston | “&ids=[a1]&ids=[b1]&ids=[c1]” ? |
| 03:34 | ianhedoesit | yes. |
| 03:34 | julianleviston | ok one sec |
| 03:35 | hellofunk | julianleviston: definitely don't make the mistake of confusing IntelliJ and Eclipse. they are quite different. I can run Cursive fine on a nearly 4-year Macbook Pro, and I don't generally hear complaints about it being slow. |
| 03:35 | hellofunk | julianleviston: worth watching Colin Fleming's Clojure conj presentation about Cursive on ClojureTV youtube channel |
| 03:36 | julianleviston | I think this should do it, |
| 03:36 | julianleviston | (let [ids ["a1" "b2" "c3"]] |
| 03:36 | julianleviston | (join "&" (map #(str "&ids=[" % "]") ids))) |
| 03:36 | ianhedoesit | hellofunk: I just watched (most) of that today. |
| 03:36 | julianleviston | oops. |
| 03:36 | julianleviston | remove the & inside the first quote… |
| 03:37 | julianleviston | (let [ids ["a1" "b2" "c3"]] (clojure.string/join "&" (map #(str "ids=[" % "]") ids))) |
| 03:37 | ianhedoesit | that should've been more obvious to me. :) I should probably sleep. thanks |
| 03:38 | julianleviston | ianhedoesit: no wukkaz. |
| 03:38 | julianleviston | hellofunk: I just started watching jonyelipson’s… but ok. |
| 03:38 | julianleviston | epsilon |
| 03:38 | julianleviston | http://vimeo.com/103808402 |
| 03:39 | ianhedoesit | (inc julianleviston) |
| 03:39 | lazybot | ⇒ 3 |
| 03:53 | ianhedoesit | (identity ianhedoesit) |
| 03:53 | lazybot | ianhedoesit has karma 1. |
| 03:53 | ianhedoesit | (karma ianhedoesit) |
| 04:02 | daniel` | (identity daniel`) |
| 04:02 | lazybot | daniel` has karma 0. |
| 04:03 | ianhedoesit | :( |
| 04:04 | daniel` | i know |
| 04:05 | hyPiRion | (inc daniel`) ; fixed? |
| 04:05 | lazybot | ⇒ 1 |
| 04:07 | julianleviston | cfleming: nice talk! |
| 04:08 | julianleviston | cfleming: interesting, because I’ve been ranting about structural editing for a long while… and I’ve been applying these same ideas in the project I’ve been devving for the last year or so… which is a structural editor for content… (ie websites). |
| 04:08 | daniel` | hyPiRion: :D ty |
| 04:09 | daniel` | (inc hyPiRion) |
| 04:09 | lazybot | ⇒ 65 |
| 04:09 | michaelr` | hey |
| 04:11 | julianleviston | hey |
| 04:25 | cfleming | julianleviston: Thanks, glad you liked it! |
| 04:27 | julianleviston | cfleming: it’s a really good further step into having languages and projects that are self-describing, learnable, and intelligently structured rather than “dumb text”. |
| 04:28 | tomjack | hmm, in gorilla repl, are we actually supposed to type code into the browser? ;[ |
| 04:28 | julianleviston | cfleming: I really hate how I generally can’t apply the language to the source. “Homoiconicity what?” |
| 04:28 | cfleming | julianleviston: Right - I actually think text is a fine serialisation mechanism, having tried it I'm not a fan of graphical editors. |
| 04:28 | tomjack | ah |
| 04:28 | tomjack | nevermind. whew. |
| 04:28 | cfleming | julianleviston: I think tools should understand it though |
| 04:29 | julianleviston | cfleming: yeah, definitely… cf previous work on transite. |
| 04:29 | julianleviston | transit* |
| 04:29 | tomjack | "Should you prefer more of an antique editing experience" |
| 04:29 | cfleming | tomjack: I didn |
| 04:29 | cfleming | oops |
| 04:29 | cfleming | tomjack: I didn't write that, but I did have a little chuckle when I read it |
| 04:32 | tomjack | ah, so we are supposed to paste from emacs into gorilla I guess |
| 04:34 | cfleming | tomjack: It seems like it would be nice to be able to treat gorilla as a remote REPL and connect to it from some other editor |
| 04:34 | cfleming | tomjack: Although I haven't used it so I'm not sure if that makes sense |
| 04:34 | julianleviston | cfleming: what do you use as a REPL? |
| 04:34 | julianleviston | cfleming: or don’t you really do REPL dev? |
| 04:35 | cfleming | julianleviston: Cursive |
| 04:35 | julianleviston | oh it has a REPL in it? Sorry I missed that. |
| 04:35 | tomjack | the problem is all the other stuff |
| 04:35 | tomjack | and your interface to a document shouldn't be a cider repl |
| 04:36 | cfleming | julianleviston: Yeah, I should have made that clearer in the talk - I'm not anti-REPL, I just don't think it should be used for providing basic editor functionality |
| 04:36 | cfleming | julianleviston: The Cursive REPL is pretty full-featured these days |
| 04:36 | julianleviston | cfleming: <3 |
| 04:36 | tomjack | copying into gorilla seems worth it, though |
| 04:37 | julianleviston | tomjack: howcomes? tell me about gorilla? |
| 04:37 | Glenjamin | there's various things you can get which will send text to another app |
| 04:38 | tomjack | julianleviston: well, latex, for one thing, that's very nice |
| 04:38 | tomjack | plus.. everything else :) |
| 04:38 | julianleviston | tomjack: i’ve never heard of gorilla before now. |
| 04:38 | julianleviston | tomjack: I’ll go take a look. |
| 04:38 | tomjack | I mean, if I want to share code as pedagogy, that's what I'm gonna do |
| 04:38 | tomjack | http://gorilla-repl.org/ |
| 04:39 | tomjack | http://viewer.gorilla-repl.org/view.html?source=github&user=<>&repo=<>&path=<> |
| 04:39 | tomjack | pretty nuts |
| 04:40 | cfleming | does that take a worksheet from github? |
| 04:40 | cfleming | Any suggestions for one to try out? |
| 04:43 | julianleviston | Oh ok so it’s sort of like mathematica for code, similarly to that other project that was built on Om whose name eludes me right now... |
| 04:43 | julianleviston | mathematica for clojure* |
| 04:44 | tomjack | I'd say more "wolfram for code"? |
| 04:44 | julianleviston | So dumb question (cursive) but… how do I open my existing git project. lol... |
| 04:44 | tomjack | er, "wolfram for clojure"? |
| 04:44 | julianleviston | tomjack: same same, really… right... |
| 04:45 | tomjack | http://viewer.gorilla-repl.org/view.html?source=github&user=JonyEpsilon&repo=sr-basics&path=ws/introduction.clj |
| 04:46 | tomjack | (first one I found via depth-first search on the owner of the gorilla repo) |
| 04:46 | cfleming | julianleviston: Lein project? |
| 04:46 | julianleviston | cfleming: actually it’s a rails project that has a lein project inside it… |
| 04:47 | cfleming | julianleviston: ok, I guess you're not using IntelliJ Ultimate? |
| 04:47 | tomjack | pretty cool that clojure code can return latex too |
| 04:47 | julianleviston | cfleming: no… I just started. |
| 04:47 | cfleming | julianleviston: Ok, you won't get any Ruby support in that case. |
| 04:47 | julianleviston | cfleming: that’s ok. I’m fine with no ruby support :) |
| 04:47 | julianleviston | cfleming: just keen for the clojurescript support |
| 04:49 | tomjack | I guess: render/Renderable (render [self] {:type :latex :content "\\frac{1}{2}" :value 1/2}) |
| 04:49 | cfleming | julianleviston: So I'm actually not sure what the best way to do that is. I think you'd be best creating the project from scratch, since if you import your lein project it won't know anything about the rest of it |
| 04:49 | cfleming | julianleviston: So, File->New project, tell IntelliJ where it is |
| 04:50 | julianleviston | cfleming: I’ll give it a shot |
| 04:50 | julianleviston | using open |
| 04:50 | cfleming | julianleviston: You'll be able to use open to just open the Clojure part if that's all you need |
| 04:50 | cfleming | julianleviston: Just use open, and point it to either the project.clj or the enclosing dir |
| 04:53 | julianleviston | CMD-SHIFT-N… guh. |
| 04:55 | julianleviston | Ah. I wish the find was softer (ie treated all punctuation as whitespace in search terms AND target files) |
| 04:56 | julianleviston | Argh why does option-shift-right arrow (word select kbd) include the whitespace after it? |
| 04:57 | julianleviston | how do I move between objects? it seems to be “move around between text” as the standard way of navigation. |
| 04:57 | julianleviston | (ie char-by-char) |
| 04:57 | Glenjamin | that was the issue i found when using cursive - intellij didn't quite seem to have the "usual shortcuts" i expected |
| 04:58 | julianleviston | Glenjamin: yeah well I’ll put up with that. |
| 04:58 | Glenjamin | yeah, i didn't have time to get used to it at that point :( |
| 04:58 | julianleviston | but selecting space after is a pain in the butt. |
| 04:58 | julianleviston | it all feels very java-y to me. |
| 04:59 | julianleviston | time to learn |
| 04:59 | SagiCZ | intellij is java ide after all |
| 04:59 | julianleviston | SagiCZ: yes, but clojure is built on java and it doesn’t feel like java at all, even though it is. |
| 04:59 | cfleming | julianleviston: Check https://cursiveclojure.com/userguide/keybindings.html for how to set up keybindings, or if you'd rather do it by hand go to settings->keymap |
| 05:00 | julianleviston | cfleming: sorry I shouldn’t have said anything. I’m aware there are keybindings. |
| 05:00 | julianleviston | cfleming: thanks! :) |
| 05:00 | julianleviston | Is there a good tutorial on keyboard navigation? because it’s not following anything I’m used to on MacOS |
| 05:01 | cfleming | julianleviston: Which keymap do you have selected? |
| 05:01 | SagiCZ | julianleviston: there is plenty of thing to configure in intellij.. for example if you should be able to move cursor on blank line by clicking or not |
| 05:01 | cfleming | julianleviston: Settings->Keymap |
| 05:01 | julianleviston | cfleming: whatever is standard. I’ll check. |
| 05:01 | cfleming | julianleviston: Make sure it's Mac OS X 10.5+ |
| 05:02 | julianleviston | cfleming: erm… I don’t have settings. I have preferences…? but where are keymaps? |
| 05:02 | cfleming | julianleviston: Right, File->Preferences |
| 05:02 | julianleviston | Erm, no. |
| 05:02 | cfleming | julianleviston: Appearance & Behaviour -> Keymap |
| 05:02 | cfleming | julianleviston: You're on a Mac? |
| 05:03 | julianleviston | cfleming: all good. Yeah, it’s under the app menu, prefences. |
| 05:03 | julianleviston | got it |
| 05:03 | cfleming | julianleviston: Sorry, IntelliJ IDEA -> Preferences |
| 05:03 | julianleviston | keymap was os x |
| 05:03 | julianleviston | switched to 10.5+ |
| 05:04 | julianleviston | lovely |
| 05:05 | cfleming | julianleviston: Nice. That one follows Mac standards much better. |
| 05:05 | julianleviston | yeah and now I can use option up arrow to select levels of objects… huzzah :) |
| 05:06 | julianleviston | cannot wait until I’ve learned this. It’s the editor I’ve always wanted… for YEARS. |
| 05:06 | SagiCZ | julianleviston: have you been living under a rock? |
| 05:07 | julianleviston | SagiCZ: um no. |
| 05:07 | julianleviston | SagiCZ: but syntax editing editors and IDEs traditionally suck. Hard. |
| 05:07 | SagiCZ | intellij doesnt |
| 05:07 | julianleviston | SagiCZ: maybe I just have different requirements than most people. |
| 05:08 | julianleviston | SagiCZ: c’mon how many editors let you efficiently navigate around the actual objects of your program? |
| 05:08 | julianleviston | SagiCZ: as averse to the text. |
| 05:08 | SagiCZ | julianleviston: i dont understand what you mean by that |
| 05:08 | cfleming | julianleviston: Well, IntelliJ does for Java - the navigation is pretty amazing |
| 05:09 | julianleviston | SagiCZ: cfleming can you explain it to him? |
| 05:09 | julianleviston | SagiCZ: the semantic elements… as averse to the textual elements. |
| 05:09 | SagiCZ | well intellij can do that.. for years.. so whats the issue here? |
| 05:10 | julianleviston | SagiCZ: we’ll see, I guess :) |
| 05:10 | julianleviston | SagiCZ: maybe I’m assuming too much. |
| 05:13 | SagiCZ | also there is thousands of plugins.. |
| 05:13 | julianleviston | cfleming: it doesn’t like om too much. Guess that’s because of the macros in it... |
| 05:14 | cfleming | julianleviston: Yeah, I'm actually working on om and om-tools support for the next release |
| 05:14 | julianleviston | cfleming: sweet. |
| 05:14 | cfleming | julianleviston: Out in a couple of days hopefully |
| 05:20 | julianleviston | cfleming: and therefore also clojurescript? Seems to be having some issue with (.. event -target -checked) |
| 05:21 | cfleming | julianleviston: ClojureScript is generally supported, although interop is difficult. There's an open issue for the .. form |
| 05:21 | julianleviston | cfleming: it’s a bit sad that macros force you to kind of… build extra bits for it. |
| 05:21 | cfleming | julianleviston: That one is just a bug/oversight. In general interop is hard though because in many cases symbol resolution is impossible |
| 05:21 | julianleviston | cfleming: yeah... |
| 05:21 | Glenjamin | you can use -> instead of .. there |
| 05:27 | julianleviston | cfleming: ok so I read the “getting around” page on doc… how do I navigate left or right at the current hierarchical level under the cursor (so if I’m at the beginning of a defn, I’d like left-this to nav to the end of the last one) |
| 05:29 | julianleviston | cfleming: ah ok I think I found it. I turned on other setting bindings cursive binding set and I can use paredit... |
| 05:29 | cfleming | julianleviston: Does Navigate->Structural Movement->Move Forward do what you want? |
| 05:30 | cfleming | julianleviston: Ok cool |
| 05:30 | julianleviston | cfleming: one sec |
| 05:30 | julianleviston | cfleming: actually they’re for editing, not nav. I’ll check what you said. |
| 05:30 | cfleming | julianleviston: If you've applied the Cursive bindings it should have set one up for that |
| 05:31 | SagiCZ | . |
| 05:31 | julianleviston | cfleming: yes, structural movment -> Move Forward is it… ok I’ll check it out :) maybe the website could deal with this being on there, too :) |
| 05:31 | julianleviston | cfleming: sorry for so much noise. I’m just excited :) |
| 05:32 | cfleming | julianleviston: I'm pretty sure it's there - https://cursiveclojure.com/userguide/paredit.html, under Getting around |
| 05:32 | cfleming | julianleviston: Hehe, no worries |
| 05:32 | SagiCZ | . |
| 05:32 | cfleming | julianleviston: Make sure you check out https://cursiveclojure.com/userguide/navigation.html too |
| 05:34 | ianhedoesit | if I have a common string such as a REST endpoint, `ep.example.com`, and I have multiple files which use that as a root but add onto it like `/account/get-field` and `/settings/update`, is there a better way to compose that per file other than `(str core/endpoint "/settings/update?inputs=values")` |
| 05:37 | ianhedoesit | I know it doesn't really save much time, I was just curious. for example, instead of just defining it in each file (i.e. `(def endpoint "ep.example.com/account")` in one file and `(def endpoint "ep.example.com/settings")` in another), including the one root endpoint from a file and changing it per file/ns |
| 05:40 | julianleviston | ianhedoesit: What would you like? You can always define a function which prepends some string to some args… (defn heythere [& args] (apply str "yeah yeah" args)) |
| 05:41 | julianleviston | (heythere "woo") ; -> "yeah yeahwoo" |
| 05:42 | ianhedoesit | yeah, I figured. I'm not sure what I'd like. :) I was just not liking having multiple vars with the same name in different files with different meanings. |
| 05:42 | julianleviston | ianhedoesit: well if you don’t know what you’d like, then it doesn’t matter much what you write :-) <3 |
| 05:49 | ianhedoesit | I'd like to not have to define the same variable in multiple files when it's slightly different, but I suppose just having one function like you said that I can easily compose stuff with would be fine. |
| 05:51 | julianleviston | ianhedoesit: I don’t understand why you have to define the same variable in multiple files… def it in one, then use require in the others. |
| 05:52 | julianleviston | cfleming: I can’t seem to get paredit turned on for some reason. Following https://cursiveclojure.com/userguide/keybindings.html it keeps not applying. Dunno if I should tell you this here or not! |
| 05:53 | julianleviston | cfleming: lots of conflicts apparently. |
| 05:53 | cfleming | julianleviston: I think this is just a case of confusing UI - if you go to your Keymaps panel, and check your actions there (search for slurp, for example) - does it have a binding applied? |
| 05:53 | ianhedoesit | julianleviston: I don't literally define the same thing multiple times in multiple files, I just have part of the same thing in multiple files (the root of the endpoint) |
| 05:54 | julianleviston | ianhedoesit: sorry I’m really not sure what you’re not able to do, then…? |
| 05:54 | ianhedoesit | but what you suggested is fine. |
| 05:55 | julianleviston | cfleming: no it doesn't. |
| 05:55 | cfleming | julianleviston: Have you copied the Mac OS X 10.5+ keymap to your own (mutable) one? |
| 05:55 | julianleviston | cfleming: yep |
| 05:56 | julianleviston | cfleming: then when I go into other settings -> clojure -> keybindings and choose Cursive, it has a lot of conflicts… when I apply, that “goes away”, but the bindings haven’t been applied. |
| 05:56 | cfleming | julianleviston: Hmm - when you go to the Keybindings panel and select, say, Cursive from the dropdown, what do you see? Are any actions selected? |
| 05:57 | cfleming | julianleviston: I see. Could you try closing the settings panel and re-opening it? Someone else reported something similar today, and I'm not sure if this has changed in v14 or something. |
| 05:57 | julianleviston | cfleming: lots… but there are many conflicts |
| 05:58 | julianleviston | cfleming: sure. this will be my 5th time. |
| 05:58 | cfleming | julianleviston: It seems to work for most people though, not sure why it's problematic for some people. |
| 05:58 | cfleming | julianleviston: Don't worry about the conflicts |
| 05:58 | cfleming | julianleviston: The Cursive action will be used in Clojure contexts, and the default one otherwise |
| 05:59 | julianleviston | cfleming: oh… it’s working now. I have no idea what I did differently. |
| 05:59 | julianleviston | cfleming: god I feel like such a noob. apologies. |
| 06:00 | cfleming | julianleviston: Nah, don't, I hate this panel - it's the worst UI. Unfortunately I can't do much else since I can't customise the Keymap one. |
| 06:00 | cfleming | julianleviston: I still need to make it clearer what's going on. To make it worse, what I think you were seeing there is that IntelliJ keeps a mutated copy of the settings around, but doesn't show that copy in other panels (e.g. Keymap) until you close the window. |
| 06:01 | cfleming | julianleviston: Or something - there's definitely a problem in there somewhere, I can't work it out. Unfortunately this is the first thing everyone does when they try Cursive, so I have to fix it. |
| 06:02 | julianleviston | cfleming: haha :) hehe… no worries. |
| 06:02 | julianleviston | cfleming: thanks so much for your help. Embrace the fail, probably! :) (ie explicit instructions on how it stuffs up) |
| 06:03 | cfleming | julianleviston: Yeah, it'll have to be something like that unless I can fix it. |
| 06:04 | julianleviston | cfleming: God it’s still clunky as hell (not your fault… just what I should be able to do versus reality). |
| 06:07 | julianleviston | cfleming: For example, I’m two levels deep into a function… then I do “nav right” twice, and instead of going to the relative spot within the next section, it bumps me up to a higher level (level 0) and I’m now navving there. GUH. Fail. |
| 06:07 | julianleviston | cfleming: paredit is stupid. |
| 06:07 | cfleming | julianleviston: You'd like it to jump across at the same depth? |
| 06:08 | julianleviston | cfleming: yep. |
| 06:09 | julianleviston | The equivalence in prose would be… if I’m navving at word level, then I cross a sentence-bounds (ie full stop) all of a sudden I start jumping sentences and screaming running around while my house burns down ;-) |
| 06:09 | cfleming | julianleviston: What would you want here: (((foo|)) bar ((baz))) |
| 06:09 | julianleviston | sematic structure isn’t being respected. |
| 06:10 | cfleming | julianleviston: Jump to bar or baz? |
| 06:10 | julianleviston | cfleming: well, I’m navving symbols at that point, right? so… foo| -> bar| -> baz| |
| 06:10 | cfleming | julianleviston: But that doesn't respect your depth |
| 06:11 | julianleviston | cfleming: that’s true. |
| 06:11 | julianleviston | cfleming: but it does respect my semantic depth, I think… no? |
| 06:11 | Glenjamin | it's like when youre pressing "down" on a long line |
| 06:11 | Glenjamin | and there's a short line |
| 06:11 | julianleviston | exactly. |
| 06:12 | julianleviston | think like a person, not a machine. |
| 06:12 | julianleviston | (that wasn’t aimed at anyone btw) |
| 06:12 | Glenjamin | that implies some level of mind-reading |
| 06:12 | julianleviston | Glenjamin: no. |
| 06:12 | cfleming | julianleviston: Ok, so it would have to remember the depth you're at and try to maintain it. Horribly stateful. |
| 06:12 | cfleming | Glenjamin: Right |
| 06:12 | julianleviston | Glenjamin: it implies a good deal of syntactic analysis |
| 06:13 | Glenjamin | you need to know what i "meant" when i pressed "nav-right" |
| 06:13 | cfleming | julianleviston: Might be able to do it though, I'll think about it. |
| 06:13 | julianleviston | Glenjamin: what you mean is always bound to where you came from. |
| 06:13 | julianleviston | cfleming: it was actually what I thought you’d already done. |
| 06:14 | cfleming | julianleviston: But you came from somewhere else before that - it does require some mind reading to know from when you mean. |
| 06:14 | cfleming | julianleviston: I don't think it's as simple as the line length case |
| 06:14 | Glenjamin | which actions continue the stateful movement, and which reset it? |
| 06:14 | julianleviston | cfleming: actually the opposite. It’s more simple than the line lenght case. Line lenght is hard. |
| 06:14 | julianleviston | length. |
| 06:15 | cfleming | Glenjamin: Exactly |
| 06:16 | julianleviston | cfleming: well, if I’m moving by character, then the next character. If I’m moving by symbol, then the next symbol, if I’m moving by sentence, then that, if by para, then that, if by function, then that, etc. |
| 06:17 | julianleviston | It would only require three levels of functions, I think… one is “move to the next at this syntactic level”, and the other is “move to the next and jump syntactic level up”, and the third is “move right, syntactic down” |
| 06:17 | julianleviston | so it’d need current state… (what syntactic level you’re at)… and six “keys” |
| 06:18 | cfleming | julianleviston: I don't think that's what most people want when using paredit, but maybe they're just used to something crappy. |
| 06:18 | julianleviston | cfleming: you’re right. |
| 06:18 | cfleming | I'm still not sure what you mean by syntactic level |
| 06:18 | julianleviston | cfleming: apologies for confusing this with paredit. |
| 06:18 | cfleming | Do you mean depth in the tree? |
| 06:18 | julianleviston | cfleming: not quite really. |
| 06:18 | cfleming | Or do you mean char/symbol/form |
| 06:19 | julianleviston | cfleming: I’m not completely sure but possibly depth in the tree... |
| 06:20 | julianleviston | cfleming: For example… I want to work on a particular function. I open a file containing it, then quickly move at function level between them until I find it, then I go into that function… now I go in go in go in, then work on a particular section of the function… perhaps within a let block… I nav around inside that let block, doing my work… refactoring forms, shifting things, etc. (and so on). |
| 06:21 | julianleviston | cfleming: this excited me so much because it’s possible to build meta patterns of editing on top of it. For example, you’ve done extract chunk to let block binding var, I noticed. |
| 06:22 | cfleming | julianleviston: If you're talking depth in the tree, paredit already provides move forward in, move forward out, and so on |
| 06:22 | julianleviston | cfleming: it does. But the left and right don’t work properly. |
| 06:22 | cfleming | julianleviston: Right, but you need a lot more semantic knowledge to do that right than just tree depth |
| 06:23 | cfleming | julianleviston: "that" being extract let bindings |
| 06:23 | julianleviston | cfleming: Do you? |
| 06:23 | julianleviston | cfleming: ah. |
| 06:23 | cfleming | julianleviston: Sorry, unsynchronised writes to a single data store |
| 06:23 | julianleviston | cfleming: lol no worries :) |
| 06:25 | julianleviston | cfleming: I guess what I’m after is for the things we actually do to be made easier than the things we don’t do much. For example, when I’ve selected a function to work on, I very rarely need to change the arguments immediately, yet I *always* have to nav through the argument list to get to the body. W… T…. F… |
| 06:25 | julianleviston | cfleming: it’s not probably worth worrying about. |
| 06:27 | cfleming | julianleviston: That's definitely a worthy goal. |
| 06:27 | cfleming | julianleviston: It has to be unambiguous how it works, though. |
| 06:27 | cfleming | julianleviston: Anyway, I'll think about it. |
| 06:32 | julianleviston | cfleming: I think it’s probably mostly there. It’s a bit tricky, though… in that ()| () -> () |() which makes it feel like two presses between each thing, so that actually each thing is not just one thing, so it doesn’t give you the feeling of navigating between single items… it gives you the feeling of navigating between things and the spaces between them. “Beginning of form 1 -> beginning of form 2 -> |
| 06:32 | julianleviston | beginning of form 3” is uniform, but “beginning of form 1 -> end of form 1 -> beginning of form 2” feels… wrong, somehow. |
| 06:32 | R0B_ROD | $seen godd2 |
| 06:32 | lazybot | godd2 was last seen quittingPing timeout: 246 seconds 1 day and 14 hours ago. |
| 06:33 | julianleviston | cfleming: anyways. :) let me know if you want me to muddy the water further. |
| 06:34 | julianleviston | cfleming: and I love your work so far! |
| 06:44 | cfleming | julianleviston: Thanks! And thanks for the feedback too, it's interesting. I think I'll try implementing the move-at-same-depth thing and see how it works. |
| 07:43 | CookedGr1phon | Hey all, I have a genclassed namespace, which gets created with an onCreate lifecycle method |
| 07:43 | CookedGr1phon | I would like to use something from another namespace throughout the file so currently havea require :refer |
| 07:43 | CookedGr1phon | however, I would very much like to require the namespace as part of the onCreate |
| 07:44 | CookedGr1phon | so that I can do some actions immediately before loading the namespace |
| 07:44 | CookedGr1phon | but still keep the convenience of the referred naming in this file |
| 07:58 | pyrtsa | Is no one else worried that clojure.core/dedupe is going to miss a reasonable number of use cases because it doesn't take a "by key" function argument? |
| 07:59 | pyrtsa | I.e. I would've defined it as (dedupe f xs) -- remove consecutive duplicates of (map f xs); (dedupe f) -- transducer version. |
| 08:00 | pyrtsa | It would be dead simple to just say (dedupe identity xs) when the current behaviour is needed. |
| 08:01 | julianleviston | pyrtsa: can’t why can’t you just comp it with map? |
| 08:01 | julianleviston | pyrtsa: sorry if that’s a stupid q. |
| 08:01 | hyPiRion | why not just call it dedupe-by ? |
| 08:01 | pyrtsa | hyPiRion: Sure, could do that as well, but don't you think it's better to just do it in clojure.core? |
| 08:01 | hyPiRion | so you can do stuff like (dedupe-by :index = xs) |
| 08:02 | hyPiRion | Maybe. |
| 08:03 | pyrtsa | I'd still go with a signature like (dedupe[-by] f xs) |
| 08:03 | Glenjamin | i wonder how many functions like that can be defined efficiently only in terms of clojure.core |
| 08:03 | pyrtsa | I honestly don't think dedupe without a key is good library design. |
| 08:03 | Glenjamin | that would simplify massively me "one-function dependency manager" |
| 08:04 | Glenjamin | s/me/my/ |
| 08:04 | Glenjamin | certainly the -by variant is more widely applicable |
| 08:04 | julianleviston | pyrtsa: it’s not a library, tho… add it to contrib? |
| 08:05 | pyrtsa | julianleviston: My point is, 1.7 is still alpha. This thing could be changed for the better. |
| 08:05 | Glenjamin | is dedupe new in 1.7? |
| 08:05 | pyrtsa | Yes. |
| 08:05 | pyrtsa | hyPiRion: Your use case would be simply (dedupe :index xs). |
| 08:06 | hyPiRion | pyrtsa: Sure, but what if I want to check on something else? |
| 08:06 | hellofunk | a simple compojure route like (GET "/some/dir/file.html" ...) returns an error 401 when accessing site.com/some/dir/file.html#whatever and I can't figure out why... is the hash something that requires explicit mention in the compojure route also? |
| 08:06 | hyPiRion | say (dedupe-by :key identity xs) |
| 08:06 | hyPiRion | err |
| 08:06 | hyPiRion | (dedupe-by :key identical? xs) |
| 08:06 | julianleviston | hellofunk: does it work without the location? (ie the hash) |
| 08:07 | Glenjamin | the hash shouldn't be sent to the server at all |
| 08:07 | pyrtsa | hyPiRion: Ah, *that*. |
| 08:07 | hellofunk | julianleviston: good catch, it has nothing to do with the hash, same error. |
| 08:07 | Glenjamin | looks like dedupe got added as part of rich's "transducers wip" - no separate discussion on jira afaict |
| 08:08 | Glenjamin | it could probably be overloaded to support index-fn and comparison-fn |
| 08:08 | pyrtsa | hyPiRion: Actually, It could be (dedupe-by keyfn comp coll) |
| 08:09 | pyrtsa | Like the longer signature of sort-by. |
| 08:09 | hyPiRion | yeah |
| 08:10 | pyrtsa | Cool. That'd work. But because of the partial application nature of transducers, I'd not |
| 08:10 | pyrtsa | ...have (dedupe-by keyfn coll) defined at all. |
| 08:11 | hyPiRion | right. Hrm. |
| 08:11 | pyrtsa | hyPiRion: Though... sort-by asks for a Comparator. |
| 08:11 | hyPiRion | an optional comparator, mind you |
| 08:11 | julianleviston | I still don’t understand why you can’t compose them together… as in.. dedupe transducer composed with map… no? |
| 08:11 | julianleviston | I’m missing something aren’t I? |
| 08:12 | pyrtsa | julianleviston: You often want to keep the original and compare by some aspect of it. |
| 08:12 | julianleviston | yeah… but still |
| 08:13 | julianleviston | even so… i still don’t get it |
| 08:13 | pyrtsa | julianleviston: Say I'm walking a Datomic history index, only keeping the latest added/retracted boolean of the datom. If I (map :added datoms), all I've got is a sequence of booleans. |
| 08:13 | pyrtsa | Sorry, actually the booleans is what I miss. |
| 08:14 | hyPiRion | pyrtsa: perhaps ask puredanger about this. Sounds reasonable to ask about it |
| 08:14 | pyrtsa | So a datom being a map of keys [:e :a :v :tx :added], I'd dedupe by (juxt :e :a :v). If instead, I mapped (map (juxt :e :a :v) datoms), I'd lose the :tx and :added. |
| 08:15 | pyrtsa | hyPiRion: Cool. |
| 08:15 | Glenjamin | doesnt dedupe only do consecutive? |
| 08:16 | pyrtsa | Glenjamin: Yeah. And any sorted sequence is terrific for that! |
| 08:16 | pyrtsa | ...Like Datomic indices. |
| 08:16 | Glenjamin | oh right, sorted by eav |
| 08:16 | pyrtsa | Yep! |
| 08:16 | pyrtsa | ...and :tx, descending. |
| 08:18 | pyrtsa | hyPiRion: Thinking of the most generic use case, actually (dedupe pred coll) where pred takes 2 arguments, would work. Then the ordinary use case would be (dedupe = coll). |
| 08:20 | hyPiRion | pyrtsa: Would be a bit ugly to get the result you wanted though |
| 08:21 | pyrtsa | Agreed. |
| 08:23 | hyPiRion | ,(defn asidef [f nxt] (fn [& xs] (apply nxt (map f xs)))) |
| 08:23 | clojurebot | #'sandbox/asidef |
| 08:23 | hyPiRion | ,((->> = (asidef :key) (asidef :key)) {:key {:key 1}} {:key {:key 1}}) |
| 08:23 | clojurebot | true |
| 08:33 | sveri | Hi, is anyone here using environ? I am having trouble to get profiles.clj to work. It does work some sort of, but somehow does not recognize I am in dev mode anymore. There also seem to be problems with cljx regarding environ. Anyone experienced this or using a different approach? |
| 08:35 | jballanc | sveri: we've switched over to Nomad |
| 08:35 | jballanc | not quite as convenient as environ, but seems to be a bit more robust |
| 08:36 | clgv | sveri: if you can't trace it in the lib maybe that lib is too complex. |
| 08:37 | sveri | jballanc: this is the third time I don't get it running, I guess I give nomad a try too |
| 09:01 | clgv | With profiles.clj I should be able to replace all repositories by my own private proxy repository, correct? |
| 09:02 | jballanc | in theory |
| 09:02 | engblom | While I am more productive in Clojure than in Haskell, Clojure seem to be much more difficult to teach to other than Haskell. It is easier to pick out a subset to teach when it comes to Haskell. |
| 09:02 | clgv | jballanc: did you experience differently in practice? |
| 09:03 | engblom | Has anyone been teaching Clojure here? |
| 09:04 | tbaldridge | I have a friend who has picked up Clojure after only about a year in Python/Java (no programming experience at all before that). |
| 09:05 | tbaldridge | He's pretty much taken Clojure for the Brave and True and ran with it, no major issues yet |
| 09:05 | clrnd | engblom, I have taught haskell and it can be quite difficult sometimes |
| 09:05 | the_frey | that's a great way to get up to practical usefulness |
| 09:05 | the_frey | CFTBAT that is |
| 09:06 | tbaldridge | the_frey: yeah, and the early videos by Rich provide a nice basis to the whole thing. |
| 09:07 | tbaldridge | So I'm about to spout something that could be considered slightly offensive and/or controversial: |
| 09:07 | TEttinger | gasp |
| 09:07 | tbaldridge | engblom: my theory is that Haskell might be easier to start teaching to people since there are so many small details that can be covered before actually getting to the useful stuff. |
| 09:08 | tbaldridge | You have to have discussions about types, IO monads and the like before even getting to a Hello World!. In clojure you just plop a println anywhere, and can use slurp on a whim. |
| 09:09 | TEttinger | tbaldridge: so there's more that you can use with minimal necessary knowledge, so that's a broad base to cover |
| 09:09 | tbaldridge | So while it seems like they are learning a good foundation of what is needed to program Haskell, I'd question how useful this basic Haskell knowledge is. |
| 09:09 | clgv | engblom: you can start teaching Clojure similarly as you would teach Common Lisp. Start from functions definition over Control flow constructs to sequence ops (map, reduce ...) |
| 09:09 | Glenjamin | so you reckon people struggle because they get to the "i can do stuff, what should i build?" step sooner? |
| 09:09 | tbaldridge | Glenjamin: exactly. |
| 09:10 | TEttinger | I agree, definitely |
| 09:10 | Glenjamin | the idea has a certain smug appeal :) |
| 09:10 | clrnd | and SICP, it get's you to nothing to "write your own lazy eval champ!" in a few weeks |
| 09:10 | tbaldridge | and they quickly hit really hard problems (concurrency, web interop, talking to a DB, etc), and those take time to figure out. |
| 09:10 | clrnd | from* |
| 09:12 | CookedGr1phon | Can anyone think of a neat way to do a scoped require in clojure? What I want is when the block of code gets hit, it requires a namespace, loads if required, and then refers some functions but only within the scope of that one statement |
| 09:13 | tbaldridge | (require .... :as ~(gensym "ns_name")) |
| 09:13 | Glenjamin | CookedGr1phon: why? |
| 09:13 | tbaldridge | ^^ don't do that ;-) |
| 09:13 | CookedGr1phon | I'm trying to narrow down and coordinate when namespaces get loaded in order to get my startup as slick as possible, and namespaces are too granular |
| 09:14 | CookedGr1phon | waiting for everything to load (simply running through the namespace dependency tree) takes ~6 seconds, but I can get something on the screen and reacting in under 200ms if I only load what I need at the very start, and then load the rest in the background |
| 09:15 | CookedGr1phon | I can obviously make smaller namespaces, but then my code is horrible to follow |
| 09:15 | CookedGr1phon | so yeah, trying to find a way to get finer control over this |
| 09:16 | borkdude_ | does anyone have an example of Riemann instrumentation of a compojure app |
| 09:18 | clgv | CookedGr1phon: so you app has to be able to do meaningful stuff while the other parts are still loading? |
| 09:18 | CookedGr1phon | clgv: yeah on other threads |
| 09:18 | clgv | CookedGr1phon: require from multiple threads? have fun with that ;) |
| 09:19 | CookedGr1phon | heh, ideally I won't be requiring from multiple threads |
| 09:19 | CookedGr1phon | the code loading all happens in one thread, just in a strict order |
| 09:19 | CookedGr1phon | and then when the code is loaded, I let it go off and start doing useful work |
| 09:29 | julianleviston | jog my memory… find first in coll satisfying pred? not some, but … ? |
| 09:30 | julianleviston | just first filter? |
| 09:30 | Glenjamin | yeah |
| 09:30 | stuartsierra | or (some (fn [x] (when (pred x) x)) coll) |
| 09:31 | julianleviston | oh nevermind, http://stackoverflow.com/questions/10192602/return-first-item-in-a-map-list-sequence-that-satisfies-a-function-returning-tru says (some #(if (= % 1) %) '(3 4 1)) which works well... |
| 09:31 | julianleviston | stuartsierra: exactly! cool thanks.. Hey hi by the way. I loved your book! |
| 09:31 | julianleviston | oh no I got confused… I mean I loved component. |
| 09:32 | stuartsierra | julianleviston: thanks :) |
| 09:32 | julianleviston | stuartsierra: plus I really liked your last talk on it. |
| 09:32 | julianleviston | (inc stuartsierra) |
| 09:38 | clgv | lazybot seems to be on vacation |
| 09:39 | Glenjamin | (dec lazybot) |
| 09:45 | clgv | (lazybot) ; where is the irc metabot restarting lazybot? ;) |
| 09:45 | clgv | (send-off raynes restart lazybot) |
| 09:47 | bonsai_hk | quick show of hands: who is NOT into web programming |
| 09:48 | clgv | bonsai_hk: mostly algorithm dev |
| 09:48 | julianleviston | bonsai_hk: do you mean not only? |
| 09:48 | julianleviston | bonsai_hk: or not at all? |
| 09:48 | bonsai_hk | julianleviston: let's say your current focus for some definition of focus |
| 09:49 | bonsai_hk | clgv: like algorithmic trading? |
| 09:49 | tbaldridge | probably about 90% of my work is backend DB stuff, eventually it has a web API, but don't touch that much |
| 09:49 | clgv | bonsai_hk: no |
| 09:49 | clgv | bonsai_hk: http://blog.cognitect.com/blog/2014/10/24/analysis-of-the-state-of-clojure-and-clojurescript-survey-2014 |
| 09:49 | clgv | bonsai_hk: scroll down to "which domains ..." |
| 09:51 | bonsai_hk | clgv: I've seen the survey thanks but no IRC handles there to chat to :-) |
| 09:52 | bonsai_hk | tbaldridge: well is it the request - db lookup - response kind of backend? it would be web ish |
| 10:27 | luxbock | ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret) |
| 10:28 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 10:28 | luxbock | hmm |
| 10:29 | luxbock | is there a better way to do this? I'd like to get a vector/list of the expressions in the traversal order |
| 10:29 | justin_smith | &(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) |
| 10:29 | justin_smith | ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) |
| 10:29 | clojurebot | #<CompilerException java.lang.ClassNotFoundException: clojure.walk, compiling:(NO_SOURCE_PATH:0:0)> |
| 10:29 | justin_smith | ,(require 'clojure.walk) |
| 10:29 | clojurebot | nil |
| 10:29 | justin_smith | ,(let [ret (transient [])] (clojure.walk/prewalk (fn [x] (conj! ret x) x) '(let [x 123] (+ x 456))) (persistent! ret)) |
| 10:29 | clojurebot | [(let [x 123] (+ x 456)) let [x 123] x 123 ...] |
| 10:29 | clgv | luxbock: you are using transients wrongly anyway |
| 10:30 | luxbock | yeah? |
| 10:30 | clgv | you'd need to put the vector in an atom |
| 10:30 | hyPiRion | (inc clgv) |
| 10:30 | luxbock | ah right |
| 10:30 | justin_smith | luxbock: you need to use the return value of conj! |
| 10:30 | luxbock | first time using them |
| 10:30 | clgv | yes. for hashmaps this would certainly fail for larger input (> 16 elements?) |
| 10:30 | justin_smith | luxbock: or, even worse, *sometimes* your code doesn't work if you fail to use the return value |
| 10:30 | hyPiRion | clgv: 8 |
| 10:30 | luxbock | I was wondering if there was a way to do this without the transient |
| 10:30 | luxbock | or atoms |
| 10:31 | clgv | hyPiRion: ah 8 key+val pairs? |
| 10:31 | justin_smith | luxbock: sure, write your own walker, and carry two accumulators |
| 10:31 | hyPiRion | yus |
| 10:31 | hyPiRion | ,(let [t (transient {})] (dotimes [i 10] (assoc! t i i)) (count t)) |
| 10:31 | clojurebot | 8 |
| 10:31 | clgv | luxbock: not with clojure.walk |
| 10:32 | luxbock | alright, I think this looks a bit ugly but it's so much easier than writing my own walker that I'll just use an atom |
| 10:32 | clgv | luxbock: but you can write your own preorder traversal with apropriate value passing |
| 10:32 | clgv | it'll be just a recursive function after all |
| 10:33 | luxbock | right |
| 10:38 | darrenh | is there an idiomatic way to coerce something that may be a list of strings or a single string into a list? eg. (foo "bob") --> ["bob"], (foo ["bob" "fred"]) --> ["bob" "fred"] |
| 10:38 | llasram | darrenh: no, and in my experience wanting to do that is an anti-pattern |
| 10:39 | darrenh | This is to handle what ring does with multi-valued params |
| 10:39 | llasram | Ah |
| 10:39 | darrenh | I'd rather ring always returned a list |
| 10:39 | justin_smith | darrenh: one option would be a multimethod with implementations for string and list |
| 10:39 | llasram | Ok, yeah. So in this case you know ring will always yield a string or a vector, so you can just check that |
| 10:40 | justin_smith | multimethod may be overingeneered if you only get two types though |
| 10:40 | llasram | (checking generically for "any sort of sequential collection" is bizarrely more difficult) |
| 10:40 | justin_smith | ,(sequential? "hello") |
| 10:40 | clojurebot | false |
| 10:41 | darrenh | ah yes, I was thinking (flatten (merge [] "x")) |
| 10:41 | justin_smith | ,(map sequential? ["hello" () []]) |
| 10:41 | clojurebot | (false true true) |
| 10:41 | justin_smith | ,(merge [] "x") |
| 10:41 | clojurebot | ["x"] |
| 10:41 | llasram | ,(sequential? (java.util.ArrayList.)) |
| 10:41 | clojurebot | false |
| 10:41 | darrenh | ,(flatten (merge [] ["a" "b"])) |
| 10:41 | clojurebot | ("a" "b") |
| 10:41 | justin_smith | llasram: good point |
| 10:42 | justin_smith | darrenh: I have actually never seen merge used with [], why not into? |
| 10:42 | darrenh | ,(merge [] [:a :b]) |
| 10:42 | clojurebot | [[:a :b]] |
| 10:42 | TimMc | wait what |
| 10:42 | darrenh | ,(flatten (into [] "x")) |
| 10:42 | clojurebot | (\x) |
| 10:42 | darrenh | yeah, that didnt work :) |
| 10:43 | justin_smith | flatten is terrible |
| 10:43 | hyPiRion | sure, merge just does that strange conj thingy |
| 10:43 | TimMc | ~flatten |
| 10:43 | clojurebot | flatten is rarely the right answer. Suppose you need to use a list as your "base type", for example. Usually you only want to flatten a single level, and in that case you're better off with concat. Or, better still, use mapcat to produce a sequence that's shaped right to begin with. |
| 10:43 | hyPiRion | ,(conj {:a :b} {:c :d :e :f}) |
| 10:43 | clojurebot | {:c :d, :e :f, :a :b} |
| 10:43 | Glenjamin | proposal to remove flatten from core |
| 10:43 | justin_smith | hyPiRion: oh, of course, merge is just calling conj |
| 10:43 | justin_smith | ,(flatten {:a 0 :b 1}) |
| 10:43 | clojurebot | () |
| 10:43 | justin_smith | ,(flatten "hello") |
| 10:43 | clojurebot | () |
| 10:45 | clgv | darrenh: Most of the time you want (apply concat coll) instead of (flatten coll) |
| 10:46 | clgv | darrenh: It doesn't take too long until an implementation using `flatten`, will suprise you with unexpected output |
| 10:46 | justin_smith | clgv: well, his given usecase is that he might get {:key "val"} or {:key ["val1" "val2"]} from the ring api |
| 10:46 | hyPiRion | just wrap it in a list if you really need it |
| 10:46 | justin_smith | but a simple if is better than a flatten there (checking for vector?) |
| 10:46 | justin_smith | hyPiRion: well, the problem is that the API sometimes gives him a coll of strings, sometimes a string |
| 10:47 | darrenh | clearly the correct solution is to fix the ring api to be consistent at the expense of convenience ;) |
| 10:47 | justin_smith | darrenh: sometimes a coll sometimes a string is not convenience |
| 10:47 | justin_smith | not when you need to write code that uses the result |
| 10:48 | clgv | ah in that case.... darrenh: I usually have a utility function similar to (defn ->sequential [x] (if (sequential? x) x [x])) |
| 10:48 | darrenh | most query strings do not have multi-valued params, so returning a string most of the time is convenient.. most of the time |
| 10:49 | darrenh | clgv: thanks |
| 10:51 | darrenh | a lot of web frameworks have this 'surprising array when you expected a strign' issue |
| 10:51 | clgv | darrenh: often used in macro implementations that support lists and single values |
| 10:51 | clgv | darrenh: ha! try json rendering in "GNU R" - it maximises those kind of surprises... |
| 10:52 | justin_smith | darrenh: which leads to a conundrum if you want "principle of least surprise" - is the most surprising thing to offer a string sometimes, an array others, or to not provide that surpise like the others do? |
| 10:53 | darrenh | I'd go for consistency - it would confuse a new developer briefly, then they would learn the valuable lesson that query params can repeat, saving themselves much future pain |
| 10:54 | justin_smith | you mean consistency with everyone else, not consistency within the API |
| 10:54 | darrenh | consistency within the api: all query values are lists |
| 10:54 | justin_smith | ahh |
| 10:54 | justin_smith | :) |
| 10:54 | Glenjamin | a different access pattern for string vs seq is the only option that's unambiguous and still simple imo |
| 10:55 | kodumulo | On http://martintrojer.github.io/clojure/2013/07/07/coreasync-and-blocking-io/ it says that thread parking breaks the 1thread = 1 job "knot". When you park a thread does that mean that thread can do other work without spawning a new thread? |
| 10:55 | justin_smith | kodumulo: parking means your task no longer holds the thread |
| 10:56 | justin_smith | and the thread can go do other things |
| 10:56 | justin_smith | when your data is ready, some other thread will pick up the process where it left off |
| 10:56 | kodumulo | Ah so its not like the job *lives* in the thread. The job is independent and *uses* the thread when needed |
| 10:57 | justin_smith | kodumulo: right, or you could say the threads pick up jobs as they are ready to do work, and drops them as they park |
| 10:57 | julianleviston | kudumulo - core async threadparking uses a threadpool |
| 10:59 | kodumulo | Thats a brilliant concept. It kinda reminds me of a ruby fiber |
| 10:59 | justin_smith | kodumulo: the general concept is called "green threads" |
| 10:59 | kodumulo | ah |
| 11:00 | justin_smith | but in clojure it's a little different, because there are also multiple real threads |
| 11:00 | kodumulo | I thought green threads were just threads that didn't get their own cpu, like in ruby |
| 11:00 | julianleviston | justin_smith: unless you’re in cljs. ;) |
| 11:00 | ToxicFrog | justin_smith: "greenthreads" are specifically things that look like threads to code running in the interpreter but are all hosted in the same OS thread, unrelated to thread pools |
| 11:00 | Glenjamin | i also see it called 1:N threading |
| 11:00 | justin_smith | ToxicFrog: ahh, sorry |
| 11:00 | julianleviston | kodumulo: you probably don’t want to think about ruby threads. It’s a friggin nightmare. |
| 11:01 | kodumulo | julianleviston: one of the reasons I use clojure now in the first place ;) |
| 11:01 | Glenjamin | Fibers are the same/a similar system to this |
| 11:01 | kodumulo | and dependencies, rubygems is a nightmare as well |
| 11:01 | julianleviston | kodumulo: likewise ;-) the GIL … guh! |
| 11:01 | justin_smith | ToxicFrog: regardless, the same implementation issues that come up with green threads also come up with core.async style threads - you need your own threading logic in the vm |
| 11:01 | julianleviston | kodumulo: yeah, a whole bunch of things… |
| 11:02 | julianleviston | kodumulo: OOP is really just not very good for DRY. |
| 11:03 | justin_smith | ToxicFrog: is there a general term for this kind of mix of multiple real threads, with green-thread style pseudo-threading? |
| 11:04 | julianleviston | justin_smith: timesharing? |
| 11:04 | Glenjamin | ah, M:N model, that's what i was thinking of |
| 11:04 | justin_smith | aha! |
| 11:05 | justin_smith | Glenjamin: yeah, just found this as you said that http://en.wikipedia.org/wiki/Thread_%28computing%29#M:N_.28Hybrid_threading.29 |
| 11:08 | muller | is mapcat map followed by cat? |
| 11:08 | Glenjamin | concat, yes |
| 11:08 | justin_smith | $source mapcat |
| 11:08 | TimMc | There is no cat. |
| 11:08 | muller | yeah concat |
| 11:08 | Glenjamin | there is now! |
| 11:08 | slipset | while on the topic of core.async |
| 11:08 | llasram | (doc cat) |
| 11:09 | clojurebot | "([rf]); A transducer which concatenates the contents of each input, which must be a collection, into the reduction." |
| 11:09 | justin_smith | TimMc: I thought there was a cat transducer |
| 11:09 | TimMc | Oy, transducers. |
| 11:09 | slipset | the fact that the go-macro is implemented as a state-machine |
| 11:09 | justin_smith | (source mapcat) |
| 11:09 | Glenjamin | that docstring should really say "EAGER" on it massive letters |
| 11:09 | slipset | is that inherent to CSP, or does the idea stem from som other place? |
| 11:10 | TimMc | 𝑬𝑨𝑮𝑬𝑹 |
| 11:10 | justin_smith | slipset: I think CSP was first articulated in terms of state machines, it was a CS thing after all |
| 11:10 | muller | ,(mapcat reverse [[3 2 1 0] [6 5 4] [9 8 7]]) |
| 11:10 | slipset | justin_smith:hmm, I started reading the CSP book by Hoare, but sort of fell off before the state machine was mentioned. |
| 11:10 | clojurebot | (0 1 2 3 4 ...) |
| 11:10 | muller | ,(concat (map reverse [[3 2 1 0] [6 5 4] [9 8 7]])) |
| 11:10 | clojurebot | ((0 1 2 3) (4 5 6) (7 8 9)) |
| 11:11 | justin_smith | slipset: double checking that now |
| 11:11 | muller | not the same? |
| 11:11 | justin_smith | muller: apply concat |
| 11:11 | muller | what |
| 11:11 | slipset | I guess CSP mentions processes as state-machines, which makes sense. |
| 11:11 | justin_smith | ,(apply concat (map reverse [3 2 1 0] [6 5 4] 9 8 7]])) |
| 11:11 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]> |
| 11:11 | justin_smith | ,(apply concat (map reverse [3 2 1 0] [6 5 4] [9 8 7]])) |
| 11:11 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]> |
| 11:12 | justin_smith | ,(apply concat (map reverse [[3 2 1 0] [6 5 4] [9 8 7]])) |
| 11:12 | clojurebot | (0 1 2 3 4 ...) |
| 11:12 | muller | why do we need apply i don't get it |
| 11:12 | julianleviston | when the input is a collection instead of direct arguments |
| 11:12 | justin_smith | muller: map can only return one collection |
| 11:12 | Glenjamin | (doc concat) |
| 11:12 | clojurebot | "([] [x] [x y] [x y & zs]); Returns a lazy seq representing the concatenation of the elements in the supplied colls." |
| 11:12 | slipset | but the whole thing, which is nicely explained here http://hueypetersen.com/posts/2013/08/02/the-state-machines-of-core-async/ |
| 11:12 | justin_smith | muller: concat needs multiple args |
| 11:12 | TimMc | muller: I hand you [1 2 3 4 5]. Add them. |
| 11:13 | TimMc | (reduce is cheating :-P) |
| 11:13 | slipset | shows how the, I guess green thread like thingy in the go-macro is implemented as a state-machine |
| 11:13 | muller | ,(apply + [1 2 3 4 5]) |
| 11:13 | clojurebot | 15 |
| 11:13 | muller | ok :P |
| 11:13 | Glenjamin | ,((constantly 15) [1 2 3 4 5]) |
| 11:13 | clojurebot | 15 |
| 11:14 | muller | I misunderstood what concat does |
| 11:14 | justin_smith | Glenjamin: :P |
| 11:14 | Glenjamin | needs more than one testcase |
| 11:15 | justin_smith | slipset: I just double checked, by page 12 it is definitely talking about state machines http://www.usingcsp.com/cspbook.pdf |
| 11:15 | clgv | test.check ;) |
| 11:16 | slipset | justin_smith: yes, but that's sortof the vending machines state-machine |
| 11:16 | slipset | and that makes sense |
| 11:17 | slipset | but as I (akwardly) tried to formulate, my question is around how the go-macro is implemented |
| 11:17 | slipset | and the usage of a state-machine to "flatten" the callback hell. |
| 11:17 | justin_smith | slipset: I think I missed your followup while skimming the csp doc |
| 11:18 | kodumulo | in cider can you reload project dependencies from repl or do do you need to quit and start new session? |
| 11:18 | kodumulo | do you* |
| 11:18 | justin_smith | kodumulo: you can redefine functions or reload namespaces, but to change a dep version you need to restart the vm |
| 11:18 | kodumulo | justin_smith: thanks |
| 11:19 | kodumulo | everytime i cider-jack-in i feel like neo |
| 11:24 | muller | is there a difference between (1 2 3) and [1 2 3]? |
| 11:24 | clgv | muller: list vs vector |
| 11:24 | muller | ok |
| 11:25 | ToxicFrog | muller: [1 2 3] is a vector literal. (1 2 3) tries to call 1 with arguments 2 and 3 and evalutes to the result. '(1 2 3) is a list. |
| 11:25 | slipset | justin_smith:seems like c# await is implemented as a state-machine as well |
| 11:25 | slipset | https://www.simple-talk.com/dotnet/.net-tools/c-async-what-is-it,-and-how-does-it-work/ |
| 11:25 | justin_smith | slipset: yeah, a lot of things have state machines at the bottom, they are a very well understood abstraction |
| 11:25 | ToxicFrog | ,(map type [[1 2 3] '(1 2 3)]) |
| 11:25 | clojurebot | (clojure.lang.PersistentVector clojure.lang.PersistentList) |
| 11:26 | ToxicFrog | ,(type (1 2 3)) |
| 11:26 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 11:26 | muller | yeah I meant '(1 2 3) |
| 11:26 | TimMc | justin_smith: "I don't even see the parens anymore; all I see now is juxt, dosync, let." |
| 11:26 | julianleviston | muller: yeah, vectors and lists are different. |
| 11:26 | justin_smith | muller: most things that work with '(1 2 3) work with [1 2 3] also - usually what matters in clojure are the interfaces more than the concrete types |
| 11:26 | justin_smith | TimMc: heh |
| 11:27 | zerokarmaleft | whoever said that is going to betray everyone for a steak |
| 11:27 | TimMc | Err... I guess I meant that for kodumulo. |
| 11:27 | justin_smith | TimMc: I was about to say that |
| 11:27 | julianleviston | muller: vectors are fast to add to the end of, and to look up. Lists aren’t particularly. |
| 11:28 | kodumulo | TimMc: lol |
| 11:28 | justin_smith | TimMc: that's definitely true though, the parens disappear |
| 11:28 | muller | list is a singly linked list, and vector stores elements in sequence in the memory, like an array in C? |
| 11:28 | kodumulo | I (->) all the things so they do actually disappear ;) |
| 11:28 | Glenjamin | someone once pointed out i had 14 parens on the end of a line |
| 11:28 | julianleviston | muller: can I recommend you read clojure in small pieces? |
| 11:28 | Glenjamin | i hadn't noticed |
| 11:29 | justin_smith | muller: vector is more like a tree of arrays - it's complicated |
| 11:29 | justin_smith | muller: hyPiRion has a good series of blog posts about vector implementation if you really want to know the whole deal |
| 11:29 | muller | okay |
| 11:29 | julianleviston | muller: or, watch rich hickey’s talks on the persistent data structures. |
| 11:29 | Glenjamin | it's safe to say it acts much like an array, but is persistent |
| 11:29 | justin_smith | muller: http://hypirion.com/musings/understanding-persistent-vector-pt-1 |
| 11:29 | julianleviston | muller: http://daly.axiom-developer.org/clojure.pdf |
| 11:30 | muller | thanks |
| 11:30 | borkdude | I'm trying a query in the Riemann dashboard but I keep getting a parse error. My query is simply: '(service = "metri")' |
| 11:31 | julianleviston | muller: https://www.youtube.com/watch?v=ketJlzX-254 |
| 11:31 | Glenjamin | borkdude: i think there's a riemann irc channel |
| 11:31 | borkdude | I get invalid term \"metri\" |
| 11:31 | borkdude | Glenjamin thanks |
| 11:32 | muhuk | How come this isn't infinite recursion? https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L1478 |
| 11:32 | julianleviston | muller: coz it’s a call to the runtime. |
| 11:33 | hyPiRion | muller: the most important part to know for a person new to Clojure is that a vector acts like an immutable arraylist, yet is superfast for the operations you usually do on arrays/arraylists |
| 11:33 | julianleviston | muhuk: sorry… coz it’s a call to the runtime. |
| 11:33 | muhuk | justin_smith: isn't (keys map) (the 2nd) evaluated first? |
| 11:34 | julianleviston | muhuk: the java interop character calls the keys method on the runtime. |
| 11:34 | julianleviston | muhuk: that’s my understanding, anyway. |
| 11:34 | Glenjamin | i always find (. obj (method arg)) really weird |
| 11:35 | muhuk | julianleviston: what I see is it's calling the result of (keys map) on RT |
| 11:35 | Glenjamin | especially when (. obj method arg) does the same thing |
| 11:35 | julianleviston | muhuk: nah... |
| 11:35 | muhuk | I see |
| 11:35 | hyPiRion | muhuk: Think of it as (clojure.lang.RT/keys map) |
| 11:35 | julianleviston | muhuk: (. clojure.lang.RT (keys map)) means “send the keys message to RT with the arg map” |
| 11:35 | ToxicFrog | ...wow, that's a really unclear way of writing it. |
| 11:35 | muhuk | got it, thanks |
| 11:36 | julianleviston | ToxicFrog: and yet, it’s much easier than native java when you get used to it. |
| 11:36 | Glenjamin | ,[(. "a" (equals "a") (. "a" equals "a")] |
| 11:36 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: ]> |
| 11:36 | julianleviston | the . interop operator behaves more similarly to the threading macros really. |
| 11:36 | Glenjamin | oh, missed a paren |
| 11:36 | Glenjamin | ,[(. "a" (equals "a")) (. "a" equals "a")] |
| 11:36 | clojurebot | [true true] |
| 11:37 | Glenjamin | i find it very odd that those two do the same thing |
| 11:37 | TimMc | It only becomes important when you have a nullary method. |
| 11:37 | TimMc | and I guess a field with the same name :-P |
| 11:37 | Glenjamin | oh, the former is always a fn, but the latter can be a field? |
| 11:37 | ToxicFrog | julianleviston: no, I mean, it's much more unclear than either (. RT keys map) or (RT/keys map) |
| 11:38 | ToxicFrog | And AFAIK has the same semantiocs |
| 11:38 | julianleviston | ToxicFrog: k. |
| 11:38 | hyPiRion | let's try it out |
| 11:38 | hyPiRion | ,(clojure.lang.RT/keys {:a 1 :b 2}) |
| 11:38 | clojurebot | (:b :a) |
| 11:39 | TimMc | Glenjamin: As I understand it, yes. As long as there are no args. |
| 11:39 | justin_smith | ,(Math/PI) ; more interop "fun" |
| 11:39 | clojurebot | 3.141592653589793 |
| 11:39 | TimMc | (.foo obj) could be a field access or method call. |
| 11:39 | ToxicFrog | hyPiRion: there we go then. |
| 11:39 | TimMc | justin_smith: :-( |
| 11:39 | Glenjamin | ,(. (first {:a 1}) key) |
| 11:39 | clojurebot | :a |
| 11:39 | Glenjamin | erm, that's not what i meant to do |
| 11:39 | Glenjamin | but it worked :s |
| 11:40 | Glenjamin | to the local repl! |
| 11:40 | ToxicFrog | (. obj method (a b c ...)) I could see, maybe, but (. obj (method a b c ...)) just rubs me the wrong way. |
| 11:40 | hyPiRion | justin_smith: whut |
| 11:40 | hyPiRion | ,Math/PI |
| 11:40 | clojurebot | 3.141592653589793 |
| 11:40 | hyPiRion | ok, that's a tad weird |
| 11:41 | Glenjamin | ,[(. (first {:a 1}) getKey) (. (first {:a 1}) (getKey))] |
| 11:41 | clojurebot | [:a :a] |
| 11:41 | clgv | ,(read-string "(Math/PI)") |
| 11:41 | clojurebot | (Math/PI) |
| 11:41 | clgv | ,(macroexpand-1 (read-string "(Math/PI)")) |
| 11:41 | clojurebot | (. Math PI) |
| 11:42 | clgv | ,(macroexpand-1 (read-string "Math/PI")) |
| 11:42 | clojurebot | Math/PI |
| 11:43 | Bronsa | clgv: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Compiler.java#L6893-L6900 |
| 11:46 | clgv | Bronsa: alright. |
| 11:48 | justin_smith | hyPiRion: I think it is backward compatibility or something? |
| 11:51 | stuartsierra | yes, there were several variant syntaxes for the . special form before the .method and Foo/static syntax were introduced. |
| 11:52 | stuartsierra | And (.field object) still works on Clojure JVM despite the addition of (.-field object) |
| 11:56 | clgv | I always thought (.-field object) is CLJS only... |
| 12:10 | justin_smith | clgv: well, java classes are much less likely to have fields you use directly (as opposed to an accessor method) |
| 12:12 | clgv | justin_smith: what is that referring to? |
| 12:13 | hyPiRion | TimMc: how's that Swearjure transpiler going, btw? |
| 12:13 | julianleviston | clgv: interop |
| 12:14 | clgv | julianleviston: that is surprising |
| 12:16 | TimMc | hyPiRion: On hold since forever. Function-calling is actually tricky -- you have to know whether it's a call like (:foo {}) or a call to a swearjure-transpiled fn. |
| 12:17 | Glenjamin | convert to AST in between? |
| 12:17 | TimMc | and sometimes the latter is derived from an expression like (if x fn1 fn2). |
| 12:18 | TimMc | Glenjamin: I may just say that you can never call a swearjure-transpiled fn, but have to use a form like (fncall f a0 a1 a2) |
| 12:18 | Glenjamin | that seems simple enough |
| 12:19 | TimMc | THat was the only technical stumbling block I ran into. The main problem is that I have better things to do. :-P |
| 12:19 | clgv | TimMc: damn that's a pity. so swearjure is never going to see broad application in industry ... |
| 12:19 | Glenjamin | in other news, i got turned down for a remote UK clojure job today in favour of someone younger and cheaper >.< |
| 12:19 | TimMc | clgv: Pull requests welcome! |
| 12:19 | clgv | TimMc: :P |
| 12:19 | zerokarmaleft | TimMc: what would a swearjure conference be called? |
| 12:20 | clgv | zerokarmaleft: pub brawl? |
| 12:20 | TimMc | zerokarmaleft: Something unprintable, I'm sure. |
| 12:20 | justin_smith | our local clojure meetup is clojerks, so I imagine swearjerks would work nicely for swearjure |
| 12:20 | TimMc | #<conj> |
| 12:21 | justin_smith | oh wait, what's swearjure for conj? |
| 12:21 | hyPiRion | TimMc: asking because http://hypirion.com/musings/swearjure-is-turing-complete |
| 12:21 | hyPiRion | justin_smith: it's just `[~@xs ~x] |
| 12:21 | zerokarmaleft | hah, perfect |
| 12:22 | justin_smith | so, it's "the swearjure `[~@xs ~x]" of course |
| 12:22 | justin_smith | the unpronouncability is a feature |
| 12:22 | hyPiRion | heh |
| 12:22 | hyPiRion | The conj function is something like |
| 12:23 | TimMc | hyPiRion: Oh fuck, replacing the binding form! Brilliant! |
| 12:23 | justin_smith | "the swearjure syntax-quote vec-literal unquote deref xs unquote x endvec" |
| 12:23 | hyPiRion | justin_smith: #([`[~@% ~(`[~@%&](+))]](+)) I think |
| 12:24 | justin_smith | oh wow |
| 12:24 | julianleviston | Glenjamin: how old are you? If I’m allowed to ask |
| 12:24 | Glenjamin | 27 :) |
| 12:24 | justin_smith | I won't try to spell out the pronunciation of that |
| 12:24 | julianleviston | Glenjamin: waaaaaa? that’s just weird. |
| 12:24 | hyPiRion | TimMc: yeah, it's awesome. You can actually make sensible programs with Swearjure now :D |
| 12:24 | Glenjamin | well, the other guy was probably a fresh grad without 5 years of building software experience, hence cheaper |
| 12:25 | julianleviston | Glenjamin: oh well, I guess they’ll pay. LOL. |
| 12:25 | julianleviston | Glenjamin: Even 5 years is not very much. |
| 12:26 | Glenjamin | depends where & what you worked on :) |
| 12:26 | julianleviston | Glenjamin: I’m not convinced of that. |
| 12:26 | Glenjamin | well, not every 5 years of experience is the same |
| 12:26 | julianleviston | Glenjamin: but yes, the only thing you can really say about age is that it provides opportunity... |
| 12:27 | julianleviston | Glenjamin: no guarantees the person is going to have used it wisely or not. |
| 12:27 | Glenjamin | it's possible to have less overall experience after 20 than it is after 5, but obvisouly the theoretical maximum after 20 years is higher |
| 12:27 | TimMc | hyPiRion: So we can do the ski calculus now? |
| 12:27 | hyPiRion | TimMc: yes |
| 12:27 | julianleviston | Glenjamin: of course, this disregards all the things that actually matter, too. ;-) |
| 12:27 | TimMc | oop, just go to that part of the blog post |
| 12:27 | Glenjamin | anyway, the guy was probably demonstrably cheaper, and that was due to lack of experience - either in software or negotiation |
| 12:27 | TimMc | *got |
| 12:28 | julianleviston | Glenjamin: yeah, like I say, though, they’ll pay ;-) |
| 12:29 | julianleviston | Glenjamin: I wonder how old he is? Less than 5 years in a lisp is like… do they actually understand stuff? lol. Like… I think it took the last junior I taught about 4 years to start understangin map and don’t even talk about reduce. |
| 12:30 | clgv | hyPiRion: isnt the usage of x,y,z cheating? ;) |
| 12:30 | julianleviston | Glenjamin: I mean understanding when to use it and whatnot. <shrug> ah well... |
| 12:35 | TimMc | clgv: It's equivalent to $,+,- |
| 12:35 | TimMc | Well, no... ++, --, +- |
| 12:36 | clgv | TimMc: ok ;) |
| 12:38 | clgv | TimMc: hyPiRion: since floats in our cpus are finite you should be able to emulate them as well, right? |
| 12:39 | clgv | ah well, only if / would return doubles instead of ratios... damn |
| 12:57 | mikerod | Why would I be getting issues related to lein-cljsbuild when I do not have it configured as part of my leiningen project? |
| 12:57 | mikerod | "WARNING: no :cljsbuild entry found in project definition." these sorts of issues |
| 12:57 | mikerod | and then subsequently, I get failures for the more recent version of cljs now requiring Java 7 I guess |
| 12:57 | muller | julianleviston what.. map is easy.. reduce, granted, is a bit harder to grasp for newbies |
| 12:57 | mikerod | I don't need cljs for my particular workflow right now. It just started failing within the last day or so when I haven't added a dependency of any sort. |
| 12:58 | mikerod | "You're using [lein-cljsbuild "1.0.4"], which is known to work well with ClojureScript 0.0-2197 - *." I do not even see a lein-cljsbuild in my `lein deps :tree` or `lein deps :plugin-tree` |
| 12:58 | mikerod | So I'm wondering if something is implicitly going on with leiningen now. |
| 13:15 | vas | hello, is somnium the preferred way to connect to mongodb with clojure ^.^ ? |
| 13:16 | {blake} | vas: I use monger. |
| 13:16 | agarman | I use the java driver directly |
| 13:16 | vas | {blake}: thanks thanks. |
| 13:17 | {blake} | vas: No problem. |
| 13:18 | agarman | been awhile since I was in there, but also using monger |
| 13:20 | {blake} | If I were doing it again now, I might use JDBC directly! Not that there's anything wrong with Monger, just not sure what I got from using it. |
| 13:21 | agarman | monger mostly converts mongo data structures <-> clojure data structures |
| 13:22 | agarman | and doesn't make a new DSL to hide mongos... |
| 13:22 | {blake} | Well, I notice using JDBC directly (for mssql) it returns thing as a map. 'bout all I need. |
| 13:22 | {blake} | Yeah, I'm...iffy...on the DSL thing. |
| 13:23 | {blake} | I used to be pro-DSL until I started using Ruby hardcore. =P |
| 13:26 | vas | agarman: so you prefer to use the driver directly currently? how would I go about that? |
| 13:31 | agarman | @vas monger was fine...it turns Mongo's command language into a DSL written in Clojure functions and converts stuff into and out of Mongo for you. |
| 13:32 | agarman | @vas I'd probably start with the Java driver today. I'm not big for including a lot of little, simple libraries in my projects. |
| 13:34 | agarman | @vas though Monger only adds transitively adds two deps, which isn't so bad |
| 13:35 | vas | agarman: yeah, simplicity is :key. maybe i will start with monger then until i get the hang of things. thank you for your words |
| 13:57 | vas | does anyone use any templating for CSS, such as jade or haml? |
| 14:04 | {blake} | vas: Under Ruby, I have. In Clojure, I've just used Hiccup. |
| 14:04 | {blake} | Althought that's not CSS, so never mind. =P |
| 14:05 | vas | {blake}: selectors and stuff, yeah. i don't mind playing css-ninja with the actual files, but i do kinda miss the elegance of jade, for example. |
| 14:06 | {blake} | This might be instructive: http://blog.getprismatic.com/bringing-functional-to-the-frontend-clojure-clojurescript-for-the-web/ |
| 14:13 | vas | {blake}: you're the best. that link appears to be just what i needs. |
| 14:13 | {blake} | vas: Terrific! |
| 14:25 | vas | general question: i am returning a list '({:tag :div, :attrs {:id thangID}}) ... i want to evaluate thangID before returning the list, but using the ~ operator just returns (clojure.core/unquote thangID) instead of evaluating... any suggestions? |
| 14:27 | muller | why do I get a list in here? |
| 14:27 | {blake} | vas: Wouldn't that be... (thangID)? |
| 14:27 | muller | ,(map reverse [[1 2 3] [4 5 6]] |
| 14:27 | {blake} | What do you mean by "evaluate"? |
| 14:27 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 14:27 | muller | no |
| 14:27 | muller | ,(mapcat reverse [[1 2 3] [4 5 6]]) |
| 14:27 | clojurebot | (3 2 1 6 5 ...) |
| 14:27 | muller | why a list and not a vector? |
| 14:28 | muller | ,(map reverse [[1 2 3] [4 5 6]]) |
| 14:28 | clojurebot | ((3 2 1) (6 5 4)) |
| 14:28 | {blake} | muller: It's my understanding that, generally, functions use the structure that works best for their operations. |
| 14:28 | {blake} | So changing from one type to another is pretty usual. |
| 14:29 | muller | but isn't that what this code is doing? it changes the type from vector of vectors to list of lists |
| 14:29 | muller | oh sorry, I've read that as unusual |
| 14:29 | muller | reverse seems to be the culprit |
| 14:30 | muller | ,(reverse [1 2 3]) |
| 14:30 | clojurebot | (3 2 1) |
| 14:30 | {blake} | muller: Map is building a list by concatenating items, I think. Which is easiest done in a list. |
| 14:30 | {blake} | ,(map inc [1 2 3]) |
| 14:30 | clojurebot | (2 3 4) |
| 14:30 | muller | oh map always returns a list |
| 14:30 | {blake} | ,(mapv reverse [[1 2 3][4 5 6]]) |
| 14:30 | hyPiRion | map is lazy, which is why you get back a seq |
| 14:30 | clojurebot | [(3 2 1) (6 5 4)] |
| 14:30 | ianhedoesit | ,(rseq [[1 2 3] [4 5 6]]) |
| 14:30 | clojurebot | ([4 5 6] [1 2 3]) |
| 14:30 | hyPiRion | Also, if you know your input is always going to be a vector, use rseq |
| 14:31 | ianhedoesit | hey, I just did that! :) |
| 14:31 | hyPiRion | ianhedoesit: yeah, you beat me to it :) |
| 14:32 | muller | that's doesn't do the same thing |
| 14:32 | aperiodi1 | vas: your immediate problem is that ~ only works inside of `, not '. but why not just do (list {:tag :div, ...}) if you really want a list |
| 14:33 | muller | it is reversing outter vector, i am reversing inner vectors |
| 14:33 | ianhedoesit | ,(into [] (mapcat reverse [[1 2 3] [4 5 6]])) |
| 14:33 | clojurebot | [3 2 1 6 5 ...] |
| 14:36 | muller | ,(into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) |
| 14:36 | clojurebot | [[3 2 1] [6 5 4]] |
| 14:36 | muller | anything better? |
| 14:36 | muller | is there a map/reverse equivalent that keeps the original data structure |
| 14:37 | vas | aperiodic: thanks. (list) is much easier to play with. |
| 14:37 | jackhill | muller: I don't know, but I'm curious about why you want to keep the original structure. |
| 14:39 | {blake} | muller: Are there many things at all in Clojure that preserve data structures, I wonder. |
| 14:39 | {blake} | I mean, to preserve it, you sort of have to know what it is, don't you? |
| 14:40 | muller | jackhill I am just learning now. but in real code I would want to keep it a vector, because, pressumably, I picked vector over a list or sequence it for a reaswon, rather than randomly |
| 14:41 | jackhill | muller: ah. I wonder if I need to start doing that. |
| 14:41 | vas | aperiodic: excellent. got to the bottom of my issue with your insightful catalyst. gracia |
| 14:42 | muller | {blake} yes |
| 14:42 | aperiodic | vas: glad it helped! quoting is tricky and generally unnecessary outside of writing macros, which is very rarely called for |
| 14:43 | {blake} | muller: Well, having to know about the structure places a lot of limitations on how general you can make your code. If it's important to you, you could make code that did so, at least for your specific cases. |
| 14:43 | muller | so say I wanted to implement a map equivalent that kept the original data structure. how would I go about it? would I have to hardcode the types in the function, or can i somehow have each function per type |
| 14:43 | muller | s/each/one |
| 14:43 | {blake} | muller: |
| 14:43 | ianhedoesit | muller: I think you should really think about why you think you need to do that. |
| 14:44 | {blake} | muller: I'm a relative noob myself, and I used to worry about the same thing. Having actually coded in Clojure for a while, it hasn't really been an issue. |
| 14:45 | {blake} | If I need a specific type, I'll use an "into {}" or "into []" or whatever on the return value of whatever's changing my type. |
| 14:45 | muller | ianhedoesit because I picked certain data structure (be it a vector, list or something else) because of the properties it has. and I want to keep it that type |
| 14:45 | ianhedoesit | I understand the difference between a list and a vector in terms of performance, but Clojure will typically decide what's best for you anyway, as far as I understand it. |
| 14:46 | {blake} | When you get down to it, it's a sort of premature optimization. |
| 14:46 | muller | ianhedoesit but it doesn't do that, it always returns sequence. even when it is not the best type |
| 14:46 | ianhedoesit | how do you know |
| 14:47 | ianhedoesit | I mean how do you know that is not ideal? |
| 14:47 | muller | i was told that in here a couple of minutes ago |
| 14:47 | muller | blake I don' think it is premature optimizatio to pick (and stick to) appropriate data structure |
| 14:47 | {blake} | muller: I think map returns sequence precisely because it's the best option. |
| 14:48 | muller | why is it the best option? |
| 14:48 | ianhedoesit | for one it's a lazy seq, so that's obviously better than realizing any data structure every time. |
| 14:49 | {blake} | muller: That is a big question. But you're going in to this with assumptions you've carried over, presumably from other languages. |
| 14:49 | {blake} | And again, I did the same thing. I finally just gave up those notions and found the issue more-or-less vanished. |
| 14:50 | muller | if i am processing the list once what advanage do i get from laziness? |
| 14:51 | muller | ian I am not. I just want to write clear code. (into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) could be clearer |
| 14:52 | muller | so my question still remains, what would be clojure's way of writing a map like that, that doesn't return sequence but whatever datastructure caller passed |
| 14:52 | raspasov | muller: what are you trying to do? |
| 14:52 | raspasov | make this nicer? (into [] (map #(into [] (reverse %)) [[1 2 3] [4 5 6]])) |
| 14:53 | muller | raspasov I want a map equivalent that doesn't return a sequence but whatever type it was passed |
| 14:53 | muller | how would I write it? |
| 14:53 | tbaldridge | transducers can do that |
| 14:53 | muller | ok googling |
| 14:54 | tbaldridge | (one sec while I construct an example) |
| 14:54 | {blake} | tbaldridge: Ooh, cool. |
| 14:55 | bucketh3ad | to relevant parties, why not: (vec (map (comp vec reverse) [[1 2 3] [4 5 6]])) ? |
| 14:55 | raspasov | muller: when you say whatever type - is that limited to maps, vectors, sets, LazySeqs, etc usual suspects in Clojure? |
| 14:56 | ianhedoesit | ,(mapv (comp vec reverse) [[1 2 3] [4 5 6]]) |
| 14:56 | clojurebot | [[3 2 1] [6 5 4]] |
| 14:56 | bucketh3ad | Mmm. even purdier. |
| 14:56 | ianhedoesit | :) |
| 14:56 | muller | raspasov that would be enough. but im curious if we could make it extensible too, so that you could extend it for other data structures |
| 14:57 | tbaldridge | yeah, what ianhedoesit said, that's pretty clean |
| 14:57 | raspasov | do look into transducers like tbaldridge says, it can make the transformation in one step I believe, without generating intermediary lazy seqs |
| 14:57 | justin_smith | bucketh3ad: one better: (mapv (comp vec rseq) [[1 2 3] [4 5 6]]) |
| 14:57 | justin_smith | rseq is faster if you know the arg is a vec |
| 14:58 | tbaldridge | you can also make into generic via empty: ,(let [coll [1 2 3]] (into (empty coll) (map inc coll))) |
| 14:58 | {blake} | muller: Sure. Though obviously your new routines have to have someway to construct the final output of previously unknown types. |
| 14:58 | muller | that is much cleaner yeah |
| 14:58 | ianhedoesit | I recommended rseq earlier and I already forgot. |
| 14:58 | justin_smith | haha |
| 14:59 | muller | {blake} why? they have a function that transforms the elements. and you write a new function per type that represents a data structure |
| 14:59 | {blake} | ianhedoesit: I didn't! I'd never heard of rseq before you mentioned it. So, thanks! |
| 15:00 | {blake} | muller: Right, that's what I mean: You need a new function per type. Look, you either transform it yourself after, or you have your routine make that transformation for you, right? |
| 15:00 | muller | yeah |
| 15:01 | {blake} | muller: If you want to preserve structures all-the-way-down, you'd pretty much have to rewrite Clojure's basic elements to do so. |
| 15:01 | {blake} | At least I think so. Y'all can correct me if I'm wrong. |
| 15:02 | muller | I don't know what you mean by Clojure's basic elements |
| 15:02 | tbaldridge | that's pretty much what transducers allow you to do, write algorithms without worrying about input or output types |
| 15:02 | justin_smith | (inc tbaldridge) |
| 15:02 | raspasov | here is the transducer version (defn transform-into-self [xf coll] (into (empty coll) xf coll)) |
| 15:02 | raspasov | and use it (transform-into-self (map inc) [1 2 3]) |
| 15:02 | tbaldridge | ,(into [] (map inc) [1 2 3]) ;; no seqs were created by this code |
| 15:02 | clojurebot | [2 3 4] |
| 15:03 | muller | I would like to write this myself for practice and learning. can I write a map that dispatches on the type of the second argument (type that we are mapping over) |
| 15:03 | vas | thanks everyone for being kind and awesome. have a good breakfast/lunch/dinner when you do! (= |
| 15:04 | justin_smith | muller: you could. It will be easier if you use transducers. I think people use the name fmap for this function sometimes? |
| 15:04 | raspasov | muller: just a note, most likely you need 1.7 alphas to have transducers |
| 15:04 | raspasov | out of the box |
| 15:04 | muller | do I have to hardcore the types in one function definition, or can I separate definitions, one per type |
| 15:04 | muller | hardcode :) |
| 15:04 | justin_smith | oh yeah, 1.7 is not out of alpha yet, and you need 1.7 for transducing |
| 15:04 | {blake} | tbaldridge: Wait, what? How is that possible? |
| 15:05 | {blake} | tbaldridge: Doesn't (map inc) make a sequence? What sorcery is this?! |
| 15:05 | justin_smith | muller: third option is create the right type using one function, regardless of the type of the input |
| 15:05 | arrdem | {blake}: transducer magic |
| 15:05 | justin_smith | muller: without hardcoding types |
| 15:06 | {blake} | arrdem: My God, it's like a thermos! It keeps the hot hot, and the cool cool! But how does it know?! |
| 15:06 | justin_smith | the asterix on "regardless of the type of the input" being the type would need to work with the protocols underlying empty / into |
| 15:06 | tbaldridge | {blake}: no, (map inc) creates a transducer, so it looks something like this (once it all executes), (.reduce [1 2 3] (comp conj (map inc)) []) |
| 15:07 | {blake} | tbaldridge: Ahhhhh. That's kind of awesome. So this is in 1.7, though, right? Us <=1.6 types are still making seqs and whatnot. |
| 15:08 | tbaldridge | yes sadly, but 1.7 is pretty stable ;-) |
| 15:09 | {blake} | tbaldridge: Well, thank you for that example. I'd sort of grasped that transducers worked that way, but that's a simple and clear demonstration of their power. |
| 15:10 | muller | so I would use defmulti and defmethod for this? to write a function that dispatches on the type of some argument |
| 15:10 | raspasov | {blake}: the even cooler part is that you can "attach" transducer transforms to channels :) |
| 15:10 | tbaldridge | muller: since you're only using a single dispatch, protocols are probably what you want |
| 15:11 | {blake} | raspasov: I...can't even. |
| 15:11 | muller | tbaldridge ok cool |
| 15:11 | tbaldridge | {blake}: right, tansducers decomplect (*ducks*) the three things in a normal lazy seq transform: a) iterating the source, b) the transformation, c) the output type. Each one of those can be tweeked with transducers |
| 15:12 | raspasov | if you (def x (chan 1 (map inc))) |
| 15:12 | raspasov | , (>!! x 1) |
| 15:12 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: >!! in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 15:12 | raspasov | you get (<!! x) |
| 15:12 | raspasov | 2 |
| 15:12 | {blake} | tbaldridge: And we get that for free? Backwardly compatible, no performance hit... |
| 15:13 | {blake} | raspasov: Dude. |
| 15:13 | raspasov | but then you have to make sure everything that gets through the channel is a number, otherwise there will be exception (you can supple an optional exception handler) |
| 15:13 | raspasov | supply* |
| 15:13 | tbaldridge | the performance is actually better (due to less memory allocation), but at the cost of having to rewrite your code a bit. Notice how we're doing (map inc) not (map inc coll) |
| 15:14 | TimMc | It only costs one arity. :-P |
| 15:14 | michaelr` | hi |
| 15:14 | noonian | but the old version of map is still there so you can do it incrementally |
| 15:14 | noonian | old arity I should say |
| 15:14 | {blake} | raspasov: I would imagine. But still cool. |
| 15:15 | ianhedoesit | raspasov: why do you need to map inc and not just inc? |
| 15:15 | tbaldridge | TimMc: the first arity is free :-P |
| 15:15 | justin_smith | haha |
| 15:15 | ianhedoesit | (I don't know anything about channels or anything) |
| 15:16 | muller | noonian how do you pick between old and new version of map? |
| 15:16 | raspasov | ianhedoesit: everyone asks that :) it's like you're "mapping" over what passes through the channel, and because inc (I guess) does not have transducer arity? tbaldridge is that right? |
| 15:16 | michaelr` | my application will be in clojurescript with the server side API handled by compojure delegating to liberator, now i've used secretary for routing in clojurescript before. i wonder whether there is any upside to using bidi instead and whether there is any real use case to push it between compojure and liberator as well? |
| 15:16 | justin_smith | ianhedoesit: inc works on numbers, he wants inc to be applied to every number that comes from some source of data |
| 15:16 | noonian | muller: if you're using 1.7 you will have the new version, otherwise you have the old version |
| 15:16 | noonian | ,(map inc) |
| 15:16 | clojurebot | #<core$map$fn__4507 clojure.core$map$fn__4507@7b908768> |
| 15:16 | muller | hmm |
| 15:16 | noonian | guess clojurebot is using 1.7 lol |
| 15:17 | tbaldridge | ianhedoesit: right, what channels need are transducer functions which deal with streams of values. So you can also do stuff like this with channels |
| 15:17 | muller | if i got it right (map inc) calls a different function than (map inc x)? |
| 15:17 | tbaldridge | (def a (chan (comp (partition-all 2) (map inc)))) |
| 15:17 | ianhedoesit | that's what I figured, I just thought maybe channels could just take any function |
| 15:17 | tbaldridge | That'll increment numbers, and then partition them, |
| 15:17 | ianhedoesit | I don't know how data is passed around with channels or anything about them |
| 15:17 | {blake} | muller: Sorta. Multiple arities are described in the same function declaration. |
| 15:17 | raspasov | muller: yes, different arity of the same fn |
| 15:17 | ianhedoesit | ,(map inc 1) |
| 15:17 | clojurebot | #<IllegalArgumentException java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.lang.Long> |
| 15:17 | muller | ok it executes different code |
| 15:18 | muller | cool |
| 15:18 | noonian | muller: (map inc) returns a 'transducer' which you can then apply to a collection using the new transduce or sequence functions (sequence isn't actually new). (map inc [1 2 3]) actually applies the function and returns a new collection immediatly |
| 15:18 | ianhedoesit | ,((map inc) 1) |
| 15:18 | clojurebot | #<core$map$fn__4507$fn__4508 clojure.core$map$fn__4507$fn__4508@7ebb051c> |
| 15:18 | ianhedoesit | oh okay |
| 15:18 | justin_smith | ianhedoesit: by taking a transducer to apply to the channel, instead of a function to map across the channel, there is the added flexibility that the transducer could be a reduction (ie. summing all numbers to come in on the channel) |
| 15:19 | ianhedoesit | ,(((map inc) 1) 1) |
| 15:19 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 15:19 | tbaldridge | ,(((map inc) conj) [] 1) |
| 15:19 | clojurebot | [2] |
| 15:19 | ianhedoesit | justin_smith: okay, neat. |
| 15:19 | tbaldridge | ianhedoesit: thats what you want ^^ |
| 15:19 | muller | noonian (map inc [1 2 3]) returns a sequence, like now, yes? |
| 15:19 | ianhedoesit | tbaldridge: lol thanks, yeah |
| 15:19 | muller | like before rather |
| 15:19 | noonian | muller: yes, the semantics for the other arities of map are the same as always |
| 15:20 | noonian | ,(map inc [1 2 3]) |
| 15:20 | clojurebot | (2 3 4) |
| 15:20 | noonian | ,(sequence (map inc) [1 2 3]) |
| 15:20 | clojurebot | (2 3 4) |
| 15:20 | noonian | (sequence (comp (map inc) (map (partial * 10)) [1 2 3]) |
| 15:20 | noonian | ,(sequence (comp (map inc) (map (partial * 10)) [1 2 3]) |
| 15:20 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 15:20 | noonian | ,(sequence (comp (map inc) (map (partial * 10))) [1 2 3]) |
| 15:20 | clojurebot | (20 30 40) |
| 15:21 | ianhedoesit | "magic" |
| 15:21 | muller | just wondering if I understand sequences. if we assign the result of (map inc collection) to a variable nothing is computer? until we start pulling values the from resulting seqeuence |
| 15:22 | muller | computed |
| 15:22 | ianhedoesit | nothing is computer |
| 15:22 | justin_smith | muller: yes, map is lazy |
| 15:22 | {blake} | impossible is nothing |
| 15:22 | justin_smith | muller: not all sequences are lazy, but lazy-seq (which map creates) is |
| 15:23 | ianhedoesit | is there any timeline or ETA for a "stable" Clojure 1.7? |
| 15:23 | muller | can I skip some values in a lazy-seq |
| 15:23 | muller | (and skip computing those values) |
| 15:23 | justin_smith | muller: no, they must be realized in order |
| 15:24 | muller | ,(def x (map print [1 2 3])) |
| 15:24 | clojurebot | #'sandbox/x |
| 15:24 | muller | ,x |
| 15:24 | clojurebot | (123nil nil nil) |
| 15:24 | justin_smith | ,x |
| 15:24 | clojurebot | (nil nil nil) |
| 15:25 | TimMc | justin_smith: Map is *sort of* lazy. |
| 15:26 | muller | why sort of |
| 15:26 | l3dx | after connecting cider to a repl (or using jack-in) the repl buffer doesn't show up. any suggestions? |
| 15:26 | TimMc | ,(def ch (map println (range))) |
| 15:26 | clojurebot | #'sandbox/ch |
| 15:26 | TimMc | ,(def ch (first (map println (range)))) |
| 15:26 | clojurebot | 0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n#'sandbox/ch |
| 15:26 | muller | why does it compute all values? |
| 15:27 | TimMc | Chunked sequences. |
| 15:27 | TimMc | "Lazy" means "it probably won't do any computation, and it definitely won't do all of it, but it might do something in the middle." |
| 15:28 | TimMc | (range) emits a sequence that is realized in chunks of 32 at a time; map respects that and computes each of those chunks as a unit. |
| 15:28 | muller | oh |
| 15:28 | TimMc | If you're doing side-effecty stuff in there, you might get surprised. |
| 15:28 | muller | does (range) retur n lazy-seq or something else |
| 15:29 | TimMc | &(class (range)) |
| 15:29 | TimMc | ,(class (range)) |
| 15:29 | clojurebot | clojure.lang.LazySeq |
| 15:30 | {blake} | ,(type (range)) |
| 15:30 | clojurebot | clojure.lang.LazySeq |
| 15:30 | {blake} | huh |
| 15:30 | TimMc | ,(class (seq (range))) |
| 15:30 | clojurebot | clojure.lang.ChunkedCons |
| 15:32 | justin_smith | TimMc: but the specific answer for "will map do anything if I don't use the result" is the same - or is there some datatype that messes with that too? |
| 15:32 | muller | intermediate sequence won't be created in here right? (map f (map g (range)))) |
| 15:33 | justin_smith | muller: it will, and that is part of why we have transducers now |
| 15:33 | justin_smith | muller: because (comp (map g) (map f)) doesn't create the extra seq that your version does |
| 15:35 | TimMc | justin_smith: Mmmm... I could make one, I think. |
| 15:36 | amalloy | muller: it will be created, but not realized all at once |
| 15:36 | justin_smith | TimMc: I'd be interested to see that (and even more interested to see a sane reason that one would be needed :)) |
| 15:37 | TimMc | justin_smith: I don't think I can make something that will involve calling f in (map f c), but if realizing c involves side-effects, then I can make those happen. |
| 15:38 | TimMc | Mmm, no, not even that I think. |
| 15:44 | csd_ | Have any of you experienced a bug in Cider where it seems to temporarily loose the ability to create an nrepl session? |
| 15:44 | amalloy | TimMc: yeah, i think that's impossible. map just returns (lazy-seq ...) before it does any work, so nothing will happen until you seq the result |
| 15:44 | csd_ | lose* |
| 15:47 | csd_ | it would appear that the solution is to do cider-jack-in a second time, while the buffer for the first attempt is still open |
| 15:47 | amalloy | ,(read-string "#;") |
| 15:47 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 15:48 | justin_smith | csd_: weird |
| 15:48 | amalloy | i was surprised this returned EOF rather than "no dispatch macro for ;" |
| 15:49 | Bronsa | amalloy: tagged literals can have spaces between # and the tag |
| 15:49 | Bronsa | ,(read-string "#;\nfoo[]") |
| 15:49 | clojurebot | #<RuntimeException java.lang.RuntimeException: No reader function for tag foo> |
| 15:50 | justin_smith | ,(read-string "#;\n_invalid []") |
| 15:50 | clojurebot | #<RuntimeException java.lang.RuntimeException: No reader function for tag _invalid> |
| 15:50 | justin_smith | err |
| 15:50 | justin_smith | ,(read-string "#;\n_ invalid []") |
| 15:50 | clojurebot | #<RuntimeException java.lang.RuntimeException: No reader function for tag _> |
| 15:50 | justin_smith | oh, #_ is different I guess |
| 15:50 | amalloy | Bronsa: it's just, i would have expected the ; to be an invalid part of a dispatch macro, not a comment in the middle of one |
| 15:50 | justin_smith | it just looks like a tagged reader |
| 15:51 | Bronsa | amalloy: it's not going to intepret it as a dispatch macro anymore. it's in tagged-reader mode :P |
| 15:51 | Bronsa | amalloy: there's no invalid dispatch character error anymore |
| 15:52 | amalloy | Bronsa: the error message is still there, in a not-unreachable code path |
| 15:52 | Bronsa | right |
| 15:52 | Bronsa | no wait, not-unreachable? |
| 15:53 | amalloy | well, it's not unreachable as far as the compiler is concerned - there are if/else branches that lead there. i can't tell for sure whether they are "actually" unreachable |
| 15:54 | Bronsa | amalloy: I'm pretty sure there's no way to get that exception anymore |
| 15:55 | amalloy | hmmm |
| 15:55 | amalloy | challenge accepted |
| 15:55 | gfredericks | leiningen user-profile protip: seldom-used plugins can be "hidden" from the leiningen startup & classpath by shoving them in a dedicated profile and adding an alias for that plugin's command that expands to with-profile |
| 15:57 | amalloy | Bronsa: https://www.refheap.com/41aa882e49e562b2d00f0ed84 |
| 15:58 | amalloy | now that you know it's possible, care to guess how, or shall i spoil it? |
| 15:58 | zacts | hi which doc explains examples of how to create subdirectories to my project structure within a clojure app? |
| 15:58 | zacts | app -> subdirectory within my lein repo |
| 15:58 | Bronsa | amalloy: does it involve using a custom tagged reader? |
| 15:58 | amalloy | yes |
| 15:58 | Bronsa | that's cheating :P |
| 15:59 | amalloy | hey, you said it was unreachable |
| 15:59 | Bronsa | fair enough |
| 15:59 | zacts | hum.. Java.io.File. ? |
| 15:59 | amalloy | anyway, the custom reader is just (constantly nil) |
| 15:59 | zacts | is this the proper way to do this? |
| 15:59 | amalloy | if you invoke that reader you get the old no-dispatch-macro error |
| 15:59 | Bronsa | amalloy: ah yeah, there is actually a ticket in jira for that |
| 16:00 | crash_ep | Do any of Clojure's iterating procedures result in a stack overflow if actually allowed to iterate over an infinite sequence? E.g., `doseq`? |
| 16:00 | tbaldridge | crash_ep: no |
| 16:01 | crash_ep | tbaldridge thanks |
| 16:02 | {blake} | zacts: What are you trying to accomplish? |
| 16:02 | amalloy | tbaldridge: you can produce sequences that will cause stackoverflows when you iterate over them, which may be what crash_ep is worried about |
| 16:03 | tbaldridge | hey, I didn't say it was unreachable ;-) |
| 16:04 | crash_ep | amalloy what are you talking about? |
| 16:05 | zacts | {blake}: just save config files, but I figured it out |
| 16:05 | {blake} | zacts: Congrats. =) |
| 16:05 | amalloy | i mean, if you produce a sequence like uh...(nth (iterate #(map inc %) (range 5)) 10000) |
| 16:05 | zacts | thanx {blake} |
| 16:06 | amalloy | that's a perfectly fine result in theory (and if you change 10000 to 100 it works fine), but in practice trying to consume it causes a stack overflow |
| 16:06 | amalloy | but this is related to the sequences you produce, not how you iterate over them |
| 16:10 | crash_ep | amalloy: why is that? Doesn't `iterate` create a lazy sequence? |
| 16:12 | amalloy | http://stackoverflow.com/questions/2946764/recursive-function-causing-a-stack-overflow |
| 16:13 | amalloy | is the same sort of problem as what i'm describing here |
| 16:13 | fortruce | is there a way to force a rational to be represented as a decimal in the repl? |
| 16:14 | justin_smith | fortruce: (double (/ 2 3)) |
| 16:14 | justin_smith | ,(double (/ 2 3)) |
| 16:14 | fortruce | justin_smith: thanks |
| 16:14 | clojurebot | 0.6666666666666667 |
| 16:15 | ianhedoesit | ,(float (/ 2 3)) |
| 16:15 | clojurebot | 0.6666667 |
| 16:15 | justin_smith | fortruce: that's actually doing a type conversion, but it's probably the simplest thing |
| 16:16 | fortruce | justin_smith: yea, i just need it for a quick calculator |
| 16:16 | ianhedoesit | ,(/ 2.0 3) |
| 16:16 | clojurebot | 0.6666666666666666 |
| 16:16 | crash_ep | amalloy thanks for the link |
| 16:16 | fortruce | ianhedoesit: thats cool :) |
| 16:16 | justin_smith | yeah, you could always potentially pollute the calculation too |
| 16:17 | ianhedoesit | ,(/ 2. 3) |
| 16:17 | clojurebot | 0.6666666666666666 |
| 16:17 | TimMc | ,(nth (iterate #(map inc %) (range 5)) 10000) |
| 16:17 | clojurebot | #<StackOverflowError java.lang.StackOverflowError> |
| 16:17 | TimMc | Take that, bot! |
| 16:19 | justin_smith | TimMc: for some reason I thought lazy-seqs would handle that better |
| 16:19 | crash_ep | TimMc you animal |
| 16:22 | tbaldridge | hyPiRion: read your blog post earlier today, +1 |
| 16:23 | hyPiRion | tbaldridge: the performance one or the swearjure one? :p |
| 16:23 | tbaldridge | hyPiRion: both, but I was thinking about swearjure |
| 16:23 | hyPiRion | haha, thanks |
| 16:24 | tbaldridge | hyPiRion: the performance one was good as well, it mentioned many concerns I've had about vectors, but never took the time to investigate |
| 16:32 | hyPiRion | Yeah – fortunately I don't think very many people hit perf issues related to the vector impl |
| 16:33 | hyPiRion | Except for ztellman, who seems to have perf issues with about everything :p |
| 16:34 | gfredericks | the one constant factor in all of ztellman's perf issues is ztellman |
| 16:40 | {blake} | ,(map (fn[i](inc i)) [1 2 3]) |
| 16:40 | clojurebot | (2 3 4) |
| 16:41 | {blake} | (let [afn (fn[i] inc i) (map afn [1 2 3])) |
| 16:41 | {blake} | ,(let [afn (fn[i] inc i) (map afn [1 2 3])) |
| 16:41 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unmatched delimiter: )> |
| 16:42 | {blake} | ,(let [afn (fn[i] inc i)] (map afn [1 2 3])) |
| 16:42 | clojurebot | (1 2 3) |
| 16:42 | {blake} | ,(let [afn (fn[i] (inc i))] (map afn [1 2 3])) |
| 16:42 | clojurebot | (2 3 4) |
| 16:42 | TimMc | gfredericks: O(ztellman) |
| 16:44 | amalloy | what in the world is http://octopushub.org/clojure/2015/01/26/hellofunk-did-you-notice-stackoverflowcom-questions-28131135-howtoimplementzipwithfoldlinaneagerlanguage.html about, does anyone know? it seems to be a bizarre collection of things said to me about clojure |
| 16:45 | gfredericks | amalloy: this is the future of content |
| 16:45 | gfredericks | jump on the bandwagon or you'll be left by the train with no elephants in your pockets |
| 16:46 | amalloy | gfredericks: you're making the problem worse now. i can just see tomorrow's headline: "amalloy: this is the future of content" |
| 16:46 | gfredericks | you mean making the problem better |
| 16:46 | hyPiRion | haha |
| 16:53 | TimMc | Hmm, I can't see any obvious way to perform an injection attack on that site. |
| 16:54 | TimMc | It probably won't even pick on you again any time soon, so you'd have to predict the next search... |
| 16:56 | TimMc | Hah, the last "related question" is from me. |
| 16:56 | aaelony | I know I'm behind the times and this is a silly question, but I'm following a simple Transducers example using filter (http://ianrumford.github.io/blog/2014/08/08/Some-trivial-examples-of-using-Clojure-Transducers/), and the repl is telling me that I have the "Wrong number of args (1) passed to: core/filter". I imagine I need to require a particular version of Clojure and possible use/require something but haven't googled for it correctly yet |
| 16:56 | aaelony | . What might I need to get this to work? |
| 16:57 | tbaldridge | aaelony: switch to the latest clojure alpha |
| 16:57 | amalloy | TimMc: i think they record everything anyone says, and synthesize pages based on all the subjects somewhere |
| 16:57 | tbaldridge | , *clojure-version* |
| 16:57 | TimMc | The pages aren't dynamic, I think... |
| 16:57 | clojurebot | {:interim true, :major 1, :minor 7, :incremental 0, :qualifier "master"} |
| 16:58 | amalloy | well actually, that's interesting. "site:octopushub.org justin_smith" returns a bunch of results, but "site:octopushub.org timmc" gets none at all |
| 16:59 | aaelony | tbaldridge: Thanks, Tim. My google-fu is terrible though and I'm not finding the right artifact etc for the project.clj |
| 16:59 | tbaldridge | aaelony: http://search.maven.org/#artifactdetails%7Corg.clojure%7Cclojure%7C1.7.0-alpha5%7Cjar |
| 17:00 | tbaldridge | any 1.7 alpha should work, but alpha5 is the latest |
| 17:00 | aaelony | tbaldridge: perfect. thank you. |
| 17:00 | TimMc | fuzz `fuzz`` <s<b>cript>document.location = "http://zombo.com";</s<b>script> !#@*)&%@)@@$">"@$: |
| 17:00 | TimMc | *shrug* |
| 17:00 | aaelony | :) |
| 17:02 | TimMc | amalloy: You could try emailing david.mazvovsky@gmail.com to ask what up. |
| 17:03 | justin_smith | amalloy: wat? Is this some new version of blogspam? |
| 17:04 | amalloy | i don't know, man. it's weird |
| 17:04 | amalloy | TimMc: whence that address? |
| 17:04 | justin_smith | someone scraping bytes off the wire? |
| 17:04 | TimMc | amalloy: whois |
| 17:05 | TimMc | justin_smith: The content scraper is... IN the room! |
| 17:05 | justin_smith | haha |
| 17:05 | justin_smith | maybe it's the side job of that spanish speaking bot |
| 17:05 | amalloy | justin_smith: i'm inclined to think they're scraping one of the log sites or something |
| 17:05 | tbaldridge | perhaps it's someone's job |
| 17:05 | justin_smith | ahh, yeah, that makes more sense |
| 17:05 | amalloy | because someone with an irc bot would be less confused about who wrote what |
| 17:06 | TimMc | They have IRC logs from several channels. |
| 17:06 | amalloy | like, all the messages "mentioned by justin_smith" are actually messages *to* justin_smith, like "justin_smith: thanks" |
| 17:07 | TimMc | I wonder if I could file a DMCA request against them. |
| 17:07 | TimMc | ...no, they're in Israel, aren't they. |
| 17:07 | justin_smith | TimMc™ |
| 17:07 | justin_smith | haha |
| 17:08 | amalloy | TimMc: well, you could ask google to hide their links. that's how the DMCA works against non-US stuff, right? |
| 17:08 | justin_smith | I mean your nick already has the ™ |
| 17:08 | TimMc | yup |
| 17:09 | TimMc | Mmm... their website is hosted in EC2, in the US. |
| 17:09 | TimMc | I wonder how that works. |
| 17:10 | tbaldridge | TimMc: well we are talking about DCMA, isn't the domain of that basically "we'll sue anyone who doesn't abide by our laws, YAH! 'murica!" |
| 17:10 | weavejester | Has anyone come across an "unsupported binding form" error in the latest Clojurescript versions? |
| 17:11 | weavejester | Or has anyone actually successfully used the latest Clojurescript without it excepting? |
| 17:11 | weavejester | I assume it must work for someone :) |
| 17:11 | michaelr` | weavejester: are you on 55 or 60? |
| 17:11 | weavejester | michaelr`: 60 |
| 17:12 | michaelr` | 60 works for me |
| 17:12 | weavejester | Hm... |
| 17:12 | weavejester | It would be nice if I had some way of figuring out where this error is coming from |
| 17:13 | michaelr` | maybe one of the middleware |
| 17:13 | michaelr` | try maybe lein-ancient to upgrade deps |
| 17:13 | weavejester | michaelr`: Are you using cljsbuild 1.0.4? |
| 17:14 | weavejester | michaelr`: This is a pretty simple project. It just relies on Clojure, Clojurescript and tools.macro. |
| 17:15 | weavejester | Oh wait, I think I've figured it out. |
| 17:16 | weavejester | The project was still pulling in Clojure 1.5.1 |
| 17:16 | weavejester | Hm... okay, it's still failing. |
| 17:16 | michaelr` | 1.0.4 |
| 17:17 | michaelr` | lein clean (?!) |
| 17:18 | weavejester | Yeah, I think it picked up something weird |
| 17:20 | weavejester | Ahah, that's done it. Looks like the problem is that 2760 only works with Clojure 1.6.0 or greater |
| 17:20 | weavejester | michaelr`: Thanks for your help |
| 17:32 | {blake} | I'm mapping over a routine that returns a map, so I get a sequence of maps as a result. Because I want just a single map, I'm then doing an apply merge. |
| 17:32 | {blake} | (apply merge (map function stuff)) |
| 17:32 | {blake} | I feel like I'm doing too much here. |
| 17:32 | justin_smith | {blake}: wait, how do you get a sequence of maps out of a map? |
| 17:32 | justin_smith | your function turns a k/v pair into a map? |
| 17:33 | amalloy | justin_smith: {blake} means "i'm mapping (a function that returns a map) over some sequence" |
| 17:33 | {blake} | Well, my function takes parameters for an SQL query and returns a map of the values. |
| 17:33 | {blake} | amalloy, justin_smith: Yes, sorry if that wasn't clear. |
| 17:33 | justin_smith | aha |
| 17:34 | amalloy | {blake}: (apply merge (map ...)) seems fine |
| 17:34 | justin_smith | {blake}: you may want to use reduce / into, but merge over map seems decent enough |
| 17:34 | {blake} | amalloy: OK. I was thinking I could reduce it into a {}, too, but not sure it's better. |
| 17:35 | {blake} | justin_smith: Hah. OK. Thanks, guys. |
| 17:35 | justin_smith | {blake}: no need for {} even (reduce (fn [acc m] (into acc (f m))) mps) |
| 17:35 | justin_smith | or wait, that would skip the f on the first of mps, so use {} as your explicit initial val |
| 17:36 | justin_smith | but it comes out pretty much the same |
| 17:36 | {blake} | Let me try reduce, while I have the time. |
| 17:37 | amalloy | i don't really love that reduce. it's just manually inlining the map call, doing transducers by hand |
| 17:37 | tbaldridge | {blake}: in short, upgrade to 1.7 |
| 17:38 | amalloy | (into acc (map f) mps) is the same thing i think, with transducers? |
| 17:38 | tbaldridge | yep, pretty much |
| 17:38 | {blake} | justin_smith: It doesn't help readability, to my eyes. But I tried. =P |
| 17:45 | TimMc | clojurebot: {blake} |means| "i'm mapping (a function that returns a map) over some sequence" |
| 17:45 | clojurebot | In Ordnung |
| 17:46 | {blake} | Was ist das? |
| 17:50 | TimMc | Just teaching clojurebot some crap. |
| 17:52 | ianhedoesit | clojurebot: what does {blake} mean |
| 17:52 | clojurebot | Excuse me? |
| 17:52 | ianhedoesit | ;-; |
| 17:52 | {blake} | heh |
| 17:52 | {blake} | This could be useful. |
| 17:57 | TimMc | clojurebot: {blake}? |
| 17:57 | clojurebot | {blake} means "i'm mapping (a function that returns a map) over some sequence" |
| 17:58 | {blake} | clojurebot words? |
| 17:58 | {blake} | clojurebot: words? |
| 17:58 | clojurebot | These words are razors to my wounded heart |
| 17:59 | ianhedoesit | clojurebot: TimMc? |
| 17:59 | clojurebot | TimMc is a jerk |
| 17:59 | {blake} | heh |
| 17:59 | ianhedoesit | whoa there |
| 18:00 | {blake} | When I use a word, it means just what I choose it to meanneither more nor less. |
| 18:00 | TimMc | ~TimMc |
| 18:00 | clojurebot | TimMc is a jerk |
| 18:00 | TimMc | heh, maybe that's all it knows about me |
| 18:01 | ianhedoesit | ~ianhedoesit |
| 18:01 | clojurebot | Excuse me? |
| 18:01 | ianhedoesit | clojurebot: ianhedoesit |means| "what a great guy - from clojurebot with love." |
| 18:01 | clojurebot | Ik begrijp |
| 18:02 | ianhedoesit | ~ianhedoesit |
| 18:02 | clojurebot | ianhedoesit means "what a great guy - from clojurebot with love." |
| 18:03 | ianhedoesit | TimMc: clojurebot is just a clojure wrapper for PircBot by jibble.org right? |
| 18:11 | TimMc | Dunno, check source. |
| 18:12 | TimMc | ianhedoesit: I used "means" because of a comment amalloy made that made it sound like he was defining "{blake}", but you can use anything. |
| 18:12 | atratus | can anyone explain how make-array results in nesting? https://github.com/clojure/clojure/blob/clojure-1.6.0/src/clj/clojure/core.clj#L3680 |
| 18:13 | atratus | does that line mean its relying on Java to do the work and not clojure? |
| 18:14 | TimMc | yeah |
| 18:14 | TimMc | ...I don't understand why it's so hard to find the javadocs online |
| 18:16 | TimMc | Well, I guess the answer is "Oracle doesn't understand internets". |
| 18:16 | TimMc | atratus: It's a call to java.lang.reflect.Array/newInstance |
| 18:18 | atratus | TimMc: ok thankyou, yeah that stuff is awful |
| 18:18 | sardinha_biba | meaning of falsey and truthy please? I am new to programming and not a native english speaker, so I'm having some difficulty understand it and online translations didn't help. |
| 18:19 | TimMc | sardinha_biba: true and false are actual booleans; many languages use broader notions of true-like values and false-like values. |
| 18:20 | TimMc | So in Clojure, nil and false are treated as false-like (falsey) and everything else are true-like (truthy) |
| 18:21 | TimMc | Forms like (if x ...) coerce x into an actual boolean value (true or false). |
| 18:22 | sardinha_biba | TimMc: Thank you. makes more sense now. Thought that falsey was somewhat different than false |
| 18:45 | {blake} | If I have a multi-user app that connects to mongoDB, can anyone think of a reason why I shouldn't just use the same connection for all calls into it? As opposed to trying for a connection per user/session/whatever? |
| 18:55 | amalloy | {blake}: don't make a connection per user |
| 18:55 | amalloy | unless you're letting users build their own queries or something and you need them to have different permission levels i guess |
| 18:56 | {blake} | amalloy: Nah, nothing that sophisticated. It's really just a substitute file system, if we're being honest. |
| 18:57 | {blake} | I think I just need a way to check if the connection is still good. |
| 19:27 | ianhedoesit | what are you using for establishing the connections? |
| 19:27 | tcrayford____ | {blake}: I'd establish the connection at once, then pass it through everything. Typically your client should handle connection errors/reconnection/etc |
| 19:28 | tcrayford____ | (though I have *no* idea how good mongo's jvm drivers are, I try really hard to never use or think about mongo) |
| 19:28 | tcrayford____ | {blake}: one common pattern (if you're using ring) is to `assoc` it onto the request in a middleware |
| 19:29 | {blake} | tcrayford____: So you'd have it so that every session had its own connection? |
| 19:29 | tcrayford____ | {blake}: no, one connection, but shared |
| 19:29 | tcrayford____ | just it *looks* like every session has it's own connection |
| 19:30 | tcrayford____ | means that testing gets easier - you don't have a global connection anywhere, it just comes in with the request |
| 19:30 | {blake} | tcrayford____: OK, so what's the benefit of passing around...oh, I see. =P |
| 19:30 | tcrayford____ | :) |
| 19:31 | tcrayford____ | also like, means that you don't have jvm bootup dependent on connections happening, which *can* mess you up in production etc |
| 19:31 | Glenjamin | tcrayford____: ah good, it's not just me doing that (assoc resources into req) |
| 19:31 | tcrayford____ | Glenjamin: pretty sure that's a standard pattern at this point |
| 19:31 | Glenjamin | why do you always have so many underscores? |
| 19:31 | tcrayford____ | trying to win an award |
| 19:31 | Glenjamin | i've seen a few examples that have their routes close over "components" |
| 19:32 | {blake} | Well, my guy wrote some code that just blithely opens a connection for every request. Which is cool. Until you have a few zillion connections. |
| 19:32 | killfill | newbie question: (def a (atom {:hi "there" :list [1 2 3 4]})) <-- how could i delete one element of that :list? |
| 19:32 | justin_smith | killfill: does that vector have to remain a vector? |
| 19:33 | killfill | justin_smith: i think so. yes. |
| 19:33 | tcrayford____ | {blake}: I once had code in production that uh, spawned a thread for every incoming request, and left it there (because of a bug) |
| 19:33 | tcrayford____ | stuff goes south north of like 200k threads on linux apparently |
| 19:33 | {blake} | tcrayford____: That takes a man's OS to handle...a manly man's OS. |
| 19:33 | tcrayford____ | (on that hardware anyway) |
| 19:34 | {blake} | tcrayford____, Glenjamin: I'm curious about the passing around resources, though: What I get back from connect-db looks like "#<DBApiLayer mydbname>". |
| 19:34 | tcrayford____ | {blake}: also note that pattern (new connection per request) will *really* mess you up in postgres and some other databases - they spawn a new process per client connection |
| 19:35 | justin_smith | ,(swap! (atom {:hi "there" :list [1 2 3 4]}) update-in [:list] ((fn [n] (fn [v] (vec (concat (take n v) (drop (inc n) v))))) 2)) ; killfill |
| 19:35 | clojurebot | {:list [1 2 4], :hi "there"} |
| 19:35 | justin_smith | killfill: it's a little awkward with the drop-nth as an anonymous function, but that's easy to fix in a real namespace |
| 19:35 | {blake} | tcrayford____: Well, I think it's caused us some issues on Mongo, as well. =P |
| 19:35 | killfill | wops |
| 19:35 | justin_smith | killfill: also, labeling a vector as :list is kind of weird |
| 19:36 | killfill | i could probably have figure that out in 1 year.. :P |
| 19:36 | tcrayford____ | {blake}: /me resists making disparaging remarks about mongo |
| 19:36 | justin_smith | killfill: it's more straightforward if it isn't a one-liner |
| 19:37 | killfill | justin_smith: if having a list instead of a vector, would it make it simplier? or we would just take thouse 'vec' out |
| 19:37 | justin_smith | killfill: general idea is that swap! mutates the state of an atom, and returns the new state, update-in takes a sequence of keys and runs a function on the value found at the end |
| 19:37 | justin_smith | killfill: having a list would just take out the vec call |
| 19:38 | {blake} | tcrayford____: Swing away. I've got no emotional attachments. |
| 19:38 | killfill | justin_smith: thanks! |
| 19:38 | {blake} | But I'm still not seeing how I'd pass that connection through an HTTP request. |
| 19:38 | justin_smith | killfill: simpler example of update-in: |
| 19:38 | justin_smith | ,(swap! (atom {:a {:b 0}}) update-in [:a :b] inc) |
| 19:38 | clojurebot | {:a {:b 1}} |
| 19:39 | dbronico | I'm using Clojure for a simple script, and when I run it from the REPL, all is well. When I run it with lein-exec, it prints my debug messages but terminates before the call to 'map' is done. Can anyone help me sort this out? |
| 19:39 | justin_smith | killfill: what I do in the first example is only different in a couple of small details |
| 19:39 | {blake} | dbronico: Paste it to refheap! |
| 19:39 | justin_smith | dbronico: map is lazy |
| 19:39 | justin_smith | dbronico: map does nothing, unless you consume the value |
| 19:39 | justin_smith | dbronico: in the repl, the printing step consumes the value |
| 19:40 | dbronico | Aha, so a doall should fix it up, I'm thinking? |
| 19:40 | justin_smith | dbronico: use dorun, unless you need to use the return value somewhere |
| 19:40 | {blake} | dbronico: Well, it'll reveal the error in the REPL, anyway. |
| 19:40 | justin_smith | {blake}: ? |
| 19:40 | amalloy | dbronico: http://stackoverflow.com/questions/28183226/how-main-works-on-clojure/28185462#28185462 |
| 19:41 | amalloy | which is saying the same thing as justin_smith but with more words |
| 19:41 | justin_smith | {blake}: the repl hides the error because printing forces the lazy seq to be realized |
| 19:41 | bonsai_hk | dbronico: if you're "doing things" using map, i.e. a glorified for-loop, then rather use doseq instead |
| 19:41 | {blake} | justin_smith: Right...so if he does a -- okay, right, got it backwards. |
| 19:41 | justin_smith | heh |
| 19:41 | dbronico | justin_smith: OK, that seemed to be the ticket. |
| 19:42 | justin_smith | dbronico: very common mistake, I made it more times than I care to admit |
| 19:42 | justin_smith | ~map |
| 19:42 | clojurebot | map is *LAZY* |
| 19:42 | justin_smith | haha |
| 19:42 | dbronico | {blake}, amalloy: Thanks for the attempt. You guys are like sharks in here! =] |
| 19:42 | dbronico | bonsai_hk: I will definitely check that out. |
| 19:43 | justin_smith | dbronico: it's a cutthroat battle for imaginary internet points |
| 19:43 | justin_smith | $karma amalloy |
| 19:43 | justin_smith | he's ahead |
| 19:43 | justin_smith | :P but lazybot is slacking |
| 19:43 | amalloy | is lazybot dead again? i restarted him last night i think |
| 19:43 | {blake} | It's #Clojure, where the games are made up and the points don't matter. |
| 19:43 | tcrayford____ | {blake}: sent you a pm, unsure if you saw it |
| 19:44 | justin_smith | amalloy: is lazybot dying or just in a weird disconnect / netsplit state or something? |
| 19:44 | amalloy | disconnected |
| 19:44 | amalloy | but doesn't recover |
| 19:44 | amalloy | &1 |
| 19:45 | lazybot | ⇒ 1 |
| 19:45 | justin_smith | amalloy: so theoretically the fix would be detecting disconnection (which eg. my client seems to do fine) and handling that event |
| 19:45 | amalloy | i think it tries to do that but is broken somehow |
| 19:45 | justin_smith | by my client I mean my regular irc client, not some irc lib I am sitting on |
| 19:45 | amalloy | right |
| 19:46 | justin_smith | amalloy: I am not at all surprised that the API update broke that hook / trigger (if that's even how it works) |
| 19:46 | amalloy | justin_smith: it was broken before you touched it, in exactly the same way afaict |
| 19:50 | amalloy | the gradual reputation gain i get from old SO answers is a fun reminder of the weird questions people ask sometimes: http://stackoverflow.com/q/8531793/625403 is someone asking how to create a future that doesn't actually start right away |
| 19:52 | justin_smith | a slight distinction, completing in the future vs. starting in the future |
| 19:53 | justin_smith | see also, people expecting agents to abstract fixed actions over parameters that come in from the client, rather than a stored state modified by an action provided by the client |
| 19:55 | amalloy | justin_smith: of course, in one sense it actually is a fixed action: the function #(apply % current-state %&) |
| 19:56 | amalloy | not that this is a terribly useful sense |
| 19:56 | justin_smith | well, the naive expectation is that they would somehow be able to define that action of course |
| 19:57 | amalloy | right. i want a log-to-file agent, and i want to send it lines to log |
| 19:57 | justin_smith | maybe we can make a ticket on JIRA requesting that agent and go switch names from now on |
| 19:57 | justin_smith | then people would be less confused |
| 19:58 | justin_smith | (not really) |
| 19:58 | amalloy | justin_smith: that'll be the first change made after https://github.com/clojure/clojure/pull/6 |
| 19:59 | justin_smith | haha |
| 20:05 | justin_smith | so, in this CMU text, I see the following "Reactive agents simply retrieve pre-set behaviors similar to reflexes without maintaining any internal state." http://www.cs.cmu.edu/afs/cs/usr/pstone/public/papers/97MAS-survey/node14.html ; while in the docs for agent I see "Clojure's Agents are reactive, not autonomous - there is no imperative message loop and no blocking receive." http://clojure.org/agents |
| 20:05 | justin_smith | this is two different meanings for "reactive agent" right? |
| 20:05 | amalloy | probably. reactive is practically just an adjective meaning "friggin awesome" |
| 20:06 | justin_smith | heh |
| 20:06 | justin_smith | "functional friggin awesome programming" |
| 20:06 | justin_smith | it works! |
| 20:06 | amalloy | also, there is a kinda funny github bug involving issue references that i just noticed |
| 20:06 | justin_smith | amalloy: yeah, that issue ref was weird |
| 20:06 | justin_smith | on issue 6 |
| 20:06 | amalloy | justin_smith: it's not just issue 6! |
| 20:06 | justin_smith | err.. pull 6 |
| 20:06 | justin_smith | oh? |
| 20:07 | amalloy | *all* the low-numbered issues in the clojure repo are "mentioned" by that other one |
| 20:07 | amalloy | up to #29 |
| 20:07 | amalloy | because that other one includes a paste of some console output |
| 20:07 | amalloy | which contains lines looking like: "native: #25 pc 00008cf0" |
| 20:08 | justin_smith | ah, and I bet some crazy regex grabs those |
| 20:08 | justin_smith | s/crazy/dunderheaded/ |
| 20:08 | hiredman_ | it turns out github is just a pile of heuristics that fail at the edges like everything else |
| 20:08 | amalloy | but...unicorns? |
| 20:09 | hiredman_ | unicorns, scrum, and agile best practices, etc |
| 20:17 | xemdetia | I once saw a project manager increase efficiency by twelve unicorns once |
| 20:34 | tehgeekmeister | how do you set pprint to be less eager about adding newlines between keys (with no dedent) and complex values? |
| 20:34 | tehgeekmeister | is there any way? |
| 20:44 | justin_smith | tehgeekmeister: http://clojuredocs.org/clojure.pprint there are some variables that help control how pprint behaves |
| 20:44 | tehgeekmeister | @justin_smith yeah, i looked at those |
| 20:44 | tehgeekmeister | set the print-miser-width to like 10k and it still didn't do what i was after |
| 20:45 | justin_smith | tehgeekmeister: how about *print-right-margin* |
| 20:48 | tehgeekmeister | @justin_smith trying it now |
| 20:49 | tehgeekmeister | nope, set it to 10k-ish too |
| 20:51 | tehgeekmeister | maybe I'm doing it wrong, i did: (def ^:dynamic *print-right-margin* 1000000) |
| 20:51 | tehgeekmeister | (10k-ish apparently means a million.) |
| 20:51 | tehgeekmeister | @justin_smith see above |
| 20:51 | justin_smith | tehgeekmeister: that's not how it works |
| 20:52 | justin_smith | tehgeekmeister: https://www.refheap.com/96881 |
| 20:52 | tehgeekmeister | checking now, thanks for the help |
| 20:52 | justin_smith | notice I got pprint to put 100 numbers one one line |
| 20:53 | justin_smith | *on one |
| 20:53 | justin_smith | tehgeekmeister: the docs indicate that there is a variable called *print-right-margin* in clojure.pprint which controls that behavior |
| 20:54 | tehgeekmeister | yeah, so this isn't exactly what we're after fixing, but at least i've learned how to customize the options |
| 20:54 | tehgeekmeister | i'll dig through the docs a bit more and try things now |
| 20:54 | tehgeekmeister | now that i know how to do it right |
| 20:54 | justin_smith | tehgeekmeister: in general you aren't going to see code that looks for magic var names in your namespace, that's just not how we do things |
| 20:54 | tehgeekmeister | yeah, it seemed oddd |
| 20:55 | justin_smith | if some var controls a functions global behavior, it'll be defined in the same project (if not the same namespace) |
| 21:06 | justin_smith | from now on, when I use agents in my clojure code, I will be naming them "smith" |
| 21:24 | andyf | tehgeekmeister: If pprint isn?t bending to your will, you may want to take a look at aprint to see if it does what you want: https://github.com/razum2um/aprint |
| 21:28 | dbronico | If I am doing work in parallel that has prints, is there a way to guarantee no overlapping prints? I was hoping atoms with watches would work, but it's not the case. |
| 21:28 | julianleviston | dbronico: I would think a logger would have this covered. |
| 21:28 | justin_smith | dbronico: one option is (locking *out* (println ...)) - just make sure that nothing inside the println call tries to do the same of course |
| 21:28 | justin_smith | or yeah, the better option is a proper logger |
| 21:29 | dbronico | A proper logger... Can you give a little more detail or a reference to where I can find out more? |
| 21:29 | julianleviston | dbronico: maybe you could redef println for your work. |
| 21:30 | julianleviston | https://github.com/clojure/tools.logging |
| 21:30 | justin_smith | dbronico: check out clojure.tools.logging |
| 21:30 | julianleviston | just first google I found... |
| 21:30 | justin_smith | or what julianleviston said |
| 21:30 | julianleviston | haha :) |
| 21:30 | sorenmacbeth | is there a not terrible way to resolve an aliases var to it's fully qualified self? |
| 21:31 | justin_smith | sorenmacbeth: you can get the mappings of an ns programmatically, and look it up in there - depending on what you are actually doing |
| 21:31 | julianleviston | dbronico: core async channels could be good… :-) |
| 21:31 | justin_smith | ,(.getMappings *ns*) |
| 21:31 | clojurebot | {primitives-classnames #'clojure.core/primitives-classnames, +' #'clojure.core/+', Enum java.lang.Enum, decimal? #'clojure.core/decimal?, restart-agent #'clojure.core/restart-agent, ...} |
| 21:33 | dbronico | justin_smith, julianleviston: Thanks a lot. I'll check out the logging. Didn't realize it was an easily-Googlable term. =P |
| 21:33 | justin_smith | or ##(ns-refers *ns*) which is slightly higher level |
| 21:33 | lazybot | ⇒ {primitives-classnames #'clojure.core/primitives-classnames, +' #'clojure.core/+', decimal? #'clojure.core/decimal?, restart-agent #'clojure.core/restart-agent, sort-by #'clojure.core/sort-by, macroexpand #'clojure.core/macroexpand, ensure #'clojure.core/ensure, chun... https://www.refheap.com/96882 |
| 21:33 | dbronico | julianleviston: Thanks for the suggestion. I hear a lot about core.async. I'll check that out, too. |
| 21:33 | julianleviston | dbronico: it’s fricking awesome. |
| 21:34 | julianleviston | dbronico: a really good way to make sure your one thing does only one thing at once (fanning in). |
| 21:35 | sorenmacbeth | justin_smith: cheers |
| 21:35 | justin_smith | ,(ns-aliases *ns*) ; this may also be helpful |
| 21:35 | clojurebot | {} |
| 21:36 | justin_smith | and in general ##(clojure.repl/apropos #"^ns") |
| 21:36 | lazybot | ⇒ (ns-unmap ns-publics ns-unalias ns-aliases ns-resolve ns-refers ns ns-name ns-map ns-interns ns-imports nss) |
| 21:38 | dbronico | julianleviston: So I'd set up a channel, a sorta 'channel-reader' that's infinite loop (in theory) that just listens on the channel and prints whatever it gets, then just have my print messages get put on the channel. |
| 21:38 | justin_smith | dbronico: google isn't always reliable (ie. we phased out clojure.contrib much faster than google stopped giving results about clojure.contrib) |
| 21:39 | justin_smith | dbronico: yeah, that's the idea. I would write a function that takes varargs and puts them on the chan to be printed (so that your code doesn't have to look like core.async code, it can just be your-ns/println) |
| 21:39 | julianleviston | dbronico: yeah, you could have one go block with a channel set up around your main functionality that just blocks then prints, and your main functionality then passes that channel to the rest of the code, and then all your calls to println become a call to put! the channel instead. |
| 21:40 | julianleviston | justin_smith: wait… clojure.contrib is phased out? |
| 21:40 | TEttinger | julianleviston: yeah since 1.2 |
| 21:40 | justin_smith | julianleviston: http://dev.clojure.org/display/community/Where+Did+Clojure.Contrib+Go |
| 21:40 | amalloy | julianleviston: the old old old thing of a single clojure-contrib jar is out |
| 21:40 | amalloy | clojure contrib as a collection of independent libraries still exists |
| 21:40 | julianleviston | oh phew. |
| 21:41 | justin_smith | oh yeah, good point :) |
| 21:41 | justin_smith | but we don't have the clojure.contrib.whatever naming any more either |
| 21:41 | justin_smith | even if they are contrib projects |
| 21:41 | dnolen | iOS ClojureScript REPL is blowing my mind, all thanks to mfikes |
| 21:41 | dnolen | https://github.com/omcljs/ambly |
| 21:41 | julianleviston | bmabey: .… of rspec/cucumber fame? |
| 21:42 | julianleviston | dnolen: haha… wow…. that’s so fricking cool |
| 21:43 | dbronico | justin_smith, julianleviston: OK, I'm checking out core.async. Thanks again. |
| 21:46 | julianleviston | dnolen: so what are the ramifications of this that give you so much excitement? |
| 21:46 | dnolen | julianleviston: well later React Native |
| 21:46 | julianleviston | (that I’m not doubt missing) |
| 21:46 | dnolen | julianleviston: but really this just means you can script any iOS application given you've added adequate bridging |
| 21:47 | dnolen | julianleviston: React Native just ships with a bunch of free bridging |
| 21:47 | dnolen | julianleviston: but this just means you can build real iOS apps (no WebView) with ClojureScript with the expect REPL driven workflow |
| 21:47 | julianleviston | dnolen: hey what do you think of Relay, btw? I spent the last like 6 months wrangling my own with Om/CLJS and… I’m tired. :-) |
| 21:48 | julianleviston | dnolen: ah… yeah, react native… huzzah… does it transpile to the objc/swift runtime? For some reason I thought it was running a javascript vm inside it. lol. |
| 21:49 | julianleviston | (no idea if transpile is the right word to use there) |
| 21:49 | dnolen | julianleviston: Apple shipped real JavaScript bindings into Objective-C run time w/ iOS 7 |
| 21:49 | dnolen | julianleviston: this is old news |
| 21:49 | julianleviston | dnolen: oh. I think I missied that. What does real JS bindings mean, tho? |
| 21:49 | dnolen | julianleviston: but yes embedded JS that talks to native components |
| 21:50 | dnolen | julianleviston: like a real native embedded language bridge |
| 21:50 | julianleviston | ooh |
| 21:50 | dnolen | julianleviston: the same way V8 talks to C++ |
| 21:50 | julianleviston | dnolen: or Nu or CocoaRuby |
| 21:51 | dnolen | yep |
| 21:51 | julianleviston | wow |
| 21:52 | julianleviston | OMFG so we might get true native performance running clj in the browser in iOS… and on Om apps… oh this is nuts. |
| 21:54 | dnolen | julianleviston: well you're limited by JSC, no JIT yet, but this doesn't matter for many apps |
| 21:54 | dnolen | julianleviston: FB is already building real apps w/ stuff |
| 21:54 | dnolen | and the perf is good |
| 21:55 | rkneufeld | If anyone out there is using or has considered using Simulation Testing, I'd love to get your input: http://www.rkn.io/2015/02/03/state-of-sim-testing-2015/ |
| 21:56 | tehgeekmeister | @justin_smith we found fipp, it does the style of printing we're after |
| 21:56 | julianleviston | dnolen: that’s really cool |
| 21:56 | tehgeekmeister | but thanks for the pointers, they'll definitely help us get up to speed |
| 21:56 | justin_smith | tehgeekmeister: oh, nice |
| 21:57 | bbloom | tehgeekmeister: let me know if fipp works out for you |
| 21:57 | tehgeekmeister | bbloom: it does so far, in like <5 minutes of use |
| 21:57 | tehgeekmeister | will get back to you though, for sure |
| 21:57 | mfikes | dnolen: The perf of React Native is actually much better than what the FB Groups app would lead you to believe. (There is a lot of FB infrastructure that is unrelated to React Native in its init sequence.) |
| 21:58 | justin_smith | bbloom: oh, now that I see you are around, I'm thinking you may be one of the people who could give me a good answer to this question I just posted on the ml https://groups.google.com/forum/#!topic/clojure/Le_McSEy1_c |
| 21:58 | dnolen | mfikes: good to hear |
| 22:01 | mfikes | dnolen: I was concerned because the ClojureScript / native hybrid app I built starts up much (much) more quickly than FB Groups, and Vjeux esentially explained that plain-vanilla React Native apps start up instantaneously :) |
| 22:02 | mfikes | julianleviston: Also, this will all lead to Android, and (for someone like me) perhaps the ability to build decent web apps :) |
| 22:02 | julianleviston | haha :) |
| 22:04 | n0n3such | quick question: i have spent the last 2 years learning scala and building a big project in scala and now want to learn another language while i develop my scala skills further. I am considering haskell and clojure. |
| 22:04 | mfikes | julianleviston: It is an amazing thought: You can learn Clojure(Script) for front and backend (1 language), and React for several front ends. |
| 22:04 | julianleviston | mfikes: it really is… |
| 22:04 | n0n3such | How will learning clojure help me improve as a software developer ? |
| 22:04 | mfikes | julianleviston: And all of it is very functional |
| 22:04 | julianleviston | n0n3such: learn them both. They’re both excellent. |
| 22:05 | n0n3such | julianleviston: which is a better investment of my limited time and brainpower ? |
| 22:05 | julianleviston | n0n3such: clojure is a lot easier to approach, so start with that… but learn a little haskell every day. |
| 22:05 | mfikes | n0n3such: Yes, you need to at least read through the Haskell O'Reilly book. It will _force_ you to look at things a certain way. |
| 22:06 | n0n3such | mfikes: Real World Haskell ? |
| 22:06 | sharms | how do I make 'lein ring server' auto-reload? |
| 22:06 | mfikes | n0n3such: Yep. I liked that one. Brian O'Sullivan IIRC |
| 22:07 | julianleviston | sharms: I think the help tells you doesn’t it? |
| 22:07 | codestorm444 | I looked into many FP languages, and chose Elixir |
| 22:07 | n0n3such | codestorm444: why ? |
| 22:07 | julianleviston | codestorm444: why choose one? |
| 22:07 | sharms | julianleviston: no, running 'lein help ringer server' gives no help |
| 22:08 | codestorm444 | Elixir runs on the Erlang VM which has some awesome features. It incorporates some of the better features from clojure, but has a friendly Ruby-like syntax |
| 22:08 | codestorm444 | julianleviston: gotta start somewhere |
| 22:09 | codestorm444 | clojure was my #1 until I learned about Elixir, haskell would have been #3 choice |
| 22:09 | n0n3such | why clojure #2 ? |
| 22:09 | julianleviston | codestorm444: I guess, as always, it comes down to… what are you trying to do? :) |
| 22:10 | julianleviston | sharms: If the LEIN_NO_DEV environment variable is not set, the server will monitor your source directory for file modifications, and any altered files will automatically be reloaded. https://github.com/weavejester/lein-ring |
| 22:11 | sharms | julianleviston - thanks, I am not sure for whatever reason that is working, however if I add :auto-reload? true to my project.clj it works now |
| 22:11 | codestorm444 | why #2? well, clojure pros: large base of JVM libraries... concurrency features... macros |
| 22:11 | julianleviston | sharms: oh yeah, sorry… it’s been a while since I’ve used it. |
| 22:12 | julianleviston | codestorm444: erm… what about the persistent data structures? OMG |
| 22:12 | julianleviston | codestorm444: and the immutability… |
| 22:13 | codestorm444 | yeah, elixir has those too |
| 22:13 | codestorm444 | i guess most FP languages do |
| 22:13 | julianleviston | codestorm444: erm… no? |
| 22:13 | julianleviston | codestorm444: not that I know of. |
| 22:14 | codestorm444 | Elixir does |
| 22:14 | codestorm444 | Scala hedges with val and var |
| 22:14 | julianleviston | codestorm444: it has persistent data structures? |
| 22:14 | codestorm444 | yes |
| 22:14 | julianleviston | codestorm444: can you point me to where this is true? |
| 22:15 | julianleviston | codestorm444: using the same trie structures as Clojure? |
| 22:16 | TEttinger | there are probably other data structures that are persistent that are better for certain tasks |
| 22:16 | TEttinger | as in, not 32-trie based |
| 22:18 | julianleviston | TEttinger: sure. As always, it depends what you’re trying to do ;-) |
| 22:18 | codestorm444 | julianleviston: I don't have a hnady link for you, but that's how elixir works. You add something to a list, you get a different list, the original is untouched |
| 22:18 | julianleviston | TEttinger: these ones have some nice properties, tho… to put it mildly ;-) |
| 22:19 | amalloy | codestorm444: that's not necessarily the same thing as persistent |
| 22:19 | TEttinger | ah, it's immutable not necessarily persistent |
| 22:19 | amalloy | you can implement that property using copy-on-write arraylists or something, which supports a functional style but is immensely slow |
| 22:19 | julianleviston | codestorm444: can I suggest before you go down any of these paths, watch some rich hickey talks about persistent data structures... |
| 22:20 | amalloy | i don't know how elixir's data structures actually are, just pointing out that your example doesn't necessarily answer the question |
| 22:20 | julianleviston | codestorm444: that was why I asked you four times… I should have asked you to define persistent data structure instead, it seems. |
| 22:21 | julianleviston | codestorm444: the end rub is… these are incredibly fast for most of the types of things most coders do most of the time, and support concurrency really well. |
| 22:22 | amalloy | http://comments.gmane.org/gmane.comp.lang.elixir.general/442 suggests that the answer is complicated |
| 22:25 | julianleviston | amalloy: hm… it seems pretty cut and dry to me… it relies on what the erlang vm does… which isn’t aware of this stuff. What about vectors? sorted collections? the whole idea of the sequence abstraction? For the guts of most coding practice, I’m yet to see a language that encourages a programmer to pay as much attention to the upsides of the structures they pick (and why) as it does to the downsides. |
| 22:35 | julianleviston | I love that where other languages say “Don’t look into this box”, “Don’t worry about how that works”, or “I’ll handle that for you”, clojure says “It’s hard, but you can absolutely do it, let me show you how, and what the costs/benefits are of choosing each thing are”. |
| 22:37 | tehgeekmeister | so if i want to pipe a java buffered stream to stdout in clojure, how do i do that idiomatically? |
| 22:38 | tehgeekmeister | rather than reading the whole thing in, and then printing it out |
| 22:38 | tehgeekmeister | i mean i know i can read a small chunk, write it, etc, but i figure there has to be a better way |
| 22:39 | Lewix | hi gentlemen |
| 22:39 | julianleviston | tehgeekmeister: https://www.safaribooksonline.com/library/view/clojure-cookbook/9781449366384/ch04.html |
| 22:39 | Lewix | (+ (cons (nth [1 2 3] 0) [1 2 3]) ) |
| 22:39 | Lewix | I expected this to work |
| 22:40 | Lewix | what's the logic behind it not working? |
| 22:40 | ToxicFrog | Nethack bot written in Clojure achieves the first fully automated ascension: https://www.reddit.com/r/nethack/comments/2tluxv/yaap_fullauto_bot_ascension_bothack |
| 22:40 | justin_smith | oh wow, awesome |
| 22:41 | julianleviston | Lewix: you’re trying to add a cons cell |
| 22:41 | julianleviston | Lewix: what does that mean? |
| 22:41 | julianleviston | maybe you want (apply + (cons (nth [1 2 3] 0) [1 2 3]) ) |
| 22:42 | sdegutis | What's a good GUI toolkit for writing a budget app? |
| 22:42 | Lewix | julianleviston: cons produces a list |
| 22:42 | julianleviston | sdegutis: MYOB |
| 22:42 | julianleviston | sdegutis: too sarcastic? :-) |
| 22:43 | sdegutis | oh |
| 22:43 | Lewix | julianleviston: which makes me wonder why apply is needed - it's not a vector |
| 22:43 | julianleviston | Lewix: + takes numbers. |
| 22:43 | julianleviston | Lewix: you passed it a cons cell |
| 22:43 | julianleviston | Lewix: nothing to do with vectors. |
| 22:44 | julianleviston | ,(doc +) |
| 22:44 | clojurebot | "([] [x] [x y] [x y & more]); Returns the sum of nums. (+) returns 0. Does not auto-promote longs, will throw on overflow. See also: +'" |
| 22:44 | Lewix | julianleviston: i see so the first evaluator cares about the others evaluators |
| 22:44 | Lewix | strange |
| 22:44 | julianleviston | Lewix: what’s an evaluator? |
| 22:44 | Lewix | julianleviston: anyways, i expected (cons (nth [1 2 3] 0)) to return a list and be treated as such |
| 22:45 | julianleviston | Lewix: apply takes a function (ƒ) and a collection of some kind, and calls it as though you’ve poured the contents of the collection into arguments of calling that function (ƒ). |
| 22:45 | Lewix | julianleviston: However, from what you're saying + cares that it was called with cons |
| 22:45 | bbloom | (doc cons) |
| 22:45 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 22:45 | Lewix | julianleviston: i don't have apply here |
| 22:45 | julianleviston | ,(+ ‘(1 2)) |
| 22:46 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: ‘ in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 22:46 | julianleviston | ,(+ [1 2]) |
| 22:46 | clojurebot | #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentVector to java.lang.Number> |
| 22:46 | Lewix | whihc makes sense |
| 22:46 | Lewix | (+ (1 2 3)) |
| 22:46 | Lewix | ,(+ (1 2 3)) |
| 22:46 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 22:46 | julianleviston | ,(+ '(1 2)) |
| 22:46 | clojurebot | #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentList to java.lang.Number> |
| 22:46 | Lewix | ,(+ 1 2 3) |
| 22:46 | clojurebot | 6 |
| 22:47 | Lewix | ,(+ (1 2 3)) |
| 22:47 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 22:47 | Lewix | really |
| 22:47 | Lewix | here is my issue |
| 22:47 | julianleviston | ,(cons 1 nil) |
| 22:47 | clojurebot | (1) |
| 22:47 | tehgeekmeister | @julianleviston seems like that just shows how to do bytes at a time, not just plugging two streams together |
| 22:47 | julianleviston | ,(+ (cons 1 nil)) |
| 22:47 | clojurebot | #<ClassCastException java.lang.ClassCastException: Cannot cast clojure.lang.PersistentList to java.lang.Number> |
| 22:47 | julianleviston | see? |
| 22:48 | julianleviston | tehgeekmeister: what does that mean? Sorry… not really sure what plugging two streams looks like. Prolly not the best guy to answer your Q, really... |
| 22:48 | tehgeekmeister | ah okay |
| 22:48 | tehgeekmeister | nbd |
| 22:48 | julianleviston | tehgeekmeister: ask it in java… someone can explain it idiomatically in clojure. |
| 22:48 | tehgeekmeister | i basically mean, if i have a stream that produces data |
| 22:48 | tehgeekmeister | and one that can consume data |
| 22:48 | tehgeekmeister | i just want to redirect all content from the producer to the consumer |
| 22:48 | julianleviston | tehgeekmeister: yeah… why can’t you just plug them together? |
| 22:49 | tehgeekmeister | in java you'd do this imperatively, i think |
| 22:49 | julianleviston | tehgeekmeister: isn’t that just a matter of plugging the one into the other? (out (in)) |
| 22:49 | dbronico | julianleviston: Thanks for recommending core.async. For what I needed it for (non-overlapping, parallel printing), the setup was really easy and it seems to be working with 7 threads. |
| 22:49 | julianleviston | tehgeekmeister: Using a streamreader and streamwriter tho |
| 22:49 | amalloy | tehgeekmeister: clojure.java.io/copy ? |
| 22:49 | tehgeekmeister | i would like it to be that simple, i just don't know |
| 22:49 | tehgeekmeister | @amalloy checking |
| 22:49 | julianleviston | dbronico: yeah it’s great, isn’t it! :) |
| 22:49 | julianleviston | tehgeekmeister: it is that simple. |
| 22:49 | amalloy | don't touch readers and writers if you want to use bytes. those are for characters |
| 22:50 | tehgeekmeister | i just want straight redirection. |
| 22:50 | julianleviston | tehgeekmeister: what amalloy said! |
| 22:51 | julianleviston | Lewix: grok or no grok? |
| 22:52 | Lewix | julianleviston: my problem was simply that I assumed list and a serie of number was the same thing |
| 22:52 | Lewix | (+ 1 2 3 4) |
| 22:52 | clojurebot | *suffusion of yellow* |
| 22:52 | julianleviston | Lewix: ah! |
| 22:52 | tehgeekmeister | amalloy: that's synchronous, I imagine, so I couldn't copy two streams in parallel? oh wait, there's gotta be a thing for that. i can figure this out. |
| 22:52 | amalloy | tehgeekmeister: future |
| 22:52 | Lewix | (+ (1 2 3 4)) |
| 22:52 | amalloy | use threads |
| 22:52 | Lewix | not the same thing |
| 22:52 | julianleviston | add( list( 1, 2) ) // -> what is this? add doesn’t understand a list. |
| 22:52 | julianleviston | apply(add, list( 1, 2) ) // -> I will do as you wish |
| 22:53 | Lewix | julianleviston: thats right |
| 22:53 | julianleviston | Lewix: sometimes I found shifting things to C syntax helped in the past. |
| 22:54 | bbloom | think of ( and ) like you might [ and ] when initializing an array or something |
| 22:54 | bbloom | parens in C are for precedence, but in a lisp they construct a data structure like [ and ] can do |
| 22:55 | julianleviston | bbloom: which if you look at the AST C produces, is a data structure... |
| 22:55 | bbloom | julianleviston: that AST is an implementation detail of a particular compiler |
| 22:55 | julianleviston | bbloom: so really, it’s the same thing. Precedence, or data structure… LISP just lets you know what is going on under the hood. |
| 22:55 | bbloom | julianleviston: in clojure it's an abstraction provided to the object program |
| 22:56 | bbloom | julianleviston: i disagree with the notion of "under the hood" |
| 22:56 | julianleviston | bbloom: Ok. |
| 22:56 | julianleviston | bbloom: i disagree with the notion of disagreement. |
| 22:57 | julianleviston | bbloom: also, parens are not only for precedence in C. The parens I was talking about are for function call notation. |
| 22:58 | julianleviston | bbloom: which can be viewed as a data structure indicating to the compiler to call a function… which is what a list is used for in LISP |
| 22:58 | julianleviston | bbloom: granted C is in no way homoiconic, but the parallel is there IMHO. |
| 23:00 | julianleviston | bbloom: what’s your point? :-) |
| 23:01 | Lewix | bbloom: good point |
| 23:01 | julianleviston | bbloom: I like that clojure adds vectors so that linear data collections can have a separate reader syntax to program form syntax, though. That alone makes understanding clojure code so much easier than, say, scheme, or CLISP. |
| 23:01 | dnolen | julianleviston: I think you missed the simple point that C source isn't data structure the way Lisp and the benefits derived therein. In you have to go all the way to the AST. In Lisp you don't. Thank god. But the real AST is there in those rare cases that you need. |
| 23:01 | Lewix | the documention of closure sucks |
| 23:01 | Lewix | ,(doc cons) |
| 23:01 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 23:02 | Lewix | really? you dont tell me how to use it |
| 23:02 | bbloom | Lewix: every single function would have to tell you how to use it |
| 23:02 | bbloom | Lewix: the clojure docs are not for beginners |
| 23:02 | julianleviston | Lewix: sure it does… the [] is the arument list - it takes two… x and a seq… |
| 23:02 | bbloom | at least the functions are |
| 23:02 | Lewix | I dont know i can do this |
| 23:02 | dnolen | Lewix: http://clojuredocs.org |
| 23:02 | Lewix | ,(cons "doc didnt help" (1 2 3)) |
| 23:02 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 23:02 | Lewix | ,(cons "doc didnt help" [1 2 3]) |
| 23:02 | clojurebot | ("doc didnt help" 1 2 3) |
| 23:03 | bbloom | Lewix: you're trying to do multiple things at once & you don't understand the primitives |
| 23:03 | bbloom | type (1 2 3) in to your REPL by itself |
| 23:03 | bbloom | note that a leading comma uses a repl here |
| 23:03 | Lewix | ,(cons "doc didnt help" `(1 2 3)) |
| 23:03 | clojurebot | ("doc didnt help" 1 2 3) |
| 23:03 | julianleviston | Lewix: sadly we’re not QUITE at the self-describing pedagogical language we’d all love… but CLJ is a huge step there compared to other modern languages. |
| 23:03 | bbloom | ,(1 2 3) |
| 23:03 | clojurebot | #<ClassCastException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn> |
| 23:03 | Lewix | I still think the doc sucks |
| 23:03 | julianleviston | Lewix: no way, man. |
| 23:04 | julianleviston | Lewix: it’s there for people who know how to read it. |
| 23:04 | Lewix | julianleviston: it doesnt tell me what it return |
| 23:04 | Lewix | theres many form of sequences from what I read |
| 23:04 | julianleviston | Lewix: (source cons) does tho |
| 23:04 | bbloom | (doc cons) |
| 23:04 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 23:04 | bbloom | "returns" is literally the first word of the doc string |
| 23:04 | Lewix | i don't know if it's a list or a lazsequence for example |
| 23:04 | julianleviston | Lewix: ah… it’s a SEQ. |
| 23:04 | gfredericks | that's usually not important |
| 23:05 | julianleviston | Lewix: that’s a thing. |
| 23:05 | Lewix | ,(list? (cons "doc didnt help" `(1 2 3))) |
| 23:05 | clojurebot | false |
| 23:05 | bbloom | ~list? |
| 23:05 | clojurebot | excusez-moi |
| 23:05 | bbloom | ~list |
| 23:05 | clojurebot | excusez-moi |
| 23:05 | bbloom | dammit clojure-bot |
| 23:05 | julianleviston | (seq? (cons ‘yay nil)) |
| 23:05 | julianleviston | Lewix: erm… how would you impove it? |
| 23:06 | julianleviston | any less terse and you’d annoy people who don’t want to wade thru crap to get to the info. |
| 23:06 | julianleviston | Lewix: read this: http://clojure.org/sequences |
| 23:06 | Lewix | julianleviston: just be more specific. There's no excuses - some others languages have good doc |
| 23:06 | julianleviston | Lewix: I don’t follow… that *IS* very specific. |
| 23:06 | bbloom | Lewix: you're wishing for the wrong solution to your problem |
| 23:06 | julianleviston | it returns a seq. That’s what it does. |
| 23:06 | bbloom | Lewix: typical clojure users quite like clojure's docstrings |
| 23:06 | Lewix | I'm no wishing for anything |
| 23:06 | bbloom | Lewix: you need a book |
| 23:06 | bbloom | ~book |
| 23:06 | clojurebot | book is programming clojure |
| 23:07 | Lewix | julianleviston: a list is considered a seq |
| 23:07 | julianleviston | bbloom: agreed! |
| 23:07 | julianleviston | Lewix: um… what? |
| 23:07 | julianleviston | Lewix: dude… learn more. |
| 23:07 | julianleviston | go read that link I just sent you. |
| 23:07 | bbloom | julianleviston: that's not helpful |
| 23:07 | julianleviston | bbloom: no but the link may be. :) |
| 23:07 | bbloom | ~colls |
| 23:07 | clojurebot | colls is seqs and colls |
| 23:07 | bbloom | ~seqs |
| 23:07 | clojurebot | seqs is http://www.brainonfire.net/files/seqs-and-colls/main.html |
| 23:07 | julianleviston | bbloom: I’m just explaining that he needs to learn more. |
| 23:07 | bbloom | ^^ that link is more helpful |
| 23:07 | bbloom | but still, it's not helpful at all |
| 23:08 | gfredericks | julianleviston: a list is a seq though |
| 23:08 | Lewix | so wait |
| 23:08 | bbloom | Lewix: try http://www.braveclojure.com/ |
| 23:08 | julianleviston | bbloom: Sure it is :) You just hate me :) |
| 23:08 | Lewix | you guys are telling me that list are not seq ? |
| 23:08 | julianleviston | bbloom: oh god not that! |
| 23:08 | Lewix | (seq? `(1 2 3 4)) |
| 23:08 | Lewix | ,(seq? `(1 2 3 4)) |
| 23:08 | clojurebot | true |
| 23:08 | julianleviston | ,(type `(1 2 3 4)) |
| 23:08 | clojurebot | clojure.lang.Cons |
| 23:08 | amalloy | lists are seqs for sure |
| 23:09 | tomjack | bbloom: hey! after years of willful ignorance, oleg/filinski/delimc/effects/etc have come back around and bit me on the ass. just curious, is getting ext_test.clj in eclj to work a TODO, or is it supposed to work? |
| 23:09 | Lewix | amalloy: exactly which bring me back to my point. |
| 23:09 | Lewix | the doc could be more specific |
| 23:09 | gfredericks | amalloy: I have though heard it argued that lists being seqs is an impl detail |
| 23:09 | amalloy | hm |
| 23:09 | gfredericks | Lewix: more specific how? |
| 23:09 | gfredericks | saying it returns a list? |
| 23:09 | Lewix | gfredericks: saying that it returns a seq is confusing |
| 23:09 | bbloom | tomjack: nothign in eclj is supposed to work :-P |
| 23:10 | Lewix | ,(seq? `(1 2 3 4)) |
| 23:10 | clojurebot | true |
| 23:10 | bbloom | tomjack: it's totally me exploring stuff. not sure what state i left it in |
| 23:10 | Lewix | ,(list? (cons "doc didnt help" `(1 2 3))) |
| 23:10 | clojurebot | false |
| 23:10 | tomjack | ah, ok |
| 23:10 | tomjack | well, thanks for it, quite inspiring |
| 23:10 | julianleviston | Lewix: I think if you find the docs confusing, then it’s probably because you need to increase your knowledge of clojure. They’re not there to teach you clojure. They’re there to explain how things work once you know. |
| 23:10 | bbloom | tomjack: cool. glad you like it |
| 23:10 | gfredericks | Lewix: not sure what the confusion is, what else would it say? |
| 23:10 | Lewix | julianleviston: you just told me that list are not a seq, in my defense |
| 23:10 | julianleviston | Lewix: it isn’t. |
| 23:11 | julianleviston | Lewix: they’re not identical. |
| 23:11 | amalloy | julianleviston: it one million percent is. if you're going to condescend to Lewix at least be right |
| 23:11 | julianleviston | Lewix: the relationship is inclusive. |
| 23:11 | Lewix | from what i gather list and lazyseq are both seq |
| 23:11 | julianleviston | amalloy: I wasn’t aware I was being condescending. Apologies! |
| 23:11 | julianleviston | amalloy: me recommending someone else learn more doesn’t preclude me from not being ignorant! |
| 23:12 | bbloom | julianleviston: "learn more" is just a dick way to say anything |
| 23:12 | gfredericks | (inc bbloom) |
| 23:12 | julianleviston | bbloom: is it? I thought it was concise. |
| 23:12 | gfredericks | sometimes concision is dickish |
| 23:12 | julianleviston | bbloom: sorry for being a dick! |
| 23:12 | gfredericks | despite intentions |
| 23:12 | julianleviston | haha :) ok. |
| 23:13 | julianleviston | apologies for my dick. |
| 23:13 | julianleviston | ish. |
| 23:13 | julianleviston | ness. |
| 23:13 | gfredericks | especially on the internet where people can't see your face |
| 23:13 | julianleviston | Lewix: dude… apologies… I am on your side. |
| 23:13 | julianleviston | Lewix: I am here to help, and I’m interesed in all of our betterment. |
| 23:13 | amalloy | gfredericks: upcoming project: replace every website with a picture of my face |
| 23:14 | jonh | , (type (cons "doc didnt help" `(1 2 3))) |
| 23:14 | clojurebot | clojure.lang.Cons |
| 23:14 | Lewix | julianleviston: no worries |
| 23:15 | jonh | Lewix: so my guess is that is why list? does not return true |
| 23:15 | julianleviston | Lewix: also, I need to learn as much, if not more, than you… |
| 23:15 | Lewix | julianleviston: I doubt. I started three days ago. You'll probably know more |
| 23:15 | Lewix | You* |
| 23:16 | julianleviston | this might help… |
| 23:16 | julianleviston | ,(list) |
| 23:16 | clojurebot | () |
| 23:16 | julianleviston | ,(list? (list)) |
| 23:16 | clojurebot | true |
| 23:16 | julianleviston | ,(seq? (list)) |
| 23:16 | clojurebot | true |
| 23:17 | julianleviston | ,(list? (seq)) |
| 23:17 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/seq--4091> |
| 23:17 | julianleviston | ,(list? (seq (list))) |
| 23:17 | jonh | pwnd |
| 23:17 | clojurebot | false |
| 23:17 | julianleviston | does that help? |
| 23:17 | gfredericks | amalloy: I'm writing a movie script based on the premise that you somehow succeed at doing so despite the various reasons it's impossible |
| 23:17 | gfredericks | amalloy: experts are baffled |
| 23:18 | amalloy | gfredericks: sequel to The Core? |
| 23:18 | gfredericks | yeah bruce willis and a small team are going to hack into the internet to take those amalloy photos down |
| 23:18 | gfredericks | using guns |
| 23:19 | gfredericks | a side plot would involve the efforts by web designers to adapt their UIs to the new constraint of having amalloy's photo in the middle of the page |
| 23:20 | julianleviston | ,(type (seq [1 2])) |
| 23:20 | clojurebot | clojure.lang.PersistentVector$ChunkedSeq |
| 23:20 | gfredericks | ,(deftype ChocolateChunkedSeq []) |
| 23:20 | clojurebot | sandbox.ChocolateChunkedSeq |
| 23:20 | julianleviston | ,(list? (seq [1 2])) |
| 23:20 | clojurebot | false |
| 23:21 | julianleviston | ,(type (seq (list 1 2))) |
| 23:21 | clojurebot | clojure.lang.PersistentList |
| 23:21 | julianleviston | obviously that’s a list, whereas a seq’d vector isn’t, right? |
| 23:21 | julianleviston | but both are seq’s… right? |
| 23:21 | gfredericks | right |
| 23:21 | julianleviston | Lewix: ergo… some seqs ARE lists, others aren't... |
| 23:21 | julianleviston | Lewix: but all lists are seqs. |
| 23:22 | gfredericks | julianleviston: I think that's what Lewix meant, you were just misinterpreting |
| 23:22 | julianleviston | gfredericks: oh ok. Sorry, I thought he thought List == Seq or something with semantic equivalency. |
| 23:24 | raspasov | hey guys, atom/STM question |
| 23:24 | julianleviston | Lewix: it doesn’t help much that there are a bunch of things that make you think they’re all the same coz they start with the letters s e q, but they’re not exactly the same… |
| 23:24 | raspasov | so if from one thread I do something like (def x (atom 0)) (swap! x + 1) @x |
| 23:25 | jonh | Lewix initial example was a cons though, thats why list? says false |
| 23:25 | raspasov | I am guaranteed to get @x to be 1, that's clear |
| 23:25 | raspasov | what about other threads though? if there's updates coming to the x atom, are all other threads guaranteed to see "latest" state or just a "valid" state when deref-ing x? |
| 23:26 | Lewix | julianleviston: What I was saying all along is - vectors, lists, lazyseq are all sequential, lists and lazyseq are both seq and they're all collection. So when we document what we return, shouldn't we used the right term to avoid confusion |
| 23:26 | Lewix | s/used/use |
| 23:27 | gfredericks | Lewix: and what's the right term in the case of cons? |
| 23:27 | Lewix | if we return lazyseq we don't want to say we return seq - it leads to confusion. That was all i was trying to say - I guess there was some confusion or I didn't express myself properly |
| 23:27 | Lewix | (doc cons) |
| 23:27 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 23:27 | Lewix | ,(doc cons) |
| 23:27 | julianleviston | Lewix: I’m curious if that precision has any real world ramifications, though? The docs seem to explicitly refer to the level of detail that is particular to the context… so if “seq” (meaning the abstraction) is the guarantee, they tend to say that… perhaps I’m wrong, tho… it’s usual. |
| 23:27 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 23:28 | Lewix | julianleviston: even if it doesn't have real implications - better be safe than sorry especially when it does not cost much |
| 23:28 | jonh | ,(type (cons 1 [2 3])) |
| 23:28 | clojurebot | clojure.lang.Cons |
| 23:28 | julianleviston | Lewix: not if the level of “vagueness” is actually what’s precisely intended, tho… |
| 23:28 | Lewix | gfredericks: right term is lazyseq I think |
| 23:29 | gfredericks | Lewix: it's not a lazy seq |
| 23:29 | Lewix | gfredericks: If it's a seq and it's not a list, chances are it's a lazy seq I thought |
| 23:29 | gfredericks | there are other kinds of seqs besides lazy & list; and the idea is that you shouldn't have to care what kind it is |
| 23:29 | julianleviston | Lewix: a seq is something that adheres to that protocol, isn’t it? that’s the limit of the guarantee of that function signature, righ? |
| 23:30 | julianleviston | (inc gfredericks) |
| 23:30 | julianleviston | nice explanation! |
| 23:30 | Lewix | gfredericks: I dislike that train of though. I really care about precision |
| 23:30 | Lewix | thought* |
| 23:30 | julianleviston | Lewix: it *is* precise. |
| 23:31 | julianleviston | Lewix: precisely not detailed. |
| 23:31 | amalloy | clojure, the best precisely-vague language |
| 23:31 | julianleviston | amalloy: lol. Protocols are “precisely vague” :) |
| 23:31 | Lewix | if you expect it to return a seq then it would mean that it could also return a list. How precise is that? |
| 23:32 | Lewix | (However in our situation it does not return a list) |
| 23:32 | julianleviston | Lewix: It’s precise because if you choose something that builds or deals with seqs, you care about the properties of seq’ing… and not the extra properties. |
| 23:32 | julianleviston | Lewix: if you wanted a list, don’t ask for a seq. Likewise if you want a set, don’t use a vector! |
| 23:35 | julianleviston | raspasov: I don’t really remember, but I remember that the rich hickey ants talk goes into it quite well… https://www.youtube.com/watch?v=dGVqrGmwOAw |
| 23:36 | raspasov | julianleviston: yea I thought it does (I have seen this video multiple times - maybe a time for a re-watch) lol, it uses java AtomicReferences, which should ensure that changes are visible to all threads |
| 23:36 | julianleviston | raspasov: he explains the different types of refs and what you want to use each for, and the guarantees of each. |
| 23:36 | jonh | Lewix: (list? (cons 1 nil)) :) |
| 23:37 | Lewix | jonh: I'm still looking for the simple and easy part - especially after your example... |
| 23:37 | raspasov | julianleviston: I think problem is in my code most likely, so investigating there first : ) pretty sure changes are always visible |
| 23:37 | julianleviston | raspasov: oh it depends on “when” you’re talking about, I guess… from what I understand, everything happens in atomic sets… so you have a consistent view of the world… so they would all see the state, but only at the point in time at which you ask for the value (by dereffing)… does that cover your q? |
| 23:38 | raspasov | julianleviston: yes, basically... |
| 23:39 | jonh | Lewix: leaky abstractions, kinda feels javascript esque |
| 23:39 | julianleviston | raspasov: yeah, gotta make sure each thread isn’t getting its own separate atom |
| 23:39 | raspasov | julianleviston: or like, a different state of the same atom |
| 23:39 | Lewix | jonh: exactly |
| 23:39 | julianleviston | jonh: whatcha mean? |
| 23:39 | jonh | , (list? (cons 1 nil)) |
| 23:39 | clojurebot | true |
| 23:40 | julianleviston | raspasov: um… yeah, I think you might not want an atom, depending on what you’re after… you need dosync and whatnot. no? |
| 23:40 | justin_smith | Lewix: the easy /simple part is concreyr types rarely matter. what matters are thr interfaces. |
| 23:40 | julianleviston | jonh: Sorry… not really sure waht your point is :S |
| 23:41 | justin_smith | *concrete that is |
| 23:41 | raspasov | julianleviston: yea, thanks, I'm familiar with refs, etc thanks for your input :) debugging now |
| 23:41 | julianleviston | raspasov: sorry :) |
| 23:42 | jonh | sorry to hear that |
| 23:42 | julianleviston | jonh: I’d love to know, if you care to explain :) |
| 23:42 | julianleviston | ,(type (cons 1 nil)) |
| 23:42 | clojurebot | clojure.lang.PersistentList |
| 23:43 | julianleviston | That seems to be a list. |
| 23:43 | julianleviston | … and it has returned a seq. Just like the docs for cons say it should. |
| 23:44 | julianleviston | your abstraction has to be reified in SOME concrete entity, right? It happens to be a list from cons at clojure’s current version. |
| 23:45 | julianleviston | jonh: not really sure how that’s a leaky abstraction… ? |
| 23:46 | justin_smith | Lewix: imagine if I were asking what type '/' returns... |
| 23:46 | codestorm777 | http://stackoverflow.com/questions/4104805/erlang-persistent-data-structures |
| 23:46 | julianleviston | justin_smith: I just had a thought - maybe they want typed clojure! |
| 23:46 | julianleviston | justin_smith: should send them to that project. |
| 23:49 | julianleviston | Lewix: you might like this: https://github.com/clojure/core.typed |
| 23:50 | julianleviston | Lewix: and judging from our convos here, I think you’d LOVE haskell, if you haven’t already learned it. |
| 23:51 | Lewix | justin_smith: |
| 23:51 | Lewix | ,(type \/) |
| 23:51 | clojurebot | java.lang.Character |
| 23:52 | julianleviston | Lewix: erm… \/ is the backslach char… |
| 23:52 | justin_smith | Lewix: I meant the division operator, and what it returns varies based on context but the applicable interface is Number |
| 23:52 | julianleviston | backslash even. |
| 23:52 | justin_smith | julianleviston: it's forwardslash |
| 23:52 | julianleviston | justin_smith: soz… guh. Yeah. |
| 23:53 | justin_smith | Lewix: the rules for what kind of Number you get back don't belong in the docs for '/', they belong in the docs on the math operators |
| 23:54 | Lewix | justin_smith: like most languages |
| 23:54 | justin_smith | Lewix: similarly, seq suffices for documenting cons, but there is extensive clojure documentation on what a seq means, and which things can be considered seqs, etc. |
| 23:54 | justin_smith | Lewix: most of the time, "seq" or "Number" are enough to go on |
| 23:54 | Lewix | ./ is not a data structure |
| 23:54 | justin_smith | Lewix: sometimes, you really want to get into the details |
| 23:55 | justin_smith | Lewix: nor is cons |
| 23:55 | justin_smith | cons RETURNS a data structure |
| 23:55 | Lewix | list is |
| 23:55 | julianleviston | Lewix: it *would* be nice if there was a bit by bit path pedagogical learning environment, like Racket has… |
| 23:55 | justin_smith | Lewix and in fact, / can return data structures, for example ##(/ 2 3) |
| 23:55 | justin_smith | that is a data structure |
| 23:55 | Lewix | justin_smith: my issue is not about cons |
| 23:56 | Lewix | my issue is if you tell me it return a bottle i expect a bottle |
| 23:56 | Lewix | if you tell me it returns a seq i expect a seq |
| 23:56 | justin_smith | Lewix: and there are at least 20 things that are seqs |
| 23:56 | justin_smith | seq is a general category |
| 23:56 | Lewix | exactly |
| 23:56 | justin_smith | like Number |
| 23:56 | justin_smith | returns a Number |
| 23:56 | justin_smith | same thing |
| 23:56 | julianleviston | Lewix: what if you return a number, and I give you 5.0 ? But… that’s not a number… yes it is…. it’s a float… which is a number. |
| 23:56 | justin_smith | err |
| 23:56 | justin_smith | / returns a number |
| 23:56 | justin_smith | cons returns a seq, same thing |
| 23:57 | Lewix | not the same thing |
| 23:57 | justin_smith | Number is an interface describing many numeric types |
| 23:57 | justin_smith | seq is an interface describing many ordered collections |
| 23:57 | julianleviston | :) |
| 23:57 | Lewix | let's just agree to disagree |
| 23:58 | julianleviston | um… no, justin_smith isn’t incorrect. |
| 23:58 | Lewix | ,(doc /) |
| 23:58 | clojurebot | "([x] [x y] [x y & more]); If no denominators are supplied, returns 1/numerator, else returns numerator divided by all of the denominators." |
| 23:58 | justin_smith | Lewix: can you describe to me how the disparate classes Double, Float, Rational etc. can all be Numbers, but somehow a list can't be a seq? |
| 23:58 | Lewix | much better than |
| 23:58 | Lewix | ,(doc cons) |
| 23:58 | clojurebot | "([x seq]); Returns a new seq where x is the first element and seq is the rest." |
| 23:58 | justin_smith | Lewix: in fact, the docs for seq are much more precise |
| 23:58 | justin_smith | / doesn't even mention numbers |
| 23:58 | Lewix | which doesnt tell you that in its seq it does not include list unless you provide nil as the second arg |
| 23:58 | julianleviston | Lewix: are you having a problem with the fact that one of the arguments is named seq there? |
| 23:59 | Lewix | justin_smith: right but its better in the sense that its not incorrect |
| 23:59 | justin_smith | Lewix: it explicitly says it returns a seq |
| 23:59 | Lewix | or partially incorrect |
| 23:59 | justin_smith | and it always does |
| 23:59 | julianleviston | Lewix: the docs for / don’t actually tell you the type it returns at all! |