# Phil 455: Dissecting, Stinkiness, Winkiness

Let’s review some of the ways we’re talking about our piecemeal, recursive definitions expressed using `dissect`. Recall that something that looks like this:

``````foo =def {
...
}``````

is always shorthand for:

foo (α) =def dissect α { ... }

Here is a diagram of a definition, with some of its parts labeled:

Remarks:

• The bold variables are called “pattern variables.” They are orange where they occur in patterns, and are there waiting for dissected parts of an input argument to be assigned to them. They are black where they’re being used, and there expand to whatever value they’ve been assigned.
• An input argument is said to “match” a clause if there’s some way of assigning any variables in that clause’s pattern to parts of that argument (what’s being dissected) so that the pattern with its variables so assigned equals the input argument, and any attached guard condition is also satisfied.
• We say that some arguments are “legal” when they aren’t excluded by the `assuming {...}` rule. (Often there are also some additional implicit assumptions, such as that some arguments will always be `∈ ℕ`, others will always be strings over some alphabet `Σ`, and so on.)
• I’ll say that a clause “delivers a result” even in cases where it explicitly declares that the result is `undefined`. If on the other hand, a clause applies some function to an argument where no result is ever delivered (for example, because of a never-ending recursion), I’ll describe that as the result “being implicitly undefined.” When no clause applies to some legal argument, that’s also a case where the result is implicitly undefined.
• I’ll say that several clauses “deliver conflicting results” when (i) some of them explicitly declare the result to be undefined, but others attempt to deliver a defined result; or (ii) some of the clauses attempt to deliver different defined results.

## Stinky and Winky

This table may help get clearer on the relationship between the categories of “being stinky” and “being winky”:

The fact that some arguments aren’t legal because they fail to satisfy an `assuming {...}` rule won’t by itself make a definition stinky. Neither will the fact that the definition explicitly declares the result for some legal argument to be `undefined`.

Here are ways that a definition does get to be stinky and not winky (the worst category):

• The definition is implicitly undefined for some legal argument, either because (a) the argument matches no clause, or because (b) there’s no way to dissect it where a result is delivered (because of a never-ending recursion).
• A legal argument can match several dissect clauses of the same precedence, or can be dissected in different ways to match a single clause, so that (c) the different ways of matching deliver conflicting results.

Here is how a definition gets to be merely winky (but still stinky, the middling category):

• A legal argument matches several dissect clauses of the same precedence, or can be dissected in different ways to match a single clause, and (d) some of these never deliver a result (because of a never-ending recursion), but others do deliver results, which never conflict.

Here are the examples I gave in our previous class (over Zoom):

``````foo =def {
λ α ⁀ β  if α = "x" ! true;
λ α ⁀ β  if β = "x" ! true;
γ . false
}``````

That definition isn’t stinky. With arguments (“input values”) like `"x"` and `"xax"`, multiple clauses with precedence `!` will match, but they always deliver the same result.

``````bar =def {
λ "" ! true;
λ α ⁀ β  if isUnit(α) . bar(β)
}``````

That definition isn’t stinky. It will recurse in a specific predetermined way on ever-shrinking suffixes of its initial argument, until the first clause matches. In that definition, the result for any argument will eventually be `true`.

``````qux1 =def {
λ "" ! true;
λ α ⁀ β  if isUnit(α) . undefined
}``````

That definition isn’t stinky, because although it has no defined result for arguments that aren’t the empty string, it explicitly says so.

``````qux2 =def {
λ "" ! true;
λ α ⁀ β  if isUnit(α) . qux2(α)
}``````

This definition is stinky, because although it also has no defined result for arguments that aren’t the empty string, it doesn’t explicitly declare this. Instead it enters a never-ending recursion. (Contrast `qux2`, which will keep recursing on the same prefix `α`, to `bar` which recurses on the shrinking suffix `β`.)

Finally:

``````bez =def {
λ "" ! true;
λ α ⁀ β . bez(β)
}``````

This is like `bar`, but we no longer require that `α` be non-empty. This definition is also stinky, but at the same time it at least manages to be winky. There’s always a way to dissect the function’s argument that will deliver a result (and always the same result). For example, if we apply `bez` to the argument `"xy"`, that might recurse three times on the second clause, each time assigning `α` the value `""` and `β` the value `"xy"`. But then the next time through, it might assign `α` `"x"` and `β` `"y"`. It might then recurse fifteen times assigning `α` the empty string again, and then finally assigning `α` `"y"` and `β` `""`. Whereupon the final recursive call will deliver the result `true`.

## Nondeterminism

“Nondeterminism” is a label used in this literature to describe the kind of thing that happens in our dissect-definitions when more than one clause can match, or when a single clause can match against different ways of dissecting the input value.

Don’t let this label mislead you into thinking it has anything to do with chances or probabilities. In these contexts, it just means that there are multiple paths forward.

• If any of the paths deliver an answer, that is required (on pain of stinkiness) to be the same answer (including if the answer is an explicit `undefined`); and this is understood to be the answer for the whole tree of available paths.
• It may be that some paths never deliver an answer (recurse without end), and it may be that (unlike in `bez`) you can’t tell in advance which paths those will be.