ObjectScript, разработаем спецификацию совместно: операторы сравнения

в 1:05, , рубрики: api, javascript, Lua, ObjectScript, objectscript api, open source, php, Программирование, спецификация, метки: , , , , , ,

ObjectScript — новый встраиваемый и очень легкий объектно-ориентированный язык программирования с открытым исходным кодом. ObjectScript расширяет возможности таких языков, как JavaScript, Lua и PHP. Синтаксис в основном взят из JavaScript, множественное присваивание — из Lua, работа со свойствами — из PHP.

Проект ObjectScript совсем молодой, только недавно появились первые рабочие и стабильные версии. Тем не менее вопрос о спецификации некоторых моментов языка не решен окончательно и находится в стадии проработки. Например, операторы сравнения в разных скриптовых языках работают по-разному, это зависит от того, какие типы данных участвуют в сравнении и какой алгоритм используется в конкретном языке программирования.

Вопрос довольно щекотливый, т.к. от результата булевского выражения зависит, не много не мало, выполнится кусок кода или нет. Русская пословица «одна голова хорошо, а много лучше» подсказывает мне, что лучше обратится к программерскому сообществу и разобраться наверняка в том, какое поведения при сравнении (это операторы >=, >, <=, <, ==, !=) разных типов данных в скриптовом языке является наиболее уместным. Выработать коллегиональное решение и закрепить результат в спецификации ObjectScript.

ObjectScript поддерживает перегрузку операторов сравнения для объектов, но я предлагаю в текущем вопросе остановится на работе операторов сравнения только для примитивных типов данных, это null, boolean, number и string.

Как работает PHP при сравнении

PHP преобразует аргументы в числовые типы, если один из аргументов — число. null преобразуется в 0, true в 1, false в 0, string преобразуется в число до первого невалидного символа, после чего возвращается число (получившееся на текущий момент). В итоге если оба аргумента числа, происходит численное сравнение, если строки — строковое.

Выполним следующий скрипт на PHP:

echo "'a' > 'b' t--> "; var_dump('a' > 'b');
echo "'a' < 'b' t--> "; var_dump('a' < 'b');
echo "'a' > 1 t--> "; var_dump('a' > 1);
echo "'a' < 1 t--> "; var_dump('a' < 1);
echo "'1' > 1 t--> "; var_dump('1' > 1);
echo "'1' < 1 t--> "; var_dump('1' < 1);
echo "'+2.9' > 1 t--> "; var_dump('+2.9' > 1);
echo "'+2.9' < 1 t--> "; var_dump('+2.9' < 1);
echo "'2.9' > 1 t--> "; var_dump('2.9' > 1);
echo "'2.9' < 1 t--> "; var_dump('2.9' < 1);
echo "true > 1 t--> "; var_dump(true > 1);
echo "false < 1 t--> "; var_dump(false < 1);
echo "null > 1 t--> "; var_dump(null > 1);
echo "null < 1 t--> "; var_dump(null < 1);

он выведет:

'a' > 'b'       --> bool(false)
'a' < 'b'       --> bool(true)
'a' > 1         --> bool(false)
'a' < 1         --> bool(true)
'1' > 1         --> bool(false)
'1' < 1         --> bool(false)
'+2.9' > 1      --> bool(true)
'+2.9' < 1      --> bool(false)
'2.9' > 1       --> bool(true)
'2.9' < 1       --> bool(false)
true > 1        --> bool(false)
false < 1       --> bool(true)
null > 1        --> bool(false)
null < 1        --> bool(true)

Как работает JavaScript при сравнении

JavaScript также преобразует аргументы в числовые типы, если один из них — число, и делает это по следующим правилам: null в 0, undefined в NaN, true в 1, false в 0, string преобразуется в число, если в строке встречается невалидный символ, то возвращается NaN. В итоге, если оба аргумента числа (NaN — тоже число), то сравнение происходит обычным математическим способом, но нужно иметь в виду, что любое сравнение с NaN всегда возвращает false. Например, при штатном программировании на PHP, NaN редко всплывает и его практически никогда не обрабатывают отдельно, вот и строки на PHP будут преобразованы в валидное число в любом случае, в случае ошибки вернется 0, а вот в JS ситуация другая.

Если при сравнении аргументы — строки, то происходит строковое сравнение.

PHP не имеет типа данных undefined, а только null. При конвертировании скриптов c PHP на JS, мы бы всегда задумывались, что использовать на JS вместо PHP-шного null, то ли JS-ый null, то ли JS-ый undefined. Поэтому мы обязаны в тест на JS включить undefined и проверить, как он работает в сравнении с числом.

Выполним следующий код на JS в браузере:

console.log("'a' > 'b' t--> ", 'a' > 'b');
console.log("'a' < 'b' t--> ", 'a' < 'b');
console.log("'a' > 1 t--> ", 'a' > 1);
console.log("'a' < 1 t--> ", 'a' < 1);
console.log("'1' > 1 t--> ", '1' > 1);
console.log("'1' < 1 t--> ", '1' < 1);
console.log("'+2.9' > 1 t--> ", '+2.9' > 1);
console.log("'+2.9' < 1 t--> ", '+2.9' < 1);
console.log("'2.9' > 1 t--> ", '2.9' > 1);
console.log("'2.9' < 1 t--> ", '2.9' < 1);
console.log("true > 1 t--> ", true > 1);
console.log("false < 1 t--> ", false < 1);
console.log("null > 1 t--> ", null > 1);
console.log("null < 1 t--> ", null < 1);
console.log("undefined > 1 t--> ", undefined > 1);
console.log("undefined < 1 t--> ", undefined < 1);

в консоли будет выведено:

'a' > 'b'       --> false
'a' < 'b'       --> true
'a' > 1         --> false
'a' < 1         --> false
'1' > 1         --> false
'1' < 1         --> false
'+2.9' > 1      --> true
'+2.9' < 1      --> false
'2.9' > 1       --> true
'2.9' < 1       --> false
true > 1        --> false
false < 1       --> true
null > 1        --> false
null < 1        --> true
undefined > 1   --> false
undefined < 1   --> false

Как работает Lua при сравнении

Lua разрешает сравнивать только числа с числами, строки со строками. В противном случае выкидывает ошибку вида: attempt to compare number with string. Даже boolean сравнить с числом не выйдет, boolean с boolean сравнить тоже не выйдет. Вместо null в Lua используется nil. nil сравнить с числом не получится, nil c nil аналогично.

В общем на Lua тестирование как таковое провалилось по данному вопросу.

Как работает ObjectScript при сравнении

Если один из аргументов сравнения — строка, то происходит строковое сравнение. В противном случае (если аргументы — примитивные типы), то они конвертятся в числа и происходит математическое сравнение. null преобразуется в 0, true в 1, false в 0, строка полностью преобразуется в число, если в строке есть не валидные символы, то возвращается 0.

В итоге код на OS:

print("'a' > 'b' t--> ", 'a' > 'b')
print("'a' < 'b' t--> ", 'a' < 'b')
print("'a' > 1 t--> ", 'a' > 1)
print("'a' < 1 t--> ", 'a' < 1)
print("'1' > 1 t--> ", '1' > 1)
print("'1' < 1 t--> ", '1' < 1)
print("'+2.9' > 1 t--> ", '+2.9' > 1)
print("'+2.9' < 1 t--> ", '+2.9' < 1)
print("'2.9' > 1 t--> ", '2.9' > 1)
print("'2.9' < 1 t--> ", '2.9' < 1)
print("true > 1 t--> ", true > 1)
print("false < 1 t--> ", false < 1)
print("null > 1 t--> ", null > 1)
print("null < 1 t--> ", null < 1)

выведет следующее:

'a' > 'b'       -->     false
'a' < 'b'       -->     true
'a' > 1         -->     true
'a' < 1         -->     false
'1' > 1         -->     false
'1' < 1         -->     false
'+2.9' > 1      -->     false
'+2.9' < 1      -->     true
'2.9' > 1       -->     true
'2.9' < 1       -->     false
true > 1        -->     false
false < 1       -->     true
null > 1        -->     false
null < 1        -->     true

Итого

Сведем полученные результаты в одну таблицу:

ObjectScript, разработаем спецификацию совместно: операторы сравнения

Вопрос знатокам

Так какое поведение при сравнении следует считать эталонным для скриптового языка программирования и закрепить в спецификации ObjectScript?

Высказывайтесь пожалуйста в комментариях, т.к. уверен, что каждый голос будет на счету и возможно именно ваше слово будет решающим в выборе дальнейшего пути развития ObjectScript.

Другие релевантные статьи об ObjectScript:

Автор: evgeniyup


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js