Здравствуйте, Sinclair, Вы писали:
S>А вот так нельзя? Или можно, но читается хуже?
S>S>Compare(xs : string, ys : string) : int
S>{
S> | (x : tailA, x : tailB) => Compare(tailA, tailB) // префиксы равны, продолжаем рекурсивно...
S> | (x : tailX, y : tailY) => x - y // префиксы не равны
S> | ([], _ : _) => 1 // xs содержит пустой список, а ys - нет.
S> | (_ : _, []) => -1 // наоборот
S> | ([], []) => 0 // все символы равны и списки пусты
S>}
S>
Так получается бессмыслица. Конструкция x : tailA означает образец не пустого списка где первый элемент помещается в локальную переменную x типа строка, а хвост списка в переменную tailA. Строка при этом представляется в виде однонаправленного связанного списка.
В твоем коде первая строка попросту теряет первые элементы списков и безусловна начинает сравнивать их хвосты. Вторая строка у тебя никогда не выполнится и компилятор просто не должен позволить скомпилировать этот код. В моем же примере у паттернов есть гуарды when x != y и x == y. Так что секция срабатывает только при когда они вычисляются в true. Так как условия взаимно исключающие, выполнится одна из двух секций. Паттерн _ : _ означает любой не пустой список (т.е. имеющий один или более элементов). _ — означает безымянная переменная сопоставляемая с чем угодно. [] означает пустой список. Таким образом мы
| (x : tailX, y : tailY) when x != y // это паттерн сопоставляется когда оба списка не пусты и первые символы строки не равны.
| (x : tailX, y : tailY) when x == y // это паттерн сопоставляется когда оба списка не пусты и первые символы строки равны.
| ([], _ : _) => 1 // это паттерн сопоставляется когда первый список пуст, а второй содержит по меньшей мере один элемент
| (_ : _, []) => -1 // это паттерн сопоставляется когда первый список содержит по меньшей мере один элемент, а второй пуст
| ([], []) => 0 // это паттерн сопоставляется когда оба списка пусты
Сумма всех паттернов с гуардами охватывает все возможные значени переменных xs и ys.