#clojure logs

2016-04-14

00:28zvI've read a bit about clojure -> android and I understand it's limitations, but I've never heard anyone express an opinion on the *future* of such an enterprise.
00:29zvCould clojure apps on android achieve parity in any sensible future universe?
00:35TEttingerzv, I think so, but via clojurescript in particular. in one benchmark on early Android phones people found V8 (Chrome's JS engine also used on Android) was outperforming Dalvik quite abit
00:36scottjzv: parity with java apps in startup time?
00:36scottjzv: idk details, but I think there are some areas dalvik wasn't very optimized for aspects of clojure, perhaps the Android N switch to openjdk might help a tiny bit
00:37scottjs/tiny bit/somewhat
00:38scottjzv: btw you've seen Skummet right?
00:38zvI have
03:17pythysHello everyone. Complete noob here with some basic questions. Thank you in advance for your help.
03:17pythysGiven the lack of domain objects in a functional language, how do you model the domain in clojure? or do you just access the database?
03:23ben_vulpespythys: what do you mean "lack of domain objects"?
03:24ben_vulpesthere are various OOP-sy things in clojure like records and protocols
03:24ben_vulpesone can also model "the domain" if i understand you correctly with simple, named data structures.
03:24ben_vulpesthere's also stuff like plumatic/schema for stronger typing.
03:25egli``pythys: the book clojure applied deals with exact this issue
03:25pythysben_vulpes: Ahh, so you replace objects with data structures
03:25egli``https://pragprog.com/book/vmclojeco/clojure-applied
03:25egli``I can highly recommend it. Maybe not a total beginner book though
03:26ben_vulpespythys: in the immortal words of swizz beats
03:26ben_vulpes"i got a million ways to get it"
03:26ben_vulpes"choose one"
03:26pythysben_vulpes: yeah, I'm overwhelmed by choice
03:26pythysthat's why I'm trying to make sense of things in here
03:26ben_vulpesglhf
03:27ben_vulpesi typically start with functions that take args and abstract lazily
03:27ben_vulpesplumatic's schema can be nice in that it provides types for "well it's a string but it's a specific /kind/ of string"
03:27pythysI see
03:28pythysand for complex domains, you just make data structures with data structures inside them
03:28pythysbut then how do people make sense of your domain? How do you communicate the design?
03:29pythysFor example, If I have a complex object with a builder inside of it, then everyone understands it
03:29ben_vulpesno, no they don't.
03:29pythysbut If I declare a map, with some vectors and other maps inside, wouldn't that be confusing?
03:29pythysoh, sorry, please elaborate
03:29ben_vulpesoop people labor under the delusion that the abstractions are inherently more understandable
03:30ben_vulpesfundamentally, it's a communication problem that doesn't get solved with code.
03:30pythysben_vulpes: I see, so it's raw data structures all the way?
03:30ben_vulpesit's clear code and well-chosen abstractions all the way.
03:30ben_vulpesno one right solution or design methodology.
03:30ben_vulpeslife is ambiguous and hard like that.
03:31TEttingeryeah, clojure has some really really good tools for working with data
03:31ben_vulpesi get rather a lot of mileage out of simple functions that do one thing, with well-named arguments.
03:31pythysben_vulpes: ok. So do you communicate the design through the names of the data structures? do you document? how do you convey what is it that your domain is about?
03:32ben_vulpestests are nearly imperative, given the paucity of compile-time enforcement.
03:32pythysexcuse me for the noob questions, but I come from a domain driven design frame of mind, trying to shift
03:32ben_vulpespyths for example
03:32ben_vulpes(defn create-ddb-table [client-id] ... )
03:32ben_vulpescreates a dynamo db table
03:32ben_vulpesand takes a client id
03:32TEttingerstuff like destructuring is much more handy than it seems on the surface, especially when the code is open source and people are expecting to read it
03:33TEttinger(or open within an organization)
03:33ben_vulpesyeah destructuring is neat as well, complemented with, say schema.
03:35TEttinger,(def complex-data ["this is a vector" "the next element can be something other than a string" 10 "then some nesting" [1 2 3]]) ; destructuring this in the next line
03:35clojurebot#'sandbox/complex-data
03:36ben_vulpespythys: i don't really have any experience with "domain driven design", so i might not understand your background well enough to answer your questions.
03:37pythysI see, so naming sub-structures through destructuring would achieve a sort of design by naming conventions I think
03:37TEttinger,(let [[_ not-concerned num-we-like nah [x y z]] complex-data] (* num-we-like (+ x y z)))
03:37clojurebot60
03:37TEttingeryeah, even though there were no names inthe complex-data vector...
03:37TEttingerit isn't hard to provide context where it's used
03:37pythysben_vulpes: that's just a fancy word for designing the domain through a class structure (you know .. Person, Employee, Account, Order etc ...)
03:38ben_vulpespythys: https://github.com/plumatic/schema << the schema i keep nattering around
03:38TEttingermaps have names that typically matter more
03:39ben_vulpespythys: also dig http://clojure.org/reference/datatypes
03:40ben_vulpesand here are your class methods, if i might be so rude as to call them that: http://clojure.org/reference/protocols
03:40ben_vulpesif you squint it kinda looks like clos
03:40TEttingerheh, protocols aren't super commonly necessary, but I think they can be handy in the same cases where domain driven design would be useful
03:40ben_vulpeswithout the dooooope dispatch system
03:41TEttingeryeah, CLOS is kinda crazy
03:41TEttingerin a good way,mostly
03:41ben_vulpesdude clos broke me of ever wanting to work with modern OOP ever again
03:41TEttingerI've struggled to wrap my head around some code using it
03:42ben_vulpesthe "HOLY SHIT THIS IS SO RIGHT" moments i had...
03:42pythysokay, this is starting to make sense. Clojure has a sort of much more loose type system
03:42ben_vulpesheh
03:42ben_vulpesloose
03:42TEttingeryeah, most lisps are pretty much non-typed; clojure has type hints but they're really just suggestions for the compiler, not enforcements
03:43ben_vulpesTEttinger: i found cl with the sbcl compiler to be exquisitely well typed
03:44ben_vulpesin that if i bothered to provide type declarations as to what my functions accepted and what they returned (from their various return points, yes it handled that), it would go so far as to refuse to load code that had incorrect funcalls in it.
03:44ben_vulpesbut no, no Hindley Milner as far as i could tell.
03:45TEttingerlike in clojure you could type hint an argument to an fn as being a String, and give it a number, and it will compile but maybe act in a way you didn't expect from a String (it could throw an exception if you call .charAt on it). Typed Clojure and I believe Schema both provide validation for arguments I think
03:45TEttingerin different ways, I haven't used either
03:45ben_vulpesat one particularly memorable moment, i declared that a function would only ever receive a string and was politely informed that the web server would be calling it with a null value and i should provide for that.
03:45TEttingernice
03:45ben_vulpesglorious
03:45TEttingerisn't SBCL's compiler also rather slow (I suppose like lein could be)
03:46ben_vulpesi dont really write performance-oriented code, or big cl projects
03:46pythysThank you everyone for the reference links and tips. Much appreciated
03:46ben_vulpesand i can asdf:load-project fast enough that it's not a concern on the things i've built
03:46ben_vulpeslater, pythys
03:46TEttingerI do recall a Standard ML compiler that took 10 minutes to compile hello world. whole program optimization
03:47ben_vulpesmyeah
03:47ben_vulpesoptimization's not my bag
03:47ben_vulpesaugmenting my intelligence, though...
03:47TEttingerit was a pretty odd thing for it to do
03:47ben_vulpesi have occupied so many cycles the past two weeks manually ensuring that my java-in-clojure was written correctly because the clojure compiler doesn't, and i don't care to wait for runtime explosions.
03:48ben_vulpesjust because i *can* do this does not mean that i think it a good use of my mind.
03:48ben_vulpesgimme squigglies, yo.
03:49TEttingeris ~ used in CLOS? I can't really remember
03:49ben_vulpeshaha no, i mean under the text in my editor
03:50TEttingerI mean I see a ~ now and the first thing I think is "oh, unary bitwise negation operator". the second thing I think is "man, using ~~ to coerce to number in JS is silly"
03:50ben_vulpesno no no
03:50ben_vulpesmistakes in code that the compiler can catch and relay to the editor for displaying to my dumb self
03:50TEttingerheh yes
03:51ben_vulpesbleee unary bitwise negation operator
03:51TEttinger,(bit-not -2)
03:51clojurebot1
03:54ben_vulpes,(defn lol [da-str] (format "z%s"))
03:54clojurebot#'sandbox/lol
03:54ben_vulpeslike come onnnnnnnn
03:54ben_vulpes(lol "hi")
03:54ben_vulpes,(lol "hi")
03:54clojurebot#error {\n :cause "Format specifier 's'"\n :via\n [{:type java.util.MissingFormatArgumentException\n :message "Format specifier 's'"\n :at [java.util.Formatter format "Formatter.java" 2487]}]\n :trace\n [[java.util.Formatter format "Formatter.java" 2487]\n [java.util.Formatter format "Formatter.java" 2423]\n [java.lang.String format "String.java" 2790]\n [clojure.core$format invokeStatic "c...
03:54ben_vulpesanyways.
03:55ben_vulpesfwiw clojure's a better tool for most jobs that come my way than anything else.
03:55ben_vulpes"a gun to fire today"
03:55ben_vulpes"the army we have today"
03:55ben_vulpesor what was it
03:55TEttinger,(defn lol [da-str] (format "z%s" da-str))
03:55clojurebot#'sandbox/lol
03:55TEttinger,(lol "yay")
03:55clojurebot"zyay"
03:55ben_vulpesno i know!
03:56TEttingerwas it the compile error thing?
03:56ben_vulpesruntime error
03:56TEttingerah ok
03:56TEttingerI mean you wanted a compile error
03:56ben_vulpesmhm.
03:57ben_vulpesnow i have to go trash a bunch of aws resources by hand.
03:58ben_vulpeswhich is fine, i wrote this thing. but imagine the hurt the poor sod i'm going to foist this codebase will be in for when this nearly-purely-side-effecting-codebase needs tweaking on.
04:19ben_vulpeswhaddaya know, there were only three!
04:19ben_vulpesone of which was apparently a race condition in the consumed api.
04:55jonathanjIs it possible to change where the .m2 cache directory is created and searched?
04:55jonathanjIn particular when running lein tasks.
05:11winkyou could always just symlink it before running
05:12Russell-I just tried running 'lein check' for the first time, and got a bunch of reflection warnings about calls to Java methods like substring. What am I doing wrong?
07:43asdf12z_the parens have me tripping balls in clojure heh
08:06ben_vulpesturned on rainbow-delimeters-mode, did we?
09:59someone1hi
10:00someone1is there a ring channel?
10:11ben_vulpesyou're in it
10:14rcassidyasdf12z_: rainbow parens plugin for your editor :)
10:23someone1does jvm class updating work with clojure?
10:34russellwIs there a built-in function or idiom for 'save this value for a moment, do something else, then return the saved value'? It can be done with let, of course, just wondering whether there's some shorter idiom
10:37hyPiRionrussellw: Closest I know about is doto, don't think there's anything equivalent to common lisp's prog1
10:38russellwhyPiRion, doto looks interesting anyway, thanks
11:02russellwIs there a way to write a literal symbol with a non-standard name, e.g. the equivalent of |0| in other dialects of Lisp? Or do you just have to write (symbol "0")?
11:23rplacarussellw: I've missed prog1 too. It's a trivial macro to write, but I usually just go with (let [foo first-expr] other-exprs... foo)
11:23russellwrplaca, fair enough
11:47justin_smithyay, clojure/west
11:48justin_smith:b2
11:52justin_smithrussellw: we don't tend to use them, but I think (symbol "0") is the best you can do
11:55doriani need an idiot check: foo and (not (nil? foo)) are identical semantics yes?
11:55dorianer at least in the context of a predicate test
11:56dorianeg (when foo (...))
11:59ToxicFrog,(let [foo nil] (if foo "truthy" "falsy"))
11:59clojurebot"falsy"
11:59ToxicFrog,(let [foo false] (if foo "truthy" "falsy"))
11:59clojurebot"falsy"
12:00ToxicFrog,(let [foo false] (if (not (nil? foo)) "truthy" "falsy"))
12:00clojurebot"truthy"
12:00ToxicFrogdorian: not identical; see above
12:00ToxicFrogIn particular, false is boolean-false but is not nil?
12:01dorianah right i guess i was thinking in the context of things that return either some data object or nil
12:01dorianbut yeah good point
12:16rplacaon my way from SF - see everyone at Clojure/West!
12:27russellwjustin_smith, okay, thanks
12:31dorianby chance is the author of pantomime in here?
12:41sdegutisGood day.
12:41sdegutis,(symbol "0")
12:41clojurebot0
12:42Glenjamin,'0
12:42clojurebot0
12:42Glenjamin,(type '0)
12:42clojurebotjava.lang.Long
12:43sdegutisHello.
12:43sdegutis,(type (symbol "0"))
12:43clojurebotclojure.lang.Symbol
12:43sdegutisWhere can you buy real life Jedi clothing, which are comfortable, and will not wear down quickly like a costume?
12:45russellwI'm still trying to make sense of the output of 'lein check' - it's mostly reflection warnings about how it can't resolve method calls, even static methods on java.lang.Character - that's always available at compile time, right? And I've tried putting in require's for things like java.io and it makes no difference.
12:45russellwI'm kind of at a loss for things to try - what does everyone else do? Just not use 'lein check' or is there a trick I'm missing?
12:46sdegutisrussellw: I just use cider and enable the reflection warning global var in project.clj and that's sufficient for me.
12:46sdegutisrussellw: this way, whenever I do something that reflects poorly, cider highlights it in yellow for me when I eval it
12:47sdegutisI mean when I eval/define the function it's in.
12:47sdegutisWorks 100% great so far.
12:47Glenjaminrussellw: when doing java interop clojure has to use reflection to evaluate unless you add type hints
12:47sdegutisYeah then I just add ^String or whatever.
12:47russellwGlenjamin, type hints! That sounds like the thing I'm missing
12:47russellwI imagine that should improve performance?
12:47Glenjaminyeah, reflection is slow
12:48Glenjamin,(let [a "123"] (pr (.isEmpty a))) ; should emit a warning
12:48clojurebotfalse
12:48sdegutisyeah use cider
12:48russellwah, I see the syntax now
12:49russellwI should probably try timing tests before and after to see if it did improve performance
12:49Glenjaminyou can also set *warn-on-reflection* to true in the leiningen project
12:50russellwWhat will that do, the equivalent of lein check when I type lein run?
12:50Glenjaminyeah
12:50russellwMakes sense, thanks
12:52russellwThe documentation gives the type hint syntax for function names and local variables, how do you specify type hints for global variables?
12:57ak5hi, I have been using ring recently and it seems sooo much saner than the stuff I am used to. I am new to jvm based stacks for the web though - can someone link me to the definite resource for hosting stuff? I usually run some scripting language behind nginx... thanks!
12:58russellwOh, seems to be the same, just put the type before the name
13:05mgaare_ak5: there's not a definitive guide per se, however the convention is to have the app run its own web server that binds on an internal-facing interface, and use nginx/apache/some other dedicated web server as a reverse proxy
13:06mgaareak5: good options for the app web server include jetty, httpkit, immutant
13:11sdegutisI use jetty because it's included by "ring/ring"
13:24russellwOkay, I've cleared most of the reflection warnings. One I'm still puzzled by is http://pastebin.com/ZjYKTXpM line 2, the call to getProperty - anyone know what type hint would clear that one?
13:40{blake}Is there a split-with that works as a comlpement to filter/remove? (As opposed to "take-while"/"drop-while"?)
13:43@amalloysplit-at
13:44tolstoyOh, cool. If you just "extend-protocol" your records, instead of having them directly implement a protocol, you can change implementation functions, send them to the repl, and they change without having to reload all the code.
13:44@amalloyer
13:44{blake}wut?
13:44@amalloyi guess i don't understand. split-with is the answer to your question
13:44@amalloybut you used split-with as part of your question
13:44{blake}heh
13:45@amalloyno, i'm just bleary in the morning i think
13:45{blake},(split-with (fn[[k v]] (#{\a \b \c \d} (first k))) {"apple" 1 "banana" 2 "eggplant" 3 "grape" 4})
13:45@amalloythere isn't. it's just (juxt filter remove)
13:45clojurebot[(["apple" 1] ["banana" 2]) (["eggplant" 3] ["grape" 4])]
13:45{blake}oh, juxt will do...once again had forgotten it.
13:45{blake}tx
14:01rasmustoI'm a common lisp newbie, how do I use destructuring-bind so it takes care of nested lists like clojure's vector destructuring? (or should I direct this at a different channel?)
14:05rasmustooh maybe its the same, nvm :p
14:13amashiThree used to be a pretty active cl irc channel- been quite a while since I have lurked there, so I don;t know how healthy it is these days. But between http://www.gigamonkeys.com/book/beyond-lists-other-uses-for-cons-cells.html (scroll to the bottom) http://asymmetrical-view.com/2008/09/18/destructuring-bind.html and http://clhs.lisp.se/Body/03_de.htm it should be pretty much covered.
14:18rasmustoamashi: sweet, thanks. I was going in circles on the clhs.lisp.se docs and not finding anything :P
14:18rasmustothere's like one trivial example on the actual destructuring-bind page
15:10hyperhopperI'm calling a function that takes 2 arguments
15:10hyperhopperand passing 2 arguments
15:10hyperhopperbut getting an ArityException for only passing one argument
15:11hyperhopperhere is the call: (histogram-distance h (histogram "./input/coast_test2.jpg"))
15:11hyperhopperwhat could I be doing wrong?
15:11hyperhopperAlso happens with (histogram-distance h h)
15:12ridcullyare you recuring etc on itself with wrong arity?
15:13ridcullycould you share the code and the error on some copy-and-paste-site?
15:19hyperhoppersure
15:19hyperhopperand no im not doing recursion
15:20{blake}hyperhopper: Is the error for histogram, and nto histogram-distance?
15:20{blake}er, not
15:20@amalloywe'll find out once we have a stacktrace
15:20hyperhopperThe error is for histogram-distance
15:20hyperhopperone sec lemme upload it
15:21hyperhopperThe code
15:21hyperhopperhttp://pastebin.com/jLW4RjQa
15:23hyperhopperclassifier.core=> (histogram-distance h h) ArityException Wrong number of args (1) passed to: core/histogram-distance/fn--485 clojure.lang.AFn.throwArity (AFn.java:429 )
15:23@amalloyi bet either line 32 or line 33 returns an empty seq
15:23hyperhopperIt doesnt
15:23hyperhopperI can create histograms fine
15:23@amalloynm
15:23@amalloyyour lambda in (defn histogram-distance gets too few args
15:27hyperhopperoh you're right, thanks!
15:28hyperhopperwhats would be the cleanest way to do what I'm trying to do in clojure?
15:28hyperhopperI zip and map
15:28hyperhopperbut If I zip and map like that then I have to deconstruct the zipped list
15:30ridcullycan't you just put that anon fn instead the list and get rid of the outer map?
15:36hyperhopperridcully: probably but I dont understand how clojure map works with more than 2 arguments yet
15:36hyperhopperThis is like the first time using clojure
15:36ridcully,(map vector (range 3) (range))
15:37clojurebot([0 0] [1 1] [2 2])
15:41hyperhopperthats super convenient
16:15hyperhopperIn what case could (min-key) return the entire array passed to it?
16:16hyperhopperI'm manually verifying that the function returns ints for the values in the array
16:19hiredmanread the docs for min-key
16:19hiredman,(doc min-key)
16:19clojurebot"([k x] [k x y] [k x y & more]); Returns the x for which (k x), a number, is least."
16:24hyperhopperMy mistake I was passing a list
16:24hyperhopperis apply extremely common in clojure? I seem to be using it a lot. Is this bad style?
16:26arcatanit is quite common