2015-09-11
| 00:00 | justin_smith | nowprovision: why not nth? |
| 00:01 | nowprovision | justin_smith, that seems better, im very rusty.. tahnks |
| 00:01 | justin_smith | nowprovision: it might read better if you bind the (iterate ...) in the let block, then use nth on that |
| 00:10 | nowprovision | okay now I have https://www.refheap.com/20d51c2bb7ea776d05824a862 any further thoughts |
| 00:14 | ska-fan | So (:a {:a 4}) is 4, but ("a" {"a" 4)) throws an exception - does key as a function just doesn't work for strings? |
| 00:15 | TEttinger | ska-fan: ah this is neat |
| 00:15 | TEttinger | so keywords like :a actually do more than just store text conveniently |
| 00:15 | tolstoy | But ({"a" 4} "a") is 4. |
| 00:16 | ska-fan | tolstoy: Ha! indeed. /me goes of simplifying. |
| 00:16 | nowprovision | a keyword is a function |
| 00:16 | justin_smith | ska-fan: clojure always calls the first thing after the paren |
| 00:16 | TEttinger | a keyword also implements IFn (meaning, it can be called as a function), but they are fns that can be called with a map as an arg (possibly other stuff too) |
| 00:16 | justin_smith | ska-fan: it just so happens that keywords are callable |
| 00:16 | justin_smith | ,(:a :a :a) |
| 00:17 | TEttinger | maps also implement IFn and can be called with a key |
| 00:17 | clojurebot | :a |
| 00:17 | TEttinger | wha |
| 00:17 | TEttinger | ,(:a :a) |
| 00:17 | clojurebot | nil |
| 00:17 | TEttinger | ha! |
| 00:17 | TEttinger | it's a get |
| 00:17 | TEttinger | ,(:a :a :b) |
| 00:17 | clojurebot | :b |
| 00:17 | justin_smith | TEttinger: demonstrating that :a is callable, and it isn't something being done by the map |
| 00:17 | TEttinger | ,({:a 5} :a) |
| 00:17 | clojurebot | 5 |
| 00:18 | TEttinger | ,({"a" 5} "a") |
| 00:18 | clojurebot | 5 |
| 00:18 | TEttinger | maps are fns too, but like justin_smith is saying, the first thing after the '(' is what gets called |
| 00:18 | tolstoy | ,({2 4} 2) |
| 00:18 | clojurebot | 4 |
| 00:18 | TEttinger | threeve_: is that nick a celebrity jeopardy reference? |
| 00:26 | devtrope | ,(supers (class :a)) |
| 00:26 | clojurebot | #{java.util.concurrent.Callable clojure.lang.IFn java.lang.Runnable java.lang.Comparable java.io.Serializable ...} |
| 00:29 | TEttinger | ,(clojure.string/join " " (supers (class :a))) |
| 00:29 | clojurebot | "interface clojure.lang.IHashEq interface java.util.concurrent.Callable interface clojure.lang.IFn interface java.lang.Runnable interface java.lang.Comparable interface java.io.Serializable interface clojure.lang.Named class java.lang.Object" |
| 03:13 | deiodeiodeio | I want to be able to run my tests in parallel (selectively). Currently, I'm using midje, and my naive approach of wrapping parallelizable sections of my test code in futures seems to break it. What's a good way of doing this? |
| 03:15 | ordnungswidrig | deiodeiodeio: that's actually a good question. But why want you to run tests in parallel? |
| 03:16 | deiodeiodeio | I'm doing integration tests involving spinning up and taking down a lot of services |
| 03:17 | deiodeiodeio | naturally, this takes a while |
| 03:17 | ordnungswidrig | deiodeiodeio: I see. In which way do futures break it? |
| 03:17 | ordnungswidrig | deiodeiodeio: I'm assuming there are no race conditions or the tests influencing easch other |
| 03:21 | deiodeiodeio | ordnungswidrig: it doesn't seem to be my code, no.. |
| 03:22 | ordnungswidrig | can you distill an example? just how you use midje and futures? |
| 03:22 | deiodeiodeio | yeah, sorry, I'm working on it |
| 03:29 | deiodeiodeio | ordnungswidrig: basically, I did something along the lines of (facts (future (fact 1 => 0)) (future (fact 1=> 0) ...)), and got a bunch of Exception in thread "main" java.lang.AbstractMethodError: clojure.core$promise$reify__6363.invoke()Ljava/lang/Object |
| 03:30 | ordnungswidrig | deiodeiodeio: oh weird |
| 03:30 | deiodeiodeio | ordnungswidrig: yeah. but I'm now not entirely convinced it's midje's fault. if it is, it seems to be flaky |
| 03:30 | deiodeiodeio | so I guess I'll have to investigate it a bit closer |
| 03:30 | ordnungswidrig | deiodeiodeio: I would macroexpand the (facts) expression |
| 06:30 | namra | j/quit |
| 07:30 | deiodeiodeio | what's a good, simple way of doing concurrent printing without using core.async or a logging library? |
| 07:30 | deiodeiodeio | (i.e. without multiple lines printing concurrently) |
| 07:40 | mnngfltg | deiodeiodeio, using an agent perhaps? |
| 07:40 | luma | yep, create an agent and then send each printing to it |
| 09:19 | galaux | I can't find some kind of "fail" method for Clojure unit tests … |
| 09:19 | galaux | Does it exist somewhere? |
| 09:21 | snowell | Wouldn't you generally want to assert the opposite of what's happening? |
| 09:21 | galaux | well: nothing is happening, that's the idea |
| 09:21 | snowell | What are you testing for? |
| 09:21 | galaux | I'm testing for a particular function NOT to be called |
| 09:22 | galaux | This is a function I pass to some other function … I want to check it has not be called |
| 09:22 | galaux | So I thought I would just make this second method something like `(fail "Error") |
| 09:23 | snowell | I mean…you could always assert false ;) |
| 09:23 | galaux | yes … |
| 09:23 | snowell | Sorry that's not a whole lot of help |
| 09:24 | galaux | no but still it would work … even though a "fail" method would have been perfect (especially for handling a test failing messge) |
| 09:24 | galaux | snowell: thanks |
| 09:25 | snowell | I've not done much unit testing in clojure. When I have, it was with https://github.com/marick/Midje |
| 09:26 | dstockton | galaux: assert can take an option message |
| 09:26 | dstockton | (defn fail [message] (assert false message)) |
| 09:28 | dstockton | or you could throw an exception |
| 09:29 | galaux | An exception is not a failing test |
| 09:29 | galaux | I don't want to crash it, just flag it as failed |
| 09:29 | galaux | but it would work in some way |
| 09:32 | galaux | I am going to go for `(is (true? false) "Something went wrong")` |
| 09:32 | galaux | snowell: thanks for the link,looks nice ! |
| 09:33 | snowell | With both Midje and clojure.test, you can assert that exceptions are thrown/not thrown |
| 09:34 | snowell | So if you pass in a function that just throws an Exception, you can assert that said Exception isn't thrown |
| 09:34 | snowell | Without crashing the test execution |
| 10:13 | justin_smith | e |
| 10:21 | justin_smith | ,0xDEADBEEFCAFEBADD |
| 10:21 | clojurebot | 16045690984503098077N |
| 10:21 | justin_smith | I hear that number is prime |
| 10:26 | gfredericks | ,(.isProbablePrime (biginteger 0xDEADBEEFCAFEBADD) 100) |
| 10:26 | clojurebot | true |
| 10:33 | troydm | which function should I use for lenghth of string in Clojure? .length or count? |
| 10:41 | justin_smith | well only one of those is a function |
| 10:41 | justin_smith | use count |
| 12:52 | mdeboard | Ok so in cider, I'm running this long-running async process in a goroutine. How the heck do I kill it? |
| 12:59 | justin_smith | mdeboard: write it such that it checks some condition you have control over, and it exits gracefully |
| 12:59 | justin_smith | or kill your vm |
| 13:00 | mdeboard | ok, that's what I figured (the last) |
| 13:00 | justin_smith | mdeboard: is it reading from some channel? closing the channel would help in that case |
| 13:00 | justin_smith | (I was being slightly glib) |
| 13:00 | mdeboard | Yeah I just added some logic to close |
| 13:05 | mdeboard | I assume the value of `(<! ch)` if there are no messages on the channel is `nil`, is that right? |
| 13:08 | justin_smith | no |
| 13:08 | justin_smith | it doesn't return to your process |
| 13:08 | justin_smith | nil is if the channel is closed |
| 13:09 | justin_smith | (which is why I mention that closing a channel could communicate to a go block that it should exit) |
| 13:09 | justin_smith | mdeboard: forgot to highlight you in my reply ^ |
| 13:10 | mdeboard | I see |
| 13:10 | mdeboard | Hmm |
| 13:10 | mdeboard | Because I want to flush my buffered writer if there's nothing on the channel |
| 13:10 | mdeboard | so I don't have half a message in the log |
| 13:10 | mdeboard | just chilling, waiting for more data |
| 13:11 | justin_smith | mdeboard: check out alts! |
| 13:11 | justin_smith | then you can have a timeout, and flush if the timeout is hit |
| 13:11 | mdeboard | Cool |
| 13:11 | mdeboard | Very nice |
| 13:12 | justin_smith | like (alts! [ch (timeout 10000)]) either gets data from ch, or from the timeout after 10 seconds |
| 13:12 | justin_smith | and in the return value you can test which you got |
| 13:13 | mdeboard | Frustrated with Clojure's documentation atm. |
| 13:13 | mdeboard | As I have been since 2010 or something. |
| 13:13 | justin_smith | mdeboard: this is what makes our lovely community so valuable :) |
| 13:14 | justin_smith | mdeboard: the official core.async api is a bit disorganized maybe, but it is comprehensive https://clojure.github.io/core.async/#clojure.core.async/alts! |
| 13:14 | justin_smith | official core.async api docs, that is |
| 13:17 | mdeboard | yeah that's what I'm frustrated with :P |
| 13:17 | mdeboard | It's definitely exhaustive |
| 13:17 | mdeboard | Not sure how useful it actually is, but it's exhaustive |
| 13:18 | mdeboard | justin_smith, So where can I find a full example of this alts functionality |
| 13:18 | justin_smith | mdeboard: I think my skill as a developer has been helped quite a bit by my extensive experience reading postmodern literature - fragmented, odd points of view, strange aporias ... |
| 13:18 | justin_smith | mdeboard: hmm, maybe conj.io, checking |
| 13:19 | mdeboard | Is that another stab at community-curated docs? |
| 13:19 | mdeboard | Ah this is uh |
| 13:19 | justin_smith | mdeboard: if not i'll share a quick repl demo of it |
| 13:19 | mdeboard | Oh the guy lives here in Austin |
| 13:19 | mdeboard | Can't remember his name, but this is his thing |
| 13:19 | justin_smith | mdeboard: arrdem |
| 13:19 | mdeboard | arrdem, yeah |
| 13:19 | justin_smith | I thought he had core.async on here but I can't find it |
| 13:20 | mdeboard | Here's my function https://gist.github.com/mattdeboard/ecd0d033d1977bf6da78 |
| 13:21 | mdeboard | I think the alts! call would go on like line 7 (and I'd need to refactor a little to remove the arg to recur |
| 13:21 | mdeboard | ) |
| 13:23 | justin_smith | mdeboard: working demo of alts! from the repl https://www.refheap.com/109440 |
| 13:23 | justin_smith | mdeboard: you can test via the second item in that returned vector which channel the value came from |
| 13:23 | justin_smith | mdeboard: paste updated to show this fact https://www.refheap.com/109440 |
| 13:25 | justin_smith | mdeboard: yeah, I would put the alts on line 7, and if the channel the value comes from does not = ch, then flush, otherwise use the value |
| 13:26 | justin_smith | mdeboard: using my own repl example of alts as a basis for that should be easy enough |
| 13:34 | mdeboard | Nice, thanks |
| 13:35 | mungojelly | why do i need to say var# to get unclobbered variables in macros, do y'all also use macros to intentionally clobber variables? |
| 13:42 | sdegutis | Is there a simpler way of mapping characters in a string to their line/char position than this? https://gist.github.com/sdegutis/ff476b6efef23e7a5a1d |
| 13:42 | sdegutis | This function seems overly complex. |
| 13:42 | mdeboard | justin_smith, Sorry if I'm being a huge dunce but the alts! syntax doesn't make sense to me. it takes an array of "ports", and does what? |
| 13:43 | mdeboard | It says it "does at most one of several channel operations" |
| 13:43 | mdeboard | What operations is it talking about? |
| 13:43 | snowell | mdeboard: It accepts any number of channels and performs a take on whichever one of them *first* returns a value |
| 13:43 | mdeboard | Oh |
| 13:43 | mdeboard | What the hell? |
| 13:44 | mdeboard | wth @ the docs |
| 13:44 | arrdem | mdeboard: o/ |
| 13:44 | mdeboard | that's 100% impenetrable |
| 13:44 | arrdem | are we on about docs again |
| 13:44 | mdeboard | and also just seems inconsistent with actual functionality? |
| 13:44 | mdeboard | arrdem, lol |
| 13:44 | mdeboard | I don't want to get you in any legal trouble |
| 13:45 | mdeboard | or something (recalling some blog post about something like that) |
| 13:45 | snowell | I do. I'd love an excuse to go back to Austin ;) |
| 13:45 | mdeboard | "Completes at most one of several channel operations." <-- actually means "Performs a take on at most one of several channels"? |
| 13:46 | mdeboard | Ok now that I understand alts! because of the explanation in IRC, the docs make sense. That's not how docs are supposed to work. |
| 13:47 | arrdem | welcome to Clojure |
| 13:48 | mgaare_ | mdeboard: actually that's not what it means. because you can also do a put inside of alts! |
| 13:48 | mdeboard | Yeah was just saying this has been constant source of irritation for like 5 years |
| 13:48 | mdeboard | mgaare_, Yeah I see that now |
| 13:48 | mdeboard | I'm tempted to do a PR to improve that docstring |
| 13:48 | snowell | Sorry…I knew there was a chance I only partially understood it :/ |
| 13:49 | mdeboard | but by "several" it just means "two" right? Either put or take? |
| 13:49 | mgaare_ | that's why it says channel operations. |
| 13:50 | snowell | "several" refers to its args |
| 13:50 | mdeboard | wat |
| 13:50 | clojurebot | Titim gan éirí ort. |
| 13:51 | snowell | You pass in several operations, it will perform at most one of them |
| 13:51 | mdeboard | Ok, maybe I am misunderstanding the word operation. |
| 13:53 | mgaare_ | operation in this context is the combination of action + channel. So "put on channel x" is an operation, "take from channel y" is an operation, and you can have an arbitrary number of these in what you pass to alts! |
| 13:54 | seancorfield | clojars.org seems to be struggling... very very slow to respond / occasional 500 server error messages |
| 13:54 | mdeboard | ok so you can do like `(alts! [ch-foo [ch-bar 1] ch-baz [ch-qux 2]])` ? |
| 13:55 | mgaare_ | mdeboard: that's right |
| 13:55 | mdeboard | Ok. Thanks for the clarification |
| 13:55 | mdeboard | Does it just iterate left-to-right looking for the first valid operation? |
| 13:56 | mdeboard | and a put is invalid only if the channel is closed? |
| 13:57 | mgaare_ | mdeboard: if you pass :priority true as an opt, then they will be tried in order, otherwise there is no order guarantee. a put will only succeed if the channel is open and not blocked |
| 13:58 | mdeboard | Understood, thank you |
| 13:59 | mungojelly | why the ! does it change something |
| 14:03 | _alejandro | it modifies the channel it reads from / writes to |
| 14:12 | mdeboard | That's just a freaking hard function to explain. Takes more than the dry matter-of-fact tone of docstring. |
| 14:12 | mdeboard | (I'm sitting here trying to write better documentation.) |
| 14:14 | geet | Hi! I'm new to Clojrue, I'd like to start contributing. Where would you suggest I do? |
| 14:15 | mungojelly | hmm so you only get tail-call optimization if you ask for it with "recur"? |
| 14:17 | arrdem | mungojelly: correct |
| 14:18 | mungojelly | ok thanks well that's clear enough anyway. what do you want to contribute to what, geet, i don't understand? |
| 14:19 | arrdem | note that the JVM itself doesn't have TCO yet due to reliance on stack frame counting for some security stuff |
| 14:22 | geet | Contributing to clojure |
| 14:22 | geet | mungojelly: |
| 14:23 | mungojelly | personally what i think it needs is more toys |
| 14:24 | mungojelly | i'm learning by poking at lists of meaningless numbers, i'm bored, someone hand me a toy |
| 14:25 | mdeboard | Is there any kind of proscription against calling `recur` in a `do` block |
| 14:26 | justin_smith | mdeboard: only that it needs to be in the tail position (that would always be the end of a do block, or the end of a branch in a do block) |
| 14:26 | mdeboard | Alright, cool |
| 14:34 | mdeboard | I think this will do what I am wanting but not entirely sure https://gist.github.com/mattdeboard/ecd0d033d1977bf6da78 |
| 14:34 | mdeboard | It didn't, actually. I wonder if it closed too quick or something. |
| 14:35 | justin_smith | mdeboard: (if (nil? entry) ...) should be (if (nil? (first entry)) ...) |
| 14:35 | justin_smith | mdeboard: remember alts returns a two part vector |
| 14:35 | justin_smith | even better, it could be (if-not (= ch (second entry)) ...) |
| 14:36 | justin_smith | mdeboard: similarly with your other usages of entry I think you want (first entry) to actually get the data, rather than the data/channel pair |
| 14:37 | justin_smith | mdeboard: or, perhaps the easier change is (let [[entry source] (async/alts! ...) ...] ...) and then the rest of the code can stand unchanged |
| 14:37 | mdeboard | Are you sure about the vector thing? |
| 14:37 | mdeboard | https://gist.github.com/mattdeboard/f15ff4454ffd1c570ca2 |
| 14:37 | justin_smith | mdeboard: absolutely sure |
| 14:37 | justin_smith | mdeboard: it's not timeout that returns the vector |
| 14:38 | justin_smith | it is alts! that is returning a vector |
| 14:38 | mdeboard | Oh! |
| 14:38 | mdeboard | Ok. |
| 14:38 | justin_smith | mdeboard: see my example - no matter which data source is acessed, you get a two element vector of the data and the channel it came in on |
| 14:38 | justin_smith | alts! would not be very useful without that feature |
| 14:38 | mdeboard | Why is this so hard for me to grok |
| 14:39 | justin_smith | mdeboard: it's new? |
| 14:47 | mdeboard | Nice, it works |
| 14:47 | mdeboard | Thanks for the help all youse |
| 14:48 | justin_smith | cool |
| 14:50 | mdeboard | Hm maybe not. |
| 14:51 | mdeboard | This is really hard to troubleshoot, the asynchrony. Feel like I'm doing JavaScript |
| 14:52 | mdeboard | Writing javascripts* |
| 14:53 | justin_smith | jabbyscraps |
| 14:54 | justin_smith | yes, core.async can be weird to figure out when misbehaving |
| 16:52 | ben_vulpes | so i'm wiring a figwheel server setup into my clojure projects own reloaded flow, and i've bumped into an issue managing the figwheel server's state |
| 16:52 | ben_vulpes | i new up a figwheel server, stop it, and then bind the result to fig-server |
| 16:53 | ben_vulpes | pass that into the watcher as (fig/autobuild* {... :fig-server fig-server}) |
| 16:53 | ben_vulpes | call (fig/stop-server ...) on the value for the :fig-builder key in my system object |
| 16:54 | ben_vulpes | get a repl print line that claims that the fig-server has been started on :3449 |
| 16:54 | ben_vulpes | but then i simply get websocket errors in the browser, a la 'ws://localhost:3449/figwheel-ws/dev failed' ERR_CONNECTION_REFUSED |
| 16:56 | nooga | I just had the weirdest node.js like experience with clojure |
| 16:56 | ben_vulpes | oh fascinating. it's not even recompiling the cljs. |
| 16:56 | mdeboard | ben_vulpes, Is your project.clj set up right? |
| 16:57 | nooga | timbre was throwing an exception because something inside manifold returned an exception instead of a value I wanted to log |
| 16:57 | mdeboard | Here's a year-old project.clj of mine from a cljs project I was working on that uses figwheel and all that https://github.com/mattdeboard/dots/blob/master/project.clj |
| 16:57 | nooga | and I saw manifold's exception with meaningless timbre call stack |
| 16:58 | nooga | took me a while |
| 16:58 | mdeboard | ben_vulpes, figwheel used to be super, super hard to set up then... something changed that I can't remember |
| 16:59 | mdeboard | maybe I just stopped being dumb |
| 16:59 | nooga | heheh |
| 16:59 | mdeboard | Gosh darnnit I hate that i have to have the source code ordered correctly in order to compile |
| 16:59 | mdeboard | like if function A calls function B, function B has to be physically above function A in the source |
| 17:00 | mdeboard | is that unavoidable? |
| 17:07 | oddcully | ,(doc declare) |
| 17:07 | clojurebot | "([& names]); defs the supplied var names with no bindings, useful for making forward declarations." |
| 17:08 | nathanmarz | Clojurescript question for any of the experts here |
| 17:09 | nathanmarz | Trying to implement IFn protocol for more than 20 arguments, but this isn't working: https://gist.github.com/nathanmarz/e932e11c523fe90b1850 |
| 17:10 | nathanmarz | when I invoke with 21 args it just binds "rest" to the 21st arg (instead of a seq), and when I bind with more it gives an arity exception |
| 17:11 | nathanmarz | @dnolen any ideas? |
| 17:14 | ben_vulpes | mdeboard: no clue, boss. |
| 17:14 | ben_vulpes | i've fallen back to using lein-figwheel |
| 17:14 | ben_vulpes | but now it's not watching files |
| 17:16 | ben_vulpes | clean-builds and build-once work handily from the repl, but figwheel is refusing to reload changes. |
| 17:18 | dnolen | @nathanmarz probably just a bug |
| 17:19 | dnolen | @nathanmarz oh right, but there's no support for this at the protocol level in ClojureScript (and unlikely unless somebody else wants to do the work) |
| 17:19 | ben_vulpes | (i'm a derp, disregard) |
| 17:20 | nathanmarz | @dnolen: ok |
| 17:20 | dnolen | JavaScript doesn't support variadic methods in the nice way that Java does |
| 17:20 | dnolen | so you will need a fn to pull apart the args for you (fns produce a bunch of dispatching logic) |
| 17:20 | nathanmarz | @dnolen: I though that 21 arity version of -invoke (not including the "this" param) handled that case |
| 17:20 | dnolen | but this completely undesirable at the protocol level for perf reasons |
| 17:21 | dnolen | protocols are at the very bottom |
| 17:21 | dnolen | they are literally nothing but the host |
| 17:21 | dnolen | i.e. JavaScript methods |
| 17:21 | Bronsa | dnolen: isn't this the same for clojure on the jvm? IFn vs RestFn |
| 17:22 | nathanmarz | @dnolen: ok |
| 17:22 | dnolen | Bronsa: but Clojure separated these things out, Java doesn't have functions |
| 17:22 | nathanmarz | @dnolen: why to functions like assoc and + allow for more than 20 args? |
| 17:22 | dnolen | JavaScript does |
| 17:22 | dnolen | nathanmarz: var args support at the compiler level |
| 17:22 | dnolen | every function emits dispatching code to handle this stuff |
| 17:23 | nathanmarz | oh i see |
| 17:23 | dnolen | this code is not expressed at anything shareable (via a class) |
| 17:24 | dnolen | but also protocols do not support var args, neither Clojure nor ClojureScript |
| 17:24 | dnolen | IFn in Clojure is a Java thign |
| 17:24 | nathanmarz | yea, IFn in clojure has applyTo |
| 17:25 | nathanmarz | I thought the -invoke definition in cljs was the equivalent, but it just gets interpreted as a 21 artity invoke |
| 17:25 | dnolen | nathanmarz: nope |
| 17:25 | dnolen | the 21st arity is just to support fns that dispatch to protocols |
| 17:26 | dnolen | which will have already pulled apart the args |
| 17:27 | dnolen | @nathanmarz there's probably some way to make this work, but I'm not going to stick my brain there right now |
| 17:27 | nathanmarz | oh I just mean for my own extension of IFn to my own type |
| 17:27 | nathanmarz | yea it's not that big of a deal |
| 17:30 | dnolen | nathanmarz: Bronsa: actually scratch everything I just said |
| 17:30 | dnolen | I'd just forgotten how this worked (I did this so long ago) |
| 17:30 | dnolen | it's a simple bug |
| 17:31 | dnolen | nathanmarz: http://dev.clojure.org/jira/browse/CLJS-1447 |
| 17:31 | dnolen | not sure when I'll get around to this though |
| 17:34 | nathanmarz | @dnolen: I'll keep my test for this commented out in the meantime ;) |
| 17:36 | dnolen | nathanmarz: yeah ok now I remember the issue :) |
| 17:36 | dnolen | so ClojureScript functions are just JavaScript functions, there is no arity limit |
| 17:36 | dnolen | but this of course doesn't make sense for the IFn protocol, the change is actually pretty simple, the ticket is updated with some simple details on how to do it |
| 17:54 | berns_ | When I merge maps with merge-with, is there any way to maintain the order of the values? |
| 17:54 | amalloy | what do you mean, the order of the values? |
| 17:55 | eklo | Hello, I'm working on a recursive fn for counting the number of solutions to the n-queens but it seems slower then it should be. I'm just trying to learn if I used the correct structure for recursing and stopping branches early. https://www.refheap.com/109449 |
| 17:59 | berns_ | amalloy: ({:foo 1} {:foo 2} {:bar "a"} {:foo 3}) -> {:foo (1 2 3) :bar "a"} |
| 17:59 | amalloy | as opposed to...? |
| 17:59 | berns_ | {:foo (3 1 2) :bar "a"} |
| 18:00 | amalloy | the function that you give to merge-with will receive the values it needs to merge in the same order that they are present in the map you give to merge-with |
| 18:01 | amalloy | eklo: it looks reasonable enough to me |
| 18:02 | berns_ | but if I merge with conj, it prepends. If I merge with vector, it does [1 [2 3]] |
| 18:03 | amalloy | berns_: if you merge with conj it doesn't work at all, because (conj 1 2) is an error |
| 18:03 | nooga | btw. what is the best place to start learning about cljs compiler? (I mean the code, obviously, but it's a big program and it's hard to understand its structure eight away) |
| 18:03 | nooga | right* |
| 18:58 | seako | hello fellow clojurians, i'm wondering if anyone has any wisdom to share re: tuning garbage collection and jvm options or articles they can point me to? as i'm new to the jvm, nothing is too elementary. |
| 18:59 | tcrayford____ | seako: I was just reading just the thing! |
| 18:59 | tcrayford____ | http://insightfullogic.com/2013/Feb/20/garbage-collection-java-1/, http://insightfullogic.com/2013/Mar/06/garbage-collection-java-2/, http://insightfullogic.com/2013/May/07/garbage-collection-java-3/, http://insightfullogic.com/2013/Jun/24/garbage-collection-java-4/ |
| 19:00 | seako | thanks! |
| 19:00 | tcrayford____ | that's for GC at least. RE JVM options, I mention them a bit in a talk I gave at euroclojure this year: http://yellerapp.com/posts/2015-06-29-performance-and-lies.html |
| 19:00 | tcrayford____ | (there's a table in the slides that you can skip to, but it ain't useful without me talking over it) |
| 19:01 | seako | thanks so much, really appreciate it! |
| 19:02 | tcrayford____ | s'cool. Feel free to PM me on freenode if you have questions, I have done a lot of stuff with the JVM and perf/tuning/etc (I have an irc bouncer so I may not reply immediately, but I will get your message and reply eventually) |
| 19:04 | seako | super generous of you, i just might take you up on that :) |
| 20:39 | felipedvorak | http://pastebin.com/EWqrjtBs can somebody help me with that? It's ultra basic baby so probably won't take more than a few seconds of your time. I'm trying the classic "get me the odd numbers out of this sequence". What am I doing wrong? |
| 20:40 | justin_smith | felipedvorak: when would tail be 0? |
| 20:40 | justin_smith | ,(rest ()) |
| 20:40 | clojurebot | () |
| 20:41 | felipedvorak | hmmm |
| 20:41 | felipedvorak | would (nil? tail) work? |
| 20:41 | justin_smith | also why (into () resul) - you could just conj the items onto () in the first place if you want a reversed list instead of an in-order vector |
| 20:41 | justin_smith | felipedvorak: no |
| 20:41 | amalloy | also, this looks like you are trying to do the classic CL/scheme "accumulate a list and then reverse it" |
| 20:41 | justin_smith | err, maybe |
| 20:42 | justin_smith | but empty |
| 20:42 | felipedvorak | amalloy: I don't really know what I'm doing hehe |
| 20:42 | amalloy | nil? would be fine |
| 20:42 | justin_smith | oh, yeah he is using destructuring and not rest |
| 20:42 | amalloy | although uh, you then lose the last element of the sequence |
| 20:42 | amalloy | you can't just check the tail of the list and then ignore the head |
| 20:43 | justin_smith | felipedvorak: also, this is very much common-lisp style imperative code, and we have much simpler ways to do operations like this (but I trust if you stick to clojure you'll learn those eventually) |
| 20:44 | felipedvorak | I hope so, I'm only a few days in |
| 20:46 | felipedvorak | I still don't get it though |
| 20:46 | dbasch | felipedvorak: you probably want to start by looking at some of the built-ins that come with clojure http://clojure.org/cheatsheet |
| 20:46 | justin_smith | felipedvorak: rule of thumb, if what you are doing involves going through a sequence one item at a time, clojure probably has something much nicer than loop you can use for that |
| 20:47 | dbasch | felipedvorak: e.g. in this particular case, odd? and even? |
| 20:47 | justin_smith | felipedvorak: which part don't you get? |
| 20:47 | xzilend | noob question, I have a {:email ".." :password ".."} map. I'd like a validation function to add: {:errors ["error 1"]} to the initial map. I currently have (update-in creds [:errors] conj "error 1"), but that creates {:errors ("error 1")}, is there anyway I can enforce a vector instead? |
| 20:47 | justin_smith | xzilend: (fnil conj []) |
| 20:47 | felipedvorak | dbasch: I have that on my bedroom wall hehe will check it more often |
| 20:48 | justin_smith | ,((fnil conj []) [] :a) |
| 20:48 | clojurebot | [:a] |
| 20:48 | justin_smith | ,((fnil conj []) nil :a) |
| 20:48 | clojurebot | [:a] |
| 20:48 | dbasch | felipedvorak: I haven’t read your code but it sounds like you want (filter odd? your-seq) |
| 20:48 | justin_smith | dbasch: I think he still could learn a few things by making the loop work (though your version is canonical, of course) |
| 20:49 | dbasch | justin_smith: agreed |
| 20:50 | felipedvorak | lol, (filter odd? sequence) looks beautiful. Must love this language.. I'll try to fix this code for learning purposes |
| 20:53 | xzilend | justin_smith: thanks! |
| 20:53 | justin_smith | xzilend: fnil is almost as awesome to use as it is to say |
| 20:53 | justin_smith | fnil |
| 20:53 | justin_smith | rolls right off the tongue |
| 20:55 | oddcully | close to fna |
| 20:56 | lodin- | justin_smith: There's also a more esoteric solution, and that's to use a lens library and do (update creds (lookup :errors []) conj "error 1") where lookup is the lens with default value []. |
| 20:57 | justin_smith | one of my first experiences with my new job was introducing my coworkers to fnil, only to have them laugh at the word |
| 20:57 | justin_smith | lodin-: I was once talked out of trying to use lenses in clojure, do you think it's worth it? |
| 20:57 | xzilend | lodin-: thanks! I'll keep that in mind :D |
| 20:58 | lodin- | justin_smith: Yes! |
| 20:59 | lodin- | justin_smith: I really miss a solid lens library though. One day I might find the time to write one myself. |
| 21:01 | felipedvorak | hmm, and now hehe still get an error, I believe it may have to do with conj? (trying te primitively read the error output) |
| 21:01 | felipedvorak | http://pastebin.com/4M78iwvJ |
| 21:01 | justin_smith | felipedvorak: yeah, your args to conj are flipped |
| 21:01 | lodin- | justin_smith: I benched the functor implementation of lenses (my own, adapted from https://speakerdeck.com/markhibberd/lens-from-the-ground-up-in-clojure), against a 100 keys deep get-in. Lenses were faster. Blew my mind. I still believe the benchmark was wrong. |
| 21:02 | justin_smith | felipedvorak: it will still have the issue amalloy_ mentioned where if the last item is odd it will throw it away erroneously |
| 21:02 | felipedvorak | lol, now it gives me (6) as a result, but at least it runs |
| 21:03 | lodin- | Or was it update-in? Don't remember. |
| 21:03 | justin_smith | felipedvorak: oh, you flip the input and the result in your recur too |
| 21:03 | justin_smith | (in the first recur that is) |
| 21:05 | lodin- | justin_smith: Anyway, the point is that you don't need to worry about overhead, which leads us to the benefits. |
| 21:06 | felipedvorak | I still don't get why I loose the last item |
| 21:06 | lodin- | justin_smith: The biggest benefit is not actually lenses, but traversals. |
| 21:09 | xzilend | Can anyone tell me why I would prefer one of these over the other? (defn fun [s] (-> s f1 f2 f3)) or (def fun (comp f1 f2 f3))? |
| 21:11 | lodin- | xzilend: I opt for the first. The argument is explicit. (You have the order wrong in one of them though.) |
| 21:13 | xzilend | makes sense! thanks |
| 21:13 | lodin- | xzilend: Assuming the first version is correct, then it is clear that f1 takes just one argument. In the second, f1 could take any number of arguments. |
| 21:15 | lodin- | xzilend: I think linters like eastwood will help you out as well with the first, but not the second, if you do (fun x y) or (fun) etc. But I'm not sure. |
| 21:18 | xzilend | lodin-: good point! thanks :D was reading http://drboolean.gitbooks.io/mostly-adequate-guide/ and it's very keen on the (comp ..) (although in JS) form |
| 21:20 | justin_smith | xzilend: clojure definitely has its population of point-free fans |
| 21:20 | justin_smith | (point free programming being the style where you avoid named arguments, so frequently use constructs like comp or juxt) |
| 21:21 | lodin- | xzilend: At the top-level I think you should just spell out your function. Anonymous functions, like functions passed to e.g. filter, is another thing. |
| 21:23 | lodin- | xzilend: In practice, I find that I end up using #(-> % ...) anyway, since it's easier to do things like (get foo) there, rather than doing #(get % foo) in a comp. |
| 21:25 | lodin- | xzilend: If you do use comp a lot, I recommend using (defn => [f & args] #(apply f % args)) too. It will be cleaner. |
| 21:25 | lodin- | Especially since you can't nest #(). |
| 21:26 | xzilend | lodin-: yeah those arguments definitely make sense |
| 21:26 | xzilend | I've been using -> since I started clojure about a month or two ago, hadn't really seen comp used anywhere |
| 21:27 | lodin- | I'm not sure, but I think point-free makes more sense in "curried" languages, i.e. where multiple arity is just sugar for nested unary functions. |
| 21:51 | felipedvorak | justin_smith: with reduce I managed to get a list of the odd items BUT they are not in the correct order :/ http://pastebin.com/RXjZxAcH |
| 21:52 | felipedvorak | hehe but I'm almost there |
| 21:52 | justin_smith | felipedvorak: if you want to keep the order, use [] instead of () |
| 21:52 | justin_smith | also, '() is the same as (), you never need the former |
| 21:52 | felipedvorak | hmm |
| 21:52 | justin_smith | ,(= () '()) |
| 21:52 | clojurebot | true |
| 21:53 | felipedvorak | but if the answer must be given in a list format, I use `into`? |
| 21:53 | justin_smith | no, into will reverse the order |
| 21:53 | justin_smith | use seq if you need the result to be a list - but why do you need a list? |
| 21:54 | felipedvorak | justin_smith: because the 4clojure problem, as far as I understood, asks for a list output |
| 21:54 | justin_smith | felipedvorak: I doubt it will reject a vector |
| 21:55 | justin_smith | but wrap the whole thing in seq if it rejects the vector |
| 21:55 | justin_smith | ,(= [:a :b :c] '(:a :b :c)) ; felipedvorak: in clojure lists and vectors are equal if they have the same content in the same order |
| 21:55 | clojurebot | true |
| 21:56 | felipedvorak | hmm, thats new to me |
| 21:57 | felipedvorak | justin_smith: must go out for a bit, thanks for your help, I'll keep trying when I come back |
| 21:59 | felipedvorak | it works! hehe thanks |
| 22:37 | pydave6377 | Probably a stupid question, but is there a way of combining a HOF with the threading macro? Something like: (-> rtm-conn :start :users (filter :is_bot) first :id) |
| 22:38 | justin_smith | pydave6377: that works if you use ->> instead of -> |
| 22:38 | lodin- | pydave6377: You want to use ->> in front of filter. |
| 22:38 | justin_smith | since your collection needs to be the last arg |
| 22:38 | justin_smith | pydave6377: also, ->> can be used inside of -> if you need to combine the behaviors |
| 22:40 | justin_smith | ,(-> {:a [1 2 3 4]} :a (->> (map inc))) |
| 22:40 | clojurebot | (2 3 4 5) |
| 22:40 | lodin- | pydave6377: Has nothing to do with HOF though. |
| 22:40 | pydave6377 | justin_smith: lodin- This is fantastic! Thank you both so much! I always had trouble working out the difference between -> and ->> so I'm ecstatic to have finally learned! Thank you both again! |
| 22:41 | pydave6377 | lodin-: apologies - perhaps I mispoke. Still getting the hang of FP! |
| 22:42 | lodin- | pydave6377: Ah, wait. Did you mean "partial"? |
| 22:43 | pydave6377 | lodin-: partial would have been a much more apposite description. |
| 22:45 | lodin- | pydave6377: All the forms in -> and ->> are "partial". That's the point of ->. That's not always clear because you often see it with unary functions and symbols are rewritten to have a parenthesis around them. |
| 22:45 | pydave6377 | justin_smith: sorry, took me a moment to grok that. I had no clue that was possible! Thank you |
| 22:45 | lodin- | pydave6377: In other words, (-> x foo bar) is really (-> x (foo) (bar)). |
| 22:46 | felipedvorak | How do I get a number, say 424 and interpret it like a list (1 2 3 4 5...) so I can iterate? |
| 22:46 | justin_smith | lodin-: it's not really partial application though, -> / ->> don't operate on runtime functions and values, the operate on compile time forms |
| 22:46 | lodin- | pydave6377: And (-> x (foo y)) is (foo x y). |
| 22:47 | justin_smith | ,'(-> x (foo y)) |
| 22:47 | clojurebot | (-> x (foo y)) |
| 22:47 | lodin- | justin_smith: Yeah, I know. But you could say that the form is partial. |
| 22:47 | justin_smith | ,(macroexpand1 '(-> x (foo y))) |
| 22:47 | clojurebot | #error {\n :cause "Unable to resolve symbol: macroexpand1 in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: macroexpand1 in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6704]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol:... |
| 22:47 | justin_smith | err |
| 22:47 | lodin- | pydave6377: And (->> y (foo x)) is (foo x y). |
| 22:47 | pydave6377 | lodin-: that's really interesting. I've been using it the whole time as a substitute for (bar (foo (x))) |
| 22:47 | justin_smith | ,(macroexpand-1 '(-> x (foo y))) |
| 22:47 | clojurebot | (foo x y) |
| 22:51 | sotojuan | kool |
| 22:51 | lodin- | pydave6377: The name comes from how you do stitches with a needle. Thread, as in yarn. |
| 22:55 | pydave6377 | lodin-: that's just made everything so much clearer. I've never thought of it like that. You guys have been incredibly helpful. Thank you so much! |
| 22:57 | lodin- | pydave6377: But don't start abusing it. :-) |
| 22:57 | lodin- | ,(->> n dec f (* n) (if-not (pos? n) 1) (defn f [n])) |
| 22:57 | clojurebot | #'sandbox/f |
| 22:57 | lodin- | ,(f 5) |
| 22:58 | clojurebot | 120 |
| 22:58 | justin_smith | oh my god that's terrible |
| 22:58 | justin_smith | haha |
| 22:58 | lodin- | justin_smith: This is how I write all my code. ;-) |
| 22:59 | kavkaz | D: |
| 23:00 | pydave6377 | lodin-: that's the most egregious abuse of a well-intentioned feature that I have ever seen. |
| 23:00 | pydave6377 | (inc lodin-) |
| 23:14 | justin_smith | this article about fortran covers clojure, and has some invalid common lisp code in it too http://arstechnica.com/science/2014/05/scientific-computings-future-can-any-coding-language-top-a-1950s-behemoth/ |
| 23:15 | felipedvorak | What is the clojure equivalent of (i = 1; i < 1000; i++) ? |
| 23:15 | lodin- | felipedvorak: Depends on what you want to do, but probably (range 1 1000). |
| 23:16 | justin_smith | felipedvorak: (loop [i 0] (if (> i 999) nil ...) (recur (inc i))) |
| 23:16 | justin_smith | your code goes in the ... part |
| 23:16 | justin_smith | lodin-: I guess we interpreted that differently |
| 23:17 | justin_smith | another possibility is (doseq [i (range 1000)] ...) |
| 23:17 | lodin- | justin_smith: I'd doseq instead. |
| 23:17 | lodin- | Yeah. |
| 23:17 | felipedvorak | hmm |
| 23:17 | justin_smith | felipedvorak: what are you actually trying to do? |
| 23:17 | lodin- | But using range with doseq or what-not only works if you don't plan to change i in the loop. |
| 23:18 | felipedvorak | get as input a number and use it as a list to check each number for a condition |
| 23:19 | felipedvorak | also known as project euler problem 1 hehe |
| 23:19 | justin_smith | felipedvorak: what happens to the numbers you check? |
| 23:19 | justin_smith | do you return some of them? |
| 23:19 | justin_smith | do you print them? |
| 23:19 | felipedvorak | yeah |
| 23:19 | felipedvorak | if a number is multiple of 3 or 5 |
| 23:20 | justin_smith | yeah, use doseq with a print inside |
| 23:20 | lodin- | I'd first filter and then doseq over the ones I want to print. |
| 23:20 | felipedvorak | my prowess is still very basic, I still don't know doseq |
| 23:20 | felipedvorak | let me check it |
| 23:21 | justin_smith | ,(doseq [i (range 10)] (println i)) |
| 23:21 | clojurebot | 0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n |
| 23:21 | felipedvorak | in the end you must output the sum of the numbers |
| 23:21 | justin_smith | ahh, so you need to keep track and sum, you'll want more than just doseq for that yeah |
| 23:21 | felipedvorak | ^ what is this output? |
| 23:21 | lodin- | felipedvorak: Then let me point you towards reduce. |
| 23:22 | lodin- | felipedvorak: You can use a combination of reduce, filter, and range. |
| 23:22 | justin_smith | yeah, that's probably the best bet |
| 23:23 | felipedvorak | i'll try that, thanks |
| 23:25 | lodin- | felipedvorak: The "easy" solution if you are used to using loops is to use loop/recur, but resist the temptation. :-) |
| 23:25 | felipedvorak | wouldn't reduce be even easier? |
| 23:25 | justin_smith | felipedvorak: simpler vs. more familiar |
| 23:25 | lodin- | felipedvorak: Simple vs easy. ;-) |
| 23:26 | felipedvorak | I'm really looking for the hard but still "clojury" solution hehe |
| 23:26 | kavkaz | Not Clojure related but I'm expecting I'll have a quick answer, is there a MELPA package I need to download for emacs to enable spellcheck? |
| 23:27 | justin_smith | kavkaz: ispell comes with emacs, flyspell-mode is a nice way to use it |
| 23:31 | kavkaz | justin_smith: Ah cool, thanks |