r/scala

▲ 7 r/scala

Use of uninitialized val doesn't result in a compiler failure

​

object test:

val y = x

val x = 5

Will compiles but test.y will = 0. I want it to fail to compile is there a way to do that? -Wsafe-init sounds like it should but doesn't.

reddit.com
u/RaymondBKR — 1 day ago
▲ 15 r/scala+1 crossposts

Create stunning TUI interfaces with jatatui (previously tui-scala)

Apologies for the java interface, but i needed it outside of the scala bubble. Still eminently usable from scala, and still native image-safe.

There are three layers to this:

  • crossterm. Manually written facade for the rust library. has been thoroughly tested over the years it has backed `tui-scala`
  • jatatui. Mostly ported 1-1 by claude, given very specific porting instructions. 2k tests and a bunch of runnable demos means most of it works. API should be stable. Whatever porting quirks remain are likely easily fixed.
  • jatatui-react . POC-level code to express yourself using familiar react concepts. Has been used to implement one complex TUI app, but will likely see extensive changes going forward
github.com
u/elacin — 2 days ago
▲ 40 r/scala

🚀 Play Framework's newest Premium Sponsor: Evertrust

📢 We’re excited to welcome Evertrust as our newest premium sponsor! 🎉

evertrust.io is a leading European software provider specialized in integrated PKI and digital certificate lifecycle management solutions, helping companies:

  • gain visibility over their TLS and machine identities,
  • avoid costly outages caused by expired certificates, and
  • automate certificate renewal and deployment across complex, hybrid environments.

We’re proud to partner with a cybersecurity player so focused on digital trust and sovereignty in Europe.

Welcome on board, Evertrust!🔐

https://preview.redd.it/5c4hknkol32h1.png?width=5400&format=png&auto=webp&s=f9273e0c3cfc2e1e323b7c53f2d19b5fea9c23bc

reddit.com
u/mkurz — 2 days ago
▲ 34 r/scala

datomlite - A zero-dep, Datomic-style "DB-as-a-value" you can drop into your Scala 3 apps (JVM, JS, Native)... (Looking for feedback!)

Hello! Been tinkering on datomlite for a while. Its about ready for trials ... and would love your sharp eyes on (1) how the typed datalog-style API feels? (2) If there are some glaring macro faux-pas?..

https://preview.redd.it/3d6snc9zbw1h1.png?width=1340&format=png&auto=webp&s=fcf33267d5243d0c9eb5a5ff2749eac32bda830a

reddit.com
u/mattlianje — 3 days ago
▲ 12 r/scala

li-nk : a Scala backed social platform. develop your interests, find your community

Hi everyone , I just launched the Early Access release of li-nk , a community focused social platform surrounding human interests.

Through the development process I've tried to contribute back to the Scala tooling that li-nk has employed; as well as to other open source projects.

I've contributed upstream to ProtoQuill (both upstream and where I maintain a a maven repository), Caliban, zio-telemetry, and Scala Metals.

The platform geography is unfortunately currently limited to the USA. However I am looking forward to the possibility of internationalizing soon as well.

Regarding Scala. I've been working on and off with Scala since 2014 and have met some of you at Scala Up North (2019?) / Scala Days 2023 / Scala related activities in the Seattle metro.

I hope that you might consider trying out the li-nk platform. Thanks for your consideration and support for our favorite programming language !!

http://demo.li-nk.social/

http://li-nk.social

https://www.linkedin.com/posts/li-nk-social-network_li-nk-activity-7461429061517496320-Zhi2

reddit.com
u/ke7cfn — 5 days ago
▲ 4 r/scala

Job opportunity Scala Dev India .

Guys ,anyone looking for job in scala in India ,let me know . My company is hiring ,I can refer . Also I was laid off few months ago ,but got another scala role . So someone interested kindly let me know . Min exp 2 year .

reddit.com
u/Severe-Lawyer8244 — 4 days ago
▲ 10 r/scala

built a small http4s app that indexes youtube transcripts into postgres and the whole thing is about 350 lines of scala

i work at a fintech company and we have about 170 youtube videos. internal engineering talks, recorded architecture reviews, vendor integration walkthroughs, a bunch of conference talks people bookmarked over the years. all sitting in a shared playlist that nobody scrolls through because the titles are useless. someone would ask in slack "didn't we do a talk about event sourcing last year" and nobody could find it.

i built a small app to make them searchable. http4s server with a single endpoint that takes a query string and returns matching videos with transcript snippets. postgres backend with full text search. a simple html frontend with one search box because i didn't want to deal with a separate frontend project.

for pulling the transcripts i use transcript api:

npx skills add ZeroPointRepo/youtube-skills --skill youtube-full

the ingestion side is a cli tool built with decline. give it a youtube url or a file of urls and it pulls each transcript through the api, parses it, and inserts it into postgres using doobie. i wrote a TranscriptRepo algebra with an insert and a search method. the search uses postgres tsvector with a GIN index and ts_headline for the snippet extraction.

the http4s routes are one file. GET /search with a query param, returns json or html depending on the accept header. i used circe for the json encoding. the html response is just a scalatags template inlined in the route because i didn't want to set up a template engine for one page.

the part that felt nice was how well doobie handles the postgres full text search queries. the tsvector and tsquery types map cleanly and i wrote a custom fragment for the ts_headline call. no raw string interpolation, just composed fragments. it reads well.

deployed it on our internal k8s cluster as a docker container. the docker image is built with sbt-native-packager. the whole app starts in about 2 seconds which is fine for an internal tool.

about 170 videos indexed. the engineering team uses it before design reviews to check whether someone already gave a talk on the approach they're considering. someone from product started using it to find specific things our CTO said in recorded all-hands which i didn't anticipate.

the codebase is a TranscriptRepo trait, a SearchService class, the http4s routes, the decline cli, and a Main object. maybe 350 lines total. no cats-effect streaming or fs2 for this one, just straightforward IO with doobie transactions.

reddit.com
u/scheemunai_ — 7 days ago
▲ 29 r/scala

I built an open-source, high-concurrency state machine for AI tokens using Scala 3, Pekko, and GraalVM

Hey r/scala,

I recently, I noticed AI startups hitting massive race-condition problems when trying to track API token usage natively in Postgres.

I decided to build a standalone, open-source quota firewall to solve this, and I wanted to push the JVM to its limits.

The architecture:

- Written in Scala 3.

- Core engine uses Apache Pekko (Typed/Cluster). The wallet state lives entirely in-memory on a single Actor, making double-spending mathematically impossible without any row-level database locking.

- Event Sourced via Pekko Persistence R2DB, JDBC (Postgres) for the immutable audit log.

- I set it up to compile to a standalone GraalVM native image for instant startup and tiny memory footprints.

It was an awesome challenge figuring out how to handle "Zombie Holds" (when an LLM API times out and freezes a user's tokens) using Pekko's TimerScheduler.

I'd love for some experienced Scala devs to tear apart the architecture or give me feedback on the GraalVM/Pekko setup.

Repo is here: https://github.com/baseledger-io/baseledger

u/Illustrious-Rock6230 — 10 days ago
▲ 69 r/scala

Kyo going pure Scala 3 - 1.0.0-RC2 is out!

v1.0.0-RC2

v1.0.0-RC2 is a large release. Nine new modules land, the HTTP stack is rewritten from scratch in pure Scala (with both client and server running on JVM, JS, and Native), and Scala Native picks up the remaining pieces it needed to be a viable target for everything Kyo ships 🚀

A recurring theme across the release is dependency reduction. Netty, libcurl, h2o, JCTools, Caffeine, HdrHistogram, the Java OpenTelemetry SDK, sttp, and tapir are all gone, replaced by pure-Scala implementations that share Kyo's scheduler and effect channels and compile to all three platforms. The new modules build directly on that foundation: durable workflows (kyo-flow), container orchestration (kyo-pod), feature flags (kyo-config), and OpenTelemetry export (kyo-stats-otlp) all rely almost exclusively on pure Scala implementations compiled to JVM, JS, and Native.

New Features

New modules

  • kyo-http (README) replaces the sttp and tapir integrations with a single client+server API that compiles to all three platforms, dropping Netty for a pure-Scala transport that handles TLS, WebSocket, Unix sockets, SSE, and NDJSON. Routes are an interpretable pure data structure with type-level field tracking via Record. (by @fwbrasil in #1479, #1518)

  • kyo-pod (README) is a Docker and Podman client that talks the Docker Engine API directly over the Unix socket, with a shell execution fallback. Logs, stats, exec output, and image pulls stream from the first byte. Predefined containers for Postgres, MySQL, and MongoDB are provided for convenience. (by @fwbrasil in #1524)

  • kyo-flow (README) is a durable workflow engine. A Flow is a plan, not an execution: every step is checkpointed before the next begins, and if the process crashes another executor claims the work via a time-limited lease and replays from the last checkpoint, skipping completed steps. Workflows suspend on declared inputs and resume when signals arrive through the engine API or the auto-generated HTTP endpoint, so human approval, async events, and other external triggers are first-class. Saga-style compensation, per-step retry and timeout, and an event audit trail are all built in. (by @fwbrasil in #1498)

  • kyo-schema (README) is a single-source-of-truth schema module. Derive Schema[A] from a case class and get JSON, Protobuf, type-safe lenses, structural diffs that ship and replay, batched mutations, incremental builders, and bidirectional conversions between structurally compatible types. No annotations, no boilerplate. The module depends only on kyo-data and has no dependency on Kyo's effect runtime, so it can be adopted as a standalone library. (by @fwbrasil in #1517)

  • kyo-parse moves the Parse effect out of kyo-prelude and parameterizes it on input type, so token-stream parsers compose with lexers. The internals are reworked to add error accumulation and AST recovery, which makes the effect suitable for real-world parsers like programming languages and LSPs. (by @Iltotore in #1305, #1404, #1421, @fwbrasil in #1400)

  • kyo-config (README) provides typed feature flags and structured configuration. StaticFlag resolves once at class load for infrastructure settings; DynamicFlag evaluates per call for feature gates and A/B tests. Both support a rollout DSL with path matching, percentage weights, and deterministic bucketing, with automatic topology detection for K8s, AWS, and GCP. (by @fwbrasil in #1511)

  • kyo-stats-otlp replaces the JVM-only kyo-stats-otel with a from-scratch pure-Scala OTLP/HTTP exporter built on kyo-http. Speaks the protocol directly, runs on JVM, JS, and Native, and disables itself when OTEL_EXPORTER_OTLP_ENDPOINT is unset. (by @fwbrasil in #1491)

  • kyo-logging-jpl and kyo-logging-slf4j are platform logging bridges extracted from kyo-core. kyo-core no longer pulls SLF4J as a dependency; pick whichever bridge matches your stack. (by @hygt in #1396)

Cross-platform process management

Path, Command, and Process now work consistently across JVM, JS, and Native, with safer APIs that drop java.* types in favor of Stream where it makes sense. The System effect also gains availableProcessors and architecture, classifying os.arch tokens consistently across platforms. (by @fwbrasil in #1505, #1522, #1532)

New primitives

  • Dict is a new low-allocation immutable map with a dual internal representation: a flat Span for up to 8 entries (linear scan, no hashing) and a HashMap above that. Iteration takes separate key and value parameters to avoid boxing in hot paths. Used internally by the new Record encoding. (by @fwbrasil in #1470, #1523)

  • Gate replaces Barrier with a primitive that covers both the cyclic-barrier and phaser use cases. Parties pass through together once everyone arrives, with multi-pass coordination and pass tracking; a Gate.Dynamic variant supports runtime join and leave plus hierarchical subgroups. (by @fwbrasil in #1480)

  • Exchange is a new low-level primitive for ID-multiplexed protocols like HTTP/2 and WebSocket subprotocols, where requests are tagged with an ID and responses are routed back by that ID. It encapsulates the pending-promise map, the reader fiber, the cleanup races, and backpressure for unsolicited events. Intended for protocol clients, not application code. (by @fwbrasil in #1501)

  • New Record encoding: records no longer allow duplicate field names with different types. The old encoding stored a runtime Tag to disambiguate, which the new invariant plus Conversion-based subtyping replaces, also reducing memory footprint. (by @fwbrasil in #1467, #1472)

  • Base64: pure-Scala RFC 4648 implementation that cross-compiles to all three platforms without depending on java.util.Base64. (by @fwbrasil in #1531)

Interop and convenience APIs

  • Kyo Stream and ZIO ZStream interop: bidirectional conversion between the two. (by @HollandDM in #1461)

  • Abort.ignore and Abort.loopUntil: two new error-handling combinators. (by @fwbrasil in #1507)

Improvements

Native parity

Scala Native catches up to JVM and JS on the modules where it used to be missing or partial. Full HTTP client and server support lands (by @fwbrasil in #1479), along with a JCTools queue port that replaces unoptimized stubs (by @fwbrasil in #1489), a Cache primitive that retires the JVM-only Caffeine dependency (by @fwbrasil in #1487), Prometheus and OTel-inspired histograms in kyo-stats that replace HdrHistogram (by @fwbrasil in #1483), signal handling so Native binaries respond to SIGINT and SIGTERM (by @hearnadam in #1408), and a scheduler jitter fix that addresses a Native-specific Thread.sleep contention (by @fwbrasil in #1485). reactive-streams now cross-compiles to JS and Native (by @fwbrasil in #1484), and the ZIO interop modules are enabled for Native (by @fwbrasil in #1482).

General

  • Scoped Fiber.init: fibers used to be fire-and-forget by default, easy to lose track of. Fiber.init now introduces a Scope pending effect and registers a finalizer that interrupts the fiber when the scope closes. Fiber.initUnscoped preserves the prior behavior. (by @johnhungerford in #1379)

  • Reliable blocking detection and thread-interrupt propagation: the scheduler's stalled-worker detector now reads per-thread CPU time instead of thread state, which several kernel-level blocking operations leave at RUNNABLE despite genuinely being blocked. Fiber interrupts also reach into truly blocking I/O like ServerSocket.accept now: the JVM thread interrupt is dispatched, gated to fire only when the worker is genuinely parked so it can't damage in-flight work. (by @fwbrasil in #1510)

  • Nested .now and .later in direct: .now and .later inside another .now, and .later inside another .later, now compile, removing a common ergonomic wart. (by @ahoy-jon in #1369)

  • ConcreteTag derivation for unions and intersections: generic methods over Abort[E | Closed] compile with just ConcreteTag[E] instead of requiring ConcreteTag[E | Closed] at every call site. (by @johnhungerford in #1397, @fwbrasil in #1512)

  • Smaller items: Isolate.restore becomes contravariant and gains an isolate.nest helper (by @fwbrasil in #1388); AsyncShift is specialized for List and Set so direct-style for lowers to the optimized kyo.Kyo.* calls (by @ahoy-jon in #1302); Aspect.init accepts dynamic tags via Tag.dynamic (by @fwbrasil in #1389); Safepoint.ensure no longer re-registers the same finalizer on each loop iteration (by @hearnadam in #1434).

Concurrency and streams

  • Stream parallel map memory leak: mapPar and friends let an unbounded number of follower fibers accumulate when transformations took long. The rewrite caps concurrency via a Meter and a bounded queue. (by @johnhungerford in #1378)

  • Queue.closeAwaitEmpty drain on every call: only the first caller used to wait for the queue to drain; subsequent callers returned false immediately. They now join the same wait. (by @hearnadam in #1430)

Data and observability

Span gains the common Scala-collection-style APIs that don't box. Tag's string representation is now deterministic, which matters when tag strings are used as persistence keys. KyoException.getMessage no longer silently drops the wrapped exception's class and text in production mode, so "Unexpected error for X" now carries the actual cause. STM is optimized and the opacity bug from a missing second transaction timestamp is fixed. (by @fwbrasil in #1401, #1495, #1523, #1455, #1456, #1459)

Tooling and ecosystem

  • Scala 3.8.x support across the matrix (3.8.1 and 3.8.3), with scheduler-related modules also compiled on Scala 3.3.7 (LTS). (by @fwbrasil in #1451, @road21 in #1508, @hearnadam in #1407)

  • Caliban migrated to kyo-http: the GraphQL integration now runs on the unified transport. (by @fwbrasil in #1490)

  • Docs: AGENTS.md and an expanded CONTRIBUTING.md, plus a copy-to-code button on samples and a new N Queens example using Choice. (by @fwbrasil in #1468, @hearnadam in #1384, @Yummy-Yums in #1402, #1399)

Fixes

  • kyo-stats-registry never exported metrics: StatsRefresh's ThreadFactory built threads without passing the Runnable, so refresh() never ran, breaking metrics (this export is now replaced by kyo-stats-otel). (by @Salim-belkhir in #1457)

  • Channel, Stream, and Async correctness: Channel.closeAwaitEmpty no longer drops the last element on streaming consumers (the slow-path drainUpTo short-circuited the for-comprehension when the take had transitioned the channel); multi-producer split-batches are correct; Stream.mapPar propagates Closed; Async.foreach is rewritten to fix a per-item index bug and to use work-stealing instead of static batching. (by @fwbrasil in #1464, #1503, #1497, #1514)

  • Interrupt and scope races: a best-effort workaround reduces the race where a parent interrupted before joining its child failed to propagate the interrupt (the fix handles a pending Async.Join during interrupt rather than relying solely on the link that hadn't been registered yet); first wave of Scope correctness fixes also lands. (by @fwbrasil in #1458, #1504)

  • zio-test assertTrue over scope-managed resources: TestResult.result was a lazy val evaluated after Scope.run closed finalizers, so assertions over scoped resources observed torn-down state. Fixed by forcing the arrow chain inside the test body. (by @gcsolaroli in #1529)

  • Type machinery: Tag variance is now read from typeArgs rather than symbol.declarations, Null is no longer considered a subtype of literal types, and TypeMap/Env.get with intersection types is now a compile error. (by @fwbrasil in #1449, #1447, @ahoy-jon in #1492)

  • Data and miscellaneous: Chunk.toArray correctly unboxes for primitives (by @fwbrasil in #1448); Text#dropUntilNext off-by-one (by @toonvanacker in #1383); Layer.using (by @ahoy-jon in #1423); Frame.internal cleanup for clearer stack traces (by @hearnadam in #1365); test additions and stability for NestedHandler, closeAwaitEmpty, and Semaphore (by @ahoy-jon in #1493, @steinybot in #1375, @hearnadam in #1433); README code-block fence and Retry section heading (by @kyusu in #1437, @markehammons in #1533).

Breaking changes

  • Fiber.init is now scoped; use Fiber.initUnscoped for the prior behavior. (by @johnhungerford in #1379)
  • Barrier removed, replaced by Gate. (by @fwbrasil in #1480)
  • Sync.Unsafe.apply renamed to Sync.Unsafe.defer. (by @fwbrasil in #1466)
  • Abort[Throwable] removed from Future conversion result types; failures still surface as panic. (by @fwbrasil in #1465)
  • Row removed; use the new Record encoding. (by @fwbrasil in #1471)
  • Record no longer allows duplicate field names with different types. (by @fwbrasil in #1472)
  • Parse moved to kyo-parse and parameterized on input type. (by @Iltotore in #1305, @fwbrasil in #1400)
  • kyo-sttp and kyo-tapir removed; migration guide in kyo-http/README.md. (by @fwbrasil in #1537)
  • kyo-stats-otel removed; use kyo-stats-otlp. (by @fwbrasil in #1491)
  • SLF4J no longer a dependency of kyo-core; pick kyo-logging-slf4j or kyo-logging-jpl. (by @hygt in #1396)
  • TypeMap/Env.get with intersection types is now a compile error. (by @ahoy-jon in #1492)

New Contributors

  • @toonvanacker made their first contribution in #1383
  • @Yummy-Yums made their first contribution in #1399
  • @Iltotore made their first contribution in #1305
  • @hygt made their first contribution in #1396
  • @kyusu made their first contribution in #1437
  • @Salim-belkhir made their first contribution in #1457
  • @markehammons made their first contribution in #1533
  • @gcsolaroli made their first contribution in #1529

Full Changelog: https://github.com/getkyo/kyo/compare/v1.0-RC1...v1.0.0-RC2

u/fwbrasil — 11 days ago
▲ 13 r/scala

Join us at the Scala Hangout tomorrow evening (May 14th)!

The Scala Hangout will be having its May hangout tomorrow (May 14th) evening. There have been some interesting articles published this last month, but conversation is open as always.

https://heylo.com/invite/QX8kvtO8

u/littlenag — 8 days ago
▲ 7 r/scala

Hi r/scala — disclosure up front: I the maintainer of Aegis-KMS, an
open-source key manager we just shipped v0.1.1 of. This post is *not*
about the product, it's about the language/stack choice. The product
choice is in a different post next week.

Most "we picked Scala for X" posts age badly because they're aesthetic
arguments. The four properties we actually needed from the language
were:

  1. Total case analysis on every security decision (sealed traits +
    -Wunused, so a forgotten principal kind doesn't compile)
  2. Composable invariants without inheritance — the same KeyService
    algebra is wrapped by Authorizing, Auditing, ActorBacked
    decorators, each adding one orthogonal concern.
  3. Single-writer state with deterministic event-sourced replay
    (Pekko Typed actor + journal — the actor IS the user guardian,
    no Promise/Await dance).
  4. A clean fallback when the type system runs out (Cats Effect 3).

The full write-up with code from the actual repo is here:

https://medium.com/@sharma.b6/why-we-built-aegis-kms-in-scala-3-pekko-and-why-its-a-security-argument-not-an-aesthetic-one-5064a351fc08

Where the stack cost us:

  - Pekko version pinning hell — Tapir transitively pulls a different

pekko-stream and ManifestInfo refused to start; we had to

dependencyOverride across all artifacts.

  - sbt-dynver vs. Pekko user-guardian — the original

Promise/Await pattern hung on cold start on JDK 21 + sbt's

classloader. The fix was making the ActorSystem itself the actor

(`ActorSystem[T] <: ActorRef[T]` in Pekko Typed).

  - Scala 3 + Doobie 1.0.x had codec quirks we worked around.

GitHub: https://github.com/sharma-bhaskar/aegis-kms

v0.1.1 has 160 tests, scalafmt + scalafix clean, library tier

explicitly Pekko-free for embeddability.

Happy to take pushback in comments — especially from anyone who

considered Scala for a similar control-plane shape and went a

different way.

u/Ok-Cold-3354 — 14 days ago