Skip to content

Chaining operations with ? #13

@nkoturovic

Description

@nkoturovic

Proposal

Note: I'm new to Nim and not sure how to implement it nor is it even possible

Suppose we have function safeDiv

func safeDiv(x : int, y: int): Result[int, string] =
  return case y:
    of 0: err("Division by zero")
    else: ok(x div y)

Currently we have to write:

func calc(): Result[int, string] =
  result = (?(?8.safeDiv(2))).safeDiv(0)).safeDiv(1)

Since Nim supports UFCS, it would be a lot nicer to write something like:

func calc(): Result[int, string] =
  result = 8.safeDiv(2)?.safeDiv(0)?.safeDiv(1)?

Currently there are various ways to chain operations, which are similar but not quite the same:

  • Functor like map function
  • Various getter methods
  • etc ...

Motivation: Rust

Here is similar example written in rust with postfix question mark operator ?.
Rust does not fully support UFCS like Nim, for example for primitive type i32 we would write something like

trait SafeOps: Sized {
    fn safe_div(self, other: Self) -> Result<Self, String>;
}

impl SafeOps for i32 {
    fn safe_div(self, other: Self) -> Result<Self, String> {
        if other == 0 { Err(String::from("Division by zero")) }
        else { Ok(self / other) }
    }
}

fn calc() -> Result<i32, String> {
    8.safe_div(2)?.safe_div(0)?.safe_div(1)
}

fn main() {
    println!("{:?}", calc());
}

Further considerations

  • Doing similar for Option type in standard library
  • Generalizing Option and Result to some kind of Monads maybe somehow or not

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions