Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.

## 10.6 Unification

In E, unification is a way of doing complicated, conditional assignments. It may also be referred to as pattern matching because that is what it does: it matches patterns and tries to fit values to the variables mentioned in those patterns. The result of a unification is true or false, depending on whether the pattern was successfully matched.

The basic form of a unification expression is:

```  expression <=> pattern
```

The only things that can be used in a pattern are constants and variable names, and lists of patterns. (Strictly speaking, lisp-cells are also allowed, but this variant of unification is beyond the scope of this Guide.) The pattern is matched against the expression as follows:

• If pattern is a constant then the match succeeds only if expression evaluates to the same value. So, the simple unification expression `x<=>1' is similar to an equality check `x=1'.
• If pattern is a variable name then the match is always successful and the variable is assigned the value of expression. So, the simple unification expression `1<=>x' is similar to an assignment `x:=1'.
• If pattern is a list then expression is assumed to be a list, and each element of pattern is taken to be a pattern to be (recursively) matched against the corresponding element (by index) of the expression list. The match succeeds only if the pattern list and the expression list are the same length and all the elements match. (It is a serious programming error if pattern is a list but expression does not represent a list. In this case, strange things may happen and the program may crash.)

So, the things in pattern that control whether a match succeeds are the constants and the lists.

If a match succeeds then all variables mentioned in the pattern will be assigned the appropriate values. However, if a match fails you should consider all variables involved in the pattern to have undefined values (so you may need to initialise them to safely use their values again). This is because the actual way that unification is implemented may not follow the rules above in the obvious way, but will have the same effect in the successful case and will affect only the variables mentioned in the pattern if the match fails.

For example, the following program shows a couple of simple unification expressions in use:

```PROC main()
DEF x, lt
x:=0
WriteF('x is \d\n', x)
lt:=[9,-1,7,4]

/* The next line uses unification */
IF lt <=> [9,-1,x,4]
WriteF('First match succeeded\n')
WriteF('1) x is now \d\n', x)
ELSE
WriteF('First match failed\n')
/* To be safe, reset x */
x:=0
ENDIF

/* The next line uses unification */
IF lt <=> [1,x,6,4]
WriteF('Second match succeeded\n')
WriteF('2) x is now \d\n', x)
ELSE
WriteF('Second match failed\n')
/* To be safe, reset x */
x:=0
ENDIF
ENDPROC
```

The first match will succeed in this example, and there will be a side-effect of assigning seven to `x`. The second match will not succeed because, for instance, the first element of `lt` is not one.

We can rewrite the above example without using the unification operator (to show why unification is so useful). This code follows the rules in one particular way, so is not guaranteed to have the same effect as the unification version if any of the matches fail.

```PROC main()
DEF x, lt, match
x:=0
WriteF('x is \d\n', x)
lt:=[9,-1,7,4]

/* The next lines mimic: lt <=> [9,-1,x,4] */
match:=FALSE
IF ListLen(lt)=4
IF ListItem(lt, 0)=9
IF ListItem(lt, 1)=-1
x:=ListItem(lt,2)
IF ListItem(lt, 3)=4 THEN match:=TRUE
ENDIF
ENDIF
ENDIF
IF match
WriteF('First match succeeded\n')
WriteF('1) x is now \d\n', x)
ELSE
WriteF('First match failed\n')
/* To be safe, reset x */
x:=0
ENDIF

/* The next lines mimic: lt <=> [1,x,6,4] */
match:=FALSE
IF ListLen(lt)=4
IF ListItem(lt, 0)=1
x:=ListItem(lt, 1)
IF ListItem(lt, 2)=6
IF ListItem(lt, 3)=4 THEN match:=TRUE
ENDIF
ENDIF
ENDIF
IF match
WriteF('Second match succeeded\n')
WriteF('2) x is now \d\n', x)
ELSE
WriteF('Second match failed\n')
/* To be safe, reset x */
x:=0
ENDIF
ENDPROC
```

Here's a slightly more complicated example, which shows how you might use patterns made up of nested lists. Remember that if the pattern is a list then the expression to be matched must be a list. If this is not the case (e.g., if the expression represents `NIL`) then your program could behave strangely or even crash your computer. A similar, but less disastrous, problem is if the converse happens: the pattern is not a list but the expression to be matched is a list. In this case the pointer (to the list) is matched against the pattern constant or assigned to the pattern variable.

```PROC main()
DEF x=10, y=-3, p=NIL:PTR TO LONG, lt, i
WriteF('x is \d, y is \d\n', x, y)
lt:=[[23,x],y]

/* This basically swaps x and y */
IF lt <=> [[23,y],x]
WriteF('First match succeeded\n')
WriteF('1) Now x is \d, y is \d\n', x, y)
ELSE
WriteF('First match failed\n')
/* To be safe, reset x and y */
x:=10;  y:=-3
ENDIF

/* This will make p point to the sub-list of lt */
IF lt <=> [p,-3]
WriteF('Second match succeeded\n')
WriteF('2) p is now \$\h (a pointer to a list)\n', p)
FOR i:=0 TO ListLen(p)-1
WriteF('   Element \d of the list p is \d\n', i, p[i])
ENDFOR
ELSE
WriteF('First match failed\n')
/* To be safe, reset p */
p:=NIL
ENDIF
ENDPROC
```

Go to the Next or Previous section, the Detailed Contents, or the Amiga E Encyclopedia.