Lab: Scope and Ruby
In today's lab, you'll explore dynamic and static scoping and solve a Ruby coding challenge that hits on namespaces and hashes.
Scoping
Consider the following program in a C-like language that allows nested procedures:
void main() {
int z = 10;
void g() {
int x = 12;
int y = 3; // line A
void f() {
z = x * y;
printLine(x, y, z); // line B
}
void h() {
int y = 2;
int z = 5; // line C
x = y + z;
printLine(x, y, z)
f();
}
h();
printLine(x, y, z);
}
g(); // line D
}
void main() { int z = 10; void g() { int x = 12; int y = 3; // line A void f() { z = x * y; printLine(x, y, z); // line B } void h() { int y = 2; int z = 5; // line C x = y + z; printLine(x, y, z) f(); } h(); printLine(x, y, z); } g(); // line D }
In a moment you will answer some questions about scope. Keep these points in mind as you think about this code:
-
A statement like
int v = 0
declares a new variable. A statement likev = 0
merely assigns a new value to a variable declared elsewhere. - A variable is in scope under static scoping if, at compile time, you can find a prior declaration either in the current block or in the surrounding blocks. The nesting and sequencing of the code itself is what matters. You answer questions about static scoping by examining the structure of the code.
- A variable is in scope under dynamic scoping if, at runtime, you can walk through the stack frames and find the variable. The call sequence is what matters—not the code structure. You answer questions about dynamic scoping by tracing the execution of a program.
- Once a variable is reassigned, it doesn't magically revert back to its previous value, not even when we return from the function that changed it.
Answer the following questions:
-
If this language has static scoping, what is the environment that is in scope immediately after line A finishes executing? Qualify the variables by their owner. For example, if a function sees the
z
variable declared inh
, writeh::z
. List only the variables that are visible; not all of them are always visible. - After line B finishes?
- After line C finishes?
- After line D finishes?
- What is the output of this program if the language has static scoping?
- If this language has dynamic scoping, what is the environment that is in scope after line A finishes?
- After line B finishes?
- After line C finishes?
- After line D finishes?
- What is the output of this program if the language has dynamic scoping?
Tag
Write two Ruby source files: html.rb
and main.rb
. You are encouraged to place the code you write for lab in your official GitHub repository for this course—in a folder separate from your project.
In html.rb
, define a module named Html
with a function named make_tag
. Make it static using self
. Have it accept these three parameters:
- an element name
- a hash of attributes
-
a symbol that is one of
:empty
,:sandwich
, or:selfclose
It returns an HTML tag as a string. Form the string as demonstrated in these example calls:
-
make_tag('img', {src: 'bernie.jpg'}, :empty)
→'<img src="bernie.jpg">'
-
make_tag('div', {id: 'root', class: 'frame'}, :sandwich)
→'<div id="root" class="frame"></div>'
-
make_tag('Gallery', {}, :selfclose)
→'<Gallery />'
In main.rb
, include your module file with require_relative
, call your function several times to test it, and print the resulting tag each time. Ensure that your solution works for any tag, attribute hash, and tag format—and not just the examples.
Do not use include
or extends
or any other command for importing Ruby modules that you might read about on the web. Modules are used to achieve several different ends in Ruby. The include
and extends
commands are ways of making a class inherit code from a module, which is not what you want. All you want is to call a method defined in a namespace.
Submit
To receive credit for this lab, you must submit your two Ruby source files and a digital version of your answers to the scoping problems on Canvas by Monday noon. Late labs or forgot-to-submits are not accepted because Monday at noon is when your instructor has time to grade.