Regex — Regular Expressions with Pattern Matching

GALA’s regex package wraps Go’s regexp with a functional API and pattern matching extractors. Capture groups destructure directly into variables inside match expressions — no manual group indexing.

import "martianoff/gala/regex"
import . "martianoff/gala/std"
import . "martianoff/gala/collection_immutable"

Compilation

// Safe compilation — returns Try[Regex]
val r = regex.Compile("\\d+")
r.ForEach((re) => Println(re.Matches("abc123")))

// Panicking compilation — for known-good patterns
val digits = regex.MustCompile("\\d+")

Invalid patterns return Failure instead of panicking:

val bad = regex.Compile("[invalid")
Println(bad.IsFailure())  // true

Matching and Searching

val digits = regex.MustCompile("\\d+")

digits.Matches("abc123")            // true
digits.Matches("no digits")         // false

digits.FindFirst("abc 123 def")     // Some("123")
digits.FindAll("a1 b2 c3")         // Array("1", "2", "3")

Replace and Split

val digits = regex.MustCompile("\\d+")

digits.ReplaceAll("Call 555-1234", "***")   // "Call ***-***"
digits.Split("a1b2c3")                      // Array("a", "b", "c")

Capture Groups

FindGroups returns the first match with all capture groups:

val dateRegex = regex.MustCompile("(\\d{4})-(\\d{2})-(\\d{2})")
val groups = dateRegex.FindGroups("2024-01-15")
// Some(Array("2024-01-15", "2024", "01", "15"))

Pattern Matching with Array Destructuring

The real power of GALA’s regex is in match expressions. The Unapply method extracts capture groups (excluding the full match) and returns them as an Array. Combined with Array sequence patterns, each group destructures into its own variable:

val dateRegex = regex.MustCompile("(\\d{4})-(\\d{2})-(\\d{2})")

val result = "2024-01-15" match {
    case dateRegex(Array(year, month, day)) => s"$year-$month-$day"
    case _ => "not a date"
}
// "2024-01-15"

Email Extraction

val emailRegex = regex.MustCompile("([\\w.]+)@([\\w.]+)")

val parts = "user@example.com" match {
    case emailRegex(Array(user, domain)) => s"User: $user, Domain: $domain"
    case _ => "not an email"
}
// "User: user, Domain: example.com"

Multiple Patterns

Combine regex extractors with other match patterns:

val dateRegex = regex.MustCompile("(\\d{4})-(\\d{2})-(\\d{2})")
val timeRegex = regex.MustCompile("(\\d{2}):(\\d{2}):(\\d{2})")

func parseTimestamp(s string) string = s match {
    case dateRegex(Array(y, m, d)) => s"Date: $y/$m/$d"
    case timeRegex(Array(h, m, sec)) => s"Time: $h:$m:$sec"
    case _ => "unknown format"
}

API Reference

Method Description
regex.Compile(pattern) Safe compilation, returns Try[Regex]
regex.MustCompile(pattern) Panicking compilation
Matches(s) Test if string matches
FindFirst(s) First match as Option[string]
FindAll(s) All matches as Array[string]
FindGroups(s) First match with groups as Option[Array[string]]
ReplaceAll(s, replacement) Replace all matches
Split(s) Split string by pattern
Unapply(s) Pattern matching extractor, returns Option[Array[string]]

Further Reading