2013-08-16
| 01:36 | heath | what's a vector? |
| 01:36 | heath | i hail from python and javascript with some experience in haskell |
| 01:37 | heath | http://www.cplusplus.com/reference/vector/vector/ |
| 01:37 | heath | that explains |
| 01:37 | heath | similar to the math concept |
| 01:38 | callen | heath: no |
| 01:38 | callen | heath: it's not the same. |
| 01:38 | brehaut | a vector is closer to an array in javascript or a list in python |
| 01:38 | brehaut | but backed by a trie structure |
| 01:38 | brehaut | its associative with integer keys |
| 01:38 | heath | tree? |
| 01:38 | callen | heath: trie. |
| 01:38 | brehaut | trie |
| 01:38 | heath | wow |
| 01:38 | heath | ya really meant that |
| 01:38 | heath | kk |
| 01:39 | brehaut | its cheap to add and remove from the end of a vector, |
| 01:39 | callen | heath: hash array mapped tries. (HAMT) |
| 01:39 | brehaut | (rahter than the start like a list) |
| 01:39 | brehaut | and it has fast (near constant time) lookup for indices |
| 01:39 | callen | heath: the data structures are designed to be persistent, that's how you have efficient immutability. |
| 01:40 | callen | heath: without it, you'd basically have to copy-on-create or copy-on-write. |
| 01:40 | callen | which, you know, sucks. |
| 01:40 | callen | and COW doesn't even really make sense in this context. |
| 01:40 | brehaut | oh, and (unlike python lists) vectors are values |
| 01:41 | callen | heath: http://www.infoq.com/presentations/Value-Values |
| 01:41 | heath | how could you make use of a vector's value? |
| 01:41 | callen | for any wondering, yes carmine is awesome. |
| 01:41 | brehaut | compare {(1,2): "a"} and {([1,2]: "b"} in python |
| 01:41 | callen | ,(conj [] :blah) |
| 01:41 | clojurebot | [:blah] |
| 01:41 | brehaut | ,{[1 2] "b"} |
| 01:41 | clojurebot | {[1 2] "b"} |
| 01:42 | callen | ,([:a :b :c :d] 2) |
| 01:42 | clojurebot | :c |
| 01:44 | brehaut | (you cant use a python list as a key because it has no intrinsic value) |
| 01:44 | brehaut | (a tuple (or clojure vector) on the other hand has a value derived from the values of its members) |
| 01:48 | glosoli | newbie here, what is the equivalent when doing it Clojure way, when I for example define some sort of Person object with various attributes to it name, last name, address and tt ? was considering some sort of Map though |
| 01:49 | brehaut | just use a map |
| 01:49 | brehaut | {:name "foo bar" :address "123 fake st"} |
| 01:50 | brehaut | slightly apropos http://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/ |
| 01:52 | glosoli | brehaut: thanks |
| 01:57 | callen | brehaut: people are way too eager to grant data "thinghood" |
| 01:57 | callen | (I said it that way instead of saying "reify" so as to avoid confusion) |
| 02:20 | jwpalmer | pwd |
| 02:20 | lazybot | #clojure |
| 02:20 | jwpalmer | gah - sorry |
| 02:20 | jwpalmer | heh |
| 02:32 | heath | are a lot of you using clojure within your workplaces? |
| 02:32 | heath | i've been dependent upon coffeescript |
| 02:33 | heath | started to learn c++ to write node addons, i figure i'll need them at some point |
| 02:33 | heath | but i'm interested in learning clojurescript |
| 02:33 | heath | so many things to do! :) |
| 02:40 | SegFaultAX | Rowing is hard work. |
| 02:40 | TEttinger | heath, I think the south african clojure users are awake now. there are some smart businesses starting to see the functional programming light over there, and the pattern seems to be repeating |
| 02:41 | TEttinger | for certain tasks, you want the benefits of interop, a strong ecosystem, and stability that come with a language like clojure, more than you want anything else. |
| 02:44 | TEttinger | I tried writing a game in clojure and the performance left something to be desired. for a normal app, you don't have 16 AI creatures that need to scan a large map in 1 ms or 2, to keep up with a user hammering keys lightning fast. for a normal app, clojure's performance is fine. |
| 02:46 | heath | what's the value in immuatable collections, especially in the context of clojurescript/ |
| 02:47 | SegFaultAX | heath: Mutation free code is inherently easier to reason about. |
| 02:47 | amalloy | heath: what's the value in immutable strings? |
| 02:47 | SegFaultAX | heath: Data in, data out. |
| 02:47 | SegFaultAX | But more importantly /values/ in, /values/ out. |
| 02:48 | noonian | you get referential transparency pretty much for free |
| 02:48 | SegFaultAX | noonian: That's not strictly a side effect of immutable data. |
| 02:48 | noonian | don't have to think about not mutating things or protecting things from mutation with copying |
| 02:48 | heath | for some reason, i thought this was for languages like haskell :) a desire for mutation free code |
| 02:49 | heath | it kind of threw me off to see this in clojure |
| 02:49 | SegFaultAX | heath: In Clojure we have both. Immutable data structures are the default, but you can always drop down to good ol bit bashing when you need to. |
| 02:49 | SegFaultAX | The nice thing is, it's pretty rare in general that you even need those facilities. |
| 02:50 | noonian | SegFaultAX: but you tend to write code with that property when everything defaults to being immutable |
| 02:51 | noonian | SegFaultAX: I guess you're right its not directly from immutability my bad |
| 02:51 | SegFaultAX | noonian: The term you're looking for is probably purity, anyway. |
| 02:51 | SegFaultAX | Referential transparency is orthogonal. |
| 02:52 | noonian | purity huh |
| 02:52 | SegFaultAX | (Unfortunately those words are often conflated with each other, but they are distinct) |
| 02:52 | noonian | maybe, but then I sound like the haskell guys |
| 02:52 | SegFaultAX | noonian: You say that like it's a bad thing! :D |
| 02:53 | noidi | SegFaultAX, is it possible for a function to be pure without being referentially transparent, or vice versa? |
| 02:53 | noonian | I just think its kind of preachy and monads were invented so they can say 'we have the purist functional language of them all' |
| 02:54 | SegFaultAX | noonian: Monads are far, far older than Haskell. |
| 02:54 | SegFaultAX | noonian: And the monads you know and love from Haskell are only a very particular formulation of monads anyway. |
| 02:54 | noonian | not sure if you mean the theory or the technique, but no one called them monads when using them before |
| 02:55 | SegFaultAX | noonian: The fact that you weren't aware of it doesn't mean anything. |
| 02:55 | SegFaultAX | You personally, I mean. |
| 02:55 | noonian | weren't aware of what? |
| 02:55 | SegFaultAX | Monads. |
| 02:55 | SegFaultAX | Or category theory in general. |
| 02:56 | noonian | heh, you can use monads without calling them that |
| 02:56 | noonian | I know they came out of category theory, but you're right, I never heard of them before I heard of haskell |
| 02:57 | SegFaultAX | noonian: But that doesn't mean monads only /just/ popped into existence, and certainly not when /you/ became aware of Haskell. |
| 02:57 | noonian | and I'm not saying they did |
| 02:57 | noonian | sorry if I offended you sire |
| 02:57 | noonian | sir* |
| 02:57 | SegFaultAX | but no one called them monads when using them before < not sure what other way there is to interpret that, then. |
| 02:58 | SegFaultAX | noonian: Sire is fine. |
| 02:58 | noonian | forget it then, just interpret it as drunken ramblings |
| 02:59 | SegFaultAX | noidi: Sure! |
| 03:01 | SegFaultAX | noidi: So long as an expression/function/process/whatever can be substituted for its result or value without changing the semantics of the overall program, it can be considered effectively referentially transparent. |
| 03:01 | SegFaultAX | noidi: That really doesn't have much at all to do with mutating state. |
| 03:02 | noonian | but you can also have pure functions which mutate data in their local scope yes? |
| 03:02 | SegFaultAX | noonian: Depends on the definition of purity I guess. But in a strict sense, no. |
| 03:03 | SegFaultAX | noonian: I mean even Haskell can't be considered pure of you regard the mutation of the processor state to be a side effect. |
| 03:03 | SegFaultAX | In Clojure nothing is pure. The JVM is a black box of statefulness. |
| 03:04 | SegFaultAX | We might consider most stuff to be /effectively/ pure because out our level of abstraction, we are safe from most of the ills of side effecting code. |
| 03:04 | noonian | the wiki for pure function only talks about 'observable' side effects, and always evaluating to the same result given the same input (I know wiki isn't authoritative) |
| 03:04 | SegFaultAX | noonian: Right, but observable to whom is the question. |
| 03:04 | noonian | semantically observable |
| 03:05 | SegFaultAX | Exactly. |
| 03:05 | noonian | yeah, so if you are the processor then you're out of luck. But as a programmer, we get to have pure functions that may or may not mutate state internally |
| 03:06 | SegFaultAX | Haskells state monad uses this trick extensively. It creates an opaque memory region to localize mutation, but since literally nothing else can see into that mutation, it can be considered pure. |
| 03:08 | SegFaultAX | noonian: In Clojure we have to remember that we're interoping with a fundamentally stateful host, so nothing we write is truly pure. It's doing IO and stuff /all the time/. It's arguable if you can even consider it effectively pure, but I'm not pedantic enough to argue the point beyond that. |
| 03:08 | noonian | hmm, I don't understand that point |
| 03:09 | noonian | how is a function, say (fn [x] (+ x 10)), not pure? |
| 03:09 | SegFaultAX | noonian: The JVM is not pure. |
| 03:10 | noonian | but that doesn't mean you can't write pure functions that run on the jvm |
| 03:10 | SegFaultAX | noonian: Meh. |
| 03:10 | SegFaultAX | noonian: Like I said, it's a pedantic argument at best. |
| 03:10 | noonian | I can agree with that at least :P |
| 03:11 | noonian | actually, that was the point I tried to make originally |
| 03:22 | noidi | SegFaultAX, ah, right. so a function calling (reset! nobody-uses-this :foo) is referentially transparent but impure |
| 03:24 | noonian | hmm, I don |
| 03:25 | noonian | don't think its referentially transparent either, because if you replaced it with the return value it would change the programs behavior |
| 03:31 | noonian | I guess according to the definition of purity segfault put forth earlier, any referentially transparent function that uses mutation internally wouldn't be pure |
| 04:45 | supersym | SegFaultAX: I recall RH wrote somewhere the 'if a tree falls in the forrest but no one is around, does it make a sound?' parabole, which was internal mutations as well I believe |
| 04:46 | supersym | I hadn't related it to monads yet though so I think that was a nice summary of some stuff somewhere I knew subconsiously |
| 04:52 | callen | parable |
| 05:06 | supersym | really, I made an error? nooo.... or are you french? Are you French Clyde? |
| 05:06 | supersym | sorry, I'm baked :P |
| 05:06 | Raynes | supersym: Need more edibles. |
| 05:09 | supersym | lol... yea |
| 05:35 | turbopape | Hi all, |
| 05:35 | turbopape | anyone can share experience working with Riak / Welle ? |
| 05:35 | turbopape | is it sable ? Well maintained ? |
| 05:38 | schmir | turbopape: I'm using langohr from michael klishin...he's quite responsive |
| 06:50 | antares_ | turbopape: it is but don't use master, I'm breaking many things for 2.0 |
| 06:50 | antares_ | Riak is wonderful if its data model fits your problem well. Unbreakable in prod, easy to operate. |
| 06:51 | antares_ | can be a royal pain to develop against, too |
| 06:54 | antares_ | Only a few places left for the 2 day Munich Clojure workshop in October: http://clojureworkshop.com |
| 07:00 | callen | oi vey. finally done. |
| 07:01 | callen | https://github.com/bitemyapp/bulwark |
| 08:36 | noncom | hi, in clojurescript, how do i create a Date object and then setFullYear on it? |
| 08:36 | noncom | currently I do (.setFullYear (js/Date. ) 2000) but it does not work |
| 08:37 | noncom | says Uncaught Error: No protocol method ILookup.-lookup defined for type object: Fri Aug 16 2013 16:09:29 GMT+0400 (Russian Standard Time) |
| 08:38 | noncom | i would believe that it can't call the method on the date-time string, but it is not a string, the (type (js/Date.)) gives function Date() { [native code] } |
| 08:46 | edlothiol | noncom: (.setFullYear (js/Date. ) 2000) does work for me, are you sure that's what you're using? though note that setFullYear doesn't return the date object, so you probably want something like (let [d (js/Date.)] (.setFullYear d 2000) d) |
| 08:47 | mpenet | ,(doc doto) |
| 08:47 | clojurebot | "([x & forms]); Evaluates x then calls all of the methods and functions with the value of x supplied at the front of the given arguments. The forms are evaluated in order. Returns x. (doto (new java.util.HashMap) (.put \"a\" 1) (.put \"b\" 2))" |
| 08:47 | edlothiol | or that |
| 08:48 | tbaldridge | dnolen: have you seen the problem described in http://dev.clojure.org/jira/browse/ASYNC-2 recently? |
| 08:52 | mdrogalis | tbaldridge: Is there any plans to add a "topic"-like queue-construct to core.async? |
| 08:52 | mdrogalis | E.g. a queue that multiple people can consume the same messages from. |
| 08:54 | tbaldridge | mdrogalis: you mean pub/sub? |
| 08:55 | H4ns | is there function that returns a function's name, if it has one? |
| 08:55 | noncom | edlothiol: actually, i have a clojuric datastructure that pronts to the console as {:value "2000"} then, when I try (.setFullYear (js/Date. ) (:value my-struct)) i get that error |
| 08:56 | noncom | now i see that "2000" in the structure is not a stringwhen i print (type) of it, it is function String() { [native code] } |
| 08:56 | mdrogalis | tbaldridge: Pretty much, yup |
| 08:56 | noncom | and if i (js/parseInt) on it, i get NaN |
| 08:57 | noncom | ,(js/Date.) |
| 08:57 | clojurebot | #<CompilerException java.lang.RuntimeException: No such namespace: js, compiling:(NO_SOURCE_PATH:0:0)> |
| 08:57 | noncom | sure |
| 08:57 | tbaldridge | mdrogalis: no, there are no official plans. in clojure.core.async.lab there are primitives for pub/sub but they are experimental as they use low level core.async protocols. |
| 08:58 | tbaldridge | mdrogalis: that being said, you can build pub/sub from normal channels in about 30 lines of code or so |
| 08:58 | mdrogalis | H4ns: (:name (meta (var f))) |
| 08:58 | mdrogalis | tbaldridge: Yeah I was thinking about that this morning. Doesn't seem difficult. |
| 08:58 | H4ns | mdrogalis: *bow* |
| 08:58 | mdrogalis | H4ns: :) |
| 08:58 | mdrogalis | tbaldridge: Why go down to low level protocols to do it in exp then? |
| 08:59 | noncom | edlothiol: somehow that "2000" is not a string... |
| 08:59 | tbaldridge | mdrogalis: the nice thing about that approach is that you can build your own semantics that work for you. E.g. do you add new subs via a subscribe channel, or do you call a function that updates an atom, etc. |
| 09:01 | mdrogalis | tbaldridge: Intriguing. |
| 09:01 | noncom | edlothiol: then what is it?.. i have got it by calling (subs) on s string |
| 09:09 | noncom | ok, i have got why it happens. (str), (subs) and other stringy functions in clojurescript return not javascript strings but something other... how do i make it into javascript string again? |
| 10:10 | noncom | anybody fluent with clojurescript strings here? |
| 10:41 | Anderkent | did clojure.contrib.generic.functor survive the contrib apocalypse? |
| 10:41 | Anderkent | I'm looking for fmap in particular |
| 10:43 | llasram | Anderkent: I don't think it did. Of the recent category theory libraries I know at least fluokitten has an implementation of functors and fmap https://github.com/uncomplicate/fluokitten |
| 10:43 | Anderkent | mhm. I found algo.generic which does does have it |
| 10:43 | llasram | Oh, ok cool |
| 10:44 | Anderkent | but it's nowhere near as powerful |
| 10:45 | Anderkent | (as what's in fluokitten, that is. I don't need all that power tho) |
| 11:10 | papercup | Hi, does anybody use pallet here (specially with node-list option) ? |
| 11:21 | boodle | hi, can someone point me to an example of selecting an aggregate (sum/count etc) data using clojure.java.jdbc (not w/ a basic SQL stmt but it's select fn) |
| 11:27 | Anderkent | boodle: I think you can use strings as identifiers.. Something like (select [{"COUNT(id)" :count}] :tablename) ? Didn't try it though |
| 11:27 | boodle | Anderkent: great, tyvm! |
| 11:28 | boodle | was trying to figure out 'entities'.. that helps alot |
| 11:28 | Anderkent | entities sounds like sqlkorma not the simple jdbc wrapper |
| 11:28 | Anderkent | with korma it's easier :P |
| 11:28 | Anderkent | ah nvm it also has entities |
| 11:29 | boodle | Anderkent: and works great. I'm converting away as no pass/fail/anysort of results returned from Korma on Updates |
| 11:29 | Anderkent | oh. That sucks. |
| 11:29 | Anderkent | luckily we have an append-only db so don't have to worry about that! :P |
| 11:30 | boodle | Anderkent: heh lucky |
| 12:07 | abp | cemerick: around? |
| 12:08 | cemerick | abp: some :-) |
| 12:10 | abp | cemerick: Can I easily re-add those whitespaces? Would you probably merge as is also? |
| 12:10 | abp | cemerick: Regarding https://github.com/cemerick/friend/pull/70 |
| 12:10 | cemerick | abp: I'd like to keep the blame clean. You should be able to selectively stage just the relevant changes to the file(s)? |
| 12:11 | abp | cemerick: Oh ok, will try tha, I'm a git newb. |
| 12:13 | cemerick | abp: git gui will allow you to do it easily, or you can use git add -i and work through it on the command line |
| 12:18 | Anderkent | if you're new to it i'd recommend using a gui to do the staging - much easier than exploring the somewhat awkward interface of git add -i |
| 12:18 | Anderkent | gitk does pretty well I think |
| 12:18 | abp | cemerick: Anderkent where using magit |
| 12:19 | cemerick | Anderkent: gitk is just a viewer, can't stage anything there AFAIK |
| 12:19 | bbloom | the best feature of git add -i is that it can launch vim for editing patches :-) |
| 12:20 | bbloom | i use add -p frequently to review my changes when i commit them |
| 12:20 | cemerick | abp: selective staging is in magit, though I don't know anything about how it's used. |
| 12:20 | Anderkent | sorry, ment gitg |
| 12:21 | cemerick | bbloom: I've become unreasonably picky about clean commits since I started using git gui and then sourcetree for staging all my commits. |
| 12:21 | bbloom | cemerick: sure, at least for publicly sharing commits |
| 12:21 | bbloom | i tend to have dozens of WIP and "hack" and other nonsense commits on a branch |
| 12:21 | bbloom | and then i rebase a bunch |
| 12:22 | bbloom | i'm only a tiny bit interested in clean commits in history so much as i am understanding my own commits, which necessitates they be clean while working with them |
| 12:23 | abp | yeah, I'm more puzzled about how to stage my commits again |
| 12:23 | cemerick | Anderkent: oh, right. Yeah, gitg is okay. I never used it because it shows sources with such a large font. :-P |
| 12:24 | Anderkent | abp: if you want to keep each commit, you can rebase --interactive and mark them both as 'edit'... But i'd just take your current state, git reset master, git add -i, select meaningful changes, and commit to create a new commit on top of master with just the right changes |
| 12:31 | rasmusto | bbloom: if you're using vim for git edits, have you used fugitive.vim? |
| 12:31 | bbloom | rasmusto: yeah, i have it installed, but i use it very sparingly |
| 12:32 | rasmusto | bbloom: I love using :Gdiff and dp/do to do the equivalent of 'git add --patch', or to just manually edit the index |
| 12:33 | bbloom | rasmusto: yeah, i've used it a few times, but i kinda suck at gitdiff. i use :Gmove all the time though to rename a file without having to close/reopen a buffer |
| 12:34 | rasmusto | bbloom: I need to rename files more, I tend to stick with my filename/fn name choices to a fault |
| 12:34 | rasmusto | heh |
| 12:35 | steckerhalter | I'm a bit confused... shouldn't clojure.core be available in any project? yet `eval` is not as it seems in some projects I try |
| 12:36 | Anderkent | steckerhalter: the (ns ..) form imports clojure.core stuff |
| 12:36 | Anderkent | if you're evaluating outside a ns (for example in a repl you say (in-ns 'new.ns) ) then you might not have core functions referred |
| 12:37 | shiranaihito | is anyone happily writing Clojure in IDEA? |
| 12:37 | Anderkent | though hm calling them via clojure.core/something should still work |
| 12:37 | Anderkent | shiranaihito: I tried it, but found it lacking in comparison to CCW. Might be my knowledge of eclipse is better than of IDEA |
| 12:37 | Anderkent | (i mean the second is definitely true, but it might be why I found ccw better) |
| 12:37 | shiranaihito | Anderkent: what's CCW? |
| 12:38 | shiranaihito | hm |
| 12:38 | steckerhalter | anderkent: ah, ok. it's ac-nrepl that calls eval without "clojure.core" and that produces an error then in Emacs |
| 12:38 | shiranaihito | well, i know IDEA _much_ better than Eclipse, would prefer to work with it instead of anything else, pretty much |
| 12:38 | justin_smith | shiranaihito: maybe counterclockwise, the clojure ide for eclipse |
| 12:38 | shiranaihito | ah, right |
| 12:38 | Anderkent | yeah |
| 12:39 | shiranaihito | JetBrains' IDEs are simply the best out there |
| 12:39 | shiranaihito | so i'd like to keep using them even with clojure :) |
| 12:40 | shiranaihito | but yeah.. the integration is not quite "there" yet :p |
| 12:41 | Anderkent | one thing i remember in la clojure was that it would do unsafe refactorings and be wrong about it without prompting |
| 12:41 | Anderkent | but that was a while ago and maybe has changed since |
| 12:43 | shiranaihito | oh :/ |
| 12:50 | technomancy | a few of the issue comments on idea's lein integration gave me the impression they were a bit confused about how things worked |
| 12:51 | technomancy | but that was like a year ago |
| 12:54 | abp | interactively staging with magit is wicked |
| 12:54 | steckerhalter | abp: why? |
| 12:54 | Anderkent | is that a positive wicked or a negative wicked |
| 12:54 | Anderkent | :P |
| 12:55 | abp | :D |
| 12:55 | abp | positive |
| 13:05 | abp | steckerhalter: Already read tutorial etc? |
| 13:05 | technomancy | does anything besides nrepl.el use the target/repl-port file that leiningen writes? |
| 13:06 | rasmusto | technomancy: vim-fireplace does |
| 13:06 | steckerhalter | abp: going through the app-tutorial |
| 13:06 | Anderkent | yeah, but it looks at it in the wrong place afaik |
| 13:06 | rasmusto | there's already a patch for the 2.3 moved repl-port file |
| 13:06 | technomancy | rasmusto: oy; I was about to fix that |
| 13:06 | ystael | Anderkent: i never knew before why i sometimes found myself in a strange ns without clojure.core referred! thank you :) |
| 13:07 | technomancy | rasmusto: is there a discussion you could point me to? |
| 13:07 | Anderkent | technomancy: there's a github issue. |
| 13:07 | Anderkent | i'd link but github is dying |
| 13:07 | rasmusto | technomancy: https://github.com/tpope/vim-fireplace/pull/98 |
| 13:07 | technomancy | dang it |
| 13:08 | technomancy | when are they going to switch github issues over to a distributed system like everything else =P |
| 13:08 | technomancy | rasmusto: thanks! |
| 13:08 | Anderkent | 98 and 88 it is |
| 13:08 | mdrogalis | Seriously bad day for GitHub. |
| 13:08 | rasmusto | technomancy: np |
| 13:09 | Anderkent | seriously bad two days for github :P |
| 13:11 | steckerhalter | I imagine it to be a tough job to keep this running with so much data and users... |
| 13:11 | Anderkent | it's not the data and users, it's the ddos |
| 13:11 | Anderkent | usually |
| 13:12 | steckerhalter | hmm, right, sure it's just that? |
| 13:12 | TimMc | Yes. |
| 13:12 | Anderkent | when it's completely down instead of just slow I'd guess it's mostly ddos |
| 13:12 | Anderkent | when you just get a random unicorn it might be some unlucky deadlock or sth |
| 13:12 | mdrogalis | GH was in Philly for a drink up last weekend. I was told they have a team of 4 exclusively to deal with stuff like this |
| 13:13 | pandeiro | anyone know about how long it takes to build openjdk7 on something like an i5? minutes? hours? |
| 13:13 | steckerhalter | and what does it benefit them DDOSing github? |
| 13:13 | Anderkent | steckerhalter: there are a couple possible motivations |
| 13:14 | technomancy | bragging rights I guess? |
| 13:14 | Anderkent | one for example is that it acts as a proof of capability. If you're trying to sell ddos to someone and you can say 'we took down github for 20 minutes' it shows you know your stuff |
| 13:15 | Anderkent | other, as technomancy says, is bragging rights. Then comes general maliciousness |
| 13:15 | Anderkent | and if you have your tinfoil hat on I can tell you about githubs competitors |
| 13:16 | ystael | Anderkent: :( that's just sad. i can see why someone might want to ddos any number of people out there, but hitting github just makes you a jerk. |
| 13:17 | Anderkent | hitting github proves you can take down a serious infrastructure, not just some random website |
| 13:17 | Anderkent | it's in the right place between huge things that ddosers cant really touch (google) and small things that no one is gonna be impressed by (your local school webpage) |
| 13:18 | Anderkent | i'm not saying its the only possible target, but it's one of them, so it gets its own share : |
| 13:18 | Anderkent | i'd be curious on what kind of ddos they're doing tho |
| 13:19 | dnolen | tbaldridge: ping |
| 13:20 | tbaldridge | dnolen: pong |
| 13:20 | Anderkent | .. for a moment there i was like 'wow, it aligned' |
| 13:20 | mdrogalis | lol |
| 13:22 | dnolen | tbaldridge: so I'm thinking about a channel where I want the throttle to be toggleable, like be able to flip it on or off |
| 13:22 | abp | what happens if I force-push to github after resetting my local branch and already opened a pull-request? |
| 13:22 | Anderkent | abp: the pull is updated |
| 13:22 | Anderkent | it 'just works' :) |
| 13:22 | abp | oh cool |
| 13:22 | abp | thanks! |
| 13:23 | tbaldridge | dnolen: throttle being, the buffer drop size? |
| 13:23 | dnolen | tbaldridge: no like a milliseconds throttle |
| 13:23 | dnolen | tbaldridge: it takes a channel of events and only emits them at a throttle speed |
| 13:23 | dnolen | throttled |
| 13:23 | bbloom | dnolen: what about 3 channels: 1) the messages 2) the timeouts 3) a control channel to set the timeout speed? |
| 13:23 | dnolen | tbaldridge: but the point here is about the flip on/off |
| 13:24 | dnolen | bbloom: I'm looking for the absolutely most succinct solution that gets the job done in this case |
| 13:24 | bbloom | dnolen: you can encapsulate the timeout channel & the control channel into a little timeout machine |
| 13:25 | bbloom | that way you could reuse a synchronization process that just syncs one channel to any arbitrary interval channel |
| 13:25 | dnolen | bbloom: yes I know the obvious ways to do this - I want to know if there's something different, smaller|simpler is key |
| 13:25 | tbaldridge | dnolen: what's the use case? are we thinking of creating thousands of these? or why does it need to be so small? |
| 13:26 | dnolen | tbaldridge: I've been working this autocompleter blog post / code for a week now |
| 13:26 | dnolen | tbaldridge: autocompleter takes throttle query strings from input field, 750 msecs throttled |
| 13:26 | dnolen | tbaldridge: but when the user switches over the menu selection, we defer control to the menu subprocess |
| 13:27 | tbaldridge | dnolen: right. |
| 13:27 | dnolen | tbaldridge: this can happen via mouse or arrow keys, autocompleter process freezes at this point |
| 13:27 | tbaldridge | So we're just creating a single one of these throttled chans in this example. |
| 13:27 | dnolen | tbaldridge: but the menu subprocess needs the unthrottled key stream to know to exit |
| 13:28 | dnolen | tbaldridge: it sounded simpler to me and generally useful to have some sort of generic toggle pattern - so I could disable to throttle when I had the channel to the menu process |
| 13:28 | dnolen | s/had/hand |
| 13:32 | tbaldridge | dnolen: hold on...I'm writing up something |
| 13:37 | tbaldridge | dnolen: I think this is all you need: https://gist.github.com/halgari/6251731 |
| 13:37 | tbaldridge | takes an input and then outputs [output-chan throttle-chan] |
| 13:38 | tbaldridge | you can send :disabled or msec to the throttle-chan to change the behavior |
| 13:38 | tbaldridge | eh, I had to edit that, there was a bug, if you reload it s/when/when-not on line 6 |
| 13:39 | justin_smith | http://sprunge.us/NEWR?clojure really weird emacs / nrepl ppring behavior - anyone know what would do this, or how to track down what would do it? |
| 13:39 | justin_smith | *pprint |
| 13:39 | dnolen | tbaldridge: heh maybe I wasn't clear I already have a working throttle |
| 13:39 | dnolen | tbaldridge: I only care about generic toggle |
| 13:39 | tbaldridge | but throttling isn't part of channels, so I don't know how it can be made generic |
| 13:52 | dnolen | tbaldridge: I think I may have to go w/ something closer to what bbloom suggested, untested version of what I'm thinking of http://gist.github.com/swannodette/6251850 |
| 13:54 | tbaldridge | dnolen: that'd work, although I'd imagine that in your use case tap would be spinning up a go for each message right? |
| 13:55 | benedikt | hæ |
| 13:55 | dnolen | tbaldridge: gist updated with something that makes more sense :) |
| 13:56 | tbaldridge | dnolen: so less of a throttle and more of a router |
| 13:56 | dnolen | tbaldridge: sorry I wasn't clear earlier - I never needed a throttle :) |
| 13:56 | dnolen | tbaldridge: I have a throttle, I wanted a router/switch |
| 13:57 | dnolen | tbaldridge: so we route into the throttle or we don't |
| 13:57 | tbaldridge | dnolen: so yeah, I think this sort of thing would be good for general use. This is kindof what clojure.core.async.lab is for. We can throw random stuff into there and see if people use it. |
| 13:58 | eric_normand | dnolen: an idea for a toggle https://gist.github.com/halgari/6251731 |
| 13:58 | eric_normand | dnolen: added as comment |
| 13:59 | dnolen | eric_normand: I don't need an enhanced toggle :) |
| 13:59 | eric_normand | dnolen: then I misunderstood |
| 14:00 | `cbp | justin_smith: I've noticed that before. Are you using windows by any chance? |
| 14:00 | justin_smith | `cbp: ubuntu, latest build of emacs from gnu source |
| 14:00 | dnolen | eric_normand: also I'm of the mind if you can avoid returning maps you should |
| 14:00 | justin_smith | latest nrepl from marmalade |
| 14:00 | justin_smith | *nrepl-el |
| 14:01 | dnolen | an improved sketch for router/switch which can take N taps http://gist.github.com/swannodette/6251850 |
| 14:01 | `cbp | justin_smith: ah, just asking cus I'm used to things not working randomly on windows but I think it's an emacs issue. When I printed on a terminal it would print fine. |
| 14:03 | justin_smith | yeah, emacs but, does not appear in a terminal repl |
| 14:04 | justin_smith | so theoretically if I pprint into a string, and then print the string... |
| 14:04 | eric_normand | dnolen: I'm confused. Where are tap and control defined? |
| 14:05 | dnolen | eric_normand: typos updated |
| 14:05 | justin_smith | `cbp: (println (with-out-str (clojure.pprint/pprint ...))) does not display the bug |
| 14:05 | justin_smith | so at least we have a workaround until someone fixes the elisp issue (whatever that is) |
| 14:07 | nacon | Suppose I have a function f that formats my variables. And I want to pass them to the format function, like this: (format "%s %s: %s" (f fst) (f snd) (f thrd)). Is there a way to reduce the number of f calls I have to write? I tried to "unpack" with apply, but was not successfull in passing them to format afterwards. |
| 14:09 | dnolen | gist updated again with `tapify` |
| 14:10 | technomancy | nDuff: yeah, was happy to see that |
| 14:10 | eric_normand | dnolen: looks cool. what do you use it for? |
| 14:11 | dnolen | eric_normand: I want to be able to route dynamically |
| 14:11 | dnolen | eric_normand: so I may have a stream of key events and I want to dynamically apply a throttle or disable it |
| 14:11 | eric_normand | dnolen: much more sophisticated than my toggle! :) |
| 14:12 | dnolen | eric_normand: I think is a pretty handy one :) |
| 14:13 | eric_normand | dnolen: yes |
| 14:13 | rasmusto | nacon: something like this? (apply format "%s %s: %s" (map f [fst snd thrd]))? |
| 14:14 | IamDrowsy | rasmusto: haha :) i was typing the exact same line |
| 14:14 | rasmusto | IamDrowsy: IhadCoffee |
| 14:15 | dnolen | eric_normand: a lot of my ideas since Lambda Jam have changed, never returns maps if you can avoid, avoid multiplex or anything like it |
| 14:15 | dnolen | eric_normand: also you were right about the race condition in my presentation |
| 14:15 | IamDrowsy | rasmusto: i am kind of drowsy.. you know... :) |
| 14:18 | nacon | rasmusto: Yes, perfect! Hmmm.. *scratches head*, I probably have to play with apply a bit to finally "get it". |
| 14:20 | rasmusto | nacon: just imagine the last argument without one set of parens |
| 14:20 | TEttinger | I honestly have no idea how that would work if you gave it the wrong number of args in the collection. ##(apply format "%s %s: %s" ["alpha" "beta" "gamma" "kappa"]) |
| 14:20 | lazybot | ⇒ "alpha beta: gamma" |
| 14:20 | TEttinger | correctly! |
| 14:21 | rasmusto | TEttinger: !! nice |
| 14:21 | TEttinger | wow, I guess format discards args it doesn't need for the format string, great |
| 14:23 | justin_smith | sadly, it is not lazy: (apply format "a %s and a %s and a %s %s %s..." (range)) |
| 14:25 | TimMc | &(apply format "a %s and a %s and a %s %s %s..." (range)) |
| 14:25 | TimMc | Oh, does it build an array? |
| 14:25 | justin_smith | it might |
| 14:25 | TimMc | Sorry 'bout that, lazybot. |
| 14:25 | lazybot | Execution Timed Out! |
| 14:25 | justin_smith | like I said, it is not lazy |
| 14:26 | TimMc | It calls to-array. |
| 14:26 | TimMc | So... that probably tries to count the seq. |
| 14:27 | justin_smith | A laziness-compatible format may be nice |
| 14:28 | tbaldridge | what's the recommended way of using a JS lib from CLJs? |
| 14:28 | TimMc | justin_smith: (defn lazy-format [s & args] (apply format s (take 1000 args))) ;; no one needs more than 1000 string interpolations, dude |
| 14:29 | justin_smith | depending on the cost of realizing the elements, a version that only realized as many items as it needs may be nice |
| 14:29 | ystael | TimMc: what about gnu autoconf |
| 14:30 | bbloom | tbaldridge: first, see the Google Closure docs for externs |
| 14:30 | bbloom | tbaldridge: then use it just like any other gclosure namespace, import goog, for example |
| 14:31 | TimMc | ystael: Nonsense, why would I ever build a tool that would have its arguments supplied dynamically? |
| 14:32 | TimMc | I'm sure every usage will be in call position. |
| 14:36 | futile | tbaldridge: is clojure-py still alive? |
| 14:37 | Foxboron | futile: if you want a LISP on python i know a option :3 |
| 14:39 | eric_normand | dnolen: race condition? wow! |
| 14:39 | gvickers | Is pomegranate the only option for dynamically loading classes and their dependecies? |
| 14:39 | eric_normand | dnolen: one question about your switch: why not pass the function you want down the control channel? |
| 14:40 | futile | Foxboron: what? |
| 14:40 | dnolen | eric_normand: you mean the tap that I want to apply? |
| 14:41 | Foxboron | futile: afaik, clojure-py is dead or rather low activity, but there is something called Hy if you want a LISP on python. |
| 14:42 | eric_normand | dnolen: right; tapify just does this: (apply f in args) |
| 14:42 | eric_normand | dnolen: and wraps it neatly in a map |
| 14:42 | eric_normand | dnolen: why not just pass f and args on control channel? |
| 14:42 | eric_normand | dnolen: do it right there inline? |
| 14:43 | dnolen | eric_normand: hmm, worth thinking about ... I broke out tapify because it might be useful elsewhere |
| 14:44 | eric_normand | dnolen: maybe it wouldn't work with your use cases |
| 14:44 | futile | Foxboron: setv :P |
| 14:44 | eric_normand | dnolen: I don't know how you could make a throttle with a regular function |
| 14:45 | dnolen | eric_normand: right |
| 14:45 | dnolen | eric_normand: f in tapify must be a channel constructor |
| 14:45 | eric_normand | so (tapify throttle 200) |
| 14:45 | dnolen | eric_normand: yes |
| 14:45 | eric_normand | dnolen: makes sense |
| 14:46 | eric_normand | dnolen: keeps channel state around |
| 14:46 | eric_normand | dnolen: if you passed the constructor down the control channel (instead of an index), you'd lose state |
| 14:46 | dnolen | eric_normand: yes |
| 14:47 | eric_normand | dnolen: I am satisfied :) |
| 14:47 | Foxboron | futile: *cough* a few CL people there :3 Should note it has some clojure inspired features, but it isnt clojure. Just a LISP dialect |
| 14:47 | futile | Foxboron: gross |
| 14:47 | Foxboron | futile: it compiles down to Python AST, so you can import hy too python and python too hy |
| 14:47 | dnolen | eric_normand: now that you mention it, you can build a scheduler with this |
| 14:47 | Foxboron | futile: its neat |
| 14:47 | eric_normand | dnolen: yes? |
| 14:48 | futile | Foxboron: sounds neat. just wish it was more like clojure. |
| 14:48 | futile | Foxboron: id rather use clojure-py if it compiles down to pythonast |
| 14:49 | eric_normand | dnolen: I've been thinking a lot about generic channel transformers |
| 14:49 | dnolen | eric_normand: a very simplistic one anyway |
| 14:49 | eric_normand | dnolen: such as map, filter, etc |
| 14:49 | edw | dakrone, you around? |
| 14:49 | dnolen | eric_normand: like reactive stuff? |
| 14:49 | Foxboron | futile: i don't think doe actually. Can't remember. |
| 14:49 | Foxboron | does* |
| 14:49 | dakrone | edw: yep |
| 14:49 | eric_normand | dnolen: they are tough when you have to take into account closing |
| 14:49 | futile | Foxboron: k |
| 14:50 | eric_normand | dnolen: yes |
| 14:50 | dakrone | edw: what's up? |
| 14:50 | eric_normand | dnolen: closing upstream vs downstream, etc |
| 14:50 | edw | Hi. I was having a prob with the clj-http client and was wondering if you might have some thoughts. |
| 14:50 | dnolen | eric_normand: yes though closing is less important in interactive applications than it would seem |
| 14:50 | dnolen | eric_normand: just remove event sources at exit at the root, everything will get GCed |
| 14:50 | dakrone | edw: what's the issue? |
| 14:50 | edw | Basically, I'm trying to get connection pooling to work with a cookie store, without success. |
| 14:50 | eric_normand | dnolen: yes, you could just leave things open, never closing |
| 14:51 | edw | Sorry dakrone, long sentences… |
| 14:51 | dakrone | edw: no worries |
| 14:51 | eric_normand | dnolen: but would things get gc'd in complex scenarios? |
| 14:51 | dnolen | eric_normand: I've got some fun stuff here - https://github.com/swannodette/swannodette.github.com/blob/autocomplete/code/blog/src/blog/utils/reactive.cljs |
| 14:51 | dnolen | eric_normand: yes |
| 14:51 | eric_normand | dnolen: like say we had a fan-in |
| 14:52 | tford | after looking at this for a while I think I finally understand it. tapify turns a function into a "tap" that can be passed to 'switch'. 'switch' takes an input channel, N taps, and a control channel.. a value sent on the control channel tells 'switch' which 'tap' to send values to. Is that right? |
| 14:52 | dnolen | eric_normand: it doesn't matter how complex the graph is |
| 14:52 | dnolen | eric_normand: just remove event sources at exit at the root |
| 14:52 | dnolen | s/at/and |
| 14:52 | eric_normand | dnolen: I suppose if you are careful to remove them all |
| 14:52 | eric_normand | dnolen: from the root |
| 14:54 | dnolen | eric_normand: yes, though no different from JavaScript |
| 14:54 | eric_normand | dnolen: I still believe a truly generic fan-in would have to handle closing |
| 14:55 | eric_normand | dnolen: can't be having nils, can we? |
| 14:55 | edw | dakrone, I was wondering if the issue was thread-related, so I'm not using a dynamic var; that didn't work. Also, I tried the with-connection-pool form outside and inside with-connection-pool binding and neither worked. |
| 14:56 | dakrone | edw: can you post some code of what you're trying? |
| 14:56 | edw | Sure; I'll put together a sample. |
| 14:59 | dakrone | edw: gotta go grab a bite to eat, pm me a link and I'll check it out? |
| 14:59 | edw | Cool; thank you, dakrone. |
| 15:00 | eric_normand | dnolen: I'm curious: would a closed output channel break the idea of back pressure? |
| 15:01 | dnolen | eric_normand: how so (should probably get tbaldridge on this question) |
| 15:01 | eric_normand | dnolen: let's say you have the map implementation from your blog.utils.reactive |
| 15:01 | eric_normand | dnolen: if the out channel is closed, the >! never blocks |
| 15:02 | eric_normand | dnolen: so it will read everything from the channel and throw it away |
| 15:02 | eric_normand | dnolen: closing the out channel generates infinite back pressure |
| 15:03 | dnolen | eric_normand: I'm not sure what you're suggesting |
| 15:03 | dnolen | eric_normand: you mean closing the out channel outside of map? |
| 15:04 | eric_normand | dnolen: yes |
| 15:04 | jtoy | how do I use case with constants? this does not work when I pass 1 into the case: https://www.refheap.com/17705 |
| 15:04 | dnolen | eric_normand: yeah don't do that |
| 15:04 | eric_normand | dnolen: right |
| 15:05 | `cbp | ,(case 1 1 ":)") |
| 15:05 | clojurebot | ":)" |
| 15:07 | jtoy | but doesnt work with constants? |
| 15:07 | jtoy | i put a 1 1 in and it works, if I put (def ^:const user_pay1_status 1) and then do user_pay1_status 1 it doesnt work |
| 15:07 | tbaldridge | dnolen: I'm not sure I understand any of this. Is this the same problem from yesterday? |
| 15:08 | dnolen | tbaldridge: well eric_normand was suggesting something you should not do |
| 15:08 | tbaldridge | lol ok |
| 15:08 | dnolen | tbaldridge: unrelated to yesterday's convo |
| 15:08 | eric_normand | tbaldridge: hello! |
| 15:08 | jtoy | i want condp then |
| 15:09 | eric_normand | tbaldridge: sorry to cause trouble :) |
| 15:10 | tbaldridge | np, I love talking about this stuff |
| 15:11 | timvisher | what's the current tutorial we're passing out to people who want to get started with emacs and clojure? |
| 15:12 | technomancy | timvisher: the one on clojure-doc.org is good |
| 15:13 | justin_smith | also have them install clojure-cheatsheet.el - I just discovered it today, it is awesome |
| 15:13 | justin_smith | https://github.com/krisajenkins/clojure-cheatsheet |
| 15:13 | timvisher | technomancy: that does look pretty good. thanks! |
| 15:15 | gvickers | wow thats very cool |
| 15:15 | `cbp | jtoy: it seems like a bug with case |
| 15:17 | `cbp | jtoy: https://www.refheap.com/17706 |
| 15:17 | `cbp | jtoy: that -1640523857 should be a 2 |
| 15:23 | jtoy | `cbp: nice, found a bug |
| 15:27 | juhu_chapa | Is dynamic binding conveyed to future calls? |
| 15:30 | justin_smith | (do (def ^:dynamic *foo* 1) (binding [*foo* 2] (future (println *foo*)))) |
| 15:30 | justin_smith | returns 2 for me |
| 15:30 | justin_smith | *prints 2 |
| 15:30 | justin_smith | returns pending future |
| 15:38 | juhu_chapa | justin_smith: :O |
| 15:42 | llasram | jtoy, `cbp: In `case`, "not evaluated" means "not evaluated". The `x` in the test-constant in `cbp's example is matching against the symbol `x`, just as it should |
| 15:50 | `cbp | llasram: i thought the const stuff would replace the x with the number at compile time but i was wrong :). Need to know the language better. |
| 15:55 | gtrak | juhu_chapa: https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L6320 |
| 16:00 | juhu_chapa | gtrak: thanks! |
| 16:00 | gtrak | np! |
| 16:01 | gtrak | 'binding conveyed future calls' happens to be in the implemenatation.. gotta love lisp |
| 16:01 | gtrak | implementation* |
| 16:17 | edbond | I don't understand how macros in clojurescript works - https://gist.github.com/edbond/6253042 |
| 16:18 | edbond | Trying to create macro that will prepend dom queries like (inside ".div-class" ($ "#id-inside-div)) ;; => ".div-class #id-inside-div" |
| 16:19 | bbloom | edbond: you are resolving inside-sel to that dynamic var, not a local |
| 16:20 | bbloom | ,`(let [inc 1] (inc 2)) |
| 16:20 | clojurebot | (clojure.core/let [clojure.core/inc 1] (clojure.core/inc 2)) |
| 16:20 | bbloom | you need to use a gensym or force variable capture |
| 16:20 | nDuff | ...well, is the _goal_ a local? |
| 16:20 | bbloom | ,`(let [inc# 1] (inc# 2)) |
| 16:20 | clojurebot | (clojure.core/let [inc__57__auto__ 1] (inc__57__auto__ 2)) |
| 16:20 | nDuff | It looks to me like the goal is maybe a binding. |
| 16:20 | bbloom | locals may not have namespaces in their symbols |
| 16:21 | edbond | I will not be able to use gensym in $ func? Maybe a binding needed? |
| 16:21 | cap10morgan | why doesn't this work? (binding [*foo* :bar] (deftest foo-is-bar (is (= *foo* :bar)))) |
| 16:21 | nDuff | edbond: ...looks to me like you also want to unquote sel inside the macro |
| 16:21 | cap10morgan | *foo* is back to its pre-binding value inside the test |
| 16:22 | bbloom | edbond: you're trying to call $ in your cljs, but that's defined in your clj |
| 16:22 | bbloom | edbond: how are your general macro skills? ie outside of cljs, just in clj |
| 16:22 | edbond | bbloom, not much. What did you mean by "force variable capture" ? |
| 16:23 | cap10morgan | is it because of the compile-time vs. run-time difference? |
| 16:23 | edbond | I can refer $ in cljs |
| 16:23 | bbloom | ,`[inc #'inc inc# ~'inc] |
| 16:23 | clojurebot | [clojure.core/inc (var clojure.core/inc) inc__86__auto__ inc] |
| 16:23 | bbloom | that last one is forced capture |
| 16:24 | bbloom | edbond: if your macro skills are weak, you may want to practice in big brother jvm clojure first. cljs introduces some serious ADDITIONAL gotchas to macro programming that will be very surprising if you haven't fully internalized macros, vars, resolution, quasiquoting, etc |
| 16:24 | edbond | I see, thanks |
| 16:25 | edbond | this probably my best macro - https://www.refheap.com/16357 |
| 16:31 | callen | edbond: that's pretty sweet :) |
| 16:33 | callen | amalloy_: is flatland/useful being maintained? Is it still a good dumping ground for random stuff of good utility? |
| 16:55 | technomancy | cap10morgan: yeah, basically |
| 16:56 | cap10morgan | technomancy: OK, makes sense. I ended up writing another macro to insert the binding inside the test body. Seems to work pretty well. Thanks. |
| 17:02 | technomancy | cap10morgan: that's one way to do it. fixtures are another, if the binding needs to be shared for all tests in a namespace |
| 17:03 | cap10morgan | technomancy: yeah, I'll probably investigate that approach too. |
| 17:03 | technomancy | definitely worth learning to use fixtures |
| 17:11 | Profpatsch | I’m kind of clueless. How can I make this dry? (and (integer? duration) (pos? duration)) |
| 17:13 | cespare | Profpatsch: http://stackoverflow.com/questions/7922636/how-do-you-compose-two-or-more-predicates-in-clojure |
| 17:13 | bbloom | (doc every-pred) |
| 17:13 | clojurebot | "([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps]); Takes a set of predicates and returns a function f that returns true if all of its composing predicates return a logical true value against all of its arguments, else it returns false. Note that f is short-circuiting in that it will stop execution on the first argument that triggers a logical false result against the original predicates." |
| 17:13 | bbloom | ,(map (every-pred integer? pos?) [5 -2 :foo]) |
| 17:13 | clojurebot | (true false false) |
| 17:13 | Profpatsch | Many thanks. |
| 17:13 | bbloom | that said, it's probably dry enough already :-) |
| 17:14 | Profpatsch | Well, there’s a variable name occuring twice. ;) |
| 17:14 | bbloom | sure, but i'm quite certain there will be bigger fish to fry in your program :-) |
| 17:15 | hiredman | dry makes horribly brittle programs, I would not worry about it |
| 17:16 | bbloom | hiredman: that's something i wish i learned sooner |
| 17:16 | justin_smith | as shannon told us, redundancy helps with detecting errors |
| 17:16 | bbloom | hiredman: would be nice to see a list of what types of "dryness" cause what sorts of problems & how to avoid them |
| 17:17 | Profpatsch | When would you start using every-pred? Three tests? Four? |
| 17:17 | hiredman | if I have two things, a and b, and they have a common thing they do, and I factor it out in to c, now any change to c effects both a and b |
| 17:17 | technomancy | "two or more; use a for" - thus spake edsger |
| 17:17 | bbloom | Profpatsch: when you want to construct a higher order predicate at run time :-) |
| 17:17 | hiredman | do that a few times and now every change you make breaks something |
| 17:18 | Profpatsch | @hiredman Do what? |
| 17:18 | hiredman | intertwine components through shared subsystems |
| 17:19 | hiredman | sharing is not a problem as long as the shared things never change, but software always changes |
| 17:19 | Profpatsch | Isn’t that the basic principle of inheritance? |
| 17:19 | hiredman | inheritance is gross |
| 17:20 | avishai | hi |
| 17:20 | bbloom | gross partially because it shares things that are likely to need to be later unshared |
| 17:20 | avishai | what namespace contains math functions? |
| 17:20 | bbloom | but goes one step further: making it harder for you to unshare them later |
| 17:20 | bbloom | avishai: what math functions are you looking for? |
| 17:21 | avishai | e.g. sqrt |
| 17:21 | Profpatsch | Don’t multimethods share a similar problem? |
| 17:21 | justin_smith | java.lang.Math/* is not a namespace, but it has a bunch of that stuff |
| 17:21 | bbloom | use java's Math |
| 17:21 | avishai | ah. no clojure style functions? |
| 17:21 | justin_smith | ,(Math/sqrt 4.0) |
| 17:21 | clojurebot | 2.0 |
| 17:21 | bbloom | not in core |
| 17:22 | hiredman | Profpatsch: multimethods are very flexible and you can certainly do all manner of things with them, but they are not hard wired for a particular thing |
| 17:22 | patchwork | (def sqrt [x] (Math/sqrt x)) |
| 17:22 | patchwork | *defn |
| 17:22 | hiredman | Profpatsch: so you have to be more specific about the kind of usage of multimethods you are asking about |
| 17:23 | Profpatsch | They support arbitrary polymorphism, right? |
| 17:23 | bbloom | no, not arbitrary |
| 17:23 | Profpatsch | What about |
| 17:23 | bbloom | they support table-dispatch with an arbitrary key function |
| 17:24 | technomancy | how is that different? |
| 17:24 | Profpatsch | Could you theoretically create cycles? |
| 17:24 | technomancy | because it's cached I guess? |
| 17:24 | bbloom | technomancy: b/c it is a fixed set of cases |
| 17:24 | bbloom | at least at dispatch time |
| 17:25 | bbloom | it's a subset of predicate dispatch, for example |
| 17:25 | hiredman | Profpatsch: the polymorphism in multimethods is not inheritance based |
| 17:26 | bts- | Profpatsch: dispatch and inheritance are separate concepts |
| 17:26 | technomancy | sure; if you ignore methods defining other methods I guess |
| 17:26 | bbloom | "methods defining other methods"? |
| 17:26 | hiredman | Profpatsch: it really is arbitrary polymorphism, your dispatch function can dispatch on things besides the arguments if you really want |
| 17:26 | bbloom | like :default runs, i analyze the expression, defmethod with some new case, then recurse? |
| 17:26 | Profpatsch | Can you point me to an article explaining the difference? |
| 17:26 | bbloom | technomancy: gross. :-P |
| 17:26 | technomancy | bbloom: yeah, dnolen had a blog post about that a while back |
| 17:27 | technomancy | self-optimizing multimethods for when the dispatch cases aren't known up-front |
| 17:27 | bts- | Profpatsch: it just happens to be that most mainstream OO languages have both concepts baked-in |
| 17:28 | bbloom | technomancy: are you talking about his extend-type trick for an unknown set of concrete data types implementing a protocol? |
| 17:28 | dnolen | technomancy: actually I wrote about that for protocols, not multimethods - and protocol case was about lack of ISeqable and how to handle the fact that primitive array types are open ended |
| 17:28 | Profpatsch | I have the feeling most OO languages mix up a lot of orthogonal concepts. |
| 17:28 | bts- | Profpatsch: dispatch is merely calling a different implementation of a function depending on the receiver |
| 17:28 | Profpatsch | Found something:http://stackoverflow.com/questions/5671627/what-is-predicate-dispatch |
| 17:28 | dnolen | bbloom: yes |
| 17:28 | mikerod | Where is this dnolen blog? |
| 17:28 | bts- | Profpatsch: inheritance is sharing of those function implementations via a common ancestor in a hierarchy of types |
| 17:28 | technomancy | dnolen: oh right; it's been a while. but the concept could be applied to either. |
| 17:28 | dnolen | mikerod: history now, thanks to Posterous |
| 17:29 | mikerod | dnolen: oh, well that's sad |
| 17:29 | dnolen | technomancy: it could yes, Stuart Sierra's multimethod idea probably gave me the seed of the idea |
| 17:29 | technomancy | does anyone have .lein-* files in their project root that aren't gitignored? |
| 17:29 | bts- | Profpatsch: i should say "method implementations" |
| 17:29 | dnolen | mikerod: I have new blog though, I may revisit some of the more interesting examples at some point on the new blog |
| 17:30 | hiredman | technomancy: I do, I'm not sure why, or what those files are, or what projects they are in, they certainly aren't checked in to git either |
| 17:30 | hiredman | I've seen them in my untracked files |
| 17:30 | technomancy | hiredman: heh... have you considered gitignore? |
| 17:30 | hiredman | I would, but I would have to care about them first |
| 17:31 | technomancy | good point |
| 17:31 | mikerod | dnolen: ah, ok. It just seemed to be an interesting topic. |
| 17:31 | Profpatsch | Take any feature of an OO language, abstract it one or two times and you have a Clojure functionality… |
| 17:31 | hiredman | abstract it? |
| 17:31 | hiredman | cut it in to a few pieces |
| 17:31 | Profpatsch | Then abstract those pieces? |
| 17:32 | Profpatsch | Well if -> cond -> condp type dispatch -> predicate dispatch functions -> first class functions … |
| 17:34 | noncom|2 | hi, if i am writing a lein plugin that is, by idea, extends functionality of an existing one, but the amount of invasion is big enough that more than 50% of original àòû have to be changed inside. Do I simply create a new plugin withou references to the existing one or do I somehow re-use the existing one? |
| 17:34 | noncom|2 | s/àòû/fns |
| 17:34 | technomancy | noncom|2: hard to say without knowing what the old one does |
| 17:35 | hiredman | functions being the unit of programming in clojures can be viewed as a direct result of taking classes and breaking them up, the namespace features of classes become real namespaces, the functionality of classes get broken down in to the smallest unit of function, a function, and dispatch is further broken up |
| 17:35 | Profpatsch | And the field? (Data?) |
| 17:36 | hiredman | data is just data, maps, sets, lists, and vectors |
| 17:36 | bts- | data are just values. state is a sequence of value changes over time associated with an "identity" |
| 17:36 | noncom|2 | technomancy: i am extending uberjar to provide full support for any user jars and native libs using jdot jcl and it needs rewriting of (let) that starts at line 93 of uberjar |
| 17:37 | bts- | where values are immutable |
| 17:37 | Profpatsch | That’s what I like about immutabiliy, it actually resembles the way the world works much better. |
| 17:37 | technomancy | noncom|2: I'd just have it generate the uberjar and make a further modified copy of that |
| 17:37 | Profpatsch | Discretely. |
| 17:38 | noncom|2 | hiderman: i would also encourage anyone who interests in namespaces classes and functions to read about mathematical definition of class. |
| 17:38 | noncom|2 | technomancy: wow, you're genius :) |
| 17:39 | noncom|2 | oh yes, it does that already with uberjar dependency on jar, afais |
| 17:39 | technomancy | it's like... the circle of life or something |
| 17:40 | calp | Hello, getting started with clojure, but have some history with Common Lisp. Using emacs, is clojure-mode really the best, or is there some kind of slime extension I should use? |
| 17:40 | technomancy | calp: clojure-mode and slime do different things. |
| 17:41 | technomancy | clojure-mode is for static stuff; you definitely want that. |
| 17:41 | technomancy | slime is for dynamic code loading; you probably want nrepl.el instead |
| 17:41 | technomancy | calp: http://clojure-doc.org/articles/tutorials/emacs.html |
| 17:41 | calp | ok, I'll go with that, thanks. |
| 17:41 | Profpatsch | There has to be a better way to assign this map, something with zipping? I’m lost. https://www.refheap.com/17710 |
| 17:42 | Profpatsch | Can I get all function args as a seq? |
| 17:42 | Profpatsch | Or a vec? |
| 17:42 | justin_smith | (defn trip [& args] ...) |
| 17:43 | Profpatsch | But then there is no documentation. |
| 17:43 | justin_smith | (defn trip [& [origin destination mot duration :as args]] ...) |
| 17:43 | justin_smith | maybe throw in an ignored after duration to doc the fast the first four are the only needed |
| 17:44 | Profpatsch | Hm. The whole args array isn’t available without the destructuring? |
| 17:45 | justin_smith | it is |
| 17:45 | justin_smith | [& args] |
| 17:45 | Profpatsch | oh-you.png |
| 17:45 | justin_smith | I was just adding the implicit documentation you mentioned |
| 17:45 | justin_smith | but preserving the fact you can access args |
| 17:45 | Profpatsch | Hm, okay. Thanks. |
| 17:45 | justin_smith | [& args] is not destructuring, if that is what you mean |
| 17:46 | Profpatsch | Okay. |
| 17:48 | `cbp | darn it I need a way to run dbase code in java. Or make java(clojure) work properly with dot matrix printers =P /rant |
| 18:20 | lynaghk | I'm having some angst about the API design of one of my libraries: https://github.com/lynaghk/zmq-async |
| 18:20 | dnolen | lynaghk: what's the problem? |
| 18:20 | lynaghk | in particular, whether or not I should offer a set of "easy" API functions that hide the creation of a thread pool and other backing "context" stuff |
| 18:20 | lynaghk | or if I should just force everyone to be totally explicit about it and create/manage a context |
| 18:21 | dnolen | lynaghk: hmm, is this any different than core.async provide a default thread pool which configurable? |
| 18:21 | bbloom | i was gonna just say what dnolen said ^^ |
| 18:21 | lynaghk | dnolen: I didn't know core.async had a configurable threadpool |
| 18:22 | lynaghk | if there's a nice idiomatic way to have "easy" but make it configurable, I'm open to hear it |
| 18:23 | lynaghk | ultimately everything goes through the "simple" single function, `register-socket!`; I'm not sure if it'll be a net gain for people to hide that fn under the covers and provide helpers for typical use cases, or if I should just be consistent and simple and expose the single fn only. |
| 18:24 | dnolen | lynaghk: ok it looks like core.async thread pool isn't configurable yet, but I'm pretty sure there's been talk about this |
| 18:27 | lynaghk | One problem with the "easy" API is that I'd be spinning up threads under the table for people, which just feels rude. |
| 18:30 | bbloom | lynaghk: when would it spin up threads? would it be one-to-one with some obvious init function? |
| 18:30 | bbloom | lynaghk: or would there just be one general pool? |
| 18:31 | lynaghk | bbloom: that's the big question = ) |
| 18:31 | lynaghk | bbloom: Right now you can use the "simple" API to explicitly create a context, initialize it, and then give it sockets |
| 18:33 | lynaghk | bbloom: I'm on the fence about offering another API for the people who want to get up and running with one line of code---behind the scenes that line would be using a private context that was initialized at the toplevel of the library |
| 18:34 | noonian | I've seen the phrase "using clojure in anger" a few places on the web to mean using clojure for real stuff, what does that actually mean and how did that come about? |
| 18:34 | bbloom | lynaghk: would any reasonable program ever create two contexts? |
| 18:34 | technomancy | noonian: it's a reference to the Oasis song "Don't look back in Anger" |
| 18:34 | technomancy | (not really) |
| 18:34 | noonian | lol |
| 18:35 | bbloom | http://english.stackexchange.com/questions/30939/is-used-in-anger-a-britishism-for-something |
| 18:35 | lynaghk | bbloom: yes, if you want to prioritize different sets of sockets---you'd have one context to handle big/slow messages and a separate one to accept smaller control messages |
| 18:35 | lynaghk | bbloom: since each context can only read/write one socket at a time. |
| 18:35 | bbloom | lynaghk: could those contexts ever communicate? can something be shared between them? |
| 18:35 | lynaghk | bbloom: no, they're independent. |
| 18:36 | noonian | bbloom: thanks :) |
| 18:37 | lynaghk | bbloom: my main hesitation is that it just feels rude for a library to startup two threads when it's loaded. I could jigger some other global state up to lazily start the context as soon as it's needed, but the idea in general feels gross. |
| 18:37 | bbloom | lynaghk: yeah, but that doesn't stop like 789357893 java libs from doing it |
| 18:37 | lynaghk | bbloom: trying to lead by example here =P |
| 18:38 | lynaghk | bbloom: then again, limiting it to the "simple" fn only is the kind of thinking that evenutally gets you to a factorycontextfactory |
| 18:39 | bbloom | lynaghk: are contexts thread local? ie does the pool of threads for a given context share a common necessarily ancestor thread? |
| 18:39 | Profpatsch | Why don’t you simply create the simple API and document that it starts a threadpool in the background? ;) |
| 18:40 | lynaghk | Profpatsch: the simple API asks you for a context that you've already created and started for it =) |
| 18:40 | lynaghk | bbloom: I don't understand your question. Each context has two threads, and initializing the context starts those threads and binds a ZeroMQ in-proc socket that they use to communicate |
| 18:41 | Profpatsch | As long as the programmer knows what’s going on in the background, it’s okay, isn’t it? |
| 18:41 | lynaghk | Profpatsch: well, that's the thing with easy APIs---too easy to not think about what's going on in the background until it's too late |
| 18:41 | technomancy | lynaghk: just be sure to offer an alternate arity that lets users bring their own thread pool |
| 18:42 | bbloom | technomancy: i think the issue is that w/ an auto thread pool, there would be no single entry point |
| 18:42 | technomancy | ah, that chews |
| 18:42 | lynaghk | technomancy: yeah, I was thinking something along those lines myself. the only issue there is that there are now three ways to get the same thing |
| 18:42 | bbloom | or is there? lynaghk: is the only entry point creating sockets? |
| 18:42 | noonian | doesn't seem all that gross to me, and it's necessary if you need multiple threads listening (blocking) for different things |
| 18:43 | technomancy | three arities when you only need one is way better than one arity when you need three |
| 18:43 | lynaghk | This is the simple fn entry point: https://github.com/lynaghk/zmq-async/blob/master/src/com/keminglabs/zmq_async/core.clj#L253 |
| 18:43 | bbloom | lynaghk: rephrasing: my question about the ancestor thread: will all sockets be created within the dynamic extent of the process which creates the context? |
| 18:44 | lynaghk | It requires that you have a started context object and a constructed ZeroMQ socket that is already bound/connected and otherwise setup the way you like it. |
| 18:44 | bbloom | lynaghk: but creating a socket requires a context.... |
| 18:44 | bbloom | line 270 |
| 18:45 | lynaghk | bbloom: yep. take a look at the example code in the README. You have to create a socket with the context and then pass that same context into the register fn. |
| 18:45 | bbloom | lynaghk: my suggestion is as follows: create a macro that initializes & shutsdown a context in a try/finally & use a dynamic var |
| 18:45 | lynaghk | That could be a problem because you might shoot yourself in the foot by creating a socket with one context and trying to register it with another. |
| 18:46 | bbloom | but require the var be specified |
| 18:46 | bbloom | then provide overloads that do or do not take that var |
| 18:46 | bbloom | so you can get the thread local context, or override it |
| 18:46 | noncom|2 | what is the recommended way to access arbitrary web url from a lein plugin? |
| 18:46 | lynaghk | bbloom: why a dynamic var vs. passing in a value? |
| 18:46 | justin_smith | noncom|2: slurp it? |
| 18:46 | bbloom | b/c then if two people use your "easy" API from two different entry points, they won't collide |
| 18:46 | noncom|2 | ok, i'll try |
| 18:47 | bbloom | it's not global then, it's connected to the session, like a repl or another servlet host or whatever |
| 18:47 | lynaghk | bbloom: not sure what you mean. If there were an implicit context it could be used globally and be threadsafe |
| 18:47 | justin_smith | there is also http.async.client if you need to get fancy |
| 18:48 | bbloom | lynaghk: if you have one implicit global context, and two containers in the same web app try to use it, they'll get the same context & then one can shut it down on the other, for example |
| 18:48 | bbloom | lynaghk: but really, i wouldn't bother at all and do the easy thing and then wait for somebody to complain :-) |
| 18:48 | lynaghk | bbloom: I'm tempted to strip out the "easy" API entirely and just make the explicit context creation and management the only way to use the thing |
| 18:49 | bbloom | lynaghk: or that |
| 18:49 | noncom|2 | i think slurp will do, i just have to fetch a txt |
| 18:49 | lynaghk | bbloom: but now I'm thinking of this problem where you might create a socket against one context and register it on another...so I might try and wrap up socket creation and registration for you. |
| 18:49 | justin_smith | noncom|2: yeah slurp is in core, and very easy to use |
| 18:49 | bbloom | lynaghk: what does registration do exactly? |
| 18:50 | bbloom | lynaghk: why are creation and registration separate in the first place? |
| 18:50 | lynaghk | bbloom: because I didn't want to wrap all of ZeroMQ's options |
| 18:50 | lynaghk | bbloom: so you create the socket and set it up the way you like it, then give it to my library to manage for you. |
| 18:51 | lynaghk | bbloom: what I could do is have the registration fn take a "configurator" in the same way that run-jetty takes one |
| 18:51 | justin_smith | ,(slurp "http://www.google.com") |
| 18:51 | clojurebot | #<SecurityException java.lang.SecurityException: denied> |
| 18:51 | justin_smith | :( |
| 18:51 | bbloom | lynaghk: yeah, you could just do (create-socket :foo (fn [socket] configure here)) |
| 18:52 | lynaghk | so it creates a socket for you against the right context but still lets you call whatever java-y things you need to |
| 18:52 | bbloom | sure |
| 18:52 | lynaghk | yeah. I think that might be the way to go. |
| 18:53 | bbloom | although i might prefer a configuration map :-) |
| 19:19 | noncom|2 | will (spit) create the path if it does not exist? |
| 19:20 | bbloom | noncom|2: surely you can try "/tmp/some/path" yourself |
| 19:37 | justin_smith | ,(apply < (map count ["(spit \"/tmp/a/b/c/d/e\" \"hello\")" "will (spit) create the path if it does not exist?"])) |
| 19:37 | clojurebot | true |
| 19:37 | justin_smith | :P |
| 19:37 | noncom|2 | :D |
| 19:43 | justin_smith | ,36RCRAZY |
| 19:43 | clojurebot | 21429358 |
| 20:09 | cespare | Anyone use fireplace and have trouble with it finding the repl? |
| 20:09 | cespare | lein repl, that is |
| 20:09 | cespare | I've got target/repl-port. |
| 20:18 | technomancy | cespare: temporary fix: `:target-path "target"` in your user profile |
| 20:18 | technomancy | will have a proper fix in a couple days |
| 20:19 | cespare | technomancy: turns out I was editing a file that was somewhere else (through a symlink) |
| 20:19 | cespare | I assumed fireplace used my cwd to find nrepl, but I guess it looks at where the file is. |
| 20:29 | yedi | whats the simplest way to install clojure |
| 20:30 | bbloom | ~lein |
| 20:30 | clojurebot | "[Clojure ...] feels like a general-purpose language beamed back from the near future." |
| 20:30 | bbloom | *sigh* |
| 20:30 | bbloom | yedi: install leinigen |
| 20:32 | hiredman | the new inference code in clojurebot follows things besides "are" and "is", which it shouldn't |
| 20:46 | muhoo | ~what is life? |
| 20:46 | clojurebot | No entiendo |
| 20:46 | metellus | ~what is love? |
| 20:46 | clojurebot | Gabh mo leithscéal? |
| 21:16 | dnolen | hrm, bbloom I can't think of any reason why channels don't support metadata ... |
| 21:18 | bbloom | dnolen: i don't know why you're telling me that, but i assume it's for the same reason reference types don't support metadata |
| 21:18 | dnolen | bbloom: well I was gonna complain to tbaldridge but he's gone :) |
| 21:18 | dnolen | bbloom: channels aren't reference types so I'm not sure I buy that. |
| 21:18 | bbloom | dnolen: channels have object identity |
| 21:19 | bbloom | dnolen: with-meta returns a new object |
| 21:19 | dnolen | bbloom: oh right |
| 21:19 | bbloom | yeah, metadata only makes sense on things with value identity |
| 21:19 | dnolen | hmm |
| 21:20 | bbloom | dnolen: so rewinding. what makes you want the metadata? what issue are you trying to solve? |
| 21:21 | dnolen | bbloom: listening to events on the dom, but what wanting to clean up listener when something is done |
| 21:22 | bbloom | how would metadata help? |
| 21:23 | bbloom | unrelated: i'm not sure why reify puts metadata on all object types. i really don't think metadata makes sense for objects that don't have custom equals defined |
| 21:23 | dnolen | bbloom: I wasn't considering the object identity issue, wanted store goog id for removing listeners |
| 21:24 | dnolen | bbloom: metadata doesn't factor into equality so I don't know how what you're saying makes sense |
| 21:24 | bbloom | dnolen: can't you store that in a loop loop variable in some goroutine? |
| 21:24 | dnolen | bbloom: still hacking away at autocompleter, introducing another bit of state would be obnoxious |
| 21:25 | bbloom | ,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)]) |
| 21:25 | clojurebot | (true false) |
| 21:26 | bbloom | adding metadata to any-old object makes it impossible for you to get back to the underlying object to check identical? against some other object |
| 21:27 | bbloom | any time you "new" up anything that doesn't have value identity, that's basically implicit state / a side effect. if you want metadata on it, you need to store that metadata elsewhere, such as in a map, then manage the lifetime of that metadata along with the lifetime of the new-ed up object |
| 21:27 | bbloom | yet another reason objects suck |
| 21:27 | dnolen | bbloom: I just don't see why that's a problem, identical? checks are rare - is there something specific you're trying to do? |
| 21:27 | bbloom | dnolen: identical? checks are only rare b/c working with objects is rare |
| 21:28 | dnolen | bbloom: so why should it be any different for reify? |
| 21:28 | bbloom | = uses identical? internally if the object doesn't have a custom implementation |
| 21:29 | bbloom | if you reify some object & want to put metadata on it, you can't put that meta-data-deocrated object into a set or map or whatever & then later expect to look it up given the underlying non-meta-decorated object |
| 21:30 | bbloom | unless you also implement a method for = |
| 21:33 | dnolen | bbloom: sure but I guess I just don't see this as a problem, as it has nothing to do with metadata anyhow. metadata doesn't factor into equality |
| 21:33 | bbloom | dnolen: except it does for reify, i just showed you that: |
| 21:33 | dnolen | bbloom: if you make a new thing of something without defining equality w/o metadata you have the same problem |
| 21:33 | bbloom | ,(map (fn [x] (= x (with-meta x {:foo :bar}))) [{:some :value} (reify)]) |
| 21:33 | clojurebot | (true false) |
| 21:34 | dnolen | bbloom: yeah non-problem to me |
| 21:35 | bbloom | (doc with-meta) |
| 21:35 | clojurebot | "([obj m]); Returns an object of the same type and value as obj, with map m as its metadata." |
| 21:36 | bbloom | clojure has a very specific definition of "value" and, as far as i can tell, a non-value shouldn't have metadata |
| 21:36 | bbloom | but *shrug* i could be wrong |
| 21:36 | dnolen | bbloom: the doc the isn't even true for fns w/ which support metadata |
| 21:36 | dnolen | ,(= inc (with-meta inc {:foo 'bar})) |
| 21:36 | clojurebot | false |
| 21:36 | bbloom | yeah i discovered that recently too |
| 21:37 | dnolen | bbloom: ship sailed when people asked for that, so I just think non-issue |
| 21:37 | bbloom | in fact, i had this precise problem: i was tried to put a function in a map |
| 21:37 | bbloom | and then tried to put metadata on it |
| 21:37 | bbloom | later on, i couldn't look the function up |
| 21:37 | bbloom | if you use a metadata-ed function as a map or set key, you can't ever look it up |
| 21:37 | dnolen | bbloom: prior to fns supporting metadata doc string made sense, doesn't make sense after that change |
| 21:40 | bbloom | anyway, let's solve your actual problem |
| 21:40 | bbloom | you want to store the dom element ID somewhere? |
| 21:43 | bbloom | subscribe/unsubscribe function pairs for callbacks are basically the same as reference counting |
| 21:44 | dnolen | bbloom: no, no I know how to solve, just wanted the convenience of metadata :) |
| 21:44 | dnolen | but that was a weird thing to want |
| 21:44 | bbloom | if i have to deal w/ sub/unsub functions at all, i rather it be implemented as garbage collection :-) |
| 22:02 | holo | hi |
| 22:02 | akurilin | Say you're doing a MVC-style API in Clojure. Where would you validate input for POST/PUT request, if you don't really have a class to represent the model? |
| 22:02 | akurilin | Would you make that check right before making the DB call? |
| 22:08 | holo | can someone point me to an fn that will search for a value, given the coll to search in, and a predicate? when first truthy value is found, will short circuit and return it |
| 22:09 | gfredericks | akurilin: if you're validating I suppose it makes sense to have the "schema" described somewhere using an appropriate lib? and you can put that with your model logic, and just call it directly from some middleware perhaps |
| 22:09 | gfredericks | holo: (some pred coll) |
| 22:09 | gfredericks | no wait |
| 22:10 | gfredericks | that's just (first (filter pred coll)) which doesn't have a built-in shorter form |
| 22:10 | akurilin | gfredericks, sure, that sounds good, thanks! |
| 22:14 | holo | akurilin, i do most of my validation against the db schema constraints themselves. besides that, when additional validation logic is necessary, i put it in each model, and call it in the corresponding view POST defn. i didn't do client validation yet, cause at least i know server one always works. i've done validation through middleware too, but not so often |
| 22:16 | holo | gfredericks, does it short circuit? i need to get myself around lazy sequences |
| 22:16 | akurilin | holo, perfect, thanks. |
| 22:17 | gfredericks | holo: it short-circuits because of laziness |
| 22:17 | gfredericks | modulo chunking |
| 22:17 | holo | akurilin, validation by db schema constraints is dry, but it was a pain to get it working |
| 22:18 | akurilin | Ok here's another one that's been bothering me, I hope you guys have thoughts on this. Say you're doing model validation, and if it's incorrect you just throw an exception (as a quick return mechanism) which is ultimately turned into a 400 in the middleware. Because the validation doesn't do anything on the map you pass in, does it make sense to put it in a do block? |
| 22:18 | holo | gfredericks.. great! |
| 22:19 | akurilin | holo, I'm a believer in both api and db level constraint checking as a way of short-circuiting, so I tend to have both if possible. |
| 22:20 | akurilin | holo, or I guess it's just simpler to edit stuff in clj rather than messing with db migrations, so it's nicer to put more logic in there. |
| 22:20 | akurilin | So as in (do (validate input-map) (save map)) |
| 22:21 | akurilin | Can think of exceptions as side-effects/ |
| 22:21 | holo | akurilin wait, i didn't mean that.. i mean i get the constraints from db schema, but i use them at the api level |
| 22:24 | holo | i also use naming convention for validation. if a column name is *email*, the record will be checked for a valid email string |
| 22:29 | holo | akurilin, if i was reading that do block code, i would think (save map) was always executed, which is not, by your words |
| 22:30 | akurilin | holo, right. It seems like the issue here is more about readability. |
| 22:30 | akurilin | holo, on one hand the do makes it obvious that input-map will not change, on the other it also does what you said. |
| 22:33 | akurilin | Man, you guys created so many validation libraries, that's awesome. |
| 22:38 | holo | akurilin, why not do (when (validate input-map) (save map)) instead? the code flow is obvious, and it does the same as your code |
| 22:45 | akurilin | holo, it just means I'm going to have to check for nil somewhere upstream and turn that into a 400 |
| 22:45 | akurilin | as opposed to generalizing it |
| 22:46 | akurilin | I can see that working too, though, don't get me wrong :) |
| 22:48 | holo | nil? no nil will ever be returned. remember it will throw an exception |
| 22:49 | holo | i'm assuming you'll throw an exception there or return some truthy value |
| 22:50 | akurilin | holo, oh sorry, for some reason I assumed you meant not to throw an exception, my bad. |
| 22:50 | holo | akurilin, glad to help :) |
| 22:50 | akurilin | holo, yep, thank you! |
| 23:28 | callen | More idiomatic way to express this? - https://www.refheap.com/17716 |
| 23:40 | TimMc | Argh, how can Emacs packages always be such a hassle? |
| 23:42 | TimMc | clojure-mode seems to have disappeared from Marmalade. |
| 23:42 | callen | TimMc: Emacs configs didn't even have packages until recently. |
| 23:42 | callen | We've been carving the stories of our elders into tree bark for centuries. |
| 23:43 | callen | It wasn't until these young turks with their papyrus and stone that we started being able to reuse anytihng. |
| 23:43 | callen | TimMc: clojure-mode comes up in Marmalade repo search. |
| 23:43 | callen | TimMc: I strongly recommend having redundant repos in your config. |
| 23:43 | callen | I usually use Marmalade, MELPA, and the GNU one. |
| 23:47 | TimMc | Hrm. |
| 23:48 | TimMc | I'll shave that yak another day; it's not actually essential for my new home server to have a Clojure editor on it. Yet. |
| 23:51 | callen | TimMc: you could just git clone my dotfiles. |
| 23:51 | callen | TimMc: shake-n-bake Clojure env :P |