#clojure log - Apr 11 2016

The Joy of Clojure
Main Clojure site
Google Group
List of all logged dates

0:00 amalloy: (reverse []) => (nil)

0:00 justin_smith: amalloy: good point

0:00 ,(def myrev (partial into ()))

0:00 clojurebot: #'sandbox/myrev

0:00 justin_smith: ,(myrev (range 10))

0:00 clojurebot: #error {\n :cause "Unable to resolve symbol: myrev in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: myrev in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: myrev in this...

0:00 justin_smith: ,(def myrev (partial into ()))

0:00 clojurebot: #'sandbox/myrev

0:00 justin_smith: ,(myrev (range 10))

0:00 clojurebot: (9 8 7 6 5 ...)

0:00 justin_smith: not lazy though

0:02 amalloy: reverse never is

0:02 lewis: ,(first (sorted-set 5 7 2 7))

0:02 clojurebot: 2

0:03 mmercer: sorted-set is a binary tree, and set is?

0:04 lewis: java.lang.UnsupportedOperationException: nth not supported on this type: PersistentTreeSet

0:05 amalloy: you asked this 8 hours ago, mmercer. what was unsatisfying about the answer?

0:06 lewis: amalloy: justin_smith: my reserve do not work on sets

0:06 s/reserve/reverse*

0:06 justin_smith: lewis: call seq before destructuring

0:06 or use first/rest instead of destructuring

0:07 sdegutis: So, the past few years, there's been songs that I liked and I was like "Wait a second! This is a guitar song!! I CAN PLAY THIS!!!" But then I looked up the chords and it was non-standard tuning, and I didn't trust my crappy old guitar to be able to be tuned back.

0:07 But now, I have a semi-okay guitar, and a tuner thing on it, so I realized I can play things like Bon Iver's Skinny Love now, stuff with alternative tunings!

0:07 Which is cool... except I can't remember ANY of those songs from the past that had alternative tunings.

0:07 justin_smith: sdegutis: one guitar for each song

0:08 sdegutis: And I didn't keep track of them either.

0:08 So I like have no idea what songs those were which I want to play which have alternative tunings.

0:08 And I'm just sort of hoping I eventually come across them, even though I can't remember how I came across them before (none of the songs in my iTunes library fit the bill).

0:11 lewis: justin_smith: thanks

0:12 justin_smith: following my example, im reading other solutions

0:12 reduce #(conj %1 %2) () - i understand this

0:12 reduce conj () - I dont understand this

0:13 amalloy: #(conj %1 %2) is just conj

0:13 justin_smith: lewis: what is the difference between #(conj %1 %2) and conj?

0:13 ahh, sniped :)

0:13 amalloy: yours was in the form of a quetion though, so you win

0:13 socrates had it right

0:13 sdegutis: amalloy: that's not true, conj can take more than 2 arguments

0:14 justin_smith: amalloy: it's defensive, that way I learn something if they are onto something I missed

0:14 troydm: I have an transient vector, and I want to drop last element from it, how do I do that without converting it to persistant and back?

0:14 sdegutis: justin_smith: mark this day, the first time amalloy has been wrong about something in clojure

0:14 justin_smith: sdegutis: in a reduce there's no difference though, because reduce always gives you two args

0:14 sdegutis: correct

0:16 amalloy: can anyone think of an exception to "reduce always gives you two args"?

0:16 lewis: conj is the function without arguments, justin_smith: so reduce pass the arg by default

0:16 justin_smith: not me

0:16 tolstoy: reduce-kv?

0:16 justin_smith: lewis: what does "the function without arguments" mean?

0:17 amalloy: ,(reduce #(conj %1 %2) ())

0:17 clojurebot: #error {\n :cause "Wrong number of args (0) passed to: sandbox/eval27/fn--28"\n :via\n [{:type clojure.lang.ArityException\n :message "Wrong number of args (0) passed to: sandbox/eval27/fn--28"\n :at [clojure.lang.AFn throwArity "AFn.java" 429]}]\n :trace\n [[clojure.lang.AFn throwArity "AFn.java" 429]\n [clojure.lang.AFn invoke "AFn.java" 28]\n [clojure.core.protocols$iter_reduce invokeStat...

0:17 lewis: ,(reduce #(conj %1 %2) () [ 1 2 3 4])

0:17 clojurebot: (4 3 2 1)

0:17 lewis: ,(reduce conj () [ 1 2 3 4])

0:17 clojurebot: (4 3 2 1)

0:18 lewis: justin_smith: it means the operator

0:18 justin_smith: what?

0:18 clojurebot: what is seq

0:18 lewis: (operator operand1 operand2)

0:18 justin_smith: lewis: a function is a function

0:19 lewis: I have no idea what you mean by "function with no args" in this context - conj always needs args

0:19 lewis: i meant without operands*

0:19 justin_smith: do you mean a bound function rather than a literal?

0:19 what? it has operands

0:19 it just doesn't have a literal inline notation

0:20 because it's a definition and not a function literal

0:20 lewis: without explicit operands then

0:20 justin_smith: lewis: conj is conj, conj called with two args and #(conj %1 %2) always do the same thing

0:20 (if called with the same two args)

0:22 #(conj %1 %2) is a sugar for (fn [x y] (conj x y)) which is just an elaborate way of calling conj, and can usually be replaced by conj itself (unless you are trying to be stricter about argument count or something)

0:22 sdegutis: oh man

0:23 Are there any more big surprises in store for Clojure?

0:23 All sorts of cool things were happening, things like destructuring were invented.

0:23 Now it's, like, "we're adding a socket config to make things a little easier"

0:23 tolstoy: You mean, what would a Clojure 2.0 be?

0:24 sdegutis: Well I dunno, versions these days are weird.

0:24 I just mean, compare Clojure 1.0 to Clojure 1.5, big changes happened. Now look at Clojure 1.5 compared to Clojure 1.8, not a whole lot in comparison. Mostly transducers.

0:24 lewis: justin_smith: I see/ i got confused

0:26 sdegutis: (doc fold)

0:26 clojurebot: Gabh mo leithscéal?

0:26 sdegutis: clojurebot: just print the damn doc please

0:26 clojurebot: Excuse me?

0:26 sdegutis: ,(doc foldcat)

0:27 clojurebot: Cool story bro.

0:27 sdegutis: clojurebot: you're a real jerk

0:27 tolstoy: For some reason I think the defprotocol in 1.2 was the biggest deal, but just subjectice.

0:27 clojurebot: Gabh mo leithscéal?

0:27 sdegutis: tolstoy: also destructure was around then

0:27 tolstoy: before then there was literally no destructuring anywhere

0:27 justin_smith: ,(require 'clojure.core.reducers)

0:28 clojurebot: #error {\n :cause "Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath."\n :via\n [{:type java.io.FileNotFoundException\n :message "Could not locate clojure/core/reducers__init.class or clojure/core/reducers.clj on classpath."\n :at [clojure.lang.RT load "RT.java" 456]}]\n :trace\n [[clojure.lang.RT load "RT.java" 456]\n [clojure.lang.RT load "RT.java"...

0:28 justin_smith: sdegutis: fold is in reducers, I dunno why clojurebot doesn't know about reducers?

0:28 sdegutis: yeah weird

0:29 tolstoy: sdegutis: The reason I was thinking protocols were a big deal was that it made (or was a step) toward making clojure-in-clojure possible.

0:29 justin_smith: tolstoy: sure, but there's no rush to make clojure-in-clojure happen

0:30 sdegutis: tolstoy: oh i see

0:30 tolstoy: justin_smith: Right. But (subjectively) that 1.2 release seemed significant because of that new abstraction.

0:30 sdegutis: tolstoy: only the compiler could be rewritten in clojure, not the runtime, which isnt super useful for any particular reason

0:30 tolstoy: Although "starts-with?" and "ends-with?" in clojure.string hit me where I live most of the time. ;)

0:31 sdegutis: I'd much sooner prefer to have a Clojure in C, with a small compiler and runtime similar to Lua's -- which I was trying to work on but I don't get paid to do it and have no actual use for it so I put it on indefinite hold

0:31 ... but it would be cool as heck.

0:31 tolstoy: There's pixielang. Sorta close.

0:32 rhg135: if by close you mean in the same universe :P

0:33 justin_smith: rhg135: I can't think of a language more similar to clojure that is not a fork of clojure

0:33 rhg135: A while ago I had to embed in a C app

0:33 it was scary

0:33 tolstoy: I think pixielang has a nice FFI to C, no?

0:34 rhg135: does it?

0:34 justin_smith: I've seen nicer, but I've seen worse too

0:34 rhg135: that's nice

0:34 FFI from C though...

0:34 tolstoy: Okay, I mean, it has one.

0:35 I once tweeted "I hope someone does a Clojure on top of Swift." Baldridge responded, "I'm tempted." I'm still hoping.

0:35 sdegutis: tolstoy: kinda sorta

0:36 tolstoy: the whole fun of writing a language that bridges to C though is that you then have access (assuming you build a decent FFI) to *way* tons of cool libs

0:36 tolstoy: thats not true with swift

0:36 tolstoy: Well, okay. But Swift boils down to LLVM. Is there no interop with C?

0:37 sdegutis: tolstoy: its kind of there but its 1-way and terrible

0:37 justin_smith: sdegutis: on one side it's very easy to interact with c, but you inherit all of c's problems, on the other side, you don't deal with c's bs, but it's hard to interoperate (or at least computationally expensive with all the boxing/unboxing and manual tracking of which values c keeps track of and which your language does)

0:38 there's a lot of room in the middle, but the best spot is subjective (but langs that can parse .h files are handy)

0:38 sdegutis: heh

0:38 justin_smith: until you start dealing with C macros and # includes etc

0:39 and include-guards

0:39 oh man

0:39 ben_vulpes: sdegutis: stahp

0:39 sdegutis: you're basically writing the CPreP

0:39 ben_vulpes: plz no bully

0:39 there's also clasp if one wants a llvlisp

0:39 sdegutis: man i just wanna find those songs

0:39 justin_smith: sdegutis: there's langs that find ways to do it, and it makes using c much easier.

0:39 sdegutis: justin_smith: i kind of admire lua's approach but hated it as an end user

0:40 they're just like "we dont care"

0:40 "about anything. at all."

0:40 ben_vulpes: "hey man"

0:40 "programming's just strings"

0:40 sdegutis: haha

0:40 stringly typed

0:40 oh yah that reminds me i came up with a good solution to stringly typed map keys

0:40 ben_vulpes: "just concatenate your calls together at runtime and eval 'em"

0:40 * justin_smith reimplements clojure in m4.

0:40 ben_vulpes: #yolo

0:40 sdegutis: (defaccessor foo)

0:41 it expand to (def foo :foo)

0:41 :D

0:41 im not joking, i literally did this for work last week.

0:41 its there in production right now.

0:42 ben_vulpes: sdegutis: b-but why

0:42 justin_smith: (defmacro defidentity [sym] `(def ~'sym ~sym))

0:43 sdegutis: i just kept feeling anxious every time I typed (:videos-service env) and was wondering if it was plural or singular

0:43 justin_smith: it's a layer of error-checking you don't get for keywords, yeah

0:43 maybe someone will even find a valid usecase for defidentity

0:43 sdegutis: justin_smith: your version is broken

0:43 justin_smith: it's something different

0:43 sdegutis: ,(defmacro defidentity [sym] `(def ~'sym ~sym))

0:43 justin_smith: sdegutis: given foo, it should define foo to be foo

0:43 clojurebot: #'sandbox/defidentity

0:43 sdegutis: ,(defidentity foo)

0:44 clojurebot: #error {\n :cause "Unable to resolve symbol: foo in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: foo in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: foo in this conte...

0:44 justin_smith: sdegutis: foo has to exist

0:44 ,(def foo 1)

0:44 clojurebot: #'sandbox/foo

0:44 justin_smith: ,(defidentity foo)

0:44 clojurebot: #'sandbox/sym

0:44 sdegutis: ,(defidentity foo)

0:44 clojurebot: #'sandbox/sym

0:44 justin_smith: oh, that's broken

0:44 sdegutis: see thats what i said

0:44 i use the ~' trick often

0:44 so i know it when i see it

0:45 and yes i know its a literally terrible practice and amalloy would have a heart attack if he ever saw code like it

0:45 but it works

0:45 ,sym

0:45 clojurebot: 1

0:46 sdegutis: justin_smith: what were you actually going for tho?

0:46 i cant even imagine what the code was sposta be

0:46 justin_smith: sdegutis: (definidentity foo) should become (def foo foo)

0:46 sdegutis: that sounds 110% useless

0:46 justin_smith: it was meant to be

0:46 ben_vulpes: ,(defidentity :h)

0:46 clojurebot: #'sandbox/sym

0:46 sdegutis: ,sym

0:46 clojurebot: :h

0:46 justin_smith: yeah, it's broken

0:47 sdegutis: ,(defmacro defidentity [sym] `(def ~sym ~sym))

0:47 clojurebot: #'sandbox/defidentity

0:47 sdegutis: (defidentity foo)

0:47 ,(defidentity foo)

0:47 justin_smith: yeah, that's the right definition

0:47 clojurebot: #'sandbox/foo

0:47 sdegutis: ,foo

0:47 clojurebot: 1

0:47 sdegutis: ,(defidentity :g)

0:47 clojurebot: #error {\n :cause "First argument to def must be a Symbol"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: First argument to def must be a Symbol, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.RuntimeException\n :message "First argument to def must be a Symbol"\n :at [cloju...

0:47 sdegutis: hahaha def sucks

0:48 justin_smith: sdegutis: oh! not totally useless - it replaces the previously useful metadata with new misleading metadata

0:48 sdegutis: eg. the source line etc.

0:48 sdegutis: hahaha

0:48 justin_smith: also probably eliminates a docstring

0:48 sdegutis: defobfuscate

0:48 ,(defidentity map)

0:48 clojurebot: #error {\n :cause "denied"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.SecurityException: denied, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyzeSeq "Compiler.java" 6875]}\n {:type java.lang.SecurityException\n :message "denied"\n :at [clojurebot.sandbox$enable_security_manager$fn__835 invoke "sandbox.clj" 69]}]\n :trace\n [[clojureb...

0:48 sdegutis: haha jerk clojurebot

0:49 tolstoy: Maybe use the name "definitely"?

0:49 sdegutis: ;D

0:51 justin_smith: sdegutis: re-reify

0:53 tolstoy: re-iffy

0:59 rhg135: ,(defn obfuscate [v] (alter-meta! v (constantly {:macro (:macro (meta v))}))

0:59 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

0:59 rhg135: ,(defn obfuscate [v] (alter-meta! v (constantly {:macro (:macro (meta v))}))

0:59 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading>

1:02 bmuk: I'm trying to write a function which, given a seq of directories, returns a flat collection of all the files below those directories. Obviously this calls for recursion, and my insinct is to use cond, check the base case (seq is empty), and reduce the results. As I understand it, the JVM performs poorly with this kind of recursion. What is the best and most idiomatic way to do this?

1:02 clojurebot: I don't understand.

1:03 rhg135: ,(meta #'map) ; I think I broke clojurebot

1:03 clojurebot: {:macro nil}

1:04 tolstoy: bmuk Have you tried file-seq?

1:06 Oh. Hm. Doesn't answer the question, I guess.

1:06 bmuk: tolstoy: I wasn't aware of it but it looks promising

1:06 tolstoy: (mapcat #(file-seq %) [dir1 dir2])? Something like that?

1:08 rhg135: self-calls in lazy-seqs are ok iirc

1:08 bmuk: that looks like exactly what I need

1:08 mmercer: clojure newb.. is there a difference between #(file-seq %) and just file-seq?

1:09 bmuk: mmercer++, exactly what I was about to ask. Or 'file-seq or something. Ran into that issue when trying to (map .getPath '(file1 file2))

1:09 rhg135: yes, one takes only one arg (but I think file-seq does anyway) and that first fn has different metadata

1:09 tolstoy: (mapcat #(file-seq (java.io.File. %)) ["bin" "Desktop"])

1:10 rhg135: #() expands to (fn [] ()) which creates a new function

1:10 bmuk: rhg135 I know that, but why can't I just pass map the .getPath function?

1:10 tolstoy: Yeah, I always to the #() thing until I all of a sudden see it's not necessary.

1:10 rhg135: by new function I mean a clojure.lang.IFN object

1:11 methods aren't objects, bmuk

1:11 bmuk: ahh. My java knowledge is limited. .NET dev by day

1:12 not even sure if C# methods are objects

1:12 rhg135: (.method x) is sugar for (. x (method)) and in the jvm you can't pass around methods, just objects

1:13 so you can pass around an IFn object that calls the method, but not the method itself

1:13 (doc memfn)

1:13 dysfun: methods are just too attached to objects, you can't separate them as such

1:13 clojurebot: "([name & args]); Expands into code that creates a fn that expects to be passed an object and any args and calls the named instance method on the object passing the args. Use when you want to treat a Java method as a first-class fn. name may be type-hinted with the method receiver's type in order to avoid reflective calls."

1:14 rhg135: ,(memfn toString) ; thusly

1:14 clojurebot: #object[sandbox$eval48$fn__49 0x5743a3c1 "sandbox$eval48$fn__49@5743a3c1"]

1:14 rhg135: ,(macroexpand-1 '(memfn toString)) ; rather

1:14 dysfun: rhg135: hrm, didn't know about memfn, neat!

1:14 clojurebot: (clojure.core/fn [target76] (. target76 (toString)))

1:15 bmuk: yeah, this is really good info, thank you

1:15 rhg135: it's a very nice thing

1:15 bmuk: I had heard before that clojure could compile to CLR as well, is that still a thing?

1:16 dysfun: we've had a few discussions about that recently actually

1:16 it's not what i'd call 'actively maintained'

1:16 it still sees the occasional commit, but it's more a labour of love than something i'd deploy to production at this point

1:17 however if in particular you wish to make games, arcadia is a clojure wrapper for unity

1:18 bmuk: well we're thinking about using clojure where it makes sense for us in production, if that ever means we could benefit from that I'd be happy to submit PRs for any bugs I find

1:18 at this point CLR interop isn't something I really need since I'm calling a json api anyway

1:19 dysfun: well personally i'd love to see the CLR clojure get some more weight behind it :)

1:20 scala abandoned their effort at .NET a few years ago, so clojure is basically the only JVM lang that also supports .NET basically in any fashion at all right now

1:20 rhg135: now that the CLR is OSS I can possibly work on it

1:20 dysfun: or the only one anyone has ever heard of, anyway

1:20 bmuk: that's what I was about to bring up

1:21 rhg135: before thenI'd have to sell a bit of my soul to MS

1:22 bmuk: although you only get the benefit of OSS CLR if you upgrade your project to the latest .net, which has a lot of changes so it's an undertaking

1:22 lol yeah

1:22 dysfun: i considered it too, then i realised that the JVM is really very good and that .NET isn't offering me anything over that

1:22 bmuk: dysfun, I think the utility is really more for MS shops that would like to incorporate clojure

1:22 dysfun: yes, absolutely

1:23 rhg135: also before then the only way to use it was to pay MS for windows, or hope mono has no bugs besides those in CLR (lmao)

1:23 dysfun: and sounds like you're one of those

1:23 i thought mono *was* a bug?

1:23 bmuk: haha

1:23 rhg135: hence the lmao

1:24 dysfun: i think mono is a major reason why i don't like a standard linux desktop

1:24 rhg135: or even better, hope wine has no bugs (lmao-er)

1:24 dysfun: KDE is fugly and every GNOME distro either ships banshee (GTK#) or something ancient and shit for music

1:24 rhg135: I don't use mono except for writing C#

1:25 * dysfun doesn't use mono at all any more

1:25 rhg135: KDE doesn't even use mono iirc

1:25 bmuk: I'm a minimalist so I pretty much only use emacs, firefox, and terminal applications when in linux lol

1:25 * ben_vulpes nonchalantly kicks a rock and mutters about exwm to himself

1:25 rhg135: I just use an xterm with vim...

1:26 dysfun: well, right now, i've got a terminal, emacs and firefox open...

1:26 rhg135: heh

1:26 same here actually

1:26 bmuk: there's actually a pretty good music program for emacs

1:26 * dysfun is currently using youtube on his laptop

1:27 rhg135: except for the vim inside the remote connection in my terminal

1:27 dysfun: i haven't even plugged in my amp yet so no music on my desktop

1:27 rhg135: I had to fix a bug in my remote cloudbot

1:27 because hot-reloading python is a great idea

1:28 dysfun: don't go there :)

1:28 * rhg135 waits for the OOM

1:28 dysfun: naw, for real OOM action you need a JVM

1:28 bmuk: dysfun: for when you plug in your amp: https://github.com/dbrock/bongo

1:28 ben_vulpes: i want my next computer to completely eschew audio

1:28 dysfun: bmuk: ta!

1:28 rhg135: I'm running this on a rpi model 1; any leak = OOM

1:29 ben_vulpes: aren't there consumer electronics for that?

1:29 dysfun: ben_vulpes: for playing music? yes, i have a mac laptop here

1:29 bmuk: rhg135: what is the feasibility of running clojure on an rpi?

1:29 dysfun: although itunes has started to suck since Steve Jobs died

1:29 ben_vulpes: i was thinking about the handheld devices...

1:30 dysfun: iTunes was rotting on the vine five years ago.

1:30 if not seven.

1:30 rhg135: bmuk: very feasible. It runs fine

1:30 dysfun: no, it was *ok* a few years ago

1:30 recently they just change everything for the sake of change

1:30 ben_vulpes: much like winamp, it achieved adequacy at its task and was bloated beyond recognition by user experience experts.

1:30 dysfun: and i'm finally going to finish writing my media organisation tool because i'm annoyed with it

1:30 ben_vulpes: dysfun: you don't say!

1:30 rhg135: just be careful with the ram, bmuk

1:31 bmuk: I still have winamp installed solely for milkdrop

1:31 rhg135: no leaks

1:31 ben_vulpes: i just started a project out of rage at itunes and friends

1:31 rhg135: rage projects are nice

1:31 dysfun: bmuk: did you know milkdrop was created by some nutjob evangelical who wanted to stop people doing drugs by giving them pretty pictures without hallucinogens?

1:31 bmuk: rhg135: that's what I was worried about. Probably a noob question but would running cljs under node alleviate some of that (v8 mem performance vs JVM)?

1:31 rhg135: that's why com.rhg135/killslack exists

1:32 dysfun: bmuk: if i were deploying to raspi, i'd use cljs

1:32 rhg135: you know, bmuk, I dislike cljs

1:32 ben_vulpes: > pretty pictures

1:32 bmuk: dysfun: I did not know that lmao

1:32 rhg135: it's a neutered clj imo

1:32 ben_vulpes: > hallucinogens

1:33 myeah because /that's/ what that's about.

1:33 dysfun: i dislike using a binary oracle jvm just to get acceptable performance of my clojure :)

1:33 ben_vulpes: webstack

1:33 best tech is proprietary

1:33 > jvm

1:33 > datomic

1:33 dysfun: bmuk: i don't think he anticipated that immediately everyone seeing milkdrop thinks "cool, wish i was on acid"

1:33 the jvm is not proprietary

1:34 bmuk: I think that's called the barbra streisand effect

1:34 dysfun: slightly different thing, but yes

1:34 tolstoy: Is the Oracle JVM faster then OpenJDK?

1:34 dysfun: on ARM, yes.

1:34 bmuk: cljs is useful because it runs client-side. I have no alternative client-side language with hot reloading and meta programming capabilities

1:35 dysfun: bmuk: much as i'm loathe to admit it, javascript fits that bill

1:35 bmuk: I guess it would have to lol

1:35 ben_vulpes: hey

1:35 hey

1:35 dysfun: not that i'm saying you should use js. nobody wants to

1:35 ben_vulpes: why not put the jvm in the browser

1:36 tolstoy: heh.

1:36 dysfun: because it would be a security nightmare. so glad they NEVER DID THAT.

1:36 ben_vulpes: no it'll be fiiine!

1:36 * dysfun is also really glad they only made one matrix movie

1:36 ben_vulpes: hahaha

1:36 rhg135: meta-programming in cljs? only at compile time

1:37 bmuk: meanwhile the captive portal at my old college was a java web app. NBD lol

1:37 dysfun: i can top that

1:37 when i was over at nokia, we had to use this thing that was an activex control

1:37 and on top of that it was completely shit

1:37 bmuk: rhg135: I guess since I don't know it that well I'm assuming it has feature parity with clj

1:37 rhg135: keep the delusion, man

1:38 you'll be happier

1:38 dysfun: rhg135: er, well since cljs is self-bootstrapping, it's not out of the question...

1:38 ben_vulpes: javascript is an amazingly flexible language

1:38 rhg135: to be fair, people can get far with it

1:38 tolstoy: I worked at a place that went from Java Applet -> Perl webforms -> emailed Excel spreadsheets for procurement

1:38 bmuk: haha well no matter how behind it is I think I'd prefer writing cljs over Razor code

1:39 ben_vulpes: my boss once made me implement a full delegate pattern in javascript

1:39 rhg135: dysfun: true, but even then it isn't now

1:39 I mean noreified namespaces pfft

1:39 dysfun: heh, i was reading the gang of four this weekend ("Design Patterns"). I don't miss thinking in OO terms.

1:40 jeaye: Using clojure clr, I can say (.name (first foo)) but I can't say (map .name foo), since .name ends up not being found.

1:40 How can I do it?

1:40 dysfun: #(.name %)

1:40 jeaye: Ah, dirty

1:40 Works, thanks.

1:40 rhg135: js is a lisp in algol clothes more or less

1:40 dysfun: or memfn

1:41 bmuk: for a while when I started this job it was really hard for me to make my brain grok OOP again

1:41 rhg135: one of those mutable-happy ones

1:41 dysfun: rhg135: it's really not. lisp is all about the values

1:41 rhg135: js has values

1:41 ben_vulpes: > js is a lisp



1:41 tolstoy: JavaScript Isn't Scheme: http://journal.stuffwithstuff.com/2013/07/18/javascript-isnt-scheme/

1:41 ben_vulpes: man i don't know shit about shinola and even i find that entertaining

1:42 rhg135: it's the closest to in the mainstream rather

1:42 ben_vulpes: sure

1:42 dysfun: would just like to point this out at this point. McCarthy is pretty much the expert on lisp http://www.defmacro.de/?p=13

1:42 ben_vulpes: just like "american cheese" is the closest to tillamook aged white cheddar

1:42 doesn't make it fucking /cheddar/

1:42 rhg135: that stuff is disgusting

1:43 tolstoy: But it's yellow-orange.

1:43 ben_vulpes: but hey

1:43 it's "cheese"

1:43 rhg135: "american cheese"

1:43 ben_vulpes: like js is "lisp"

1:43 rhg135: "cheese"

1:43 bmuk: what happened to the lisp machines? Why would anyone ever move from having all the benefits of lisp all the way down to not having them?

1:44 rhg135: performance? maybe

1:44 but lol

1:44 dysfun: bmuk: that's a surprisingly long story. suffice to say that in the end, efficiency won out

1:44 ben_vulpes: very long story, but the long and short of it was that usg dole ran out.

1:45 i can play the unsubstantiated historical claims game too, dysfun !

1:45 dysfun: and these days we can have whatever environment we like, so long as we build it in software

1:45 bmuk: do you see us returning there at some point or does that even matter in our post-virtualization era

1:45 ben_vulpes: > whatever environment we like

1:46 bmuk: exactly ^

1:46 ben_vulpes: categorically untrue.

1:46 dysfun: ben_vulpes: but it's such a dull story. you really don't want me to

1:46 ben_vulpes: show me a language that doesn't need bounds-checking.

1:46 dysfun: agda

1:46 ben_vulpes: (or perform it under the hood!)

1:46 dysfun: assembler

1:46 bmuk: just because an environment doesn't exist doesn't mean it cannot be done

1:47 theoretically software can do anything

1:47 dysfun: anything 'technically feasible', yes

1:47 ben_vulpes: except for halt the processor, a la lisp machines.

1:47 dysfun: oh, you want to bring back the HCF instruction?

1:47 ben_vulpes: just the H part

1:47 tolstoy: I think the era of an environment vs a collection of specialzed tools is over, alas.

1:47 * ben_vulpes just finished reading the scheme-78 chip paper

1:47 ben_vulpes: chip could motherfucking loop in place

1:48 dysfun: you do realise that the lisp machines weren't exactly fast, don't you?

1:48 i can emulate one in software hundreds of times faster than they ran

1:48 ben_vulpes: ofc

1:48 i have done some amount of research dysfun

1:48 doubtless not as much as you

1:48 dysfun: hardware design is hard. ultimately we had to make computers dumber and more flexible

1:48 ben_vulpes: you might even have been so lucky as to have worked with them!

1:49 nah, cheap micros for the masses one out.

1:49 dysfun: i have not worked with a lisp machine, but i've been doing lisp for a looong time ;)

1:49 rhg135: computers are rather fast these days to the point that I prefer working code

1:49 ben_vulpes: we didn't "had to" anything.

1:49 dysfun: we really did

1:49 society demanded we have more computational power, and it needed to be provided

1:50 ben_vulpes: what "society" what "demand"

1:50 * ben_vulpes would love to see these demands in the grey lady or something

1:50 ben_vulpes: Yours,

1:50 Society

1:50 "a million chickens"?

1:50 dysfun: there was a market for computational power. the demand increased and so people provided

1:50 and the lispms weren't very good at it

1:50 ben_vulpes: goodness, no

1:51 dysfun: and you could not have had a 2GHz lisp machine even if they'd kept plugging away at it

1:51 ben_vulpes: nor were gothic cathedrals frequently defensible castles.

1:51 tolstoy: Ah, come on. The demise was part hardware, sure, but also no one really wanted a Big Environment (like Smalltalk, etc).

1:51 dysfun: you're like my flatmate. he has a huge pile of antiquated hardware and goes on about how great it was. meanwhile i just want to get my work done

1:51 tolstoy: IMHO, Lisp Machine/Smalltalk --> Excel.

1:52 ben_vulpes: dysfun: you use vim, iirc?

1:52 dysfun: tolstoy: forth was the start of that

1:52 ben_vulpes: emacs.

1:52 ben_vulpes: huh i wonder who i was thinking of

1:52 dysfun: i think justin moved to vim recently

1:52 ben_vulpes: dysfun: i don't object to the getting of work done!

1:53 dysfun: no, i mean i'm a pragmatist

1:53 ben_vulpes: heck, i work in clojure and don't crucify myself on cl or haskell or something.

1:53 dysfun: i have a lovely laptop, but it's not up to developing clojure, so i stole my flatmate's desktop

1:53 ben_vulpes: it's just hard to live on the c machine with sockets and what have you and read about how the lisp machines would let you talk directly to the nic

1:53 dysfun: haha, most of my work is in clojure, but the last week i've been doing a lot of haskell

1:54 ben_vulpes: or the wonders of the symbolics typesetter, or the distributed lisp persistence layers they built...

1:54 and i see...mysql. postgresql. mongo.

1:54 dysfun: have you looked at what they did for smalltalk?

1:54 ben_vulpes: fucking indesign

1:54 nah, symbolics depressed me enough

1:54 i know a guy who still works in smalltalk!

1:54 loves it. works on his own.

1:54 dysfun: smalltalk had many good object databases

1:55 probably still does

1:55 there are still smalltalk implementations that cost money

1:56 ben_vulpes: but the root of my gripe with compute is the end user development environment

1:56 dysfun: yup, it's terrible. but a lot of people are working on fixing it

1:56 and clojure fares better than most

1:56 ben_vulpes: dunno about "fix"

1:56 seems rather unmendable from this novice viewpoint.

1:57 dysfun: i don't believe that to be the case

1:57 ben_vulpes: but hey, clojure's a decent set of tentacles with which to wrassle the beast.

1:57 dysfun: but it's a matter of /belief/

1:57 neither of us are going to stake the next 20 years on making it happen, i don't think.

1:57 dysfun: yeah, but i've been programming for 16 years. i know what's possible by now

1:58 and i put an enormous amount of time into open source work with one of the goals being to improve the development experience

1:58 ben_vulpes: likely just a failure of imagination on my part.

1:58 dysfun: it's just something that comes with time

1:58 and learning a lot of languages

1:58 ben_vulpes: dysfun: how've you been driving it forwards?

1:59 * ben_vulpes whimpers

1:59 ben_vulpes: more languages

1:59 tolstoy: Were Lisp Machines (etc) really about "software development", or were they just super sophisticated shells for people who needed to get other stuff done?

1:59 ben_vulpes: dysfun: ^^ ?

1:59 tolstoy: Scientists, etc?

1:59 ben_vulpes: (i always imagined the latter)

1:59 dysfun: well for a start, i've been working on a clojure llvm backend that has full tracing of what optimisation does to the code

1:59 ben_vulpes: wooooooooee

2:00 dysfun: tolstoy: they saw the beauty in what mccarthy did and thought "hey, this is a great why to think about code". but all code was academic back then really

2:00 tolstoy: Yeah. So I think Excel is the spiritual successor, more than OSX, Windows, etc.

2:01 dysfun: i don't think there is a spiritual successor

2:01 the one thing we have truly lost is everything being a function

2:01 tolstoy: But that's from a dev perspective, I'm talking a user/customer perspective.

2:01 dysfun: imagine if all applications were split into screens, android-style and each one was a function call away

2:02 now pretend you've made the UI over functions much easier, and suddenly the user can do a lot more

2:02 tolstoy: Spiritual successor != better, just that it lest people do all the calculations, graphing, etc, etc, they want without "programming" with text files.

2:02 ben_vulpes: imagine if you could get into the guts of eg solidworks

2:02 dysfun: we make enormous mistakes assuming that people who use excel are not good with technology. you'd be amazed what users do

2:03 ben_vulpes: hand-cranked asm too

2:03 dysfun: tolstoy: right, but the closest i can come up with is 'office'

2:03 if anything, emacs is more of a spiritual successor

2:04 btw, if you want to know how good your software is, try and teach someone who is a non-programmer how to use it and then watch how they use it

2:04 (for end user facing things)

2:05 tolstoy: I think that's a little bit what Brett Victor is after. Not better programming tools for programmers, but more appropriate idioms for getting work done that are, kinda, programming in the way Excel sorta is.

2:06 dysfun: hrm, i hadn't come across him, but i'm now reading his website. thanks :)

2:06 tolstoy: I remember trying to help someone get started with Java (back in the Ant days) and after hearing myself speak, I realized it was bat-sh*t insane. ;)

2:07 dysfun: i think it was feynman who said "if you can't explain it to a child, you don't understand it"

2:07 tolstoy: He's the guy that inspired some of the early LightTable work, before it went all traditional.

2:07 dysfun: before it became a bit disappointing? yes.

2:08 tolstoy: I could explain it, I just realized that Java had so many, "Download this, okay, create a dir like that, okay, type this and this and this, then whatever.xml and, a couple of hours from now, you should be able to print hello."

2:08 bmuk: what is the benefit of LightTable over emacs? Is it just that it sets everything up for you?

2:08 rhg135: Speaking of which, what happened to the author?

2:08 dysfun: bmuk: emacs is more powerful by far. lighttable is 'easy'. some people prefer it.

2:08 tolstoy: Of LightTable? Chris Granger (ibdknox) has a startup working on a new way for "regular people" to interact with data. Called Eve, or something like that.

2:09 dysfun: eve is disappointing too

2:09 rhg135: Yeah, but that was years ago

2:09 dysfun: i appreciate they've made a pragmatic decision that will allow them to get to market quicker, but they shouldn't have

2:09 rhg135: I'd not be surprised if he rage quit

2:10 dysfun: his blog has been stagnant since Eve 0

2:11 rhg135: Indeed

2:11 bmuk: I've often thought of emacs as the *best* interactive environment for text, but why do you think we still use text for programs? Is editing a string of characters really the most intuitive way to tell the computer what you want it to do?

2:11 tolstoy: He tweets about it ever now and then.

2:11 dysfun: bmuk: no, but every time someone has tried graphical programming (i'm trying too!) it's come out shit

2:12 tolstoy: I bet non-text programming is really something that should be tuned to domains, rather than general purpose. Like that Brett Victor dynamic design language for circuits.

2:13 dysfun: yes, that's the area i'm heading in at the minute

2:13 bmuk: I like the lego/puzzle approach that scratch has, but I've never actually used it

2:13 dysfun: i don't know how it's going to work for clojure, but for example in C++ you might have a "create new" > "Observer Pattern"

2:13 yeah, the scratch blocks are a nice refinement. i've stolen them of course

2:14 but i also decided mutable variables had to go

2:14 bmuk: tolstoy that sounds more feasible, I just think of all the times people are going to have to create interactive environments for each domain and I cringe. Repeating work bothers me

2:14 I think that's what drew me to macros, sometimes I can't really abstract this away with a function, I need something more powerful

2:15 dysfun: macros are where graphical programming really falls apart for me

2:15 rhg135: You could have a core to build them with

2:15 Sharing code ftw

2:15 tolstoy: It seems much more difficult to "draw" a while loop, but using something to drag/drop to create music, better.

2:15 bmuk: a DSL for making interactive graphical DSLs

2:16 rhg135: Exactly

2:16 That's not confusing at all

2:16 bmuk: clojure seems like you could have a map -> filter -> reduce pattern that is graphically represented somehow

2:16 dysfun: one of the things that's pissed me off doing this actually has been that GUI libraries fucking suck.

2:17 it's very difficult to experiment when the libraries are so tedious to use

2:17 bmuk: dysfun: why use GTK/QT at all, use HTML+CSS

2:17 dysfun: well, that's what lighttable did

2:17 but i don't want to be tied to a browser

2:18 tolstoy: OSX has some sort of graphical thing you can use to hook up elements here to there ... quartz composer? Is that it?

2:18 dysfun: otherwise i wouldn't be doing an llvm backend for clojure

2:18 bmuk: what do you mean "tied to a browser"?

2:18 tolstoy: Kind of a neat visual language: (not that I understand it).

2:18 dysfun: tolstoy: are you thinking of automator?

2:18 quartz composer is for building special effects

2:19 tolstoy: dysfun That too, but I was thinking the graphical thing.

2:19 https://en.wikipedia.org/wiki/Quartz_Composer#/media/File:QuartzComposerSnowLeopard.png

2:19 Just an example of a specialized visual language, not general purpose, of course.

2:20 dysfun: oh there are many langs like that

2:20 if you look on the code golf stack exchange, you'll see a few crop up on random questions

2:20 bmuk: dysfun: wouldn't something like react-native divorce you from the browser?

2:21 dysfun: bmuk: i really haven't played with it

2:21 bmuk: unrelated, where is mapcar? I'm getting unable to resolve symbol

2:21 dysfun: for $startup, i'm encapsulating the bulk of the logic into a library and building a GUI for each supported platform separately

2:22 there isn't a mapcar in the standard library that i'm aware of

2:23 bmuk: I'm an idiot. I meant mapcat, but I typed mapcar XD

2:23 dysfun: if you're using it to 'stripe' multiple lists, map supports that natively

2:23 oh heh

2:25 you may also like http://conj.io/

2:25 bmuk: that's awesome, thank you

2:25 I've been using https://clojuredocs.org

2:26 dysfun: i tend to use ctrl-f rather than grimoire search though

2:26 the clojure cheatsheet is my fallback if arrdem breaks grimoire

2:27 bmuk: I'm pretty sure I have grimoire in my editor already. Not sure how to use it though

2:27 * dysfun isn't aware of a grimoire editor plugin

2:28 bmuk: https://github.com/syl20bnr/spacemacs/tree/master/layers/%2Blang/clojure

2:28 cider grimoire. I had no idea what it did until now

2:28 dysfun: cool :)

2:29 i keep putting off changes to my emacs config because it sucks programming an inferior lisp

2:29 bmuk: I used to make my own config by hand, but spacemacs does everything I want it to do. My config now consists only of enabling modes

2:30 ben_vulpes: imagine my surprise when i discovered that "superior lisp interaction mode" did not mean "a mode for interacting with a superior lisp"

2:30 bmuk: But I'm the weird variety that loves modal editing

2:31 ben_vulpes: bmuk: were evil-mode a little better, and were i to spend more time in non-lisps...

2:31 dysfun: don't most vim-using lisp programmers spend 50% of their time bouncing on the % key?

2:32 bmuk: maybe it's because I don't use enough of vim's features, but evil-mode is more than sufficient for me. I'm comparing it to Visual Studio's vim plugin though

2:32 dysfun: you can still use emacs chords in normal mode

2:32 dysfun: vim plugin is a comparatively easy proposition. an emacs plugin is basically impossible

2:33 bmuk: plus there is a lisp-mode where you can structurally edit

2:33 dysfun: paredit?

2:33 clojurebot: paredit is not for everyone, but what you need to understand ís how to become the kind of person that paredit ís for.

2:34 dysfun: paredit would be for me, but i can't be bothered to learn it

2:34 bmuk: https://github.com/syl20bnr/spacemacs/blob/master/doc/DOCUMENTATION.org#editing-lisp-code

2:35 dysfun: tbh a lot of internal emacs stuff needs overhauling a lot

2:35 tolstoy: I enabled paredit, then eventually learned on of the commands, and, centuries later, a second command. Still seems worth it just for the paren matching.

2:35 bmuk: true. Isn't someone writing it in clojure?

2:35 dysfun: DEUCE? Yeah, but he wasn't getting anywhere last i checked

2:35 ben_vulpes: bmuk: lol

2:36 bmuk: there's also yi

2:36 dysfun: problem he figured out is "if you can't run elisp, it isn't emacs". so he's spent a lot of effort there

2:36 tolstoy: Aren't the making progress converting the underlying interpreter to Guile Scheme?

2:36 prohobo: atom is the new emacs

2:36 except slow

2:36 and buggy

2:36 tolstoy: *shudder*

2:36 dysfun: and browser-bound

2:37 prohobo: but it IS genuinely nicer

2:37 dysfun: (yes, it's still a browser if your app is a single-purpose browser)

2:37 prohobo: the UI is worth it imo

2:37 bmuk: even if you also provide a terminal interaction mode?

2:37 prohobo: just, dear god, dont do any remote work

2:37 bmuk: (not saying atom does this)

2:37 ben_vulpes: prohobo: single threaded?

2:38 dysfun: bmuk: you know, terminals are better at that

2:38 prohobo: ben_vulpes: i think so, but it has these git extensions that require practically a full FS refresh on filesave

2:38 bmuk: no, I mean you can use the GUI mode (single purpose browser), or the cli app

2:38 prohobo: so its easy to lock up your entire editor when saving something remotely

2:38 bmuk: which both connect to a server running locally

2:39 think emacsclient

2:39 dysfun: it's definitely about time that emacs became concurrent

2:39 and got PCRE support

2:39 prohobo: i could never get minimap to work properly on emacs -_-

2:39 dysfun: even still, all those libraries wouldn't get ported

2:40 ben_vulpes: it's pretty easy to lock emacs up too, fwiw

2:40 prohobo: hehehe, u said "even still"

2:40 like an italian mobster

2:40 dysfun: it's honestly a case of someone is going to have to quietly build a better thing and port the libraries themselves and then release it upon the world

2:40 but that's an impossible ask

2:40 so we'll just keep using broken emacs

2:40 bmuk: why quietly?

2:40 prohobo: use broken atom, maybe it will outpace emacs

2:41 dysfun: because it's a problem that needs hammock time

2:41 and you can't have hammock time once it's unleashed upon the world

2:41 well, if it *is* actually better, anyway

2:41 bmuk: I'm suggesting develop it OSS so you have help

2:42 VapeNaysh: so i wrote a function that uses re-seq to convert matches into a new datastructure and do things to them

2:42 my test is comparing the result of this to another known value

2:42 bmuk: hammock time -> document strategy -> github -> profit?

2:42 VapeNaysh: and it appears to be failing because the first value is a lazy sequence still

2:42 which is confusing

2:42 dysfun: bmuk: basically the plan, yes

2:43 for everything i do

2:43 VapeNaysh: the returned value looks good except its apparently wrapped in a lazy seq

2:43 dysfun: well, i add "make it usable" to that list before github usually

2:43 VapeNaysh: code?

2:44 VapeNaysh: one sec

2:44 https://gist.github.com/hderms/0429d709f6e511fc0ce8435088c284dd

2:44 this is some of it

2:44 dysfun: bmuk: i like to demonstrate the feasibility of something with some useful code before i publish

2:45 VapeNaysh: you're comparing a set to a seq

2:45 bmuk: makes sense. Before I had a job I just used github like my private git server that just happened to be public

2:45 VapeNaysh: yeah i'd like to return a set instead of the seq

2:45 expected: (= (str->pieces "Q2") #{[2 100] [2 101] [3 100] [3 101]}) actual: (not (= (#{[2 100] [2 101] [3 100] [3 101]}) #{[2 100] [2 101] [3 100] [3 101]}))

2:45 dysfun: (into #{} ...)

2:46 VapeNaysh: ahh ok

2:46 great

2:46 clojure is very elegant just challenging to learn idioms

2:46 bmuk: so file-seq doesn't appear to be traversing child directories?

2:47 wait maybe I didn't reload my repl

2:48 VapeNaysh: so (into #{} (str->pieces ...)

2:48 right?

2:48 clojurebot: right is not wrong

2:48 dysfun: bmuk: try this http://raynes.github.io/fs/me.raynes.fs.html#var-iterate-dir

2:48 VapeNaysh: yes

2:48 VapeNaysh: it doesnt appear to be working

2:48 its wrapping it with another set now

2:49 actual: (not (= #{#{[2 100] [2 101] [3 100] [3 101]}} #{[2 100] [2 101] [3 100] [3 101]}))

2:49 bmuk: dysfun: I was using an old name for my function that was still left around in my repl

2:49 I'm pretty sure this works

2:49 dysfun: repaste the code. you've probably gotten the arrow positioning wrong

2:49 VapeNaysh: HERE WE GO

2:49 oops

2:49 i think i needed to apply

2:50 dysfun: i commented a suggestion on your post

2:51 oh wow. i forgot the markdown syntax

2:52 VapeNaysh: dysfun: replacing (into #{}) in your example with (apply set)

2:52 worked

2:52 dysfun: cool

2:52 VapeNaysh: thanks though

2:53 is that code relatively idiomatic though or does it look bad

2:53 like threading macro, etc...

2:53 using maps and anonymous functions

2:53 dysfun: well, i'd write it differently, but i'd need to see make-piece's code to give good advice

2:54 the art of good example code is giving something runnable so we can play with it in a repl

2:54 VapeNaysh: what kind of changes woud you make

2:54 dysfun: well for a start i'd abstract out that function in the middle

2:55 bmuk: how does this look so far: https://gist.github.com/bmuk/5899d95b6d510441f35993ab771ae6e2

2:56 dysfun: bmuk: well i'd rip out half of that code and use the 'fs' library i linked you to earlier, otherwise good

2:57 exists? and directory? are already written for you and expand is subsumed by another function

2:58 bmuk: the library you linked to earlier?

2:58 dysfun: > bmuk: try this http://raynes.github.io/fs/me.raynes.fs.html#var-iterate-dir

2:58 bmuk: exists? and directory? are already in the standard library?

2:58 http://clojure-doc.org/articles/cookbooks/files_and_directories.html

2:58 dysfun: no, they're in this library 'fs'

2:59 bmuk: ahh ok

2:59 ben_vulpes: https://github.com/Raynes/fs

2:59 ?

2:59 dysfun: yes

2:59 ben_vulpes: https://github.com/Raynes/fs/blob/master/src/me/raynes/fs.clj#L148 << classy

3:00 welp tooling day is complete

3:00 i have independent jvms for cljs and clj

3:01 there is even a figwheel for normals


3:01 ... for tonight.

3:03 bmuk: noob question, I can just :require [me.raynes.fs :as fs] after putting it in my project.clj? (I guess my real question is do you always remove the /)

3:03 dysfun: in this case, yes

3:03 ben_vulpes: [me.raynes/fs "1.4.6"]

3:03 wat

3:04 dysfun: however, there is not necessarily a mapping between the artifact name and the namespace

3:04 ben_vulpes: group-id/artifact-id

3:04 ben_vulpes: https://github.com/Raynes/fs/blob/master/README.markdown#the-most-recent-release

3:04 bmuk: where is the namespace documented? Usually the README has had some example that I get it from but there was none in this case

3:04 ben_vulpes: bmuk: just start reading through fs.clj

3:05 dysfun: either the README or the source files

3:05 ben_vulpes: or http://raynes.github.io/fs/

3:05 dysfun: the README links to the API docs. i linked you earlier too

3:05 the api docs tell you what ns something is in

3:06 ben_vulpes: semi relatedly, is it not possible to get a line link to a markdown file in github?

3:06 dysfun: i've always assumed it wasn't, but if you find out it is, let me know :)

3:06 ben_vulpes: a brief investigation indicates that it is not

3:07 thanks obama

3:07 bmuk: ah okay. I know there has to be a way to automatically reload and require everything in cider on save, I'm getting tired of typing (require 'doc-generator.core :reload)

3:07 dysfun: hooks?

3:08 ben_vulpes: bmuk: if you're using cider, why not C-c C-k to load the file

3:08 bmuk: I'm only familiar with mode-hooks but I guess there's probably a save hook as well

3:08 dysfun: bmuk: what is this json you're generating docs from btw? i'm curious (since i've got a docgen tool on the go)

3:11 bmuk: I'm experimenting with the idea of rewriting our web app in cljs (since it's already a separate project from the core web service anyway), but our api is undocumented. So I added a finally block in the ExecuteOperation method (called for every api operation) that converts the request and response objects to json and logs them to a file

3:11 with some other meta data that will probably evolve as this doc-generator does

3:12 I wanted to just start in on the cljs but proxying IIS from a VM to my macbook and sending incorrect json over and over again just to hit some breakpoints to see what was even going on was a nightmare lol

3:13 it wouldn't have been that big of a deal if our request and response objects were simple and flat, but they're pretty complicated

4:08 ridcully: dysfun: paredit and that sexp-somethingsomething plugin help to don't have to fall back to crude %

4:14 dysfun: :)

5:10 qsys: must be easy: how to go from [2 3 5 7] to [2 5 10 17] (each time: get next and add it to the result so far)

5:11 luma: ,(reductions + [2 3 5 7])

5:11 clojurebot: (2 5 10 17)

5:12 qsys: lol, easy it is :p

8:56 russellw: What is the recommended way to write parsers in clojure?

8:59 kwladyka: russellw do not write, use something what was done :)

9:01 russellw: kwladyka, well, if existing ones don't do what I need :)

9:02 luma: https://github.com/Engelberg/instaparse

9:03 Glenjamin: what is it you want to parse?

9:04 russellw: Glenjamin, dimacs, tptp, smt-lib

9:05 Glenjamin: i expect using the existing java parsers as a base will be the best bet there

9:07 russellw: From a quick skim thus far, the dimacs parsers seem to be unmaintained, dimacs and smt-lib are syntactically simple enough that it's not worth incurring a tricky dependency for, the tptp parser doesn't seem to be currently maintained either and is missing some features and is written with a Java parser library, so a one-shot effort of just writing a TPTP parser in clojure seems likely to pay

9:07 off better than dealing with that on an ongoing basis

9:08 Glenjamin: what does it mean to maintain a parser for something like that?

9:08 do the formats change?

9:08 russellw: tptp certainly does

9:09 Glenjamin: that seems a bit silly

9:09 russellw: Not disagreeing about that, but it's not up to me

9:09 Glenjamin: mm

9:09 i'd have assumed enough people were interacting with such things via java that you'd at least to be able to get some classes representing the data :(

9:10 russellw: You can for some input files but not for ones that use language features the parser doesn't support

9:12 luma, thanks, that looks interesting. If I understand correctly, for a nontrivial language, you write the grammar in a text file - presumably lein can package a text file into an uberjar? instaparse wants to read the text file at runtime, but hopefully that only takes a few milliseconds, no significant performance impact?

9:12 luma: yep

9:13 russellw: Cool, I'll try it out, then

9:13 luma: if you already have your language in EBNF, you should be able to plug it directly into instaparse

9:23 irctc: How to do the equivalent of int i = (int)l where l is a long in Clojure?

9:24 Glenjamin: ,(int 100)

9:24 clojurebot: 100

9:24 Glenjamin: (doc int)

9:24 clojurebot: "([x]); Coerce to int"

9:25 irctc: ,(int Long/MAX_VALUE)

9:25 clojurebot: #error {\n :cause "Value out of range for int: 9223372036854775807"\n :via\n [{:type java.lang.IllegalArgumentException\n :message "Value out of range for int: 9223372036854775807"\n :at [clojure.lang.RT intCast "RT.java" 1205]}]\n :trace\n [[clojure.lang.RT intCast "RT.java" 1205]\n [sandbox$eval71 invokeStatic "NO_SOURCE_FILE" 0]\n [sandbox$eval71 invoke "NO_SOURCE_FILE" -1]\n [clojure.la...

9:25 irctc: So, it's not the same

9:26 Glenjamin: what does int cast do in java?

9:26 (doc unchecked-int) you probably want this then?

9:26 clojurebot: "([x]); Coerce to int. Subject to rounding or truncation."

9:26 Lewix: ,(int64 100)

9:26 clojurebot: #error {\n :cause "Unable to resolve symbol: int64 in this context"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: Unable to resolve symbol: int64 in this context, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "Unable to resolve symbol: int64 in this...

9:27 Lewix: ,(long 100)

9:27 clojurebot: 100

9:27 Lewix: ,(long Long/MAX_VALUE)

9:27 clojurebot: 9223372036854775807

9:27 Lewix: irctc: hew you go

9:27 irctc: I want the bottom 32 bits

9:30 yes, unchecked may be working

9:31 Glenjamin: looks like it: https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L1451

9:31 irctc: yep -- thanks!

9:32 Lewix: ,(bit-shift-left LONG/MAX_VALUE 15)

9:32 clojurebot: #error {\n :cause "No such namespace: LONG"\n :via\n [{:type clojure.lang.Compiler$CompilerException\n :message "java.lang.RuntimeException: No such namespace: LONG, compiling:(NO_SOURCE_PATH:0:0)"\n :at [clojure.lang.Compiler analyze "Compiler.java" 6688]}\n {:type java.lang.RuntimeException\n :message "No such namespace: LONG"\n :at [clojure.lang.Util runtimeException "Util.java" 221]}]...

9:33 Lewix: ,(bit-shift-left Long/MAX_VALUE 15)

9:33 clojurebot: -32768

9:33 Lewix: ,(bit-shift-left Long/MAX_VALUE 14)

9:33 clojurebot: -16384

9:33 Lewix: ,(bit-shift-right Long/MAX_VALUE 14)

9:33 clojurebot: 562949953421311

10:22 melipone: Hiya! I have an incanter question

10:25 I am getting an error with incanter 1.9 on the principal-components with the Iris dataset as in the example given in the documentation

11:16 clgv: hello, how exactly do you tell leiningen to work with metadependencies where maven central contains only a pom file with information about the other needed artifacts?

11:18 TimMc: You just include the coordinates of that metadependency, yeah?

11:20 clgv: TimMc: well, it did not fetch anything but complained "Could not find artifact org.uma.jmetal:jmetal:jar:5.0 in central"

11:21 TimMc: providing [org.uma.jmetal/jmetal "5.0" :extension "pom"] just makes Leiningen happy enough to not complain, but none of the artifacts is fetched

11:22 TimMc: Interesting.

11:30 Can reproduce with 2.6.1

11:51 clgv: Looks like half of this is discussed at https://github.com/technomancy/leiningen/issues/1451

11:51 clgv: TimMc: ah thank you

11:52 TimMc: https://github.com/technomancy/leiningen/issues/1866 is linked from that, might be the same issue or different

11:52 I think different.

11:53 clgv: well, manual deps then...

11:53 luckily there are only 4 of them ;)

12:00 Glenjamin: why would they do that?

12:00 (have a pom-only thing)

12:31 bsima: Does anyone know of any custom core.async buffer types? I'm thinking about creating a buffer that interfaces with kafka logs, thus creating an immutable channel

12:31 this is the only one I've found so far https://github.com/steveyen/ago/blob/master/src/ago/core.cljs#L102-L147

12:36 dysfun: umm, why would it be a buffer?

12:36 the purpose of a buffer is to... buffer

12:37 if you wanted to treat kafka as a queue, you would instead connect a kafka client to a channel

12:37 so that each time you became aware there was something for the taking, it placed it onto the channel

12:39 and for publishing, you would publish to a channel and the kafka client would transmit it

13:00 bsima: dysfun: If I can mimic the core.async api, then I can reuse a lot of code

13:01 in development I use channels to pass maps between components, but in prod I want this data to be stored in kafka

13:02 yeah its kinda blurring the lines between "queue" and "channel" and "log", but I don't think thats a problem

13:09 tolstoy: Maybe make a super set abstraction with core.async and kafka implementations?

13:19 sdegutis: Good evening.

13:20 How is it?

13:23 dysfun: bsima: it's not an idiomatic way of modelling it

13:23 the idea of channels is to disconnect the sender from the receiver. that you happen to put another process is a non-event. your application code remains otherwise the same

13:31 sdegutis: What is Up?

13:31 dysfun: the sky?

13:31 the opposite of down?

13:32 Glenjamin: bsima: dysfun one of the best explanations of the difference I've heard was that channels cannot fail

13:32 but as soon as you put a network in there, you have problems you now need to deal with

13:32 russellw: For a function that takes a filename as input, parses the contents of the file and returns a syntax tree, what's the typical/idiomatic name for the function? load-foo, parse-foo, read-foo, something else?

13:33 dysfun: Glenjamin: i'm not going to pretend the picture is perfect, but better to deal with that in one place

13:33 Glenjamin: (foo/parse) perhaps?

13:33 sdegutis: dysfun: no its a movie

13:33 Glenjamin: dysfun: i guess that depends on whether you plan to make every component optionally in another process

13:33 sdegutis: One which I will not say whether it is good or bad, because I refuse to pass judgement on such a crappy movie.

13:34 russellw: Glenjamin, ah, so use the fully qualified name and let the module name be the root? That makes sense, thanks

13:34 dysfun: Glenjamin: we're not erlang

13:34 sdegutis: how many litres of beer does it take to make it watchable?

13:35 sdegutis: dysfun: nobody counts in litres anymore, its the 90s man

13:35 dysfun: litres are a much better unit than pints. they're a lot bigger for a start

13:35 sdegutis: get with the times dude

13:35 nobody counts in pints anymore, what is this medieval yourup?

13:35 dysfun: are you drunk again?

13:35 sdegutis: Good evening. How are you all doing this fine day?

13:36 dysfun: i dignify to refuse that with an answer

13:36 dysfun: hard day at work, was it?

13:37 sdegutis: Our CEO and I just had a nice long meeting.

13:38 Afterwards I sent an email suggesting we may want to make use of more agile ways of communication, to increase productivity in development and other areas of our respective tasks.

13:39 Agile is big here, so he agreed and we're going to move forward with this, and benefit from it all around.

13:39 So yeah, it's been a productive day.

13:39 I'm about to start programming in a minute.

14:10 uto: How I merge two maps while preserving the order? Basically (merge {:a 1 :c 2} {:d 3 :b 4}) returns {:a 1 :b 4 :c 2 :d 3} but I want {:a 1 :c 2 :d 3 :b 4}

14:10 opqdonut: maps don't have order

14:11 though there is sorted-map

14:11 if you care about order you should probably use a sequence of pairs

14:12 rhg135: ordered-map too

14:13 opqdonut: rhg135: where is that?

14:14 rhg135: I don't remember exactly

14:16 tolstoy: https://github.com/amalloy/ordered

14:16 opqdonut: right

14:19 tolstoy: Good code there to help figure out what you have to do to implement something that satisfies map.

14:20 russellw: How do you get instaparse to ignore whitespace between tokens?

14:22 sdegutis: uto: or you can turn a map into a sequence of map-entries

14:22 ,(map-entry? (first {:a 1}))

14:22 clojurebot: true

14:22 sdegutis: ,(map type {:a 1})

14:22 clojurebot: (clojure.lang.MapEntry)

14:23 sdegutis: ,(map type {:a 1, :b 2})

14:23 clojurebot: (clojure.lang.MapEntry clojure.lang.MapEntry)

14:23 sdegutis: uto: you'd probably turn them into a coll of map-entries by sorting it

14:23 ,(->> {:a 3 :b 2 :c 1} (sort-by val) (map type))

14:23 clojurebot: (clojure.lang.MapEntry clojure.lang.MapEntry clojure.lang.MapEntry)

14:24 sdegutis: ,(->> {:a 3 :b 2 :c 1} (sort-by val) (map (juxt identity type)))

14:24 clojurebot: ([[:c 1] clojure.lang.MapEntry] [[:b 2] clojure.lang.MapEntry] [[:a 3] clojure.lang.MapEntry])

14:24 sdegutis: There there.

14:32 (doc val)

14:32 clojurebot: "([e]); Returns the value in the map entry."

14:32 sdegutis: (doc key)

14:32 clojurebot: "([e]); Returns the key of the map entry."

14:38 lokien_: Heyy guys, is there any list of functions/macros everyone should know? Like "top 100 functions" or something?

14:39 russellw: lokien, http://clojure.org/api/cheatsheet

14:41 lokien_: russellw: that's like "every function"

14:41 but probably I'm wrong

14:41 russellw: I don't think it's quite every function, though it is impressively comprehensive for such a compact document

14:43 lokien_: I'd like something different, but thanks, still

15:06 kwladyka: I wrote article when use vars, atoms, agents, refs and async. I share it with you http://clojure.wladyka.eu/posts-output/2016-04-06-concurrency.html Please give me feedback if all is clear. Maybe i can improve something? It is very complex topic and i want stay with short text. What do you think about flowchart? Do you agree with it? Any idea how can i do it better?

15:09 I feel i can do it better but i need some feedback :)

15:14 Glenjamin: kwladyka: i'd say the var example, while it works, isn't very representative

15:15 kwladyka: Glenjamin do you prefer example with binding or what kind of example?

15:15 Glenjamin: generally vars are only used at the top level, and are there to make late binding work when evalling stuff at a repl

15:15 in practice, they don't really change at runtime i'd expect

15:17 kwladyka: generally this article don't explain all possibilities and power of them. As i mentioned on the beginning. It is more to which one should i choose for me, then about how to use it in most powerfull way. I guess then i can write separate topic for each of them. But from other side maybe i should give more examples...

15:18 Glenjamin: the examples you have are fine, i just think the vars example is showing something that no-one really does

15:20 kwladyka: yes, but it showing technical aspect how it is working. Can you propose better example?

15:20 Glenjamin: i wouldn't categorise a var as a concurrency construct at all actually

15:21 your flow chart is correct that if the data ever changes, you shouldn't use a var

15:21 kwladyka: but what i saw people ask what to use and also include varts to the question

15:22 Glenjamin: my usual advice is: use an atom until it doesn't work

15:22 amalloy: the ref example is bad, because (println "read, foo:" @foo "bar:" @bar) isn't enclosed in a dosync

15:22 kwladyka: haha ;)

15:22 amalloy: so you might read inconsistent values

15:23 kwladyka: amalloy but alter is in dosync. How can i get inconsistent values then?

15:23 amalloy: you can read foo, then a commit happens, then you read bar

15:23 kwladyka: it is exactly to show that alter will commit when dosync end

15:24 amalloy: try throwing a (Thread/sleep 5000) in between those two derefs

15:24 kwladyka: amalloy it is exactly about that it can't happen

15:24 it is why to use refs

15:24 amalloy: then it is exactly wrong

15:24 kwladyka: did you read text?

15:25 what is wrong there

15:25 ?

15:25 amalloy: did you try my suggestion?

15:25 kwladyka: hang a sec

15:27 amalloy between which one? In println?

15:27 amalloy: yes

15:27 in the "read", not "updated", thread. the one that's not in dosync

15:28 dosync/alter guarantee that if you take a snapshot of the world at any time, all refs will be in a coordinated state. but you don't do that: you take *two* isolated snapshots, with your two derefs

15:28 how can the runtime possibly know you intend those two to be coordinated

15:29 kwladyka: oh because println don't read them in the same time, it is very small chance for that, but it is. Thanks for suggestion.

15:29 of course not in this example, because alter run longer, but generally i can do better example

15:30 thx

16:25 I just did new version http://clojure.wladyka.eu with some improvements

16:31 What do you think now about flowchart?

16:35 lokien_: kwladyka: as a still learning person, thank you for that

16:36 kwladyka: lokien_ nice to hear that :)

16:38 TimMc: kwladyka: You might talk about how it is unsafe to modify vars from more than one thread at once, and modifying them at all is generally not something to rely on.

16:38 lokien_: kwladyka: can you make more posts like this in the future? I feel like they're needed in the community, as we don't have anything like that yet

16:39 kwladyka: TimMc it is good idea, but i am not sure it will be still in the topic

16:39 lokien_ i am trying but it consumes so much energy and time :)

16:40 lokien_: kwladyka: keep going, I believe in you :)

16:40 kwladyka: lokien_ i can recommend also read article how to improve algorithm speed, that was my mile stone in clojure.

16:40 TimMc: kwladyka: As it is, it looks like you are putting vars on the same level with constructs that are used as data structures, and that might mislead someone into trying to use set! to bash on vars

16:40 lokien_: kwladyka: 4 boring classes tomorrow, I'm sure I'll read that :D

16:41 TimMc: Oh good, you do cover that in the flowchart.

16:41 kwladyka: TimMc is good or bad? :)

16:42 TimMc can you propose better example for vars?

16:42 TimMc: That's good, I think it would be better to include a very short statement in the vars section about how vars are not generally intended for modification.

16:43 In the flowchart, I don't think the non-idempotent functions branch should lead to refs.

16:43 Same for the long-running functions branch. Refs can have contention, just like atoms.

16:43 (Well, differently than atoms, actually.)

16:46 kwladyka: maybe i should add additional condition but not sure what should be the question

16:47 TimMc what i now refs retry when read the same ref more then one time if it was alter on that ref during that. Any other cases?

16:48 but generally read the same ref in dosync more then once is not something common

16:48 i don't know other cases when ref retry

16:51 TimMc: kwladyka: Refs are modified optimistically. If two threads try to modify the same ref during concurrent transacations, one backs out and retries.

16:52 If there were side-effecting calls during the transaction, you might get in trouble.

16:52 You might also want to draw a distinction between idempotency and side-effects.

16:53 sdegutis: Hey amalloy.

16:55 kwladyka: TimMc not if you call side-effect after alter :P But yes you have right. I should do additional question in flowchart, but not sure how to do it clear.

16:57 WorldsEndless: What library is recommended for making API requests (get, post, the others)?

16:57 TimMc: HTTP calls?

16:57 WorldsEndless: Yeah

16:57 sdegutis: WorldsEndless: I use clj.http-lite or whatever it's called

16:57 WorldsEndless: it's got minimal dependencies and does all the things i need

16:58 kwladyka: WorldsEndless Clojure or ClojureScript?

16:58 TimMc: https://github.com/dakrone/clj-http is pretty nice

16:58 WorldsEndless: kwladyka: Just Clojure

16:59 sdegutis: TimMc: yeah thats the one that links to the one i use

16:59 WorldsEndless: TimMc: Looks like the one that http-lite thinks is too heavy

16:59 kwladyka: WorldsEndless so like TimMc wrote

16:59 sdegutis: https://github.com/hiredman/clj-http-lite

16:59 WorldsEndless: Any major reasons to go with http instead of http-lite?

16:59 sdegutis: WorldsEndless: look at "Differences from clj-http" on my link

16:59 WorldsEndless: if you need any of those then go with http-fat

17:00 WorldsEndless: i did not need any of those things so i went with http-light

17:00 WorldsEndless: Got it. I don't think I need any of those things, either, unless I end up needing the JSON decoding

17:01 sdegutis: WorldsEndless: it doesnt do *automatic* json decoding, but you can still decode your own json from the :body key

17:01 WorldsEndless: i use clojure.data.json to decode the :body key into a json thing along with http-skinny

17:01 kwladyka: WorldsEndless light has last update a year ago

17:01 sdegutis: kwladyka: when a thing is done, its done.

17:01 WorldsEndless: lol

17:01 sdegutis: if it aint broke, dont fix it

17:02 WorldsEndless: sdegutis: Said like an emacs user?

17:02 kwladyka: generally i most of cases it means something

17:02 sdegutis: WorldsEndless: i use 'choose'

17:02 kwladyka: but in that one of course it can be ok

17:02 sdegutis: https://github.com/sdegutis/choose/commits/master

17:02 last real-world commit was march 2015

17:02 i mean real-stuff commit

17:02 and hey it still works 13 months later

17:03 kwladyka: last time of commit is my personal decisive factor. Software is never done :)

17:04 sdegutis: kwladyka: i used to think that way too.

17:04 kwladyka: sometimes inactive software is actually just done though.

17:05 kwladyka: in the readme i can read "No support for insecure HTTPS connection (yet" and last commit is a year ago

17:05 It is enough for me to choose http-clj

17:05 sdegutis: like, 'choose' does one job but does it well. the only time ill ever need to update it is if Apple changes some API and deprecates any of the ones this uses on like OS X 10.15 or whatever

17:05 kwladyka: then choose http-big

17:06 kwladyka: but still it is my personal decisive factor form my experience. Find you own way :)

17:07 WorldsEndless: Yeah, the "supported" factor is a big one, given that this app should have longevity and maintainability

17:09 sdegutis: WorldsEndless: thats a hard thing to predict

17:10 WorldsEndless: for example predicting dommy vs domina was hard

17:11 and if you looked at their commits, they're both relatively inactive about the same amount

17:12 kwladyka: TimMc I am thinking about flowchart and what you said... but when somebody use not idempotent functions and need synchronise access there is nothing better then refs. Isn't it?

17:54 sdegutis: TIFU by using some? on a value that had a boolean value returned.

17:55 I mean some? is great but I need to be more careful about these things.

18:00 parenjitsu: I'm curious, is there any consensus about the best libraries for spinning up a convention-over-configuration API server with Clojure?

18:01 amalloy: shell out to rails

18:01 parenjitsu: Pretty much just authentication, and then a thin serialization layer between http and the database

18:01 amalloy: I hadn't considered that

18:02 amalloy: well it's not really good advice, so much as a claim that clojure doesn't really do "convention over configuration"

18:02 Glenjamin: (inc amalloy) that made me chuckle

18:02 amalloy: if that's an important feature for you, try rails or python

18:02 parenjitsu: Yeah, that's kind of a community thing

18:03 cultural thing

18:03 a clojure version of Rails API would be awesome

18:04 maybe a good lost weekend project

18:04 Glenjamin: what would it do that rails api doesnt?

18:04 parenjitsu: I guess what I would get out of it would be:

18:04 Glenjamin: there is compojure-api and liberator, but afaik they don't attempt to deal with either auth or databases

18:05 parenjitsu: 1. I could spin up a database, api-server and clojurescript frontend boilerplate in a couple minutes

18:06 2. If the API layer needs to get smarter, I can write it in clojure, instead of ruby

18:08 patchwork: parenjitsu: You can pretty much do this with luminus, last I checked

18:08 parenjitsu: patchwork: I'll give it another look, thanks

18:08 Hadn't seen compojure-api before either. The swagger integration looks great.

18:09 (been away from clojure for a few years, trying to get back up to speed)

18:13 {blake}: Ever-changing-poorly-documented-fragile-convention Over Configuration!

18:14 That said: I'm using straight JDBC for a web app and now I want to allow the user to page through results of a select. Opinions?

18:14 Glenjamin: LIMIT?

18:14 :D

18:15 {blake}: Brilliant! A series of calls using "Limit 1" should produce just what I need!

18:15 Glenjamin: which bit did you want an opinion on?

18:15 {blake}: Heh. Paging isn't really a big issue here. The database isn't so big that I =shouldn't= be able to load it all into memory.

18:16 Glenjamin: i'd normally do a count, and then render page links with offset=x&pagesize=y

18:16 {blake}: It's a one-at-a-time viewer.

18:16 parenjitsu: {blake}: usually the client would pass in a page parameter and that would transformed into OFFSET and LIMIT to get the appropriate results

18:16 Glenjamin: oh, then y=1 and it's easier

18:16 parenjitsu: lol

18:16 {blake}: parenjitsu: Oh, so I really can do "Limit 1" if I combine with "Offset"! Ha!

18:17 I can't believe Codd & Date would approve somehow.

18:18 Glenjamin: one thing you want to watch out for, is new items getting added during paging

18:20 {blake}: Or deleted, I presume. Shouldn't be an issue here.

18:20 I'm mostly trying to figure out if it's worth it to switch from straight JDBC.

18:20 To any of the multitude of SQL libs.

18:20 Glenjamin: unlikely, i don't think they'd help here

18:21 {blake}: I'm only suspicious because that's the answer I want.

18:22 Glenjamin: they mostly help you write SQL, although I do quite like yesql

18:24 {blake}: They all look okay, but I feel like they all would take time to get up to speed. Maybe not much, but I'm...behind. =P

18:37 srruby: loop/recur - Can I use let to define local variables ?

18:38 justin_smith: srruby: locals of what scope?

18:38 srruby: local to the "invocation of the loop".

18:38 justin_smith: srruby: within one iteration, definitely, if each iteration might modify the binding, it goes in the loop binding vector instead

18:38 srruby: Thanks.

18:44 sdegutis: right

18:48 tolstoy: If I want to have a little "storage" data structure that I persist to disk on change, would it make sense to have it implement the IAtom protocol or the IPersistentMap protocol rather than come up with something custom?

18:49 Seems like (assoc storage :key "value") implies immutable values, while (swap! storage assoc :key "value") at least suggests it's mutable.

18:49 amalloy: tolstoy: my first step would be to do none of that, but instead research the thousands of other attempts people have made to implement this exact feature

18:49 there is probably one that meets your needs

18:50 justin_smith: tolstoy: I would attach a single thread to a queue, and put the modifications to that data structure on the queue. This could be expressed as a function that sends an action to an agent, a core.async go block looping on a chan, or a java concurrent queue with a thread polling it

18:50 Glenjamin: add-watch -> spit

18:51 tolstoy: amalloy: Good idea, I'll do that.

18:51 justin_smith: That's implementation, I'm talking about the interface.

18:52 Glenjamin: i do like how lots of clojure libs start their README with a picture of something

18:52 amalloy: you're going to have a hard time making something that's truly atomic in the face of multiple threads when you involve the disk

18:52 so you'll have to decide what kind of contract you want to support

18:53 *then* you can start looking at things like justin_smith's and Glenjamin's suggestions, which each do some rather surprising things in the case of concurrent modification

18:53 tolstoy: But is it just a bad idea to implement those existing Clojure interfaces, all that other taken of?

18:53 Glenjamin: i mostly suggested mine as a contrast to demonstrate the range of possibile answers

18:53 amalloy: implementing IAtom might be fine

18:54 ben_vulpes: does anyone know how to get the string that clojure.java.shell/sh tried to evaluate back out of it?

18:54 amalloy: implementing IPM would be evil imo

18:54 "tried to evaluate"?

18:54 hiredman: implementing IAtom for something that only wraps a map seems really weird

18:54 and you would need to do really weird stuff to implement (swap! … assoc k v)

18:54 since assoc works on maps

18:55 ben_vulpes: "tried to evaluate" -> "passed to Runtime.exec()

18:55 "

18:55 Glenjamin: having assoc write to disk seems weirder though

18:55 asdf12z_: what is the symbol ^ mean?

18:55 hiredman: implementing IPM for something that isn't a value is terrible

18:55 asdf12z_: does*

18:55 ben_vulpes: amalloy: ^^

18:55 Glenjamin: asdf12z_: metadata

18:55 amalloy: ben_vulpes: that's the arguments you passed to shell yourself

18:55 just look at them before you call shell

18:55 hiredman: asdf12z_: http://clojure.org/reference/reader#_metadata

18:56 amalloy: hiredman: does it only wrap a map? i was imagining since he's just going to use pr-str/spit/read-string/slurp, it would work for other non-map things

18:56 * ben_vulpes goes back to looking for the broken coercion

18:56 Glenjamin: ben_vulpes: you could trace it perhaps

18:57 hiredman: amalloy: could be, but if that is the plan, why the heck would tolstoy be talking about implementing IPM?

18:57 amalloy: over-focus on the current situation, where what he's thinking of persisting happens to be a map

18:59 hiredman: anyway, either way, do neither

18:59 either using a map or a map in an atom

18:59 don't implement anything

18:59 tolstoy: Heh. Well, that's the safe route.

19:00 ben_vulpes: Glenjamin: nah i just thought really hard for a half second

19:00 Glenjamin: usually a good bed

19:00 bet

19:00 eugh

19:02 hiredman: whatever you do, don't decide the transient interfaces make more sense, then implement them for a mutable store that obviously doesn't have transient semantics then submit it to lobsters so everyone can see how cool it is

19:02 Glenjamin: yeah, submit to r/clojure instead

19:03 ben_vulpes: AA

19:03 AAAAAA

19:03 AAAAA

19:03 hiredman: scary.

19:04 hiredman: and then sits on the lobsters frontpage for a while, which tells you how much of a grain of salt to apply to that sort of thing

19:05 amalloy: i hadn't heard of lobsters till now

19:06 hiredman: it is a thing

19:06 tolstoy: It's somehow ... better ... than hacker news, right?

19:06 amalloy: "better"

19:08 hiredman: slightly less startup stuff, which is nice, trends slightly more technical

19:09 tolstoy: I don't see a lot of "persist / cache a data structure to disk" things out there. Must not know the right keywords.

19:09 I'm not worried about implementing it myself. Just was curious about using some Clojure interfaces for a basic key/value thingy.

19:09 amalloy: https://github.com/alandipert/enduro is the first one i found

19:09 hiredman: tolstoy: atoms that use watchers to read and write to disk are a common thing people do

19:09 I would recommend using apacha derby

19:10 tolstoy: Derby seems too heavyweight for two or four keys. (I'd use h2, probs.)

19:10 amalloy: it has plenty of problems in the face of concurrency

19:11 hiredman: lobsters big, I dunno, claim to fame?, is the user tree, to get an account you need an invite, and you can go look at the tree of invites https://lobste.rs/u

19:11 amalloy: tolstoy: if you want more reading, searching for `clojure persistent durable atom` works pretty well

19:11 tolstoy: Okay. I just found konserve.

19:11 amalloy: Lobsters 'R' U

19:11 Glenjamin: tolstoy: what is your wider context here?

19:11 tolstoy: App needs to generate a couple of UUIDs that need to persist across restarts. No persistence other than that.

19:12 Glenjamin: how much do you care about data loss?

19:12 tolstoy: BUT, I might like to make a component out of it. And maybe store some additional stuff when running in simulator mode.

19:13 Glenjamin Reasonably concerned, but if a sysadmin comes along and kills the file, well, *shrug*.

19:13 Glenjamin: i was thinking more along the lines of synchronous vs asychronous write

19:13 tolstoy: This is code running on a device shipped to customers. It does connect to the "cload". IMHO, a better solution is that it calls home with a hostname and gets back an ID. ;)

19:14 Glenjamin: do said uuids change?

19:14 tolstoy: Oh, well, I wrote my own fatom before and used core.async, I think. Maybe locking.

19:14 They shouldn't.

19:14 Glenjamin: you could just write text to disk on first start i suspect

19:14 tolstoy: Yes.

19:15 And never change it ever after. That works.

19:16 Anyway, it sounds like if someone had a good reason to write a file-backed "thing" such that adding or removing stuff from it was reflected on disk, implementing IAtom is sketchy, and IPersistentMap is misleading (at best).

19:18 Then again, enduro does that.

19:20 Glenjamin: why do I keep reading HN :(

19:44 rhg135: implementing IPM for a file write, that's wow

19:51 tolstoy: Lay it on me, buddy.

20:05 rhg135: I'm sure in certain languages that'd be great

20:06 along with 1 = '1'

20:07 tolstoy: Well, I didn't think it was a good idea, so I won't defend the unmitigated temerity it took to publicly suggest it. ;)

20:14 rhg135: the sad part is I know there's people who think it's a good idea

20:38 VapeNaysh: hey so using loop/recur. If I want to like start the bound values with defaults would I wrap the (loop ...) form with some kind of (let..) binding

20:39 like first iteration it starts with let bound values but every further iteration will loop rebind them and shadow over the let binding?

20:42 is this the right way to do something like that

20:45 nvm im stupid

20:45 tolstoy: If you do (let [xs (foo x)] (loop [xs xs] .... (recur (rest xs)))) ... (foo x) is only called once. ;) Okay. ;)

20:47 VapeNaysh: yeah i saw that loop has bindings

21:45 asdf12z_: uh when i run lein repl, it's not installing my dependencies? lein deps :tree looks ok

21:46 oh nevermind

21:57 bendlas: do ^:unsynchronized-mutable deftype fields still work?

21:59 sdegutis: Good morning.

22:02 justin_smith: I have a race condition, help.

22:42 asdf12z_: so if i wanted to make a constant, but local to a function, how would i do that? just use let? is there a performance issue over using def ?

22:46 machinewar: https://gist.github.com/AlexWheeler/84503e2fe46c37f2f2dcd31a294e49f8 having trouble with basic reduce function, when I call (even-or-odd [1 2 3 4 5]) I get (5)

22:47 expecting {:evens [2 4] :odd [1 3 5]}

23:10 hiredman: it would be illuminating for you to print the arguments to your reducing function

23:10 also maybe print out what the function returns every time it is run

23:12 or just, sort of step through it in your head, what are the arguments the reducing function will get the first time it is called, what will be returned from it

23:20 TEttinger: reductions can be handy too.

23:20 ,(reduce + [10 20 30 40])

23:20 ,(reductions + [10 20 30 40])

23:21 clojurebot: 100

23:21 (10 30 60 100)

Logging service provided by n01se.net