cursorless icon indicating copy to clipboard operation
cursorless copied to clipboard

Support the concept of pattern matching

Open SCdF opened this issue 3 years ago • 2 comments

In Scala (and probably Haskell and other languages) there is a concept of pattern matching. This is similar to but not the same as destructoring, and similar to but not the same as switch statements.

A basic example that looks like a switch statement:

import scala.util.Random

val x: Int = Random.nextInt(10)

x match {
  case 0 => "zero"
  case 1 => "one"
  case 2 => "two"
  case _ => "other"
}

A slightly more complex example:

def showImportantNotification(notification: Notification, importantPeopleInfo: Seq[String]): String = {
  notification match {
    case Email(sender, _, _) if importantPeopleInfo.contains(sender) =>
      "You got an email from special someone!"
    case SMS(number, _) if importantPeopleInfo.contains(number) =>
      "You got an SMS from special someone!"
    case other =>
      showNotification(other) // nothing special, delegate to our original showNotification function
  }
}

So you have a match expression, which is something match {}, and inside the block you have cases, where on the left of the => is a pattern that you match against, and on the right is the resulting expression that gets evaluated.

it gets way more complicated than this, and you can use them in weird ways like:

scala> case class Count(count: Int)
defined class Count

scala> val Count(pulledOut) = Count(1)
pulledOut: Int = 1

scala> val counts = List(Count(1), Count(2), Count(3))
counts: List[Count] = List(Count(1), Count(2), Count(3))

scala> counts.map({case Count(c) => c})
res0: List[Int] = List(1, 2, 3)

Where you use patterns for destructoring, and can have an individual cases as partial function shorthand

We should work out what kind of language / keywords would be helpful in cursorless to let us maniuplate patterns.

SCdF avatar Jan 08 '22 15:01 SCdF

Related to #247

pokey avatar Jan 08 '22 16:01 pokey

  • I'd argue that the foo match {...} construct can be handled the same way as other case / switch statements outlined in https://github.com/cursorless-dev/cursorless/issues/579#issuecomment-1161627378
  • The val Count(pulledOut) = Count(1) can be handled like destructuring in Typescript:
    • Use "name" to select Count(pulledOut)
    • Also use "call" to select Count(pulledOut)

pokey avatar Aug 01 '22 11:08 pokey