2010-07-02 4 views
4

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

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 возвращает ложное здесь. С другой стороны, если я заполнить недостающие ветви с заданием:

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" 

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

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

+0

В чем проблема? –

+0

Это четкий вопрос для любых повторителей, если вы не reboler, пропустите это, а не просто голосуйте, что вы не способны понять. –

+0

Может быть, вы должны спросить: «Почему -part - вернуть false, но -part 2- вернуть true?» Вероятно, это не странное поведение. – John

ответ

2

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

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

+0

Ах, вот и все. Но это следует рассматривать как ошибку, поскольку это не ожидаемое поведение функции. funct не должен вести себя иначе, чем func, за исключением того, что переменные становятся локальными. Так что я должен вернуться к func и объявить все мои переменные локальными только потому, что функция не ведет себя как истинная функция? Это побеждает цель создания функции. –

+1

funct - синтаксический сахар для func/local. Он сканирует тело функции для поиска заданных слов и создает их как/местные. Если вы объявите их с/local, эффект будет таким же. –

+0

Я не думаю, что это должно считаться ошибкой, потому что она не может работать иначе. Помните, что в REBOL единственный динамический динамический контекст - глобальный. В вашем случае поведение в точности соответствует ожидаемому: создается контекст и привязываются к нему слова. –

1

Здесь я покажу вам два примера, а не с помощью функции, но в противном случае эквивалентно код:

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 для реализации локальных переменных «под капотом», приведенное выше описание относится ко всем функциям, которые он генерирует.

+0

Спасибо ladislav Я знаю о/local, но это так сложно добавить в/local каждый раз, когда вы добавляете другую переменную, чтобы вы забыли сделать это. Теперь я, наконец, предпочитаю func и/local, если функция не может вести себя точно так же, как func/local. –

1

Существует другой способ, который позволяет избежать использования 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 в глобальной среде ... не как локальный.

+0

Спасибо Ladislav, но это не меняет того факта, что я не могу использовать функцию, и поэтому функция бесполезна для меня. Либо funct - это ярлык для func/local, либо это не так, и для меня это не в моем примере. –

+1

Это как * мой пример * proves – Ladislav

1

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

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

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

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

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

+0

Ну, я не понимаю, почему вы говорите, что это не ведет себя по-другому, так как я нашел пример, где он делает :) –

+0

Но в вашем первом примере нет заданного слова, как в вашем втором примере: «class-name: default-class-name». funct выполняется во время определения не при вызове функции. Когда вы используете funct, и если есть заданное слово типа «class-name:», то оно уже определено как локальная переменная в вашей функции. Даже если вы никогда не вызываете функцию. И это точно такое же поведение, как func/local. Если вы поместите имя класса как/локальное в свой func, тогда он будет таким же. – endo64

Смежные вопросы