Skip to content

Instantly share code, notes, and snippets.

@maiha
Created February 15, 2021 04:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maiha/ebccd8ff5e4cbf3add17a2db2f8592fc to your computer and use it in GitHub Desktop.
Save maiha/ebccd8ff5e4cbf3add17a2db2f8592fc to your computer and use it in GitHub Desktop.

Let's consider some value holder. For example, Try monad. For simplicity, Let's assume it only works with Int32.

record Success, value : Int32
record Failure, value : Exception

# some try object
try : Success | Failure = Success(1)

It usually looks like this by using crystal's case statement.

# Extract it.
case try
when Success
  v = try.value
  puts "Got #{v}"
when Failure
  e = try.value
  puts "Oops, #{e}"
end

Generally, we can write intuitively in languages with extractor, such as Scala, Rust, and more recently, Ruby.

Scala

try match {
  case Success(v) => printf("Got  %s\n", v)
  case Failure(e) => ...

Rust

match try {
    Success(v) => println!("Got {:?}", v),
    Failure(e) => ...

Ruby 3

case try
in Success(value: v); puts "Got #{v}"
in Failure(value: e); ...

But we Crystal have powerful macros. Let's define it by myself!

module Try
  macro match(try)
    case {{try}}
    {{yield}}  # To be precise, parse 'when' here and extract the value
    end
  end
end

Try.match(try) {
  when Success(v) then puts "Got #{v}"
}

How elegant! But we will get...

Error: expecting token '}', not 'when'

This style is called Partial Function in Scala. That is first class object and it can be applied to case sentences.

val pf:PartialFunction[Try,Int32] = {
  case Success(v) => printf("Got  %s\n", v)
  case Failure(e) => ...
}

my_try_match(pf) // works

Thus, my wishes are.

  1. Crystal will support Extractor. (best)
  2. Crystal will support Partial Function for AST. (second best)
@maiha
Copy link
Author

maiha commented Feb 15, 2021

Since I had no choice, I now use the local variable TypeDeclaration 😃
https://github.com/maiha/try.cr/blob/master/spec/match_spec.cr#L66-L71

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment