2013-08-09 3 views
9

Целью приведенной ниже функции является возвращение строки, вставившей значение аргумента между двумя звездами.Что именно произошло, когда вы не использовали «копию» для обработки строки?

star-name: func [name /local stars] [ 
    stars: "**" 
    insert next stars name 
    stars 
] 
print star-name "test" ;*test* 
print star-name "this" ;*thistest*, but what I really want is *this* 

Во второй раз, когда я вызываю функцию, аргумент первого вызова по-прежнему остается вставленным. Я знаю, что ответ заключается в использовании copy "**". Мой вопрос в том, не переназначает ли переменную stars на "**" каждый раз, когда вызывается функция?

ответ

6

В случае функции есть только один «**» Определение строки. Это определение используется функцией Rebol load только один раз, так как load запускается только один раз, чтобы перевести код на внутреннюю форму Rebol - блок. Верно, что назначение выполняется дважды, если вы вызываете функцию дважды, но присваивание ничего не создает, это просто заставляет переменную ссылаться на ту же строку снова.

В своем комментарии вы должны заметить, что на самом деле у вас есть два определения строки «**», которые приводят к созданию двух строк, созданных load. Если вы используете

code: [stars: "**" insert next stars something] 
something: "this" 
do code 
something: "that" 
do code 

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

+0

Думаю, у меня есть идея. В Rebol функции - это просто блоки. Это сильно отличается от функций на других языках. Большое спасибо :) –

+0

Некоторое понимание того, почему Rebol ведет себя так: [Является Rebol чистым функциональным языком] (http://www.rebol.com/article/0206.html) – rgchris

2

Если вы используете заданное слово в серии, то по умолчанию используется распределение памяти для этой серии только один раз. Это позволяет использовать это как статическую переменную, которая сохраняется между вызовами функций, как вы уже нашли.

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

Это еще один способ, которым Вы можете сделать это, как звезда местным не требуется

star-name: func [ name ][ 
    rejoin [ "*" name "*" ] 
] 
+0

Тогда это функция функции? Потому что я просто пишу: «звезды:» ** «вставить следующие звезды» это «звезды звезд печати:» ** «вставить следующие звезды», которые «печатают звезды», не будут иметь вышеуказанной проблемы. –

+1

В этом случае у вас есть две разные серии на двух разных адресах памяти. –