Ответ 1
Конечная причина в том, что если вы выполняете как программирование общего назначения, так и численные вычисления, полезно иметь большой набор бинарных операторов. Например, если вы храните цифры в двумерных массивах, вы можете захотеть умножить массивы по элементам или вы можете вычислить матричный продукт двух массивов. В Matlab эти два оператора .*
и *
; в R они *
и %*%
. Python сопротивлялся попытки добавлять новые операторы, и поэтому numpy дифференцирует между двумя видами продукта, имея два класса: класс массива умножается по элементам, матричный класс умножается в линейной алгебре чувство.
Другим примером из Python является то, что для списков плюс означает конкатенацию: [1,2,3]+[4,5] == [1,2,3,4,5]
. Но для numpy массивов плюс означает элементное дополнение: array([1,2]) + array([4,5]) == array([5,7])
. Если вашему коду нужно обойти оба, вам нужно преобразовать между классами или использовать нотацию функций, что может привести к громоздкому коду, особенно в том случае, если речь идет о математике.
Поэтому иногда было бы удобно иметь больше доступных для использования операторов, и вы не можете заранее знать, к каким операторам относится конкретное приложение. Поэтому разработчики R решили рассматривать в качестве операторов все, что называется %foo%
, и существует несколько примеров: %in%
установлено членство, %x%
- произведение Кронекера, %o%
- внешнее произведение. Например, язык, который довел это до крайности, см. Fortress (раздел 16 спецификации начинается с правил для имен операторов).
В упомянутом вами сообщении в блоге автор использует ggplot2 графический пакет, который определяет %+%
как означающий какой-то сочетание двух сюжетных элементов. На самом деле, похоже, он добавляет метод к bare +
(который является общей функцией, поэтому вы можете определить, что это означает для определяемых пользователем объектов), но также определяет %+%
, чтобы вы могли использовать значение ggplot2 +
(что бы это ни было) для других объектов. Если вы установите ggplot2, введите require(ggplot2)
и ?`%+%`
, чтобы увидеть документацию этого оператора, и methods(`+`)
, чтобы увидеть, что новое определение было добавлено в +
.