next up previous contents
Next: Arrays Up: Maps and arrays Previous: Maps and arrays   Contents


Maps

As explained above, a map is defined as a ``set'' (built with the associative and commutative operator _,_) of entries. Notice that Entry, whose only constructor is the operator _|->_, is a subsort of Map.

The domain and codomain values of the map come from the parameters of the parameterized data type, both of them satisfying the theory TRIV and thus providing a set of elements.

The module MAP provides a constant undefined of the kind [Y$Elt] corresponding to the sort Y$Elt and representing the undefined result.

  fmod MAP{X :: TRIV, Y :: TRIV} is
    protecting BOOL .
    sorts Entry{X,Y} Map{X,Y} .
    subsort Entry{X,Y} < Map{X,Y} .

    op _|->_ : X$Elt Y$Elt -> Entry{X,Y} [ctor] .
    op empty : -> Map{X,Y} [ctor] .
    op _,_ : Map{X,Y} Map{X,Y} -> Map{X,Y}
         [ctor assoc comm id: empty prec 121 format (d r os d)] .
    op undefined : -> [Y$Elt] [ctor] .

    var  D : X$Elt .
    vars R R' : Y$Elt .
    var  M : Map{X,Y} .

The operator insert adds a new entry to a map, but when the first argument already appears in the domain of definition of the map, the second argument is used to update the map. Notice the use of matching and of the otherwise attribute to distinguish these two cases in a simple way. Furthermore, in the first case, an auxiliary operation $hasMapping is used to make sure that in the resulting map only one entry is associated with the given value. The operation $hasMapping checks whether a domain value actually has an associated entry in a map.

    op insert : X$Elt Y$Elt Map{X,Y} -> Map{X,Y} .
    eq insert(D, R, (M, D |-> R')) 
      = if $hasMapping(M, D) 
        then insert(D, R, M)
        else (M, D |-> R)
        fi .
    eq insert(D, R, M) = (M, D |-> R) [owise] .
    
    op $hasMapping : Map{X,Y} X$Elt -> Bool .
    eq $hasMapping((M, D |-> R), D) = true .
    eq $hasMapping(M, D) = false [owise] .

The lookup operator is represented with the notation _[_]. Again, matching and owise are used to distinguish whether or not the second argument appears in the domain of definition of the map provided as first argument. When the answer is affirmative an the map contains exactly one entry associated with such argument (as checked with the auxiliary operation $hasMapping), the result is the value provided in that entry. When the answer is negative or the map is not well defined because there is more than one entry associated with the same argument, the result is the constant undefined in the kind, with the self-explanatory meaning that in those cases the map is undefined on the given argument.

    op _[_] : Map{X,Y} X$Elt -> [Y$Elt] [prec 23] .
    eq (M, D |-> R)[D] 
      = if $hasMapping(M, D) then undefined else R fi .
    eq M[D] = undefined [owise] .
  endfm

We use the predefined views String and Nat (see Section 7.11.1) to define maps from strings to natural numbers, and do some sample reductions.

  fmod STRING-NAT-MAP is
    pr MAP{String, Nat} .
  endfm

  Maude> red in STRING-NAT-MAP :
           insert("one", 1, 
             insert("two", 2, insert("three", 3, empty))) .
  result Map{String,Nat}: "one" |-> 1, "three" |-> 3, "two" |-> 2

  Maude> red insert("one", 1, 
               insert("two", 2, 
                 insert("three", 3, empty)))["two"] .
  result NzNat: 2

  Maude> red insert("one", 1, 
               insert("two", 2, 
                 insert("three", 3, empty)))["four"] .
  result [FindResult]: undefined

  Maude> red ("a" |-> 3, "a" |-> 2)["a"] .
  result [FindResult]: undefined

The last reduction shows that the undesired repetition of a domain value in two entries of the same map also produces the undefined constant as result.


next up previous contents
Next: Arrays Up: Maps and arrays Previous: Maps and arrays   Contents
The Maude Team