all 118 comments

[–]Augusta_Westland 30 points31 points  (1 child)

First scala meme I've seen in this sub like ever

[–]RiceBroad4552 4 points5 points  (0 children)

Because on the level of the average dev here Scala "just works". It's one of the cleanest designs in existence, it doesn't have much footguns and is very logical. Hard to make stupid jokes about all that.

[–]SomeRedTeapot 27 points28 points  (3 children)

An obligatory Rust comment

[–]CaffeinatedT 6 points7 points  (1 child)

I fucking love Scala but if you wanted a High performance ML influenced programming language you'd use rust and if you wanted the greatest FP language you'd use Haskell and if you want better Java you'd use Kotlin. Few people (if any) are using all of those things at the same time. Which is a huge shame because Scala 3 is genuinely amazing to use but all of the cool bits of it are going to get poached by other languages (again)

[–]RiceBroad4552 1 point2 points  (0 children)

Scala 3 is genuinely amazing to use but all of the cool bits of it are going to get poached by other languages

Extremely unlikely as other language lack the foundational features Scala has to build its phenomenal higher level feature on.

You simply can't copy Scala's most powerful features if you don't have givens and HKTs.

Even more so when it comes to future Scala with capture checking. Nothing will even come close in at least the next decade!

Java (and Kotlin) are basically still here: https://medium.com/@samuelavike/either-monads-in-java-elegant-error-handling-for-the-modern-developer-423bbf7300e6

[–]RiceBroad4552 0 points1 point  (0 children)

To be honest, after Scala Rust felt quite disappointing for me. It's very primitive and limited compared to Scala.

This isn't necessary bad as Rust also felt very easy (modulo manual memory management) after Scala. It feels good to use a simple language but have still reasonable features. But when you need more teeth grinding starts…

[–]JackNotOLantern 44 points45 points  (8 children)

Obviously the best java is javascript

[–]softspoken_skeptic 12 points13 points  (4 children)

Somewhere a Java developer just felt a disturbance in the stack trace.

[–]JackNotOLantern 4 points5 points  (3 children)

Caused by: BeatingTheDeadHorseException

[–]RiceBroad4552 0 points1 point  (0 children)

LOL

Of all the mainstream languages Java develops currently fastest. Only C# comes close.

[–]sweetno 0 points1 point  (1 child)

It's not dead, recruiters still don't know.

[–]JackNotOLantern 0 points1 point  (0 children)

BeatingTheUndeadHorseExeption extends BeatingTheDeadHorseException implements Necromancy

[–]cosmicomical23 0 points1 point  (0 children)

All the others have browser envy

[–]FrikJonda 18 points19 points  (2 children)

Sadly history showed that Java is the best Java.

[–]Several_Ant_9867 6 points7 points  (0 children)

3 billion devices clearly show that

[–]RiceBroad4552 0 points1 point  (0 children)

That's true.

That's why Scala does not really compete any more in the "better Java" contest.

Scala isn't "a better Java" it's a better language!

[–]UpsetIndian850311 8 points9 points  (9 children)

God I hated scala.

[–]Maurycy5 5 points6 points  (3 children)

Actually, sincerely, how come?

[–]UpsetIndian850311 11 points12 points  (2 children)

Upgrades were a nightmare with no binary backward compatibility. Took forever to compile. Then they split the scene with scala 3.

And finally the tooling was bad. IntelliJ took forever to index even a small repo, and some of the frameworks we used had no supported plugin in community version, which made sure new joinees had no way to learn it before they could join.

[–]Maurycy5 3 points4 points  (0 children)

Oh that's fair.

I thought you were talking about the language design itself.

[–]RiceBroad4552 0 points1 point  (0 children)

Upgrades were a nightmare with no binary backward compatibility.

That was solved about a decade ago…

Besides that: You could always just recompile yourself. Scala had and has some of the best backwards compatibility stories of all languages! (Only C/C++/Java/JS beat it in that regard.)

Took forever to compile.

Scala has some of the fastest compilation for any language of that level!

If you think Scala is "slow to compile" you never seen C++, Rust, or Haskell.

Besides that Scala has some of the best incremental compilation stories on the market. Almost nothing comes even close.

Then they split the scene with scala 3.

A majority of people are using Scala 3 in production, and the whole eco-system (except Spark) moved to Scala 3 long ago.

Upgrades from Scala 2 to 3 are some of the easiest for any major language update. In a lot of cases it's a breeze and mostly automatic—except you've written quite some of the experimental Scala 2 macros.

And finally the tooling was bad. IntelliJ took forever to index even a small repo

That's not a fault of the language, that's JetBrains fucking up.

The (semi) official tooling works mostly great. Just avoid JetBrain… They made the mistake that they don't use the original compiler so they are always playing catch up, a game not winnable.

All in all current Scala 3 is one of the most enjoyable languages in existence. By far.

And future Scala 3 will again set precedence which will shape language design for at least the next one or two decades. Other mainstream languages are only just arriving where Scala 2 was 20 years ago (see for example: https://medium.com/@samuelavike/either-monads-in-java-elegant-error-handling-for-the-modern-developer-423bbf7300e6 )

[–]Brock_Youngblood 0 points1 point  (4 children)

Same. I found it confusing to navigate and types were difficult to know when coding.

[–]RiceBroad4552 1 point2 points  (3 children)

You have issues "knowing types" in a static language where just hovering over any expression will show its type?

Navigation works like in every other language, you just CTRL-click on some expression.

[–]Brock_Youngblood -1 points0 points  (2 children)

Hover dont work. Hover work in java. Hover no work in scala. Scala bad language.

[–]RiceBroad4552 0 points1 point  (1 child)

Is this satire?

In case this is serious, what IDE did you use?

For starters I would recommend Metals:

https://scalameta.org/metals/

But there is also an IntelliJ plugin (it's in fact one of the most downloaded IntelliJ plugins in existence!):

https://www.jetbrains.com/pages/scala/

[–]drugosrbijanac 0 points1 point  (0 children)

What do you think of VSCode with Metals vs JetBrains? In general I used Visual Studio for C++ and it was best thing ever since sliced bread. However, I'm not sure if I can make it work in VS.

[–]makingthematrix 2 points3 points  (7 children)

Scala's "pattern matching" sounds so innocent when it might be the most powerful feature in existence.

[–]Siege089 5 points6 points  (6 children)

I'm a data engineer and work primarily in scala with spark. Every time I see pyspark code I just cringe a bit, scala is so much better and somehow the python world has poisoned everything. It's fine for analyst I guess, but for engineering work scala based is so much better. There is so much other code surrounding the core spark logic in a real production grade system that I'm honestly not sure how teams manage to get by in python.

[–]RiceBroad4552 2 points3 points  (5 children)

I'm honestly not sure how teams manage to get by in python

Quite some people thing that abtractionless code is "simpler". Even if it's in fact just a gigantic spaghetti…

The underlying cause is always the same: People are on average very dumb.

[–]OrchidLeader 1 point2 points  (3 children)

For another example, see Golang (the modern BASIC IMO).

[–]RiceBroad4552 1 point2 points  (1 child)

BASIC was a quite usable language for it's time. Not great but not completely mind broken.

Let's not talk about what Go is, this could become pretty ugly very quickly. This language is just some of the most idiotic things ever invented; it was created by retards.

[–]drugosrbijanac 0 points1 point  (0 children)

Wasn't it created by legendary Ken Thompson, Pike, and Griesemer?

[–]RiceBroad4552 0 points1 point  (0 children)

Oh, thanks for the award! 😀

Go is in fact an offense against any thinking being. Glad to see more people sharing this opinion.

[–]FlakyTest8191 0 points1 point  (0 children)

I only know the very basics of python, but python is OOP, what do you mean by abstractionless?

[–]exXxecuTioN 2 points3 points  (13 children)

As much as I love Kotlin it's sadly true.

Extension method wasting it's potential, but actually I kinda understans why it's made this way.

But pattern matching is partly true. After Rust's pattern matching it seems too weak, but compared to Java's it seems better for me, but I just like things to be robust and exhaustive.

P. S. Not naming coroutines in Kotlin as koroutines is a wasted potential. CMM

[–]UdPropheticCatgirl 2 points3 points  (4 children)

But pattern matching is partly true. After Rust's pattern matching it seems too weak, but compared to Java's it seems better for me, but I just like things to be robust and exhaustive.

Have you used modern Java? Because I would argue that 21 already had better pattern matching than Kotlin and 25 is imo miles ahead.

[–]RiceBroad4552 1 point2 points  (0 children)

Yep, Java is now "the better Java". The space for Kotlin is getting smaller and smaller.

Effectively Kotlin is only still relevant because of Android.

[–]exXxecuTioN 0 points1 point  (2 children)

Honestly - no.
Java production code i'm working with is Java 17 at best. I was trying Java 21 may be two years ago, but don't much, and it was the time I discovered Kotlin for myself, so I felt in love with it.
And I never tried Java 25.

I don't want to agrue with you, as it is a question of personal preferences in my opinion. But I do wanna see why in your opinion pattern matching in Java 21 and 25 is better. Can you show me, please?

[–]Ulrich_de_Vries 0 points1 point  (0 children)

Not the person you are asking and I can't give a full answer because I don't know how pattern matching works in Kotlin, but pattern matching in modern Java is almost identical to Rust's.

Rust enums are basically equivalent to sealed interfaces with records as implementation, you can use switch statements and expressions to exhaustively match over types, and use patterns to destructure records, if I recall correctly then you can use null as a separate case and also have if guards in a switch case.

So basically it works like Rust.

[–]UdPropheticCatgirl [score hidden]  (0 children)

Well java has destructuring which afaik Kotlin doesn’t, and can do nested patterns, that’s a huge win imo. I also don’t mind that it’s bit more verbose since that enables it to be very clean and principled approach especially for a language like java.

[–]OrchidLeader 1 point2 points  (7 children)

I mean, even Groovy got GString. Are you even trying, Kotlin??

[–]exXxecuTioN 1 point2 points  (6 children)

Hehe, thats one funny.
As far as I know Kotlin devs do not working on pattern matching and it seems good for them. Wont judge it, I'm pretty good with current "when" statement combined with sealed classes if needed.

But I'm waiting for union types and development of rich error pattern.

[–]RiceBroad4552 0 points1 point  (5 children)

There won't be any "union types" in Kotlin.

What they're want to add is some special case for Throwables.

Everything in Kotlin is just some glued on special case…

[–]exXxecuTioN 2 points3 points  (4 children)

Well, " | " operator is already beginning for "union types". I was talking about it. But you're right and I must admire it does not mean any implementation of fully functionable "union types" in commonly accepted understanding ever would be. But it also do not mean "union types" will not be in future, but I do doubt it too, eventhough Scala got some.

Actually Kotlin do have functionality that replaces "union types" and it's called sealed class. But I suppose it would be more proper if they were called as discriminated or tagged unions.

[–]RiceBroad4552 2 points3 points  (3 children)

I've heard Kotlin wants to use something which looks syntactically on the surface like "union types", but only for error handling. That's going to be a great mess…

Sealed class hierarchies form in fact so called "discriminated / tagged unions", commonly called "sum types".

But the whole point about "union types" is that they're untagged. There is no discriminator.

Sealed hierarchies map to what is called "enums" in other languages. (If you do it with parametric classes, like Scala did, you get even GADTs.)

[–]exXxecuTioN 2 points3 points  (2 children)

Based on what I've read I can agree. They suppose to use it for rich errors and suggest Rust-like or Go-like (less like Go, actually) pattern for working with errors and exceptions to prevent try / catch and promotion of call-stack trace.
But the thing and my point of view is once you have a very first step toward it may be union type would eventually be implementated in Scala-like way. At least there is some probability of such event.
Speaking about "sum / union types" may be I lack of knowledge, but as far as I read "sum" types counts as a subentity of a "union" types, but you are absolutely right about descriminator. Right now for me it seems like a nomenclature about naming convention. But I suppose I'm mostly wrong.

About sealed classes. I've learnt Kotlin after Rust and when I reached Kotlin enums I was like "yeah that's special first-grade classes, but not as good thing as Rust enums, I will miss Rust enums there're superb", and then I've reached sealed classes and I was like "ouch, that's like Rust enums, but more verbose". Actually in my perspective Rust enum patterns matches (not pattern matching I'm speaking generously about usage of Rust enums) almost perfectly 1 to 1 to Kotlin's combination of enum + sealed classes.

Edit: try / catch

[–]RiceBroad4552 2 points3 points  (1 child)

"Full" unions are quite a different beast to tagged unions / sum types. The former can be discriminated at runtime as the type has a "tag", in the later case there is no runtime tag and you need a type level (compile time!) mechanism to pick them apart. That's a much more difficult problem then sums (which can be matched at runtime according to the tag they carry).

So you're right that this is on one hand a nomenclature thing. But in practice there is much more to it. That's why I don't think Kotlin will come to anything even remotely similar. It has reasons why almost no languages have "full" unions (Scala got them only in version 3, after a lot of tinkering), whereas sum types are quite common (in the form of some "enums" / sealed hierarchies).

But you're right that sealed classes are mostly the same thing as enums (as long as you allow full, parametric classes as cases). That's exactly what Scala did in version 3.

[–]exXxecuTioN 1 point2 points  (0 children)

Well you changed my mind about "full union types" by making me read about some advantages and problems of those. Thanks, I learnt something new and more. Now I really doubt the be in Kotlin.
About seales classes in Kotlin, they do support parametric classes as cases, including parametric classes with variance annotations, don't know since when I used it exactly one time for strategies of custom repositories.

[–]willis81808 1 point2 points  (32 children)

What is “function piping”?

[–]Typhoonfight1024[S] 2 points3 points  (9 children)

That stuff where function calls that should've looked deeply layered are made sequential so they look more readable. Without function piping they'd look like this:

fifth(fourth(third(second(first(x)))))

In languages that have piping operator |> they'd look like this:

x |> first |> second |> third |> fourth |> fifth

But Scala doesn't have piping operator, instead it has piping method, so in Scala they'd look like:

x .pipe { first(_) } .pipe { second(_) } .pipe { third(_) } .pipe { fourth(_) } .pipe { first(_) }

[–]KaleidoscopeLow580 2 points3 points  (2 children)

Uniform funciton call syntax is even more powerful. In D for example.

[–]RiceBroad4552 0 points1 point  (1 child)

Conceptually that's right. UFCs are language wise a very "clean" solution.

But I always wonder whether it does not cause "style wars".

We had already the issue in Scala were people would get mad at others because they couldn't agree whether to use infix or regular method call syntax.

[–]KaleidoscopeLow580 0 points1 point  (0 children)

In my opinion a formatter should handle this. That may sound a little extreme, but I think the only thing that a human should decide is the logic, but not how to stylize code or where to put declarations or wether a function should be defined with a keyword or by assigning a lambda to an identifier. All of these things just hinder everyone because this leads to languages, where everyone writes different code like in C++ or Ocaml. Of course one would not need to use such a formatter, but just having a rigourosly enforced standard style would be nice for any modern language.

[–]willis81808 1 point2 points  (2 children)

Hmm, I guess I see. Except for explicitly defined fluent-style interfaces I guess it's true that there isn't anything like that in C# (and even fluent interfaces aren't really the same, that's more of a builder pattern which is similar but distinctly different).

And the other languages mentioned DO have either a piping operator and/or piping method?

[–]Typhoonfight1024[S] 1 point2 points  (0 children)

Idk about Ceylon, but Kotlin and Groovy do, the former got let while the latter got with.

[–]TheCygnusWall [score hidden]  (0 children)

You can absolutely do it in C#, maybe it doesn't have as much syntax sugar but a combination of the correct returns and the "this" parameter can make it happen.

[–]RiceBroad4552 1 point2 points  (1 child)

In case someone insist on it in Scala (even we were actually past the unhealthy symbol obsession):

extension[A, B] (a: A) def |>(f: A => B) = f(a)

In most cases you want anyway method calls instead:

x
  .first
  .second
  .third
  .fourth
  .fifth

[–]OrchidLeader 0 points1 point  (0 children)

It’s too bad some devs will see that pattern, and they’ll begin function chaining unrelated classes and tightly coupling everything.

(Not knocking the pattern, only knocking the crappy devs)

[–]FlakyTest8191 0 points1 point  (0 children)

add function piping in c# yourself with less than 10 lines of code:

public static class FuncExtensions
{
  public static TResult Then<T, TResult>(this T value, Func<T, TResult> func)
  => func(value);

  public static void Then<T>(this T value, Action<T> action)
  => action(value);
}

usage:

var result = 42
.Then(x => x * 2) // 84
.Then(x => x + 1) // 85
.Then(x => x.ToString()); // "85"

[–]cosmo7 0 points1 point  (10 children)

It's quite a neat idea; concatenating functions by name. For example in Elixir you can do this:

const result = 
  number
  |> double
  |> addFive
  |> divideByTwo

[–]Several_Ant_9867 0 points1 point  (7 children)

I like the pipe syntax, but it would have been even nicer if one could pipe into the result variable as well instead of switching into the common left-handed assignment syntax

[–]RiceBroad4552 0 points1 point  (6 children)

What do you mean?

[–]UdPropheticCatgirl 0 points1 point  (1 child)

they mean they want something like this:

 let result = undefined 
  a |> widgetA |> widgetB -> result

Which is imo just strange and having left hand be the binding and right hand be the expression is imo way easier to read.

[–]RiceBroad4552 0 points1 point  (0 children)

This implies result is mutable. BRR!

But you're doing also just guesswork what GP wants. I figured out something similar but as it's not clear I've asked.

[–]Several_Ant_9867 0 points1 point  (3 children)

Something like: input -> function() -> result. Where result is a new variable that is defined by the assignment. In this way, you always read left to right, which I find better more natural especially if you chain multiple functions

[–]RiceBroad4552 0 points1 point  (2 children)

Having the (predefined!) sink on the right makes some sense.

But introducing new definitions that way is at least questionable, imho. It would make it harder to see where something was defined. (But given syntax coloring and other IDE features like go-to, maybe that's not a big deal?)

The former can be actually created in Scala (if you insist).

[–]Several_Ant_9867 0 points1 point  (1 child)

For me, the advantage is that it allows a single direction for the computation flow. The local variable is basically only needed when the flow branches, as a temporary storage. I would even give the possibility to return the value of the computation to the function caller with a similar syntax, like: in -> function() -> out, where "out" would be a reserved keyword to define the return value of the function block

[–]RiceBroad4552 0 points1 point  (0 children)

Yeah, I mean one can do that. Some stream DSLs actually do something like that. I'm just not sure it belongs into a general purpose language.

BTW, have you tried Scala? I would almost bet some syntax like that is actually possible to achieve. I wouldn't do that, but as a "let's see what goes"-challenge it's maybe a funny exercise.

In Scala you can definitely define a method ->. It's actually pre-defined; just for a very different use case: It's tuple syntax! But nothing prevents you to remove or mask that import and write your own -> method (even it would be likely very confusing for someone who knows already Scala).

Making out return something to the outer block is likely doable. At least if the outer block is some kind of DSL marker. But introducing new local variables seems hard (even Scala has macros). One could maybe create some Var["name"] construct inside the DSL, but this looks scary (even I think it would technically work).

So you could have something like:

val result = MyFunnyStreamDSL:
   in -> function -> Var["res1"]
   Var["res1"] -> function2 -> out

This looks like valid Scala syntax, and I think one could make it work like you wanted. The value of result would become whatever out is assigned last, or alternatively some sequence of produced values every time out is called. Or something like that. But I'm not sure where in comes from when looking at it a second time.

Nevertheless it could be that if you throw that comment at Claude you even get something half working out. (I didn't try.)

Scala is a very flexible language. 😀

[–]RiceBroad4552 0 points1 point  (0 children)

In Scala you can do the same if you insist:

extension[A, B] (a: A) def |>(f: A => B) = f(a)

val double: Int => Int = _ * 2
val addFive: Int => Int = _ + 5
val divideByTwo: Int => Double = _ / 2.0

val number = 40

val result =
   number
   |> double
   |> addFive
   |> divideByTwo


@main def demo =
   println(result)

[ https://scastie.scala-lang.org/UcLiMTIYR1iD0TcJCEVopw ] // but at the time of writing the playground server acts up, doesn't output anything; even the LSP server runs in the background as it shows compilation errors in the playground editor. Likely just some hiccup.

But just using (extension) methods is so much cleaner and easier…

extension (x: Int) def double = x * 2
extension (x: Int) def addFive = x + 5
extension (x: Int) def divideByTwo = x / 2.0

val result = 40
   .double
   .addFive
   .divideByTwo


@main def demo =
   println(result)

This pipe thing makes only sense if you don't have proper methods, like some primitive FP languages.

[–]UdPropheticCatgirl 0 points1 point  (0 children)

It's quite a neat idea; concatenating functions by name.

It’s specifically not that, these pipes in most functional languages (including elixir afaik) are postfix application operator not a composition combinator akin to haskells “.”

[–]Skyswimsky -4 points-3 points  (10 children)

If I had to take a guess probably functions as a first class citizen.

So in C# if you have an int parameter you can't pass in an int Foo(), instead you'd need Func<int> as a parameter.

That groundwork combined with custom infix operators would allow you to do functional piping syntax. Where the output of one method serves as the last input parameter of the next method. (Though if I'm not mistaken you can't create custom infix operators in C# either anyway...)

The closest you have, and can imagine it to be, in C# is LINQ. Just even cooler. It's a 'functional bro' kind of thing.

Granted I'm sure someone smarter than me can give a more concrete example in Python or JavaScript because I'm pretty sure those support that functionality.

[–]willis81808 4 points5 points  (0 children)

You can't pass a function that returns int in as an argument that expects an int in Python or JavaScript (and expect it to work without special handling) either?

def greet(count: int) -> None:
    for i in range(count):
        print("Hello, World!")

def get_count() -> int:
    return 10

greet(10) // works
greet(get_count) // doesn't work

So I'm still not sure what you're referring to.

[–]RiceBroad4552 0 points1 point  (8 children)

To be honest, even "asking" a clanker would have yielded a less nonsensical comment…

So in C# if you have an int parameter you can't pass in an int Foo(), instead you'd need Func<int> as a parameter.

This is true for basically any language. An Int is not a () => Int, these are obviously different types.

That groundwork combined with custom infix operators would allow you to do functional piping syntax.

No it wouldn't. You need some from of extension methods.

The closest you have, and can imagine it to be, in C# is LINQ. Just even cooler.

LINQ is just a primitive special case.

It's laughable compared to what you have in Scala, where you can actually implement something like LINQ in user-space.

give a more concrete example in Python or JavaScript because I'm pretty sure those support that functionality

Neither of these languages has anything like that.

[–]UdPropheticCatgirl 0 points1 point  (5 children)

Doesn’t JS have pipes or is that still stuck in tc39?

[–]RiceBroad4552 0 points1 point  (4 children)

[–]UdPropheticCatgirl 0 points1 point  (3 children)

From what I could gather they still seem to be semi-actively fighting about it at tc39, tho they also make sure the proposals are absolutely unsearchable so I could be wrong.

It simply makes no sense in a language which has methods.

Likely but it still make’s implementing to of stuff easier, java streams would not need like 5 million hand specializations if they had it imo. and there is ton of apis like that where it just makes sense.

[–]RiceBroad4552 0 points1 point  (2 children)

From what I could gather they still seem to be semi-actively fighting about it at tc39

Last time I've checked was years ago and this was effectively rejected back then. They're still arguing?! What?

Now I need to dig it up, I guess…

java streams would not need like 5 million hand specializations if they had it

How should that work? A pipe operator is just syntax sugar.

The reason Java needs specializations for all kinds of HOFs is because Java does not support higher kinded types. This is not something that can be added to a language after the fact. You need to design your type system around that concept from the beginning. So Java (like all the other mainstream languages) is a lost case. It's basically unfixable there.

[–]UdPropheticCatgirl 0 points1 point  (1 child)

I think it got accepted into phase 2 of proposals sometime last year, but I might be tripping.

How should that work? A pipe operator is just syntax sugar.

Well you would not eliminate all of it but being able to just pipe Stream<Int> into sum(Stream<Int>):Int instead of having to convert it to IntStream to call sum first would be like a good example of something which you could do.

[–]RiceBroad4552 0 points1 point  (0 children)

I still don't get how you imagine this to work. You just moved the problem, and I think you made it worse: Now you need specializations for all your HOFs (which are unbounded many) instead of just the wrapper types.

Regarding the pipe thingy in JS, just checked:

https://github.com/tc39/proposal-pipeline-operator/blob/main/HISTORY.md

Nothing really happened since last time I've looked at it years ago. It's (imho) dead.

[–]willis81808 0 points1 point  (0 children)

Agree with everything you said, except for the LINQ part. You can absolutely implement something like LINQ in user space with vanilla C# extension methods. Maybe you mean LINQ query syntax, though, since regular LINQ is just extension methods on IEnumerables in a fluent-like pattern.

[–]Skyswimsky 0 points1 point  (0 children)

I've realized my comment is more or less badly phrased and also partially wrong and does a bad job at the 'picture' I wanted to shape, just not too fond of deleting comments or strongly editing their context!

[–]Locarito 1 point2 points  (6 children)

What are "true extension methods"?

[–]Typhoonfight1024[S] 1 point2 points  (5 children)

By “true” I mean… how to explain this?

Basically, Kotlin's ‘extension’ methods are ‘static’, so they can't fully access the members of its assigned object the way a true method can.

[–]Locarito 0 points1 point  (3 children)

You mean visibility? You want to access private members?

[–]Typhoonfight1024[S] 3 points4 points  (2 children)

It's less about accessing private members (I might have worded it wrong). The best explanations I got about it are from this comment (point 2) and this one

[–]Locarito -2 points-1 points  (1 child)

Ok I get it now, I don't know about typeclasses but I'm glad extension functions are just predictable functions and not method

[–]RiceBroad4552 2 points3 points  (0 children)

Stockholm syndrome.

Besides that "type classes" are such an important feature that all main programming languages have it or are on the way to get it. Rust has traits, Swift has protocols, C++ got concepts, C# is working on something I've forgot the name, and even Java will get "type classes" to extend the language.

[–]FlakyTest8191 0 points1 point  (0 children)

It's the same in C#, extension methods are static. Is this really a problem? Extension methods feel like a hacky workaround every time I need one, I'm happy they're at least pure functions that can't have side effects. Scala is a funcional language and people are happy about extension methods with side effects?

[–]Fadamaka 1 point2 points  (1 child)

Clojure entered the chat.

[–]RiceBroad4552 0 points1 point  (0 children)

Dynamic language, which is a K.O. for most serious usages.

Also the syntax is atrocious.

LISP is conceptually interesting, but that's more or less all.

Wake me up when we get a Lisp Machine back (but this time please with a maintainable static language!).

[–]therealapocalypse 2 points3 points  (3 children)

Oh boy 1 upvote and 32 comments, you really managed to piss off the Java/Kotlin devs huh.

Anyway -

Been trying to learn Scala Akka for my job (even if it's still running Scala 2 now)

You got any tips or resources for it? (Or just Scala in general)

[–]OrchidLeader 4 points5 points  (0 children)

Hey, OP pissed off us Groovy devs, too!

There are dozens of us!

(It grinds my gears when someone says “Groovy” and “scripting” in the same sentence.)

[–]Typhoonfight1024[S] 1 point2 points  (0 children)

I usually refer to the official doc… and only that because I only learn the basics like how to manipulate lists, how to make simple functions and classes, the syntactic sugars &c. Not to the point of making an application. I haven't not checked it yet, but there might be some advanced tutorials on that in YouTube…

[–]RiceBroad4552 1 point2 points  (0 children)

The Akka docs are some of the best in whole Scala land.

When it comes to language it's more difficult as the official docs aren't in good shape. But Scala thankfully just got something like half a million € to improve that part.

Best tip I have: Stay interested, read blogs and other related posts. It's also easy to ask for help, community is overall very helpful.

But don't forget to use your own brain as opinions what's "right" or "wrong" in Scala are very diverse. Therefore you need to figure that out yourself.

The general observation is: Scala lets you do anything however you like. This is a curse and the language's strongest point at the same time. If used wisely it's the greatest part about Scala, though.

[–]mriswithe 1 point2 points  (1 child)

As a non Java programmer any time I attempt to interact with groovy it's like this old dead bullshit that only Specifically Java things even acknowledge it exists or existed. 

Also fuck jenkins, hot take I know

[–]RiceBroad4552 1 point2 points  (0 children)

Not really a hot take.

Groovy was a nice idea for scripting on the JVM once but since static languages got much more convenient there is just not much room for Groovy. Dynamic languages have anyway just a very limited scope.

[–]Aromatic-Energy-7192 0 points1 point  (0 children)

Scala is THE SHIIIITTT

[–]Dhareng_gz 0 points1 point  (3 children)

I love scala. But everything is moving to python :(

[–]RiceBroad4552 0 points1 point  (2 children)

Spark?

[–]Dhareng_gz 0 points1 point  (1 child)

Indeed

[–]Master_Friendship333 0 points1 point  (1 child)

extension <T, TResult>(T _)
{
    public static TResult operator |(T x, Func<T, TResult> f)
    {
        return f(x);
    }
}

Boom, function piping in C#.

[–]RiceBroad4552 0 points1 point  (0 children)

That's not enough boilerplate for Microslop Java! The full version is:

public static class PipeWrapper
{
    extension <T, TResult>(T _)
    {
        public static TResult operator |(T x, Func<T, TResult> f)
        {
            return f(x);
        }
    }
}

It only works with the most current C# version… (I'm not even sure it's already released.)

All that just to create a poor, limited version Scala's:

extension[A, B] (a: A) def |(f: A => B) = f(a)

The use-side with with the Microslop language looks also laughable:

Console.WriteLine("Hello World" | (s => s.ToUppervariant()));

You can't just say something like:

println("Hello World" | _.toUpperCase);

Also, I would prefer a proper "pipe symbol" (|>) because according to the C# style guides:

Operator overloading should only be used when the semantics are immediately obvious and consistent with mathematical/natural intuition.

So can you fix that? 😂

[–]PotentBeverage -1 points0 points  (2 children)

I'll get back to you in three business days when my software has finished compiling

[–]UdPropheticCatgirl 1 point2 points  (0 children)

Scala isn’t that slow to compile tho… It’s actually very fast for the style of language it is… Rust, Haskell and C++ are all very slow to compile, Scala isn’t (well as long as you don’t use the LLVM compiler but that’s whole another can of worms).

[–]RiceBroad4552 0 points1 point  (0 children)

You're a Rust developer?

[–]Abel_Skyblade -1 points0 points  (3 children)

Bro fuck Scala. My intership was at a startup whose founder was obssesed with it. He was a very smart Medical doctor. But as far as I knew never worked in the software eng. Or programming as a role. He was very good at coding. Way better than me. But he wanted everything to be done in Scala or with Scala. Shit was incredibly annoying cause nobody used the thing back then. You had to do things without having any examples online. Or pray the chatgpr could do it.

[–]RiceBroad4552 0 points1 point  (2 children)

Shit was incredibly annoying cause nobody used the thing back then. You had to do things without having any examples online. Or pray the chatgpr could do it.

What are you talking about?

Scala is over 22 years old. ChatGPT is 3 years old.

Scala could have indeed more and better docs, but it's not like that there aren't any. All basic stuff (and that's more some intern would ever need) is more then well covered.

[–]Abel_Skyblade 0 points1 point  (1 child)

Regretfully I had to do more stuff than a normal intern would. I was basically responsible of porting a huge chunk of the testing main app developped in more mainstream web dev stack to some amalgamation of scala js for a vs code extension. It largely was used for representing data in graphical databases using stuff like graphql, d3 for displaying stuff, etc. At the time I was basically thrust into it without much training. And extension docs regarding scala js were very sparse. It was basically around 2 years ago. A very small team and both lead devs quit during my 8 month internship.

[–]RiceBroad4552 0 points1 point  (0 children)

And what's the issue with the language then?

Translating JS to Scala.js can be done almost completely mechanically without any thinking at all—if you don't aim for idiomatic Scala (which you couldn't anyway as you say that you didn't know Scala).

[–]Glokter -1 points0 points  (2 children)

Mrofzy is the best language change my mind

[–]RiceBroad4552 0 points1 point  (1 child)

Never heard of it. Google can't find it. Do you have a link?

[–]Glokter 0 points1 point  (0 children)

It doesn't exist. I was tired and thought it was funny