Reguły zakresu leksykalnego
Dowiedz się, jak R wyszukuje zmienne, przeszukując środowiska nadrzędne.
Reguły zakresu leksykalnego to bezpłatna lekcja R Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
Czym jest zakres leksykalny?
Zakres leksykalny oznacza, że funkcja wyszukuje zmienne w miejscu, w którym została zdefiniowana, a nie w miejscu, z którego została wywołana. R używa zakresu leksykalnego. Jest to przewidywalne: środowisko przeszukiwane przez funkcję jest ustalane w chwili jej utworzenia, a nie wywołania.
x <- 'global'
f <- function() {
cat('x =', x, '\n') # looks where f was defined (global)
}
local({
x <- 'local to local block'
f() # still prints global x, not the local one
})Zakres leksykalny a dynamiczny
W zakresie dynamicznym (używanym w niektórych innych językach) funkcja znalazłaby zmienną w środowisku wywołującym. R używa natomiast zakresu leksykalnego: środowisko otaczające z chwili definicji ma zawsze pierwszeństwo. Dzięki temu funkcje zachowują się spójnie niezależnie od miejsca ich wywołania.
val <- 100
make_adder <- function(n) {
# n is captured from the definition environment
function(x) x + n
}
add10 <- make_adder(10)
add20 <- make_adder(20)
cat(add10(5), '\n') # 15 — n=10 from definition
cat(add20(5), '\n') # 25 — n=20 from definitionZmienne wolne i domknięcia
Zmienna wewnątrz funkcji, która nie jest parametrem ani zmienną przypisywaną lokalnie, to zmienna wolna. R wyszukuje ją w środowisku otaczającym. Funkcja przechwytująca zmienne wolne jest nazywana domknięciem.
base_rate <- 0.05 # free variable captured by f
f <- function(principal, years) {
principal * (1 + base_rate) ^ years
}
cat('5 yr return:', f(1000, 5), '\n')
# Even if we change base_rate later:
base_rate <- 0.08
cat('New rate return:', f(1000, 5), '\n')Domknięcia przechwytują środowiska
Za każdym razem, gdy funkcja fabrykująca jest wywoływana, zwracana funkcja (domknięcie) przechwytuje migawkę środowiska otaczającego. Różne wywołania tworzą domknięcia z różnymi przechwyconymi wartościami — na tym opierają się fabryki funkcji.
power_fn <- function(exp) {
function(x) x ^ exp
}
square <- power_fn(2)
cube <- power_fn(3)
cat('square(4) =', square(4), '\n')
cat('cube(3) =', cube(3), '\n')Operator <<-
<<- (przypisanie podwójną strzałką) przeszukuje łańcuch środowisk nadrzędnych w poszukiwaniu istniejącego powiązania i modyfikuje je w miejscu. Jeśli nie znajdzie powiązania, tworzy je w środowisku globalnym. Jest to narzędzie służące do modyfikowania zmiennej w zakresie otaczającym z wnętrza funkcji.
count <- 0
increment <- function() {
count <<- count + 1
}
increment()
increment()
increment()
cat('count:', count, '\n')<<- z domknięciami
Najbardziej idiomatyczne zastosowanie <<- występuje wewnątrz domknięć, które muszą aktualizować stan w swoim środowisku otaczającym. Tworzy to funkcje stanowe — funkcje zachowujące pamięć między wywołaniami.
make_counter <- function() {
n <- 0
list(
increment = function() n <<- n + 1,
get = function() n,
reset = function() n <<- 0
)
}
ctr <- make_counter()
ctr$increment()
ctr$increment()
cat('Count:', ctr$get(), '\n')
ctr$reset()
cat('After reset:', ctr$get(), '\n')Zakres w funkcjach zagnieżdżonych
Gdy funkcje są zagnieżdżone, funkcja wewnętrzna może odczytywać zmienne zdefiniowane w funkcji zewnętrznej. Środowisko funkcji zewnętrznej staje się środowiskiem otaczającym funkcji wewnętrznej, tworząc łańcuch.
outer <- function() {
greeting <- 'Hello'
inner <- function(name) {
# greeting comes from outer's environment
paste(greeting, name)
}
inner('World')
}
cat(outer(), '\n')Wyszukiwanie w łańcuchu zakresów
Podczas wyszukiwania zmiennej R przeszukuje środowiska w następującej kolejności: własne środowisko funkcji → otaczające → środowisko otaczającego → ... → globalne → ścieżka wyszukiwania → bazowe → puste. Zwycięża pierwsze znalezione dopasowanie.
x <- 'global'
f <- function() {
x <- 'local to f'
g <- function() {
# g has no x, so looks in f's env
cat('g sees x =', x, '\n')
}
g()
}
f()environment() funkcji
Środowisko otaczające dowolnej funkcji można sprawdzić za pomocą environment(f). Można je nawet ustawić za pomocą environment(f) <- e, zmieniając miejsce wyszukiwania zmiennych wolnych przez funkcję — jest to zaawansowana, ale potężna technika.
x <- 'global_x'
f <- function() x
cat('f sees:', f(), '\n')
# Change f's enclosing environment
my_env <- new.env(parent = emptyenv())
my_env$x <- 'env_x'
environment(f) <- my_env
cat('f now sees:', f(), '\n')Praktyczne domknięcie: zapamiętywanie wyników
Zakres leksykalny + <<- umożliwia zapamiętywanie wyników: można buforować kosztowne wyniki funkcji w środowisku domknięcia. Pamięć podręczna jest prywatna dla domknięcia i zachowuje się między wywołaniami.
make_memoized_fib <- function() {
cache <- c()
function(n) {
if (!is.null(cache[n])) return(cache[n])
if (n <= 1) { cache[n] <<- n; return(n) }
result <- Recall(n-1) + Recall(n-2)
cache[n] <<- result
result
}
}
fib <- make_memoized_fib()
cat(sapply(0:8, fib), '\n')Pułapka zakresu leksykalnego: zmienne pętli
Klasyczna pułapka polega na tworzeniu domknięć wewnątrz pętli. Wszystkie domknięcia przechwytują to samo środowisko, a nie migawkę wartości. W chwili ich wywołania zmienna pętli ma już wartość końcową.
fns <- vector('list', 3)
for (i in 1:3) {
local({
captured_i <- i
fns[[captured_i]] <<- function() captured_i
})
}
cat(fns[[1]](), fns[[2]](), fns[[3]](), '\n')Szybkie sprawdzenie
W zakresie leksykalnym R gdzie funkcja szuka zmiennej wolnej (niezdefiniowanej w samej funkcji)?
Zakres leksykalny: najważniejsze informacje
Najważniejsze informacje o zakresie leksykalnym:
- R używa zakresu leksykalnego — funkcje wyszukują zmienne w miejscu, w którym zostały zdefiniowane
- Funkcja przechwytuje swoje środowisko otaczające jako domknięcie
- Zmienne wolne są rozwiązywane w chwili definicji, a nie wywołania
<<-modyfikuje powiązanie w łańcuchu środowisk nadrzędnych (lub w środowisku globalnym, jeśli go nie znajdzie)- Domknięcia +
<<-= funkcje stanowe z trwałym prywatnym stanem - Pułapka domknięć w pętli: użyj
local(), aby wymusić nowe środowisko w każdej iteracji
make_multiplier <- function(factor) {
function(x) x * factor
}
double <- make_multiplier(2)
triple <- make_multiplier(3)
cat('double(7):', double(7), '\n')
cat('triple(7):', triple(7), '\n')
cat('double env factor:', get('factor', envir = environment(double)), '\n')Często zadawane pytania
Czy lekcja „Reguły zakresu leksykalnego” jest bezpłatna?
Tak — pełny tekst „Reguły zakresu leksykalnego” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Reguły zakresu leksykalnego”?
Dowiedz się, jak R wyszukuje zmienne, przeszukując środowiska nadrzędne. Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „Reguły zakresu leksykalnego”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Czym jest środowisko w R?
- Reguły zakresu leksykalnego
- Zakres globalny a lokalny
- Tworzenie i analizowanie środowisk