#clojure log - May 18 2016

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

0:45 Gh0stInTheShell: if I want to write generalized code for the JVM and then later I want it to work with Clojurescript, is that reasonable

0:45 ?

0:46 what about, like, the java math libs? I can't call those, right?

0:46 dysfun: correct

0:46 Gh0stInTheShell: so how do I round numbers?

0:46 matt_d: Gh0stInTheShell: yup, cant call java libs using clojurescript

0:46 dysfun: but you can use feature expressions to provide alternate implementations for clojure and cljs

0:46 Gh0stInTheShell: dysfun: okay will check that out, thank you

0:46 dysfun: i do it a lot in my modules because i use native java string functions

0:47 #?(:clj ... :cljs ...)

0:47 where ... is one form

0:47 #?@(:clj [...] :cljs [...]) for slicing

0:47 Gh0stInTheShell: gotcha

0:47 dysfun: splicing*

0:47 Gh0stInTheShell: you guys think of almost everything :)

0:48 dysfun: https://github.com/irresponsible/oolong/blob/cljs/src/irresponsible/oolong/util.cljc

0:48 we try :)

0:49 although we stole those from common lisp

0:49 Gh0stInTheShell: :)

0:49 dysfun: you use .cljc files if you need feature expressions

0:49 Gh0stInTheShell: 'You guys' goes all the way back to Gosper or Greenblatt or whatever ;)

0:49 dysfun: they can become clojure or clojurescript or whatever else we support next

0:50 you can also have a .clj file and a .cljs file with the same module name

0:50 engblom: I wish you would also have been "stealing" native compilatation (not compilation for jvm, javascript, .net)

0:50 dysfun: that's one of my side projects

0:50 but i might just jump to lfe instead

0:51 i do find it a bit annoying at times that clojure chose the jvm, but it's meant good things for clojure

0:54 Gh0stInTheShell: is clojure more performant on Dalvik/ART than JVM?

0:54 engblom: dysfun: I am in particular interrested in programming control system with tiny computers like rpi. Native compilation would be great for this kind of platform, especially as it would probably mean easier to use kernel sys-calls for faster IO.

0:54 dysfun: Gh0stInTheShell: there are...issues with android and clojure

0:55 engblom: dysfun: Or interfacing native libraries

0:55 dysfun: engblom: i'm use lfe for a raspi project

0:55 yes, native libraries are where i have problems with clojure too

0:55 because JNI = no thanks, hope someone else did it already

0:55 Gh0stInTheShell: dysfun: But I keep watching talks about writing games for android with clojure? Is it all a bad idea?

0:55 dysfun: no, but it will make your app slower to start up

0:56 would you rather write it all in java? ;)

0:56 Gh0stInTheShell: dysfun: :)

0:57 dysfun: honestly most people deploying to phones are using cljs

0:58 Gh0stInTheShell: dysfun: Using cljs on top of Apache Cordova?

0:59 or similar?

1:01 dysfun: pretty much

1:01 you gain support for other platforms for free

1:02 there's an up-to-date webkit component for cordova

1:04 my app problem is worse, i have a lot of code to be shared across all platforms, so i wrapped it up into a c++ library

1:04 c++ turns out to be the only sane way to do this

1:04 then native guis

1:05 Gh0stInTheShell: :(

1:06 dysfun: when i was looking at clojure native compilation, i thought it would be fun to use native interop syntax for c++ classes

1:07 Gh0stInTheShell: cause c++ is just like sane java :)

1:07 dysfun: exactly like it, obvs :)

1:07 Gh0stInTheShell: How hard could it be? :P

1:07 dysfun: well i doubt it will surprise you terribly much to hear it can be very hard

1:07 Gh0stInTheShell: not surprised ;)

1:07 justin_smith: depends how you feel about memory leaks maybe?

1:08 dysfun: justin_smith: i use the jvm, it *is* a memory leak

1:08 Gh0stInTheShell: In 1999 I felt, much like the rest of the industry, that C++ was the only sane way to do anything....

1:08 dysfun: in the modern days there are still areas where c++ is the least insane choice

1:09 i still write quite a lot of c++

1:09 mostly because i can't afford to pay someone else to :p

1:09 justin_smith: I got a PR accepted on csound (a c project) over the weekend

1:09 not going to pretend it was a complex contribution...

1:09 dysfun: i contributed to some post-quantum crypto written in C the other week

1:09 that's a challenge

1:10 crypto puts loads of extra constraints in play

1:10 Gh0stInTheShell: There's still problems where I like the memory model in c and c++ better than JS or Java or clj. it lends well to things like fast manipulations of memory etc

1:11 dysfun: 'manipulation of memory'. the antithesis of clojure

1:12 i don't like the js machine because most browsers don't support proper ints yet

1:14 Gh0stInTheShell: (inc dysfun)

1:14 I agree

1:14 dysfun: i don't like the JVM at the part i have to write JNI, to the degree that i never do it

1:15 look at how non-jvm langs handle this, it tends to be a simple interface you can drive easily from C

1:15 Gh0stInTheShell: and then you just write bindings in your fave langs etc

1:15 But they're not on the JVM :)

1:16 dysfun: yeah, which means i can't use clojure. shame, but them's the breaks

1:16 and so i've concluded java is absolutely fine for long running server processes and very little else

1:17 Gh0stInTheShell: but there's cljs :)

1:17 with the crappy ints

1:17 dysfun: and deploy node to production? are you kidding me?

1:18 Gh0stInTheShell: with unstable web workers so it's truly multithreaded

1:18 :)

1:18 dysfun: webworkers suck

1:18 Gh0stInTheShell: oui

1:18 dysfun: you have to load a separate script file into them

1:18 they really really do not want to be a general purpose mechanism

1:18 Gh0stInTheShell: and their context is all stupid and stuff

1:18 yeah I know

1:19 * dysfun goes to make coffee

1:24 Gh0stInTheShell: I'll just take this languague designed to be massively parallel and run it in this one little lightning fast thread....

1:25 s/languague/language

1:26 dysfun: So do you mean it's a bad idea to deploy node to production, or just clojurescript running on node?

1:26 dysfun: personally i don't trust node at all

1:27 Gh0stInTheShell: oh okay

1:27 dysfun: and i'm not mad fond of javascript, even behind a clojurey wrapper

1:27 Gh0stInTheShell: but plenty of people are running it in production...

1:27 I'm sure you have good reasons for your distrust :)

1:28 dysfun: ah, the politics argument: you voted for him

1:28 how wrong can a majority be? well...

1:28 Gh0stInTheShell: I'm not arguing :)

1:28 just trying to learn some things

1:29 dysfun: also heard as "if it's good enough for the bbc"

1:29 Gh0stInTheShell: gothcha

1:29 dysfun: there are many people who do deploy node to production, but i'm more risk averse

1:29 Gh0stInTheShell: gotcha

1:32 so what to deploy? ;)

1:32 dysfun: at the minute i have a clojure site running aleph deployed behind nginx

1:32 Gh0stInTheShell: I fear just running java on my system to write code for android and clojure

1:32 Like I just dropped the security soap

1:33 dysfun: it's just a vm, it isn't going to eat your firstborn

1:33 Gh0stInTheShell: I hate it

1:33 :)

1:33 dysfun: i hate the startup time

1:33 Gh0stInTheShell: there's that

1:33 dysfun: or i did when it was 45s on my last machine

1:33 but i've since stolen a friend's machine

1:33 Gh0stInTheShell: nodejs will find those prime numbers before clojure is done loading

1:33 :)

1:34 dysfun: but there you go, i already said it's only good for long running processes

1:34 Gh0stInTheShell: I know. SO what to deploy?

1:34 :)

1:34 dysfun: for your app?

1:34 Gh0stInTheShell: No I mean, you told us what you wouldn't deploy?

1:35 I was just curious if you had any banner for a path to success or anything.

1:35 dysfun: i deploy clojure!

1:35 Gh0stInTheShell: I don't have a particular app I'm talking about. I realize that's really pertinent.

1:35 dysfun: Okay cool

1:35 dysfun: okay, well i believe in the unix philosophy, right tool for the job

1:36 an awful lot of what i do is long-lived server processes. clojure is ace for that

1:36 Gh0stInTheShell: right I realized that as I was asking

1:36 you answered my question

1:37 dysfun: if you have another usecase in mind, i can make recommendations for the specific

1:37 but otherwise, i use whatever tools seem least likely to make me throw my keyboard against a wall

1:37 and if clojure fits, that's likely to be clojure

1:38 Gh0stInTheShell: Nah man, just curious. I'm excited about using clojurescript with nodejs and excited about clojure on the JVM and still use old scool OOP to make money.

1:39 I realize lisp is older school, but it goes back to that C++ is the only sane way to build native business applications blah blah, and then "PHP has a C++ like object model now!" and crap like that

1:39 dysfun: yeah, NASA was under pressure to move to C++ for the mission they sent out in lisp

1:39 good job they sent it out in lisp, they needed a repl to debug a C component

1:39 one with a formal proof, no less!

1:41 Gh0stInTheShell: So I know Javascript, I know Lisp, I know C/C++/PHP/Perl/Java/SQL/NoSQL and I'm just trying to draw Clojure and cljs into my tiny personal grand theory of things :)

1:41 dysfun: good

1:41 while you're at it, look at lisp flavoured erlang and haskell too

1:42 Gh0stInTheShell: Had to learn a small amount of haskell to fix the window manager :)

1:42 dysfun: i find it's easier to use than to bother with all the type theory

1:42 Gh0stInTheShell: I'm supposed to learn ELixir for work

1:43 but that's not lisp flavored erlang is it?

1:43 dysfun: heh, i've gone LFE instead of elixir

1:43 no, but it's on the erlang vm

1:43 Gh0stInTheShell: yep

1:43 dysfun: it's got a very different view of concurrency. it's worthwhile knowing both

1:47 Gh0stInTheShell: My brain is only so large. :)

1:47 and I'm lazy and impatient

1:47 dysfun: me too. that's why i loved perl

1:48 Gh0stInTheShell: I still use it as a sysadmin tool, which it is great for

1:48 :)

1:48 dysfun: i rarely write any any more

1:48 Gh0stInTheShell: I use it with -e from the command line

1:49 dysfun: At the minute i've been ignoring my work and doing LFE

1:49 work is mostly clojure at the minute

1:49 Gh0stInTheShell: I used to write webservers with it, and then with it and Catalyst, but that was utter nonsense :)

1:49 dysfun: haha, i was never a Catalyst fan either

1:49 the modern era of perl web frameworks is pretty cool, but i just don't care enough about perl anymore

1:49 Gh0stInTheShell: the stuff without catalyst was worse, clojure is like a sane boat in a rough sea of BS for me :)

1:50 dysfun: and it feels like perl6 will end up killing off perl5 and complete its transition to 'legacy'

1:50 Gh0stInTheShell: I was so excited about perl 6 in 2008!

1:50 lmao

1:50 dysfun: i was never

1:50 they didn't learn first time round

1:50 jesus

1:50 Gh0stInTheShell: I mean they kept saying it would come out

1:50 well they killed perl

1:50 clojurebot: It's greek to me.

1:50 Gh0stInTheShell: :)

1:51 sorry let's talk about greek :)

1:51 dysfun: yeah, quite a few of my perly friends have a lot to say about perl6 that isn't positive

1:51 and i was a bit dismayed to see someone i used to have a great deal of respect for slag off clojure and say perl6 was better

1:52 (cause, y'know, clojure is something i know a lot about)

1:53 maybe he caught the same thing larry did that turned him into an embarrassment on stage

1:53 Gh0stInTheShell: People are ignorant :)

1:54 dysfun: oftentimes you just expect better of people than cheap FUD

1:57 Gh0stInTheShell: I fear the JVM. I loathe it. I have to have five versions of java installed on my GNU linux system to build different versions of Android.

1:57 dysfun: then clojure is not the right tool for you

1:57 Gh0stInTheShell: it might be irrational, my fear and hate. But I can't get away from it and am it's prisoner.

1:57 Like those RMS users in cahins

1:57 :)

1:57 dysfun: i think it is irrational

1:57 clojure is a wonderful tool

1:58 i'd use it to build an android app

1:58 Gh0stInTheShell: I just want to learn clojure

1:58 dysfun: because java? are you fucking kidding me?

1:58 Gh0stInTheShell: I'll put up with the JVM, like I do for android builds

1:58 dysfun: the jvm is one of the reasons clojure is *fast*

1:59 hotspot is an amazing optimising compiler, for free in every JVM

1:59 well, not *every* JDK, but that's beside the point

2:02 Gh0stInTheShell: dysfun: well cool, I appreciate you taking the time to talk to me about this

2:02 I continue to be excited about CS in general in the face of great adversity. ;)

2:03 dysfun: haha, that's called 'learning', it's good for you

2:04 Gh0stInTheShell: :)

2:05 namra: hm is a .edn file treaded as .clj file?

2:05 dysfun: no

2:05 it won't be loaded with (require) either

2:05 namra: but i'm getting a runtime exception

2:05 dysfun: pastebin?

2:05 clojurebot: pastebin how about refheap? https://www.refheap.com/

2:06 namra: have a edn file in resource-paths and when i do a 'lein run' it complains that a symbol cant be resolved in that context

2:06 dysfun: what are you using to read the edn file?

2:06 namra: load-file

2:07 dysfun: yeah, wrong tool

2:07 namra: confusing

2:07 it worked as expected within the repl

2:07 dysfun: okay, well edn is a subset of clojure syntax

2:07 namra: yep

2:07 dysfun: https://github.com/clojure/tools.reader this is the tool we use to read edn

2:07 clojure.tools.reader.edn

2:08 namra: thanks alot

2:09 dysfun: np

2:09 namra: but still confusing ^^

2:10 dysfun: totally fair :)

2:18 namra: :(

2:20 ben_vulpes: isn't refheap deprecated?

2:20 dysfun: so i'm tentatively looking for a gui stack

2:20 and yes elm is covered in warts

2:20 dysfun: i'm shocked

2:21 ben_vulpes: hey look i only bit it off because i'm looking to learn 3/4 ui paradigms in the next 2 quarters

2:21 i have no illusions about the misery of software development

2:21 anyways

2:21 dysfun: have you done the clojurescript single source of truth one?

2:22 ben_vulpes: "one atom to rule all state in my spa"?

2:22 dysfun: yeah

2:22 ben_vulpes: doesn't sit too well with me

2:22 dimon_: hey, in luminus I don't want the config files and others statics such as html, css, js and images to be embedded in the output jar. How can I achieve that?

2:22 dysfun: i think it's a lovely idea but terrible in practice

2:22 ben_vulpes: why tho uh

2:22 well types mostly

2:22 composability also

2:22 dysfun: dimon_: remove them from resources, put them in another directory

2:23 dimon_: ok, tnx.

2:23 dysfun: change any references to using them as a resource to pick them up from the directory

2:23 (such as ring middleware that luminus uses to serve files...)

2:23 dimon_: but will luminus be able to find them?

2:23 I see

2:23 dysfun: i expect you will now have to change middleware and learn about how middleware work

2:24 ben_vulpes: yeah why do you *need* that, dimon_ ?

2:24 dysfun: because he's deployed before and he knows the value of having things where you can modify them

2:24 * ben_vulpes blinks

2:25 ben_vulpes: twiddle css, redeploy, what

2:25 dysfun: hah. one of my clients wants things modifying willy-nilly and having the site splayed with template errors for a few seconds isn't a problem

2:25 ben_vulpes: yeah no fuck that

2:26 dysfun: srsly though, correct answer for that situation

2:26 ben_vulpes: let the human speak for themselves

2:26 i too have deployed static files behind nginx

2:26 when resource constraints demanded it

2:27 dysfun: yeah, it's a light traffic site, so i just let aleph serve them :)

2:27 ben_vulpes: i have only seen one stack so miserably designed that the payoff for moving off the paas was less than two years

2:27 dimon_: I'm new to dealing with SQL in clojure, what library do you recommend for simple blog? korma or anything else?

2:27 ben_vulpes: "designed" is not even what it was

2:27 dimon_: jdbc

2:27 dysfun: dimon_: they all come with various tradeoffs

2:27 first question: do you want to write SQL?

2:27 ben_vulpes: just write the sql

2:28 you'll end up doing it anyways

2:28 dysfun: ben_vulpes: that's exactly what the clojure library i've been learning another language to avoid finishing deals with

2:28 Gh0stInTheShell: lol

2:28 dimon_: I can write it, no problem

2:28 ben_vulpes: *parser error*

2:29 second pass ate it

2:29 Gh0stInTheShell: make sure you escape user input porperly ;)

2:29 properly even

2:29 dysfun: okay, if you don't mind writing sql, i'd recommend https://github.com/irresponsible/utrecht and https://github.com/mpg-project/mpg

2:29 ben_vulpes: dimon_: if it's really a simple blog, consider datomic

2:29 dysfun: disclaimer: i hack on both of them

2:30 ben_vulpes: nifty, dysfun

2:30 the latter'd be my hibernate equivalent?

2:30 dysfun: not really

2:31 dimon_: why would I use which isn't popular with a couple of * at github?

2:31 ben_vulpes: > mpg/patch

2:31 dysfun: it will 'just work' for vectors though

2:31 dimon_: **library

2:31 ben_vulpes: that is some stateful shit unless i misread?

2:31 dysfun: users will come when i stop slacking on my marketing

2:31 ben_vulpes: yeah and to my transactolator too

2:31 dysfun: these are brand new, and i can assure you they are very high quality and not going anywhere

2:32 ben_vulpes: mpg looks neat

2:33 dysfun: mpg was very painful to write

2:33 dimon_: how about HugSQL ?

2:33 ben_vulpes: has a cute name

2:33 probably going to cut off your fingers

2:34 TEttinger: yakuzaSQL

2:34 dysfun: well for one, it puts sql in different files, which is just asking for bitrot

2:34 ben_vulpes: > irresponsible clojure guild

2:34 who do i have to kill as an initiation rite for this club

2:34 dysfun: depends who i'm not liking this week :p

2:34 ben_vulpes: i once wrote a datomic transactor provisioning clojure app that poked at aws from the java api

2:35 is that irresponsible enough?

2:35 my aws bill is absurd

2:35 dysfun: no, it's just ironic naming

2:35 it amused me, i give them away for free

2:37 ben_vulpes: dysfun: anyways on an ancient topic, do you have any gui toolchain recommendations?

2:37 dysfun: in terms of expanding your knowledge of gui paradigms?

2:37 what have you done already?

2:38 Gh0stInTheShell: WHy are there all of these empty repos in https://github.com/irresponsible

2:38 ben_vulpes: no, for use in slamming out robust client apps.

2:38 Gh0stInTheShell: ;)

2:38 dysfun: Gh0stInTheShell: because i'm too ashamed of the code to push it just yet

2:38 ben_vulpes: something i can get comfortable and fast with within six months

2:39 dysfun: Qt

2:39 there's really no other game in town

2:39 ben_vulpes: the "learn gui paradigms" project is separate from but related to "build personal GUI-shitting toolchain"

2:39 dysfun: if you're doing desktop anyway

2:39 ben_vulpes: blee

2:39 what if mobile is a constraint

2:40 dysfun: pick whichever javascript framework pisses you off the least

2:40 ben_vulpes: what if i drip feed you constraints annoyingly

2:40 Gh0stInTheShell: Then jquery-ui

2:40 duh

2:40 :)

2:40 ben_vulpes: Gh0stInTheShell: hate speech!

2:40 Gh0stInTheShell: do what dysfun says, not offense intended :)

2:41 ben_vulpes: no i kid

2:42 dysfun: and actually just build the damn thing as a website

2:42 ben_vulpes: myeah

2:42 that juicy native feel tho

2:42 Gh0stInTheShell: and use apache cordova to make it a native app

2:42 dysfun: jquery-ui

2:42 you can have native feel on a website

2:42 ben_vulpes: for real?

2:43 Gh0stInTheShell: ben_vulpes: It can have that juicy native feel you can even have native code for each family of device

2:43 And at the heart of it all you can just run some javascript to present mobile friendly froms and controls

2:43 ben_vulpes: > for each family of device

2:43 yeah about that

2:44 Gh0stInTheShell: You know, like blackbeery, ios, etc retch

2:44 dysfun: you will still need tweaks

2:44 * Gh0stInTheShell starts laughing maniacally and rocking in place.

2:44 ben_vulpes: fuck tweaks, shit shouldn't be that complex

2:44 dysfun: blackberry's most common form factor isn't iphone-proportioned

2:45 Gh0stInTheShell: I mean, you want that native feel?

2:45 ben_vulpes: well, "you"

2:45 dysfun: yeah, if everyone is using a shit device, why lower yourself to its level?

2:45 Gh0stInTheShell: Or do you want drones to quickly eneter data into forms on their phones and send it back to the mothership for assessment?

2:45 dysfun: and, y'know, outside of the valley, everyone is

2:45 ben_vulpes: hey if you've got 300k i'll write swift, sure why not

2:46 dysfun: outside of the mobile device earners with disposable income you mean

2:46 users

2:46 dysfun: if they're your demographic, go for them

2:47 they're one for one of my projects, so obviously we take a different approach

2:47 ben_vulpes: right tool etc, ofc

2:48 dysfun: i'm feeling like i might actually finish my sql generation library today

2:48 Gh0stInTheShell: I have had great success making android apps with HTML5 and javascript. Had no real issues, made nice apps. I have written android apps natively in java and found it to be extremly technical, work intensive, and time consuming. All apps were dleivered and functioned as promised for clients...

2:49 dysfun: yeah, if you can get away with it, build a mobile html app

2:49 ben_vulpes: "these people on irc said to use whatever js framework i wanted to, boss!"

2:50 Gh0stInTheShell: The HTML5 and Javascript apps were eventually able to work on iOS, and could have worked on Blackberry or WIndows Mobile had I desired and done a little bit more work.

2:50 dysfun: "so i picked a thing you've never heard of because it had a hipster name"

2:50 ben_vulpes: ehueaaehuaehaueahu

2:50 TEttinger: scriptr.io

2:50 Gh0stInTheShell: lol

2:50 ben_vulpes: alllll i wannnnt is for it to handle some fucking amount of complexity for me

2:50 for the love of fuck

2:51 Gh0stInTheShell: I mean you've heard of jquery-ui and jquery-mobile, right?

2:51 ben_vulpes: get

2:51 the

2:51 fuck

2:51 out

2:51 i suppose i should add that to the list

2:51 dysfun: actually, if i want to get something out, i use jquery

2:51 ben_vulpes: if i'm serious about guiquest

2:52 Gh0stInTheShell: guiquest!

2:52 ben_vulpes: it's like gentoo quest

2:52 but profitable

2:52 maybe

2:52 Gh0stInTheShell: I support you in your quest Sir Ben_vulpes

2:53 ben_vulpes: yes

2:53 these roaches

2:53 six concrete walls

2:53 Gh0stInTheShell: lol all my quests are profitable maybe as well

2:53 ben_vulpes: it is a kingdom

2:53 and they my cattle

2:53 Gh0stInTheShell: hindsight is alway 20 20

2:53 ben_vulpes: honestly i'd rather be doing ito calculus at a bank

2:53 Gh0stInTheShell: I kill my roaches but don't eat them

2:53 wasteful

2:54 we have cats like cowboys have cattle but I don't eat those either

2:54 ben_vulpes: i have never understood the point of hosting cats

2:55 even children and wives are more rewarding

2:55 Gh0stInTheShell: hosting, lol

2:55 like they're a windows vm or something

2:55 lmao

2:55 ben_vulpes: well, parasites.

2:55 generally speaking.

2:55 Gh0stInTheShell: cats are sweet and sleep in a big pile with you

2:55 ben_vulpes: children wives and dogs as well

2:55 Gh0stInTheShell: lol

2:55 ben_vulpes: with no toxoplasmosis even

2:56 if you'll forgive a crude, crude joke meant only to lambast cats

2:56 Gh0stInTheShell: that stuff makes me strong and introduce random seeds into my thinking, in the form of harmless cysts in my brain!

2:56 ben_vulpes: oh god

2:56 triggered

2:56 so this jquery ui thing

2:56 Gh0stInTheShell: lmao

2:57 yes jquery ui

2:57 ben_vulpes: can i get type safety with it?

2:57 Gh0stInTheShell: lmao


2:57 poor kid grew up on macs, never stood a chance

2:57 funny how the world changed

2:57 dysfun: if you want type safety, you may want to consider the haskell solutions

2:58 but don't expect to actually release anything

2:58 ben_vulpes: why not?

2:58 Gh0stInTheShell: lmao

2:58 dysfun: you'd have to actually learn it to understand

2:58 suffice to say you can never quite forget you run in the browser, on javascript

2:58 ben_vulpes: that is a dark dark perspective on the world dysfun

2:59 dysfun: ah well

2:59 ben_vulpes: yeah one of the first things i did in elm was blow up its float representation

2:59 TEttinger: NaN?

2:59 dysfun: elm isn't really haskell. try haste or fay

2:59 TEttinger: FREEEEEGE

2:59 ben_vulpes: nah TEttinger there was some < comparison and i put in val.00000000000000001 and it failed

2:59 dysfun: elm is also a much more practical tool than either :)

2:59 Gh0stInTheShell: What kind of mobile app needs type safety? Are you sure the drones aren't entering data into forms and sending it back to the mothership for analysis?

3:00 ben_vulpes: Gh0stInTheShell: i want type safety in writing the thing

3:00 dysfun: yeah, definitely need type safety for that "which celebrity murderer are you?" quiz

3:00 Gh0stInTheShell: oh man

3:00 TEttinger: murderer who is a celebrity? or murderer of a celebrity?

3:01 Gh0stInTheShell: well I'm in the wrong channel to argue against type saftey, so have at it

3:01 dysfun: TEttinger: i really hadn't thought that far ahead, but i was thinking the former

3:01 TEttinger: or figurative murderer of the state of celebrity?

3:01 ben_vulpes: i don't think y'all grok how truly small my brain is, or how truly and perversely lazy i am

3:02 dysfun: no, my morning brain really really doesn't go that far

3:02 TEttinger: heh

3:02 dysfun: we are out of tea and the coffee tastes horrible

3:02 TEttinger: hookah simulator lite for android

3:03 dysfun: haha. i was in an amsterdam coffeeshop and someone showed me his vape and how he could get live stats on his iphone while he was vaping

3:03 TEttinger: coffee simulator for iOS

3:03 dysfun: what's that? loud sounds?

3:04 flashing the display to bright white

3:07 TEttinger: it's a picture of a cup of coffee. you tilt the phone to drink it, making it hard to see the screen. when you untilt the screen, the cup is empty and there's the blood-curdling scream of "MY CROTCH! IT BURNS!"

3:08 dysfun: haha

3:08 you're doing coffee wrong

3:08 TEttinger: the rest of the app is in paid installments as you go through physical therapy to regain sensation in your virtual body

3:09 Gh0stInTheShell: Is it type safe?

3:09 dysfun: LOL

3:09 TEttinger: I uh don't drink coffee anymore. I used to a lot, aeropress is wonderful. but caffeine pills are easier on my stomach, by a lot

3:10 dysfun: i hear ya, but i find caffeine pills too strong

3:10 Gh0stInTheShell: ben_vulpes: If you want badass 3d stuff for video games on mobile you can use Unity and Lua and pay for it like a chump but some of the smartest people I know really like Lua so there's that. :)

3:11 I dunno if Lua is typesafe, lazily tried to learn it for like 45 minutes once

3:11 dysfun: it's not

3:11 Gh0stInTheShell: But you can use it to write a large scale sapce combat game

3:12 :)

3:12 TEttinger: Unity uses C# anyway

3:12 old version, maybe updating

3:12 dysfun: if you want types, you have to pick C++, Java or Haskell in practice, basically

3:12 oh yeah, C#

3:14 Gh0stInTheShell: There you go. Use Unity and C# to make some forms for drones to send data back to the mothership.

3:14 What could be simpler?

3:15 SO can I use jquery-ui with cljs?

3:15 I can, right

3:15 and any other js library I fell like

3:16 s/fell/feel

3:16 sorry for my atrocious typing

3:17 dysfun: sure. might take some figuring out though

3:17 but you can use all of javascript

3:23 Gh0stInTheShell: I'm going to try to make cljs work with https://jquerymobile.com/

3:23 dysfun: i just heard a fantastic bit of bob martin "hundreds of dollars for a terabyte of memory"

3:23 Gh0stInTheShell: I kept saying jquery ui but I meant that

3:24 allwinner 64 bit SoC is $5, right now :)

3:24 dysfun: what's that useful for?

3:24 Gh0stInTheShell: lol

3:25 dysfun: (asking, not taking the piss)

3:25 Gh0stInTheShell: I dunno, a $15 server appliance running linux, or a tablet, or a phone, or a little computer for a poor baby in africa that costs $45

3:25 lol

3:25 just saw your taking the piss

3:25 lmao

3:26 dysfun: how much grunt do they have?

3:27 Gh0stInTheShell: as much as node or webkit will give them?

3:27 I dunno

3:27 * Gh0stInTheShell is so confused.

3:27 dysfun: lol, i mean how powerful are they?

3:28 Gh0stInTheShell: looking

3:30 http://www.allwinnertech.com/en/clq/processora/6053.html

3:30 4 cortex A53s

3:30 Built in video GPU etc

3:31 dysfun: hrm i can't find the clockspeeds

3:31 Gh0stInTheShell: anyway, you could picture a parallel board with 100 of those on it also, sexy for parallel and functional immutables blah blah

3:31 dysfun: me neither

3:32 dysfun: yup, i've been seriously considering a huge number of simpler cores

3:33 but there comes a point when you just do it on FPGA

3:33 or GPU

3:33 Gh0stInTheShell: Yeah I have played with OpenCL and stuff like that

3:34 If only it was lisp :)

3:34 dysfun: heh

3:37 Gh0stInTheShell: So if I can run JDK 8 for ARM I can run Clojure against that, too, right?

3:38 dysfun: yes, but the openjdk builds for raspi are slw

3:38 you have to compile your own at the minute or use azul's

3:38 Gh0stInTheShell: but do you think they'll be faster on A64? ;)

3:39 dysfun: doubt it. too new an architecture for them to really do a good job taking advantage of it

3:39 Gh0stInTheShell: oh well

3:42 The JDK is slow on my 8-core AMD workstation with 64 GB of ram. :)

3:42 dysfun: it should only be slow to start up

3:42 but to get some of the benefits it has to run for a while

3:42 Gh0stInTheShell: yes, I know long running server processes

3:42 :)

3:43 just let that repl finish cooking....

3:47 TEttinger: azul is nice for making the zulu builds. are the arm ones free like the desktop/server ones?

3:48 dysfun: i don't honestly know

3:59 Gh0stInTheShell: so if I use (long-array seq) to make an array, that array is a mutable Java array and not thread safe right?

4:00 dysfun: correct. don't use it across multiple threads concurrently

4:01 Gh0stInTheShell: dysfun: thank you

4:01 dysfun: yw

5:26 dimon_: should I import "db" or what?

5:26 in my luminus project in the file home.clj I call a function "db/get-all-articles" and get an error "No such namespace: db"

5:26 last time I tried, I got other kinds of errors because I'm a newbie

5:27 the function get-all-articles should be defined in "db" because I've defined it in the *.sql

5:27 so how can I properly import "db"?

5:29 dysfun: (:require [app.db :as db])

5:30 dimon_: tnx

5:35 I have another error. My code at home.clj

5:35 (:require [my_app.db :as db])

5:36 and the error:

5:36 java.lang.ClassNotFoundException: my_app.db.core,

5:36 I've tried (:require [my_app.db.core :as db]) but also got a similar error

5:39 helllloooo

5:40 dysfun: my-app

5:40 my_app should be the filename, my-app should be the module name

5:41 being rude doesn't help your question get answered any faster

5:42 dimon_: my-app is just an example, the real name is without "-"

5:43 dysfun: and it's in the right place, ie my-app/db.clj ?

5:44 dimon_: no, it's in src/clj/my-app/db/core.clj -- where it's created by default by Luminus

5:44 dysfun: okay, that's the right place for the require form you have there

5:45 can you pastebin the full error please?

5:45 dimon_: oh, sorry, it's already working. by itself. although last time I did reload it.

6:18 hey, when I go to the url articles/15 in my Luminus app

6:18 I have an error Parameter Mismatch: :id parameter data not found.

6:18 although everything has been setup correctly I think

6:18 dysfun: what's the route?

6:18 dimon_: (GET "/articles/:id" [id] (article-show-page id))

6:19 dysfun: odd

6:31 dimon_: another error

6:31 ERROR: operator does not exist: integer = character varying Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts. Position: 32

6:31 dysfun: so typecast it

6:31 val :: type

6:31 dimon_: for this

6:31 (defn article-show-page [id]

6:32 (layout/render "show.html"

6:32 {:title "123", :article (db/get-single-article {:id id})}))

6:32 dysfun: pastebin!

6:35 dimon_: this is not working

6:35 {:title "123", :article (db/get-single-article {:id id})}))

6:35 but this

6:35 {:title "123", :article (db/get-single-article {:id 123})}))

6:35 is

6:35 any idea?

6:36 dysfun: if that is not working, then the variable isn't getting passed

6:36 correctly

6:37 oh. you're trying to query an integer column and you've got a string which is part of the url

6:37 you need Integer/parseInt

6:37 dimon_: let me try

6:58 shiranai_: dysfun: so Java is only good for "long-running (server?) processes" and nothing else? :P i'd be curious to hear more about that :)

6:58 dysfun: personal opinion

6:59 if you simply must write in java for other devices, you can build a compact profile jvm

7:00 and if it's not constraints of the hardware maybe you have a usecase where the usual exclusion factors don't apply

7:02 shiranai_: well, i was just thinking there are bound to be lots of things you can do just fine with Java even on a home computer

7:03 dysfun: well sure, if the startup time isn't going to annoy your users too much

7:03 but have you ever tried to build a gui application in java?

7:03 it's not fun

7:04 shiranai_: yeah i've done something with Swing.. but nothing (really) serious

7:04 i imagine it would get painful

7:05 though as you discussed earlier, maybe there is no painless GUI toolkit for any language anyway :)

7:07 dysfun: indeed

7:07 but i'm not convinced swing is ever the answer

7:07 you can make it work, but everyone who uses your software will complain about it

7:11 shiranai_: :)

7:11 those ungrateful bastards, the users.. :)

7:15 dysfun: the user is king

7:15 doesn't matter what things should be like, only what they are like

7:15 oh bollocks, where's my torx screwdriver?

7:15 shiranai_: dysfun: i guess IDEA uses Swing, by the way.. or do you know if it's something else? i've never felt like complaining about the way it looks though

7:15 dysfun: almost certainly swing

7:16 shiranai_: yeah, and it looks native to me at least

7:17 anyway, i think it's kind of lame to complain about an app not looking native if it's a good app and works well etc..

7:25 ilevd: Is it normal to force garbage collector after big processing?

7:30 shiranai_: "normal"?

7:30 i guess you might want to do it if it helps? :) that should be "normal" :)

7:38 engblom: dysfun: Regarding the discussion we had earlier about about raspi programming, I actually made a gpio library for raspi. It is using the /sys folder for accessing gpio and works on rasbian out of the box as rasbian got udev rules giving normal users access to /sys/class/gpio/*

7:39 As it is using file operations, it is quite a bit slower compared to using a C library... but for most cases fast enough.

7:40 I was considering to use something as JNI for making a faster version, but now I am actually looking at alternative lispy languages for this kind of tasks.

8:25 stain: engblom: which JDK do you use on the Raspberry pi?

8:25 hav eyou tried the ARM optimized edition from Oracle?

8:25 you would need to change some endian thingie

8:25 engblom: stain: I am using the oracle one. With openjdk, I do not even get to REPL as it will time out before it comes there

8:25 stain: I know..

8:26 because it has no JIT

8:26 engblom: Yep

8:26 stain: how about the Android Dalvik? Can that work with Clojure?

8:27 engblom: That I do not know.

8:27 My library is fast enough to max out several of those cheap $1 stepper motor on rpi2, so it works for most cases

8:28 stain: :)

8:30 engblom: https://github.com/engblom/gpio <--- my library. Some part of it, especially the wait-for-input function is a bit uggly formated, but it do work

10:13 sdegutis: Hi. I'm about to use (frequencies) in production for the first time. Is it best practice to cache that data into the database instead?

10:16 Bronsa: sdegutis: that question doesn't make any sense, as usual

10:17 sdegutis: Bronsa: Oh, hello again. I haven't heard from you since the last time you chose to complain about something I've said, a few months ago I think. How have you been since then?

10:18 Oh wow, I just used fnil again. justin_smith was right all along.

10:18 Bronsa: it never ceases to amaze how however sporadically I join this channel nowadays there's always a completely nonsensical stream of messages from you

10:18 sdegutis: But this time it was (fnil - 0) in a comp-chain used within juxt within sort-by.

10:19 Bronsa: Actually it's just a really unlikely coincidence. For the most part I make perfect sense. The only times I ever don't, you happen to fricken be here and whine about it.

10:21 Bronsa: I must be really unlucky then. I can't remember ever witnessing what you say happens regularly

10:23 sdegutis: welp.

10:24 Bronsa: last week or this week or something I suggested :chop within :require like [foo.bar.quux :chop foo] as an alternative to [foo.bar.quux :as bar.quux]

10:25 but justin was like "I wouldn't use that cuz then I can't grep for bar.quux inside my :require block"

10:25 which I can see getting confusing so yeah

10:45 hodapp: If I need a 'map' solely for its side effects over some collection, and I have no need for the resultant list, what's the idiomatic way to do that?

10:45 luma: doseq

10:46 hodapp: ah, thanks

10:49 Bronsa: or run! if you want to keep the shape of map

10:49 (run! println (range 10)) vs (doseq [el (range 10)] (println el))

10:50 hodapp: 'run!' will distract me less because I'll quit trying to read 'doseq' as Dos Eq(uis) and think of the beer commercials

11:05 sdegutis: ,(time (->> (repeat 100000000 2) (apply +)))

11:05 clojurebot: eval service is offline

11:05 sdegutis: ,(time (->> (repeat 100000000 2) (reduce +)))

11:05 clojurebot: eval service is offline

11:05 bacon1989: anyone here ever use the library specter?

11:05 sdegutis: I rest my case.

11:08 Locally, (apply +) takes 6518 msec, (reduce +) takes 1233 msec.

11:08 Remember, always use reduce +

11:09 bacon1989: is that because apply has to determine if it needs to fold or add the next value in the sequence?

11:10 where as reduce can have a pre-loaded level of arities to handle any extra seqs

11:10 MJB47: i think its mostly because reduce is optimised with this sort of thing

11:10 even having its own data collection it uses internally

11:10 bacon1989: ah

11:10 sdegutis: I don't think reduce + does anything special.

11:10 dysfun: (apply str ...) is the exception

11:10 sdegutis: I think apply + just has to deal with a really really long coll.

11:11 Oh right, it's because of how range is lazy, and reduce takes things in chunks.

11:11 MJB47: in general reduce is the fastest way of looping in core

11:11 will_sm: apply will expand the seq and pass it to +, reduce will pas them 2 at a time

11:11 sdegutis: So (apply +) has to take the entire 2-million-element array at once.

11:11 MJB47: i believe if you did the same test again with doseq vs reduce, reduce would still win

11:11 sdegutis: But (reduce +) takes chunks of only 32 elements at a time, and reduces them, and goes onto the next chunk, until it's done.

11:13 ,(->> (range 40) (map #(pr %)) first)

11:13 clojurebot: 012345678910111213141516171819202122232425262728293031

11:15 sdegutis: dysfun is right, apply str is probably one of the only exceptions

11:15 dysfun: you sound surprised

11:17 justin_smith: sdegutis: apply + does not need to consume the entire array at once

11:17 will_sm: apply is not eager

11:18 ,(apply (partial take 2) (repeat (range)))

11:18 clojurebot: eval service is offline

11:18 justin_smith: ergh.

11:19 shiranai_: any americans here? is this even real: https://www.youtube.com/watch?v=-4S0gHlKiho&t=63 ?

11:20 Bronsa: shiranai_: don't think this is the forum for this conversation

11:21 shiranai_: Bronsa well, i was kind of expecting a reaction like that :) yeah, you're right that this forum isn't *meant* for "random stuff", but that doesn't mean random stuff should never be brought up

11:21 but i'm curious about what americans think about that video

11:22 justin_smith: look like typical seattle college kids to me, but really not on topic here so lets drop it

11:23 shiranai_: it's not just off the topic, but controversial in a way that isn't really useful or helpful here

11:23 shiranai_: do you think the way the people in the video answer the questions represents a problem?

11:23 justin_smith: shiranai_: stop

11:23 shiranai_: :P

11:23 Bronsa: is #clojure-offtopic still a thing?

11:23 doesn't look like it

11:24 shiranai_: it's also interesting how highly intelligent people can't handle intellectual inquiry into things that actually matter in the real world, but alright, i'll stop

11:24 bacon1989: shiranai_: I found it interesting. I have a friend who's like that

11:24 Bronsa: shiranai_: there's a place for discussing that, and a place for not discussing that. This is a place to discuss clojure.

11:24 bacon1989: very up in the air about being 'accused' of a certain gender

11:25 shiranai_: bacon1989 oh? that's interesting, but it seems we're not allowed to talk about it here :)

11:25 bacon1989: well, let's look at clojure, it's dynamically typed

11:25 our classification of data isn't very strict

11:25 justin_smith: shiranai_: there are plenty of channels on IRC for people who want to discuss that topic, this isn't one of them, I'd like to think people can be friendly and helpful to each other here regardless of our opinions on those issues

11:26 shiranai_: sure, i for one have no intention of being unfriendly

11:28 hodapp: TV show designed to make people look stupid shows clips of people who appear to look stupid. Story at 11.

11:29 Dealing with this object-oriented code already brings me enough real stupidity that we don't much need a TV show that manufactures additional stupidity.

11:31 sdegutis: How hard would it be to create a new clojurebot?

11:33 Bronsa: the existing one works just fine

11:36 sdegutis: ,(prn "okay Bronsa")

11:36 clojurebot: "okay Bronsa"\n

11:36 sdegutis: sweet

11:36 bak online

11:36 Bronsa: for the nth time, stop needlessly mentioning me

11:37 sdegutis: Bronsa: you've got to be kidding me

11:37 Bronsa: you're going on permanent ignore

11:37 I'm done dealing with your unreasonable shit.

11:38 hodapp: ...

11:38 sdegutis: Bronsa: the next time someone replies to you 3 minutes later after you replied to them, you may want to rethink asking them to not "needlessly" mention you

12:06 bmuk: I'm trying out compojure, but I still want a -main function. What can I do to pass my app-routes to run-jetty?

12:09 dysfun: i think you just answered your own question

12:17 sdegutis: What namespace alias convention do you use, if any?

12:18 dysfun: single letter

12:19 justin_smith: would a superscript or subscript namespace alias count as half a letter?

12:20 ,(require '[clojure.string :as ™])

12:20 clojurebot: nil

12:20 justin_smith: two letters, or half a letter - who knows?

12:36 phillord: when will clojure allow circular namespaces? when? when? when?

12:37 dysfun: never probably

12:38 phillord: I know, and every day my monolithic namespace gets bigger and bigger

12:38 just wanted to sahre

12:38 share

12:41 bmuk: dysfun: it's that easy? haha

12:41 dysfun: bmuk: pretty muc

12:42 bmuk: I just saw that the compojure lein template only has support for lein ring (as opposed to a standalone jar)

12:42 dysfun: yes. you do not need to use lein ring's building stuff

12:42 you can use it during dev and not deploy with it if you want

12:44 bmuk: I'm trying to make it as painless as possible for people on my team to build/test this stuff so I'm probably just going to use docker

12:44 which could run ring server-headless I suppose

12:44 dysfun: for testing, you should probably just run it from lein

12:45 unless you mean automated testing

12:46 bmuk: I do mean automated testing, but with docker they wouldn't have to have lein (or even java) installed, just docker build and docker run

12:48 dysfun: with automated testing, it's expected that you will have your tools installed

12:48 bmuk: true

12:48 I haven't gotten that far yet. I'm looking into Jenkins

12:49 dysfun: if it's open source, just use travis

12:50 bmuk: It isn't. It may be in the future, not sure yet

12:50 hodapp: even if it's closed-source, you may be able to pay to use Travis

12:50 and in my experience, Travis was far easier to screw with than Hudson & Jenkins

12:51 dysfun: i used to administer jenkins. very powerful, very annoying

12:51 travis is easy, but you pay real money for it

12:52 bmuk: yeah $129/month for just 2 concurrent jobs is steep

12:53 dysfun: this is why i just open source my commercial code

12:53 you get all sorts of cool stuff for free

12:54 bmuk: That's definitely true. It's something we've talked about

12:54 dysfun: and if you're in a competitive closed industry, it's a massive commercial advantage

12:57 bmuk: I can see how it would be an advantage for clients who are programmers, but I'm not sure clients who aren't would know what that means

12:57 * dysfun works for himself

12:58 bmuk: If you don't mind me asking, what is/are your product(s)

12:58 dysfun: vaporware, obviously

12:58 bmuk: haha

13:02 hodapp: I love working on vaporware

13:03 sometimes people will throw so much money at you to help them make vaporware

13:10 sdegutis: dysfun: I used to use single-letters but then they get ambiguous, e.g. s could be symbol or string. So I don't use them for aliases or variables anymore.

13:11 dysfun: so because a few overlap (s is a very good letter for overlaps), you don't use it anywhere?

13:11 sdegutis: dysfun: it's happened too much

13:11 justin_smith: clearly "first letter of name" is not the right hash function

13:11 sdegutis: dysfun: We used them for about 2 years before we replaced all of them with a longer convention this March.

13:12 at first the convention included symbols, like myapp.view.foo :as foo#, myapp.presenter.foo :as foo$, myapp.model.foo :as foo*, myapp.service.foo :as foo!

13:13 dysfun: hungarian notation

13:13 sdegutis: But that wasn't as useful as I'd hoped, so I replaced them with myapp.view.foo :as foo.view, myapp.model.foo :as foo.model, etc

13:13 But that's still inconvenient to use, because I keep typing model.foo/ waiting for autocompletion, when it's actually foo.model

13:13 So lately I'm thinking of just doing myapp.model.foo :as model.foo

13:17 And thought it'd be prudent to see what conventions y'all use.

13:17 dysfun: brief ones

13:18 sdegutis: dysfun: what do you do when you have overlap, e.g. myapp.model.user and myapp.view.user and myapp.routes.user and myapp.presenter.user ?

13:21 dysfun: whatever works

13:21 like user-m (odel) vs user-v (iew)

13:22 the point is that it doesn't matter as long as a user can reasonably guess

13:22 sdegutis: ok

13:22 justin_smith: ,(require '[clojure.string :as the.namespace.that.has.stuff.for.working.with.strings.that.comes.from.clojure])

13:22 clojurebot: nil

13:23 tolstoy: Maybe just try out names in functions such that the functions are clear, then backport that to the require declaration?

13:23 sdegutis: justin_smith: that's not a very practical nor predictable convention

13:23 Thanks. Vased on everyone here's feedback, I think the right way for our app is myapp.model.user :as model.user

13:24 justin_smith: sdegutis: one could even say it is unconventional

13:24 sdegutis: Fortunately these things can be changed pretty quickly, in the span of like 30 minutes with a call to `sed` and a little proofreading.

13:24 jonathanj: ,(do (require '[clojure.string :as ™]) (™/lower-case "OKAY"))

13:24 clojurebot: "okay"

13:24 jonathanj: haha

13:24 justin_smith: jonathanj: I like how that looks like a fraction

13:24 jonathanj: i didn't actually know unicode names were allowed

13:25 time to rename all my stuff to emoji

13:25 dysfun: shh, noone tell sdegutis that coding standards doesn't mean bikeshedding

13:26 sdegutis: dysfun: yeah I got that that was your opinion of this conversation from your last comment, which is why I just replied to you with "ok" and left it at that, but thanks for being condescendingly explicit

13:26 jonathanj: wouldn't it be better to use something like mu and mv as names?

13:26 dysfun: you're welcome. leave the money on the dresser on your way out

13:26 jonathanj: i mean, having to type model.user/X instead of myapp.model.user/X seems like a pretty minor improvement

13:27 sdegutis: jonathanj: sometimes you have multiple models that begin with the same letter

13:27 jonathanj: then i guess user-m and user-v are good suggestions

13:27 tolstoy: If the models (whatever that is) have a lot of similar functions, a protocol would work?

13:28 sdegutis: yep that's why I'm going with model.user and view.user

13:28 tolstoy: hmm

13:28 tolstoy: interesting idea, will ponder on it

13:29 tolstoy: sdegutis I've been working with transforming incoming data into "records" and then having a "persist" protocol, and a "query" protocol, etc.

13:29 If incoming message satisfies "persist" then proceed, etc, etc.

13:29 sdegutis: ah right I remember you mentining that tolstoy

13:29 tolstoy: Sometimes a message implements multiple of these things. (Also "validate" protocol.)

13:30 sdegutis Yeah. It still hasn't seem like a super bad idea. ;)

13:30 sdegutis: Hmm. Our model namespaces don't actually share any functions.

13:30 I guess it's a good thing, it means we're not really repeating ourselves, and we have well structured and partitioned functionality.

13:30 justin_smith: tolstoy: works pretty well for clojure.core - that's how almost everything in clojure.core works (or functions built on that pattern of usage)

13:31 tolstoy: Yeah. The idea is that an incoming packet from a web socket just needs to do a few things: save some data, query some data, be validated, send a notification, so why not just have four functions?

13:31 BUT, then I use extend-protocol for a lot of defrecords. It doesn't remove all that code, but it does (maybe) factor it a tiny bit more cleanly.

13:32 sdegutis: tolstoy: during the past few years I've been developing a practice which currently is: avoid implementing helper functions or protocols until I'm 150% sure that I won't regret it in 12 months

13:32 (or macros, etc)

13:32 tolstoy: sdegutis The result is I just (require [my.protocol :as proto] ...) and don't need all those namespaces.

13:33 sdegutis Yeah, I've never really _needed_ those things, but how do I know that unless I try and fail? I feel like protocols are super useful, but not obviously so (for app devs, not lib devs).

13:33 hiredman: if you extend protocol, and then don't require the code that does the extending, and just require the protocol, you are asking for a problem

13:34 tolstoy: I do a lot of (m/map->SaveUserProfile some-data-from-socket) and at least once nice thing: when it prints, I can see exactly what it wsa supposed to be.

13:34 hiredman Yes. I've encountered that.

13:35 sdegutis: tolstoy: hmm interesting

13:36 tolstoy: What I don't do is (defrecord ...) and then extend all the protocols in the same file/declaration as that defrecord.

13:38 I can have a "validatable.clj" namespace and keep all that logic (and helper functions) together. But as hiredman noted, you have to (:require app.persitable app.validatable) etc somewhere, or those impls won't get noticed.

13:38 Downside: When you create a new entity, you sorta have to know what to do in several different files.

13:40 justin_smith: tolstoy: cross-cutting concerns are hard - the relationships in real code are often more like a DAG than a tree

13:40 at least we can usually avoid full fledged multi-graphs...

13:41 tolstoy: Yeah. I organize by function, rather than type: all the validate functions, all the persist functions, all the query functions, etc. So, I'm not sure there's a "model" in any traditional sense.

13:42 anandamide: I just started with clojure today, and im getting some "weird" behavoir

13:42 tolstoy: s/functions/implementations/ (for each type) but it seems like functions. ;)

13:42 justin_smith: tolstoy: well, one can model operations and transforms rather than objects and state, this is FP after all :)

13:42 anandamide: do tell

13:43 anandamide: I have this function that is over multiple lines, and unless I remove the linebreaks before pasting it into the repl, it doesnt evaluate it correctly, cutting it in half

13:43 one sec, ill make a paste of the error message

13:43 hiredman: given the recomendation to not extend protocols unless you own the type or the protocol, the logical places for protocol extending are the file where the protocol or the type is defined

13:43 justin_smith: anandamide: yeah, if you can show how the input goes in too that would be good

13:43 tolstoy: justin_smith Yeah. That's why I'm wondering of sdegutis namespace naming conventions are pointing up the need for a foundational shift in his code base (admittedly probably not worth it).

13:44 justin_smith: sdegutis: you should learn category theory

13:44 tolstoy: hiredman Notes.

13:44 hiredman I mean, noted.

13:44 sdegutis: justin_smith: y4?

13:45 justin_smith: sdegutis: to internalize structures as operations between domains rather than recipes for punching state in containers

13:45 it's often simpler (but of course not always)

13:45 anandamide: http://pastebin.com/TAGggTQp

13:46 sdegutis: tolstoy: So far the only two things I could see doing are implementing (description some-model) and (element some-model), but even then, the description and (hiccup) element are highly dependent on the context, e.g. we have one element-generating view-function for orders as the user sees them in order history, and one for orders as admins see them (with much more detail and admin links)

13:46 justin_smith: anandamide: it's iterate not itereate

13:46 that's all

13:46 anandamide: sorry, i fixed that later

13:47 sdegutis: tolstoy: For the most part, I've only found lego-style helper functions to be helpful, i.e. ones which are used within business-logic functions, rather than ones which become/replace business-logic functions

13:47 anandamide: I did notice that, but when pasting that specific function with the correct spelling and with line breaks it still doesnt work

13:47 justin_smith: anandamide: the repl doesn't care about newlines and accepts them anywhere it accepts whitespace

13:47 anandamide: feel free to share the new error

13:48 tolstoy: sdegutis In my model, I convert the request to a type (defrecord), and the "query" protocol to fit the needs, so it might be (query [type user database-ref]) or something like that.

13:48 sdegutis: tolstoy: hmm, by request do you mean http request?

13:48 tolstoy: sdegutis If the user isn't not available with the incoming request, then AdminOrders vs UserOrders, or something.

13:49 sdegutis: tolstoy: ah, i remember this now, your model is tied to an edn-based http interpreter (called via clojurescript), right?

13:49 tolstoy: sdegutis Yeah. Just as an example. I'm using records as just convenient data containers, not as a "Model" for real word Entities or anything.

13:50 sdegutis Yeah. Click something on the UI, then [:save/stuff {:foo "bar" :baz "quux"}] is sent to the server. A case statement takes that first keyword and applies an appropriate record to it. Then (proto/validate! new-record) and so on.

13:51 If it were rest/stype http posts, the route itself would indicate which record to apply to the data. Then a single "process!" function is enough to handled _any_ item that flows in.

13:52 sdegutis: tolstoy: your conventions make more sense to me now that i know the context better

13:52 jonathanj: tolstoy: that's an interesting idea

13:52 sdegutis: tolstoy: do you use datomic on the backend of this?

13:53 jonathanj: tolstoy: i've been using protocol like i might have used a class in Java or Python but breaking them down into smaller individual things seems doable

13:53 tolstoy: I have dozens of types which are convenient to the data that comes in, NOT as a representation of Biz Objects. There's no user record. There's a "saveuser" or "update-password" or "expire-user" or whatever.

13:54 sdegutis Yes. Datomic. IMutatable implements (mutate! [this datomic] ....) and IQueryable for (query [this datomic]).

13:54 sdegutis: tolstoy: haha, IMutable is mutable

13:54 tolstoy: do you expose any of the actual shape/structure of your datomic schema to your front-end?

13:55 jonathanj: should've named it I'mMutable

13:55 tolstoy: jonathanj Yeah, I'm using it more as an organization strategy, kind of. Or like algebraic types, kinda.

13:55 jonathanj: tolstoy: yeah, i like it

13:56 tolstoy: sdegutis: Well, say, when a user logs in, I send a [:user/auth {:token "aklaslda"}] and the IQueryable (or IFindable) then returns with a blob of useful data that's a cobbled together pull-api thing.

13:57 sdegutis But I gave up, a long time ago, modeling entities in my database. The "database" is the model. Ask it questions, get arbitrary results back out.

13:58 Need a page with some user data, some orders the user has seen, and a peach? Just run the query and shove it back out. No need to model Users Orders and Peaches in the code other than as temporary value objects.

13:58 sdegutis: tolstoy: my only concern is that may be a security risk, to expose some of the shape/schema of your database to the front-end

13:59 tolstoy: but I do agree with your philosophy, since datomic entities are our official first-class model, and we merely have helper functions to assist in examining/manipulating entities

13:59 tolstoy: sdegutis Well, db/ids don't make it through. foo/bar becomes bar. I guess I'm not sure what you mean.

14:00 sdegutis: tolstoy: the attributes themselves, if the user may know anything about them, i.e. their name or cardinality or type, then the user may find a security hole

14:00 tolstoy: sdegutis Oh, they make it back to the client as regular maps. No schema attributes.

14:00 sdegutis: e.g. if the user knows that :user/email is of :db.cardinality/one and :db.type/string and unique/value, then they may find a security hole or something

14:00 ok

14:01 tolstoy: Something like, {:id "asads" :name "Some User" :orders [...] :peach {:id "asdas" :status "tasty"}}.

14:02 I try to keep in mind that I'm writing a custom app, not a general API or library or massive netflix style endpoint. ;)

14:03 The end result of all of this is that my server-side API is down to a large case statement that transforms the edn/json into a clojure record, and a single 10 line "process!" function.

14:04 BTW, technique works great in ClojureScript, too.

14:05 Click a button, put (FindUserOrders. user-id) on a channel, implement Sendable and/ or Mutatable to update the state atom, or send a socket message, etc.

14:12 sdegutis: Netflix has an endpoint?

14:13 man I wouldn't be surprised if charmin.com had a rest api these days

14:13 tolstoy: Oh, I don't know. Whatever serves all their clients.

14:13 sdegutis: :P

14:14 tolstoy: They ended up implementing a query API rather than REST, so they could keep up, if you follow some of David Nolen's vids.

14:28 sdegutis: i have not, sorry

14:30 Videos and conference talks are hard for me to learn anything from due to them always taking way too long to get to the point. Text is much easier to skim/grep/read.

14:31 tolstoy: I watch them just to get a feel, or to (hopefully) load up the lateral thinking potential.

14:31 I'm never going to do anything with automata, but sometimes a sentence in the talk will spark an idea. That kind of thing.

14:32 dysfun: flatmap flatmap flatmap boom?

14:40 tolstoy: The Anxiety of Influence

15:00 sdegutis: Is it possible to completely destroy a var?

15:00 Not merely unset it.

15:00 dysfun: what effect would that have beyond unsetting it?

15:01 sdegutis: dysfun: destroying it

15:01 dysfun: you mean calling its finaliser?

15:01 sdegutis: Ah, ns-unmap

15:01 dysfun: oh, unmapping it

15:01 sdegutis: dysfun: mainly to clear up clutter in an ns

15:01 dysfun: yeah, unmap it from the ns

15:16 machinewar: how can I download/require a third-party package in leinengen repl?

15:17 I know how to do it with dependencies in a file, but can I do it somehow from within a repl session in user namespace

15:21 bmuk: if I have a named parameter in a route (say (GET "/message/:id" ...)), how can I access both the request and the id? would it just be [request, id]?

15:21 thachmai: hello

15:21 do you know an efficient way to make sure that the vector doesn't grow beyond a certain size?

15:23 I could do a combination of count and subvec but it feels rather heavy

15:23 hiredman: uh

15:23 definitely not subvec

15:23 just don't add things

15:24 thachmai: I do want to add things. But if the vector is too large I want to keep only the last n elements

15:24 hiredman: you want a ring buffer, not a vector

15:24 thachmai: oh cool, thanks

15:25 hiredman: you can build one from a vector, a vector a number indicating where to write, and and you increment the write position and mod it to the size you want

15:26 or, you could just use a queue

15:30 bmuk: I want to have a route with a parameter, but I still need to access the JSON in the request body

15:39 thachmai: bmuk, what's stopping you from accessing the :body?

15:43 bmuk: thachmai: all my other routes look like this: (POST "/login" req (let [username (get-in req [:body :username])]...

15:44 if I have to replace req with the route parameter, what do I call get-in with?

15:45 dysfun: :params :name

15:53 bmuk: dysfun: so you're saying keep it like this - (POST "/message" req .. and just do (get-in request [:params :id])?

15:53 wouldn't that have to be sent as https://foo.com/message?id=1234

15:54 dysfun: (POST "/message/:id" req ... (get-in req [:params :id]))

15:54 POST is just a very clever macro around ring maps and functions

15:55 bmuk: ah ok. So the macro behaves differently if instead of req I say [id]?

15:56 and without ":id" being in the route :params would refer to a query string

15:56 dysfun: if you pass it a vector, it treats it specially

15:56 otherwise you are just binding to the request map

15:56 so you can e.g. {:keys [params] :as req}

15:58 bmuk: ahh. I feel like I'm repeating myself a lot in this routing - several routes are identical except the name of the route and the function I call to get the body. Is there any way I can write that once?

15:59 dysfun: you can make the bodies call simple functions that handle the entire request

15:59 literally just treating the routes as a mapping from route to function

16:00 and then you can refactor those functions as normal when you see repeating patterns

16:01 bmuk: that makes sense

16:01 dysfun: as a general case, getting things where you can see them helps

16:01 bmuk: so (POST "/login" req (login-user req))?

16:01 what do you mean by that?

16:02 dysfun: that macro is doing a lot of things

16:02 when you can more clearly see what's going on, things become easier to refactor

16:03 bmuk: push more of the logic into a function I control

16:03 dysfun: yeah

16:04 amalloy: or just (POST "/login" req login-user)

16:11 bmuk: if I'm going to be making requests and decoding responses to json, is clj-http-lite + cheshire, or just clj-http the better option (in regards to speed)?

16:12 dysfun: no idea. figure out if you have a performance problem first through profiling and benchmark if necessary

16:14 bmuk: True

16:14 So the easiest way would be to use clj-http's built in decoding and if it's not fast enough try cheshire?

16:15 dysfun: if you look, you'll probably find it uses cheshire

16:15 most clojure libs do

16:15 bmuk: It does, just checked

16:15 optionally, anyway

16:33 hiredman: clj-http-lite is unlikely to be faster

16:34 clj-http-lite exists entirely to depend on just classes that ship with the jvm, if you don't care about that, don't use it

17:54 amoe: does anyone have some pattern to deal with the situation where a REST API needs to make a link to some resource. The absolute URL can only be resolved by knowing some details from the "Host" header. So the full http request (or at least the looked-up URL prefix) needs to be passed through many functions as a parameter even though the prefix is really peripheral to the purpose of many of the functions.

18:11 alex-weej: looking for something like python / perl ‘or’ which returns the first none-nil argument lazily evaluating

18:11 does this exist in the core?

18:12 (or foo bar) where bar is only evaluated if foo is nil

18:12 danlarkin: that's how it works

18:12 except s/nil/falsy/

18:13 alex-weej: it returns true or false though

18:13 danlarkin: no it doesn't

18:13 alex-weej: buh, i must have been doing it wrong :/

18:14 hah yes, sorry, ignore me

18:14 definitely too late to be hacking ;)

18:14 thanks

19:08 dimon_: I have this (def users [{:name "James" :age 26} {:name "John" :age 43}]). How can I change all its values of "name" using the functions map and assoc? I can't figure out how I'd use "assoc" in particular. By changing "name" I mean adding a string "_change" to its "name" value.

19:08 justin_smith: dimon_: something like (map #(update % :name str "_change") ...) should do it

19:09 dimon_: or is it required that you use assoc?

19:09 ,(map #(update % :name str "_change) [{:name "James" :age 26} {:name "John" :age 43}])

19:09 dimon_: justin_smith: thx, that's it.

19:09 clojurebot: #<RuntimeException java.lang.RuntimeException: EOF while reading string>

19:09 justin_smith: ,(map #(update % :name str "_change") [{:name "James" :age 26} {:name "John" :age 43}])

19:09 clojurebot: ({:name "James_change", :age 26} {:name "John_change", :age 43})

19:59 dimon_: I'm trying to change the format of a date which I display on a page in Luminum application:

19:59 (defn home-page

20:00 ;........

20:00 :articles (map #(update % :inserted_at (.format (java.text.SimpleDateFormat. "MM/dd/yyyy"))) (db/get-all-articles))

20:00 an error is No matching field found: format for class java.text.SimpleDateFormat

20:00 what am I doing wrong?

20:00 justin_smith: dimon_: is format a static method?

20:01 amalloy: you're calling format on a formatter but no date

20:01 dimon_: .

20:01 how should I call it properly?

20:02 justin_smith: dimon_: you need an anonymous function wrapping the (.format ...) call that inserts the passed in inserted-at value

20:03 and you'll need the (fn [x] ...) style syntax because #() does not nest

20:04 dimon_: justin_smith: could you show me?

20:05 TEttinger: (map #(update % :inserted_at (fn [date] (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") date)))

20:05 justin_smith: ,(map #(update % :inserted-at (fn [d] (.format (java.text.SimpleDateFormat. "MM/dd/yyyy") d))) [{:inserted-at (java.util.Date. 0)} {:inserted-at (java.util.Date. 666666666)}])

20:06 clojurebot: ({:inserted-at "01/01/1970"} {:inserted-at "01/08/1970"})

20:06 justin_smith: ~666666666 is aproximately 1 week.

20:06 clojurebot: c'est bon!

20:07 dimon_: justin_smith: tnx, I'll check it out.

20:12 justin_smith: TEttinger: hah https://gist.github.com/noisesmith/4ffc657ff89ad3b9903f7e7b6dd159e6

20:13 tolstoy: Right around midnight, 1970: bad times!

20:27 TEttinger: justin_smith: there's almost no significant stuff on those dates

20:27 1991 – The Visegrád Agreement, establishing cooperation to move toward free-market systems, is signed by the leaders of Czechoslovakia, Hungary and Poland.

20:29 steve macmanaman and the keyboard player for slipknot were born on one of those dates https://en.wikipedia.org/wiki/Steve_McManaman https://en.wikipedia.org/wiki/Craig_Jones_(musician)

20:33 justin_smith: haha

20:33 (dec numerology)

20:41 TEttinger: justin_smith: these fibonacci numbers are certainly off by a few milliseconds, but https://gist.github.com/pastebot/123af012b0a9f9a2255453161750a7c1

20:42 justin_smith: cool, we have a fibonacci date coming up then

20:43 TEttinger: 1546105899666

20:43 justin_smith: but that would be easier to read with pprint :P

20:43 TEttinger: interesting last 3 digits

20:43 pprint had a weird issue on my lazybot

20:43 it couldn't read the file separator property

20:43 err

20:43 line separator

21:42 machinewar: is there a core function to swap values in a vector? i.e. I have [

21:42 [1 2 3] and want it to be swapped w/ ["a" "b" "c"]

21:42 justin_smith: machinewar: assoc

21:42 ore replace

21:42 machinewar: do you want to replace by value or by position?

21:43 machinewar: justin_smith: value

21:43 amalloy: what does "swapped with" mean

21:43 like, what are your two inputs, and what is your desired output

21:43 justin_smith: ,(replace {1 "a" 2 "b" 3 "c"} [1 2 3])

21:43 clojurebot: ["a" "b" "c"]

21:44 justin_smith: ,(replace {1 "a" 2 "b" 3 "c"} [1 2 3 4])

21:44 clojurebot: ["a" "b" "c" 4]

21:44 machinewar: i.e something like input [1 "b" 2 "c"] {1 "a" 2 "b"} output -> ["a" "b" "c"]

21:44 meaning swap 1 w/ a 2 w/ b

21:45 justin_smith: machinewar: so close to what replace does as shown above?

21:45 machinewar: justin_smith: correct!

21:45 ah thanks that works1

21:49 man clojure is awesome

21:50 definitely in a honeymoon phase, but its perfect use case for what I'm working on

22:29 sdegutis: If you ever want to add a delimiter in a file and you have Cider running, paste in (symbol (apply str (repeat 80 ";"))) and press C-c C-w after it

22:29 Or just hold the ; key for a while and let go when the line is long enough, if you're not like me and don't care if it's exactly 80 or not

22:33 jeaye: sdegutis: 80I;<ESC>

22:34 sdegutis: jeaye: pfft, you and your vim wizardry

22:34 amalloy: M-8 M-0 ;

22:34 sdegutis: amalloy: pfft, you and your pure-emacs sorcery

22:35 jeaye: amalloy: Appears to be a tie

22:35 amalloy: in terms of what? number of keys?

22:35 jeaye: Key presses, both 5, assuming we use i instead of I since yours doesn't go to the beginning of the line

22:35 sdegutis: mine has the most typing so it wins

22:36 amalloy: imo emacs wins, because you don't have to release meta between 8 and 0

22:36 so you only press meta once

22:36 sdegutis: Mv 8 0 M^ ;

22:36 amalloy: but of course emacs and vim both win for just being editors where it's easy to do custom things

22:36 sdegutis: imo cider wins cuz it uses the most convoluted method possible

22:36 including requiring a full jvm to be running

22:37 jeaye: amalloy: Agreed.

22:37 amalloy: i can just imagine the eclipse bugzilla page

22:37 where someone asks for the next version to include the "insert a character 80 times" feature

22:38 sdegutis: amalloy: also, that explains why sometimes when using I'm emacs I accidentally press the wrong things and suddenly there's a lot of extra letters in there than I meant

22:38 amalloy: sdegutis: you can use C-h l to see what crazy thing you accidentally typed

22:38 sdegutis: whoa

22:38 insanity.

22:58 tolstoy: Huh. I've used C-u 78 - to get a line.

Logging service provided by n01se.net