Можно ли установить значения параметров по умолчанию для возврата функции?(TCL) - PullRequest
0 голосов
/ 05 февраля 2019

В TCL возможно ли, чтобы значения параметров по умолчанию были возвращаемым значением вызова функции?

proc GetParameterValue { } {
    # calculation for value...
    return value
}

proc TestFunction { {paramVal [GetParameterValue]} } { 
    puts $paramVal
}

TestFunction

Это приводит к печати «[GetParameterValue]».Вместо вызова процедуры GetParameterValue.Это возможно сделать в TCL или мне нужно изменить этот бит кода?

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Это подразумевается как дополнение к полному ответу Донала.В прошлом я иногда прибегал к помощи [subst] для вычисленных значений по умолчанию:

proc GetParameterValue {} { return computedDefault }

proc TestFunction {{paramVal [GetParameterValue]}} { 
    puts [subst -novariables $paramVal]
}

TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}

Это избавляет от необходимости (реализации) полного контроля над аргументами и совмещает свстроенный обработчик аргументов.Он также позволяет использовать анонимные процедуры вместо явно названных для вычисления значений по умолчанию:

proc TestFunction {{paramVal "[apply {{} { return computedValue }}]"}} {
    puts [subst -novariables ${paramVal}]
}

TestFunction; # returns "computedDefault"
TestFunction "providedValue"
TestFunction {$test}

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

  • Необходимо соблюдать некоторую дисциплину, используя скобки для значений по умолчанию в списках аргументов и размещая [subst] на сайтах использования переменной аргумента.

  • Предполагается, что вы имеете некоторый контроль над аргументами или что вы можете гарантировать, что определенные символы специального назначения не являются допустимыми членами домена значений аргументов.

Часы:

TestFunction {[xxx]}

бросков

invalid command name "xxx"

и должны быть продезинфицированы до

TestFunction {\[xxx\]}
0 голосов
/ 05 февраля 2019

Значения параметров по умолчанию могут быть только константами, которые вы вычисляете во время объявления процедуры (чаще всего это литералы, что означает, что вам не нужно использовать list для построения):

proc TestFunction [list [list paramVal [GetParameterValue]]] { 
    ...
}

Чтобы вычислить значение по умолчанию во время вызова процедуры, необходимо переместить вычисление в тело процедуры.Есть несколько способов определить, выполнять ли вычисления, но они сводятся к трем вариантам: использование значения маркера, получение количества слов в вызове и полный контроль над синтаксическим анализом.

Использование значения маркера

Хитрость в том, чтобы найти какое-то значение, которое действительно вряд ли будет передано. Например, если это должен быть фрагмент текста, показанный пользователюзначение, не имеющее ничего, кроме ASCII NUL в нем, не произойдет;установите его в значение по умолчанию, тогда вы сможете определить, есть ли у вас значение по умолчанию, и можете заменить его тем, что предоставляет сложный код.

proc TestFunction {{paramVal "\u0000"}} {
    if {$paramVal eq "\u0000"} {
        set paramVal [GetParameterValue]
    }
    ...
}

Получение количества слов в вызове

Этоопирается на возможности команды info level introspection.В частности, info level 0 сообщает полный список фактических аргументов текущей процедуре.Немного подсчитаем, и мы сможем узнать, было ли передано реальное значение.

proc TestFunction {{paramVal "dummy"}} {
    if {[llength [info level 0]] < 2} {
        # Note that the command name itself is always present
        set paramVal [GetParameterValue]
    }
    ...
}

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

Полный контроль над синтаксическим анализом

В конечном счете, вы также можете принять решение о создании процедуры, которая получает полный контроль надразбор его аргументов.Вы делаете это, давая ему единственный аргумент args, и затем вы можете использовать любой подход, который вы хотите обработать фактический список аргументов.(Я обычно не ставлю формальный список аргументов в скобках , в данном случае только , но это только мой стиль.)

proc TestFunction args {
    if {[llength $args] == 0} {
        set paramVal [GetParameterValue]
    } elseif {[llength $args] == 1} {
        set paramVal [lindex $args 0]
    } else {
        # IMPORTANT! Let users discover how to use the command!
        return -code error -errorcode {TCL WRONGARGS} \
                "wrong # args: should be \"TestFunction ?paramVal?\""
    }
    ...
}

В настоящее время это единственный способ сделать что-то действительно продвинутоеНапример, иметь необязательные аргументы перед обязательными.Это также в значительной степени то, что вам пришлось бы делать в C, если бы вы реализовали команду там, хотя и с поправкой на другой язык.Недостатком является то, что это определенно больше работы, чем использование встроенного базового кода поддержки синтаксического анализа аргументов, предоставляемого реализацией команды proc.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...