Foto av Jack Anstey på Unsplash

An översikt över blockens exekveringskontext

Mehdi Farsi

Follow

Sep 20, 2019 – 3 min read

I den här artikeln kommer vi att undersöka följande ämnen:

  • scopes och block
  • flat scope guard i klass/modul

Först kan du gärna bläddra bland Scope Gates i Ruby: Del II.

För att börja

Jag är glad att kunna dela med mig av vårt senaste projekt: Fun Facts about Ruby – Volume 1

Varsågod att sprida ordet och dela den här länken! 🙏

Tack för din tid!

I Ruby kan ett block få tillgång till yttre scope

I det här exemplet kan vi få tillgång till variabeln outer_scope_variable i vårt block. Vårt block får tillgång till variabeln trots att variabeln är deklarerad på en main-nivå. I det här fallet säger vi att blocket plattar till scopes. Det är därför vi vanligtvis kallar denna mekanism för: Flat Scope.

Å andra sidan skapar blocket ett isolerat scope – även om värdet av self inom blocket förblir main-objektet.

Så vi kan inte få tillgång till lokala variabler som definierats inom blocket

Här kan vi inte få tillgång till block_variable från det yttre scope. Nu när vi är mer bekanta med begreppet flat scope i Ruby ska vi se om detta begrepp påverkar klassdefinitionen.

Klass, modul och block

I Ruby är det man vanligen kallar en klass, bakom scenen, en instans av Class-klassen

Här skapar vi Hello– och Greeting-klasserna på två olika sätt:

  • med hjälp av nyckelordet class
  • genom att tilldela en instans av Class-klassen till Greeting-konstanten

Notera att vi överlämnar ett block till Class.new-metoden. Detta block kommer att tolkas som klassens innehåll. Normalt kan en klass inte få tillgång till variabler som definierats i det yttre tillämpningsområdet – eftersom nyckelordet class ändrar värdet på self och skapar ett isolerat tillämpningsområde.

Så, eftersom vi använder ett block för att skapa vår Greeting-klass bör vi kunna använda mekanismen för det platta tillämpningsområdet. Verkligen?

Här kan vi se att värdet på self ändras när vi använder class eller Class.new.

Också vårt Class#message-block är fortfarande isolerat från main-objektet på grund av användningen av nyckelordet def. Eftersom vårt block exekveras i kontexten för metoden så har blocket en plattare räckvidd inom detta givna objekt – och inte med en högre räckvidd som main-objektet.

Det är därför som vi inte har tillgång till outer_variable inom message.

Men om vi använder define_method för att definiera message så blir räckvidden plattare

Här, eftersom define_method(:message) tar ett block som argument, blir räckvidden för detta block plattare och denna metod har tillgång till outer_variable.

Voilà!

Articles

Lämna ett svar

Din e-postadress kommer inte publiceras.