В большинстве объектно-ориентированных языков программирования точка используется и для полей (user.name
) и для методов (stream.write(s)
), что приводит к двусмысленности, поскольку в поле m.sin
вообще-то может храниться функция, и её вообще-то может хотеться применить к какому-то аргументу m.sin(x)
, что выглядит точно как вызов метода, но устроено совершенно по-другому: метод получает в распоряжение объект, относительно которого вызывается, функция вообще говоря нет.
Синтаксически я считаю идеальным использовать для методов треугольничек вправо вместо точки.
То есть point.x, или s.length, или list.size, но file ▸close и
files ▸filter { it.size > 0 } ▸map { it.name }
И особенно
n ▸elim {
is Zero ↦ 1
is Positive ↦ it · this(it.prev)
}
Мне вообще нравится использовать ▸ как оператор обратного применения, то есть x ▸ f
:= f(x)
, и это очень хорошо сочетается с применением ▸ без пробела справа в качестве замены точки при вызове методов.
Дело в том, что если мы имеем дело с данными (такими как натуральное число n или список files), то “методы” это на самом деле поля из объекта-компаньона, применённые сперва к аргументам справа, а потом к значению слева. То есть,
n ▸elim(motive)
// := n ▸ Nat.elim(motive)
files ▸filter { it.size > 0 } ▸map { it.name }
// := files ▸ List.filter { it.size > 0 } ▸ List.map { it.name }.
Отмечу, что в языке с тайпклассами переменный тип T
может иметь объект-компаньон:
fun<T : Serializable> foo(t : T) {
...
t ▸serialize
// := t ▸ T.serialize
}
fun<C<T> : Functorial> foo(t : C<Int>) {
...
t ▸map {it + 1}
// := t ▸ C.map {it + 1}
}