0Pricing
R Academy · Lekcja

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 definition

Zmienne 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

  1. Czym jest środowisko w R?
  2. Reguły zakresu leksykalnego
  3. Zakres globalny a lokalny
  4. Tworzenie i analizowanie środowisk
← Powrót do R Academy