Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Как должен работать if #26

Closed
alexeyten opened this issue Feb 10, 2012 · 13 comments
Closed

Как должен работать if #26

alexeyten opened this issue Feb 10, 2012 · 13 comments
Assignees
Labels

Comments

@alexeyten
Copy link
Contributor

Хочется, писать условия проще, что бы они были ближе к JS-ным.
Сейчас только пустой массив и undefined считаются ложными условиями.
Хочется, что бы пустая строка, false, 0, null тоже считались ложными

02.json

{
    "sOK": "OK",
    "sEmpty": "", // false
    "sZero": "0",
    "bTrue": true,
    "bFalse": false, // false
    "nZero": 0, // false
    "nOne": 1,
    "Null": null, // false
    "Undef": undefined,
    "oEmpty": {},
    "oOne": { "a": 1 },
    "aEmpty": [],
    "aZero": [0],
    "aOne": [1]
}

if.02.yate

match / {
    "sOK: "
    if .sOK { "true" } else { "false" }
    "\n"
    "sEmpty: "
    if .sEmpty { "true" } else { "false" }
    "\n"
    "sZero: "
    if .sZero { "true" } else { "false" }
    "\n"
    "bTrue: "
    if .bTrue { "true" } else { "false" }
    "\n"
    "bFalse: "
    if .bFalse { "true" } else { "false" }
    "\n"
    "nZero: "
    if .nZero { "true" } else { "false" }
    "\n"
    "nOne: "
    if .nOne { "true" } else { "false" }
    "\n"
    "Null: "
    if .Null { "true" } else { "false" }
    "\n"
    "Undef: "
    if .Undef { "true" } else { "false" }
    "\n"
    "oEmpty: "
    if .oEmpty { "true" } else { "false" }
    "\n"
    "oOne: "
    if .oOne { "true" } else { "false" }
    "\n"
    "aEmpty: "
    if .aEmpty { "true" } else { "false" }
    "\n"
    "aZero: "
    if .aZero { "true" } else { "false" }
    "\n"
    "aOne: "
    if .aOne { "true" } else { "false" }
}

Результат

sOK: true
sEmpty: true
sZero: true
bTrue: true
bFalse: true
nZero: true
nOne: true
Null: true
Undef: false
oEmpty: true
oOne: true
aEmpty: false
aZero: true
aOne: true
@alexeyten
Copy link
Contributor Author

ОК, если пустая строка и 0 будут ложными, то это будет не похоже на то, как себя ведёт XSLT.
Но false и null, надо приводить всё-таки имеет смысл считать ложью.

@ghost ghost assigned pasaran Feb 15, 2012
@pasaran
Copy link
Owner

pasaran commented Feb 21, 2012

Ну тут тонкий момент, да.
В xslt истинно любое наличие ноды. Независимо от ее контента.
Я сделал так же.
Непонятно, почему вот эти ситуации разные:

{
    a: '',
    b: null,
    c: false,
    d: undefined,
    e: 0
}

Ноды есть. Видимо ты хочешь привести ноду к строке (скаляру)?
Т.е. нужна специальная функция scalar(...).

@alexeyten
Copy link
Contributor Author

Ну мы же не хотим бездумно скопировать xslt.
Потому что JS всё-таки типизированный.
И если я написал false, то это не просто так.

По факту, в твоём примере ноды d нет. И уж совершенно непонятно для обычного JS-ера почему нет ноды aEmpty из первого поста.

@alexeyten
Copy link
Contributor Author

Прошёлся по условиям в реальном проекте.
Из 28 if-ов:

  • 21 — проверка скаляров: (не-)пустые строки, число 0, булевы типы. Из них 10 вида if .node+""
  • 6 — проверка существования ноды.
  • 1 — непонятный вида bool || .node.

@alexeyten
Copy link
Contributor Author

Мне кажется, что нужно в if-е приводить ноды к скаляру и завести отдельный ifnode .nodeset который будет просто проверять количество нод. Или даже просто допилить наконец функцию count, и писать if count(.nodeset).

@pasaran
Copy link
Owner

pasaran commented May 26, 2012

Ок.
Давайте попробуем так.
count(...) можно допилить, но лучше еще и иметь функцию exists(...) -- она дешевле по производительности будет.

@alexeyten
Copy link
Contributor Author

ОК. Итого, условия в if приводятся к скаляру. Для проверки существования ноды используем отдельную функцию exist(nodeset)

@pasaran
Copy link
Owner

pasaran commented May 27, 2012

Нет, я подумал и понял, что так плохо.
Потому что, например:

if 42 > 0 {
    ...
}

Там условие уже типа boolean, его нельзя привести к scalar.

Вариант — если boolean, то ничего не делать, а все остальное приводить к scalar.

Например, данные такие:

{
    "foo": true,
    "bar": false
}

Шаблон:

// Здесь .foo -- это boolean, приводим его к scalar.
if .foo {

}

// А здесь !(...) -- это boolean, значит выражение .foo тоже нужно приводить к boolean.
if !(.foo) {

}

Т.е. в симметричных условиях мы приводим nodeset то к boolean, то к scalar.

Отсюда вывод. Приводить условие нужно таки к boolean, а менять нужно nodeset2boolean.

@pasaran
Copy link
Owner

pasaran commented May 27, 2012

function nodeset2boolean(nodeset) {
    var node = nodeset[0];
    if (!node) { return false; }

    var data = node.data;
    if (data instanceof Array) {
        // Или вариант -- смотреть на первый элемент массива.
        return (data.length > 0);
    }

    if (typeof data === 'object') {
        // Или вариант -- смотреть, пустой ли объект или нет.
        return true;
    }

    return !!data;
}

Как-то так чтоль.

@pasaran
Copy link
Owner

pasaran commented May 27, 2012

В общем я переделал nodeset2boolean и добавил exists.
Соответственно их поведение описывается в тестах if.02.yate и if.03.yate.
Вроде все довольно логично получилось.

@alexeyten
Copy link
Contributor Author

Да, так мне нравится :)

@pasaran
Copy link
Owner

pasaran commented May 28, 2012

Ладно, тогда я закрываю.

@pasaran pasaran closed this as completed May 28, 2012
@alexeyten
Copy link
Contributor Author

для истории коммит 019de43

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants