Страница 1 из 2
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 10:07
Игорь Столяров
Привет всем !
Хотелось бы вернуться к обсуждению вопроса пользовательских функций в Evaluate()
и вообще к оптимизации его работы, раз это единственный вариант хоть как-то делать
выборки по пользовательским запросам в БД TPS при отсутствии SQL синтаксиса.
Можно ли как-то обойти запрет на использование "not be omittable" для параметров в забинденных функциях ?
Пример из жизни кроликов.
Мне нужна элементарная функция MAX(Val1,Val2[,Val3][,Val4][,Val5]), которая вернет максимальной значение
от 2-х до 5-ти переданных в нее параметров. Алгоритмика работы самой функции проблем не представляет,
можно написать обработку любого ФИКСИРОВАННОГО кол-ва параметров.
Сейчас это выливается в то, что приходится выполнять, что то вроде MAX(Val1,MAX(Val2,MAX(Val3,Val4))) - что
кроме запутанного синтаксиса, думаю еще не лучшим образом влияет на производительность.
Хотя например те же функции Choose(), InList(), InRange() и т.д. внутри Evaluate() могут иметь переменное число параметров.
Значит это как-то сделать можно ?
Заранее спасибо за идеи !

Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 10:56
kreator
А почему не отказаться от omittable параметров? Всё равно параметры должны быть String, можно в функции проверять параметр на пустоту ('').
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 11:01
Игорь Столяров
Мне, как худо-бедно программисту, конечно понятен синтаксис Max(11,12,34,'','') ...
Но пользователям думаю, что нет ... К тому же опять лишняя информация внутри Evaluate() ...

Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 11:17
Yufil
До какой-то версии Кларион разрешалось указывать меньше параметров, недостающие замещались пробелами. Потом исправили

. Я в разных проектах либо использовал свой препроцессор (писал что-то вида $Max x1,x2; с преобразованием в Max(x1,x2,-1,-1,-1) ), либо просто пользовал функции с разными именами (у меня есть Message, Message2, Message3 с разным комплектом параметров). Была идея с обратной записью и стеком, но и не сложилось...
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 11:55
kreator
Попробовал на С10. Всё прокатило, с omittable параметрами. Подозреваю, что нельзя писать так:
А вот так без проблем:
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 12:23
Дед Пахом
А что, перегруженные функции нельзя использовать?
Код: Выделить всё
Max(long, long), long
Max(long, long, long), long
Max(long, long, long, long), long
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 12:31
Игорь Столяров
У меня как-то есть в подсознании (сам не знаю откуда !), что в Bind они не работают.
Сейчас попробую проверить наверняка ... Спасибо !
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 14:04
Игорь Столяров
Дед Пахом писал(а): А что, перегруженные функции нельзя использовать?
К сожалению не работает. Функции Overload сделать можно, без проблем.
Но когда мы биндим это имя функции, внутри Evaluate() мы видим только один вариант.
Судя по всему разбор схемы вызова overload procedure в зависимости от параметров выполняется
на этапе компиляции, а не в рантайме. По крайне мере не в рантайм Evaluate() - точно !

Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 14:30
kreator
А мой вариант. У меня всё прокатило без всяких выкрутасов.
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 14:37
Игорь Столяров
kreator писал(а): А мой вариант. У меня всё прокатило без всяких выкрутасов.
Спасибо. Класс ! Да это решает проблему.
До этого смотрел C63, а в справке С10 нас ждет приятный бонус:
With regards to EVALUATE, the evaluator is assuming a default value '' to all parameters in the function call in the expression string passed to EVALUATE. In other words, the prototype is assumed to be as follows:
myfunction (STRING='',STRING=''),STRING
and therefore actual parameters can be omitted in the expression.
Спасибо еще раз ! Пошел работать ...

Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 14:54
kreator
Я, кстати, вот этот "десяточный приятный бонус" не понял. Просто попробовал.
Код: Выделить всё
Max PROCEDURE (String v1, String v2, <String v3>, <String v4>, <String v5>) ! Declare Procedure
CODE
if not omitted(3)
if v3>v2 and v3>v1
return v3
else
return v2
end
end
if v2>v1
return v2
else
return v1
end
И вызов:
Код: Выделить всё
bind('Max', Max)
stop(evaluate(Max(5,6,9)))
unbind('Max')
Получается, что в C6.3 такая конструкция не работает? Тогда десятке очередной зачёт!
Пользовательские функции в Evaluate()
Добавлено: 02 Ноябрь 2015, 14:57
Yufil
Проверил в Cw6, как опущенные, так и лишние параметры не работают
Кусок из старой программы.
Код: Выделить всё
BMsg PROCEDURE (Loc:Msg) ! Declare Procedure
CODE
Message(Loc:Msg,'Внимание!',Icon:Asterisk)
Return('')
BMsg2 PROCEDURE (Loc:Msg,Loc:Title) ! Declare Procedure
CODE
Message(Loc:Msg,Loc:Title,Icon:Asterisk)
Return('')
Bind выполнен.
Bind('Msg',BMsg)
Bind('Msg2',BMsg2)
Вызываю Evaluate(Bmsg('Привет')) => Message('Привет')
Evaluate(Bmsg('Привет', 'Привет2' )) => Errorcode
Evaluate(Bmsg2('Привет', 'Привет2' )) => Message('Привет','Привет2')
Evaluate(Bmsg2('Привет' )) => Message('Привет') => Errorcode
Правда, CW6.3, в 6.2 можно было пропускать поля. Сюрприз был ОЧЕНЬ неприятен...
Пользовательские функции в Evaluate()
Добавлено: 04 Ноябрь 2015, 17:50
Игорь Столяров
kreator писал(а): Я, кстати, вот этот "десяточный приятный бонус" не понял.
А не так все просто, как казалось ... В справке C10 об этом как-то туманно ...
Внутри Evaluate() параметры после 2 всегда возвращают Omitted() = True независимо от
их наличия при вызове, но при этом всегда имеют значение ...
Получается, что рабочий вариант в C10 будет выглядеть так:
Код: Выделить всё
! --- Расчет максимума от 2 до 5 значений для Evaluate() ---
Map
Max_(String,String,<String>,<String>,<String>),Real
end
Max_ Procedure(ZP1_,ZP2_,ZP3_,ZP4_,ZP5_)
Loc:xRetValue Decimal(18,6)
Code
If (ZP1_ * 1) > (ZP2_ * 1) then Loc:xRetValue = ZP1_ else Loc:xRetValue = ZP2_.
If ZP3_ <> ''
If (ZP3_ * 1) > Loc:xRetValue then Loc:xRetValue = ZP3_.
If ZP4_ <> ''
If (ZP4_ * 1) > Loc:xRetValue then Loc:xRetValue = ZP4_.
If ZP5_ <> ''
If (ZP5_ * 1) > Loc:xRetValue then Loc:xRetValue = ZP5_.
end
end
end
Return(Loc:xRetValue)
Пользовательские функции в Evaluate()
Добавлено: 05 Ноябрь 2015, 10:42
kreator
Игорь Столяров писал(а):Внутри Evaluate() параметры после 2 всегда возвращают Omitted() = True независимо от
их наличия при вызове, но при этом всегда имеют значение ...
В версии 11975 Omitted() отрабатывается правильно (когда надо True, когда надо False).
Пользовательские функции в Evaluate()
Добавлено: 05 Ноябрь 2015, 11:06
Игорь Столяров
kreator писал(а): В версии 11975 Omitted() отрабатывается правильно (когда надо True, когда надо False).
Очень странно. Именно на этом релизе и проверял. Проверю еще раз. Спасибо.