Search code examples
smlsmlnj

Standard ML (smlnj): "constant" variables for pattern matching


I'm new to SMLNJ. This works:

case (tts t2) of
    (other, "<+") => parse_append t t2 ts pre c j
|   (other, "<<-") => parse_sample t t2 ts pre c j
|   (other, "<-") => parse_assign_or_sub t t2 ts pre c j
|   (_, _) => error t2 "parse_stmt: Expected sample, append or assignment operator."

(other is of type "datatype tokentype", t and t2 are tokens and tts maps a token to a pair (tokentype, content). The rest is context-specific and not important here.)

But it's not very modular. Especially as I'm matching against the same operators in multiple places and I don't want them repeated all over the place. So I attempted this, which doesn't work:

(* this should go in a separate file of declarations *)
structure Ops = struct
    val APPEND = "<+"
    val SAMPLE = "<<-"
    val ASSIGN = "<-"
end

(* this stays in the code *)
case (tts t2) of
    (other, Op.APPEND) => parse_append t t2 ts pre c j
|   (other, Op.SAMPLE) => parse_sample t t2 ts pre c j
|   (other, Op.ASSIGN) => parse_assign_or_sub t t2 ts pre c j
|   (_, _) => error t2 "parse_stmt: Expected sample, append or assignment operator."

Apparently you can't pattern-match against the value of a variable (which makes sense, in a way). Is there any kind of "constant" declaration I can apply to the operator definitions so that I can put their values in a separate module, or is there some other nice way to do this in SMLNJ?


Solution

  • You can make them constructors:

    datatype Op = APPEND | ...
    

    and then tokenize your stream

    datatype Token = Op of Op | Id of string | ...
    

    and then your pattern match can be

    case (tts t2) of
      (other, APPEND) => ...