Fork me on GitHub
#off-topic
<
2015-12-08
>
agile_geek07:12:28

@borkdude interesting. I suspect most of the 'issues' they mention apply equally to Clojure?

seancorfield07:12:25

@agile_geek: Coda's criticisms mostly ring true with my experiences back in the Scala 2.7 / 2.8 / 2.9 days but we chose to go to Clojure instead. We have not regretted that decision and we have not found similar problems with Clojure (we did not have performance problems with either language). /cc @borkdude

agile_geek07:12:12

@seancorfield: interesting. Yammer's comments about not finding Scala dev's easily would apply x5 for Clojure and I think this is the largest hint about why they backed out Scala. They are trying to commoditise development and make developers more fungible.

mpenet07:12:42

getting up to speed writing "idiomatic" (whatever that means) scala vs clojure doesn't require the same amount of time/effort either

mpenet07:12:04

but java probably fits better in their case I guess

agile_geek07:12:26

@mpenet: do you mean idiomatic Scala is faster to get up to speed on (assuming you're hiring Java dev's)?

agile_geek07:12:23

It looks to me like their issues stem from not understanding how to best use the language for their use case as it's hard to get experienced dev's. It's something that worries me about Clojure too as both languages are young and we haven't learned all the patterns and pitfalls yet.

mpenet08:12:44

No, clojure

mpenet08:12:29

In my experience finding clojure devs or having a decent dev get up to speed with clojure isnt that difficult

agile_geek08:12:28

@mpenet: I would say there's less to learn to write idiomatic Clojure. I must not be a decent developer then as 19 years of pure OO and Java meant I found the learning curve very steep!

borkdude08:12:01

@agile_geek: I would expect the same things with clojure, maybe even worse performance in some cases. don't know

mpenet08:12:21

Yes, it's also very easy to learn from other's people code, given how few building blocks there are. Back then I got a team of Java/C devs in a large company writing "ok" clj code in a couple of weeks, and in 2 months or so they would write quality clj code. Mostly through code reviews and using nicely written libs as examples

mpenet08:12:05

performance is another matter entirely

agile_geek08:12:48

@mpenet: I think you've proved my points: 1. I am not a good developer 😉 2. You need mentoring and an experienced developer to code review.

borkdude08:12:52

@agile_geek: I've heard from a Scala guy who rewrote a for loop to a while loop with vars, because in his system, too many objects were moved to old generation and then requiring too much heap memory

borkdude08:12:24

@agile_geek: it was a system that processed many messages a second running on AWS

mpenet08:12:04

agile_geek: just read lots of code, reviews are nice but you can get there by yourself too

mpenet08:12:25

also github, people are doing code reviews for free via PRs simple_smile

borkdude08:12:38

there's also a #C053PTJE6 channel here

borkdude08:12:49

I would have expected the same problem with Clojure in such a system maybe

mpenet08:12:27

about perf we also have options in extreme cases, either writing in java the slow bits or JNI when it makes sense (rarely).

agile_geek08:12:54

@mpenet: although I don't do Clojure for the 'day job' I've been using it for side projects for 3 years and pretty much having to learn it on my own with a little help from Clojure Dojo's but it's been painful...but then I'm old!

borkdude09:12:42

I posted this in #C053PTJE6 but maybe also relevant to our discussion here: I was wondering why this Clojure program takes ages to manipulate a mutable array, while a comparable Scala program only takes 2 seconds on my Macbook Air. Clojure: https://gist.github.com/borkdude/8bf5780efa371455e83d Scala: https://gist.github.com/borkdude/62094893df250225c9bc

jaen09:12:37

@borkdude: Hmm, that's interesting. If you want you can compare with mine - https://gitlab.com/jaen/advent-of-code/blob/master/6/lights.clj - but I've used core.matrix.

borkdude09:12:49

(this is only part one btw, but part two would be similar)

dm309:12:58

@borkdude: first step is to (set! *warn-on-reflection* true)

dm309:12:39

then, once you fix reflection warnings, convert doseq, reduce and for to loop

borkdude10:12:24

there's something else not right either. When I do C-c C-k in Emacs, the code takes too long to evaluate. When I switch namespace, it takes a few seconds. It might be a problem with Cider, etc.

borkdude10:12:15

maybe I know what it is: kibit etc are trying to evaluate my code too and are creating this huge array every time.

borkdude10:12:49

unfortunately that wasn't the problem

jaen10:12:51

Yeah, I've also converted things to use loop and it didn't seem to have helped for some reason

dm310:12:44

the biggest offender is usually reflection

dm310:12:03

then if you convert to loop - use transient/mutable data structures

borkdude10:12:34

@dm3: I get no reflection warnings, which may be a bit weird?

jaen10:12:16

@dm3: that's already mutable structures, since it's a Java array

dm310:12:31

yeah, I meant in general case

jaen10:12:01

I bastardised this example to use loop and whatnot and it's still slow. Puzzling.

jaen10:12:17

Up to couple seconds per once process-line

jaen10:12:10

(defn process-line [command ^ints coords] ; left top right bottom
  (let [left   (aget coords 0)
        top    (aget coords 1)
        right  (aget coords 2)
        bottom (aget coords 3)]
    (time
      (loop [i left]
        (when (<= i right)
          (loop [j top]
            (when (<= j bottom)
              (case command
                :turn-off (aset ^longs grid i j -1)
                :turn-on  (aset ^longs grid i j 1)
                :toggle   (aset ^longs grid i j (* -1 (aget grid i j))))
              (recur (unchecked-inc j))))
          (recur (unchecked-inc i)))))))

jaen10:12:17

I don't know what can be done more than that

jaen10:12:50

"Elapsed time: 19.703443 msecs"
"Elapsed time: 251.43566 msecs"
"Elapsed time: 483.458811 msecs"
"Elapsed time: 2044.198587 msecs"
"Elapsed time: 1014.591659 msecs"
"Elapsed time: 49.72036 msecs"
"Elapsed time: 558.516576 msecs"
"Elapsed time: 522.276886 msecs"
"Elapsed time: 118.047631 msecs"
"Elapsed time: 37.807507 msecs"
"Elapsed time: 149.030111 msecs"
"Elapsed time: 2560.647433 msecs"
"Elapsed time: 609.248053 msecs"
"Elapsed time: 301.237468 msecs"
"Elapsed time: 94.728694 msecs"
"Elapsed time: 1544.405323 msecs"
"Elapsed time: 489.866394 msecs"
"Elapsed time: 3104.153334 msecs"
"Elapsed time: 100.474167 msecs"
"Elapsed time: 700.43767 msecs"
"Elapsed time: 0.467456 msecs"
"Elapsed time: 5.8063 msecs"
"Elapsed time: 135.177811 msecs"
"Elapsed time: 893.965435 msecs"
"Elapsed time: 431.381867 msecs"
"Elapsed time: 132.645449 msecs"
"Elapsed time: 611.209867 msecs"
"Elapsed time: 2.890451 msecs"
"Elapsed time: 2467.134139 msecs"
"Elapsed time: 1324.462145 msecs"
"Elapsed time: 266.358281 msecs"
"Elapsed time: 1018.531767 msecs"
"Elapsed time: 227.757252 msecs"
"Elapsed time: 70.854271 msecs"
"Elapsed time: 642.159927 msecs"

jaen10:12:56

That's just puzzling

jaen10:12:12

I guess you'd have to break out a profiler to understand why it's slow.

borkdude10:12:51

yeah, already downloaded Yourkit. First to the gym now

dm310:12:12

know the problem

dm310:12:19

multi-arity aset

dm310:12:53

you have to aget the inner array and then (aset inner idx -1)

dm310:12:58

as that will get inlined

dm310:12:09

multi-arity goes through function invocation

dm310:12:42

I'm wrong 😞

dm310:12:53

got excited for no reason simple_smile

jaen10:12:43

I found it curious that my core.matrix solution works the problem in ~6s

jaen10:12:04

But when I switch the implementation from vectorz to clatrix (which uses jblas)

jaen10:12:13

It is considerably slower

jaen10:12:29

Which is counter-intuitive, one would expect jblas to be faster.

dm310:12:36

hm, wait

dm310:12:39

wasn't wrong after all

dm310:12:47

just didn't apply a type hint

dm310:12:09

make-grid went from 16 sec to 30msec

dm310:12:38

(defn make-grid []
  (let [^"[[J" grid (make-array Long/TYPE grid-size grid-size)]
    (loop [i 0]
      (loop [j 0]
        (let [^"[J" d1 (aget grid i)]
          (aset d1 j -1))
        (when (< (inc j) grid-size)
          (recur (inc j))))
      (when (< (inc i) grid-size)
        (recur (inc i))))
    grid))

dm310:12:04

not the most elegant code...

dm310:12:43

conclusion - multi-arity aset shouldn't really be used

jaen11:12:39

"Elapsed time: 418.730455 msecs"

jaen11:12:18

But yeah

jaen11:12:20

It's sooo ugly

jaen11:12:25

(defn process-line [command ^ints coords] ; left top right bottom
  (let [left   (aget coords 0)
        top    (aget coords 1)
        right  (aget coords 2)
        bottom (aget coords 3)]
    (loop [i left]
      (when (<= i right)
        (loop [j top]
          (when (<= j bottom)
            (case command
              :turn-off (aset ^longs (aget ^"[[J" grid i) j -1)
              :turn-on  (aset ^longs (aget ^"[[J" grid i) j 1)
              :toggle   (aset ^longs (aget ^"[[J" grid i) j (* -1 (aget ^longs (aget ^"[[J" grid i) j))))
            (recur (unchecked-inc j))))
        (recur (unchecked-inc i))))))

jaen11:12:32

The question is

jaen11:12:58

The question is then why aset with multiple indices is written in a way that does not optimise.

dm311:12:24

I guess you'll be able to find a patch providing optimized inlined versions for more arities somewhere in Clojure JIRA

dm311:12:51

submitted some ~5 years ago simple_smile

dm311:12:19

just 2 years

jaen11:12:30

insert a sarcastic remark how it's better than expected

Alex Miller (Clojure team)12:12:12

That ticket has 0 votes - voting helps us determine priority

borkdude12:12:29

I have to admit this is the first time I needed mutable nested arrays in Clojure simple_smile

borkdude12:12:51

and maybe I shouldn't have needed them. I saw a solution using regular vectors, but I wonder how that would have performed

jaen12:12:22

Certainly faster than the version with reflection, but probably noticeably slower than core.matrix. I think it strikes nice balance between performance and readability

borkdude12:12:38

@jaen: did you try it?

jaen12:12:10

No, that's a conjecture. But since you say you've seen that I would certainly try it for comparison if you'd link it.

borkdude12:12:10

let me find it

jaen12:12:09

Yeah, just found it as well

jaen12:12:10

Let's see

jaen13:12:45

╭─jaen@himitsu  ~/projects/adventofcode/6 ‹2.2.0› ‹master*› 
╰─$ ./lights.clj 
# of lights lit: 569999
"Elapsed time: 6345.035897 msecs"
Total brightness: 17836115
"Elapsed time: 6327.370421 msecs"
╭─jaen@himitsu  ~/projects/adventofcode/6 ‹2.2.0› ‹master*› 
╰─$ ./lights.clj
LIGHTS ON:  569999
"Elapsed time: 6010.859778 msecs"
TOTAL BRIGHTNESS:  1.7836115E7
"Elapsed time: 15314.694691 msecs"

jaen13:12:52

That's faster than I expected

jaen13:12:25

Especially interesting how the total brightness case looks

borkdude13:12:42

On my machine it takes a looong while, probably because my memory is full

borkdude13:12:27

I should've upgraded when I bought this Macbook Air, totally sucks for this kind of problem in Clojure 😉

borkdude13:12:39

let's try on my macbook pro

jaen13:12:18

1.2GB resident for me

borkdude13:12:33

@jaen: what's that?

jaen13:12:45

Well, you said something about memory being full

jaen13:12:52

So I said how much the program takes for me

jaen13:12:03

1.2GB, ran through boot scripting thing

jaen13:12:18

Second part in my code is probably this slow, because I multiply the whole 1000x1000 grid element-wise; I couldn't find a way to multiply only a subset of a matrix with core.matrix.

borkdude13:12:03

15 seconds on my Pro, still not that good, but better. What kind of hardware do you have?

jaen13:12:18

Intel(R) Core(TM) i5-4670K CPU @ 3.40GHz

jaen13:12:23

Overclocked to 4.2 GHz though.

borkdude13:12:41

2.4 GHz i7 here

jaen13:12:17

I guess twice the clock (and possibly newer generation) could account for that difference

borkdude13:12:56

maybe using a single vector would have been viable too and using a transient way of updating it

borkdude13:12:02

worth checking out

borkdude14:12:26

good. using a transient vector 11 seconds on my macbook air (vs 86 seconds persistent vector) simple_smile

borkdude14:12:14

about 7 on the pro

borkdude14:12:33

I rewrote it now using a single mutable array: not faster than transient vector

seancorfield15:12:48

@agile_geek: if you're really steeped in OOP then FP can be hard / painful to learn. Of all the folks I've watched learning Clojure those with years of Java had the most trouble.

agile_geek15:12:57

😄 that's been my experience.

seancorfield15:12:42

As for old, I'm 53 and had been doing OOP for 20 years before learning Clojure (a decade of C++, a decade of Java, roughly), but before all that OOP I'd done some FP way back in the 80's which really helped me.

seancorfield15:12:39

My early Clojure was far from idiomatic 😢

agile_geek15:12:57

@seancorfield: you have 3 years on me. I had no FP in the 80's just procedural code (Fortran, COBOL, PL-1, Basic, etc.)

agile_geek15:12:25

I taught myself OOP and Java..

agile_geek16:12:15

and FP and Clojure now but learning a new paradigm 20 years on is hard.

seancorfield16:12:00

I had to teach myself OOP too as I'd been raised on procedural stuff (like you, COBOL, FORTRAN, PL/1 etc).

agile_geek16:12:43

A kindred spirit!

seancorfield16:12:52

But I'd encountered APL during college (in my industrial placement year) and then Lisp in my final year and then SASL, ML, and Miranda in my research years before I became a C and COBOL dev 😃

seancorfield16:12:06

Forgetting all the bad stuff you learn with Java really can be tough (and I truly believe Java is bad for you - worse than BASIC ever was).

borkdude17:12:26

Personally I think FP is easier to learn than OOP.

borkdude17:12:00

but you have FP and FP though. Typical Clojure FP is simpler than Haskell FP.

borkdude17:12:39

of course you can do anything, monads, lenses, etc, in Clojure, but with typical I mean what you'll see in an average program

jaen17:12:56

I don't have much programming experience (couple-ish years) but I wouldn't say learning OOP as a paradign is necessarily hard, it's just "stuff with state doing things". Using OOP effectively though, that's a different beast.

jaen17:12:49

For example when I tried to learn about event sourcing from the OO viewpoint I couldn't make head or tails out of it.

jaen17:12:23

When some blog post explained it to me in terms of a fold I grokked it immediately.

jaen17:12:54

So I don't think OOP is hard in and of itself, but makes other things harder than they necessarily are.

noonian17:12:17

OOP isn’t hard, living with it after is.

donaldball17:12:11

OOP is a fine tool, it’s just not the right tool for every job. I like building stateful objects to encapsulate stateful things, even in clojure; e.g. a persistent http client. I don’t miss writing custom objects for every domain data type.

sveri17:12:26

Getting clojure and the FP concepts behind it was far easier than getting OOP. Considering the fact I have been doing OOP for almost 10 years and still feel like a rat in a labyrinth in it. Especially in a large code base. In the books, OOP is dead easy. Pizzathing PizzaThingProvider PizzaDto, it's all cool, but mix like several thousand of them and try to remember all the mistakes or shortcuts you took in the last 5 years^^

jaen17:12:32

Yeah, that's exactly what I mean. OOP itself it's easy, usage of OOP not necessarily so. Thinking in terms of data transforms is usually easier, even in the imperative world (that PS3 presentation where data-driven code was ~5x faster than pure OOP anyone?).

borkdude18:12:20

@jaen: Down to 1.5 seconds now in Clojure simple_smile

borkdude18:12:10

@jaen: that's on my Macbook Air. On your system it should even run faster.

seancorfield18:12:53

@borkdude: does that mean the Clojure version is faster than the Scala version?

borkdude18:12:10

@seancorfield: about the same now

borkdude18:12:39

@seancorfield: the solution comes down to manipulating a mutable array. Faster than Java/Scala we can't get on the JVM I think

borkdude18:12:10

@seancorfield: of course this could be implemted by manipulating bits, that would be even faster, but we might as well go to assembly then.

jaen18:12:07

@borkdude: is that code complete? It complains about toggle-grid! not being defined

jaen18:12:06

I imagine #(toggle-grid! grid %1 %2) should have been #(update-grid! grid %1 %2 toggle), yes?

cab18:12:23

its from http://adventofcode.com/day/6 i’m not sure how much code existed

jaen18:12:09

@borkdude: still slightly slower than my version (probably because you have the left/top/bottom/right exploded like that) but ~500-600 msecs

jaen19:12:12

Hah, that's funny

jaen19:12:26

If I typehint an arg it complains I can't typehint something with a primitive initializer

jaen19:12:31

If I remove the typehint

jaen19:12:34

I get reflection warning

jaen19:12:43

And No matching method found: aget

jaen19:12:51

That's a bit of a Catch22

jaen19:12:25

Hah, there was a conflicting type hint further in the code, that was a bit of a confusing error message.

jaen19:12:31

@borkdude: with some further changes I've gotten it down to ~370msecs. Looks ugly as hell, but is fast ; d

jaen19:12:53

Scala is faster

jaen19:12:55

~190ms for me

jaen19:12:46

Wow, ran it again and 120ms. Curious.

jaen19:12:35

Also another curious thing - running from REPL Clojure is 2x slower.

noisesmith19:12:28

@jaen: in your last loop based version the case is still inside the loop, you should see a speedup by moving the case out of the loop, because clojure is not smart enough to optimize a constant switch like that

jaen19:12:32

In @borkdude's last version it's outside

jaen19:12:40

I used that this time

noisesmith19:12:24

yeah, I made the same suggestion on stackoverflow simple_smile

dm320:12:13

@jaen that is probably due to the TieredCompilation options

dm320:12:40

TieredStopAtLevel=1 which is probably switched on for repl

jaen20:12:55

Hah, yeah

jaen20:12:03

I've just ran boot repl instead of lein repl

jaen20:12:15

And it's ~400ms again.

jaen20:12:27

Could be that lein repl forces less optimisations

sveri20:12:33

@jaen: leiningen has some settings set that slow down execution. You might want to google that, AFAIK you can turn them off too

jaen20:12:01

I don't use lein much nowadays (cljs + boot = <3) but good to know

cab20:12:51

what do you like about boot @jaen?

cab20:12:04

(not meant in a negative way — ive never tried it but have considered switching)

jaen20:12:29

Basically when I've started playing with Clojure and Clojurescript more seriously

jaen20:12:05

Setting up project with lein-cljsbuild to have a console repl, hot reloading, mutliple builds and other such niceties was a major pain

jaen20:12:14

With boot it Just Worked™

jaen20:12:20

So I never looked back

jaen20:12:30

Maybe it's not a pain with leiningen anymore either

jaen20:12:48

But I'm pretty content with how simple setting up a Clojurescript project with boot is.

cab20:12:20

interesting, thanks!

cab20:12:33

i’ll give it a try. i also liked how easy it makes it to set up “one-file” tools

jaen20:12:43

Yeah, the shebang thing is nice, I run my adventofcode scritps that way

jaen20:12:58

You can take a look at https://github.com/martinklepsch/tenzing, https://github.com/Deraen/saapas or this thing of mine - https://gitlab.com/jaen/clj-cljs-presentation/tree/master - if you want to see how a boot project set up for Clojurescript development looks.

cab20:12:48

awesome! thanks!

jaen20:12:47

My project has a few niceties over two former projects in that it uses boot-middleman (slightly modified to support specified output dir) for things like stylesheets or statis HTML, hot reloading with component (also slightly modified to work with regex exclusions) and a dev handler that works well with F5'ing an SPA (redirects any URL to the index.html).

jaen20:12:54

But it's more for comparision to the first two

jaen20:12:56

Than anything.

cab20:12:28

very cool

sveri20:12:33

@jaen: that's what I made closp for. I was trying boot back then, but it has 3 or 4 defects that make it unusable on windows which keeps every windows user from using it

sveri20:12:51

And closp also has hot reloading with components

sveri20:12:49

I am not saying leiningen is better than boot or so. It's just, it doesnt work on windows, which is a pity, I like the concept itself very much

jaen21:12:37

@cab: I've just noticed it was a bit old; I've updated it right now. It even now has a fancy thing that reloads dependencies from resources/dependencies.edn on the fly, a la vinyasa for lein. It doesn't always work (when transitive deps conflict for example) but most of time it's awesome to add a dep and have it Just Work™ with restarting the process. But this is a bit non standard, so like I said - learn from the first two projects I linked and you can compare that with my changes afterwards.

jaen21:12:42

@sveri: well, I have an urge to bust out my greentext and go

> 2015
> using windows

jaen21:12:46

But I kinda understand

jaen21:12:56

How it must be annoying to have a tool not working where you want it

jaen21:12:21

At least I know how it is annoying when a game I would want to play won't get a linux port ; d

jaen21:12:19

I remember trying things like chestnut and such a year ago and having problem to get it to behave as well.

jaen21:12:49

(at least that's what you based closp on if I understand correctly)

jaen21:12:37

Like I say, maybe it's cool now and you don't have to use boot, I didn't have a reason to re-evaluate that choice thus far though.

sveri21:12:46

@jaen Having used Linux for a long time I feel with you 😄 Based on chestnut and luminus basically means I adapted it to make everything work. Where everything is related to the delveopment workflow like hot code reloading and instant change pushes to the browser and uberjar and tests and integration tests and authentication and stuff that you might need some day. I totally agree, everything did not work out of the box back then, therefore, a template that makes it work. Was my only choice back then and probably still is today regarding boot.

jaen21:12:07

Well, if you made everything work reliably then I imagine there's little reason to use boot, yeah.

jaen21:12:40

Though I'm pretty curious why anyone would want to go back to Windows after using a better OS (be it MacOS or Linux).

jaen21:12:54

Unless he really misses being able to play DX11-only games ; d

sveri21:12:28

Yay, OS-Wars. I have been a linux proponent for many years, convinced my mother, my sister, my room mates to use it, they all still do. However, when I got my newborn all of a sudden my spare time shrank ad infinitum and I felt what it takes to have to make stuff work all the time. Things like energy mode for laptops where you have to fiddle endlessly and still don't manage to use as few power as windows does. Or the last thing I remember was that I could not reliably switch between two sound devices on my desktop on gnome. Yea, all that stuff that tikes time and googling somehow just works for me on Windows. So I got converted, it's sad, but true.

naomarik21:12:59

is it correct to say that figwheel is a repl option like rhino/node/weasel?

jaen21:12:09

@sveri: but why not Mac then. It combines the Just Works™ of Windows with not wanting to kill yourself when developing.

jaen21:12:49

At least that's what I wanted to do when I had to develop on Windows and that's actually what made me switch to Linux - I couldn't for the life of me figure out how to install SFML.

sveri21:12:42

@jaen: Easy, I don't want to pay more money for the same hardware. Whenever I buy a new laptop I look how the same mac would cost me and just instantly turn back. No reason to pay 3 - 600€ more just for the fun of it

jaen21:12:27

@naomarik: it's probably more than that; you have a browser repl for sure, but you have other things as well, like hot code reloading, just repl doesn't provide.

sveri21:12:05

Sometimes of course it bites me. Stuff like Haskell seems to work better on linux. Vagrant, Docker and some other things. I always wanted to try bazel and see if I could make it work for clojure, but it does not work on windows either.

naomarik21:12:34

@jaen yeah, i love the hot code loading, been using that now, but trying to get the full repl experience going... i'm assuming it's possible to use the same figwheel nrepl that is in context of the browser?

jaen22:12:41

@sveri: I don't think a comparable quality ultrabook with Windows is any cheaper, but if you don't need such high build quality then I guess you can save hunderds of bucks by not going with a Mac for sure.

naomarik22:12:43

so essentially i can swap the same atoms that get updated in browser?

juhoteperi22:12:02

I would say it makes sense to buy Macbook if one saves 3-6 hours of tinkering with Windows, even if the hardware is more expensive than comparable Windows laptop

sveri22:12:04

Well, my bed is calling. Have a nice sleep everyone

jaen22:12:04

@naomarik: it's been a long time since I tried figwheel, but I think it's REPL connected to the browser so whatever you did there, was reflected in your app state in the browser.

jaen22:12:48

@sveri: about docker - oh yeah, I've a university project now and I packed things up with docker, because apart from one girl everyone else is running Windows.

naomarik22:12:55

@jaen do you use om/reagent and if so waht's your workflow like if not figwheel?

jaen22:12:02

I hoped that would make running the project for them flawless

jaen22:12:13

Docker wouldn't even run.

jaen22:12:32

It complained that virtualisation extensions are not available on a i7 Haswell o_0

jaen22:12:01

We wasted 2 hours on this and didn't accomplish anything in the end '

jaen22:12:31

So I'd choose Linux any time even if sometimes I had to tinker a bit.

jaen22:12:44

Maybe the hardware part can be finnicky

jaen22:12:51

But the development part Just Works™

jaen22:12:48

@naomarik: I use reagent and drumroll boot.

jaen22:12:57

You can scroll a bit above for my comment

naomarik22:12:59

you get hotcode reloading etc?

jaen22:12:04

Out of the box

naomarik22:12:10

what am i doing with figwheel then?!

jaen22:12:39

For your convenience: > You can take a look at https://github.com/martinklepsch/tenzing, https://github.com/Deraen/saapas or this thing of mine - https://gitlab.com/jaen/clj-cljs-presentation/tree/master - if you want to see how a boot project set up for Clojurescript development looks.

naomarik22:12:41

jaen i've essentially just started hacking on this today and chose luminus with its built in generators

jaen22:12:00

Luminus is pretty nice if you're just starting out

jaen22:12:11

Gives you a simple sample structure and libraries

jaen22:12:17

Not exactly choices I would make

jaen22:12:20

But a nice introduction

naomarik22:12:39

everything kinda works well but i feel that the cljs repl should be on browser and not in its own environment

jaen22:12:33

Also, I wholeheartedly suggest trying Cursive as your development enironment, it's awesome

jaen22:12:42

You can't evaluate Clojure in the browser, period.

jaen22:12:55

Browser understand Javascript only

jaen22:12:07

(unless it's Dartium, then it understands Dart)

jaen22:12:13

You have to have an external REPL

jaen22:12:16

That will compile CLJS

jaen22:12:21

And send it over to browser

naomarik22:12:26

i mean the context of the repl being in the browser

naomarik22:12:37

so editing atoms would update etc

jaen22:12:40

Ah, I must have misunderstood this time

jaen22:12:06

I thought you've meant this, but your last comment made me think I misunderstood you ; d

naomarik22:12:33

i downloaded cursive today and seems like 9000 more select boxes and dropdowns to learn on top of the 90 new terms i've learned in the past few days

naomarik22:12:55

so i'll stick with emacs at the moment seems a bit easier 😛

jaen22:12:24

Hah, before Cursive I used Sublime Text or vim without REPL integration at all

jaen22:12:45

I never could get to grips with emacs

jaen22:12:59

With all those weird chording keybindings and whatnot

cab22:12:14

im just using atom right now 😞

cab22:12:23

with parinfer

jaen22:12:52

And at some point I've tried Cursive and surprisingly loved it

jaen22:12:01

even though I totally hated IDEs before this point

naomarik22:12:03

using spacemacs simple_smile

naomarik22:12:12

i would die with all the chording

jaen22:12:15

thinking they have all those nonsense tabs, options and total bloat

jaen22:12:30

Hah, I've heard good things about spacemacs

jaen22:12:43

But I don't think CIDER has as good debugging as Cursive has?

naomarik22:12:45

i came from vim, so it's very natural

naomarik22:12:07

not sure... at least for clojure it makes emacs feel like a complete IDE

naomarik22:12:18

gives you so much stuff

jaen22:12:42

@cab: well, I'd love to try parinfer, but I have to wait for Cursive to integrate it

naomarik22:12:46

i came from ruby so i'm used to coding without anything helping me

jaen22:12:53

Yeah, Ruby before here as well.

jaen22:12:08

But I can appreciate code navigation

jaen22:12:19

When I had to debug source of gems in Ruby

cfleming22:12:33

@jaen: Parinfer will hopefully be coming very soon

jaen22:12:34

It was annoying to get to the source

jaen22:12:53

If I can't ctrl+click but have to gem show and navigate there.

jaen22:12:18

@cfleming: wheee. I'm trying to learn me some paredit, but it's a bit rough. Parinfer would be awesome.

cab22:12:53

yeah, parinfer is very cool

cfleming22:12:00

@jaen: I’d also like to make something like a typing tutor for paredit.

cfleming22:12:11

With exercises to help learn the commands.

jaen22:12:17

That would be nice

jaen22:12:44

What trips me up the most if I somehow end up with unbalanced params and it doesn't let me delete the ending paren wherever I want

jaen22:12:54

I understand parinfer would just remove it and balance things.

naomarik22:12:32

@cfleming: one point bbatsov made for CIDER was that cause cursive is completely yours, what would happen if you decided to abandon the project?

cfleming22:12:20

@naomarik: I can always OSS it and donate it to either JetBrains or Cognitect.

naomarik22:12:54

and if you got hit by a bus? 😛 (hope this never happens to you)

cab22:12:12

@cfleming will add it to his last will and testament

cfleming22:12:13

I thought that was a bit of a straw man to be honest, if you look at the commit graphs it’s really only bbatsov and amalabarba working on CIDER right now.

jaen22:12:44

@naomarik: as for debugging, I've seen CIDER is starting to get some debugging, but it's still considerably behind IntelliJ+Cursive and for some inexplicable reason my Clojure workflow hinges heavily on debuggability

cfleming22:12:47

Well, I’ve had discussions with both JetBrains and Cognitect, and JetBrains at least have access to the source.

jaen22:12:02

(but that just might be me being a crappy Clojure programmer)

naomarik22:12:16

just that this is time investment, learning these tools. so trying to make a well informed decision

cfleming22:12:21

I should probably add something like that to my will though, right @cab

cab22:12:22

crappy programmers think they dont need to debug simple_smile

naomarik22:12:25

does cursive have CLJS debugging (cider does not)

cfleming22:12:41

@naomarik: Not yet but I have it planned

jaen22:12:42

Nothing has CLJS debugging, really

jaen22:12:51

@cfleming: oh, how woudl that work?

jaen22:12:08

@naomarik: but debugging in Chrome devtools is pretty good

jaen22:12:15

especially if you use cljs-devtools

cfleming22:12:17

Over the debug protocol, same as the JetBrains JS debugger.

cfleming22:12:32

It’s actually probably not that hard (touch wood)

jaen22:12:02

And it would be able to inspect Clojurescript structures in debugger and eval Clojurescript code? D :

naomarik22:12:04

are there any compelling features that cursive has at the moment that CIDER doesn't? or vice versa

naomarik22:12:47

or unknown 😛

jaen22:12:59

I didn't use both so I can't say ; d

naomarik22:12:05

yeah i reckon most people are like that

jaen22:12:51

But I think Cursive has probably an edge in debugging from what I've seen

jaen22:12:57

But on other - I don't really know

naomarik22:12:16

i was using cider's debugging to debug a recursive macro and it was pretty awesome

cfleming22:12:27

@jaen: Yeah, it would.

cfleming22:12:00

They have pros and cons - IntelliJ’s is based on JDI, so it’s heavily line based - CIDER’s is expression based

cfleming22:12:19

But CIDER’s can’t debug into Java code

naomarik22:12:29

@cfleming: any recent/good youtube videos you'd recommend watching to see workflow?

cfleming22:12:34

And you have to manually instrument code for it to work.

jaen22:12:54

> crappy programmers think they dont need to debug @cab: well, yeah, I kind of agree with that, but for some reason people are surprised when I say I lean heavily on debugging in Clojure and say they don't ever have to do that, so maybe I'm the odd one out.

cfleming22:12:27

@jaen: Don’t feel bad, I debug every day

cfleming22:12:37

I’d have a really hard time without it

naomarik22:12:43

in ruby i live in binding.prys 😜

jaen22:12:50

@cfleming: wow, if it'll be able to do that then that's awesome. Not being able to eval Clojurescript on a breakpoint is about the only thing missing in the Clojurescript debugging story.

cfleming22:12:59

@naomarik: Not really sorry, I’m planning to make some videos soon.

cfleming22:12:15

@jaen: Yeah, it would also allow breakpoints conditional on cljs expressions etc

naomarik22:12:56

@cfleming: would love to see them; even if i noticed there's a few killer things cursive does that cider cannot, i'd be very interested

jaen22:12:56

@naomarik: yeah, when I first came to Clojure and learned there's no binding.pry equivalent I was like "how you can guys live without debugging" and then after some time I've come across Cursive

jaen22:12:04

And it had debugging. Love at first sight.

naomarik22:12:21

@jaen yah #break will do that in cider or you can just M-x debug function at point

jaen22:12:44

@cfleming: much wow, such awesome. My eyes are totally sparkling. Though I imagine it'll be a while before that comes.

cfleming22:12:15

@naomarik: Based on conversations, the main feature Cursive has that CIDER doesn’t is stability - it pretty much always works with no fiddling.

cfleming23:12:39

Is anyone able to help with a quick debian sysadmin question?

cab23:12:01

possibly? 😉

cab23:12:08

might as well ask!

borkdude23:12:42

@jaen Yeah, I'm sorry. I corrected the code now

borkdude23:12:04

@jaen it's hard to keep code in sync on Stackoverflow

jaen23:12:21

@borkdude: no problem, I figured that out in the end

borkdude23:12:01

@cfleming: yeah +1 on that. CIDER isn't always that stable and often requires a REPL to analyze stuff. It interferes with your process, where Cursive is independent.

cfleming23:12:02

@cab: I’ve had a new IP assigned to my Debian 7 VPS. I’ve updated /etc/network/interfaces to look like this:

auto lo eth1
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

iface eth1 inet static
    address 149.210.165.105
    netmask 255.255.255.0
    gateway 149.210.165.1

cfleming23:12:22

But when I ifup eth1 it says Cannot find device "eth1"

cfleming23:12:42

Perhaps I need some special interface name for a virtual network interface of some kind?

cab23:12:44

did you ifdown first?

cfleming23:12:54

No, I just added eth1

cab23:12:11

try ifdown eth0 then ifup eth1

cab23:12:16

(sudo, of course)

cfleming23:12:38

That’s the new IP, eth0 is the existing interface allocated via DHCP

cab23:12:41

oh, i read that as “renamed eth0 to eth1”, sorry

cab23:12:09

what does ifconfig -a show?

cfleming23:12:10

No, I need two IPs because Java 6 is a POS

cfleming23:12:25

It only shows info on lo and eth0

cab23:12:57

thats the extent of my sysadmin knowledge 😞 sorry

naomarik23:12:00

does boot have no figwheel repl equivalent? where you can get access to entire app state in a repl?

jaen23:12:47

@naomarik: it has, boot-cljs-repl

jaen23:12:58

Like I said, look at the example projects I linked

jaen23:12:09

They all have that set up IIRC

naomarik23:12:25

ah, i just had it running and it didn't seem to be linked to my browser state

naomarik23:12:33

everything else was working though

naomarik23:12:41

i'll check that example project

jaen23:12:58

boot-cljs-repl works in that you connect to a normal repl

jaen23:12:35

and there you run adzerk.boot-cljs-repl/start-repl

naomarik23:12:36

yup, that was working perfectly

jaen23:12:43

which will connect to the browser

jaen23:12:31

For example I have this wrapped into a simple function - https://gitlab.com/jaen/clj-cljs-presentation/blob/master/build.boot#L88 -

jaen23:12:33

So I can just do

jaen23:12:42

(cljs-repl!) from the REPL

jaen23:12:51

And have Clojurescript repl connect

jaen23:12:12

Just an important thing

jaen23:12:30

Both boot reload and boot cljs repl have to be in the pipeline before boot cljs for it to work.

naomarik23:12:30

i've got cljs repl running at the moment

jaen23:12:30

(comp
    (watch)
    ....
    (bh/serve :dir "target")
    (br/reload)
    (bcr/cljs-repl)
    ....
    (bc/cljs))

jaen23:12:18

And whatever you do there

jaen23:12:23

Should affect the browser

naomarik23:12:28

yeah this part i don't have 😛

jaen23:12:31

For exampel if you open the devtools and do

naomarik23:12:36

trying to find the missing link

jaen23:12:40

(.log js/console "test")

jaen23:12:44

It should display there

naomarik23:12:47

i think it's running node

jaen23:12:04

Hmm, I don't think it runs node, at least by default.

naomarik23:12:38

you're using weasel to connect to browser?

jaen23:12:56

But boot-cljs-repl uses it, yes

jaen23:12:04

But you don't need to fiddle with weasel directly at all

naomarik23:12:59

cider cljs repl was configured for node, just changed it to weasel

naomarik23:12:02

will see if it works

jaen23:12:11

Oh, I see

jaen23:12:44

I don't understand all that emacs stuff though ; d

naomarik23:12:53

it's waiting for ws on port 9001 ;/

jaen23:12:12

Can you connect to the nREPL?

jaen23:12:56

so do so

jaen23:12:04

and then call that start-repl function

jaen23:12:06

I mentioned

jaen23:12:16

This should connect you with the browser repl

jaen23:12:57

If the projects I linked are too complex for you right now this one is probably the simplest I've found - https://github.com/adzerk-oss/boot-cljs-example

jaen23:12:07

It's somewhat outdated

jaen23:12:21

But the basic things didn't change a lot

jaen23:12:53

If you get that working then you can see what those other repos I've sent you do differently.

naomarik23:12:26

<< waiting for client to connect ... java.lang.NullPointerException closest i can get tonight ;(