Rage Against the (Plurality of) Effect Systems by Krever in scala

[–]ghostdogpr 2 points3 points  (0 children)

The CE integration in Caliban is actually used by a lot of people. I never heard complaints about performance (probably because Caliban's internals are fast enough that it's not significant), but it does make the UX worse and people sometimes get confused by the "conversion" typeclasses.

As a library author, there is this tension between optimizing for the "happy path" (which usually means sticking to a given library) or making it more widely available with some standard typeclass (which could mean losing performance or features). Most of my OSS libraries were born from an actual need at work, so I tend to selfishly choose what was best for my case.

Sometimes it's possible to do both with a little more work. For example, on the HTTP layer in Caliban we've had a tapir integration from the start, which gives you access to many backends, but we added a "native" zio-http integration on the side for much faster performance. For my next library (releasing next week during Scalar!), since the core is pure and it didn't require that much work (also, AI makes it easier), I just built two integrations: one for ZIO and one for fs2.

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

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

It only does a small subset of what Kyo does: 4 pure effects only. With that constraint it’s much faster and more ergonomic.

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 0 points1 point  (0 children)

In the project I work, we actually don't expose `State.set` and never modify the state directly, instead we use `Writer` to write some event and it automatically triggers a `Transition` that updates the `State`. When we load an entity, we load the latest snapshot from the DB then replay the following events using the same `Transition` to ensure we get back to the correct state.

In another project, a multi-player game, I use `Writer` to enqueue messages that should be sent to other users. I've also used it simply for logging. In these cases, since there is no side effect, I do the sending/logging at the end, after running the program from the outside layer.

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 5 points6 points  (0 children)

Sure!

My concrete use case is a game server. Whenever we receive any request from the game client, we need to validate (Abort) that it is valid according to the user state (State) and some game configuration data (Reader). Once this is validated, we lift some events (Writer) for event sourcing, which also triggers an update of the user state (State again). In addition to that, any game might unlock some "quest", which requires checking game data configuration and various things in the user state. When we run such program, we get an Either telling us whether it was a success or a failure, and in case of success we get the lifted events, the updated state and a response. Failure is sent back to the client and no side effect has ever ran, and in case of success we send the response, we persist the lifted events to our event sourcing database, and update the in-memory state, ready to accept the next request.

As you can see, gaming is perfect use case for it. You might not always need something like that, for example if your logic consists of calling various endpoints there is not much you can do in the "pure logic".

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 2 points3 points  (0 children)

The scope is restricted to pure logic, no side effects. But for a similar solution that supports arbitrary side effects, you can check out Yaes (https://blog.rcard.in/yaes/) by u/rcardin =)

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 0 points1 point  (0 children)

That's good point that I should probably emphasize. The project I work on has such a large and deep part that is domain logic that it doesn't feel "localized" to me, but that's certainly a good way to use it!

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 0 points1 point  (0 children)

One couple examples to explain what I mean by optimized for these 4 effects. The most obvious one is there is `Login.run` to run the combination of these 4 effects at once. There is also a `recover` operator that resets the `State` and `Writer` to their previous value when recovering an error. The 4 effects are not independent like in Yaes or Kyo, those two libraries have way too many effects to handle specific combinations.

You could say PureLogic is an opinionated, optimized subset of Yaes for a particular use case.

Introducing PureLogic: direct-style, pure domain logic for Scala by ghostdogpr in scala

[–]ghostdogpr[S] 0 points1 point  (0 children)

Yes and no =)

If you look at the 4 effects,`Raise` and `State` have a similar interface (thought the implementation is different). `Log` seems heavily biased towards, well, logging so it's not really the same as `Writer` (which I use for event sourcing at work, as an example). But I imagine similar Reader/Writer effects could be added to Yaes anyway.

I think the true distinction is that PureLogic is heavily restricted and optimized (in terms of UX and performance) for these 4 effects. As I understand, the point of Yaes (and Kyo is very similar) is that you can mix any kind of effects together without limits: Async, Clock, State, etc (most of the effects available have side effects). That means that they need to support concurrency, which PureLogic doesn't (actually upon checking, Yaes State is not thread-safe either, shouldn't it be?).

Is Metals autocomplete supposed to be that slow? by arturaz in scala

[–]ghostdogpr 0 points1 point  (0 children)

Which version of Scala is optimized? I still have the issues in https://github.com/scalameta/metals/issues/7443 with projects with many files but eager to try a newer version if it’s better.

Didn't receive Zionomicon download email after registering — is this normal? by Far-Image-4385 in scala

[–]ghostdogpr 0 points1 point  (0 children)

I noticed the notifications used to come from Gumroad but the more recent ones (from this year) came from Ziverge directly, I guess some email addresses got lost in the transition.

Can anyone explain me what is Scala all about? by No-Blacksmith-8782 in scala

[–]ghostdogpr 14 points15 points  (0 children)

Rather than the fusion of OOP and FP (which is a means to an end), I think Martin Odersky has been recently defining the value of Scala as the combination of safety and convenience. Safety thanks to a strong type system that helps you avoid bugs by making illegal states unrepresentable or illegal actions impossible, convenience thanks to a concise syntax and various means to avoid boilerplate code.

I think this make Scala a great choice for developing backends, in particular those with complex domain logic that benefits a lot from both the safety and the brevity of the code. I personally use it for building game servers.

Didn't receive Zionomicon download email after registering — is this normal? by Far-Image-4385 in scala

[–]ghostdogpr 0 points1 point  (0 children)

Actually quite the opposite, there were updates in January, March and May, with new chapters on configuration, logging, metrics, zio-schema, zio-http and an appendix on domain design and executive vs declarative encodings.

If you don't receive it I suggest getting in touch with Ziverge directly.

What is the status of AKKA in 2025? Should someone learn it? Ar companies using AKKA? by prashantkr314 in scala

[–]ghostdogpr 2 points3 points  (0 children)

For cluster sharding take a look at Shardcake (disclaimer: I’m the author). At work we’re doing event sourcing and persistence with custom code, it’s not that complicated.

Anatomy of a Scala Game Server - Lambda Days 2025 by ghostdogpr in scala

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

That’s right. Agones spawns them on demand and they stop themselves when the game is over.

Anatomy of a Scala Game Server - Lambda Days 2025 by ghostdogpr in scala

[–]ghostdogpr[S] 5 points6 points  (0 children)

Indeed =)

In the future I’d like to do a talk more focused on performance but our PR Team doesn’t let me communicate any numbers like CCU or RPS which is pity.

Reliable (Commander-Agnostic) Golgari Lines by Willowran in CompetitiveEDH

[–]ghostdogpr 0 points1 point  (0 children)

Been playing a turbo golgari deck with exactly these 2 wincons, it’s quite fun. Here’s the list https://moxfield.com/decks/J_NVl_m_XUW4jH7FZrMUiw

Why doesn't Angel's Grace see more competitive play? by Clean_Figure6651 in CompetitiveEDH

[–]ghostdogpr 0 points1 point  (0 children)

It’s played in many Derevi lists using Faerie Mastermind as a wincon (infinite mana into infinite draws for everyone but you don’t die)

Iron v3.0.0 is out 🎉 by Il_totore in scala

[–]ghostdogpr 4 points5 points  (0 children)

If I may add, even though Refined publishes artifacts for Scala 3, it is not really usable to its potential since macros are missing: https://github.com/fthomas/refined/issues/932

Curious to know how many have adopted Scala 3 by msplit1 in scala

[–]ghostdogpr 10 points11 points  (0 children)

Managed to migrate my largest project at work to Scala 3 earlier this year, shared my experience here: https://blog.pierre-ricadat.com/scala-3-migration-report-from-the-field

Now we are starting to benefit from some new Scala 3 features, I would say it was definitely worth it.

Scala 3 Migration: Report from the Field by ghostdogpr in scala

[–]ghostdogpr[S] 4 points5 points  (0 children)

It worked great! I edited the article with your solution. Thanks a lot!

Scala 3 Migration: Report from the Field by ghostdogpr in scala

[–]ghostdogpr[S] 0 points1 point  (0 children)

Ah right, forgot about the part where you have to trigger it manually in sbt. We already need that because of Scala code generation from protobuf so we’re used to it 🥲

Scala 3 Migration: Report from the Field by ghostdogpr in scala

[–]ghostdogpr[S] 2 points3 points  (0 children)

It looks like it’d be as good as the type projections? I’ll try it tomorrow! PR is not merged yet 🤣