#clojure logs

2017-02-22

11:06Ardxwhat does the @ symbol mean in macros?
11:11winkthat feeling when you read such a question and first have to check what language channel you're in. :P
11:11mavbozo@ is a shorthand for deref function
11:12Ardxhow is it different from ~
11:12Ardx?
11:12mavbozois the @ symbol you see has ~ in front of it?
11:12mavbozolike ~@
11:12Ardxwell I'm trying to use it
11:13Ardx~@ seems to make it worse :D
11:13clojurebotGabh mo leithscéal?
11:13mavbozo~please listen clojurebot
11:13clojurebotExcuse me?
11:14mavbozo,(def three-and-four (list 3 4))
11:14clojurebot#error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval3$fn__4$fn__17 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval3$fn__4$fn__17 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval3$fn__4 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval3 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval3 invoke "NO_SOURCE_FIL...
11:14mavbozo,(def a 1)
11:14clojurebot#error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval29$fn__30$fn__43 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval29$fn__30$fn__43 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval29$fn__30 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval29 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval29 invoke "NO_SO...
11:14mavbozo~aaargh
11:14clojurebotGabh mo leithscéal?
11:16Ardxmavbozo this is my code http://pastebin.com/tUKyrd8a
11:16Ardxsee it produces nil a lot
11:16mavbozo,(let [tf (list 3 4)] `(1 ~@tf))
11:16clojurebot(1 3 4)
11:17mavbozothe ~@ unquote-splicing removes the parentheses from a list
11:17mavbozo,(let [tf (list 3 4)] `(1 ~tf))
11:17clojurebot(1 (3 4))
11:18Ardxah ok dont think that helps then
11:25ArdxHmm are macros expanded before defs are initialised?
11:25Ardxthat would explain why I get nil, as what I pass in is empty
11:38Ardx,(= 2 3)
11:38clojurebotfalse
11:38Ardxhmm how do I actually set values in clojure
11:46mavbozoArdx, in a namespace you can bind value to a var using def
11:46mavbozo,(def x 1)
11:46clojurebot#error {\n :cause "SANBOX DENIED"\n :via\n [{:type java.lang.Exception\n :message "SANBOX DENIED"\n :at [clojure.core$eval31$fn__32$fn__45 invoke "NO_SOURCE_FILE" -1]}]\n :trace\n [[clojure.core$eval31$fn__32$fn__45 invoke "NO_SOURCE_FILE" -1]\n [clojure.core$eval31$fn__32 invoke "NO_SOURCE_FILE" 0]\n [clojure.core$eval31 invokeStatic "NO_SOURCE_FILE" 0]\n [clojure.core$eval31 invoke "NO_SO...
11:46mavbozo~darn
11:46clojurebotNo entiendo
11:47ArdxYeah I may as well figure out the clojure fnctional way of doing it though
11:48scriptorArdx: you use (let) for local bindings, but try to think in terms of transformations and flows of data
11:48scriptorrather than setting values at each step
12:05osfabibisiArdx: do you need a macro?
12:06osfabibisiif you are both trying to single-step through because it's complicated *and* asking about the syntax, then you may be biting off more than you can chew? ;-P
12:06osfabibisi(I feel I can say this, because I was doing exactly the same thing a month ago...)
12:15ArdxYeah I started clojure yesterday
12:16ArdxBut I fixed the macro now
12:17ArdxNow I'm just wondering, if I have a tree structure of hashmap, and I update a leaf node, how do I then add that lea node back onto the tee?
12:18ArdxBecause it's all immutable, I can't just update one value. I guess I have to go back up the chain and recrate every hashmap along the way
12:18technomancyyou would use update-in
12:19technomancy,(update-in {:a {:b [45 88 {:c 5}]}} [:a :b 2 :c] inc)
12:20clojurebot{:a {:b [45 88 {:c 6}]}}
12:20Ardxhmmm
12:23Ardxthat would update any :a :b :c it finds though
12:23technomancyno, the second arg is a linear path to follow
12:24Ardxahh
12:24technomancy,(update-in {:a {:b [45 88 {:c 5}]}} [:b 2 :c] inc)
12:24clojurebot#error {\n :cause nil\n :via\n [{:type java.lang.NullPointerException\n :message nil\n :at [clojure.lang.Numbers ops "Numbers.java" 1013]}]\n :trace\n [[clojure.lang.Numbers ops "Numbers.java" 1013]\n [clojure.lang.Numbers inc "Numbers.java" 112]\n [clojure.core$inc invokeStatic "core.clj" 919]\n [clojure.core$inc invoke "core.clj" 914]\n [clojure.lang.AFn applyToHelper "AFn.java" 154]\n ...
12:24osfabibisior you can use zippers
12:24technomancyosfabibisi: hush you; he's on his second day
12:24osfabibisitechnomancy: then he shouldn't be playing with macros :D
12:24technomancytrue
12:24Ardx\o/
12:25justin_smithmacros are for absolute beginners (so you know what they hell they are about) and for people of advanced expertise who are redefining the language in their code, in between you'll rarely need macros
12:26osfabibisijustin_smith: ooo, good point ;-)
12:26justin_smithI'm barely at the point where making my own macros is a good idea myself
12:26technomancyday 2 of learning clojure: write three macros, understand how they work, and throw them immediately away
12:26justin_smithright
12:27justin_smiththere's an optional "make a semi useful lib and fill it with domain specific macros with a cute syntax" - just skip that idea and throw it away
12:28osfabibisi;-)
12:29osfabibisione day, there will be a `git diff` that isn't rendered crazy by the reordering of functions...
12:29justin_smithosfabibisi: it's possible to make diff plugins for git that are smarter about individual languages
12:30osfabibisijustin_smith: is there one for clojure that you can recommend?
12:30justin_smithit would be cool to make a diff plugin for clojure using planck (since it starts up fast and knows about clojure syntax...)
12:30justin_smithosfabibisi: not that I know of, but I think it would be an awesome idea
12:30justin_smithdiffing by form/sexp rather than line...
12:30osfabibisithat said, diffing by sexp isn't my problem here
12:31osfabibisiit's 2 forms changing order e.g. (defn foo ......) (defn bar ......) getting swapped around
12:31osfabibisiwhich always results in one hunk being deleted from origin point and added to new point, because diff algos only work on things as sequences
12:32justin_smithosfabibisi: that's what I mean, if it was looking at balanced forms / subforms, it would know not to do weird splitting in the middle like that
12:32justin_smithit's diffing by line, which gives the weirdness
12:32osfabibisino no, I've explained badly, sorry
12:33osfabibisie.g. the definition of (defn foo ...) moves from line 15 to line 100
12:33justin_smithosfabibisi: I think we just disagree about why git is misbehaving
12:33justin_smithI know the behavior
12:33osfabibisithe forms are still balanced
12:33amalloyi think osfabibisi is complaining about even more benign behavior than you're thinking of
12:42osfabibisiyes, I think I understand what justin_smith is talking about - when 2 forms share common features
12:43osfabibisibut in this case they're not incorrectly misidentified, they've just moved
12:45amalloythere's not really a lot you can do about that in the unix diff model, since it's line based. there are sexp-based diff tools out there, though i don't know how good they are or whether you can get them involved in git diff at all
12:45Ardxso if I have a tree, made of hash maps, and then I have a list [:area :top], is there a function that does something like (get-leaf root-map [:area :top]), and iterates that list and goes down through the tree?
12:47amalloyactually i bet you could configure diff.tool to point to a shell script that launches your sexp differ for .clj files and a standard diff otherwise
12:47Ardxor I could use a macro to turn it into "(-> :area :top)" I guess
12:47amalloy(doc get-in)
12:47clojurebot"([m ks] [m ks not-found]); Returns the value in a nested associative structure, where ks is a sequence of keys. Returns nil if the key is not present, or the not-found value if supplied."
12:47osfabibisiprobably. but again if it's sequence-based that won't really help for this case
12:47osfabibisiinstead, I'm just going to give colleagues a hard time about their commit being impossible to review :D
12:47Ardxamalloy cheers!
13:04justin_smithamalloy: yeah- a sexp based diff for sexp languages was kind of what I had in mind
13:55osfameronwhat's the minimum I need to do to set a classpath in a boot repl?
13:55osfamerone.g. I have a project template I know works, if I have src/project/foo.repl and a namespace project.foo
13:56osfameronand a boot.build and so on
13:56osfameronbut if I just want to edit scratch.clj to play around then my editor complains " Could not locate scratch/scratch__init.class or scratch/s
13:56osfameroncratch.clj on classpath"
14:05justin_smithosfameron: for super basic stuff I just use load-file
14:05justin_smitheg. $ vim /tmp/scratch.clj then (load-file "/tmp/scratch.clj")
14:05justin_smithI leave require and such for things that are defined parts of my project
14:06justin_smith(I did find the annoying fact that I can't do macros in planck this way - it only allows macros via classpath... but that's the only hiccup I've had for this workflow)
14:07osfameronjustin_smith: you mean from the repl itself?
14:07osfameronah yes, that works
14:08osfameronand then fireplace stops complaining
14:08osfameronta
14:08justin_smithosfameron: yes, I call load-file from the repl - though most editors with clojure integration have a simple keypress that invokes load-file
14:09osfameronfireplace has the odd thing that it's supposed to be namespace aware, but it can't seem to resolve the location of a file it actually has open...
14:09osfameronit all works with a properly set up project of course
14:10justin_smithaha - I use fireplace but only in a very rudimentary way - I think I just assumed that rando .clj file would not play nicely so I should use blunt tools like load-file
14:10justin_smithbut that was based on hunches, not expertise
14:11osfameronif you open a project with a proper boot (or I imagine leiningen) setup, then everything Just Works
14:11justin_smithyeah, all my work since I started using fireplace is in a library that doesn't have its own repl / process, so I have not been so lucky
14:12osfameronand you can't use clojure's builtin repl?
14:12justin_smithosfameron: I have an app, the app runs from two repls, this library is used by each of the repl based apps
14:12justin_smithpoint being that the code I am editing is not on the classpath of either repl - they are using the version that was put in cache by lein install
14:13osfameronah. sounds complicated
14:13justin_smithand I refuse to muck with the whole symlink nonsense
14:13justin_smithosfameron: it would be super complicated if I tried to have convenient tooling, but all I need is a repl plus load-file and things work
14:14osfameron:D
14:14justin_smitheg. there are two different repls that both want the new version of foo.clj - doing this via the editor would be silly
14:16justin_smithsince editor tooling that allows multiple repls wants to map a file to a single repl in my experience
14:22Ardxended up using assoc-in
14:22Ardxand an atom for the tree root :D
14:23Ardxand turned the macro into a function, so I could actually step throguh and debug the many problems the code had
14:23Ardxgod dang are clojure errors cryptic though
14:24justin_smithArdx: a good design strategy is to use a function for all your logic, and if you need a custom syntax, make a minimal macro where the function is doing the real work
14:24justin_smithI think you've learned already how much easier that is to debug (also if you need to build more functionality, a function is a much easier starting point than a macro usually)
14:25machinewardo you think clojure.spec would be good solution for masking data? pretty much need to restore data from one db to another, but obfuscate some of the data (but it needs to still resemble valid data)
14:25machinewarso I'm thinking you could for example describe the shape of a postal code, a first name, last name, etc
14:25machinewarand use it at runtime to generate fake data
14:25justin_smiththat doesn't sound like what spec is for at all...
14:25justin_smithI mean I guess it plugs into generators for testing purposes...
14:26machinewaryea that's what I'm thinking
14:26Ardxjustin_smith yeah keeping macros small sounds like a good plan
14:27justin_smithArdx: of course there's special cases like core.match and core.async which build whole languages (very useful languages!) that can't just be summed up with a bunch of functions, but those are very special
15:46justin_smithwhy would a ref have a name?
15:47dysfundid you call name on it?
15:47osfameronhmm, maybe I don't mean refs then? "stuff that you've def'd" ?
15:47dysfunvars!
15:47justin_smithvars?
15:47osfamerondysfun: yes!
15:47clojurebotvars are a linking construct
15:47dysfunvars are not refs
15:47osfameronright, so vars then.
15:47osfameronthey have names don't they?
15:48justin_smith,(:name (meta #'+))
15:48clojurebot+
15:48osfameronthat doesn't seem to work for things I've def'd or defn'd myself though
15:49justin_smithdef and defn both attach :name
15:49justin_smith(as a metadata)
15:49osfameronah, I missed the #' bit... what does that do?
15:50justin_smithaccesses the var
15:50justin_smith+ points to the function pointed at by the var
15:50osfameronah... instead of the value?
15:50justin_smith#'+ gets the var itself
15:50osfameronok
15:50amalloyosfameron: imagine (def x 1)
15:50amalloyyou want x to eval to 1, not to a var
15:50justin_smith,#'+
15:50clojurebot#'clojure.core/+
15:50justin_smitherr
15:50justin_smith,'#'+
15:50clojurebot(var +)
15:50amalloybut sometimes, you want to get at the var anyway, and that's what #'x does
15:50osfameronok
15:51justin_smith#' is a reader macro, shorthand for (var )
15:51amalloythe name can't be stored on the value 1, and is instead stored on the var
15:51osfameronso why doesn't (name #'+) work?
15:51justin_smithwell that's a more controversial decision
15:51amalloyso, name is for getting the "name" part of a name+namespace pair thingy
15:51justin_smithbut regardless of reasons, at least the :name key on the metadata will help
15:51osfamerontrue
15:51osfameronthanks!
15:51amalloyand a var is not one of those; it is a lot more things than just a name
15:52osfameronah
15:52dysfuna var *has* a named thing, but it isn't one
15:52amalloy,(keys (meta #'inc))
15:52clojurebot(:arglists :doc :inline :added :line ...)
15:53osfameronwell, that was all so exciting, I've now forgotten why I thought I wanted to call (name) on a var in the first place...
15:56justin_smithosfameron: my assumptions is shenanigans of some sort
15:56justin_smithosfameron: consider that given a symbol, you can get a var and a name from it
15:56justin_smith,((juxt name resolve) '+)
15:56clojurebot["+" #'clojure.core/+]
15:56justin_smithmaybe that's what you wanted? resolve is good for shenanigans
15:56amalloya symbol and a namespace
15:57justin_smithamalloy: well, symbols can be namespaced, and resolve will use your namespace's lookup rules to find a namespace
15:57amalloyyes, "your namespace" is the namespace here that you need
15:58amalloycalling resolve at runtime outside of a repl without specifying a namespace is going to give you trouble
15:58justin_smithright, because your thing likely isn't available by any shorthand in user
15:58osfameronjustin_smith: ooo, thanks
15:59amalloy(because *ns* is bound to the current namespace while in a repl, but it's not when running an actual program via -main)
15:59justin_smithamalloy: in my experience it's always bound to user, unless someone made some effort to switch it
15:59justin_smithI've never seen it unbound
16:00amalloywhat i mean is, it's not bound to any useful value that you might think of as "the current namespace"
16:00justin_smithfair
16:01technomancydoesn't resolve DTRT when passed a qualified symbol?
16:01osfameronif I want to go the other way - e.g. I have a map of {name function, ...} what's the best way to get those defn'd together?
16:01justin_smithtechnomancy: if it's fully qualified, yes
16:01technomancyoh justin said that already
16:01justin_smithosfameron: intern
16:02justin_smithosfameron: the tricky part is that intern doesn't add the nice metadata that def/defn do
16:02justin_smithin my experience intern is a good sign you are being too clever for your own good (moreso than resolve is even)
16:03osfameronyes, probably
16:03osfameronit's quite a common ask in e.g. Perl though
16:03justin_smithosfameron: consider that looking something up in a hashmap and calling it is perfectly acceptable
16:03osfameronwhere you can define exporters custom exporters for functions
16:03justin_smithsure, and perl is known for tricky business as a common programming style, right?
16:04justin_smithI'm not saying intern is never valid, just that it indicates you are likely adding complexity, which is a good moment to ask what you are getting in return for that cost
16:04osfameronwell, that's part of doing hard work *behind the scenes* to get a nice API for the user of a library
16:04osfameronbut yes, point taken, and I'll see if I can avoid it :D
16:05justin_smithosfameron: but clojure is a very introspective and reflective language, and libraries that make it hard to find definitions or map definitions back to some form are really annoying
16:05osfameronis that a problem if I set the metadata politely?
16:05justin_smithwe have a lot of tools to find the code that generated a thing, but tricks like intern undermine them
16:06justin_smithosfameron: hmm, I wonder how hard it would be to set the right file/line metadata automatically...
16:07osfameronso the thing I'm thinking about is a logging library
16:08osfameron(info "hello") might write to stdout or it might send a message to a queue or whatever
16:08osfameronand I want to avoid a singleton global
16:08osfameron(info my-logger "hello") is ok, and doesn't need any cleverness
16:09justin_smithaside - (but don't most clients of logging libraries expect a global behavior?)
16:11osfameronhmm, maybe?
16:11osfameronI think dysfun mentioned that being something he didn't like about timbre
16:12osfameronand it chimed with whatever I was thinking
16:12osfameronanyway, you could always (info *global-logger* "hello") if you wanted it :D
16:12justin_smithI don't fully agree, but I've seen it argued that logging config should be global and static and hard to modify dynamically because security
16:13osfameronstatic sure, but why does global help there?
16:14osfameronI kinda understand why people want the dynamic behaviour, but I've found that confusing far more often than actually useful
16:16justin_smithI guess less complexity means less possibility for corner cases or unexpected combinations of behaviors
16:16justin_smithit wasn't my argument so I'm not sure :)
16:17justin_smithI mean, once someone can change a var in my clojure program, that machine is hosed, messing with logging is the least of it
16:20jonathanjWhere do you get the logger from that you want to log to?
16:23jonathanjIs it okay if your library uses a different logger than the user calling your library?
16:24jonathanjIt seems (but perhaps I don't fully understand) like it would be annoying if a library logged stuff somewhere else when I don't want it to.
16:28justin_smithjonathanj: I don't really get logging but/and I find "annoying" a good description for all my interactions with things related to logging
16:29jonathanjI'm probing because I'm on the brink of porting a logger library to Clojure and I'd like a nice API.
16:30osfameronyeah, logging tends to be overcomplicated, overengineered and badly documented
16:30jonathanjI thought of having something like `(with-logger a-logger some forms)` rebind `*logger*`.
16:31dysfuni hope you didn't want some async with that because dynamic bindings are thread local
16:31jonathanjI was wondering about that.
16:32justin_smithI've been briefly enticed with ideas of software friendly logging (eg. every log is a json record including level and namespace etc. and the one reading the logs uses a client to filter and format)
16:32dysfun(in fact i use them in my single threaded cljs refs implementation)
16:32jonathanjSo if any of those forms are async then I guess you need to wrap the logger at another level.
16:32technomancyjustin_smith: how about https://brandur.org/logfmt
16:32dysfunjustin_smith: i think riemann is a good base for that sort of thing
16:33jonathanjjustin_smith: the library I intend on porting is http://eliot.readthedocs.io/ which might be an inspirational read then
16:33justin_smithtechnomancy: I've never seen that, interesting
16:33technomancyjustin_smith: we used it heavily at heroku and it was <3
16:34justin_smithsee, all these things are great, but they are improvements to a thing I find very unpleasant so my likelyhood of taking them on is lower
16:35technomancythe team I was on at heroku was literally the logging team =)
16:36technomancyit was an island of erlang in a sea of ruby/golang so I wasn't complaining
16:36justin_smithhah, nice
16:36jonathanjAfter having used Eiot for some complex logging, being able to visualise the hierarchy seems like a can't-go-back experience.
16:36patchworkjustin_smith: I like your vision of logging. That is all it needs to be
16:37dysfunalways fun to play with things like erlang
16:37patchwork(tears out swaths of logging code from project)
16:37patchworktechnomancy: Are you anti-golang? Is golang the devil? I haven't tried it yet
16:37patchworkYou used it in the same sentence as ruby so....
16:37technomancypatchwork: it's ... not a good programming language
16:38patchworkI have a coworker who is an evangelist of golang right now
16:38patchworksince I don't have any experience with it I don't really have a good response for the guy
16:38dysfuntechnomancy: diplomacy, you has it. i would be less polite about it than that
16:38technomancywe use it some at work and the only reason I can live with it is that no one is evangelistic about it
16:39patchworkWhat are the issues? I thought the goal towards concurrency and minimalism coincides with why I love clojure
16:39patchworkLike I said though, haven't tried it
16:39technomancypatchwork: it's very clearly designed by someone who hasn't done their homework around type systems, to say the least
16:40dysfunor on many other areas critical to it, like garbage collection
16:40patchworkAh okay.... after working in scala for the past year I am starting to resent heavy type systems ; )
16:40technomancylike ... what's the most common type error by at least an order of magnitude? null references. so you would think then if you were designing a type system, handling null references would be the first thing you would encode into it? not in golang. =(
16:40patchworkbut maybe that is just because of implicits
16:41technomancyscala at least has the interop excuse; golang has no excuse.
16:41patchworkAh yes, null references
16:41technomancy"this is how we did it in the 1970s so it's probably the best way to do it"
16:41patchworkSomething I have been very happy to do away with in scala
16:41patchworkhaven't had one of those in a long time
16:41patchworkI see, funny!
16:41dysfunand whoever thought it was a good idea to make all the containers non-threadsafe in a highly concurrent language, well that's just a stroke of genius
16:41l1xgolang is amazing i think interface{} is just a pretty nice way of saying go and fuck yourself and your types
16:41patchworkYou think the google people would put someone more thoughtful on their signature language design team
16:42technomancyalso "pass by value semantics" aka we are going to implicitly copy all values for every function call unless you opt out of it
16:42dysfunsignature language? perhaps you mean dart?
16:42technomancypatchwork: famous is apparently an acceptable replacement for thoughtful
16:42l1xyeah that too
16:42dysfuntechnomancy: oh yes, it's *definitely* a replacement for C!
16:42patchworkAh, I thought golang was their flagship
16:42l1xthe lack of proper types bothers me more though
16:43patchworkCool, so it is better than C
16:43patchworkProgress is good
16:43l1xlike we did not have ocaml or any good languages with decent type systems
16:43dysfunpatchwork: that was sarcasm
16:43patchworkThanks for the summary!
16:43l1xpatchwork: it is good for a single reason: CSP
16:43technomancypatchwork: my favorite way to describe golang's type system is it's like wearing a bulletproof vest with a big gaping hole over the heart. it's bulky and impedes your movement, but it doesn't actually protect your most vital organs.
16:43l1x:D
16:44patchworkdysfun: I don't know what sarcasm is anymore
16:44dysfunthere isn't a hole to get into it because they don't support generic vests
16:44l1xwell go is pretty good if you are a python programmer
16:44l1xhey look ma, i can ship a single binary!
16:44dysfunl1x: so one of my friends is currently writing cgo and FFIing from python...
16:44l1xthere you go! :)
16:45technomancyl1x: it's funny how ruby and python people are so impressed by such a simple thing
16:45dysfuntbf it's a cool thing
16:45dysfunsingle artifact deployments are ace
16:45osfameronuberjars!
16:45l1xtechnomancy: yeah, they havent seen ocaml this is why
16:45technomancydysfun: yeah but racket, ocaml, lua... this is not exactly a high bar
16:46dysfunsure
16:46technomancyit's just the jvm/python/ruby go out of their way to make things difficult
16:46patchworkIt is for people who've never seen it before ; )
16:46l1xdo you want a single binary? or do you want byte code? do you want union types? do you have Some(x) or None? Please be my gues
16:46osfameronis Rust more interesting?
16:46l1xguest*
16:46technomancyosfameron: by a long shot
16:46l1xyeah
16:47l1xit has almost all the great features of ml languages
16:47technomancyosfameron: the original rust compiler was written in ocaml, so you know it's designed by someone who hasn't been ignoring the last couple decades of research
16:47l1xyep
16:47patchworkI mean, right now the heavyweight nature of the JVM is a pretty big strike against it
16:48patchworkI am shipping a 300MB uberjar.... it raises some eyebrows
16:48l1xsure
16:48osfameronfor some applications yeah
16:48patchworkMostly of code I did not write
16:48l1xthis is because many of the Java devs are morons
16:49technomancyit's a great fit for server-side code but not a one-size-fits-all by any means
16:49l1xhttp://mail-archives.apache.org/mod_mbox/orc-user/201702.mbox/%3CCAB25XEXALvkPWcG1mf6VRS-C0ZXvfdZGww-Bf-mgYiFo%2BhObaw%40mail.gmail.com%3E
16:49l1xstory of today
16:50dysfunbut rust has some horriblenesses
16:50dysfunlike a constant deprecation cycle
16:51l1xyeah, i am not going to use it before it turns 10 years old
16:51l1xthat is the qualifier for a programming language
16:51dysfunand the libraries are way too immature. they're trying to get the type safety and doing it at the cost of the flexibility you need from a systems language
16:51dysfunlike don't even get me started about things like raw files last time i tried
16:51technomancywait a minute...
16:51l1x:D
16:51dysfunwasn't clojure 2006?
16:52dxtrIt takes 30 seconds to start the jvm on my other laptop. Just food for thought :p
16:52technomancydysfun: I guess it depends on if you're counting from first commit or first public commit
16:52l1xFirst appeared 2007; 10 years ago
16:52dysfundxtr: over a minute on a shitty box i borrowed last year when i was down on my luck
16:52l1xwhat?! :D
16:52dxtrdysfun: :D
16:52dysfuntechnomancy: close enough then :)
16:53l1xdxtr: well it is slow but once it is up!!
16:53dysfunyes and no
16:53dxtrl1x: Once the help text shows it shows it lightning fast!
16:53patchworkWell luckily you don't ever need to modify your code
16:53dysfuni swear too many silicon valley people think we're all running supercomputers
16:53dxtrdysfun: Are we not?
16:54dysfun"i write my shell scripts in clojure" "i don't have a minute to wait for them to start"
16:54l1xhahaha
16:54l1xactually ocaml is much better for "shell scripts"
16:54justin_smithdysfun: did you meantion you were working on a lumo fork at some point?
16:54dysfunyeah, there are some good libs for that
16:54l1xdxtr: have you tried a neutered jvm?
16:54technomancydysfun: my personal laptop is a core 2 duo
16:54justin_smithl1x: yeah - you can even compile ocaml to machine code from source, then run it, fast enough :)
16:54dxtrRemember that time when you parallelized some stuff in ocaml?
16:55l1xjustin_smith: yep exactly that
16:55patchworkJust wrote a script in planck a few days ago.... that is my new paradigm
16:55technomancyhave been enjoying mostly writing luajit on that
16:55dysfunjustin_smith: no. i am working on a build tool that uses lumo
16:55dxtrl1x: I have not
16:55justin_smithaha, now I get it - that's smart
16:55technomancydxtr: the best thing about ocaml is it's like the mirror world of the jvm. low memory usage, terrible at concurrency, no %$@& nils, spock has a beard, etc
16:56patchworkAh sigh.... so 2017, we still don't have the perfect programming environment
16:56dxtrtechnomancy: It can do concurrency fine
16:56patchworkSomeone told me we would have this down by now
16:56dxtrtechnomancy: Parallelism on the other hand :)
16:56patchworkdxtr: Oh yeah? Just by spawning a new process and communicating over sockets?
16:56l1xtechnomancy: hahaha this is a perfect explanation
16:56technomancydxtr: well I mean literal concurrency
16:56justin_smithpatchwork: we might not have the perfect programming language, or flying cars, but you can get "croc martens" boots
16:56l1xbut hey, concurrency is coming! :)
16:57patchworkBased on the way most people I see drive, I am super glad we don't have flying cars yet
16:57l1xwell self driving flying cars
16:57technomancypatchwork: maybe we could wait till decent type systems become a bit more widespread before coding self-driving flying cars
16:58dxtrpatchwork: Either that or you could just use the async package, for example.
16:58l1xbtw. clojure got really fast over the years, lein repl is much faster to start up, lein uberjar is also more performant
16:58technomancyyou put wings on that sucker and it better be written in Ada or an ML spinoff
16:58l1xi remember when lein repl took a decent amount of time
16:58technomancylein repl is fast now? cool!
16:58l1xmaybe because of java 1.8
16:59l1xtechnomancy: what do you use instead?
16:59patchworkJust started lein repl.... 5 seconds
16:59l1xsince you wrote it, i bet you use lein :)
16:59dysfun3s here, but this is a nice machine
16:59technomancyl1x: I use lein inside docker-compose where it takes like five minutes to bring up the whole cluster
16:59l1xnice
17:00dysfunboot repl took 20s!
17:00dxtrAlso, I started with clojure las week! Yay me, or something
17:00l1xdxtr: \o/
17:00dxtrI've been putting it off for years because jvm
17:01l1xdxtr: the best part is the community
17:01l1xlike seriously
17:01dysfundxtr: you learn to live with it. i was a massive java hater when i started with clojure
17:01l1xdxtr: the reason i started to use clojure because i could not even read java at the time
17:01dxtrdysfun: I have actually done Java professionally :p
17:01l1xdysfun: highfive
17:01justin_smith$ time java -jar ~/bin/clojure.jar -e '(System/exit 0)' => real 0m2.866s
17:02dysfunclojure is truly a breakthrough: it enables me to tolerate writing code that runs on the jvm
17:02dxtrI don't mind the jvm in itself. It's the bulkyness I dread
17:02dysfuni don't mind the jvm either, but the traditional way of programming it was java, which i do mind
17:02l1xdxtr: once in production this does not matter really
17:03dysfuneven the java standard libraries aren't so bad driven with clojure
17:03dxtrWhat clojure needs is more templating, amirite?
17:03l1xmost of our projects are 10-50MB uberjars where 95% is libraries not even needed but Java devs just add dependencies like trump outputs executive orders
17:04l1xdxtr: not sure
17:04dxtr:p
17:04dysfun(in particular i have to say AWT is a really nice API - transformation steps return new data rather than modifying in place)
17:04l1xi do not use too much templating
17:04technomancyif you can get over the horrid name http://docs.racket-lang.org/rackjure/index.html is a great way to write clojurey code without the huge jvm overhead
17:04dxtrl1x: I made a funny Java joke
17:05dysfuntechnomancy: they made ~> and ~>> more powerful than clojure's -> and ->> didn't they?
17:05l1xdxtr: no java jokes are funny :D
17:05l1xtechnomancy: racket does not have the libraries i need for my work
17:05technomancydysfun: I hadn't heard that
17:05dysfunlibraries are why i ended up sticking with clojure
17:05l1xthis is why clojure is winning, there is a (shitty) java lib for everything
17:06dxtrl1x: Also, the worst part about Java stuff is the XML that surrounds it. I learned to hate a lot of things when I coded java at the job :p
17:06l1xdxtr: edn ftw
17:06technomancyl1x: well it's good to have options anyway
17:06dxtrMainly XML and factory patterns
17:06l1xtechnomancy: true that
17:06dysfuni think most professional java devs know how to drive IDEs that generate boilerplate for them
17:06l1xhow is CSP/concurrency in racket?
17:07dxtrdysfun: Which sucks when things break
17:07technomancyl1x: you get real threads, but the GC is stop-the-world. I would be surprised if there weren't a good CSP implementation but I don't know if it ships in the stdlib
17:08l1xi see
17:08dxtrwell, Racket isn't really made to be performant, is it?
17:08l1xthis is why i think lfe is a better direction
17:08l1xthe erlang no global vm stop is just amazing
17:08technomancydxtr: it's made serious strides in the past few years (especially on ARM) but nothing like the JVM
17:09l1xdxtr: last time i checked it was up in the same bracket with clojure in terms of http-hello-world-micro-benchmark-e-penis
17:09technomancyactually there was a brief window when racket could beat clojure on ARM performance
17:09technomancywhen most of hotspot's jit smarts were x86-only
17:09l1xand it does not require a 160MB JVM
17:10dysfunl1x: i lost faith in lfe
17:10dxtrI just go with erlang
17:10l1xdysfun: how about joxa? :)
17:10technomancyjoxa's design is great
17:10l1xdxtr: alright, erlang than! :)
17:11dysfunpartially i think erlang is a nicer language, partially i'm not happy with some fundamental qualities of the erlang vm
17:11l1xi like erlang but i cannot find developers who i could work with
17:11l1xdysfun: like?
17:11l1xi really like beam
17:11dysfunfor example the atom table
17:11dysfunwe wrote some generative tests for lfe and it would exhaust the atom table and crash the BEAM
17:12dysfunand the fact that the builtins can't spawn processes and reliably recover if they close (they expect an EOF character!)
17:12l1xeven when you configure it right?
17:12dxtrWell, to be fair, if you're generating that many atoms you should consider another data structure
17:12dysfunOS processes i mean, not erlang processes
17:12dysfundxtr: hard to do generative tests involving atoms without generating lots of atoms
17:13l1xdysfun: these are sort of issues that either i dont care or if i had to care i could solve them
17:13dxtrdysfun: Just seems like a weird thing to do :p
17:13dysfungenerative testing? yeah it is but it's great
17:14l1xBy default, the maximum number of atoms is 1,048,576. This limit can be raised or lowered using the +t option.
17:14l1xthere, easy to fix for a real world use case
17:14dysfunl1x: of course, but the solutions here involve reserving memory for a large atom table and shipping extra C
17:15dxtrAlso, the vm is pretty slow
17:15dysfuncompared to the jvm, sure
17:15dxtrCompared to most things?
17:15dysfunnah
17:16l1xdysfun: what is the usecase when 1,048,576 atoms are not enough?
17:16dysfunerlang compares favourably with dynamic langs
17:16l1xalso erlang beats almost everything with template rendering
17:17l1xmight not be true anymore
17:21dysfuntemplatewise, everyone uses erydtl
17:26dysfuntechnomancy: do you prefer racket or clojure?
17:27technomancydysfun: depends on what I'm doing I guess. I wouldn't do server-side stuff in racket, and I wouldn't do guis and CLI tools in clojure (with the obvious exception of lein)
17:28dysfuni saw they're moving to chez scheme because it's faster
17:28technomancydysfun: I feel like Racket has historically had the edge on "prevent flexibility from becoming an unmaintainable mess over time" but now that Racket contracts are becoming part of Clojure that advantage is likely to lessen.
17:28technomancyI'm one of the weird ones who has never cared about speed
17:30justin_smithtechnomancy: "slow code" - hammock developed artisinal quality algorithms
17:30technomancyapart from leiningen startup I have only once had to profile Clojure code because it was too slow
17:30technomancyjustin_smith: on a thinkpad from 2008!
17:30justin_smithsounds like a pitch
17:34technomancydysfun: just for the record when I was hanging out in the #racket channel I frequently brought up how silly it was that hash-tables aren't callable and how their "just get the latest version of that lib lol" dependency system worked was ill-advised, etc
17:35technomancyI bring it up here more to avoid the echo chamber effect than to convince people to stop using clojure =)
17:35dysfunheh
17:35dysfunwe tend to be free with our criticism of clojure in here too
17:36dysfunracket ~> tries to fix that, btw
17:37technomancydysfun: racket or rackjure?
17:37dysfun(~> foo 'a 'b) -> (dict-ref (dict-ref foo 'a) 'b)
17:37dysfunrackjure, sorry
17:37technomancyIIRC rackjure fixes callable hash tables in a way that is not related to ~>
17:37dysfunthat also
17:38dysfunof course you pay a performance penalty for those checks
17:39technomancywhich is why regexes still aren't IFn in clojure =(
17:39l1xi was profiling clojure several times and rewrote parts that were slow
17:39dysfunwell, if we moved to protocols for everything like cljs did, we *could*
17:39l1xjust to beat java devs like 100x
17:40l1x10x was not good enough for me :)
17:40l1xthreading is a bitch :(
17:40dysfunbut that's not particularly likely, i think
17:40technomancydysfun: how do you implement protocols if you can't define functions yet?
17:41dysfunfall back to Runnable
17:42l1xone guy was trying to convince our ceo that the bottleneck was our network (10G/s) and i was surprised to figure out he used a single thread to do network IO to a remote datacenter
17:42technomancythen you can't declare any protocol functions that take args though, right?
17:42dysfunokay, Callable then
17:43technomancyIIUC the only reason you don't have circularity issues on JS is that you can change your initial protocol implementation once you've bootstrapped enough of the language
17:44dysfuni haven't looked into it. i can see there are difficulties, but i think it's a bit moot because it would be a huge compatibility-breaking change at this point
17:46technomancysome day I'll be able to (filter #"correct horse battery staple" passwords)
17:46dysfunthat would be pretty neat
17:50justin_smithtechnomancy: I knew someone once who called this "exampling" - where a concept is sound but someone takes an example of the concept's usage and follows literally, and remains ignorant of the concept itself
17:51technomancyjustin_smith: sounds like a useful term but I'm not seeing the connection
17:51justin_smithtechnomancy: "here is how you can create a high entropy string that is straightforward to remember"
17:51technomancyoh haha right
17:51justin_smith"oh, OK, I will always remember that one high entropy string you used!
17:51justin_smith"
17:52justin_smithwhich is like, pathologically against the original point :)
17:52technomancyhttps://xkcd.com/221/
17:52justin_smiththat's another good example of exampling actually
17:52clojurebotI don't understand.
17:52justin_smithclojurebot: you wouldn't, dummy
17:52clojurebotPardon?
18:06fifi-vhow can I play sound in reagent? Need something equivalent to js `new Audio("...")' and `.play()' as demonstrated here http://stackoverflow.com/a/23395136
18:08justin_smithfifi-v: that's not reagent specific is it?
18:10justin_smithfifi-v: (js/Audio. "data.....")
18:10justin_smith(.play ...)
18:10justin_smithfifi-v: this will all use standard interop syntax, it's pretty simple and well documented and worth learning
18:14dxtrIs korma a good choice for postgresql stuff?
18:16dysfundepends what you need
18:16dysfunit doesn't have json operator niceties
18:16dysfunit's very good for bread and butter traditional queries
18:17amalloykorma is more of a naan and curry thing than bread and butter
18:18dysfunhar har
18:18technomancydid someone pick up the development of korma? I thought it was abandonware for some time
18:19amalloyabandonware doesn't have to be brokenware
18:19dysfunit still works. it hasn't seen much action, but it's not total abandonware i think
18:19amalloy(i have no opinion about korma personally, i just don't really go for the "x hasn't been committed to in two months, therefore it must be garbage" attitude i see sometimes)
18:20technomancyamalloy: I was thinking more like 4 years but sure
18:20dysfunkorma is okay for the 90%
18:20dysfunthe limitations it puts on the remaining 10% triggered me to start building something more powerful though
18:24dxtrtechnomancy: Last commit was 11 days go, apparently
18:24technomancycool
18:26dxtrSo what do other people use?
18:27Ardxwhat does ! mean in clojure? Like if I had (set! ) does it denote that it will execute immediately (not lazy), or that it is a macro?
18:27dxtrside effects, if I'm not mistaken
18:28dysfunnot safe inside dosync
18:28Ardxoh
18:28dxtrI was mistaken
18:28dysfunbut that's only clojure core and some functions do not have the ! when they're not safe (it's presumed e.g. println is obvious)
18:33Ardxugh emacs keeps puttign all my comment lines in the middle of the screen when I press return
18:34technomancyArdx: use two semicolons for beginning-of-line comments
18:36Ardxoh yeah
18:36Ardxnice
18:48justin_smithdxtr: well, most things not safe in dosync are not safe because of a side effect
18:48justin_smithdxtr: dosync retries on conflict, and your side-effecting functions could be called N times
18:48justin_smithso, bigger picture, still mostly right :)
18:49dxtrWell, you've gotta *really* make sure your sides are affected
18:50technomancyI get the feeling "let's mark side-effects with a !" was something that seemed like a good idea early on but eventually was considered too much
18:51dysfunis that like "let's sprinkle io! in our code"?
18:55justin_smithat night, when I should sleep, I am haunted by the visions of all the code I should have wrapped in io!
18:56dysfuni believe you. millions wouldn't.
18:56technomancyearly on a lot of the buzz around clojure was due to its STM
18:57technomancywhich is quite remarkably good, but it's just not that frequently used
18:57justin_smithindeed
18:58dysfunwell most of us build webapps which talk to a database. we just don't have much call for it
19:07fifi-vjustin_smith: thanks
19:26dysfunso i'm reading an olde english book and all the 's' are 'f'. it's surprisingly demanding to parse
19:27justin_smithit's a separate ss that looks like an f but it has a tail on the lower left that an f doesn't have
19:27justin_smithiirc
19:27TimMctechnomancy: Come for the STM, stay for the PDSs.
19:27dysfunjustin_smith: nope
19:27dysfunhttps://archive.org/details/firstsixbooksofe00eucl
19:28dysfunflick to the introduction
19:29dysfunthere is a less pronounced horizontal bar to the 's' than the 'f', but they're not double s because 'ssciences' in the first sentence
19:29justin_smithdysfun: https://en.wikipedia.org/wiki/Long_s
19:30justin_smithit is used for doubles, including if the second s is in the middle of the word
19:30justin_smithyes, super weird rule
19:31justin_smithwait, not doubles - just any lower case s not at the end of the word
19:32technomancyI remember on classic Mac they used to use that as shorthand for "folder"
19:32justin_smithtechnomancy: solder - it's a secret message
19:32dysfunwhat, a long s?
19:33justin_smithſſſſſſſ
19:34dysfunhttps://ia800204.us.archive.org/BookReader/BookReaderImages.php?zip=/14/items/firstsixbooksofe00eucl/firstsixbooksofe00eucl_jp2.zip&amp;file=firstsixbooksofe00eucl_jp2/firstsixbooksofe00eucl_0015.jp2&amp;scale=2&amp;rotate=0 # look at how beautiful this book is though
19:34dysfundespite the long ssssssss
19:35justin_smithyes, very nice
19:36justin_smithſyſtem took me a moment
19:36dysfunfquare just looks so wrong
19:36justin_smithſupercallifragiliſticexpealidocious
19:36dysfun"Befides the fuperior fimplicity"
19:38dysfun"lefs" is a tedious one
19:38justin_smithfor fucks ſake
19:39dysfunbut yeah, it surprised me how much effort it was to parse
19:40dysfuni suspect "correcting" that probably involves OCRing it and then spellchecking the OCR results because the OCR doesn't speak long S
19:52Ardxhah so cool you can do "lein new play-clj hello-world" and it downloads play-clj
19:53dysfundid your last language not have that?
19:54ArdxI'm used to c# and viual studio where there is a GUI on everything. I'm used to command line things never working quite right :>
19:54dysfunheh
19:55justin_smithArdx: btw you can use clojure with CLR - it's even up to date and everything
19:55dysfunyeah, i was really surprised to see how well they've kept up to date
19:56ArdxYeah I know, meaning to try out at some point
19:56justin_smithit doesn't have a clojure-centric tool like leiningen though
19:57dysfunyeah, i should add clr support to my lumo build tool when i get more time to hack on it
19:58justin_smiththat would be awesome
19:58dysfunwell the idea for me was that it shouldn't just build cljs
19:58dysfunbecause that would be lame
19:58justin_smithand putting the build tool in something that starts up fast (eg. lumo) is a great idea
19:58dysfuni want it to build all sorts of things so i can take my build tool wherever i go
19:59justin_smithdysfun: in this room, 10 years from now "hey I want to try clojure, does it have a lumo build plugin?"
22:58iannnnhiiiiiii