2014-09-16
| 00:50 | gzmask | hello guys, what is the clj-http translation of "curl -s https://aaa.com -d "a=b&c=d" ? |
| 00:52 | justin_smith | (client/post "https://aaa.com" {:form-params {"a" "b", "c" "d"}}) |
| 00:53 | justin_smith | also, example.com is the canonical filler url |
| 00:57 | gzmask | thanks justin_smith. but paypal doesn't think they are the same :( |
| 01:02 | dbasch | gzmask: the user agent obviously is not the same. Does it work with curl and not clj-http? |
| 01:03 | gzmask | yes, it worked with curl, but gives RESPMSG=User authentication failed for clj-http |
| 01:04 | dbasch | what if you do (client/post "https://aaa.com" {:form-params {:a “b” :c “d”}}) |
| 01:05 | gzmask | same error. I tried the query-params, no luck either. |
| 01:06 | gzmask | it's escaping my "!" char to "%21" . now sure if this cause the error |
| 01:13 | gzmask | It did cause the error!! Why in the world would you change ! to %21 .... |
| 02:16 | cisza | Hi guys |
| 02:17 | seangone | hi cisza ! |
| 02:27 | raspasov | hello |
| 02:27 | noncom | hi |
| 02:28 | cisza | what's up guys? |
| 02:29 | raspasov | coding :) |
| 02:29 | seangone | tends to be quiet in here at night US time :) |
| 02:29 | raspasov | yea |
| 02:29 | raspasov | I'm SFF |
| 02:29 | raspasov | SF* |
| 02:29 | seangone | I'm off to The Strange Loop in a few hours... |
| 02:30 | raspasov | yea? nice |
| 02:31 | seangone | Powered by JavaScript too... should be fun... |
| 02:31 | raspasov | what do you mean powered by JavaScript? :) |
| 02:32 | seangone | Manning's one day three track conference the day before Strange Loop |
| 02:32 | raspasov | ah I see |
| 02:32 | seangone | http://www.manning.com/poweredbyjavascript/ |
| 02:32 | raspasov | any ClojureScript in that? |
| 02:32 | seangone | there's a bunch of pre-conference stuff... workshops, future of programming, and pbj :) |
| 02:33 | seangone | I was hoping there would be some compile-to-JS stuff but there doesn't seem to be |
| 02:33 | seangone | I'm interested in React.js and stuff like that tho'... |
| 02:33 | raspasov | yea React is good |
| 02:45 | clj-learner | hi, im trying to solve http://www.4clojure.com/problem/82 and having difficulty, this seems like it can be solved with graph theory(?) could someone point me to a tutorial to be able solve this? |
| 02:51 | averell | it would be possible. you make edges between words where the distance is 1, then find a hamilton-path (that is a path of all nodes). Pretty sure it's overkill for this though. |
| 02:52 | amalloy | heh, looking back at my solution to that problem it's not actually correct |
| 02:52 | clj-learner | so how would i solve it? |
| 02:52 | averell | do you have distance already? just try all combos |
| 02:53 | clj-learner | distance? |
| 02:53 | averell | i mean, something to decide if the words are "similar enough" |
| 02:53 | amalloy | or, i dunno, maybe it does. the flaw i thought i saw in my algorithm is exercised by the tests |
| 02:54 | averell | did you do something clever? |
| 02:54 | clj-learner | i did this (fn chain? [s1 s2] (= (inc (count s1)) |
| 02:54 | clj-learner | (count (union (set s1) (set s2))))) |
| 02:55 | averell | ok, that's not enough though |
| 02:56 | amalloy | i'm not sure. i compute the degree of each node, and then i assert that there are are at most two nodes with degree less than two. that certainly doesn't sound sufficient to me |
| 02:56 | amalloy | seems like i should fail on '(sit sat sot dog) |
| 02:56 | averell | ah, that's for euler-path i think :) |
| 02:57 | amalloy | averell: well it's not really sufficient in either case, because of disjoint subgraphs |
| 02:57 | clj-learner | i think this is probably too much for me, ill just pass this one for now |
| 02:57 | clj-learner | i dont know graph theory |
| 02:57 | averell | oh right |
| 02:57 | clj-learner | at least i completed all other 81 |
| 02:57 | averell | nice |
| 02:57 | clj-learner | thanks for the help |
| 02:59 | dbasch | clj-learner: you want to find a Hamiltonian path |
| 03:06 | dbasch | amalloy: even with connected subgraphs it's still not sufficient |
| 03:06 | amalloy | indeed, it's quite wrong in a lot of ways |
| 03:07 | dbasch | that problem should have test cases that forced you to solve it right |
| 03:08 | amalloy | dbasch: of course. but it's easy to miss edge cases; 4clojure is littered with such problems |
| 03:08 | dbasch | amalloy: for that one it's not hard, just create a couple of evil graphs |
| 03:09 | dbasch | e.g. a fork and a join |
| 03:10 | amalloy | but that entails thinking of all the hard cases that someone might incorrectly identify with a wonky algorithm. you say "not hard", but of course it's impossible to find a set of inputs that causes only correct algorithms to pass |
| 03:10 | amalloy | if nothing else, the standard 4clojure cheat of mapping each input test case directly to its output will always work |
| 03:10 | averell | there certainly are drawbacks to posting all test-cases :) |
| 03:11 | amalloy | *shrug* i don't think so, averell. you only cheat yourself when you cheat a 4clojure problem. if that's what gives you satisfaction, feel free. i don't see that as a drawback |
| 03:12 | amalloy | and it drastically improves the user experience for the actual target market, ie people trying to learn clojure. imagine "you passed all the test cases you can see, but there's an input i won't tell you about that breaks your program" |
| 03:12 | averell | hm true. but i have poor self-control... |
| 03:13 | amalloy | there certainly are drawbacks to having no self control |
| 03:13 | averell | obviously a problem that should be solved externally. |
| 03:16 | dbasch | amalloy: yeah, I was just thinking of cases that would force you to either cheat or try to solve the Hamiltonian path problem |
| 03:19 | dbasch | you also learn by breaking other people's solutions :P |
| 03:23 | dbasch | I ran into some code that goes (defn foo ^String [^bytes x] ….) |
| 03:24 | dbasch | I have no idea what's the intended purpose of ^String there |
| 03:41 | cdr_ | Hey :) |
| 04:01 | SagiCZ1 | ~lazy-logs |
| 04:01 | clojurebot | lazy-logs is http://logs.lazybot.org/ |
| 04:12 | cdr_ | Soo... does some1 chat here ? |
| 04:12 | cdr_ | Or just come online and leave ? |
| 04:13 | TEttinger | when people have questions they usually get answered, cdr_ |
| 04:13 | cdr_ | Ohh, thanks :) |
| 04:13 | TEttinger | this is more of a quiet time since most of the US-based people are asleep |
| 04:14 | cdr_ | Ohh... i am from EU, so this is morning for me :D |
| 04:16 | maxthoursie | There's a bunch of EU ppl here too |
| 04:18 | hyPiRion | It's usually silent until about 2-4pm EU time, but it varies |
| 04:57 | ssideris | EU-based and present! (but yes, usually silent) |
| 05:07 | yotsov | If I want to build a clojure webapp with some ajax-like functionality but without clojurescript, are there tools that would be recommended? |
| 05:14 | perplexa | do people use System/getenv or weavejester/environ? |
| 05:41 | ddellacosta_ | perplexa: I like environ, personally |
| 05:42 | ddellacosta_ | yotsov: the backend wouldn't change (from a typical Clojure web app), and the front-end would be whatever non-CLJS thing you wanted...what are you asking about in particular though? I'm not sure I understand. |
| 05:50 | yotsov | ddellacosta_: just wondering if there are things known to work together with examples out there, such as a particular js ajax framework with a particular clojure lib on server side... |
| 05:52 | ddellacosta_ | yotsov: well, based on my experience with Om, I can tell you that using React with an immutable data structure lib like Mori and a Clojure backend could be a good fit |
| 05:52 | ddellacosta_ | yotsov: but I will sell ClojureScript a bit--it's quite nice, seriously. :-) |
| 05:54 | yotsov | ddellacosta_: thanks. Do you think cljs makes sense even for just like 2 very small ajax-ish features? It would not feel like an overkill? |
| 05:55 | ddellacosta_ | yotsov: I mean, no, but I use it every day and find it to be "no big deal." Have you done much CLJS? |
| 05:56 | ddellacosta_ | yotsov: for example, take a look here for something very simple to set up and get going: http://swannodette.github.io/2013/10/27/the-essence-of-clojurescript/ |
| 05:56 | ddellacosta_ | yotsov: apologies if you're beyond that |
| 05:56 | borkdude | CLJS makes me less afraid of javascript. |
| 05:56 | ddellacosta_ | borkdude: ha, never thought of that, but I think that's true for me too |
| 05:57 | ddellacosta_ | it also makes me more aware of JS's idiosyncracies |
| 05:59 | borkdude | Actually I find it quite fun to write front end code now. |
| 05:59 | borkdude | although I haven't really got much experience with javascript |
| 06:00 | yotsov | ddellacosta_: I am not very familiar with cljs, have just played with it a bit (hello world, a bit of Om). I wanted to postpone learning it, as I have a lot going on right now. But, interestingly enough, it seems that for clojure+ajax it is pretty much the easiest way to start, due to the sheer amount of examples out there |
| 06:01 | borkdude | yotsov ajax, look at cljs-http and channels |
| 06:01 | ddellacosta_ | yotsov: yeah, I would say that it's actually easier in terms of the "impedance mismatch" to get CLJS + CLJ working vs. Clojure and JS |
| 06:01 | borkdude | it's also lots easier to just be able to send edn back and forth |
| 06:02 | borkdude | haven't tried Transit though |
| 06:05 | yotsov | borkdude: If I go the cljs road, I hope to be able to do without channels, just with Om. I actually still have hard time understanding how people mix the two |
| 06:06 | yotsov | to me it sounds a bit contradictory, basically injecting mutability into something immutable |
| 06:06 | borkdude | yotsov you can also just use a callback, but working with channels and asynchronous is really nice, because you have the illusion that they work synchronously |
| 06:06 | borkdude | *requests |
| 06:07 | borkdude | yotsov the combination ajax+channels is something apart from Om |
| 06:08 | yotsov | borkdude: yes, but it seems to be in fashion to use both channels and Om, which confuses me |
| 06:08 | borkdude | yotsov You can use channels with Om to communicate changes to components, like: the request has finished and here are the results, now update yourself |
| 06:09 | borkdude | or: update the app state, or whatever |
| 06:09 | borkdude | yotsov in this way you can decouple logic from components |
| 06:09 | yotsov | wouldn't you rather send the full state of the page to Om then, which would then update just the necessary component? |
| 06:09 | yotsov | I see |
| 06:10 | borkdude | yotsov to "send the full state" you would first have to update it |
| 06:11 | borkdude | for example, I have a function: lookup-items. Its parameter is a channel. It doesn't know where it sends the results, but the component that reads from the channel knows that it should update the app state when something arrives there. |
| 06:11 | yotsov | borkdude: in my case, the webapp is fairly simple, and I can have everything the user sees at any point of time in just one data structure. In that case Om is enough and I do not need channels, right? |
| 06:12 | borkdude | yotsov you can do everything in one giant component and avoid channels |
| 06:12 | yotsov | borkdude: got it, thanks |
| 06:13 | ddellacosta_ | yotsov: actually Om *without* channels is a major mess and a pain in the ass, basically impossible if you ask me. |
| 06:13 | ddellacosta_ | yotsov: no way to effectively communicate back up the component hierarchy |
| 06:13 | borkdude | yotsov ddellacosta_ communication upwards happens through channels or handlers |
| 06:14 | ddellacosta_ | borkdude: yeah, I find using a lot of handlers is more frustrating |
| 06:14 | ddellacosta_ | ...thank channels |
| 06:14 | ddellacosta_ | than* |
| 06:14 | borkdude | yotsov ddellacosta_ but if you have just a small app and every part has access to the whole app-state, you can do without. That's what I meant with "giant" |
| 06:15 | ddellacosta_ | borkdude: sure, fair enough--if you don't have a deep component stack it's fine, it becomes tricky when you have complicated UI interactions |
| 06:15 | borkdude | ddellacosta_ yeah |
| 06:15 | yotsov | borkdude ddellacosta_ I think handlers should be fine for me |
| 06:16 | ddellacosta_ | yotsov: give it a shot, just keep in mind that channels really do help out once communication gets complex--if you find yourself swearing about passing state around, come back and talk to us. ;-) |
| 06:17 | borkdude | ddellacosta_ I actually found having many channels wiring component to each other can get complex too. I am now using just one channel and a pub/sub mechanism to keep it simple, where I can, unless the communication is very local. |
| 06:17 | ddellacosta_ | borkdude: that's a fair point. I have a few components with like six channels, and that really is not nice to keep track of. I guess there's a sweet spot with a few channels. |
| 06:18 | ddellacosta_ | borkdude: I need to look into something like your pub/sub mechanism, it's become pretty obvious we need something like that to alleviate the pressure in a few spots |
| 06:18 | ddellacosta_ | "complexity pressure" so to speak |
| 06:18 | yotsov | borkdude ddellacosta_ thanks guys, I think I see a bit more clearly now. Can you recommend a sample Om webapp that uses handlers rather than channels? |
| 06:18 | borkdude | ddellacosta_ yotsov http://yobriefca.se/blog/2014/06/04/publish-and-subscribe-with-core-dot-asyncs-pub-and-sub/ |
| 06:19 | ddellacosta_ | borkdude: nice, thanks |
| 06:19 | cityspirit | yotsov: you could also look at luminus with reagent. with the +cljs option you'll get a template with an example built in. I found that a really easy way to get started with simple clojure app with a clojurescript + react frontend. |
| 06:19 | ddellacosta_ | borkdude: oh, but that has no Om, sad. Well, still, good tip |
| 06:20 | ddellacosta_ | (we're using pub/sub elsewhere not just with Om yet) |
| 06:20 | borkdude | ddellacosta_ in Om I have two channels in global state: one event-ch to write to and one event-publication to subscribe to. |
| 06:20 | borkdude | ddellacosta_ the rest is very easy to figure out, once you read the blog post |
| 06:20 | ddellacosta_ | borkdude: and then if a child component needs to talk to a parent, the parent just listens on that topic basically, right? |
| 06:20 | ddellacosta_ | ...and child sends on that topic? That could work really well, hmm |
| 06:21 | borkdude | ddellacosta_ that's what I meant with "local", if it's just a parent-child relationship, I will sometimes still use a dedicated channel, but you could do it with pub sub also |
| 06:21 | ddellacosta_ | borkdude: gotcha |
| 06:22 | ddellacosta_ | that along with shared data is our biggest problem |
| 06:22 | borkdude | ddellacosta_ shared data? |
| 06:23 | ddellacosta_ | borkdude: yeah, if you have a bit of data that needs to be used in child components pretty deep in the stack. I have used shared a bit, but it doesn't seem to update in the way I need it to--so I end up putting stuff in state or app data |
| 06:23 | borkdude | ddellacosta_ you can also use pub sub for this |
| 06:24 | ddellacosta_ | borkdude: well, but then I have to manage updates myself somehow |
| 06:24 | borkdude | in IWillMount you put a go loop that reads from the subscription |
| 06:24 | ddellacosta_ | borkdude: I want to leverage React/Om's update mechanisms as much as possible |
| 06:25 | borkdude | ddellacosta_ it depends on what the data is. it could be something worthy of the app-state |
| 06:25 | yotsov | Om examples without core.async seem to be as common as clojure ajax examples without cljs :) I guess I should not try kicking against the pricks and go with Om + core.async channels... |
| 06:25 | ddellacosta_ | borkdude: that's the thing, it usually is--it's just not in the right form, or it needs to be referenced deep in the hierarchy, so a child has to have a copy of something that has effectively been "stirpped out" by that point |
| 06:25 | ddellacosta_ | *stripped |
| 06:25 | borkdude | ddellacosta_ if you do a go loop in will-mount that reads from the right subscription and updates it's local state, the component will re-render |
| 06:26 | ddellacosta_ | borkdude: yeah, but again, I don't want to have to do that--I do stuff like that now |
| 06:27 | borkdude | ddellacosta_ then pass it down the hierarchy with state. I don't know other options so far, sorry. My time with Om has been limited to a few weeks now :) |
| 06:27 | ddellacosta_ | borkdude: no, we do that too...again, though, it is usually app data that we are abusing. I do like to keep state and app data appropriately separate. |
| 06:27 | ddellacosta_ | borkdude: I mean, yeah, everything you're suggesting makes sense, I think this is a limitation in Om right now is all |
| 06:28 | borkdude | ddellacosta_ actually, I'm rewriting an app now that "abused" the app state to store component state |
| 06:28 | ddellacosta_ | ha |
| 06:28 | ddellacosta_ | "Abusing State for Fun and Profit with Om," my new ebook |
| 06:28 | borkdude | ddellacosta_ in order to make components re-usable, it should not depend on the app state too much |
| 06:28 | yotsov | ddellacosta_ borkdude there are several alternatives to Om for using react.js. Are you guys familiar with them? Is any of them simpler than Om and making using core.async more optional? |
| 06:29 | ddellacosta_ | yotsov: a lot of folks seem to like reagent, and say it is simpler, per what cityspirit was saying above |
| 06:29 | borkdude | yotsov I hear reagent is simpler, but I don't know its limitations, my only experience is with Om really |
| 06:30 | yotsov | borkdude: ddellacosta_: thank you! |
| 06:31 | ddellacosta_ | yotsov: my sense is that it's easier to get going but (this is a guess, I don't know for sure) harder to build out bigger systems with--Om's rigidity also helps enforce some good practices, not withstanding its weak points |
| 06:31 | ddellacosta_ | ...which makes it easier to build big complex web apps (as we have done) |
| 06:32 | ddellacosta_ | but again, that's not really fair to reagent, since I have barely touched it; it could be equally good, I need to give it a shot |
| 06:32 | borkdude | ddellacosta_ is what you want a shared local state between parent and childs? |
| 06:32 | yotsov | ddellacosta_: thanks. I need to build just a small demo that will never become more than that |
| 06:32 | ddellacosta_ | borkdude: no, I basically want to be able to restructure app data and re-attach things at various points/drop new cursors in at various points |
| 06:33 | ddellacosta_ | re-attach things = re-attach different pieces of app data |
| 06:34 | ddellacosta_ | maybe shared can do it, but my recent experiences suggest it doesn't update as predictably as I need it to, not like app-data/state |
| 06:34 | borkdude | so for example, app-state: {:foo {:bar :baz}}, parent component has cursor too app-state, child component gets cursor into :bar, but his child component needs :foo again? |
| 06:38 | ddellacosta_ | borkdude: (assuming app-state in your example is app data, not component local state, to be clear) |
| 06:38 | borkdude | ddellacosta_ yes |
| 06:38 | ddellacosta_ | borkdude: yeah, or more like I have {:foo [{:id 1 ...}{:id 2 ...}] :bar [...other relevant data...]} and I use build-all on :foo, and I need :bar also in each :foo |
| 06:39 | borkdude | I'm guessing that is not how react works: you can't re-render a child without re-rendering the parent maybe? |
| 06:39 | ddellacosta_ | borkdude: no, you can totally re-render a child without re-rendering the parent...if your data is structured correctly |
| 06:40 | ddellacosta_ | borkdude: that's the point of the virtual DOM really |
| 06:40 | borkdude | ddellacosta_ ok, could be, I don't know :) |
| 06:40 | ddellacosta_ | borkdude: well, if you've only been using it a few weeks, then I'm still impressed with your knowledge of Om. ;-) |
| 06:40 | borkdude | ddellacosta_ I've been asking a lot of dumb questions in #clojurescript ;) |
| 06:41 | ddellacosta_ | borkdude: jeez, I should be hanging out there, I'm never in there |
| 06:47 | borkdude | ddellacosta_ so basically, the whole parent-child structure makes no sense in re-rendering. Each component should just be able to pick what to subscribe to in the app-state? |
| 06:47 | ddellacosta_ | borkdude: no, it totally makes sense I think--it's just that I want to be able to restructure the data itself, or pass different bits around so they are reintegrated later, at certain points in the component hierarchy. I find this hard to do now in Om. |
| 06:47 | borkdude | ddellacosta_ you can just pass (dissoc cursor :foo :bar) to the components, but probably that's not what you want either |
| 06:47 | ddellacosta_ | borkdude: well, but what if I want those things later on down the chain? |
| 06:47 | borkdude | ddellacosta_ oops, I mean the opposite of dissoc, only select those two keys |
| 06:47 | yocapybara | any emacs/cider whizzes here? I'm finding I'm working in a certain way and it feels like it isn't optimal, just wanted to check with others whether they do a similar thing or if they (as I suspect) do something much smarter |
| 06:48 | ddellacosta_ | borkdude: oh, yeah, but again--what about all the stuff it's leaving off, and what if it's a build-all? |
| 06:48 | ddellacosta_ | yocapybara: I've gone back and forth between cider and just having a repl open w/emacs separate |
| 06:48 | borkdude | ddellacosta_ often I don't use build-all, but just map |
| 06:49 | ddellacosta_ | borkdude: to be fair, that's all build-all is |
| 06:49 | borkdude | (map #(om/build ... cursor {:opts {:foo %)}) [1 2 3 4]) |
| 06:49 | ddellacosta_ | yocapybara: sorry, not a super useful answer. Some folks I know are really brilliant with loading and running stuff in cider, but I think it takes some practice. :-/ |
| 06:50 | ddellacosta_ | borkdude: opts means it's not going to trigger a re-render though. |
| 06:50 | borkdude | ddellacosta_ it's not the same, because in my map example the children get acces to the whole cursor |
| 06:50 | ddellacosta_ | borkdude: yeah, I mean, that's one solution |
| 06:50 | borkdude | ddellacosta_ yeah, whatever, could be :state as well :) |
| 06:51 | ddellacosta_ | borkdude: it's tough though, if you want to build individual elements and take advantage of keys and whatnot |
| 06:51 | yocapybara | ddellacosta_: any info is useful man, thanks! I'm finding that I copy or (C-c M-p) each expression into the REPL buffer so I can play around with my code, if I execute an expression it doesn't seem to be executed in the actual repl buffer even if I've got one running. I feel like I'm missing something about how it works - like there should be a very easy way to issue a command to have the REPL run all the expressions in |
| 06:51 | yocapybara | my buffer. |
| 06:51 | yocapybara | I've had good luck with lighttable but I wanted to give emacs/cider a proper go |
| 06:52 | borkdude | ddellacosta_ I think we need concrete cases to talk about. |
| 06:53 | borkdude | ddellacosta_ but I'm very interested, because these are the problems I also deal with \ |
| 06:55 | apod | yocapybara: you probably need to switch the namespace, try C-c M-n |
| 06:55 | ddellacosta_ | borkdude: yeah, I'm probably not explaining it well, sorry. I have to put some solid examples together that really expose these confusing points, 'cause I run into them a lot day-to-day |
| 06:57 | apod | yocapybara: to evaluate the buffer C-c C-k |
| 06:59 | yocapybara | apod: thanks, this is exactly what I was missing and I hadn't put the pieces together - have just tried it and that's doing exactly what I was missing |
| 07:00 | yocapybara | apod: thanks loads :) |
| 07:00 | apod | yocapybara: also you can evaluate an expression under the point with C-c C-e (or C-c C-c to evaluate the top level form under point) and see the result on the minibuffer |
| 07:03 | yocapybara | apod: thanks also for that - I was doing that but I think perhaps due to not switching the namespace it seemed like anything I had previously executed with C-c C-e wasn't accessible. But having switched the namespace all clicks into place. I should have realised but didn't. Thanks! :) closer to clojure nirvana |
| 07:05 | yotsov | ddellacosta_: borkdude: my first attempt will be to use this approach https://github.com/yogthos/reagent-example (corresponding blog post http://getprismatic.com/story/1405451329953 ), It looks so simple and accessible and great that I got high on adrenaline+endorphin combo like in my early clojure days :) |
| 07:06 | ddellacosta_ | yotsov: awesome, whatever keeps the enthusiasm going. :-) |
| 07:06 | borkdude | yotsov :) |
| 07:45 | lvh | In clojure.test, how do I test multiple predicates, but retain useful error messages? |
| 07:46 | lvh | currently I'm doing (and (p? example) (q? example)) which results in totally useless error messages :( |
| 07:56 | hyPiRion | lvh: I usually `(do (is (p? example)) (is (q? example)))` |
| 07:56 | hyPiRion | at least then you know which one failed |
| 09:09 | piranha | I wonder if anybody has some code to generate simplest documentation for a liberator-based API? It seems there are no ready tools for that so I'll have to invent something... |
| 09:20 | CookedGryphon | what's the best way to do distinct? on a collection? |
| 09:20 | CookedGryphon | where the collection might be empty |
| 09:20 | CookedGryphon | best I can come up with so far is (apply distinct? :unlikely/ham coll) |
| 09:21 | CookedGryphon | otherwise I get an error with empty collections and have to do a separate check |
| 09:21 | TimMc | File a JIRA, wait, and sob. |
| 09:22 | TimMc | Mourn for http://dev.clojure.org/jira/browse/CLJ-1179 |
| 09:22 | CookedGryphon | ffs |
| 09:23 | TimMc | srsly |
| 09:23 | TimMc | It's shit like this... |
| 09:23 | justin_smith | ,(map (fnil #(apply distinct? %) [0]) (map seq [[] [:a] [:a :a] [:a :b :c]])) ; CookedGryphon |
| 09:23 | clojurebot | (true true false true) |
| 09:24 | justin_smith | unless you want (distinct? []) to be false, then change the last arg of fnil to [0 0] |
| 09:25 | justin_smith | sadly fnil only does its magic if the input is coerced via seq before you use it |
| 09:29 | CookedGryphon | justin_smith: yeah, it's still a bit messy though |
| 09:29 | CookedGryphon | feels a bit more professional than my :ham version :P |
| 09:31 | justin_smith | (defn distinctish? [& args] (or (empty? args) (apply distinct? args))) |
| 09:31 | justin_smith | another option |
| 09:32 | justin_smith | that's likely the clean one ... or (and args (apply distinct? args)) |
| 09:33 | CookedGryphon | yeah, that's what I've done |
| 09:33 | CookedGryphon | just defined the less stupid distinct? function |
| 09:33 | dnolen_ | (defn distinct-coll [coll] (reduce (fn [s x] (if (contains? s x) (reduced false) (conj s x))) #{} coll)) |
| 09:34 | CookedGryphon | It would make some amount of sense if it errored out on one argument as well |
| 09:34 | CookedGryphon | but apparently that's fine |
| 09:36 | CookedGryphon | can anyone offer any sort of explanation as to why it would be undesirable behaviour to return true rather than explode? |
| 09:37 | CookedGryphon | one single example of where it's not correct behaviour to just return true for the zero arity version |
| 09:37 | xemdetia | I don't think there is an opposing argument CookedGryphon |
| 09:38 | xemdetia | if you have variable length arguments surely you must handle gracefully a case where no arguments are passed |
| 09:38 | CookedGryphon | sorry, not in here, but on the jira ticket linked earlier apparently the change was rejected by rich |
| 09:39 | xemdetia | did anyone follow up with Rich? |
| 09:39 | CookedGryphon | not sure, all I have is the info on the ticket http://dev.clojure.org/jira/browse/CLJ-1179 |
| 09:40 | xemdetia | I saw the ticket a while ago but it's clearly a sore point |
| 09:40 | xemdetia | that's why I asked if anyone followed up |
| 09:46 | dnolen_ | CookedGryphon: xemdetia: likely not considered that important, also there are other fns with the exact same "problem" i.e. =, <, etc. |
| 09:47 | xemdetia | ah |
| 09:47 | CookedGryphon | dnolen_: I'm not sure it's as clear cut with = and < |
| 09:47 | xemdetia | still I think it's one of those |
| 09:48 | xemdetia | variable # arity functions should do something other then exceptions |
| 09:48 | xemdetia | when passed 0 args |
| 09:48 | CookedGryphon | there's an equal argument for true and false with = and not=, it's undefined i would say... |
| 09:48 | dnolen_ | CookedGryphon: anyways, clearly there are more nuances none which are in the ticket |
| 09:55 | justin_smith | xemdetia: what about / ? |
| 09:55 | justin_smith | ,(/ 2) |
| 09:55 | clojurebot | 1/2 |
| 09:55 | justin_smith | ,(/) |
| 09:55 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core//> |
| 09:55 | justin_smith | ,(/ 1 2 3) ; for good measure |
| 09:55 | clojurebot | 1/6 |
| 09:56 | justin_smith | I guess (/) could return NaN |
| 09:56 | xemdetia | justin_smith, I wouldn't normally consider / a variable length argument |
| 09:56 | justin_smith | but it is! |
| 09:56 | xemdetia | it is clearly :) |
| 10:04 | xemdetia | I guess I have to adjust my expectation, but so I will reduce it to still believing vararity -? functions should handle a 0 case. A query against an empty set still should provide a meaningful result, even if it's NOSETSILLY |
| 10:07 | CookedGryphon | but yeah, especially for distinct, it's really cut and dry. It currently does not perform the function described in its docstring "Returns true if no two of the arguments are =", point at the two arguments which are equal in (distinct?) and (distinct? 1) |
| 10:11 | bja | I should start returning 'NOTSETSILLY instead of nil for the 0 case |
| 10:11 | bja | with a link to this irc history |
| 10:11 | TimMc | dnolen_: I've never heard rhickey give nuance on tickets regarding base cases. |
| 10:12 | TimMc | I *have* to assume he just doesn't see the problem. |
| 10:13 | dnolen_ | TimMc: I also don't see the problem unless there's some larger discussion about apply not working on empty collections. |
| 10:13 | dnolen_ | for many fns. |
| 10:13 | TimMc | What do you mean? |
| 10:13 | TimMc | &(apply + []) |
| 10:13 | TimMc | Oh, not apply, but the fns themselves. |
| 10:14 | xemdetia | well it should be well-defined that it's going to error out so we don't have to point to some obscure Jira issue |
| 10:14 | dnolen_ | ,(apply = []) |
| 10:14 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/=> |
| 10:14 | dnolen_ | ,(apply < []) |
| 10:14 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/<> |
| 10:15 | xemdetia | numeric functions make sense to fail, I now reduce my argument to only predicate functions (-?) |
| 10:15 | TimMc | I don't think there's much to discuss -- base cases need to be defined unless there's a compelling reason not to. I mean it's a Lisp ffs. You'd think we'd get recursive base cases correct. :-/ |
| 10:16 | TimMc | But all I get from JIRA is... "nah". |
| 10:16 | dnolen_ | xemdetia: they do not make sense to fail |
| 10:16 | dnolen_ | ,(apply + []) |
| 10:16 | clojurebot | 0 |
| 10:16 | dnolen_ | ,(apply * []) |
| 10:16 | clojurebot | 1 |
| 10:17 | dnolen_ | people can keep pretending like there a simpler answer here |
| 10:17 | dnolen_ | or just write distinct-coll? and move on |
| 10:17 | TimMc | To the extent that there needs to be a larger discussion, it's "why do so many reasonable patches get rejected without comment?" |
| 10:18 | justin_smith | TimMc: meanwhile, Hickey is all like "let them eat transducers" |
| 10:18 | TimMc | (I am fine with comments like "we don't need that feature in core", that's a perfectly reasonable judgement call to make, even if I disagree sometimes.) |
| 10:30 | mavbozo | in leiningen :repl-options, the :ack-port is used for what? |
| 10:31 | borkdude | piranha I have seen a presentation on someone who used Swagger in combination with Liberator. That might be interesting for you? |
| 10:31 | piranha | borkdude: for sure! |
| 10:31 | borkdude | piranha it was at Euroclojure 2014. The video might be up |
| 10:31 | piranha | I'll look for that, thanks |
| 10:32 | borkdude | piranha http://vimeo.com/100485830 |
| 10:32 | mavbozo | i couldn't find the description for :ack-port in leiningen sample project here https://github.com/technomancy/leiningen/blob/master/sample.project.clj |
| 10:32 | piranha | borkdude: thanks :) |
| 10:32 | mavbozo | but :ack-port is used in leiningen.repl |
| 10:33 | corecode_ | hi |
| 10:33 | corecode_ | i think i found a bug in 4clojure or clojail, but i'm new to clojure and might be wrong |
| 10:34 | hyPiRion | mavbozo: ack-port is used to decide which port the acknowledgement from the repl server is sent/received |
| 10:34 | corecode_ | anybody like to indulge in following the issue? |
| 10:34 | hyPiRion | It's then used to generate e.g. .nrepl-port and similar |
| 10:34 | hyPiRion | ~anyone |
| 10:34 | clojurebot | anyone is anybody |
| 10:34 | hyPiRion | ~anybody |
| 10:34 | clojurebot | Just a heads up, you're more likely to get some help if you ask the question you really want the answer to, instead of "does anyone ..." |
| 10:34 | corecode_ | https://www.4clojure.com/problem/21 <- if you supply (fn [[h &t]] 1), it complains about nth being used |
| 10:35 | corecode_ | hyPiRion: finger reflexes? |
| 10:35 | borkdude | piranha sorry, no liberator in it, but still interesting ;) |
| 10:35 | corecode_ | hyPiRion: did you read what i wrote before? |
| 10:36 | tbaldridge | corecode_: yeah, I think the destructuring is calling nth |
| 10:36 | corecode_ | tbaldridge: ah, not in my clojure |
| 10:36 | tbaldridge | ,(macroexpand ,(let [[x y] (range 2)] x)) |
| 10:36 | clojurebot | 0 |
| 10:36 | tbaldridge | ,(macroexpand '(let [[x y] (range 2)] x)) |
| 10:36 | clojurebot | (let* [vec__52 (range 2) x (clojure.core/nth vec__52 0 nil) y ...] x) |
| 10:36 | hyPiRion | corecode_: right, just saying that people would reply if they know the answer :) It's not always easy to say "I'll help" if they don't know the problem |
| 10:37 | tbaldridge | corecode_: see my example there, it is calling nth via the let macro. So 4clojure is probably mocking out nth to make sure you're not calling it. But you are, just via a macro |
| 10:37 | corecode_ | hyPiRion: i think mindlessly doing the ~anybody is as bad as mindlessly asking such questions the bot refered to |
| 10:37 | jcsims | I've got a friend who wants to participate in the clojure cup with me, but is not familiar with clojure (he's comfortable in haskell). Any recommendations for someone coming to clojure from haskell? |
| 10:38 | corecode_ | tbaldridge: (macroexpand (read-string "(fn [[h & t]] h)")) |
| 10:38 | corecode_ | (fn* ([p__978] (clojure.core/let [[h & t] p__978] h))) |
| 10:38 | corecode_ | different clojure, i guess |
| 10:38 | tbaldridge | corecode_: that only macro expands a single form, you'd want something like macro expand all. |
| 10:38 | corecode_ | aha! |
| 10:38 | corecode_ | thanks |
| 10:38 | tbaldridge | corecode_: your let inside the fn hasn't been expanded to let* |
| 10:39 | corecode_ | right |
| 10:39 | piranha | borkdude: indeed, just watched slides. fnhouse-swagger is 54 lines, so maybe it won't be very hard to swaggerize my bidi + liberator setup... |
| 10:41 | corecode_ | hyPiRion: wouldn't you agree? |
| 10:42 | ncthom91 | hey y'all. Can I define a map literal where one of hte keys is a local variable? |
| 10:43 | ncthom91 | { my-var "val" } ? |
| 10:43 | ncthom91 | oh nvm, that works :P |
| 10:45 | hyPiRion | corecode_: I'm not saying it's bad to ask for help in that way, neither does the bot. It's just very common that new people ask "does anybody want to help me?", in which the reply rate is significantly lower than if you just ask the question itself |
| 10:45 | mavbozo | hyPiRion: why leiningen.repl creates another nrepl-server just to handle ack replies from the nrepl-server it creates? |
| 10:47 | hyPiRion | mavbozo: No, it creates only a single nrepl-server. Let me see if I can explain |
| 10:48 | mavbozo | hyPiRion: thanks |
| 10:48 | corecode_ | hyPiRion: what i'm saying is that it is bad to type ~anybody as a reflex to seeing the word |
| 10:49 | dbasch | I saw this code: (defn foo ^String [^bytes x] ….) <- is there something I'm missing or the ^String does nothing? |
| 10:49 | justin_smith | dbasch: it means foo returns String right? or is that the wrong place for that metadata? |
| 10:50 | dbasch | justin_smith: thst would be (defn ^String foo …) |
| 10:50 | justin_smith | in that case, I would guess it was a typo, and they were trying to do that |
| 10:51 | dbasch | justin_smith: it's interesting that it compiles quietly |
| 10:51 | hyPiRion | corecode_: Sure, but that wasn't what I did (or at least not what I was trying to convey). You asked if anybody wanted to indulge in the issue, which most people won't reply to |
| 10:51 | justin_smith | dbasch: well, it's not an error to add metadata to whatever silly thing you want to put it on |
| 10:52 | justin_smith | I guess that is putting metadata on the args vec? |
| 10:52 | cocquecigrue | has anyone ever had issues testing monger code in tests? I have a weird issue where when I run tests in the repl it works fine, the app itself works fine but when I use lein test it fails with nullpointerexception |
| 10:53 | cocquecigrue | i use clojure.test |
| 10:53 | justin_smith | cocquecigrue: the first thing I would suspect is that you are using something like map, where the result is forced in the repl but not in your code |
| 10:54 | dbasch | justin_smith: I suppose, but how would you even access that metadata? |
| 10:54 | justin_smith | dbasch: I don't think you could |
| 10:54 | cocquecigrue | justin_smith: what do you mean by map? |
| 10:54 | cocquecigrue | wait a second I push my code to github |
| 10:54 | justin_smith | cocquecigrue: the function map, which is lazy, but will seem not to be lazy in the repl because the print stage forces the result |
| 10:55 | justin_smith | cocquecigrue: but yeah, push your code, that will help |
| 10:55 | cocquecigrue | https://github.com/joelmarty/bonjour-compojure/blob/master/src/bonjour_compojure/database.clj |
| 10:56 | cocquecigrue | so the idea is to store the db object in an atom |
| 10:56 | cocquecigrue | when I call the init function |
| 10:56 | justin_smith | cocquecigrue: why would (:mongo-host (io/resource "app.edn")) return anything but nil? |
| 10:57 | justin_smith | oh, sorry, "defconfig", I missed that |
| 10:57 | cocquecigrue | that's the first thing i looked into :) |
| 10:58 | cocquecigrue | you can check the test in test/database |
| 11:00 | justin_smith | list-empty? is oddly named |
| 11:00 | justin_smith | it tests the reverse of that, right? |
| 11:01 | cocquecigrue | I don't use that yet |
| 11:01 | cocquecigrue | so it doesn't really matter |
| 11:01 | justin_smith | why do you nest use-fixtures inside deftest? |
| 11:01 | justin_smith | I don't know if that works, but I have never used it that way |
| 11:01 | justin_smith | it works just fine as a top level form |
| 11:01 | cocquecigrue | that's how the doc says to use it |
| 11:02 | justin_smith | weird |
| 11:02 | justin_smith | I have only used it as a top level form, and it works |
| 11:03 | cocquecigrue | when I use https://github.com/joelmarty/bonjour-compojure/blob/master/src/bonj |
| 11:03 | cocquecigrue | oops |
| 11:03 | cocquecigrue | when I use clojure.test/run-tests 'namespace in the repl it works just fine |
| 11:04 | cocquecigrue | but when I use it through lein that fails because the atom that holds the db is nil |
| 11:04 | cocquecigrue | so I guess the issue is not from the test but from the interaction with lein |
| 11:05 | cocquecigrue | maybe it's related to my environment i don't know |
| 11:05 | justin_smith | cocquecigrue: use-fixtures is a side-effecting function that changes how all functions in an ns are run, putting it inside a test makes no sense |
| 11:05 | cocquecigrue | how would you use it? |
| 11:05 | justin_smith | it is global, it does not modify the current scoped test definition, it alters all tests in the ns |
| 11:05 | cocquecigrue | you said to use it as a top form, what did you mean with that? |
| 11:06 | justin_smith | (use-fixtures :once f) will wrap all tests in one invocation of f |
| 11:06 | justin_smith | top level means not inside any other definition |
| 11:06 | cocquecigrue | ok |
| 11:06 | justin_smith | at the top level of the namespace |
| 11:06 | justin_smith | because it is a function that modifies the whole namespace |
| 11:07 | justin_smith | I think you would want (use-fixtures :each f) for your example |
| 11:07 | cocquecigrue | no I just want to create the db, run all the db-related tests and destroy it |
| 11:07 | justin_smith | OK |
| 11:07 | cocquecigrue | aaaaaaaaaaaah |
| 11:08 | justin_smith | then yeah, :once is fine |
| 11:08 | cocquecigrue | and it works |
| 11:08 | justin_smith | right, I told you you were using use-fixtures wrong |
| 11:08 | cocquecigrue | I must have misunderstood the doc, thank you :) |
| 11:08 | cocquecigrue | kudos |
| 11:09 | nburtsev | Hello |
| 11:09 | justin_smith | hi |
| 11:09 | nburtsev | user=> (defn test2 [] (prn "hello") (map (fn [[k v]] (prn k "-" v)) {:test "test" :test2 "test2"}) (when-not false (prn "hello2"))) |
| 11:09 | nburtsev | #'user/test2 |
| 11:09 | nburtsev | user=> (test2) |
| 11:09 | nburtsev | "hello" |
| 11:09 | nburtsev | "hello2" |
| 11:09 | nburtsev | anyone knows why map is not running ? |
| 11:09 | justin_smith | map is lazy |
| 11:10 | agarman | (doall ... |
| 11:10 | justin_smith | if you want it to run for side effects use dorun on it, or use doseq instead of map |
| 11:10 | agarman | or that |
| 11:10 | justin_smith | agarman: doall is pointless if you are not using the return value |
| 11:10 | justin_smith | it just generates garbage |
| 11:11 | justin_smith | doall is for when you need to force evaluation within a specific scope |
| 11:11 | nburtsev | thanks a lot! |
| 11:12 | nburtsev | it was starting to hurt my brain :\ |
| 11:12 | justin_smith | laziness is weird (it also creates weird stack traces sometimes) |
| 11:22 | perplexa | is (let [x []]) preferable over (let []) |
| 11:22 | borkdude | Is it possible in Om to inspect the state of children components? I have a form with fields that have local state :valid? and I want to "calculate" if the form as a whole is valid |
| 11:22 | perplexa | is (let [x []]) preferable over (let [x (vector)]) ? |
| 11:22 | justin_smith | yes |
| 11:22 | perplexa | ty |
| 11:22 | clgv | perplexa: is a matter of taste I guess - in the minimal case you posted [] is awful ;) |
| 11:23 | clgv | perplexa: but usually [a b ...] is pretty concise |
| 11:23 | perplexa | well i need an empty vector to which i conj later :P |
| 11:24 | borkdude | I could solve this with callbacks, but it really seems overhead to me |
| 11:24 | justin_smith | perplexa: usually, I find putting [] directly at the site of usage makes more sense than binding it to some symbol and using the symbol |
| 11:27 | clgv | borkdude: I have no idea about Om, but couldnt those components just implement a protocol where you can ask them "(valid? child)"? |
| 11:27 | perplexa | justin_smith: yeah i prefer it too tbh :) |
| 11:28 | clgv | lol yeah, since [] already is that symbol when you think about it ;) |
| 11:28 | justin_smith | if I am binding [], that would be in an atom or agent |
| 11:28 | justin_smith | clgv: indeed |
| 11:29 | borkdude | clgv don't know if this is possible |
| 11:29 | clgv | borkdude: me neither, it's just a general strategy where you do not have to know about the state which works often in general ;) |
| 11:34 | agarman | @justin_smith yeah I didn't read his example completely... missed that he was only doing prn |
| 11:52 | pjstadig | any opinions experience around sending a schema definition over the wire as data (Clojure->ClojureScript), reading it in as data, then using it to validate something ClojureScript side? |
| 11:54 | noonian | i think more commonly you would just use the same source file client and server side using cljx |
| 11:54 | schmir | pjstadig: why not? I'm doing something similar with clojure on both sides |
| 11:55 | noonian | you'd have to make sure they are serializable |
| 11:55 | pjstadig | noonian: we want to describe services and their data in a generic way, we don't know the schema ahead of time |
| 11:55 | noonian | ah, i see |
| 11:55 | pjstadig | the service would send a schema over the wire that could be used to construct a UI and validate before submitting a request |
| 11:57 | clgv | pjstadig: you might have to define a schema data since some constructs are not EDN serializable (if that is a requirement), e.g. regexps... |
| 12:06 | pjstadig | clgv: the challenge is that s/Str resolves to either java.lang.String or a javascript string and gets printed out in a way that cannot be read in the same with both Clojure and ClojureScript, most of the other stuff like vectors and sets seem to be fine |
| 12:07 | clgv | pjstadig: yeah and regexps are problematic ;) |
| 12:07 | pjstadig | so we're thinking of defining a deftype that represents a string, extending the schema protocol to it, defining its print method, and defining a data reader that we can use to write/read the schema as edn |
| 12:08 | clgv | sounds reaonable |
| 12:21 | radix | there's no insert operation for vectors, right? just double-checking my reading :) |
| 12:23 | justin_smith | radix: only append |
| 12:23 | justin_smith | radix: maybe you want a finger-tree |
| 12:23 | justin_smith | https://github.com/clojure/data.finger-tree |
| 12:24 | radix | oh, I see that hyPiRion is here. I actually got confused because his blog post (ostensibly about clojure vectors) talks about efficient insertion, but I guess that's not a property of clojure's vectors |
| 12:24 | radix | justin_smith: oh cool |
| 12:24 | justin_smith | efficient insertion, but only at the end :) |
| 12:26 | hyPiRion | radix: Hrm, where do I talk about that? Because that's wrong, and I should change the wording if you belived that |
| 12:26 | hyPiRion | Apologies for the confusion |
| 12:26 | radix | hyPiRion: I guess I just assumed mentions of "insertion" are the generalized case of insertion, not just appending. |
| 12:27 | radix | hyPiRion: by the way, thank you for writing that series, it's very very good :) |
| 12:27 | hyPiRion | radix: Ah, right. I should clarify that I mean appends. And thanks! :) |
| 12:28 | clgv | radix: you found bad wording there ;) |
| 12:30 | radix | finger trees look cool. |
| 12:33 | dnolen_ | radix: there's also rrb-trees, they are available for both Clojure/ClojureScript |
| 12:34 | noonian | you could also just use a hashmap |
| 12:35 | dnolen_ | radix: rrb-trees have the same api as vectors and can be used in their stead |
| 12:37 | radix | that's cool, I'll look at those too. |
| 12:56 | lodin | There's no harm in firing up lots of go blocks, right? |
| 12:59 | bendlas | lodin: not for your thread count, if that's what you mean |
| 12:59 | clojer_ | Compiling my cljs file produces: "Invalid token: :America/North_Dakota/Beulah" but this map key causes no errors when I test it in an Emacs cider repl. |
| 12:59 | bendlas | you'll eventually run out of memory though |
| 13:01 | bendlas | clojer_: hm, looks like symbols with more than one / are not allowed in cljs. They are definitely allowed in clj. dnolen_ do you know about this? |
| 13:01 | clgv | lodin: you won't be able to sell it as "Green IT" ;) :P |
| 13:01 | clojer_ | bendlas: Token originates from tzinfo so I need to keep it exactly as is. |
| 13:02 | lodin | bendlas: Sure. Memory is a cap. But that I don't think I have to worry about. |
| 13:02 | perplexa | mmh, i have a vector and want to append to that vector for each item in a different list with conj. i assumed it would change the referenced vector but didn't. what i got is: (doseq [source-cfg sources-cfg] (conj sources (source-tap (key source-cfg) (val source-cfg)))) - how do i get conj to append to the existing vector repeatedly? |
| 13:02 | justin_smith | clojer_: why not use it as a string? |
| 13:02 | bendlas | clojer_: maybe not save it into a keyword? seems wrong. |
| 13:02 | justin_smith | or a symbol |
| 13:02 | lodin | clgv: I'll have to find another angle then. ;-) |
| 13:03 | clgv | perplexa: persistent datastructures! |
| 13:03 | justin_smith | ,(get {"a" 0} "a") ; the syntax is a little funkier, but it works |
| 13:03 | clojurebot | 0 |
| 13:03 | perplexa | ,(let x [] (conj x "1") x) |
| 13:03 | clojurebot | #<CompilerException java.lang.IllegalArgumentException: let requires a vector for its binding in sandbox:, compiling:(NO_SOURCE_FILE:0:0)> |
| 13:03 | clgv | clgv: you need `reduce` |
| 13:03 | perplexa | ,(let [x []] (conj x "1") x) |
| 13:03 | clojurebot | [] |
| 13:03 | perplexa | how do i make that return 1? |
| 13:03 | perplexa | [1] to be precise |
| 13:04 | clojer_ | bendlas: Do you mean use a string as a map key instead? |
| 13:04 | justin_smith | perplexa: as clgv said, use reduce |
| 13:04 | bendlas | ,[(namespace :name/space/name) (name :name/space/name)] <- also consider this |
| 13:04 | clojurebot | ["name" "space/name"] |
| 13:04 | clgv | perplexa: please do read some introductory material on clojure since you fail the simplest basics |
| 13:04 | justin_smith | clojer_: no, use a string as the key |
| 13:04 | perplexa | clgv: i know :P |
| 13:04 | perplexa | thx |
| 13:04 | bendlas | clojer_: yes, string is the way to go |
| 13:04 | perplexa | i know about macros though :D |
| 13:05 | perplexa | i'm actually just learning it by implementing a project |
| 13:06 | clojer_ | bendlas: OK. The map is very large so will it impact performance significantly using strings? |
| 13:06 | clgv | perplexa: you'll have much quicker learning progress if you read either one of the online available introductions or a book while implementing that project |
| 13:07 | bendlas | clojer_: probably not, the map entry is found by hash anyway |
| 13:07 | perplexa | clgv: well i do that, too. |
| 13:07 | perplexa | but i honestly don't get how to use reduce in that case. |
| 13:08 | bendlas | clojer_: if you want to make sure to have no performance impact, intern the strings |
| 13:08 | bendlas | but shouldn't be nessecary at all |
| 13:08 | clgv | perplexa: then read up on reduce ;) |
| 13:08 | perplexa | at it |
| 13:11 | perplexa | clojurebot: so reduce + fn + conj it is :P |
| 13:11 | clojurebot | Ok. |
| 13:11 | perplexa | oh dude left :) |
| 13:12 | bendlas | perplexa: I think your case is served by into |
| 13:12 | bendlas | ,(into [1 2 3] (list 4 5 6)) |
| 13:12 | clojurebot | [1 2 3 4 5 ...] |
| 13:13 | bendlas | just make sure that you always go ahead with the return value (same as with conj) |
| 13:13 | bendlas | into is essentially (reduce conj to from) |
| 13:14 | perplexa | thx |
| 13:15 | bendlas | _the_ central value proposition of clojure is that functions like conj _never_ mutate in-place |
| 13:17 | lodin | perplexa: Beware that conj depends on the data type though. |
| 13:17 | lodin | ,(into (seq [1 2 3]) (list 4 5 6)) |
| 13:17 | clojurebot | (6 5 4 1 2 ...) |
| 13:21 | perplexa | lodin: yeah i read about that. |
| 13:29 | dnolen_ | bendlas: "'/' has special meaning, it can be used once in the middle of a symbol to separate the namespace from the name" |
| 13:29 | dnolen_ | bendlas: http://clojure.org/reader |
| 13:29 | dnolen_ | bendlas: it's not clear to me that means / can be used multiple times even though the reader implementation may allow it |
| 13:31 | bendlas | dnolen_: ok, question rephrased: is that incompatibility with clojure intentional? Schould we harmonize behavior in either direction? |
| 13:32 | dnolen_ | bendlas: I don't see a need to harmonize an implementation detail w/o asking on clojure-dev what is intended |
| 13:33 | Bronsa | AFAIK some-ns// is the only valid symbol that can have multiple "/" |
| 13:34 | hlprmnky_ | I have myself confused about a simple syntax question and cannot see what I’m doing wrong - I’m binding a java class inside a let form, and the thing I get in the form reports itself as a class, but calling ‘new’ on it is passing the bound name to ‘new’ instead of the class symbol |
| 13:35 | hlprmnky_ | e.g. (let [class java.lang.String] class) returns java.lang.String, but (let [class java.lang.String] (new class)) throws a CompilationException that the class ‘class’ cannot be found |
| 13:35 | bendlas | Bronsa: is that your interpretation of the reader doc? |
| 13:35 | hyPiRion | ,'_//_ |
| 13:35 | hlprmnky_ | I have searched many permutations of germane terms, read docs on java interop, and I still don’t see what I’m doing wrong htere |
| 13:35 | clojurebot | _//_ |
| 13:35 | hlprmnky_ | there* |
| 13:35 | bendlas | hlprmnky_: new is a special form, that only works with literal classes |
| 13:36 | hyPiRion | It's strange stuff. |
| 13:36 | hyPiRion | ,'_//_//_ |
| 13:36 | clojurebot | _//_//_ |
| 13:36 | Bronsa | bendlas: no, until 1.4.0 IIRC foo// would throw an exception and only clojure.core// was allowed. then a ticket was made to allow any-ns// that got in, but never has foo/bar/baz been a valid symbol |
| 13:36 | bendlas | if you want to instantiate from a class object, you need reflection |
| 13:36 | Bronsa | hlprmnky_: new is a special form that doesn't evaluate its first expression, the class name must be literal |
| 13:37 | bendlas | ,(namespace 'foo/bar/baz) |
| 13:37 | clojurebot | "foo" |
| 13:37 | hlprmnky_ | I see |
| 13:37 | bendlas | ,(name 'foo/bar/baz) |
| 13:37 | clojurebot | "bar/baz" |
| 13:37 | bendlas | Bronsa, seems to be valid |
| 13:37 | Bronsa | ,(symbol "foo bar") |
| 13:37 | clojurebot | foo bar |
| 13:37 | agarman | name of symbols accounts for the namespace it's in |
| 13:37 | agarman | ,(name 'foo.bar/baz) |
| 13:37 | clojurebot | "baz" |
| 13:37 | Bronsa | bendlas: clojure doesn't do much input validation, just because it accepts some inputs doesn't mean they are valid |
| 13:38 | bendlas | Bronsa: so what was the ticket to _make_ it valid about? |
| 13:38 | hyPiRion | bendlas: defining a function named / |
| 13:38 | hyPiRion | in other namespaces other than clojure.core |
| 13:38 | Bronsa | bendlas: only symbols whose name is "/" |
| 13:39 | bendlas | So that was the only thing, that didn't actually work? |
| 13:39 | hyPiRion | that works fine |
| 13:40 | hyPiRion | ,(defn / [x y] (+ x y)) |
| 13:40 | clojurebot | #<CompilerException java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)> |
| 13:40 | hyPiRion | except not in clojurebot |
| 13:40 | Bronsa | bendlas: right, in 1.4.0 'foo// would cause an exception |
| 13:40 | bendlas | or is a working foo/bar/baz a side effect of makeing foo// work? |
| 13:40 | bendlas | Bronsa: ok, IC |
| 13:41 | Bronsa | bendlas: I suspect that the reader change that made foo// a valid symbol made the reader accept foo/bar/baz aswell, unintentionally |
| 13:42 | dnolen_ | Bronsa: foo/bar/baz has actually worked for a long time, it's seems like a real ambiguity to me |
| 13:42 | agarman | Bronsa: not sure why bar/baz shouldn't be valid |
| 13:43 | Bronsa | tools.reader for example doesn't use tha same regex as LispReader.java and errors out when trying to read foo/bar/baz |
| 13:43 | bendlas | interesting, so i guess clojure.tools.reader does more input validation; and since that's what cljs uses by now there is this incompatibility |
| 13:43 | Bronsa | dnolen_: oh, you're right |
| 13:43 | Bronsa | dnolen_: well it's just another case of GIGO |
| 13:45 | Bronsa | the docs are explicit about that, so I'm confident in saying that foo/bar/baz is -- and has always been -- invalid |
| 13:46 | bendlas | Bronsa: I'm not so sure, stuff like (symbol "foo bar// $#%" "baz//zab") is perfectly valid |
| 13:46 | bendlas | there is just no reader syntax for it |
| 13:46 | Bronsa | bendlas: it's allowed because there's no validation, but it's not valid |
| 13:47 | bendlas | nope, even if there was validation, it should only ever be in the reader |
| 13:47 | bendlas | the docs you're referring to are also on a page called /reader |
| 13:48 | bendlas | Bronsa: at least that's my firmly held opinion, that constructors for symbol, keyword, ... should do no further validation than to see if namespace and name are strings |
| 13:49 | agarman | Bronsa: the docs I'm reading just says that symbols containing / are qualified |
| 13:50 | agarman | Bronsa: my understanding of qualified is that the namespace will consume the symbols string to the first / not that there can be no additional / |
| 13:50 | bendlas | agarman: well, it says '/' has special meaning, it can be used once in the middle of a symbol |
| 13:50 | hyPiRion | The docs are outdated |
| 13:50 | bendlas | that can conceivably be interpreted to mean "at most once" |
| 13:51 | hyPiRion | There's nothing about quote being a legal part of a symbol on the /reader page. |
| 13:51 | agarman | bendlas: the rest of that doc is "to separate the namespace from the name" nothing stating that an additional / can't be used, but it's assumed that it won't have special meaning then |
| 13:52 | agarman | not assumed it's explicit that any other / won't have special meaning |
| 13:52 | bendlas | agarman: yes, I tend to follow this interpretation. Bronsa seems to be against it and dnolen_ seems to be on the fence and wants it discussed on clojure-dev |
| 13:53 | agarman | hyPiRion: (other characters will be allowed eventually, but not all macro characters have been determined) would cover ' |
| 13:54 | agarman | in that the expected behavior is indeterminate |
| 13:55 | Bronsa | bendlas: agarman wrt "foo/bar/baz", as hyPiRion says the clojure.org docs are outdated and open to interpretations, however if you read https://github.com/edn-format/edn#symbols it's clear that "foo/bar/baz" is not valid |
| 13:56 | agarman | edn is a data exchange format... it doesn't represent the full capabilities of the reader |
| 13:56 | agarman | though I'd agree that they should be fairly consistent |
| 13:56 | Bronsa | agarman: I'm well aware of that but I hardly doubt that an edn symbol and a clojure symbol would differ |
| 13:57 | bendlas | Bronsa: but they do, ' isn't mentioned in edn symbols either |
| 13:58 | bendlas | Bronsa: (edn/read-string "foo'") works though |
| 13:58 | Bronsa | bendlas: eh, that's a bug in the spec |
| 13:58 | agarman | ,(clojure.edn/read-string "foo/bar/baz") |
| 13:58 | clojurebot | #<ClassNotFoundException java.lang.ClassNotFoundException: clojure.edn> |
| 13:59 | agarman | ,(require '[clojure.edn :as edn]) |
| 13:59 | clojurebot | nil |
| 13:59 | agarman | ,(edn/read-string "foo/bar/baz") |
| 13:59 | clojurebot | foo/bar/baz |
| 13:59 | agarman | valid is what works |
| 13:59 | dnolen_ | Bronsa: well I think supporting quirks is OK - but I definitely never thought of foo/bar/baz as being valid |
| 13:59 | agarman | docs or code should be fixed though |
| 13:59 | dnolen_ | agarman: sadly it is not, it's just undefined |
| 13:59 | justin_smith | ,(edn/read-string "this\nis\nmultiple\lines") |
| 13:59 | clojurebot | #<RuntimeException java.lang.RuntimeException: Unsupported escape character: \l> |
| 13:59 | hlprmnky_ | Bronsa, bendlas: thanks for the assistance - I was (after only a few moments of slack-jawed disdain) able to use .getConstructor … .newInstance to do what I wanted |
| 13:59 | justin_smith | ,(edn/read-string "this\nis\nmultiple\nlines") |
| 13:59 | clojurebot | this |
| 14:00 | hlprmnky_ | slack-jawed disdain at the hoops you have to jump through to make Java give you an instance of something via reflection, not at new being a special form :) |
| 14:00 | agarman | ,(type (edn/read-string "foo/bar/baz/quux/giggle")) |
| 14:00 | clojurebot | clojure.lang.Symbol |
| 14:01 | bendlas | hlprmnky_: yw |
| 14:01 | hyPiRion | that's because |
| 14:01 | hyPiRion | ,(read-string "foo/bar/baz/quux/giggle") |
| 14:01 | clojurebot | foo/bar/baz/quux/giggle |
| 14:02 | Bronsa | agarman: bendlas I'm in the difficult position of using an uncomplete/outdated spec as basis of my thesis, but I think the documentation is clear on the foo/bar/baz issue. |
| 14:04 | Bronsa | agarman: bendlas paraphrasing, it says "those are the valid characters you can use in a symbol, additionally you can use '/' once in the middle of the symbol", that "once" is definitely "once and only once" if you take into account how it's phrased for '.': "it can be used one or more times in the middle of a symbol" |
| 14:04 | bendlas | but why not take a step back, and admit that it should mean, what we want it to mean, with Rich having the last say of course. |
| 14:06 | bendlas | Bronsa: yeah, ok, foo/bar/baz really should be disallowed in edn _and_ in the reader, because it's unnessecarily surprising |
| 14:06 | bendlas | however, (symbol "foo/bar" "baz") aswell as (symbol "foo" "bar/baz") should be considered valid |
| 14:07 | bendlas | (and distinct) |
| 14:11 | bendlas | Bronsa, dnolen_, agarman, hyPiRion: unless any of you is already at it, I'll do a writeup to clojure-dev |
| 14:14 | Bronsa | bendlas: you might be right about "runtime symbols" not being restricted in the same ways of "reader symbols", I have to say that every time the discussion about (symbol "foo bar") being valid has come up, the consensus has been that it's just a result of GIGO -- go on with a ml writup if you want official answers |
| 14:27 | shoepie | any vim users know how to correctly indent .clj files using vim-clojure-static? |
| 14:32 | TimMc | ,(.newInstance String) ;; hlprmnky: It's easy if you want the nullary constructor. |
| 14:32 | clojurebot | "" |
| 14:33 | hlprmnky | true, but I actually needed a String constructor |
| 14:34 | hlprmnky | it’s not so bad, considering, I just don’t have to wander down that deep into the boilerplate mines very often |
| 14:35 | amalloy | hlprmnky: clojure.lang.Reflector/invokeConstructor is easier to use |
| 14:36 | amalloy | ,(let [c java.util.ArrayList] (clojure.lang.Reflector/invokeConstructor c (object-array [10]))) |
| 14:36 | clojurebot | [] |
| 14:36 | amalloy | (that 10 is the initial capacity, so it still just looks like an empty list |
| 14:36 | amalloy | ) |
| 14:36 | hlprmnky | ! |
| 14:37 | hlprmnky | that is indeed much nicer |
| 14:37 | hlprmnky | thanks! |
| 14:44 | TimMc | So that's if you only care about dynamic dispatch to a constructor, not static dispatch. |
| 14:44 | TimMc | handy |
| 14:47 | amalloy | TimMc: indeed, i think it's the same logic that (Foo. x y z) goes through if you don't hint x/y/z |
| 14:48 | amalloy | the last time i wanted to reflectively invoke a constructor i wanted to do it multiple times, though, so i ended up saving the Constructor handle to reuse it |
| 14:48 | amalloy | the reflector doesn't give you that flexibility |
| 14:48 | amalloy | (if you care about performance, anyway) |
| 14:52 | upwardindex | I’m getting Unsupported major.minor version 51.0 when trying to lein `cljsbuild once`. Google tells me something about not having the right jdk/jre. Has anyone encountered this? |
| 14:55 | amalloy | upwardindex: you're running something compiled against java 7, on a jre 6 or lower |
| 14:55 | justin_smith | upwardindex: what does "java -version" return in your shell? |
| 14:56 | upwardindex | justin_smith: java version "1.6.0_65" in terminal but in system preferences it says java 1.7something |
| 14:56 | justin_smith | upwardindex: then call the 1.7something version, or fix your path so it is before the 1.6 |
| 14:57 | justin_smith | upwardindex: you can explicitly set the java location via an env var or project.clj setting in lein |
| 14:58 | upwardindex | justin_smith: thank you, I’ll look into that |
| 14:58 | justin_smith | https://github.com/technomancy/leiningen/blob/master/sample.project.clj#L259 |
| 14:58 | justin_smith | example in the above link |
| 15:13 | ToxicFrog | Huh. |
| 15:13 | ToxicFrog | So I can't use :refer :all even for things that will be released as an uberjar, because the warning messages from the compiler can't be supressed and are emitted when it's run from the jar, too |
| 15:15 | noonian | ToxicFrog: you might find slamhound helpful; it will automatically figure out which vars you're using and generate a nice require form for you |
| 15:15 | noonian | https://github.com/technomancy/slamhound |
| 15:16 | bendlas | ToxicFrog: Don't use :refer :all, only acceptable usage is from a repl session how or why should uberjar protect from its perils? |
| 15:17 | bendlas | yeah, slamhound's pretty cool for that |
| 15:18 | ToxicFrog | bendlas: I'm :refer :alling core.typed, so that I get all of the typenames in scope, rather than having an ugly mix of naked type names and t/ prefixed type names. |
| 15:18 | TimMc | bendlas: It is sometimes appropriate. |
| 15:18 | ToxicFrog | However, this also brings in core.typed/for et al which generates the shadowing warnings. |
| 15:18 | TimMc | You can exclude that, I think? |
| 15:18 | ToxicFrog | I was hoping that the requiring would happen entirely during the compilation process, and thus there would be nothing to warn about during runtime when the jar is executed. |
| 15:19 | ToxicFrog | Of course, this doesn't address at all the common case where you want to refer those and quite deliberately shadow the clojure.core versions |
| 15:19 | ToxicFrog | AFAICT, in that case, you're just screwed |
| 15:19 | TimMc | ToxicFrog: :refer-clojure :exclude |
| 15:20 | bendlas | ToxicFrog: yeah, it would be pretty cool for clojure to be able to compile that way |
| 15:20 | bendlas | similar to cljs |
| 15:20 | bendlas | maybe we'll get there one day, with the lean-compile stuff |
| 15:20 | ToxicFrog | TimMc: holy this I did not know about refer-clojure |
| 15:20 | ToxicFrog | Thank you |
| 15:24 | jlongster | do you have to use a buffer when using a transducer with a channel? |
| 15:31 | linman32 | hi i have a clojure compile error. |
| 15:31 | linman32 | http://pastebin.com/ZZFaNFFC |
| 15:32 | linman32 | the error doesn't seem to point to a specific file though |
| 15:32 | ToxicFrog | Welcome to clojure compile errors: abandon every hope, ye that enter |
| 15:33 | justin_smith | /tmp/form-init3292773767470107555.clj:1:72 is something your toolchain likely created |
| 15:33 | justin_smith | no promises that it is readable... |
| 15:33 | justin_smith | the :1:72 mean line 1, character 72 |
| 15:33 | stompyj | jlongster: I’ve only ever seen it done that way, but I don’t know for sure |
| 15:34 | linman32 | the file is no longer there |
| 15:34 | jlongster | stompyj: I think that's true. reading the source, and it kinda makes sense |
| 15:35 | justin_smith | linman32: what did you run when you got that error? lein repl? |
| 15:35 | linman32 | justin_smith: should i try updating my toolchain? i got leiningen recently. like 3 days ago |
| 15:35 | linman32 | justin_smith: yes |
| 15:35 | justin_smith | was this run from inside a project directory? |
| 15:36 | linman32 | yes |
| 15:36 | justin_smith | can you share your project.clj? |
| 15:36 | justin_smith | I suspect a string where there should be a symbol, in either project.clj or your core namespace |
| 15:37 | linman32 | justin_smith: https://github.com/AustinClojure/groops/blob/master/project.clj |
| 15:38 | justin_smith | :init-ns should not be a string, it should be a symbol |
| 15:38 | justin_smith | that may be the issue |
| 15:38 | justin_smith | (under :profiles / :dev / :repl-options) |
| 15:39 | justin_smith | so try taking out the quotation marks, and running lein repl again - that may just fix it |
| 15:40 | linman32 | wow, seems to be working! that was a nice find |
| 15:41 | caldiar | New to clojure and was wondering if it's considered "proper" clojure to make use of records rather than maps. Or are records/protocols there to make transitioning to clojure easier for people used to object-oriented design? |
| 15:41 | linman32 | justin_smith: how did you find it so fast? |
| 15:41 | justin_smith | linman32: those temp files are created based on the contents of project.clj |
| 15:42 | justin_smith | the error was string could not be cast to symbol |
| 15:43 | justin_smith | so I looked for strings that should not be strings, it's a small file |
| 15:43 | justin_smith | double checked with the lein example project.clj that :init-ns should not be a string |
| 15:43 | perplexa | had some time to read up on reduce+conj \o/ |
| 15:44 | caldiar | To provide some context, I have several entities which can have different behaviors such that a minotaur can move 1 unit at a time while an imp could move 2 units at a time. I was thinking a protocol and records which implement the move method would be best suited for this or if there was a more idiomatic way. |
| 15:44 | justin_smith | caldiar: you can switch to records if maps are slowing you down in a bottleneck |
| 15:44 | justin_smith | a multimethod can determine behavior from any function on your data |
| 15:44 | justin_smith | also, multimethods that use keywords can take advantage of multiple inheritence via derive |
| 15:45 | justin_smith | (this is not possible with records) |
| 15:45 | justin_smith | well, I guess it could be, but it isn't possible with protocols is what I really meant |
| 15:48 | caldiar | one of the ways I'm seeing things done (from the caves of clojure series of articles) is that there's multiple protocols and a record which uses extend-type for each protocol it would like to implement |
| 15:48 | justin_smith | that's another way to do it |
| 15:48 | justin_smith | protocols are a pain in the ass in interactive development |
| 15:48 | mdeboard[IND] | Elixir helped me understand protocols in Clojure much better |
| 15:49 | caldiar | my concern is that I don't want to get into bad habits and wind up having things come back to bite me later |
| 15:49 | justin_smith | maps upgrade seamlessless to records |
| 15:50 | caldiar | alright, thanks guys |
| 15:53 | borkdude | I would like to start my clojure app in a Docker container, wait until the server is started and then run tests against that server in the same docker container. My question: can I run test from something like an uberjar which I will add to the container? |
| 15:53 | borkdude | so basically it all runs in one container |
| 15:54 | borkdude | and I don't want to install leiningen etc in the image, too much work |
| 15:54 | justin_smith | borkdude: you can use test/run-tests for each test-ns inside an init function |
| 15:55 | borkdude | justin_smith ah, of course, thanks. |
| 15:55 | justin_smith | you may want to make sure the test namespaces are compiled into the uberjar, of course |
| 15:55 | borkdude | will the test code be included in an uberjar? |
| 15:55 | justin_smith | if it isn't, there should be a simple path to make it happen |
| 15:55 | borkdude | justin_smith hmyeah |
| 15:57 | justin_smith | and its easy to check if those files are in your uberjar - a jar is just a zip with special properties |
| 15:59 | borkdude | justin_smith right |
| 17:13 | mikerod | I'm wanting to understand the rationale behind this: |
| 17:13 | mikerod | ,(coll? {}) |
| 17:13 | clojurebot | true |
| 17:13 | mikerod | ,(instance? java.util.Collection {}) |
| 17:13 | clojurebot | false |
| 17:14 | mikerod | Are there any good links? |
| 17:14 | mikerod | :D |
| 17:14 | jkj | mikerod: well i quess java collections have features that coll doesn't need |
| 17:14 | jkj | let's see |
| 17:14 | mikerod | jkj: searching has been difficult |
| 17:14 | mikerod | hitting completely unrelated topics |
| 17:15 | justin_smith | ,(instance? clojure.lang.IPersistentCollection {}) |
| 17:15 | clojurebot | true |
| 17:15 | justin_smith | that's what coll tests |
| 17:15 | mikerod | yes, justin_smith I was just shorthand'ing that part |
| 17:15 | jkj | mikerod: momentos. firing up my repl |
| 17:15 | mikerod | ,(instance? java.util.Collection []) |
| 17:15 | clojurebot | true |
| 17:15 | jkj | when do we have fast start |
| 17:15 | mikerod | I just see that Clojure chose to view a Persistent*Map as a IPersistentCollection |
| 17:16 | mikerod | but not as a j.u.Collection |
| 17:16 | jkj | ,(map :name (:members (clojure.reflect/reflect java.util.Collection))) |
| 17:16 | clojurebot | #<CompilerException java.lang.ClassNotFoundException: clojure.reflect, compiling:(NO_SOURCE_PATH:0:0)> |
| 17:16 | jkj | oops. it is cljs? |
| 17:16 | justin_smith | mikerod: based on the docs for Collection, it is not used for maps |
| 17:17 | jkj | mikerod: (:bases (clojure.reflect/reflect {})) |
| 17:23 | mikerod | justin_smith: I don't see the docs that you are referring to for that |
| 17:24 | mikerod | It makes sense to me that Clj maps are not a j.u.Collection since j.u.Map is not though. I guess I should just look at it that way. |
| 17:25 | justin_smith | http://stackoverflow.com/a/2651833/2258453 answer has a quote from the java design documents |
| 17:31 | mikerod | Oh, yes I should have looked for that. Thanks justin_smith |
| 17:32 | mikerod | and thanks jkj for the input |
| 18:02 | razum2um1 | is there any library to inspect java object - for now i use https://gist.github.com/razum2um/ffaaf90731f27a988141 but maybe someone has better ways? |
| 18:07 | razum2um1 | better to say - is there any way to get, say, annotated source from maven (if possible) and show members with descriptions. Or (javadoc) with lucky google is best option? |
| 18:10 | justin_smith | #(apply dissoc % [:exception-types]) is #(dissoc % :exception-types) |
| 18:11 | justin_smith | #(contains? (:flags %) :public) could be (comp :public :flags) in this case |
| 18:11 | celwell | Hello, what's a good library (or technique) for running a function every 3 minutes? |
| 18:12 | Jaood | sleep? |
| 18:13 | celwell | Jaood: is that safe? i just don't want to run out of memory after a few days |
| 18:13 | Jaood | Thread/sleep |
| 18:13 | justin_smith | celwell: depends on whether you are using loop / while or simple self call |
| 18:14 | arrdem | Bronsa: so does the scheduler buy you anything performance wise? |
| 18:14 | justin_smith | celwell: for more power (and complexity) there is java.util.Timer which you can use via interop |
| 18:15 | bendlas | razum2um1: just the other day, I've written a thing that uses reflection to pretty-print java classes: https://github.com/webnf/webnf/blob/master/base/src/webnf/base.clj#L100 |
| 18:16 | bendlas | it's turned out pretty nifty for exploring interacting with java objects from repl |
| 18:16 | razum2um1 | justin_smith: thanks for feedback ;) |
| 18:17 | justin_smith | there is also bean, which suffices for some objects (and at least helps with others) |
| 18:17 | justin_smith | ,(bean "hello") |
| 18:17 | clojurebot | {:empty false, :class java.lang.String, :bytes #<byte[] [B@1c1e75a>} |
| 18:17 | razum2um1 | bendias: could you provide an example of this? |
| 18:18 | Bronsa | arrdem: no, it just automates the pass composition/dependency resolution |
| 18:18 | arrdem | Bronsa: :thumbsup: |
| 18:18 | Jaood | celwell: I guess using a delay with some time api could be more elegant |
| 18:19 | dbasch | celwell: that question is pretty generic, it depends on what you want to do and what level of operational reliability you need |
| 18:19 | dbasch | celwell: e.g. if you don't trust your own code you could use cron to start a jvm every time |
| 18:19 | razum2um1 | bendlas: may I mention webnf in https://github.com/razum2um/awesome-clojure under frameworks? |
| 18:20 | celwell | dbasch: I'm running a ring server and need to spawn a 3-minute-interval-called function that gets certain rows from a db and may or may not update those rows. |
| 18:20 | Bronsa | arrdem: I was able to reduce the number of complete tree traversals from 8 to 7 but I doubt it's going to result in a noticeable speedup |
| 18:21 | bendlas | razum2um1: here http://pastebin.com/CsUGvAy5 |
| 18:21 | arrdem | Bronsa: yeah that sounds about right. |
| 18:21 | bendlas | razum2um1: of course! |
| 18:22 | dbasch | celwell: as long as you don't hold on to the rows so they can be garbage-collected, and you run your jvm with enough heap, you should be fine |
| 18:22 | bendlas | although, it's intended to not be a framework, but a set of orthogonal libs that happen to interact well |
| 18:22 | dbasch | celwell: if you're on linux there's always a chance that the kernel might kill your process, so you may want to have a watchdog script to restart it |
| 18:23 | celwell | dbasch: are you saying that same would be true for the ring server itself? it might just die without auto restarting? |
| 18:23 | dbasch | celwell: yes, any jvm on linux could die without autorestarting |
| 18:24 | dbasch | celwell: you can tell the oom killer to ignore a process, but it's usually not the best idea |
| 18:25 | arrdem | dec finite memory machines |
| 18:25 | celwell | dbasch: I'm relatively new to the JVM (coming from PHP). Do you know of any material I can read to learn how to have a reliable ring server. Sorry I guess that's vague. But with PHP I would just let it run until I something messed up and i would restart apache. |
| 18:26 | razum2um1 | bendlas: looks nice, maybe extract some fns like that? |
| 18:27 | bendlas | razum2um1: by 'extract' do you mean 'pack them in a library, so that they can be used independently'? |
| 18:27 | razum2um1 | bendlas: pack |
| 18:27 | bendlas | if so, that's what I'm doing with webnf |
| 18:28 | razum2um1 | bendlas: they are too different, e.g. hostname and pr-cls |
| 18:28 | dbasch | celwell: the important thing is to run the jvm with appropriate parameters, and to have a cron job or script to restart it if it dies unexpectedly |
| 18:28 | bendlas | it's basically all the fns, that I kept copy-pasting from project to project |
| 18:28 | dbasch | celwell: you also want to configure it to run on boot if your machine could lose power or reboot for some reason |
| 18:28 | razum2um1 | bendlas: )) yep. saw this in clojure community everywhere |
| 18:29 | celwell | dbasch: thanks for the advice |
| 18:30 | razum2um1 | hm folks, why not to join efforts and have one modular project like webnf, but having MORE than 1 contributor. just like active support in ruby land? |
| 18:30 | bendlas | yeah, I'm trying to split them into sub projects tastefully, it's always a balancing act between getting on with my projects while pushing snippets into webnf, and then refactoring webnf itself, e.g. introducing new packages |
| 18:31 | razum2um1 | now I see everyone is duplicating some fnsctions with different names or even copypaste them into HIS toolbox library |
| 18:31 | razum2um1 | is it really a trend to have *my-own-helper-library* ? |
| 18:31 | justin_smith | no |
| 18:32 | razum2um1 | e.g. timbre's author has his lib too |
| 18:32 | bendlas | razum2um1: yay, I'd be all for it. problem is maintainership in all its facets |
| 18:32 | justin_smith | check out flatland/useful for a general set of useful stuff that isn't in core though https://github.com/flatland/useful |
| 18:33 | razum2um1 | justin_smith: 6 contributors ;) |
| 18:33 | justin_smith | and they accept pull requests |
| 18:34 | razum2um1 | justin_smith: I meant forces are disjoint. compare rails with 2k contributors (of cource, clj is not widly used, but *there ARE more than 6 clojurists) |
| 18:35 | noonian | ,(def truthy? (comp not not)) |
| 18:35 | clojurebot | #'sandbox/truthy? |
| 18:35 | justin_smith | razum2um1: I'd say 6/2000 is about the ratio of clojure to ruby users (maybe it is a bit hight actually) |
| 18:35 | justin_smith | noonian: isn't that what boolean does? |
| 18:36 | justin_smith | ,(map boolean [true false nil 1 0 () []]) |
| 18:36 | clojurebot | (true false false true true ...) |
| 18:36 | noonian | justin_smith: heh, i guess so; i didn't know boolean was a core function :P |
| 18:36 | razum2um1 | justin_smith: e.g. in golang land there are LOTS of lein/bundler analogs all of them are depending on 1-2 devs. we have lein and it's cool or pain of choice ;) |
| 18:37 | razum2um1 | i meant *no* pain of choice ;) |
| 18:38 | justin_smith | there have been alternatives to lein, but they haven't gone far |
| 18:38 | noonian | i think most clojure libs tend to be smallish and so much easier to maintain by 1-2 people, also tend to get to a point where they work and aren't touched much except for major refactors or api changes |
| 18:38 | xemdetia | such is the land of lisp |
| 18:39 | razum2um1 | justin_smith: yes and 227 contributors to lein show where the mainstream is. why there is no lein-like "activesupport" what do you think? |
| 18:40 | justin_smith | razum2um1: for the most part, clojure people hate frameworks and don't use them |
| 18:40 | razum2um1 | it doesn't have to be one repo |
| 18:41 | razum2um1 | but can be ogranisation |
| 18:41 | bendlas | razum2um1, justin_smith: so IMO, if we were to have a place where everybody could maintain their favourite helper code, it would nessecarily have to be split into various subprojects with different focus |
| 18:41 | justin_smith | razum2um1: and if there was a single lib that supplied multibyte strings, internationalization, time zones, testing, etc. for clojure, people would ask why so many different things were in one lib |
| 18:41 | xemdetia | I thought we already had github /snark |
| 18:41 | bendlas | that's why i laid out webnf that way from the start |
| 18:41 | razum2um1 | bendlas: yes, but I don't see any so far |
| 18:41 | razum2um1 | oops, perhaps webnf is it ;) |
| 18:42 | razum2um1 | but again, bendlas, you are *alone* |
| 18:42 | justin_smith | razum2um1: thanks to lein / clojars, we don't need everything to be coming from one organization. It is easy for anyone to share whatever libs they would like to share. |
| 18:43 | bendlas | yeah, ML reactions to new announcements have become increasingly apathetic, last couple of years |
| 18:44 | razum2um1 | justin_smith: I didn't mean that, I mean some really mainstream helper lib. like clojure.contrib before, *but* it doesn't have to be single project/repo |
| 18:44 | noonian | it seems like we are somewhat converging in terms of ways to design system with design patterns like stuart sierra's component and libraries building on those ideas like trapperkeeper and modular |
| 18:44 | bendlas | I mean, leiningen + clojars gets you 90% there, the only thing that's really missing are dependency sets to get rid of those ridiculously long :dependency lists |
| 18:44 | bendlas | i.e. webnf.deps/* |
| 18:44 | razum2um1 | bendlas: :) |
| 18:44 | justin_smith | razum2um1: we have a mainstream helper lib. If you want a bigger, more comprehensive one, go ahead and make it I guess? |
| 18:45 | razum2um1 | justin_smith: there will be no good since I will be only one, who is using it |
| 18:46 | justin_smith | if it's good enough, other people will use it, if it isn't good enough they shouldn't be using it - I really fail to see what the problem is here |
| 18:47 | noonian | i bring prismatic plumbing into all the project i make now, i think they've done a good job extending the language with small useful functions/macros |
| 18:47 | bendlas | justin_smith: the problem is, that even for more that good enough code, if it doesn't hit an immediate need (like leiningen did), you have a discoverability problem (i.e. marketing) |
| 18:48 | razum2um1 | justin_smith: it starts when I started write class-inspection function and setup a repo for it and some more others, then saw bendlas's webnf, then you… everyone has his own. it dramatically reduces recognizable of other's code |
| 18:48 | noonian | the ?> and ?>> conditionals for use with the threading macros are really nice |
| 18:49 | razum2um1 | justin_smith: I mean to read someone's code with *HIS* helper functions we must read them all too |
| 18:49 | razum2um1 | justin_smith: some standard is needed i think |
| 18:49 | justin_smith | how much of rails code have you read? |
| 18:49 | justin_smith | I mean the underlying code |
| 18:49 | razum2um1 | justin_smith: lots and have commits there |
| 18:51 | bendlas | FWIW, i don't think rails is the model we should be aiming for, despite its success |
| 18:51 | razum2um1 | and some not accepted PR's since I made gems for that, but it's offtopic |
| 18:51 | bendlas | I try to think more along the lines of the new clojure contrib stuff |
| 18:52 | bendlas | single-purpose, replaceable |
| 18:52 | justin_smith | bendlas: agreed 100%, just checking if razum2um1 was actually one to read the source for all the libraries used by the libraries he uses |
| 18:52 | razum2um1 | bendlas: now I mean some very specific thing: activesupport is *widely* accepted, without rails too, and I read code with it much faster |
| 18:53 | bendlas | OIC |
| 18:54 | bendlas | i think, the excellent platform support of clojure hurts this cause. Most people are just like: 'eh, i can use that java lib' |
| 18:54 | justin_smith | and they are probably better off just using the java lib too, in many cases |
| 18:55 | bendlas | true\ |
| 18:55 | bja | I don't think I even use very many clojure libraries. Mostly just wrappers for java stuff |
| 18:56 | razum2um1 | bja: do you think it's better *even* no to wrap them? |
| 18:57 | noonian | i prefer pure clojure libs to java wrappers if they are available |
| 18:57 | razum2um1 | actually I'm late to this party, is this trend still in (wrap java)? |
| 18:57 | razum2um1 | noonian: tend to agree |
| 18:58 | bendlas | i'd say yes, but only for stuff whose java impl is excellent |
| 18:58 | matthiasn | hey guys, I am stuck with a problem. I have an application that runs nicely on my mac but when I try to run it on Ubuntu 14.04 (lein run or the uberjar makes no difference) I get the following error: Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :make-writer of protocol: #'clojure.java.io/IOFactory found for class: nil, compiling:(/tmp/form-init5185754411886008906.clj:1:72) |
| 18:58 | matthiasn | Does anyone have an idea where to look? thanks a lot |
| 18:58 | noonian | when there are big java libs that don't need to be re-written people tend to wrap them, like aws java clients for example |
| 18:59 | rweir | weird java errors always make me trash ~/.m2/repos just in case |
| 18:59 | justin_smith | matthiasn: wait, the uberjar is referring to /tmp/form-intblablahblah? |
| 18:59 | noonian | matthiasn: when you say it runs fine on your mac did you try running from an uberjar or just in the repl? |
| 18:59 | bja | razum2um1, it depends on the java library. I go back and forth on whether marceline is an improvement over regular JVM interop for Storm's Trident API |
| 18:59 | bendlas | matthiasn: thats basically a null pointer exception. Probably from a resource fail, that's not been found on the different platform |
| 19:00 | matthiasn | @noonian on mac either repl, run or uberjar all work |
| 19:00 | bendlas | lol, *resource file |
| 19:01 | matthiasn | @justin_smith: that was when doing lein run |
| 19:01 | justin_smith | matthiasn: OK, what is the error with an uberjar? |
| 19:01 | noonian | matthiasn: maybe forgot to check a resource into git or something? |
| 19:01 | justin_smith | also, the error with lein run points to a file, in /tmp/ that is generated based on your project.clj |
| 19:02 | matthiasn | noonian: there’s one config file that’s not checked in because of credentials, but it’s there locally |
| 19:02 | justin_smith | matthiasn: with an identical path? |
| 19:02 | bendlas | look for stuff that would lead to (clojure.java.io/writer nil) |
| 19:03 | matthiasn | justin_smith: with uberjar its just: Exception in thread "main" java.lang.IllegalArgumentException: No implementation of method: :make-writer of protocol: #'clojure.java.io/IOFactory found for class: nil |
| 19:04 | bendlas | does it try to write to some OSX specific path like /User/... ? |
| 19:04 | matthiasn | justin_smith: in the project root |
| 19:04 | justin_smith | yeah, something in there is trying to create something to write output to (a file? a network connection?) and is getting nil |
| 19:04 | justin_smith | matthiasn: can you share your project.clj? |
| 19:05 | matthiasn | sure: https://github.com/matthiasn/BirdWatch/blob/master/Clojure-Websockets/project.clj |
| 19:05 | justin_smith | matthiasn: in the ubuntu computer, is there a target/ directory? git won't create it if it doesn't have any checked in files inside it |
| 19:06 | matthiasn | Oh I have an idea, let me check |
| 19:07 | justin_smith | also, "target/%s" may need to be "target/%s/" - at least that is how it is done in the example project.clj |
| 19:08 | matthiasn | found it :-) |
| 19:08 | justin_smith | what was it? |
| 19:09 | matthiasn | so there was a new key in twitterclient.edn for the name of the PID file to write |
| 19:09 | matthiasn | and I did not add that key in the edn file on the server |
| 19:10 | matthiasn | that was the right pointer with the program trying to write something :-) thanks a lot |
| 19:18 | phao | Hi. I'm curious. Does Clojure have something like CL's loop facility? |
| 19:18 | phao | And... Does Rich Hickey come in here? Hehe |
| 19:18 | justin_smith | phao: not really, there are for and doseq, but we don't use DSLs as much as CL does |
| 19:18 | phao | justin_smith, Ok. Thanks =). |
| 19:18 | matthiasn_ | hmm, got kicked out of my network for the last three minutes or so |
| 19:18 | matthiasn_ | thanks for the help, much appreciated |
| 19:18 | noonian | what does cl loop macro give you that for doesn't? i'm not trying to be argumentative i just don't have any cl experience |
| 19:18 | justin_smith | phao: actually some uses of "loop" would even be covered by our own loop, or reduce (in combination with reduced for short circuiting), or iterate as well |
| 19:18 | justin_smith | noonian: it is an embedded language for describing recursion |
| 19:18 | justin_smith | (loop for item in list for i from 1 to 10 do (something)) |
| 19:18 | technomancy | CL LOOP can do basically anything |
| 19:18 | phao | noonian, I do have experience in CL, but not much. It could be just likely that you know more about it than I do. |
| 19:18 | justin_smith | (loop for i from 20 downto 10 ...) |
| 19:18 | technomancy | in clojure you would express it as a series of sequence operations, but in CL you just mush it into a single macro |
| 19:18 | phao | I was just curious because my belief is the same as technomancy's. |
| 19:18 | justin_smith | (loop for k being the hash-keys in h using (hash-value v) ...) |
| 19:18 | justin_smith | it's almost like cobol |
| 19:19 | phao | technomancy, any clues on why loop-ish macros aren't in clojure? |
| 19:19 | technomancy | even among CL fans loop is pretty controversial because it tries to be english-like instead of being lispy |
| 19:19 | technomancy | phao: you mean why huge english-like macros in general aren't in wide use? |
| 19:19 | phao | technomancy, that as well =) |
| 19:19 | justin_smith | right, it is a COBOL like language for describing loops, that just happens to sit in a lisp file |
| 19:19 | phao | justin_smith, hehehehe |
| 19:20 | technomancy | I would have thought that'd be self-evident. trying to be english-like pretty much always results in weird unpredictable idiosyncracies because english is a crazy language. |
| 19:20 | phao | technomancy, I didn't know loop also had these issues |
| 19:20 | justin_smith | but in all seriousness, the clojure design goals are to make small composible things that combine powerfully, rather than monolithic standalone features |
| 19:20 | phao | I thought it kept itself to simple syntactical constructions. |
| 19:21 | technomancy | loop is basically its own language... we already have a language that we like for describing sequences; adding another one doesn't make sense |
| 19:21 | phao | justin_smith, Right. CL seems, to me, to approach the other end of that. |
| 19:21 | technomancy | I'm sure someone has ported it as an exercise though |
| 19:21 | noonian | (loop for i from 1 to 3 sum (* i i)) would be (reduce + (range 1 4)) in clojure |
| 19:21 | justin_smith | phao: https://www.refheap.com/90332 this is a valid usage of the loop macro |
| 19:22 | justin_smith | from this page http://www.gigamonkeys.com/book/loop-for-black-belts.html |
| 19:22 | phao | hahahahaha |
| 19:22 | phao | it looks like those algorithms book pseudo-code |
| 19:22 | justin_smith | not quite as verbose as COBOL, and not in all caps, but the same "we want to program in english" concept |
| 19:22 | noonian | most of the examples from here look like they would read better in clojure imo |
| 19:22 | noonian | http://www.unixuser.org/~euske/doc/cl/loop.html |
| 19:23 | noonian | cl loop macro for beginners |
| 19:24 | phao | justin_smith, stuff like this breaks my foundations on believing that there is a logic which controls it all. |
| 19:24 | arrdem | so um... what does this macro _not_ do |
| 19:24 | justin_smith | "it all"? |
| 19:24 | justin_smith | arrdem: solve the halting problem? dunno, maybe it does that too |
| 19:24 | phao | justin_smith, In this case, what is acceptable or not by the loop, and what it does, and how the macro decides what to do, and many other aspects. |
| 19:25 | arrdem | justin_smith: if it does I'm handing in my badge |
| 19:25 | justin_smith | arrdem: I am still laughing at the example I pasted in the refheap link above |
| 19:25 | arrdem | justin_smith: I missed it. repost? |
| 19:25 | justin_smith | arrdem: https://www.refheap.com/90332 this is a valid usage of the loop macro |
| 19:25 | phao | justin_smith, Oh! THe 'and' tokens combine stuff together. |
| 19:25 | phao | Now things are starting to make sense. |
| 19:26 | technomancy | it would make a lot more sense if it just used parens like regular lisp |
| 19:26 | arrdem | justin_smith: we're a lisp. fuckit. lets embed some bash. |
| 19:26 | arrdem | ^ what technomancy said |
| 19:26 | phao | technomancy, I couldn't agree more =) |
| 19:26 | justin_smith | arrdem: hell, I still maintain it's closest living relative is COBOL |
| 19:26 | phao | technomancy, but maybe it's just a learning curve kind of thing, as in once you learn it, you maybe can be productive with it. |
| 19:26 | arrdem | justin_smith: "living"... |
| 19:27 | technomancy | clojure.core/for is the closest thing to a mini-language in that it supports :when and :let, but they're just a different syntax for things you already know |
| 19:28 | justin_smith | phao: but we can't easily compose new functionality by combining it with other tools |
| 19:28 | phao | justin_smith, I see. |
| 19:28 | arrdem | I guess my issue with this is while it's a legitimate macro it's almost entirely divorced from the syntactic style of the host language.. |
| 19:28 | noonian | yeah, i had no idea for supported :when and :let for months and was doing it all in the body or filtering outside |
| 19:29 | arrdem | which aggravates what justin_smith is saying that it doesn't trivially or obviously compose |
| 19:29 | phao | justin_smith, CL has the notion of a sequence type too, if I'm not mistaken, can't the loop macro work with any sequence? |
| 19:30 | noonian | it just seems like its trying to do too much all so you can do it in a single form |
| 19:30 | justin_smith | phao: in one of the examples I quoted above, it was iterating on the keys / values of a hashtable |
| 19:32 | amalloy | oh boy, is it time to talk about LOOP again? |
| 19:32 | arrdem | no thanks |
| 19:32 | justin_smith | ~loop |
| 19:32 | clojurebot | I don't understand. |
| 19:32 | justin_smith | ~cl-loop |
| 19:32 | clojurebot | No entiendo |
| 19:32 | phao | hehehe |
| 19:32 | justin_smith | clearly, we need to rectify this situation |
| 19:33 | phao | justin_smith, put that link as the output for ~loop |
| 19:33 | justin_smith | clojurebot: loop |is| https://www.refheap.com/90332 |
| 19:33 | clojurebot | In Ordnung |
| 19:34 | phao | hehehehe |
| 19:34 | rweir | is that really truly valid CL? |
| 19:35 | justin_smith | rweir: yeah |
| 19:36 | justin_smith | here is the formal description, which may be even more daunting http://www.lispworks.com/documentation/HyperSpec/Body/m_loop.htm |
| 19:44 | clop2 | hi, new to clojure (from common lisp), going to port an app to get some experience; wondering, does clojure have any syntax mechanism for structure sharing input in its reader, like #1=... style reader macros in lisp? |
| 19:46 | amalloy | clop2: no. it's kinda hard to have such things anyway, in a language that is immutable and strict/eager |
| 19:46 | SegFaultAX | clop2: Clojure doesn't have reader macros, no. |
| 19:47 | clop2 | ok thanks, so i guess i need to write a parser, that'll be a good project too |
| 19:47 | amalloy | SegFaultAX: he's not asking about user-supplied reader macros, but about one specific one that the CL reader has. clojure certainly has many prepackaged reader macros, like #{...} |
| 19:47 | SegFaultAX | amalloy: Do I need to specify "user-defined" there? I assume the "except for what Clojure does internally" is implied. |
| 19:49 | amalloy | SegFaultAX: if i include the "implied" part, then you haven't even attempted to answer the question. "clojure doesn't have user-supplied reader macros" is not an answer to "is there a #1= macro built in" |
| 19:49 | TEttinger | what does #1= do? |
| 19:50 | amalloy | TEttinger: it's for printing circular references |
| 19:50 | amalloy | (and then reading them back in as still-circular) |
| 19:50 | TimMc | I think that's called sharp-notation in some JSON supersets. |
| 19:50 | clop2 | right, or for simply sharing common subexpressions (that don't happen to be circular) |
| 19:50 | amalloy | more genrally, i guess, it's for capturing shared structure, of which circular references are a special case |
| 19:51 | TEttinger | you can change the behavior of fns like pr and prn pretty easily, though I don't know how you'd detect shared structure |
| 19:52 | justin_smith | TEttinger: but could you read in a way that made prn actually do the right thing? |
| 19:52 | amalloy | clop2: does CL really use that for non-circular lists? like, if i write (let ((x (cons 1 2))) (list x x)), i don't get a #1= notation |
| 19:52 | TEttinger | justin_smith, with read-eval, yes |
| 19:53 | justin_smith | ahh, of course, read-eval |
| 19:53 | clop2 | amalloy: cl can be instructed to print with structure sharing if you bind *print-circle* to t, or custom printers can print it out in other cases |
| 19:53 | TEttinger | ,(print "#=(+ 1 1 1)") |
| 19:53 | clojurebot | #=(+ 1 1 1) |
| 19:53 | clop2 | amalloy: typically it will only create #= abbreviations for circular objects, I think, but I'm not an expert |
| 19:54 | amalloy | actually even if i write (let ((x (cons 1 2))) (setf (cdr x) x) x) i don't get that pretty notation out of clisp; the interpreter just hangs |
| 19:54 | clop2 | amalloy: but for reading back in, you can do, e.g., (+ #1=5 4 #1#) or similar |
| 19:54 | amalloy | but i can't figure out how to set print-circle |
| 19:54 | amalloy | anyway, not really important |
| 19:56 | clop2 | this should do it: (let ((*print-circle* t) (x (cons 1 2))) (setf (cdr x) x) (print x) nil) |
| 19:56 | TEttinger | hm, I can't remember if clojurebot allows read-eval |
| 20:11 | amalloy | so guys, i found a funny trick in my old 4clojure solutions. suppose you have 3 objects named x, y, and z, and you want to compute (f x) + (f y) - (f z), but you don't like repeating f. you'd rather use (map f [x y z]) or something like it, and then do the math on the resulting list |
| 20:11 | amalloy | here is the solution i used, way back then: (- (apply - (map f [z x y]))) |
| 20:16 | justin_smith | hah, nice |
| 20:16 | amalloy | for those following along at home, that converts the problem to -(f(z) - f(x) - f(y)) |
| 20:16 | amalloy | - has the funny property that the first item is given a different sign than the rest |
| 20:21 | TEttinger | ,(apply - [10 22 55]) |
| 20:21 | clojurebot | -67 |
| 20:21 | TEttinger | huh |
| 20:22 | justin_smith | ,(reduce - [10 22 55]) |
| 20:22 | clojurebot | -67 |
| 20:22 | TEttinger | ,(reduce - 0 [10 22 55]) |
| 20:22 | clojurebot | -87 |
| 20:22 | TEttinger | neat trick, amalloy |
| 20:22 | TEttinger | (inc amalloy) |
| 20:23 | TEttinger | lazybot is ded |
| 20:23 | amalloy | he's been having a rough time recently for some reason |
| 20:23 | arrdem | the bot is dead long live the bot |
| 20:26 | dbasch | here's a (stupid) gotcha. What do you expect t and second t to be? https://www.refheap.com/90336 |
| 20:27 | justin_smith | well, locking 128 won't work |
| 20:27 | justin_smith | or won't really do what you expect at least |
| 20:28 | amalloy | yeah, don't lock integers. what kind of wacko thinks he deserves an exclusive lock on a mathematic ideal? |
| 20:28 | dbasch | amalloy: you can happily lock 127 or -128 though |
| 20:28 | justin_smith | well, at least for 127 you have a single instance |
| 20:28 | dbasch | or anything in between |
| 20:28 | amalloy | dbasch: sure, you get lucky with an implementation detail |
| 20:29 | amalloy | i doubt the interning of Long objects between -128 and 127 is part of the jvm spec |
| 20:29 | amalloy | (or the jls) |
| 20:30 | dbasch | amalloy: in fact, the doc for the oracle jvm says they "may cache values outside this range" |
| 20:30 | clop2 | does clojure have any haskell/ml-like way to define simple types like, maybe-number ::= number | nil ? |
| 20:30 | amalloy | clop2: no, we don't have ADTs |
| 20:30 | Guest26510 | ,(reduce - |
| 20:30 | clojurebot | #<RuntimeException java.lang.RuntimeException: EOF while reading> |
| 20:31 | Guest26510 | err |
| 20:31 | dbasch | (locking 4 (println "http://www.imdb.com/title/tt1464540/")) |
| 20:31 | johnnycage | ,(reduce - '()) |
| 20:31 | clojurebot | #<ArityException clojure.lang.ArityException: Wrong number of args (0) passed to: core/-> |
| 20:31 | johnnycage | can I supply a starting value for the accumulator? |
| 20:31 | amalloy | ,(doc reduce) |
| 20:31 | clojurebot | "([f coll] [f val coll]); f should be a function of 2 arguments. If val is not supplied, returns the result of applying f to the first 2 items in coll, then applying f to that result and the 3rd item, etc. If coll contains no items, f must accept no arguments as well, and reduce returns the result of calling f with no arguments. If coll has only 1 item, it is returned and f is not called. If val i... |
| 20:32 | TEttinger | johnnycage, yes, ##(reduce + 10 [1 2 3]) |
| 20:32 | lazybot | ⇒ 16 |
| 20:33 | TEttinger | (inc amalloy) |
| 20:33 | lazybot | ⇒ 167 |
| 20:33 | johnnycage | is that the same function? it uses optional argument, or? |
| 20:33 | johnnycage | overloaded function? |
| 20:33 | TEttinger | starting values for reduce are very very useful for reduce on strings |
| 20:34 | TEttinger | see in the docstring amalloy called up, ([f coll] [f val coll]) ? |
| 20:34 | johnnycage | yes |
| 20:34 | TEttinger | that means it can take [f coll] as two args, or [f val coll] as 3 args |
| 20:34 | TEttinger | val is the starting value |
| 20:34 | johnnycage | I realize this. I am just curious how is something like implemented |
| 20:34 | johnnycage | +that |
| 20:34 | dbasch | ,(reduce str "can " ["I " "supply " "a " "value?"]) |
| 20:34 | clojurebot | "can I supply a value?" |
| 20:35 | TEttinger | ,(defn multi ([] "you gotta give me some args!") ([f coll]) (reduce f coll)) |
| 20:35 | clojurebot | #<CompilerException java.lang.IllegalArgumentException: Parameter declaration "reduce" should be a vector, compiling:(NO_SOURCE_FILE:0:0)> |
| 20:35 | TEttinger | ,(defn multi ([] "you gotta give me some args!") ([f coll] (reduce f coll))) |
| 20:35 | clojurebot | #'sandbox/multi |
| 20:35 | TEttinger | ,(multi) |
| 20:35 | clojurebot | "you gotta give me some args!" |
| 20:36 | TEttinger | ,(multi + [1 2 3]) |
| 20:36 | clojurebot | 6 |
| 20:36 | justin_smith | dbasch: why not apply str? |
| 20:36 | johnnycage | neat |
| 20:37 | dbasch | ,(apply str "they " ["were " "taking " "about " "reduce."]) ; justin_smith |
| 20:37 | clojurebot | "they were taking about reduce." |
| 20:37 | amalloy | yeah, i don't recommend ever using str as the function you're reducing |
| 20:37 | dbasch | talking that is |
| 20:37 | justin_smith | we have apply str, string/join, even reduce on StringBuilder if you have to go that way |
| 20:37 | amalloy | it should always be apply (or, better yet, something more suitable like clojure.string/join) |
| 20:38 | dbasch | yes, you don't want to be concatenating strings like crazy |
| 20:38 | TEttinger | johnnycage, that multiple argument list technique is used heavily by clojure's standard lib, but it hasn't come up too often for me in code I have written. still quite useful. |
| 20:38 | amalloy | justin_smith: not much point in reducing over a stringbuilder |
| 20:38 | amalloy | might as well hammer on it in place with doseq |
| 20:38 | justin_smith | fair enough |
| 20:42 | justin_smith | and now that I check, yup, of course clojure.string/join is a loop with a StringBuilder in it |
| 20:44 | johnnycage | what is apply's relationship with reduce? can we just replace one with the other, always? |
| 20:44 | dbasch | johnnycage: no |
| 20:44 | johnnycage | tey seem to be interchangeable in many cases |
| 20:44 | johnnycage | they |
| 20:44 | justin_smith | johnnycage: well, many functions with varargs are implemented in terms of a two arg function + reduce, so apply invokes reduce internally |
| 20:44 | dbasch | johnnycage: apply simply converts a collection (or arguments plus a collection) into arguments |
| 20:45 | justin_smith | (in those cases, that is) |
| 20:45 | johnnycage | oh, apply just passes all the elements to the function |
| 20:45 | justin_smith | right |
| 20:46 | justin_smith | and if you look at the source to + for example, it uses the internal clojure.lang.Numbers.add which takes two args, and then uses reduce for the rest of the args |
| 20:46 | justin_smith | (reduce1 which is an optimized reduce in this case, but anyway...) |
| 20:47 | amalloy | i wonder: why is it called reduce1? it reminds me of foldl1 or something, which isn't right at all |
| 20:49 | justin_smith | odd, especially given that reduce* was not taken |
| 20:50 | justin_smith | and that would kind of make sense given things like fn* and let* |
| 20:51 | dbasch | amalloy: because it was June 11, so 1 was the digit of the day. https://github.com/clojure/clojure/commit/3f74c9ff6e9bf8e5e120129ea1c1c7e4719b4dcc |
| 20:52 | justin_smith | (inc dbasch) |
| 20:52 | lazybot | ⇒ 10 |
| 20:53 | amalloy | hey, who was it who was telling me that it's easy to forgot where the return-type annotation goes? Bronsa? i just found evidence that rich forgets too: https://github.com/clojure/clojure/commit/e354b011 puts them in both places, like (defn ^Foo f ^Foo [x]) |
| 20:53 | amalloy | (the second Foo there is entirely ignored afaik) |
| 20:53 | justin_smith | yeah, I think dbasch was asking why the misplacement was not an error |
| 20:54 | justin_smith | it would logically indicate metadata on the params vactor, but how would you even access that... |
| 20:54 | dbasch | I think I disassembled both versions and saw no difference |
| 20:54 | amalloy | justin_smith: well, it's the correct place to put a primitive typehint |
| 20:54 | justin_smith | oh wow, OK |
| 20:54 | amalloy | but means nothing if you hint with an object type |
| 20:55 | amalloy | (defn square ^long [^long x] (* x x)) avoids boxing |
| 20:56 | dbasch | the one I found had ^String |
| 20:56 | amalloy | right, those are wrong |
| 21:03 | johnnycage | is there a reduce equivalent that returns a list of all the intermediate results (the value of the accumulator) instead of just the final result? |
| 21:03 | justin_smith | reductions |
| 21:03 | amalloy | ,(doc reductiosn) |
| 21:03 | clojurebot | No entiendo |
| 21:03 | amalloy | boo |
| 21:03 | justin_smith | you misspelled it |
| 21:03 | amalloy | yeah |
| 21:03 | justin_smith | ,(doc reductions) |
| 21:03 | clojurebot | "([f coll] [f init coll]); Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init." |
| 21:04 | johnnycage | nice thanks |
| 21:04 | amalloy | incidentally, has anyone ever used the first item in the value returned by reductions? i feel like i only ever call it as (rest (reductions ...)) |
| 21:06 | amalloy | well, never mind. i just searched all the code i have on the computer, and the one time i used it i didn't call rest |
| 21:15 | justin_smith | amalloy: one of mine was without using rest, the other only had reductions as a comment, and was an excersize blind-rewriting it from scratch |
| 21:21 | joobus | what's crackin' clojure clan? |
| 21:25 | justin_smith | workin on some 4clojure problems |
| 21:25 | amalloy | justin_smith: you are worse at spelling exercise than i am at spelling privelidge |
| 21:26 | justin_smith | hah |
| 21:27 | joobus | i'm working projecteuler problem 9 in clojure :) |
| 21:28 | joobus | justin_smith: are you writing them or doing them? |
| 21:28 | justin_smith | doing them, after I solve them all I will make some up |
| 21:55 | phao | Does Rich Hickey come in here? |
| 21:55 | xeqi | rarely |
| 22:00 | kenrestivo | bar |
| 22:37 | kenrestivo | ~seen rhickey |
| 22:37 | clojurebot | Gabh mo leithscéal? |
| 22:37 | kenrestivo | ,seen rhickey |
| 22:37 | clojurebot | #<CompilerException java.lang.RuntimeException: Unable to resolve symbol: seen in this context, compiling:(NO_SOURCE_PATH:0:0)> |
| 22:37 | kenrestivo | lazybot: seen rhickey |
| 22:37 | lazybot | rhickey was last seen quitting 65 weeks and 1 day ago. |
| 22:37 | kenrestivo | phao: ^ |
| 22:46 | kyun | How to use clojure file as script? |
| 22:47 | justin_smith | kyun: there is a lein plugin for it, or you can just reference the clojure jar and your script, but clojure tends to be awkward for scripting because the core takes a long time to load |
| 22:47 | brehaut | slowly |
| 22:48 | justin_smith | https://github.com/kumarshantanu/lein-exec lein-exec is probably easiest |
| 22:49 | kyun | Oh, I see, thanks. |
| 22:51 | kyun | I think it will faster to scala script:) |
| 22:51 | TEttinger | kyun, nope |
| 22:51 | TEttinger | jvm startup time is slow either way |
| 22:52 | TEttinger | there's stuff like drip that makes jvm startup time faster for clojure and maybe other languages |
| 22:53 | amalloy | TEttinger: most of the startup time is clojure's fault, not the jvm |
| 22:54 | amalloy | building a bunch of vars, compiling your code, and so on |
| 22:54 | TEttinger | right, but scala's compiler is even slower if you just changed the script :) |
| 22:57 | kyun | Scala's type system is to too hard for me-_- |
| 22:57 | TEttinger | https://github.com/flatland/drip is drip, btw |
| 22:58 | TEttinger | kyun: http://tpolecat.github.io/assets/list.png |
| 22:59 | justin_smith | lol |
| 23:00 | kyun | Oh my god. |
| 23:04 | TEttinger | err, https://github.com/ninjudd/drip is newer |
| 23:12 | izirku | hi all! a noob question perhaps - when different libraries themselves depend on different versions of the same library, what are the implications?... |
| 23:13 | izirku | some even require different version of Clojure itself. Should one be concerned with it? |
| 23:13 | TEttinger | izirku, that is a common problem and a hard one to resolve |
| 23:14 | izirku | TEttinger: I'm aware somewhat of not using :aot :all, which supposed to help, but is there anything else? I tried to search the web with... |
| 23:14 | izirku | not much success on this. Coming from Common Lisp, this is something new to me. |
| 23:14 | TEttinger | which libs have different dependency versions? |
| 23:15 | TEttinger | it |
| 23:16 | TEttinger | it's possible you can fork one that needs an older version, update the version it depends on, upload your personal copy to clojars for now (submitting a pull request to the author for later), and depend on your clojars copy or a locally installed version until they are both up-to-date |
| 23:17 | izirku | TEttinger: for example lib-noir "0.8.9" depends on cheshire 5.3.1, which in turn depends on jackson-core 2.3.1 ... |
| 23:17 | TEttinger | that's probably a bad approach but I have done it |
| 23:18 | izirku | also lib-noir "0.8.9" depends on ring-middleware-format "0.4.0" and some more, which in the end depend on jackson-core "2.3.2" |
| 23:18 | xeqi | izirku: `lein deps :tree` should help you identify potential problems. Implications are the libraries erroring or half working at runtime |
| 23:18 | TEttinger | that's interesting, I wouldn't expect that lib-noir would have that problem |
| 23:19 | izirku | xeqi: that's exactly where I got the dependency information from |
| 23:20 | izirku | xeqi: I see the implications :( |
| 23:21 | TEttinger | hm, https://clojars.org/ring-middleware-format doesn't itself depend on jackson-core 2.3.2 |
| 23:21 | izirku | TEttinger: I guess forking could work, but that's a lot of forks :) |
| 23:23 | izirku | TEttinger: no, not itself, but one of it's dependencies. here is a pastebin of my lein deps :tree http://paste.lisp.org/+32WW |
| 23:25 | xeqi | wow those extra parens are annoying. I thought I had fixed that |
| 23:25 | TEttinger | using the dep on ([lib-noir "0.8.9" :exclusions [com.fasterxml.jackson.core/jackson-core]]) should be good |
| 23:25 | xeqi | izirku: what lein version? |
| 23:26 | izirku | xeqi: Leiningen 2.4.2 on Java 1.8.0_11 Java HotSpot(TM) 64-Bit Server VM |
| 23:26 | xeqi | ah, that fix didn't come till later |
| 23:30 | izirku | xeqi: noted, updating now :) |
| 23:30 | mmitchel_ | I'm having a problem using this library https://github.com/ring-clojure/ring-session-timeout --- it seems that a session logout, followed very quickly by another request (which updates the session value with a timeout) value, causes the session to continue living -- has anyone experienced this? |
| 23:31 | mmitchel_ | The underlying session storage is ring in-memory, which is using an atom |
| 23:32 | izirku | TEttinger: I did put the :exclude in, will work through the rest. Does the exclude basically tells a package to ignore dependency, ... |
| 23:32 | xeqi | mmitchel_: what is a "session logout" ? |
| 23:32 | izirku | TEttinger: and whatever else version is pulled will be used? |
| 23:32 | mmitchel_ | I think the problem is that the delete happens in a swap!, and before it finishes, the timeout middleware gets access to the session data. Then the delete tries removes it, but then the timeout middleware finishes its work and re-populates the session data. |
| 23:32 | mmitchel_ | xeqi: a request handler that responds with a {:status 200 :session nil} |
| 23:34 | xeqi | izirku: correct |
| 23:35 | izirku | xeqi, TEttinger: thank you for your help, much appreciated! |
| 23:39 | xeqi | mmitchel_: are the requests overlapping? |
| 23:41 | mmitchel_ | xeqi: yes they are |
| 23:44 | xeqi | mmitchel_: then I don't think it has to do with atoms/swap. More that both request get the session from the session store. Then whichever writes last "wins" |
| 23:45 | xeqi | similar ideas, just at a level higher then the underlying session store |
| 23:45 | mmitchel_ | xeqi: yeah, i'm not sure what to do here |
| 23:49 | mmitchel_ | xeqi: any suggestions? |
| 23:50 | xeqi | mmitchel_: what do you expect to happen to the side effecting parts of the second request? |
| 23:50 | xeqi | * want to have happen |
| 23:53 | xeqi | for example, overlapping "logout" and "delete project" requests |
| 23:54 | mmitchel_ | xeqi: yeah, good question. I guess I'm hoping "delete" wins -- somewhow |
| 23:55 | mmitchel_ | but i guess that can only happen if the delete start, only happens when something else hasn't already got to it |
| 23:56 | mmitchel_ | so a blocking delete etc.. |