Foto af Jack Anstey på Unsplash

An oversigt over blokers eksekveringskontekst

Mehdi Farsi

Follow

20. sep, 2019 – 3 min read

I denne artikel kommer vi til at udforske følgende emner:

  • scopes og blokke
  • flad scope guard i klasse/modul

Først er du velkommen til at kigge på Scope Gates i Ruby: Del II-artiklen.

Hvor vi går i gang

Jeg er glad for at dele vores seneste projekt med dig: Fun Facts about Ruby – Volume 1

Du er velkommen til at sprede budskabet og dele dette link! 🙏

Tak for din tid!

I Ruby kan en blok få adgang til ydre scope

I dette eksempel kan vi få adgang til outer_scope_variable-variablen inden for vores blok. Vores blok får adgang til denne variabel, selv om variablen er deklareret på et main-niveau scope. I dette tilfælde siger vi, at blokken flatterer scopes. Det er derfor, vi almindeligvis kalder denne mekanisme: Flat Scope.

På den anden side skaber blokken et isoleret scope – selv om værdien af self inden for blokken fortsat er main-objektet.

Så vi kan ikke få adgang til lokale variabler, der er defineret inden for blokken

Her kan vi ikke få adgang til block_variable fra det ydre scope. Nu hvor vi er mere fortrolige med begrebet flat scope i Ruby, lad os se, om dette begreb påvirker klassedefinitionen.

Klasse, modul og blok

I Ruby er det, man almindeligvis kalder en klasse, bag scenen en instans af Class-klassen

Her opretter vi Hello– og Greeting-klasserne på to forskellige måder:

  • ved hjælp af nøgleordet class
  • ved at tildele en instans af Class-klassen til Greeting-konstanten

Bemærk, at vi overdrager en blok til Class.new-metoden. Denne blok vil blive fortolket som indholdet af klassen. Normalt kan en klasse ikke få adgang til variabler, der er defineret i det ydre scope – da nøgleordet class ændrer værdien af self og skaber et isoleret scope.

Så da vi bruger en blok til at oprette vores Greeting-klasse, burde vi kunne bruge den flade scope-mekanisme. Virkelig?

Her kan vi se, at værdien af self ændres, når vi bruger class eller Class.new.

Dertil kommer, at vores Class#message-blok stadig er isoleret fra main-objektet på grund af brugen af def-keywordet. Da vores blok nemlig udføres i konteksten af metoden, så flader blokken scope inden for dette givne objekt – og ikke med et højere scope som main-objektet.

Det er derfor, at vi ikke har adgang til outer_variable inden for message.

Men hvis vi bruger define_method til at definere message, så bliver scope fladet ud

Her, da define_method(:message) tager en blok som argument, bliver scope for denne blok fladet ud, og denne metode har adgang til outer_variable.

Voilà!

Articles

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.