Учтите следующее:
if(a == b or c)
На большинстве языков это должно быть записано как:
if(a == b or a == c)
что немного громоздко и повторяет информацию.
Я знаю, что мой приведенный выше пример синтаксиса немного неуклюж, но я уверен, что есть лучшие способы донести эту идею.
Почему больше языков не предлагают это? Есть ли проблемы с производительностью или синтаксисом?
a == b or c
, и это даже не очень хорошо ИМХО.Ответы:
Синтаксическая проблема заключается в том, что он требует синтаксиса.
Какой бы синтаксис ни был у вашего языка, люди, использующие язык, должны выучить его. В противном случае они рискуют увидеть код и не знать, что он делает. Таким образом, обычно считается хорошей вещью, если язык имеет простой синтаксис, который четко обрабатывает множество случаев.
В вашем конкретном примере вы пытаетесь использовать инфиксный оператор (функция, которая принимает два аргумента, но записана
Argument1 Operator Argument2
) и пытаетесь расширить его до нескольких аргументов. Это не очень хорошо работает, потому что весь смысл инфиксных операторов, если таковой имеется, состоит в том, чтобы поместить оператор прямо между двумя аргументами. Расширение до,(Argument1 Operator Argument2 MagicallyClearSymbol Argument3...)
кажется, не добавляет много ясностиEquals(Arg1,Arg2,...)
. Infix также обычно используется для эмуляции математических соглашений, с которыми знакомы люди, что было бы неверно для альтернативного синтаксиса.С вашей идеей не возникнет никаких особых проблем с производительностью, кроме того, что анализатору придется иметь дело с грамматикой с другим или двумя производственными правилами, что может незначительно повлиять на скорость синтаксического анализа. Это может иметь некоторое значение для интерпретируемого или JIT-компилируемого языка, но, вероятно, не большая разница.
Большая проблема с этой идеей состоит в том, что создание множества особых случаев на языке, как правило, является плохой идеей .
источник
.
. Таким образом, они будут написаны какarg1 op (arg2, arg3)
. Не совсем красиво, но нужно в некоторых местах в контексте этого языка.if my_var in (a, b)
тогда? разве это не вопрос использования правильного инструмента для работы?a == b or c
а другим нужноa == b or c but not d
. ИМО, вот где полезные функции / библиотеки приходят на помощь.f().Equals(a,b,c)
; можно было бы оценить, что(var temp=f(); temp.Equals(a)||temp.Equals(b)||temp.Equals(c))
этот синтаксис был бы идеальным, но если бы он оценивался так,int[] arr = {a,b,c}; f().Equals(arr);
это было бы не очень хорошо, особенно если для каждого вызова нужно было создавать новый массив.Потому что это не проблема, и ее решение приносит практически нулевую выгоду, но ее реализация приносит ненулевые затраты.
Существующие функции, основанные на диапазоне, и такие, которые предлагает практически каждый язык, могут прекрасно работать в этой ситуации, если они масштабируются до размера,
a == b || a == c
который не позволяет их сократить.источник
in_array($a, [$b, $c, $d, $e, $f])
. : PНекоторые языки имеют такие функции. Например, в Perl6 мы можем использовать соединения , которые являются «суперпозициями» двух значений:
Соединения позволяют нам выразить операции над набором данных довольно лаконично, подобно тому, как скалярные операции распространяются по коллекциям в некоторых языках. Например, используя Python с numpy, сравнение можно распределить по всем значениям:
Однако это работает только для выбранных примитивных типов.
Почему развязки проблематичны? Поскольку операции над соединением распределяются по содержащимся значениям, сам объект соединения ведет себя как прокси-сервер для вызовов методов - то, с чем могут справиться немногие системы типов, кроме утки.
Проблем системы типов можно избежать, если такие соединения разрешены только в качестве специального синтаксиса вокруг операторов сравнения. Но в этом случае они настолько ограничены, что не добавляют достаточной ценности для добавления к любому здравомыслящему языку. Такое же поведение может быть выражено с помощью операций набора или написания всех сравнений вручную, и большинство языков не верят в добавление избыточного синтаксиса, если уже есть идеальное решение.
источник
2 in [1, 2, 3]
. С другой стороны, если у numpy есть.all()
или что-то, эквивалентный простой питон не так лаконичен.==
оператор, мы также можем использовать<
вместо него - где вашin
сейчас? Перекрестки являются более общими , чем членство набора тестов, поскольку операции на стыке распределить по всем членам -(x|y).foo
этоx.foo|y.foo
, пока узел не будет , наконец , рухнул на одно значение. Предоставленный код NumPy показывает точно эквивалентный, но более подробный перевод переходов Perl6, предполагая примитивные типы.В языки с макросами легко добавить что-то подобное, если его там еще нет. Рассмотреть ракетку
В других языках без метапрограммирования, возможно, вы можете переформулировать это как проверку членства в наборе / списке, возможно:
источник
В некоторых (популярных) языках
==
оператор не транзитивен. Например, в JavaScript0
равно''
и'0'
, и , но тогда''
и'0'
не равны друг другу. Больше таких причуд в PHP.Это означает, что
a == b == c
это добавит еще одну двусмысленность, потому что это может дать другой результат в зависимости от того, интерпретируется ли он как(a == b) & (a == c)
или(a == b) & (a == c) & (b == c)
.источник
На большинстве языков это должно быть легко достижимо путем написания
In
функции, так зачем делать ее частью реального языка?Линк, например, имеет
Contains()
.Хорошо, для всех вас, педанты, вот моя реализация в C #:
источник
a == b || a == c
несколько раз, может быть , пришло время дляequals_any(a, {b, c})
if (a > (b or c))
иif (a mod (b or c) == 2)
.i
переменных. И в целом это, кажется, написано после того, как у вас был долгий день :) Потому что включениеreturn true
иreturn false
внутри, и внутри цикла означает, что нет никакого способа, которым он когда-либо выйдет за пределы первой итерации. Ты сравниваешь только с первымvalue
. Кстати, почему бы не использовать,Any
как предложил @Bob, и упростить это доreturn values.Any(value => Object.Equals(obj, value));
«if (a == b или c)» работает в большинстве языков: если a == b или c не отрицательно, равно нулю или нулю.
Жаловаться, что это многословно, упускает суть: вы не должны складывать дюжину вещей в условные выражения. Если вам нужно сравнить одно значение с произвольным числом других значений, то создайте подпрограмму.
источник
c
вычисляется как логическое значение, то почти любой язык может обрабатыватьa == b || c
:)if(a == b or c)
. Мне нужно сделать перерыв, я думаю ...: Pif (a == b or c)
является псевдокодом, чтобы проверить,a
равенb
илиa
равенc
. Он не предназначен для проверки того, чтоc
это не ноль.Обычно вы хотите сохранить синтаксис минимальным и вместо этого позволить таким конструкциям определяться в самом языке.
Например, в Haskell вы можете преобразовать любую функцию с двумя или более аргументами в инфиксный оператор, используя обратные ссылки. Это позволяет вам написать:
где
elem
обычная функция принимает два аргумента - значение и список значений - и проверяет, является ли первый элементом второго.Что делать, если вы хотите использовать
and
вместоor
? В Haskell вы можете просто использовать следующее вместо ожидания, пока поставщик компилятора реализует новую функцию:источник
Некоторые языки предлагают это - до некоторой степени.
Может быть, не как ваш конкретный пример, но возьмем, например, строку Python:
Итак, некоторые языки подходят для множественных сравнений, если вы правильно их выражаете.
К сожалению, это не работает так, как вы ожидаете, для сравнения.
«Что вы имеете в виду, что он возвращает либо True, либо 4?» - прокат за тобой
Одним из решений в этом случае, по крайней мере с Python, является использование его немного по-другому:
РЕДАКТИРОВАТЬ: следующее также будет делать нечто подобное, снова в Python ...
Таким образом, какой бы язык вы ни использовали, возможно, вы этого не сделаете, просто вы должны сначала поближе познакомиться с тем, как на самом деле работает логика. Как правило, это просто вопрос знания того, что вы на самом деле «просите», чтобы язык сказал вам.
источник
Метод indexOf, используемый в массиве Array, который есть практически во всех языках, позволяет сравнивать значение с несколькими другими, поэтому, я думаю, специальный оператор не имеет особого смысла.
В JavaScript, который будет писать:
источник
Вы спрашиваете, почему мы не можем сделать это:
if(a == b or c)
Python делает это очень эффективно, фактически наиболее эффективно с
set
:Для проверки членства 'set' проверяет, что хэши элемента одинаковы, и только после этого сравниваются на равенство, поэтому элементы b и c должны быть хэшируемыми, в противном случае список напрямую сравнивается на равенство:
источник
Языки в стиле APL позволяют сравнивать скаляр с каждым элементом вектора за одну операцию. Это производит логический вектор. Например, я хотел бы безбожно рекламировать свой минимально-функциональный калькулятор apl, inca ( онлайн-переводчик ).
Чтобы свести это к одному значению, мы можем сделать включение или путем суммирования и проверки на ненулевое значение.
Итак, как говорят другие ответы, проблема в синтаксисе. В какой - то степени, синтаксические решения были найдены, на , возможно , тяжелой стоимости обучения парадигму массива.
источник