Я бы предположил, что с учетом X + Y
компилятор должен искать как X.op_plus(Y)
, так и Y.op_added_to(X)
;каждая реализация должна включать атрибут, указывающий, должна ли она быть «предпочтительной», «нормальной», «резервной» реализацией, и, необязательно, также указывающая, что она является «общей».Если обе реализации определены, и они имеют разные приоритеты (например, «предпочтительный» и «нормальный»), используйте тип для выбора предпочтения.Если оба определены как имеющие одинаковый приоритет, и оба являются «общими», предпочтение отдается форме X.op_plus(Y)
.Если оба определены с одним и тем же приоритетом и не являются «общими», отметьте ошибку.
Я бы предположил, что возможность расставлять приоритеты по перегрузкам и преобразованиям будет ИМХО очень важной функцией для языка.Для языков бесполезно грызть неоднозначные перегрузки в тех случаях, когда оба кандидата будут делать одно и то же, но языки должны грызть в тех случаях, когда две возможные перегрузки будут иметь разные значения, каждое из которых будет полезно в определенных контекстах.Например, учитывая someFloat==someDouble
или someDouble==someLong
, компилятор должен squawk, поскольку может оказаться полезным знать, совпадают ли числовые величины, представленные двумя значениями, и также может быть полезно знать, является лилевый операнд содержит лучшее возможное представление (для своего типа) значения в правом операнде.Java и C # не отмечают неоднозначность в любом случае, вместо этого выбрав использовать первое значение для первого выражения и второе для второго, хотя любое значение может быть полезно в любом случае.Я бы предположил, что было бы лучше отказаться от таких сравнений, чем от того, что они реализуют противоречивую семантику.
В целом, я бы предложил в качестве философии, что хороший дизайн языка должен позволять программисту указывать, что важно, а что нет«т.Если программист знает, что определенные «неоднозначности» не являются проблемами, но есть и другие, должно быть легко иметь флаг компилятора, но не первый.
Добавление
Я кратко просмотрел ваше предложение;он видит, что вы ожидаете, что привязки будут полностью динамичными.Я работал с таким языком (HyperTalk, около 1988 года), и это было «интересно».Рассмотрим, например, что «2X» <«3» <4 <10 <«11» <«2X».Двойная диспетчеризация иногда может быть полезна, но только в тех случаях, когда перегрузки операторов с различной семантикой (например, сравнения строк и чисел) ограничены работой с непересекающимися наборами вещей.Запретить неоднозначные операции во время компиляции - это хорошо, так как программист сможет указать, что предполагается.Наличие такой неоднозначности запускает ошибку времени выполнения, это плохая вещь, потому что программист может давно уйти к тому времени, когда ошибка появляется.Следовательно, я действительно не могу дать никаких советов о том, как выполнить двойную диспетчеризацию во время выполнения для операторов, кроме как сказать «не», если только во время компиляции вы не ограничите операнды комбинациями, где любая возможная перегрузка всегда будет иметь одинаковую семантику.. </p>
Например, если у вас был абстрактный тип «неизменяемый список чисел» с членом, сообщающим длину или возвращающим число по определенному индексу, вы можете указать, что два экземпляра равны, если они имеют одинаковую длину,и каждый для каждого индекса они возвращают одно и то же число.Хотя можно было бы сравнить любые два экземпляра на равенство, исследуя каждый элемент, это могло бы быть неэффективно, если бы, например, один экземпляр был типом «BunchOfZeroes», который просто содержал целое число N = 1000000 и фактически не сохранял никаких элементов, идругой был "NCopiesOfArray", который содержал N = 500000 и {0,0} как массив для копирования.Если многие экземпляры этих типов будут сравниваться, эффективность можно было бы повысить, если бы такие сравнения вызывали метод, который после проверки общей длины массива проверяет, содержит ли массив «шаблон» какие-либо ненулевые элементы.Если это не так, то он может быть представлен как равный массиву с нулями без необходимости выполнять 1 000 000 сравнений элементов.Обратите внимание, что вызов такого метода двойной диспетчеризацией не изменит поведения программы - он просто позволит выполнить ее быстрее.