Fork me on GitHub
#clojure
<
2022-12-01
>
Takis_01:12:44

Can Clojure be used as systems programming language? For make things like Apache projects that most of them are Java and Scala

Takis_01:12:18

i know its dynamic language, but is there a way with type annotations etc to fast enough to compete?

Takis_01:12:33

Scala for example became popular i think from Apache Spark, we could have a Clojure version of apache spark, that could compete in perfomance?

Sam Ritchie01:12:38

You can definitely do this, because you can write spark jobs from clojure

Sam Ritchie01:12:37

I do get what you’re asking! Storm was clojure to start and may still be clojure

Takis_01:12:03

yes it makes me sad, that now became java alot, i read that they re-wrote Clojure code in Java

Takis_01:12:37

and i was wondering if this is for perfomance reasons, or just because more people know Java

Sam Ritchie01:12:28

Whenever I’ve seen these rewrites happen the latter is definitely a big factor, and the folks doing the rewrite always talk about the former. In theory the performance can be the same…

Sam Ritchie01:12:59

But writing in Java definitely makes it easier to consume from scala, clojure etc imo

Sam Ritchie01:12:39

clojure is really fast! It’s not like python where it’s terribly slow unless you call out to C, Fortran etc (that’s my understanding, could be wrong)

Takis_01:12:33

thank you for the information, i hope sometime, we have a Clojure project that uses all the benefits of Clojure to make it more popular. But ok all functional languages for now are not popular.

Sam Ritchie01:12:36

The vast majority of people don’t know anything about any language, most of the pie is still up for grabs!

🤯 2
seancorfield05:12:17

I thought they mostly rewrote Spark/Storm/whatever in Java to allow for a larger community of contributors, since there are so many more Java developers out there than Clojure developers?

3
chrisbetz08:12:32

Dev „availability“ is the misconception of those rewrites. In my experience, performance is no issue (btw: Never was with sparkling, the Clojure/Spark lib). Quite the opposite: I could squeeze more performance out oder the system built on sparkling, because I was faster achieving the goal and then use time to find the performance bottlenecks (which usually were rooted in me not leveraging data characteristics right from the start).

phill09:12:11

In my experience Clojure programs can get the job done faster than Java programs (given that you will put a limited amount of energy into programming) because you, the programmer, "work smarter, not harder"... the program spends no time making "safe copies" of structures... can use zippers instead of xslt... and you spend less time debugging and more time at a higher level.

phill09:12:21

But random anecdotes should be paired with a citation to Rich Hickey's comment that attaining "on-the-metal" speed was a guiding principle.

👍 1
Alex Miller (Clojure team)01:12:08

Clojure and Scala and Java are all compiled bytecode so conceptually they are not significantly different in their performance

❤️ 4
Al Z. Heymer11:12:34

(defn lazy-print-diff []
  (let [list '(1 2 3)
        lazy (map inc list)]
    (prn lazy)
    (printf "%s\n" lazy)))
This code produces (1 2 3) and clojure.lang.LazySeq@7c42 . I think its quite interesting, that the behaviour of format and print differ here. Is this intentional or documented somewhere? I mean, I can think about why that happens, but it seems counter-intuitive. Especially for logging purposes, I tend to prefer format strings over print strings, so this happens to be a bust for me, because I have to wrap that into a printer first.

pavlosmelissinos13:12:02

Is this expected?

(clojure.java.shell/sh "git" "clone" "[email protected]:rtyley/small-test-repo.git" "/tmp/local-repo")
  ;;=> {:exit 0, :out "", :err "Cloning into '/tmp/local-repo'...\n"}

p-himik13:12:49

I don't see anything suspicious about it.

pavlosmelissinos13:12:26

The message is in stderr, shouldn't it be in stdout since there's no actual error?

p-himik13:12:08

stderr is not about errors per se, it's more about diagnostic output.

👍 1
pavlosmelissinos13:12:09

Alright, so this is something git does and clojure.java.shell doesn't change anything on top of it?

p-himik13:12:36

Yeah.

👍 1
emilaasa13:12:50

Looks like everything is working as intended

Rachel Westmacott13:12:09

I'm no expert here, but I suspect that if the secondary output stream was referred to as 'altout' instead of 'stderr' then a great many people would be less confused by its purpose.

emilaasa13:12:14

Yeah, I think this is all that's said about stderr in the POSIX standard: > At program start-up, three streams shall be predefined and need not be opened explicitly: standard input (for reading conventional input), standard output (for writing conventional output), and standard error (for writing diagnostic output).

👍 1
gratitude 1
emilaasa13:12:31

What diagnostic means is an exercise left to the reader

😄 1
pavlosmelissinos13:12:37

Yeah, exactly Thank you all, TIL

Taylor Allred21:12:05

I'm sure this has been asked before but I'm curious: which one of these is preferred?

(apply + lst)
or
(reduce + lst)

Joshua Suskalo21:12:18

reduce is preferred. the implementation of apply just calls reduce

Joshua Suskalo21:12:28

reduce therefore is the same semantically and provides better performance

ghadi21:12:03

this is wrong

Joshua Suskalo21:12:15

oh? I'm curious about that.

ghadi21:12:09

Rich has mentioned that the reduce arity without an 'init' argument is regretful

Joshua Suskalo21:12:49

Yeah, in this case it will provide equivalent behavior because + will never be called with 1 argument in the reduce case, but with 0 elements it will be called with 0 arguments and produce 0, the same as apply, and with 2 or more elements it will correctly sum them.

ghadi21:12:53

(apply + ints) or (reduce + 0 ints) would be my preference, in that order

Joshua Suskalo21:12:14

what's the reason to prefer apply when the high-arity version of + just calls out to reduce?

ghadi21:12:32

not because of performance, but because it's closer to what your intent is

ghadi21:12:35

one op, many args

ghadi21:12:19

(reduce + 0 ints) is describing a particular strategy for adding (sequential)

Taylor Allred21:12:28

apply doesn't appear to call out to reduce but perhaps I'm misunderstanding https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L660

ghadi21:12:59

+ with varargs calls a reduce internally

Joshua Suskalo21:12:01

apply itself does not, but the high-arity version of + which is what apply will call does

ghadi21:12:04

(but doesn't have to!)

Joshua Suskalo21:12:36

also the non-init case of reduce is just fine, the problem is that it's not documented it requires that the values contained in the list and the function must together produce a monoid. It might make more sense for it to exist under its own name, like mfold or something, but it has every reason to exist.

Joshua Suskalo21:12:50

or rather the documentation expresses that constraint, just not in a way that makes it clear that's what it requires.

ghadi21:12:15

no it's not 'just fine'

ghadi21:12:28

> Who knows what the semantics of reduce are when you call it with a collection and no initial value? No one, right. No one knows. It's a ridiculous, complex rule. It's one of the worst things I ever copied from Common List was definitely the semantics of reduce. It's very complex. If there's nothing, it does one thing. If there's one thing, it does a different thing. If there's more than one thing, it does another thing. It's much more straightforward to have it be monoidal and just use f to create the initial value. That's what transduce does, so transduce says, "If you don't supply me any information, f with no arguments better give me an initial value." from https://github.com/matthiasn/talk-transcripts/blob/master/Hickey_Rich/InsideTransducers.md

Joshua Suskalo21:12:06

(I recommend we move this part of the convo to a different thread)

Joshua Suskalo21:12:40

So yeah, back to original question: (apply + lst) matches the semantic the best (reduce + lst) happens to match the semantic because numbers and + form a monoid and it will be more performant (on the current implementation which is technically subject to change but likely not to in the near future) (reduce + 0 lst) matches the semantic, requires no obscure maths knowledge for it to make sense, and will likely be the most performant of the three (with the same caveat)

daveliepmann11:12:46

Thanks for that quote-with-link, Ghadi. TIL.

Joshua Suskalo21:12:17

non-init reduce semantics 🧵

Joshua Suskalo21:12:30

So I agree that the way the documentation for reduce is worded it's confusing, and I've seen what Rich says about it before, and on some level I agree that coming at it from a strict values perspective it is weird, but it is just a monoid. It's requiring that the list has monoidal values in it, and it has join on the 2-arity of the function and zero on the zero-arity, which results in a pure monoid.

Joshua Suskalo21:12:58

It's a sensible semantic, but confusing compared to the general version of reduce and therefore it would perhaps be a better idea to have it be under a different name if it could be changed.

seancorfield21:12:03

This is why next.jdbc only implements IReduceInit for plan: https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc.clj#L225 -- there is no sane default init value for most result set reducing functions.

Joshua Suskalo21:12:36

Yes, precisely because it doesn't construct a monoid with sensible reducing functions, and that's why reduce is a poor name for the monoidal fold operation.

Joshua Suskalo21:12:08

And I applaud that decision to only implement ireduceinit

Alex Miller (Clojure team)22:12:56

I think this cake is baked

1
😆 1
🍰 2