Как ЦЕННОСТЬ? функция работы? - PullRequest
4 голосов
/ 02 июля 2010

Я сократил до небольшого примера мой код, который проверяет, имеет ли переменная с именем class-name присвоенное ей значение:

ask-params: function [
    config-file [file!]
    default-class-name
    default-fields
] [
    probe value? 'class-name
    input
    either (value? 'class-name) [
        probe class-name
    ] [
        ;-- omit code in this branch for now
    ]
]

ret-block: ask-params %simple-class.params.txt "Person" "First Name, Last Name"

Выражение value? 'class-name возвращает falseВот.С другой стороны, если я заполню недостающую ветку с помощью присваивания:

ask-params: function [
    config-file [file!]
    default-class-name
    default-fields
] [
    probe value? 'class-name
    input
    either (value? 'class-name) [
        probe class-name
    ] [
        class-name: default-class-name
    ]
]

ret-block: ask-params %simple-class.params.txt "Person" "First Name, Last Name"

Это вернет true для value? 'class-name.Но во втором случае class-name: default-class-name даже еще не выполняется.

Я думаю, что имя класса не должно существовать в памяти, поэтому value? 'class-name должно возвращать false.Почему value? вместо этого возвращает true?

Ответы [ 4 ]

2 голосов
/ 03 июля 2010

Вы используете function. Это сканирует тело функции и предварительно создает для вас локальные переменные, инициализированные NONE. Вот почему value? 'class-name становится истинным (потому что NONE - это допустимое значение для переменной, отличное от ситуации "unset").

Если бы вы использовали func вместо этого, оба возвращали бы false.

1 голос
/ 29 июля 2010

Я не думаю, что function ведет себя иначе, чем func /local. Посмотрите на эти примеры:

>> f: func [/x] [value? 'x]
>> f
== true

Я не дал никакого значения x, но он говорит, что он имеет значение. То же самое для / местного

>> f: func [/local x] [value? 'x]
>> f
== true

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

1 голос
/ 26 июля 2010

Есть еще один способ, который избегает использования FUNC / LOCAL и все же позволяет использовать FUNCTION.

То есть не использовать SET-WORD! для назначения. Вместо этого используйте функцию SET на LIT-WORD!

ask-params: function [config-file [file!] default-class-name default-fields] [
    probe value? 'class-name
    input
    either (value? 'class-name) [
        probe class-name
    ] [
        set 'class-name default-class-name
    ]
]

Вы получите #[false] для функции value?. Тем не менее, вызов SET будет устанавливать class-name в глобальной среде ... не как локальный.

1 голос
/ 17 июля 2010

Здесь я покажу вам два примера, не использующих FUNCTION, но в остальном эквивалентных вашему коду:

ask-params: func [config-file [file!] default-class-name default-fields] [
    probe value? 'class-name
    input
    either (value? 'class-name) [
        probe class-name
    ][
    ]
]

ask-params: func [
    config-file [file!] default-class-name default-fields /local class-name
] [
    probe value? 'class-name
    input
    either (value? 'class-name) [
        probe class-name
    ][
    ]
]

В то время как функция value? в первом примере выдает #[false], во втором примере она выдает #[true]. Это связано с тем, что «аргументы уточнения», следующие за «неиспользованным уточнением» (уточнение, которое не используется в реальном вызове), инициализируются в #[none!] вместе с переменной уточнения. Это относится и к переменным /local, поскольку уточнение /local не отличается от других уточнений функций (за исключением того факта, что принято использовать его для определения локальных переменных).

Поскольку генератор function использует метод /local для реализации локальных переменных «под капотом», вышеприведенное описание применимо также ко всем функциям, которые он генерирует.

...