Search code examples
gf

What is the meaning of alias "@" in GF?


I have encountered alias sign inside RGL in this operation:

  mkRoot3 : Str -> Root3 = \fcl -> case fcl of {
      f@? + c@? + l => {f = f ; c = c ; l = l} ;
      _ => error ("mkRoot3: too short root" ++ fcl)
      } ;

What does it mean, and what's the use of it?


Solution

  • The character @ is used in pattern matching. The expression foo@bar means that you match something with the regex bar, and bind the result to variable foo.

    Let's first recap some ways you can pattern match a string without @:

    example1 : Str -> Str = \s -> case s of {
      "x"           => "the string is exactly x" ;
      "x" + _       => "the string starts with x" ;
      ?             => "the string is one character long" ;
      ? + ?         => "the string is two characters long" ;
      ("a"|"i"|"u") => "the string is a vowel" ;
      _             => "whatever, I'm bored"
      } ;
    

    In all of these, we are not reusing the string in the right-hand side. If you want to do that, you can just bind it into a variable, like this—not yet using @ , because we are simply matching the start and the end of a string:

    example2 : Str -> Str = \s -> case s of {
      "x" + rest  => "the string starts with x and ends with" ++ rest ;
      start + "x" => "the string starts with" ++ start ++ "and ends with x" ;
      _           => "..." } ;
    

    Finally, if you want to match something to a regular expression and use whatever matches the regex on the RHS, now you need to use @:

    example3 : Str -> Str = \s -> case s of {
      v@("a"|"i"|"u") => "the string is the vowel" ++ v ;
      a@?             => "the string is one character long:" ++ a  ;
      a@? + b@?       => "the string is two characters long:" ++ a ++ "followed by" ++ b ;
      _               => "..." } ;
    

    If you just tried to match a + b => … , or any other pattern that only contains variables, it wouldn't match words that are exactly 2 characters long. Instead it would just match empty string to one of them and the full string to the other.

    So matching the regex ?, which matches exactly one character, and then binding the result to a variable, is the only way you can match something with exact length, and then reuse the matched character/string on the right-hand side.

    You can read more on pattern matching at http://www.grammaticalframework.org/doc/gf-refman.html#pattern-matching .