#clojure logs

2015-09-11

00:00justin_smithnowprovision: why not nth?
00:01nowprovisionjustin_smith, that seems better, im very rusty.. tahnks
00:01justin_smithnowprovision: it might read better if you bind the (iterate ...) in the let block, then use nth on that
00:10nowprovisionokay now I have https://www.refheap.com/20d51c2bb7ea776d05824a862 any further thoughts
00:14ska-fanSo (:a {:a 4}) is 4, but ("a" {"a" 4)) throws an exception - does key as a function just doesn't work for strings?
00:15TEttingerska-fan: ah this is neat
00:15TEttingerso keywords like :a actually do more than just store text conveniently
00:15tolstoyBut ({"a" 4} "a") is 4.
00:16ska-fantolstoy: Ha! indeed. /me goes of simplifying.
00:16nowprovisiona keyword is a function
00:16justin_smithska-fan: clojure always calls the first thing after the paren
00:16TEttingera 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:16justin_smithska-fan: it just so happens that keywords are callable
00:16justin_smith,(:a :a :a)
00:17TEttingermaps also implement IFn and can be called with a key
00:17clojurebot:a
00:17TEttingerwha
00:17TEttinger,(:a :a)
00:17clojurebotnil
00:17TEttingerha!
00:17TEttingerit's a get
00:17TEttinger,(:a :a :b)
00:17clojurebot:b
00:17justin_smithTEttinger: demonstrating that :a is callable, and it isn't something being done by the map
00:17TEttinger,({:a 5} :a)
00:17clojurebot5
00:18TEttinger,({"a" 5} "a")
00:18clojurebot5
00:18TEttingermaps are fns too, but like justin_smith is saying, the first thing after the '(' is what gets called
00:18tolstoy,({2 4} 2)
00:18clojurebot4
00:18TEttingerthreeve_: is that nick a celebrity jeopardy reference?
00:26devtrope,(supers (class :a))
00:26clojurebot#{java.util.concurrent.Callable clojure.lang.IFn java.lang.Runnable java.lang.Comparable java.io.Serializable ...}
00:29TEttinger,(clojure.string/join " " (supers (class :a)))
00:29clojurebot"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:13deiodeiodeioI 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:15ordnungswidrigdeiodeiodeio: that's actually a good question. But why want you to run tests in parallel?
03:16deiodeiodeioI'm doing integration tests involving spinning up and taking down a lot of services
03:17deiodeiodeionaturally, this takes a while
03:17ordnungswidrigdeiodeiodeio: I see. In which way do futures break it?
03:17ordnungswidrigdeiodeiodeio: I'm assuming there are no race conditions or the tests influencing easch other
03:21deiodeiodeioordnungswidrig: it doesn't seem to be my code, no..
03:22ordnungswidrigcan you distill an example? just how you use midje and futures?
03:22deiodeiodeioyeah, sorry, I'm working on it
03:29deiodeiodeioordnungswidrig: 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:30ordnungswidrigdeiodeiodeio: oh weird
03:30deiodeiodeioordnungswidrig: yeah. but I'm now not entirely convinced it's midje's fault. if it is, it seems to be flaky
03:30deiodeiodeioso I guess I'll have to investigate it a bit closer
03:30ordnungswidrigdeiodeiodeio: I would macroexpand the (facts) expression
06:30namraj/quit
07:30deiodeiodeiowhat's a good, simple way of doing concurrent printing without using core.async or a logging library?
07:30deiodeiodeio(i.e. without multiple lines printing concurrently)
07:40mnngfltgdeiodeiodeio, using an agent perhaps?
07:40lumayep, create an agent and then send each printing to it
09:19galauxI can't find some kind of "fail" method for Clojure unit tests …
09:19galauxDoes it exist somewhere?
09:21snowellWouldn't you generally want to assert the opposite of what's happening?
09:21galauxwell: nothing is happening, that's the idea
09:21snowellWhat are you testing for?
09:21galauxI'm testing for a particular function NOT to be called
09:22galauxThis is a function I pass to some other function … I want to check it has not be called
09:22galauxSo I thought I would just make this second method something like `(fail "Error")
09:23snowellI mean…you could always assert false ;)
09:23galauxyes …
09:23snowellSorry that's not a whole lot of help
09:24galauxno but still it would work … even though a "fail" method would have been perfect (especially for handling a test failing messge)
09:24galauxsnowell: thanks
09:25snowellI've not done much unit testing in clojure. When I have, it was with https://github.com/marick/Midje
09:26dstocktongalaux: assert can take an option message
09:26dstockton(defn fail [message] (assert false message))
09:28dstocktonor you could throw an exception
09:29galauxAn exception is not a failing test
09:29galauxI don't want to crash it, just flag it as failed
09:29galauxbut it would work in some way
09:32galauxI am going to go for `(is (true? false) "Something went wrong")`
09:32galauxsnowell: thanks for the link,looks nice !
09:33snowellWith both Midje and clojure.test, you can assert that exceptions are thrown/not thrown
09:34snowellSo if you pass in a function that just throws an Exception, you can assert that said Exception isn't thrown
09:34snowellWithout crashing the test execution
10:13justin_smithe
10:21justin_smith,0xDEADBEEFCAFEBADD
10:21clojurebot16045690984503098077N
10:21justin_smithI hear that number is prime
10:26gfredericks,(.isProbablePrime (biginteger 0xDEADBEEFCAFEBADD) 100)
10:26clojurebottrue
10:33troydmwhich function should I use for lenghth of string in Clojure? .length or count?
10:41justin_smithwell only one of those is a function
10:41justin_smithuse count
12:52mdeboardOk so in cider, I'm running this long-running async process in a goroutine. How the heck do I kill it?
12:59justin_smithmdeboard: write it such that it checks some condition you have control over, and it exits gracefully
12:59justin_smithor kill your vm
13:00mdeboardok, that's what I figured (the last)
13:00justin_smithmdeboard: is it reading from some channel? closing the channel would help in that case
13:00justin_smith(I was being slightly glib)
13:00mdeboardYeah I just added some logic to close
13:05mdeboardI assume the value of `(<! ch)` if there are no messages on the channel is `nil`, is that right?
13:08justin_smithno
13:08justin_smithit doesn't return to your process
13:08justin_smithnil is if the channel is closed
13:09justin_smith(which is why I mention that closing a channel could communicate to a go block that it should exit)
13:09justin_smithmdeboard: forgot to highlight you in my reply ^
13:10mdeboardI see
13:10mdeboardHmm
13:10mdeboardBecause I want to flush my buffered writer if there's nothing on the channel
13:10mdeboardso I don't have half a message in the log
13:10mdeboardjust chilling, waiting for more data
13:11justin_smithmdeboard: check out alts!
13:11justin_smiththen you can have a timeout, and flush if the timeout is hit
13:11mdeboardCool
13:11mdeboardVery nice
13:12justin_smithlike (alts! [ch (timeout 10000)]) either gets data from ch, or from the timeout after 10 seconds
13:12justin_smithand in the return value you can test which you got
13:13mdeboardFrustrated with Clojure's documentation atm.
13:13mdeboardAs I have been since 2010 or something.
13:13justin_smithmdeboard: this is what makes our lovely community so valuable :)
13:14justin_smithmdeboard: 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:14justin_smithofficial core.async api docs, that is
13:17mdeboardyeah that's what I'm frustrated with :P
13:17mdeboardIt's definitely exhaustive
13:17mdeboardNot sure how useful it actually is, but it's exhaustive
13:18mdeboardjustin_smith, So where can I find a full example of this alts functionality
13:18justin_smithmdeboard: 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:18justin_smithmdeboard: hmm, maybe conj.io, checking
13:19mdeboardIs that another stab at community-curated docs?
13:19mdeboardAh this is uh
13:19justin_smithmdeboard: if not i'll share a quick repl demo of it
13:19mdeboardOh the guy lives here in Austin
13:19mdeboardCan't remember his name, but this is his thing
13:19justin_smithmdeboard: arrdem
13:19mdeboardarrdem, yeah
13:19justin_smithI thought he had core.async on here but I can't find it
13:20mdeboardHere's my function https://gist.github.com/mattdeboard/ecd0d033d1977bf6da78
13:21mdeboardI 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:21mdeboard)
13:23justin_smithmdeboard: working demo of alts! from the repl https://www.refheap.com/109440
13:23justin_smithmdeboard: you can test via the second item in that returned vector which channel the value came from
13:23justin_smithmdeboard: paste updated to show this fact https://www.refheap.com/109440
13:25justin_smithmdeboard: 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:26justin_smithmdeboard: using my own repl example of alts as a basis for that should be easy enough
13:34mdeboardNice, thanks
13:35mungojellywhy do i need to say var# to get unclobbered variables in macros, do y'all also use macros to intentionally clobber variables?
13:42sdegutisIs there a simpler way of mapping characters in a string to their line/char position than this? https://gist.github.com/sdegutis/ff476b6efef23e7a5a1d
13:42sdegutisThis function seems overly complex.
13:42mdeboardjustin_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:43mdeboardIt says it "does at most one of several channel operations"
13:43mdeboardWhat operations is it talking about?
13:43snowellmdeboard: It accepts any number of channels and performs a take on whichever one of them *first* returns a value
13:43mdeboardOh
13:43mdeboardWhat the hell?
13:44mdeboardwth @ the docs
13:44arrdemmdeboard: o/
13:44mdeboardthat's 100% impenetrable
13:44arrdemare we on about docs again
13:44mdeboardand also just seems inconsistent with actual functionality?
13:44mdeboardarrdem, lol
13:44mdeboardI don't want to get you in any legal trouble
13:45mdeboardor something (recalling some blog post about something like that)
13:45snowellI do. I'd love an excuse to go back to Austin ;)
13:45mdeboard"Completes at most one of several channel operations." <-- actually means "Performs a take on at most one of several channels"?
13:46mdeboardOk 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:47arrdemwelcome to Clojure
13:48mgaare_mdeboard: actually that's not what it means. because you can also do a put inside of alts!
13:48mdeboardYeah was just saying this has been constant source of irritation for like 5 years
13:48mdeboardmgaare_, Yeah I see that now
13:48mdeboardI'm tempted to do a PR to improve that docstring
13:48snowellSorry…I knew there was a chance I only partially understood it :/
13:49mdeboardbut by "several" it just means "two" right? Either put or take?
13:49mgaare_that's why it says channel operations.
13:50snowell"several" refers to its args
13:50mdeboardwat
13:50clojurebotTitim gan éirí ort.
13:51snowellYou pass in several operations, it will perform at most one of them
13:51mdeboardOk, maybe I am misunderstanding the word operation.
13:53mgaare_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:54seancorfieldclojars.org seems to be struggling... very very slow to respond / occasional 500 server error messages
13:54mdeboardok so you can do like `(alts! [ch-foo [ch-bar 1] ch-baz [ch-qux 2]])` ?
13:55mgaare_mdeboard: that's right
13:55mdeboardOk. Thanks for the clarification
13:55mdeboardDoes it just iterate left-to-right looking for the first valid operation?
13:56mdeboardand a put is invalid only if the channel is closed?
13:57mgaare_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:58mdeboardUnderstood, thank you
13:59mungojellywhy the ! does it change something
14:03_alejandroit modifies the channel it reads from / writes to
14:12mdeboardThat's just a freaking hard function to explain. Takes more than the dry matter-of-fact tone of docstring.
14:12mdeboard(I'm sitting here trying to write better documentation.)
14:14geetHi! I'm new to Clojrue, I'd like to start contributing. Where would you suggest I do?
14:15mungojellyhmm so you only get tail-call optimization if you ask for it with "recur"?
14:17arrdemmungojelly: correct
14:18mungojellyok thanks well that's clear enough anyway. what do you want to contribute to what, geet, i don't understand?
14:19arrdemnote that the JVM itself doesn't have TCO yet due to reliance on stack frame counting for some security stuff
14:22geetContributing to clojure
14:22geetmungojelly:
14:23mungojellypersonally what i think it needs is more toys
14:24mungojellyi'm learning by poking at lists of meaningless numbers, i'm bored, someone hand me a toy
14:25mdeboardIs there any kind of proscription against calling `recur` in a `do` block
14:26justin_smithmdeboard: 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:26mdeboardAlright, cool
14:34mdeboardI think this will do what I am wanting but not entirely sure https://gist.github.com/mattdeboard/ecd0d033d1977bf6da78
14:34mdeboardIt didn't, actually. I wonder if it closed too quick or something.
14:35justin_smithmdeboard: (if (nil? entry) ...) should be (if (nil? (first entry)) ...)
14:35justin_smithmdeboard: remember alts returns a two part vector
14:35justin_smitheven better, it could be (if-not (= ch (second entry)) ...)
14:36justin_smithmdeboard: 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:37justin_smithmdeboard: or, perhaps the easier change is (let [[entry source] (async/alts! ...) ...] ...) and then the rest of the code can stand unchanged
14:37mdeboardAre you sure about the vector thing?
14:37mdeboardhttps://gist.github.com/mattdeboard/f15ff4454ffd1c570ca2
14:37justin_smithmdeboard: absolutely sure
14:37justin_smithmdeboard: it's not timeout that returns the vector
14:38justin_smithit is alts! that is returning a vector
14:38mdeboardOh!
14:38mdeboardOk.
14:38justin_smithmdeboard: 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:38justin_smithalts! would not be very useful without that feature
14:38mdeboardWhy is this so hard for me to grok
14:39justin_smithmdeboard: it's new?
14:47mdeboardNice, it works
14:47mdeboardThanks for the help all youse
14:48justin_smithcool
14:50mdeboardHm maybe not.
14:51mdeboardThis is really hard to troubleshoot, the asynchrony. Feel like I'm doing JavaScript
14:52mdeboardWriting javascripts*
14:53justin_smithjabbyscraps
14:54justin_smithyes, core.async can be weird to figure out when misbehaving
16:52ben_vulpesso 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:52ben_vulpesi new up a figwheel server, stop it, and then bind the result to fig-server
16:53ben_vulpespass that into the watcher as (fig/autobuild* {... :fig-server fig-server})
16:53ben_vulpescall (fig/stop-server ...) on the value for the :fig-builder key in my system object
16:54ben_vulpesget a repl print line that claims that the fig-server has been started on :3449
16:54ben_vulpesbut then i simply get websocket errors in the browser, a la 'ws://localhost:3449/figwheel-ws/dev failed' ERR_CONNECTION_REFUSED
16:56noogaI just had the weirdest node.js like experience with clojure
16:56ben_vulpesoh fascinating. it's not even recompiling the cljs.
16:56mdeboardben_vulpes, Is your project.clj set up right?
16:57noogatimbre was throwing an exception because something inside manifold returned an exception instead of a value I wanted to log
16:57mdeboardHere'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:57noogaand I saw manifold's exception with meaningless timbre call stack
16:58noogatook me a while
16:58mdeboardben_vulpes, figwheel used to be super, super hard to set up then... something changed that I can't remember
16:59mdeboardmaybe I just stopped being dumb
16:59noogaheheh
16:59mdeboardGosh darnnit I hate that i have to have the source code ordered correctly in order to compile
16:59mdeboardlike if function A calls function B, function B has to be physically above function A in the source
17:00mdeboardis that unavoidable?
17:07oddcully,(doc declare)
17:07clojurebot"([& names]); defs the supplied var names with no bindings, useful for making forward declarations."
17:08nathanmarzClojurescript question for any of the experts here
17:09nathanmarzTrying to implement IFn protocol for more than 20 arguments, but this isn't working: https://gist.github.com/nathanmarz/e932e11c523fe90b1850
17:10nathanmarzwhen 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:11nathanmarz@dnolen any ideas?
17:14ben_vulpesmdeboard: no clue, boss.
17:14ben_vulpesi've fallen back to using lein-figwheel
17:14ben_vulpesbut now it's not watching files
17:16ben_vulpesclean-builds and build-once work handily from the repl, but figwheel is refusing to reload changes.
17:18dnolen@nathanmarz probably just a bug
17:19dnolen@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:19ben_vulpes(i'm a derp, disregard)
17:20nathanmarz@dnolen: ok
17:20dnolenJavaScript doesn't support variadic methods in the nice way that Java does
17:20dnolenso you will need a fn to pull apart the args for you (fns produce a bunch of dispatching logic)
17:20nathanmarz@dnolen: I though that 21 arity version of -invoke (not including the "this" param) handled that case
17:20dnolenbut this completely undesirable at the protocol level for perf reasons
17:21dnolenprotocols are at the very bottom
17:21dnolenthey are literally nothing but the host
17:21dnoleni.e. JavaScript methods
17:21Bronsadnolen: isn't this the same for clojure on the jvm? IFn vs RestFn
17:22nathanmarz@dnolen: ok
17:22dnolenBronsa: but Clojure separated these things out, Java doesn't have functions
17:22nathanmarz@dnolen: why to functions like assoc and + allow for more than 20 args?
17:22dnolenJavaScript does
17:22dnolennathanmarz: var args support at the compiler level
17:22dnolenevery function emits dispatching code to handle this stuff
17:23nathanmarzoh i see
17:23dnolenthis code is not expressed at anything shareable (via a class)
17:24dnolenbut also protocols do not support var args, neither Clojure nor ClojureScript
17:24dnolenIFn in Clojure is a Java thign
17:24nathanmarzyea, IFn in clojure has applyTo
17:25nathanmarzI thought the -invoke definition in cljs was the equivalent, but it just gets interpreted as a 21 artity invoke
17:25dnolennathanmarz: nope
17:25dnolenthe 21st arity is just to support fns that dispatch to protocols
17:26dnolenwhich will have already pulled apart the args
17:27dnolen@nathanmarz there's probably some way to make this work, but I'm not going to stick my brain there right now
17:27nathanmarzoh I just mean for my own extension of IFn to my own type
17:27nathanmarzyea it's not that big of a deal
17:30dnolennathanmarz: Bronsa: actually scratch everything I just said
17:30dnolenI'd just forgotten how this worked (I did this so long ago)
17:30dnolenit's a simple bug
17:31dnolennathanmarz: http://dev.clojure.org/jira/browse/CLJS-1447
17:31dnolennot sure when I'll get around to this though
17:34nathanmarz@dnolen: I'll keep my test for this commented out in the meantime ;)
17:36dnolennathanmarz: yeah ok now I remember the issue :)
17:36dnolenso ClojureScript functions are just JavaScript functions, there is no arity limit
17:36dnolenbut 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:54berns_When I merge maps with merge-with, is there any way to maintain the order of the values?
17:54amalloywhat do you mean, the order of the values?
17:55ekloHello, 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:59berns_amalloy: ({:foo 1} {:foo 2} {:bar "a"} {:foo 3}) -> {:foo (1 2 3) :bar "a"}
17:59amalloyas opposed to...?
17:59berns_{:foo (3 1 2) :bar "a"}
18:00amalloythe 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:01amalloyeklo: it looks reasonable enough to me
18:02berns_but if I merge with conj, it prepends. If I merge with vector, it does [1 [2 3]]
18:03amalloyberns_: if you merge with conj it doesn't work at all, because (conj 1 2) is an error
18:03noogabtw. 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:03noogaright*
18:58seakohello 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:59tcrayford____seako: I was just reading just the thing!
18:59tcrayford____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:00seakothanks!
19:00tcrayford____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:00tcrayford____(there's a table in the slides that you can skip to, but it ain't useful without me talking over it)
19:01seakothanks so much, really appreciate it!
19:02tcrayford____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:04seakosuper generous of you, i just might take you up on that :)
20:39felipedvorakhttp://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:40justin_smithfelipedvorak: when would tail be 0?
20:40justin_smith,(rest ())
20:40clojurebot()
20:41felipedvorakhmmm
20:41felipedvorakwould (nil? tail) work?
20:41justin_smithalso 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:41justin_smithfelipedvorak: no
20:41amalloyalso, this looks like you are trying to do the classic CL/scheme "accumulate a list and then reverse it"
20:41justin_smitherr, maybe
20:42justin_smithbut empty
20:42felipedvorakamalloy: I don't really know what I'm doing hehe
20:42amalloynil? would be fine
20:42justin_smithoh, yeah he is using destructuring and not rest
20:42amalloyalthough uh, you then lose the last element of the sequence
20:42amalloyyou can't just check the tail of the list and then ignore the head
20:43justin_smithfelipedvorak: 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:44felipedvorakI hope so, I'm only a few days in
20:46felipedvorakI still don't get it though
20:46dbaschfelipedvorak: you probably want to start by looking at some of the built-ins that come with clojure http://clojure.org/cheatsheet
20:46justin_smithfelipedvorak: 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:47dbaschfelipedvorak: e.g. in this particular case, odd? and even?
20:47justin_smithfelipedvorak: which part don't you get?
20:47xzilendnoob 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:47justin_smithxzilend: (fnil conj [])
20:47felipedvorakdbasch: I have that on my bedroom wall hehe will check it more often
20:48justin_smith,((fnil conj []) [] :a)
20:48clojurebot[:a]
20:48justin_smith,((fnil conj []) nil :a)
20:48clojurebot[:a]
20:48dbaschfelipedvorak: I haven’t read your code but it sounds like you want (filter odd? your-seq)
20:48justin_smithdbasch: I think he still could learn a few things by making the loop work (though your version is canonical, of course)
20:49dbaschjustin_smith: agreed
20:50felipedvoraklol, (filter odd? sequence) looks beautiful. Must love this language.. I'll try to fix this code for learning purposes
20:53xzilendjustin_smith: thanks!
20:53justin_smithxzilend: fnil is almost as awesome to use as it is to say
20:53justin_smithfnil
20:53justin_smithrolls right off the tongue
20:55oddcullyclose to fna
20:56lodin-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:57justin_smithone of my first experiences with my new job was introducing my coworkers to fnil, only to have them laugh at the word
20:57justin_smithlodin-: I was once talked out of trying to use lenses in clojure, do you think it's worth it?
20:57xzilendlodin-: thanks! I'll keep that in mind :D
20:58lodin-justin_smith: Yes!
20:59lodin-justin_smith: I really miss a solid lens library though. One day I might find the time to write one myself.
21:01felipedvorakhmm, and now hehe still get an error, I believe it may have to do with conj? (trying te primitively read the error output)
21:01felipedvorakhttp://pastebin.com/4M78iwvJ
21:01justin_smithfelipedvorak: yeah, your args to conj are flipped
21:01lodin-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:02justin_smithfelipedvorak: it will still have the issue amalloy_ mentioned where if the last item is odd it will throw it away erroneously
21:02felipedvoraklol, now it gives me (6) as a result, but at least it runs
21:03lodin-Or was it update-in? Don't remember.
21:03justin_smithfelipedvorak: oh, you flip the input and the result in your recur too
21:03justin_smith(in the first recur that is)
21:05lodin-justin_smith: Anyway, the point is that you don't need to worry about overhead, which leads us to the benefits.
21:06felipedvorakI still don't get why I loose the last item
21:06lodin-justin_smith: The biggest benefit is not actually lenses, but traversals.
21:09xzilendCan 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:11lodin-xzilend: I opt for the first. The argument is explicit. (You have the order wrong in one of them though.)
21:13xzilendmakes sense! thanks
21:13lodin-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:15lodin-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:18xzilendlodin-: 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:20justin_smithxzilend: clojure definitely has its population of point-free fans
21:20justin_smith(point free programming being the style where you avoid named arguments, so frequently use constructs like comp or juxt)
21:21lodin-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:23lodin-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:25lodin-xzilend: If you do use comp a lot, I recommend using (defn => [f & args] #(apply f % args)) too. It will be cleaner.
21:25lodin-Especially since you can't nest #().
21:26xzilendlodin-: yeah those arguments definitely make sense
21:26xzilendI've been using -> since I started clojure about a month or two ago, hadn't really seen comp used anywhere
21:27lodin-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:51felipedvorakjustin_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:52felipedvorakhehe but I'm almost there
21:52justin_smithfelipedvorak: if you want to keep the order, use [] instead of ()
21:52justin_smithalso, '() is the same as (), you never need the former
21:52felipedvorakhmm
21:52justin_smith,(= () '())
21:52clojurebottrue
21:53felipedvorakbut if the answer must be given in a list format, I use `into`?
21:53justin_smithno, into will reverse the order
21:53justin_smithuse seq if you need the result to be a list - but why do you need a list?
21:54felipedvorakjustin_smith: because the 4clojure problem, as far as I understood, asks for a list output
21:54justin_smithfelipedvorak: I doubt it will reject a vector
21:55justin_smithbut wrap the whole thing in seq if it rejects the vector
21:55justin_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:55clojurebottrue
21:56felipedvorakhmm, thats new to me
21:57felipedvorakjustin_smith: must go out for a bit, thanks for your help, I'll keep trying when I come back
21:59felipedvorakit works! hehe thanks
22:37pydave6377Probably 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:38justin_smithpydave6377: that works if you use ->> instead of ->
22:38lodin-pydave6377: You want to use ->> in front of filter.
22:38justin_smithsince your collection needs to be the last arg
22:38justin_smithpydave6377: also, ->> can be used inside of -> if you need to combine the behaviors
22:40justin_smith,(-> {:a [1 2 3 4]} :a (->> (map inc)))
22:40clojurebot(2 3 4 5)
22:40lodin-pydave6377: Has nothing to do with HOF though.
22:40pydave6377justin_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:41pydave6377lodin-: apologies - perhaps I mispoke. Still getting the hang of FP!
22:42lodin-pydave6377: Ah, wait. Did you mean "partial"?
22:43pydave6377lodin-: partial would have been a much more apposite description.
22:45lodin-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:45pydave6377justin_smith: sorry, took me a moment to grok that. I had no clue that was possible! Thank you
22:45lodin-pydave6377: In other words, (-> x foo bar) is really (-> x (foo) (bar)).
22:46felipedvorakHow do I get a number, say 424 and interpret it like a list (1 2 3 4 5...) so I can iterate?
22:46justin_smithlodin-: it's not really partial application though, -> / ->> don't operate on runtime functions and values, the operate on compile time forms
22:46lodin-pydave6377: And (-> x (foo y)) is (foo x y).
22:47justin_smith,'(-> x (foo y))
22:47clojurebot(-> x (foo y))
22:47lodin-justin_smith: Yeah, I know. But you could say that the form is partial.
22:47justin_smith,(macroexpand1 '(-> x (foo y)))
22:47clojurebot#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:47justin_smitherr
22:47lodin-pydave6377: And (->> y (foo x)) is (foo x y).
22:47pydave6377lodin-: that's really interesting. I've been using it the whole time as a substitute for (bar (foo (x)))
22:47justin_smith,(macroexpand-1 '(-> x (foo y)))
22:47clojurebot(foo x y)
22:51sotojuankool
22:51lodin-pydave6377: The name comes from how you do stitches with a needle. Thread, as in yarn.
22:55pydave6377lodin-: 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:57lodin-pydave6377: But don't start abusing it. :-)
22:57lodin-,(->> n dec f (* n) (if-not (pos? n) 1) (defn f [n]))
22:57clojurebot#'sandbox/f
22:57lodin-,(f 5)
22:58clojurebot120
22:58justin_smithoh my god that's terrible
22:58justin_smithhaha
22:58lodin-justin_smith: This is how I write all my code. ;-)
22:59kavkazD:
23:00pydave6377lodin-: that's the most egregious abuse of a well-intentioned feature that I have ever seen.
23:00pydave6377(inc lodin-)
23:14justin_smiththis 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:15felipedvorakWhat is the clojure equivalent of (i = 1; i < 1000; i++) ?
23:15lodin-felipedvorak: Depends on what you want to do, but probably (range 1 1000).
23:16justin_smithfelipedvorak: (loop [i 0] (if (> i 999) nil ...) (recur (inc i)))
23:16justin_smithyour code goes in the ... part
23:16justin_smithlodin-: I guess we interpreted that differently
23:17justin_smithanother possibility is (doseq [i (range 1000)] ...)
23:17lodin-justin_smith: I'd doseq instead.
23:17lodin-Yeah.
23:17felipedvorakhmm
23:17justin_smithfelipedvorak: what are you actually trying to do?
23:17lodin-But using range with doseq or what-not only works if you don't plan to change i in the loop.
23:18felipedvorakget as input a number and use it as a list to check each number for a condition
23:19felipedvorakalso known as project euler problem 1 hehe
23:19justin_smithfelipedvorak: what happens to the numbers you check?
23:19justin_smithdo you return some of them?
23:19justin_smithdo you print them?
23:19felipedvorakyeah
23:19felipedvorakif a number is multiple of 3 or 5
23:20justin_smithyeah, use doseq with a print inside
23:20lodin-I'd first filter and then doseq over the ones I want to print.
23:20felipedvorakmy prowess is still very basic, I still don't know doseq
23:20felipedvoraklet me check it
23:21justin_smith,(doseq [i (range 10)] (println i))
23:21clojurebot0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n
23:21felipedvorakin the end you must output the sum of the numbers
23:21justin_smithahh, so you need to keep track and sum, you'll want more than just doseq for that yeah
23:21felipedvorak^ what is this output?
23:21lodin-felipedvorak: Then let me point you towards reduce.
23:22lodin-felipedvorak: You can use a combination of reduce, filter, and range.
23:22justin_smithyeah, that's probably the best bet
23:23felipedvoraki'll try that, thanks
23:25lodin-felipedvorak: The "easy" solution if you are used to using loops is to use loop/recur, but resist the temptation. :-)
23:25felipedvorakwouldn't reduce be even easier?
23:25justin_smithfelipedvorak: simpler vs. more familiar
23:25lodin-felipedvorak: Simple vs easy. ;-)
23:26felipedvorakI'm really looking for the hard but still "clojury" solution hehe
23:26kavkazNot 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:27justin_smithkavkaz: ispell comes with emacs, flyspell-mode is a nice way to use it
23:31kavkazjustin_smith: Ah cool, thanks