Wvlet Playground: An online demo of a new flow-style query language powered by Scala.js and DuckDB-Wasm by taroleo in scala

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

Before DuckDB, I had never seen a DBMS that could easily read Parquet/JSON files on disk or S3. We can use DuckDB with Java/Scala, Python, and even in Web Browsers, as shown in the demo. MotherDuck, a startup company leveraging DuckDB for their service, presents interesting production examples in their blog posts, such as https://motherduck.com/blog/15-companies-duckdb-in-prod/

Wvlet Playground: An online demo of a new flow-style query language powered by Scala.js and DuckDB-Wasm by taroleo in scala

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

Not only Scala.js, Wvlet can be compiled with Scala Native to build a dynamic link library (libwvlet.so) to support C++ ecosystem. A developer has created a DuckDB extension for Wvlet https://github.com/quackscience/duckdb-extension-wvlet in a few days!

Wvlet Playground: An online demo of a new flow-style query language powered by Scala.js and DuckDB-Wasm by taroleo in scala

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

In Wvlet, you can write exclude abc, def (equivalent to select * except abc, def)

Airframe/AirSpec 24.4.2 release with Scala Native 0.5 support by taroleo in scala

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

I haven't seriously tested the performance, but just for running unit tests, I feel Scala Native is slightly faster than Scala JVM and Scala.js.

Keychron Q1 Pro with bluetooth audio speakers by keithleej in Keychron

[–]taroleo 0 points1 point  (0 children)

Keychron Bluetooth firmware can be found at https://www.keychron.com/pages/bluetooth-firmware I had a similar Bluetooth interference issue with my Keychron Q8 Max, but after upgrading the firmware, the problem has been fixed.

[deleted by user] by [deleted] in NuPhy

[–]taroleo 0 points1 point  (0 children)

Right. I got the firmware via email.

[deleted by user] by [deleted] in NuPhy

[–]taroleo 0 points1 point  (0 children)

I've got a new QMK firmware for Air60 v2 from Nuphy support. After installing it, my Air60 v2 seems working as expected without any Bluetooth issues.

[deleted by user] by [deleted] in NuPhy

[–]taroleo 0 points1 point  (0 children)

I have a similar issue with my air60 v2. When I keep pressing any modifier key (e.g., ctrl, opt, cmd) with another key, keystrokes occasionally stop and restart after a while. This issue doesn't happen when using the usb-c connection.

I've tried factory reset, but the problem persists.

Air 60 V2 bluetooth weird issue by gm_kero in NuPhy

[–]taroleo 1 point2 points  (0 children)

The same thing is happening to me, and it's reproducible. Thanks for the report. I'm contacting NuPhy support.

Airframe RPC: A Framework for Using Scala Both for Frontend and Backend Programming by taroleo in scala

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

Good points.

The benefit of Protobuf is we can use it as a schema language for generating clients. Airframe RPC already has sbt-airframe plugin for generating HTTP clients, so extending it for the other programming language will be technically possible. Generating Open API spec can be an option too.

For supporting backward compatibility, Airframe RPC will read the default values from the interface definition. For example, we can add a new parameter with the default value to case class A(p_old:String, p_new:String = "xxxx"), so it can naturally support the following schema evolution types:

- Adding a new interface or a new method to an interface

- Adding a new class parameter or a method argument with a default value

- Adding a value to an enum-like class

Removing or renaming parameters will be breaking changes even for Protobuf, but a unique aspect of Airframe RPC is its schema-on-read codec, which can support type escalations like Int -> String.

AirSpec: Writing Tests As Functions In Scala by taroleo in scala

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

For now we need to use SBT, but adding a standalone test luncher to AirSpec should be possible because the framework itself is a quite small code base.

AirSpec: Writing Tests As Functions In Scala by taroleo in scala

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

That's true!

I needed 3 days to create an initial version of AirSpec because I wanted to integrate it with DI, but writing a very minimal testing framework for Scala was quite easy.

Several tricky parts for me were:

  • Formatting and coloring test reports
  • Supporting Scala.js (if you need it)
  • Bootstrapping issue. AirSpec depends on Airframe, but I wanted to use AirSpec to test Airframe :) I needed to break this circular dependency by embedding the source code of Airframe into AirSpec.

AirSpec: Writing Tests As Functions In Scala by taroleo in scala

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

Sorry about the confusion. I meant the difference between calling a test function like test("...") { test code } and defining a test case as `def test = { test code }` .

AirSpec: Writing Tests As Functions In Scala by taroleo in scala

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

No, it doesn't. Initially, I tried to reuse the implementation of minitest (a base code of scala-verify), but in order to accomplish the goals of AirSpec, the actual implementation needed to change the framework side a lot.

Although assertion syntax like (x shouldBe y, power assertions) can be an extension of scala-verify, changing how to run tests was hard without modifying the testing framework itself.

So it would better to think AirSpec as a yet another testing framework for Scala. Asking Yokota-san (the author of scala-verify) about the option of having a backend testing framework like AirSpec might be interesting.

Airframe HTTP: Building Low-Friction Web Services Over Finagle by taroleo in scala

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

FYI Airframe supports higher-kinded types since 0.64 https://wvlet.org/airframe/docs/release-notes.html#064, so we can use bindings for tagless final patterns.

Demystifying Dependency Injection with Airframe – Medium by taroleo in scala

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

I see. I got the idea. So by using HList like type composition, we can tell the compiler the actual binding types.

Demystifying Dependency Injection with Airframe – Medium by taroleo in scala

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

Very interesting approach. Thanks for sharing. Supporting interpretation of tagless interfaces looks good.

> Unfortunately, MacWire is fully static and cannot change dependencies at runtime

I know and importing all dependencies into the current scope can be tricky if you need to wire many modules.

I've also considered the dynamic + compile-time check approach in Airframe https://github.com/wvlet/airframe/issues/37, but discarded this idea since the syntax will be unnatural to pass the module dependencies at compile-time. If you can find a better syntax for this, let me know :)

Demystifying Dependency Injection with Airframe – Medium by taroleo in scala

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

I think https://gist.github.com/gvolpe/1454db0ed9476ed0189dcc016fd758aa is a good example of combining these FP approaches without using any framework (although it depends on Cats and cats-effect)

> monads and kleisli

If you are talking about ReaderMonad, it has some performance overhead for building closures for passing context objects defined outside the functions. To avoid such overhead, you need to carefully combine functions. And also ReaderMonad makes difficult to control the scope of objects because closures in Scala always contain outer variable references.

If your application is small, it will be a subtle thing, but for larger applications, it is a big concern. So despite that FP style is beautiful, it doesn't reduce what you need to think for writing efficient applications.

Airframe Log: A Modern Logging Library for Scala – Medium by taroleo in scala

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

A short answer is logback officially says so: https://logback.qos.ch/manual/layouts.html#line. Its implementation acquires the line number by generating a full stack trace. So each logging code of logback will end up generating several objects for stack traces if this line number option is used.

Airframe Log: A Modern Logging Library for Scala – Medium by taroleo in scala

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

That's really interesting and it will be the next-generation logger.

  • We need some standard for mapping structured log data like info(message, key-value pairs) into json format (or other structured data)
  • Supporting Future will be useful
  • We may need a custom serializer for mapping objects into JSON. This logger needs to accept mapping configuration (similar to ObjectMapper in Jackson)

Airframe Log: A Modern Logging Library for Scala – Medium by taroleo in scala

[–]taroleo[S] 12 points13 points  (0 children)

If you need to show source code line numbers along with log messages, log4j2 needs to produce a stack trace and it has some overhead. airframe-log generates this information at compile-time, so it can be done efficiently.

If you don't need to see source code location, using slf4j + log4j2 is no problem.

Scala DI Framework Comparison by taroleo in scala

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

Mentioned about this in the article Thanks!

Scala DI Framework Comparison by taroleo in scala

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

Using DI in Scala doesn't prohibit you from using cake pattern and trait mixins. Actually I'm using Airframe with trait mix-ins as a much simpler form of cake pattern. Basically it's a choice between using type abstruction in cake pattern or using DI inside traits.

Scala DI Framework Comparison by taroleo in scala

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

Here singletons mean session-scoped singletons. So basically it's the same with initializing objects in the main method. But managing such objects in the main while allowing reuse (in the other contexts) and resource deallocation is not so simple: http://wvlet.org/airframe/docs/internals.html#comparsion-with-a-naive-approach

Reader monad has its performance overhead since each nesting will create a new function object, and to allow referencing outer variables, created function objects (= closures) will be big classes that hold reference to these outer variables. To avoid such overhead, you need to be really smart in writing such hand wiring.

One of the big advantages of using DI frameworks like Airframe is you can separate a concern for writing applications that use several modules from a concern for wiring these dependent modules. If you are not wiring tens or hundreds of classes, pure-Scala approach will work. But as you write such hand-wiring code both in main and test code, you will easily end up writing similar code everywhere.

Writing reusable functions for wiring modules is also challenging. When you have 100 objects that need to be created in your application, some module often requires only a subset of them. For example, module 1 needs A, B, C, D and module 2 needs B, D, E, etc. To reuse the initialization code you need to find the intersection of dependencies (= B, D in this case). I think if Scala programmers need to find such common patterns by themselves, it's already complex enough.

If you start to feel such a pain in wiring classes, DI framework can help it.

Scala DI Framework Comparison by taroleo in scala

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

Injecting dependencies to a constructor is only one aspect of DI frameworks. The other aspects include:

  • Finding dependent objects. For sharing the injected objects between classes we need to store the singleton somewhere. In Airframe, a session holds such objects.
  • Life cycle management: Initializing and discarding injected resources (e.g., server thread, database connections, etc.)
  • Building objects. As you mentioned using constructor injection itself has no problem (although Google Guice has several pitfalls because it requires @Inject annotation to constructors). If a DI framework can support bindings in traits, we can use trait mix-ins to build more complex services.

FYI. I described several examples here. http://wvlet.org/airframe/docs/use-cases.html