Coder Social home page Coder Social logo

quest's Introduction

Rust-like Question Operator for Scala 3

This small library introduces a Rust-like ?-Operator for Scala 3.

Example

// Add to build.sbt
libraryDependencies += "net.reactivecore" %% "quest" % <Version>
import quest.*

def getUser(id: Int): Option[String] = { ... }

def getPermissions(id: Int): Option[List[String]] = { ... }

def getUserAndPermissions(id: Int): Option[(String, List[String])] = quest {
  val user = getUser(id).?
  val permissions = getPermissions(id).?
  Some((user, permissions))
}

Operations

  • quest(f: => T): T initiates a block within which the question operator can be utilized.
  • ? extracts the value from some type (e.g. Either[L,R]) if it represents a success, or exits the quest block if it represents a failure.
  • bail(value: T) immediately exits the quest block with the specified value. It's an alias for scala.util.boundary.break.

Supported Types

  • Option[T]
  • Either[L,R]
  • Try[T]

To use other types with the question operator, implement the QuestionOperatorSupport type class.

How it works

The quest block leverages scala.util.boundary which uses exceptions for early exit. In cases of failure, an scala.util.boundary.Break exception is thrown and caught by the scala.boundary.apply function. (Note that this is optimised to a labelled jump, instead of exception, when no intermediate closures are in between ? and quest)

Two helper classes simplify its use:

  • scala.boundary.Label[T] captures the return type of the quest/break method, enabling the question operator and leveraging Scala's type system to determine the correct return type
  • QuestionOperatorSupport[T] decodes each supported type into it's Failure and Success type. Failure and Success type can be gathered using the Aux-Pattern: QuestionOperatorSupport.Aux[T,F,S]

Features

  • Short notation
  • Minimal codebase (50 LOC)
  • Compatible with IntelliJ IDEA (unlike some macros)
  • Supports Loom-based virtual threads

Caveats

  • scala.util.boundary uses exceptions for control flow, deviating from purely functional Scala practices. This approach may cause issues in certain contexts:
    • It is incompatible with delayed execution contexts (e.g., Future, Effect Systems or collection views), potentially throwing Break exceptions unexpectedly.

Performance

  • A small performance test measured an overhead of ~5ns per Failure return per Call in comparison to flatMap and return.

Prior Art

quest's People

Contributors

nob13 avatar bishabosha avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.