Menu
Coddy logo textTech

Durum Kalıbı

Coddy'nin R Journey'sinin Nesne Tabanlı Programlama bölümünün bir parçası. Ders 48 / 57.

state desenindeki bir nesne, mevcut durumuna bağlı olarak farklı davranır. Her durum, işleyici işlevlerin bir listesidir ve nesne, her isteği içinde bulunduğu durumun işleyicilerine iletir:

states <- list(
  green = list(label = "go", next_state = "yellow"),
  yellow = list(label = "slow down", next_state = "red"),
  red = list(label = "stop", next_state = "green")
)
current <- "green"
for (i in 1:4) {
  cat(current, ":", states[[current]]$label, "\n")
  current <- states[[current]]$next_state
}

Çıktı:

green : go 
yellow : slow down 
red : stop 
green : go 

İşleyiciler bir olay alır ve bir sonraki durumu ve yanıtı döndürür; böylece geçişler bir if zinciri yerine veridir. Bir turnike, bir bozuk para yerleştirildiğinde kilidini açar ve biri geçtikten sonra tekrar kilitlenir:

states <- list(
  locked = list(
    coin = function() list(to = "unlocked", say = "unlocked"),
    push = function() list(to = "locked", say = "blocked")
  ),
  unlocked = list(
    coin = function() list(to = "unlocked", say = "already open"),
    push = function() list(to = "locked", say = "welcome")
  )
)
current <- "locked"
for (event in c("push", "coin", "coin", "push")) {
  r <- states[[current]][[event]]()
  current <- r$to
  cat(event, "->", r$say, "\n")
}

Çıktı:

push -> blocked 
coin -> unlocked 
coin -> already open 
push -> welcome 

Makinenin kendisi küçük bir closure'dır: mevcut durumu tutar, işleyiciyi arar ve durumun tanımadığı bir olay için ignored yanıtını verir:

make_machine <- function(states, start) {
  current <- start
  list(
    handle = function(event) {
      h <- states[[current]][[event]]
      if (is.null(h)) return("ignored")
      r <- h()
      current <<- r$to
      r$say
    },
    state = function() current
  )
}
states <- list(off = list(press = function() list(to = "on", say = "light on")),
               on = list(press = function() list(to = "off", say = "light off")))
m <- make_machine(states, "off")
for (e in c("press", "kick", "press")) cat(e, ":", m$handle(e), "|", m$state(), "\n")

Çıktı:

press : light on | on 
kick : ignored | on 
press : light off | off 

Yeni bir durum, listeye yeni bir giriştir. Makine değişmez ve yalnızca yeni duruma götüren durumların yeni bir işleyiciye ihtiyacı vardır:

states <- list(
  off = list(press = function() list(to = "on", say = "on")),
  on = list(press = function() list(to = "off", say = "off"),
            overheat = function() list(to = "broken", say = "fuse blown")),
  broken = list(repair = function() list(to = "off", say = "repaired"))
)
current <- "off"
for (e in c("press", "overheat", "press", "repair")) {
  h <- states[[current]][[e]]
  if (is.null(h)) { cat(e, ": ignored\n"); next }
  r <- h()
  current <- r$to
  cat(e, ":", r$say, "\n")
}

Çıktı:

press : on 
overheat : fuse blown 
press : ignored
repair : repaired 
challenge icon

Görev

Kolay

Turnstile.R dosyasındaki turnikeyi tamamlayın. states listesi locked ve unlocked durumlarına sahiptir ve her işleyici list(to = ..., say = ...) döndürür:

  • locked: coin, unlocked ile kilidi açar; push, blocked ile kilitli kalır;
  • unlocked: coin, thanks, already open ile kilidi açık tutar; push, welcome ile kilitler ve bir geçiş sayar.

Ardından, başlangıçta kilitli olan ve handle(event) (yanıtı veya bilinmeyen bir olay için ignored), state() ve passes() işlevlerini döndüren make_turnstile() işlevini tamamlayın. push kilidi açık durumda işlendiğinde bir geçiş sayın. Sağlanan kod olayları okur ve her yanıtı yeni durumla birlikte, ardından geçiş sayısını yazdırır.

Kodunuz Turnstile.R dosyasına yazılmalıdır. main.R, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

source("Turnstile.R")

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input <- suppressWarnings(readLines(file("stdin")))
t <- make_turnstile()
for (event in input) cat(event, ": ", t$handle(event), " [", t$state(), "]\n", sep = "")
cat("passes: ", t$passes(), "\n", sep = "")
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Tabanlı Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online R derleyicisi