Arguments of Optional Type

Objective: Define a fucntion that takes argument x of Optional[int] type. Return 123 if x is None. Otherwise return x.

Caution: don't confuse optional arguments (that can be skipped at the function call) with arguments of Optional type (that cannot be skipped, but can take value of None).

Python

from typing import Optional

def foo(x: Optional[int]):
    #x = x or 123  # not valid, foo(0) would give 321
    x = 123 if x is None else x
    print(x)

foo(321)  # 321
foo(0)    # 0
foo(None) # 123

Rust

fn foo(x: Option<i32>) {
    
    let x = match x {
        None => 123,
        Some(x) => x,
    };
    
    println!("x={}", x);
}

fn main() {
    foo(Some(321)); // x=321
    foo(Some(0));   // x=0
    foo(None);      // x=123
}

Alternatively, Into allows for a convenient definition where Somecan be skipped at the function call:

fn foo<T: Into<Option<i32>>>(x: T) {
   
    let x = x.into();
    let x = match x {
        None => 123,
        Some(x) => x,
    };
    
    println!("x={}", x);
}

fn main() {
    foo(Some(321)); // x=321
    foo(321);       // x=321
    foo(Some(0));   // x=0
    foo(0);         // x=0
    foo(None);      // x=123
}

Crystal

def foo(x : Int32?)
  # note that here only nil evaluates to false
  x = x || 123
  puts x
end

foo 321 # 321
foo 0   # 0
foo nil # 123

Arguments of Bool type need special attention. Short syntax above can provide unintended results. Universal alternative:

def bar(x : Bool?)
  # x = x || true # not valid, it always gives true
  x = x.nil? ? true : x
  puts x
end

bar false # false
bar true  # true
bar nil   # true