Я новичок в R, и меня довольно смущает использование локальных и глобальных переменных в R.
Я прочитал несколько сообщений в Интернете, в которых говорится, использую ли я =
или <-
назначу переменную в текущей среде, и с помощью <<-
я могу получить доступ к глобальной переменной, находясь внутри функции.
Однако, как я помню, в C ++ локальные переменные возникают всякий раз, когда вы объявляете переменную в скобках {}
, поэтому мне интересно, то же самое для R? Или это просто для функций в R, что у нас есть концепция локальных переменных.
Я провел небольшой эксперимент, который, кажется, предполагает, что одних скобок недостаточно, я что-то не так понимаю?
{
x=matrix(1:10,2,5)
}
print(x[2,2])
[1] 4
globalenv(); globalenv() %>% parent.env; globalenv() %>% parent.env %>% parent.env
,…Error: could not find function "%>%"
. Это еще одна форма назначения?require(magrittr)
. Это способ применения функций справа (x | f1 | f2 | f3
), а не слева (f3( f2( f1( x ) ) )
).Ответы:
Переменные, объявленные внутри функции, являются локальными для этой функции. Например:
дает следующее сообщение об ошибке:
Error: object 'bar' not found
.Если вы хотите создать
bar
глобальную переменную, вам следует сделать:В этом случае
bar
доступен извне функции.Однако, в отличие от C, C ++ или многих других языков, скобки не определяют объем переменных. Например, в следующем фрагменте кода:
y
остается доступным послеif-else
утверждения.Как вы хорошо сказали, вы также можете создавать вложенные среды. Вы можете взглянуть на эти две ссылки, чтобы понять, как их использовать:
Вот небольшой пример:
источник
<-
выполняет присваивание в текущей среде.Когда вы находитесь внутри функции, R создает для вас новую среду. По умолчанию он включает все из среды, в которой он был создан, поэтому вы также можете использовать эти переменные, но все новое, что вы создаете, не будет записано в глобальную среду.
В большинстве случаев
<<-
будет присваиваться переменным уже в глобальной среде или создавать переменную в глобальной среде, даже если вы находитесь внутри функции. Однако это не так просто. Что он делает, так это проверяет родительскую среду на наличие переменной с интересующим именем. Если он не находит его в родительской среде, он переходит к родительскому элементу родительской среды (на момент создания функции) и ищет там. Он продолжает движение вверх в глобальную среду и, если он не найден в глобальной среде, присваивает переменную в глобальной среде.Это может проиллюстрировать, что происходит.
В первый раз, когда мы печатаем bar, мы еще не вызвали
foo
его, поэтому он все равно должен быть глобальным - это имеет смысл. Во второй раз мы печатаем его внутриfoo
перед вызовом,baz
поэтому значение in foo имеет смысл. Ниже мы видим, что<<-
происходит на самом деле. Следующим напечатанным значением будет «in baz - before << -», хотя оператор печати идет после<<-
. Это потому,<<-
что не смотрит в текущую среду (если вы не находитесь в глобальной среде, и в этом случае<<-
действует как<-
). Таким образом, внутриbaz
значение бара остается как «in baz - before << -». Как только мы вызываемbaz
копию бара внутри, меняемfoo
на «in baz», но, как мы видим, глобальное значениеbar
не меняется.bar
который определен внутри,foo
находится в родительской среде, когда мы создавали,baz
поэтому это первая копия,bar
которую<<-
видит, и, следовательно, копия, которой она назначается. Так что<<-
это не просто прямое присвоение глобальной среде.<<-
сложно, и я бы не рекомендовал его использовать, если вы можете этого избежать. Если вы действительно хотите назначить глобальную среду, вы можете использовать функцию назначения и явно указать ей, что вы хотите назначить глобально.Теперь я меняю
<<-
оператор на оператор assign, и мы можем увидеть, какой эффект это имеет:Итак, оба раза мы печатаем bar внутри
foo
значения «in foo» даже после вызоваbaz
. Это потому, что мыassign
даже не рассматривали копиюbar
внутри foo, потому что мы сказали, где именно искать. Однако на этот раз значение bar в глобальной среде было изменено, потому что мы явно присвоили ему значение.Теперь вы также спросили о создании локальных переменных, и вы можете сделать это довольно легко, не создавая функцию ... Нам просто нужно использовать
local
функцию.источник
Еще немного в том же духе
напечатает "1"
Напечатает «20»
источник