Oddbean new post about | logout

Notes by Alex Nedelcu | export

 This is my personal server, Ubuntu LTS — which is the reason for why I think servers should not be bleeding edge

https://social-cdn.alexn.org/media_attachments/files/112/194/663/381/277/642/original/29b5cf5cee9aaf6f.png 
 At gym, I received my first unsolicited advice. A bro told me that I should start w/ a higher bar in rack, my eyesight is too low, and I should use leg machines until I lost weight 🙄

My squats are low-bar, looking at ceiling is a mistake, and squats don't work just legs 🤷‍♂️ 
 I'm trying to like #IntelliJIDEA with BSP for #Scala projects, but it's tough because you end up with 10 minutes project refreshes that often end in failure, every time you switch branches or modify `build.sbt`. 
 #FunctionalProgramming will make you build better software, regardless of language. Some understated effects:
‣ Prefer params to global state
‣ Prefer data pipelines to fragile state mutation
‣ Prefer clear responsibilities for components
‣ Make dangerous side effects visible. 
 When presenting people with more difficult problems, in programming, sometimes there's a knee-jerk reaction like …  “This is relevant for library authors, not users”.

Software developers are not users. Users shouldn't be just users (and many aren't, judging by the success of programming tools like Excel), but at least users don't get paid to build software.

Learning is hard, and a bad attitude doesn't help. Learn, grow, or not, your choice, but ChatGPT is getting pretty good.

#programming 
 There are other knee-jerk reactions, too. Another one is:

“This is too academic, not relevant for the real world.” 
“This tool is built by academics interested more in publishing papers, than solving problems.”

This kind of anti-intellectual reaction can hide some actually good criticism, it's a pity that people resort to what's basically populism. These are basically negative feelings being blurted out without reflection, robbing us of learning opportunities.

#programming 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m try with cancelable instead... 
 @210f29ed Damn, looking at `cancelable`, it's precisely the pattern I implemented in the sample 🙂 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m :fry: This… is in bad taste. 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m 

How many angels can dance... 
 Here's a concurrency problem that's implemented with #Scala's Cats-Effect and with #Kotlin's Coroutines for comparison — model a JDBC query that can be interrupted.

Which of them do you find more readable or more free of gotchas?

https://gist.github.com/alexandru/60e977fcf75ed88c4d0b824b312dba44 
 Out of the Alt-JS languages I've played with, #Scala.js seems to be the best.

Given it's probably not widely adopted, its maturity is surprising. E.g., ScalablyTyped can convert TypeScript definitions, and actually works. Interop is good. And the compiler is, dare I say it, pretty fast compared to 2–3 years ago. Scala 3 also helps. E.g., it has untagged unions, just like TypeScript.

I'm surprised that it's in better shape than #KotlinJS, for all its multi-platform marketing. 
 And the experience feels good, at least for toys. Seriously, download this sample and fire it up: https://github.com/sjrd/scalajs-sbt-vite-laminar-chartjs-example

#Scala #Scalajs #Scala3 
 Since the pandemic, with the war and the inflation, I've basically lost acquaintances to the online rage pit. People got locked into all sorts of conspiracies about vaccines, 5G, wokeness, transgenderism, capitalism, NATO imperialism, or even Jewish complots.

I'm tolerant when I see scared people, despite bigotry or assholery. But I can only tolerate so much, and I had to watch people that I admire succumb to fear and hatred.

Go outside and touch grass, before it's too late. 
 IMO, people complain about #OOP just because it's the established and well-known paradigm, and not an underdog. That, plus side effects, but side effects are better with OOP, than without.

All non-OOP languages eventually grow a GObject, or a MOOSE. Checkmate atheists! 
 I did some experiments in Scala 3, to learn more about its new features, including metaprogramming / macros.

IntelliJ IDEA is unfortunately unusable for me 😞 which may prevent our team from migrating to Scala 3 until it gets fixed. The good news for me is that the compiler is behaving well, with friendlier error messages, Scalafmt works fine, the needed libraries seem to be all available, and VS Code + Metals behaved better than expected 😍

#Scala #Scala3 
 Is it correct to refer to a laptop as a “desktop”? 🤔 
 @db915dd6 ClassTag can give you a Class, which the JVM needs, so yes, that's related to RTTI, but the ClassTag itself is generated by the compiler. I mentioned ClassTag because it's the easiest to use, and you basically get the equivalent of C#'s reification.

That library, izumi-reflect, doesn't have anything to do with a RTTI. All type info is exposed in macros, but AFAIK it's no longer easily accessible as a TypeTag, so you have to write a macro to get it 🤷‍♂️ 
 @db915dd6 BTW, one pretty good development is that you can derive type class instances pretty easily, and you only need "inline" functions with no macros, just compile-time reflection via implicits, which can deconstruct sum and product types. 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m But it looks like you still... 
 @db915dd6 ClassTag can give you a Class, which the JVM needs, so yes, that's related to RTTI, but the ClassTag itself is generated by the compiler. I mentioned ClassTag because it's the easiest to use, and you basically get the equivalent of C#'s reification.

That library, izumi-reflect, doesn't have anything to do with a RTTI. All type info is exposed in macros, but AFAIK it's no longer easily accessible as a TypeTag, so you have to write a macro to get it 🤷‍♂️ 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m So is A: Type mean that met... 
 @db915dd6 Ah, in this case it's all compile time, Type being an intrinsic.

You do have quite powerful compile-time reflection. For one there is ClassTag – this is weaker, but it allows you to create reified Arrays.

https://scala-lang.org/api/3.3.1/scala/reflect/ClassTag.html

Scala 2.x had TypeTag, with everything, but it was exposing compiler info so it was removed. You can use ClassTag for more depth, like what I did here, e.g.:

https://github.com/monix/newtypes/blob/main/core/shared/src/main/scala/monix/newtypes/TypeInfo.scala

Or smth like this is probably more complete: https://github.com/zio/izumi-reflect 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Do Scala macros have access... 
 @db915dd6 You can have access to type information, yes. That requires to have a `A: Type` implicit in the macro's definition to workaround erasure.

In that sample, I can define Caller[A], but it may not help for my use-case because my function call will be without types, so it will infer it as `Any`, anyway.

I tried working around that with `transparent`, but for now, I don't really know what I'm doing. Trying to find more resources. 
 I might have managed to build my first Scala 3 macro that returns a raw AST ☺️

It captures `this` from the current scope as an implicit:

https://gist.github.com/alexandru/786520e5a89089234c5fc39fe1d16550

#Scala #Scala3 #Programming 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Have you used it for someth... 
 @d3363229 I'm trying to use `sourcecode.Name` for an API. In a statement like:

val link = parameter()

I want the `parameter` to automatically receive the name on the left-hand side, i.e., “link”. 
 This small #Scala library is so cool:

https://github.com/com-lihaoyi/sourcecode/ 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Common since ain't that com... 
 @4ec27e3f In that documentation, the effect is clear if you look at the "Usage" tabs.

And I like that it supports complicated use-cases, like the mega CLI in Mastodon, which looks like this:

    tootctl accounts migrate --replay
   
So it's multi-level, and some options can indeed be shared. 
 What I really like about #Kotlin is that the popular libraries tend to be based on common-sense. You look at a sample, and you understand it.

Here's a sample that I discovered and understood in seconds, showing me how to define reusable CLI sub-commands in multiple subprojects: https://ajalt.github.io/clikt/commands/

Scala's libs in this space (case-app, decline, mainargs, scopt,...) are based on compiler magic or weird data structures, have poor docs, and I can't tell if they get the job done 🤷‍♂️ 
 Basically, I tend to agree with Li Haoyi, except that I don't like his MainArgs library, and I don't like what's available in Python either, having had a bad experience with `argparse`. Great article though, and he does have the common sense we need:

https://www.lihaoyi.com/post/comlihaoyiScalaExecutablePseudocodethatsEasyBoringandFast.html 
 #Java has its IO implementations. Multiple, actually. They don't have the same properties or ergonomics as #Scala's IO (e.g., flatMaps are not optimized for tail-recursion). People may not like it, but they are deployed at scale.

Here's what #Spring WebFlux uses:
https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html

Here's the venerable #ReactiveX (#RxJava): https://reactivex.io/documentation/single.html 
 I was excited that C# now supports "abstract static methods". The feature is basically "type classes" with limitations. 

It seems F# implemented the feature, but its designers don't like it:
https://github.com/fsharp/fslang-design/blob/main/FSharp-7.0/FS-1124-interfaces-with-static-abstract-members.md#drawbacks
#fsharp #csharp #programming #pic

https://social-cdn.alexn.org/media_attachments/files/111/173/110/995/270/940/original/f61416e2de336b62.jpg 
 #Programming languages I've used for building software, either delivering value at my $job, or building utilities for myself:

Awk, Bash, C/C++, C#, Clojure, ColdFusion, Elisp, F#, Flow, Haskell, Java, JavaScript, Kotlin, Pascal, Perl, PHP, Python, Ruby, Scala, TypeScript.

I'm trying to add Rust and OCaml to that list, working my way to “two dozen”. I think I could have stuck to just one or two, though. Just my luck. 
 Stories on #Chrome's Privacy Sandbox are pretty disingenuous.

Chrome does local classification, in certain categories, then shares those categories to third parties. They don't share your data. It's still violating privacy, making fingerprinting easier, but I smell a double standard.

I heard nobody complain about Microsoft Edge asking for permission to actually share data w/ the entire advertising industry, using dark patterns for consent:

https://social.alexn.org/@alexelcu/109839532798225547 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Which problems do you see w... 
 @0157049a I think support for Scala 3 is OK. Still a work in progress, but I loaded some projects (with BSP) and seems OK. It's also available with IntelliJ IDEA Community.

My problem is that of a polyglot, needing support for multiple languages in my personal time. 
 I prefer to run PWAs (progressive web apps) in the browser, instead of their Electron-based equivalents.

‣ Browser apps are sandboxed, Electron apps are not;
‣ Memory use is more efficient in my tests;
‣ You can use ad/blockers or extensions like LanguageTool.

Support for PWAs is an area where #Firefox has dropped the ball, on both desktop and Android. 

See this feature detector: https://howfuguismybrowser.dev/

https://social-cdn.alexn.org/media_attachments/files/111/164/934/330/049/554/original/47d2e2c071a296e6.png 
 “Use the best tool for the job” is bullshit advice, being a lazy form of persuasion, used to justify crappy tools.

I would rather not have to learn new tools for every job, I want multipurpose tools that are useful for many jobs, that I only master once and use indefinitely, that can adapt to changing requirements, that are not a fad destined to become obsolete within the next news cycle.

“When all you have is a hammer…” hell yeah, give me a good hammer!

🔥🔥🔥
#programming 
 #Scala's #Metals, the LSP-based IDE, is great, actually.

My $work happens in IntelliJ IDEA, but unfortunately, it's not good for enthusiasts. I can't use my $work license on my personal computer, and many language plugins are only available for the Ultimate edition.

All my play time gradually moved to #VSCode (e.g., Rust, C++, Python, Ruby, Haskell, OCaml, and now Scala). I'm truly thankful that Metals exists. And it works fine, better in some cases ❤️

https://scalameta.org/metals/

https://social-cdn.alexn.org/media_attachments/files/111/161/356/917/539/997/original/7994a88c042a6043.png 
 I quite like #Scala 3, and can't wait to migrate our project at $work 🤷‍♂️ 
 This is a pretty cool use of "AI" — Spotify will automatically translate the audio of podcasts using the author's own voice:

https://www.youtube.com/watch?v=8RJeyDveRSc 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Hmm you're right. I misreme... 
 @bcc9c456 invokeDynamic was awesome for JRuby, and it yielded some optimisations for Clojure, too.

Scala is making use of invokeDynamic since version 2.12, when it dropped support for Java 6/7. And I think they did it to reduce the generate JAR size, but I'm not sure. 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m I'm enjoying Kotlin, but I ... 
 @bcc9c456 invokeDynamic doesn't yield much benefit for static languages, but I agree with you, as improvements in the JVM lifts all boats. And I also appreciate Java's backward-compatibility. 
 @fd32800e I don't think we'll ever see Scala's implicit parameters or metaprogramming facilities. Or Kotlin's context receivers, or compiler plugins.

This is because Java prefers runtime reflection, and even though GraalVM's native-image is now a problem, they'll rather do something to make runtime reflection more compatible, instead of introducing new ways of doing things.

The more Java evolves, the more it stays the same. This is a strength (backwards compat 💪), but also a weakness. 
 @fd32800e And you can infer Java's direction from its history.

Java, for better or worse, evolved in tandem with the runtime. This is in many ways a strength. E.g., Java's records have a semantic for the runtime that Scala's case classes cannot have. Virtual threads leave the language untouched, etc.

Java is tied to the JVM, JVM improvements lift all boats, but Scala & Kotlin are free to directly target other platforms (JS, wasm, native), which also pushes them to compile-time solutions. 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m that sounds rather ominous ... 
 @fd32800e I don't think we'll ever see Scala's implicit parameters or metaprogramming facilities. Or Kotlin's context receivers, or compiler plugins.

This is because Java prefers runtime reflection, and even though GraalVM's native-image is now a problem, they'll rather do something to make runtime reflection more compatible, instead of introducing new ways of doing things.

The more Java evolves, the more it stays the same. This is a strength (backwards compat 💪), but also a weakness. 
 With #Java's evolution (discriminated unions, pattern matching, virtual threads), are #Scala/#Kotlin still worth it?

Scala & Kotlin have a culture of doing things at compile-time, the former more so than the latter. 

This yields safety & expressiveness, and is reflected in features that Java will never implement, in platforms that it will never target well, or in paradigms it will never embrace.

Java is still Java, and you're stuck with Spring, Hibernate, and Jackson, sorry. 
 "CS3100 Paradigms of Programming @ IITM (OCaml + Prolog)"

"The aim of the course is to teach you about the different paradigms of programming, their underlying concepts, and the relationships between them."

#Link #OCaml #Programming #YouTube #Video

https://www.youtube.com/playlist?list=PLt0HgEXFOHdkE-NTs87s7QjwYwqeihb-D 
 @8264ba52 Elon Musk has Asperger's and, as a neurodivergent, experiences empathy differently, which is also reflected in his communication skills.

I mean no offense, but your rant is unhinged nonsense, even if he may be, in fact, a jerk with an authoritarian tendency. Unhinged nonsense that popped into my feed, as such is the nature of social media, but you already know how things work due to your profession. 
 “FXGL — Java / JavaFX / Kotlin Game Library (Engine)”

#Link #Java #Kotlin #Programming #Gamedev 

https://github.com/AlmasB/FXGL 
 On the right, that's Thomas, my cat, standing on the fence. He's having an argument with the next door neighbour, just before I swoop in to save the day.

#photography #cats #catsOfMastodon

https://social-cdn.alexn.org/media_attachments/files/111/137/770/655/331/331/original/3b3e6ed766e6934e.jpg 
 You know my #Mastodon instance move, from my own instance to #Hachyderm from yesterday?

I changed my mind 🤷‍♂️

It's pretty awesome to be able to just move between instances like this ❤️ although be careful when you do it, as some followers seem to get stuck and may need later intervention to unstuck them. 
 I'm migrating my account to a new #Mastodon instance:

https://hachyderm.io/@alexelcu 
 Years ago, I planted a few black walnut trees in my back yard.  They grew tall and provide good s... 
 @deab03d8 Walnut trees are a protected species here. They've been massively cut down due to the wood being great for furniture. I also remember a case of local corruption ... the mayor of a town cut down the walnut trees from an entire street between 2 cities (30 km). Those trees provided shade and were cut down presumably to expand the road, just before the protection law passed.

Anyway, you're doing the world a favor for growing walnut trees. 
 nostr:npub12jq5ktly2vht4w467kall6e0wuruu3dfy2mm473gqyslynxau3fsakhq6m Hmm good suggestion. I'll c... 
 @40bf96e5 On Hetzner I have an instance with 4 GB of RAM. It's enough to self-host Matomo, Mastodon, the Isso commenting widget, a couple of static websites, and a personal project.

Costs 5.35 EUR / month (without VAT), and it would be 22.5 EUR on DigitalOcean.

I think personal projects / servers need to be cheap for sustainability. 
 Alright, so the goal this weekend is to start setting up a completely open source marketing engin... 
 @40bf96e5 Hetzner is cheaper, and you may need the extra RAM. 
 Going out on a limb to say that I like #Chrome's new #Topics API.

The bad and the ugly is that targeted #advertisement can deceive, and also the bits of data provided by the Topics API can aid in better fingerprinting.

The good is that the web, for better or worse, is built on ads, and the Topics API actually helps smaller websites, not #Google, and not the big ads exchanges. And it can also lead to better #privacy.

https://privacysandbox.com/proposals/topics 
 In light of #Chrome's Topics API, before advertising #Firefox, you might want to know that #Mozilla is one of the authors of IPA:

https://github.com/patcg-individual-drafts/ipa/

https://blog.mozilla.org/en/mozilla/privacy-preserving-attribution-for-advertising/ 
 Sorry, but I can't any "languages popularity index" seriously if I see Fortran, Delphi, Assembly, or Scratch in the top 20 🤷‍♂️ 
 Also, curse you #Kotlin and #Rust for having different syntaxes for range values and confusing th... 
 @3c745deb Kotlin also has this operator:

x ..< y 
 I know, from experience, that ~nobody dragging React behind them into the new gig is thinking in ... 
 @cecee30c I'm not a front-end developer, I only dabble in client-side Javascript to get things done.

It's always interesting to me how the JS ecosystem is willing to throw away everything foundational every couple of years. And evolution might be warranted, but the result is instability and a really poor ROI for developers learning the latest shiny tech, doomed to be irrelevant soon, or for businesses that have to continually be on the upgrade treadmill, or risk unmanageable technical debt. 
Event not found
 @bbfa4eba You're right 👍 
Event not found
 @4b70148b JRuby is a mature project that has significantly better performance for server-side apps than CRuby. Due to the Ruby-FFI efforts, it's also fairly compatible. It should be more popular, but it does have industrial use. 
Event not found
 Narrator's voice: "part 2 never came" 
Event not found
 @ebc0eaba Out of the Scala alternatives, `decline` is probably the best.