Ruby - Colorado School of Mines

Download Report

Transcript Ruby - Colorado School of Mines

various languages…
 Nested
methods
 Lexical (static) vs. Dynamic Scope
 Referencing Environments
 Some examples from Clojure and Ruby
 Union Types
• Ada – compare to classes
 Coroutines
 Not
allowed in C and descendants
 Allowed in Algol 68, Pascal, Ada
 More recently included in JavaScript and
Python
 What
about Ruby? Not really…
(interesting example coming up)
 The
scope of a variable is the range of
statements over which it is visible
 The nonlocal variables of a program unit are
those that are visible but not declared there
 Static scoping: Algol, Pascal, C-type, Ruby
 Dynamic scoping: Bash
 Programmer choice: Perl, Lisp
Don’t confuse static scope with static lifetime!
Scope of Sub1
Scope of Big
Scope of Sub2
procedure Big is
• Based on program text
X : Integer;
procedure Sub1 is • Search declarations, first
locally, then in
X : Integer;
begin ...
increasingly larger
end;
enclosing scopes
procedure Sub2 is
begin
..X..
end;
Reference to X in Sub2 refers
begin // Big
to X in static parent Big. The
...
X in Sub1 is not a static
end;
ancestor of Sub2.
What languages use static scope?
Pascal, Ada, ML, Haskell
C & C++ do not allow nested procedures. Nor
does Java. Inner classes may accomplish some of
1-5
same goals


Variables can be hidden from a unit by having a "closer"
variable with the same name
int count;
Notice that blocks also create static scopes
while (...) {
int count;
...
}
• illegal in Java and C#, legal in C and C++
C++ and Ada allow access to these "hidden" variables
• In Ada: unit.name
• In C++: class_name::name, ::name for global
Scope resolution operator
 Based
on calling sequences of program
units, not their textual layout
• temporal versus spatial
 References
to variables are connected to
declarations by searching back through
the chain of subprogram calls that forced
execution to this point.
 Must be determined at runtime.
MAIN
declaration of x
SUB1
declaration of x
...
call SUB2
...
SUB2
...
reference to x
...
... main body
Static scoping
• Reference to x in SUB2 is to MAIN's
x
Dynamic scoping
• Reference to x depends on call
sequence
MAIN calls SUB1
SUB1 calls SUB2
SUB2 uses x
---- declared in SUB1
MAIN calls SUB2
SUB2 uses x
----- declared in MAIN
Example from Sebesta: Principles of Programming Languages
var y = "global";
function print-y() {
print(y);
}
function test-scope() {
var y = "local";
print-y();
}
test-scope(); // static languages print "global"
// dynamic languages print "local"
print-y(); // all languages should print "global"


The referencing environment of a statement is the
collection of all names that are visible in the statement
In a static-scoped language
• local variables plus
• all of the visible variables in all of the enclosing scopes

In a dynamic-scoped language
• local variables plus
• all visible variables in all active subprograms

Referencing Environment concept is important
because data structures must be created to provide
access to all nonlocal variables
Future topic: closures
procedure Example is
A, B : Integer; ...
procedure Sub1 is
X, Y : Integer;
begin – #a ...
end;
procedure Sub2 is
X : Integer; ...
procedure Sub3 is
X : Integer;
begin - #b
end;
begin - …#c
end; // Sub2
begin - ... #d
end.
Point a env:
X and Y of Sub1,
A and B of Example
Point b env:
X of Sub3 (X of Sub2 is hidden),
A and B of Example
Point c env:
X of Sub2,
A and B of Example
Point d env:
A and B of Example
Example from Sebesta: Principles of Programming Languages
void sub1() {
int a, b;
#X
}
void sub2() {
int b, c;
#Y
sub1;
}
int main()
{
int c, d;
#Z
sub2();
}
Assume main calls sub2, which calls
sub1:
 Point #X env:
• a and b of sub1
• c of sub2
• d of main (c of main and b of sub2 are
hidden)

Point #Y env:
• b and c of sub2
• d of main (c of main hidden)

Point #Z env:
• c and d of main
We’ll do a scoping exercise
Example from Sebesta: Principles of Programming Languages
 Uses
the binding macro
 Suggested uses
• debug function calls by dynamically overriding that
function to print every time it gets called
• The clojure/java.jdbc library uses a dynamic var
*db* so that you don't have to pass in a database
connection to every function call. You can just use the
with-connection macro to bind *db* to the database
you want to use, and then perform any database
queries within the body of the macro.
• It allows you to mock functions that have side-effects
to make them more unit-testable.
From: http://blog.rjmetrics.com/lexical-vs-dynamic-scope-in-clojure/
A very useful application of dynamic scoping is
for passing contextual parameters without having to
add new parameters explicitly to every function in
a call stack
(defn do-stuff []
(do-other-stuff)
(print "stuff done!"))

(binding [*out* my-debug-output-writer]
(do-stuff))
From: http://programmers.stackexchange.com/questions/103164/when-would-dynamic-scoping-be-useful
 Ruby
allows access to current variable
bindings via Kernel#binding
class Largeco
puts "Scott and Mark are casual"
class Person
scott = Largeco::Person.new
def hello
mark = Largeco::Person.new
# notice definitions inside hello
puts "Scott says: #{scott.hi}"
def hi
puts "Mark says: #{mark.hi}"
"hello"
puts "Scott says: #{scott.bye}"
end
puts "Mark says: #{mark.bye}"
def bye
puts "\nBUT Chris is formal, everyone
"goodbye"
must respond in kind"
end
chris = Largeco::Person.new
#notice call to hi
puts "Chris says: #{chris.hello}"
hi
puts "Scott says: #{scott.hi}"
end # of hello definition
puts "Chris says: #{chris.bye}"
def hi
puts "Scott says: #{scott.bye}"
"hi"
end
Quick Ex: Trace this!
def bye
"bye-bye"
Example (not recommended)
end
from https://gist.github.com/markmcspadden/1322598
end # end Person class
end # end Largeco class
 Result: b is undefined
def test_outer( a, b )
def test_inner( a )
puts "#{a} and #{b}"
end
test_inner( a+b )
end # test_outer
test_outer( 1, 2 )
http://www.justskins.com/forums/nested-methods-and-scope-198687.html
def toggle
def toggle
puts "subsequent"
end
puts "first"
end
Output:
first
subsequent
subsequent


Why?
toggle
toggle
toggle
Explain to your partner – why are these not nested methods?
A
union is a type whose variables are
allowed to store different type values at
different times during execution
 Example: flex/bison.
• Lexer needs to pass values to the parser.
• Flex/Bison (lex/yacc) uses a memory location
that both programs know.
• BUT, value passed may be string, int, float, etc.
• Use a UNION to handle.
union flexType {
int intEl;
float floatEl;
} el1;
float x;
int y;
...
el1.intEl = 27;
y = el1.intEl;
x = el1.floatEl; // nonsense
Is this the same as Ruby’s dynamic types? Why/why not?
 Fortran, C, and
C++ provide union
constructs in which there is no language
support for type checking; the union in
these languages is called free union
 Type checking of unions require that
each union include a type indicator
called a discriminant
• Supported by Ada
type Shape is (Circle, Triangle, Rectangle);
type Colors is (Red, Green, Blue);
type Figure (Form: Shape) is record
Filled: Boolean;
Color: Colors;
case Form is
when Circle => Diameter: Float;
when Triangle =>
Leftside, Rightside: Integer;
Angle: Float;
when Rectangle => Side1, Side2: Integer;
end case;
end record;
A discriminated union of three shape variables
 Potentially
unsafe construct
• Do not allow type checking
 Java
and C# do not support unions
• Reflective of growing concerns for safety in
programming language
 http://stackoverflow.com/questions/565
3678/union-types-and-intersection-types






A coroutine is a subprogram that has multiple entries
and controls them itself (maintain status)
Also called symmetric control: caller and called
coroutines are on a more equal basis
A coroutine call is named a resume
The first resume of a coroutine is to its beginning, but
subsequent calls enter at the point just after the last
executed statement in the coroutine
Coroutines repeatedly resume each other, possibly
forever
Coroutines provide quasi-concurrent execution of
program units (the coroutines); their execution is
interleaved, but not overlapped
Information from: Programming Languages, Sebesta
Copyright © 2006 Addison-Wesley. All rights reserved.
Copyright © 2006 Addison-Wesley. All rights reserved.
Copyright © 2006 Addison-Wesley. All rights reserved.
 Coroutines
originated as an assemblylanguage technique
 Supported in some high-level languages,
Simula and Modula-2 being two early
examples.
 Coroutines are well-suited for
implementing more familiar program
components such as cooperative tasks,
iterators, infinite lists, and pipes (per
Wikipedia)
 http://en.wikipedia.org/wiki/Object-
based_language
 http://stackoverflow.com/questions/15430004/
core-difference-between-object-oriented-andobject-based-language
 http://cse3342.blogspot.com/2006/03/objectbased-vs-object-oriented-and.html