k001
k001
:...
k001 [userpic]
code wtf

Вот такой эпический код сегодня встретился:

        assert '(( 1 <= level <= 5))'


В комментах желающие могут рассказать, почему это не работает. Завтра расскриню.

Да, это написано на bash, но на С будет примерно так же.

Comments

Предполагаю потому, что:

<= имеет левую ассоциативность, поэтому выражение 1 <= level будет вычислено первым; его результат (1 или 0 / true или false) всегда <= 5.

Это если я навскидку правильно помню последовательность вычислений на C. :-)

Это — на bash? А где жэ баксы (перед level)? Не, я вообще не понимаю, что имелось в виду, если это на bash.

Да, на C — очевидно, 1 <= level вернёт true либо false (не важно, что напрямую таких названий в C нет) — сравнивайте это с 5-ю наздоровье.

у баша есть много всякой доп. функциональности, в частности,

в частности, оператор (( ))

Всегда возвращает единицу. Должно быть assert '((level >= 1 && level <= 5))', если я правильно помню баш.

ну да, как-то так

Я так понимаю, 5 будет сравниваться с булевым результатом предыдущего сравнения, а это, вероятно, не совсем то, что хотел сказать программист.

Не силен я в bash, но в С сначало бы проверилось одно неравенство и результат его станет операндом второго неравенства. В итоге результат будет не предсказуемым.

всё верно, только результат будет предсказуем — первое сравнение возвращает 0 или 1, что всегда меньше 5

Чё тут думать-то, первое сравнение возвращает bool, а он уже меньше пяти Ж-)

Лучше б на http://lj.rossia.org/users/k001/660024.html отгадку повесил. Я по слайдам, конечно, догадываюсь (dcache - какой-то ядерный кэш содержимого каталогов?), а так тож сначала на иноды подумал.

> Чё тут думать-то, первое сравнение возвращает bool, а он уже меньше пяти Ж-)

ну да

> Лучше б на http://lj.rossia.org/users/k001/660024.html отгадку повесил.

да что-то не успеваю…

Зависит, конечно, от того как реализован assert, но если он eval'ит строчку, то что 0, что 1 - все меньше 5-ти :)

а как ассерт реализован — ниже в комментах

1<=level принимает значения true или false. Оба они меньше пяти. (false -- это 0, а true обычно 1, хотя я не помню, гарантировано ли, что это именно единица.)

P.S. Это я про C. В bash мне как-то assert не попадался.

ну да.

самое удивительное — в питоне такая конструкция работает!

У него это так и задумано было.

Поискал в баше среди built-in assert. Не нашел.

assert -- самописная функция, она запускает то, что ей передали, и проверяет код возврата, *примерно* так:

assert()
{
eval "$@" || exit 1
}

Ага, как я и предполагал.

Ясен пень не будет :). <= -- левоассоциативная операция, поэтому условие переписывается так: ((1 <= level) <= 5). Выражение 1 <= level будет равно 0 или 1, в зависимости от значения level, но это, по сути, пофигу, так как и 0 и 1 меньше 5. Поэтому этого ассерта все равно что нет.

Правильно вот так:
assert (1 <= level && level <= 5)

Эти операции в Баше, вроде, LTR.
Тогда (1 <= level) даст либо 0, либо 1, т.е. всегда меньше 5.

Ну то есть, assert никогда не ругнется, поскольку и 0 <= 5, и 1 <= 5.

Почти не знаю bash (и плохо знаю C), но попробую угадать.

Результат вычисления '1 <= level' это 0 либо 1 (в bash нет логического типа). И то, и другое меньше пяти. Тест всегда будет выполняться вне зависимости от значения level.

Это, наверное, математик или студентег писал :) Мне такое студенты регулярно сдать пытаются.

В C будет либо сравниваться результат сравнения 1 <= level (это 0 или 1) с пятёркой (т.е. (1 <= level) <= 5) и будет получаться единица всегда, либо же, наоборот, будет 1 <= (level <= 5) и будет 0, если level > 5. Мне кажется, что порядок вычисления в данном случае стандартом не оговаривается. Сейчас проверил в gcc, получается всегда единица.

Интересно, что в перле такие выражения не позволяется писать: ошибка возникает.

всё верно

> Интересно, что в перле такие выражения не позволяется
> писать: ошибка возникает.

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

не понимаю bash programming. Есть standard-compliant sh. Есть язык программирования perl, который, при всех своих недостатках, вполне пригоден для написания небольших программ, которые слишком сложны по логике чтобы писать их на sh. А bash - и не то и не то. Он вообще зачем?

2 вопроса:
- А что, там можно подставлять перенные без "$"?
- А что, там есть оператор "x1 <= x2 <= x3"?

переменные без $ можно подставлять, например, в let, а ещё в (( ))

> А что, там есть оператор «x1 <= x2 <= x3»?

нет там такого оператора

А на питоне без кавычек это валидный код и работать будет как надо. :)

Вот это-то меня более всего удивило!


С интересом читаю http://docs.python.org/reference/expressions.html#notin

(1 <= level){0,1}, что всегда меньше 5