I am new to elixir, having hard time with updating the variables. Need some help. I have two Maps
firstMsg = %{msg: "Hello", vt: %{"p1" => 1, "p2" => 1, "p3" => 1}, from: "p3"}
state = %{ :name => "p2",
vector: %{"p1" => 0, "p2" => 0, "p3" => 0},
participants: ["p1","p3","p2"]
}
I am passing these two maps in a function, which should return me either true or false, depending on some conditions.
defmodule Testfunc do
def keep_in_pending(firstMsg, state) do
if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do
#IO.puts("Origin proc clock is 1 step ahead from rcvd process Origin clk")
checking = false #initially set this to false
for n <- state.participants do
if n != firstMsg.from do #filter the origin processes
IO.puts("#{n}: #{inspect firstMsg.vt[n]} <= #{n}: #{inspect state.vector[n]} ")
checking = cond do
(firstMsg.vt[n] <= state.vector[n]) -> false
(firstMsg.vt[n] > state.vector[n]) -> true
end
end
end
end
checking
end
end
out = Testfunc.keep_in_pending(firstMsg, state)
IO.puts("#{inspect out}")
It always gives me false (value that I initially assigned to it), and doesn't updates. I think the scope of variable is restricted to the inner "if". Can anyone give me suggestion on how to re arrange this code so that it returns me proper updated boolean value ?
So in this case it should return me true because firstMsg.vt["p1"] > state.vector["p1"].
Welcome to Elixir. You're right, it is a matter of scope, but it runs a bit deeper than that. Elixir is a language where your data is immutable. You can't set checked to false, run a loop, and set it to true somewhere in that loop. That would mutate checked. It's not that someone designed devilish scope rules to prevent this, but rather that the underlying virtual machine doesn't mutate state.
The style of programming where you set some state, then run a procedure that changes that state, relies on mutable state. When state is immutable, the alternative to a loop is instead recursion. You carry new state in every recursive call.
You're learning a functional language, and I think it will be helpful to pull apart your code into a few functions. This will both address your immediate concern, and make your code easier to understand.
def keep_in_pending(%{from: from, vt: vt}, %{vector: vector, participants: ps}) do
if vt[from] == vector[from] + 1 do
ps
|> Enum.reject(& &1 == from)
|> check_participants(vector, vt, false)
end
end
def check_participants([], _, _, bool), do: bool
def check_participants([h | t], vector, vt, bool) do
check_participants(t, vector, vt, vt[h] > vector[h])
end
I'll briefly explain it.
First, note that I've pattern matched the inputs, to pull out the interesting parts we're using in the function body. This gets rid of some of the repetitive firstMsg.from business. (Btw, snake_case your variable names.)
Second, I haven't touched the gnarly outer if-condition. I simply don't know what it means. You should perhaps extract it and give it an intention revealing name.
The real action begins when we pipe participants. You were filtering inside your list comprehension. I've filtered with Enum.reject/1 instead. Then we pipe the list into a recursive function. It's going to carry the boolean through to the end, starting off with false. It needs to check values in vt and vector, so they're also passed in.
The first rule of recursion is the first rule of recursion. No, wait. It's to think about how to terminate the recursion. We're working through a list of participants, so we'll stop when the list is empty. At that point, we have the boolean we're looking for, so just return it.
The recursive step is to pick off an item from the list (h), use it to determine a new boolean (vt[h] > vector[h]) and call the function again with the rest of the list (check_participants(t, ...)).
Hope this helps! Have fun learning functional programming!
So here is an idea: if you are trying to make a function return a boolean, just make it return a boolean, don't assign it to a variable. Assigning inside an if/case/cond will show a warning. Also, you are not reassigning the checking because variables bound inside the comprehension (for) are restricted to that scope. Your best tools in Elixir will be first pattern matching and second the pipe operator, so always try to use them.
Here is an idea to refactor that code:
defmodule Testfunc do
def keep_in_pending(firstMsg, state) do
if (firstMsg.vt[firstMsg.from] == state.vector[firstMsg.from] + 1) do
state.participants
|> Enum.filter(fn (n) -> n != firstMsg.from end)
|> Enum.reduce(fn (n, _) ->
cond do
(firstMsg.vt[n] <= state.vector[n]) -> false
(firstMsg.vt[n] > state.vector[n]) -> true
end
end)
end
end
end
Related
So I have a custom programming language, and in it I am doing some math formalization/modeling. In this instance I am doing basically this (a pseudo-javascript representation):
isIntersection([1, 2, 3], [1, 2], [2, 3]) // => true
isIntersection([1, 2, 3], [1, 2, 3], [3, 4, 5]) // => false
function isIntersection(setTest, setA, setB) {
i = 0
while (i < setTest.length) {
let t = setTest[i]
if (includes(setA, t) || includes(setB, t)) {
i++
} else {
return false
}
}
return true
}
function includes(set, element) {
for (x in set) {
if (isEqual(element, x)) {
return true
}
}
return false
}
function isEqual(a, b) {
if (a is Set && b is Set) {
return isSetEqual(a, b)
} else if (a is X... && b is X...) {
return isX...Equal(a, b)
} ... {
...
}
}
function isSetEqual(a, b) {
i = 0
while (i < a.length) {
let x = a[i]
let y = b[i]
if (!isEqual(x, y)) {
return false
}
i++
}
return true
}
The isIntersection is checking isEqual, and isEqual is configured to be able to handle all kinds of cases of equality check, from sets compared to sets, objects to objects, X's to X's, etc..
The question is, how can we make the isEqual somehow ignorant of the implementation details? Right now you have to have one big if/else/switch statement for every possible type of object. If we add a new type, we have to modify this gigantic isEqual method to add support for it. How can we avoid this, and just define them separately and cleanly?
I was thinking initially of making the objects be "instances of classes" so to speak, with class methods. But I like the purity of having everything just be functions and structs (objects without methods). Is there any way to implement this sort of thing without using classes with methods, instead keeping it just functions and objects?
If not, then how would you implement it with classes? Would it just be something like this?
class Set {
isEqual(set) {
i = 0
while (i < this.length) {
let x = this[i]
let y = set[i]
if (!x.isEqual(y)) {
return false
}
i++
}
return true
}
}
This would mean every object would have to have an isEqual defined on it. How does Haskell handle such a system? Basically looking for inspiration on how this can be most cleanly done. I want to ideally avoid having classes with methods.
Note: You can't just delegate to == native implementation (like assuming this is in JavaScript). We are using a custom programming language and are basically trying to define the meaning of == in the first place.
Another approach is to pass around an isEqual function along with everything somehow, though I don't really see how to do this and if it were possible it would be clunky. So not sure what the best approach is.
Haskell leverages its type and type-class system to deal with polymorphic equality.
The relevant code is
class Eq a where
(==) :: a -> a -> Bool
The English translation is: a type a implements the Eq class if, and only if, it defines a function (==) which takes two inputs of type a and outputs a Bool.
Generally, we declare certain "laws" that type-classes should abide by. For example, x == y should be identical to y == x in all cases, and x == x should never be False. There's no way for the compiler to check these laws, so one typically just writes them into the documentation.
Once we have defined the typeclass Eq in the above manner, we have access to the (==) function (which can be called using infix notation - ie, we can either write (==) x y or x == y). The type of this function is
(==) :: forall a . Eq a => a -> a -> Bool
In other words, for every a that implements the typeclass Eq, (==) is of type a -> a -> Bool.
Consider an example type
data Boring = Dull | Uninteresting
The type Boring has two proper values, Dull and Uninteresting. We can define the Eq implementation as follows:
instance Eq Boring where
Dull == Dull = True
Dull == Uninteresting = False
Uninteresting == Uninteresting = True
Uninteresting == Dull = False
Now, we will be able to evaluate whether two elements of type Boring are equal.
ghci> Dull == Dull
True
ghci> Dull == Uninteresting
False
Note that this is very different from Javascript's notion of equality. It's not possible to compare elements of different types using (==). For example,
ghci> Dull == 'w'
<interactive>:146:9: error:
* Couldn't match expected type `Boring' with actual type `Char'
* In the second argument of `(==)', namely 'w'
In the expression: Dull == 'w'
In an equation for `it': it = Dull == 'w'
When we try to compare Dull to the character 'w', we get a type error because Boring and Char are different types.
We can thus define
includes :: Eq a => [a] -> a -> Bool
includes [] _ = False
includes (x:xs) element = element == x || includes xs element
We read this definition as follows:
includes is a function that, for any type a which implements equality testing, takes a list of as and a single a and checks whether the element is in the list.
If the list is empty, then includes list element will evaluate to False.
If the list is not empty, we write the list as x : xs (a list with the first element as x and the remaining elements as xs). Then x:xs includes element iff either x equals element, or xs includes element.
We can also define
instance Eq a => Eq [a] where
[] == [] = True
[] == (_:_) = False
(_:_) == [] = False
(x:xs) == (y:ys) = x == y && xs == ys
The English translation of this code is:
Consider any type a such that a implements the Eq class (in other words, so that (==) is defined for type a). Then [a] also implements the Eq type class - that is, we can use (==) on two values of type [a].
The way that [a] implements the typeclass is as follows:
The empty list equals itself.
An empty list does not equal a non-empty list.
To decide whether two non-empty lists (x:xs) and (y:ys) are equal, check whether their first elements are equal (aka whether x == y). If the first elements are equal, check whether the remaining elements are equal (whether xs == ys) recursively. If both of these are true, the two lists are equal. Otherwise, they're not equal.
Notice that we're actually using two different ==s in the implementation of Eq [a]. The equality x == y is using the Eq a instance, while the equality xs == ys is recursively using the Eq [a] instance.
In practice, defining Eq instances is typically so simple that Haskell lets the compiler do the work. For example, if we had instead written
data Boring = Dull | Uninteresting deriving (Eq)
Haskell would have automatically generated the Eq Boring instance for us. Haskell also lets us derive other type classes like Ord (where the functions (<) and (>) are defined), show (which allows us to turn our data into Strings), and read (which allows us to turn Strings back into our data type).
Keep in mind that this approach relies heavily on static types and type-checking. Haskell makes sure that we only ever use the (==) function when comparing elements of the same type. The compiler also always knows at compile type which definition of (==) to use in any given situation because it knows the types of the values being compared, so there is no need to do any sort of dynamic dispatch (although there are situations where the compiler will choose to do dynamic dispatch).
If your language uses dynamic typing, this method will not work and you'll be forced to use dynamic dispatch of some variety if you want to be able to define new types. If you use static typing, you should definitely look into Haskell's type class system.
I need to check if a particular string is one of a set of predetermined strings.
Two methods to do it came to my mind: setting up a table to return true on a particular value
local isParticular = {
[string1] = true,
[string2] = true
}
print(isParticular[string1]) -- true
print(isParticular[randomString]) -- nil -> false
Or setting a function to check it with a conditional determination
function isParticular(s)
return s == string1 or s == string2
end
print(isParticular(string1)) -- true
print(isParticular(randomString)) -- false
From what I understand the table method would take the same time for both any of the particular strings and for different strings, while the function call because of short-circuit evaluation will take less time for string1 and more time for string2 and randomString.
Also, both the function call and the table access are known for causing a little overhead, but maybe the short-circuit evaluation can make the difference (in being slower I think, especially considered I have more than 2 particular strings and that most of the times the string won't match any of them).
So what method should I use?
A hash-table lookup would outperform your functional lookup for a large dataset. So, go with the first method:
local isParticular = {
string1 = true,
string2 = true
}
print(isParticular[string1]) -- true
print(isParticular[randomString]) -- nil -> false
I wrote a program that will determine whether some imaginary school would have a snow day or not. I have the program working correctly I'm just having an issue.
Basically what I want is for the True/False to be Y/N. And later when I print SnowDay --tells whether there's a snow day. Then it will print either "Yes" or "No" instead of "True" or "False"
SofieAssignment : Boolean;
SnowDay : Boolean;
.
.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Get(Item => SophieAssignment);
.
.
Put(Item => "Should we have a snow day today? " & Boolean'Image (SnowDay));
Assuming I understand what you're trying to do:
(1) If you want the user to enter Y or N for SophieAssignment, there are a couple possibilities:
You can input a string and analyze the string yourself.
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
declare
Answer : String := Get_Line; -- Get_Line is in Ada.Text_IO
begin
if Answer = "Y" or else Answer = "y" or else Answer = "Yes" or else
Answer = "yes" then
SophieAssignment := True;
elsif Answer = "N" or else Answer = "n" or else Answer = "No" or else
Answer = "no" then
SophieAssignment := False;
else
-- whatever you want to do for an invalid entry
end if;
end;
(This could be improved, but I'm just trying to cover the fundamental approach.) Another possibility is to define your own enumeration that has the values Y and N:
type Yes_No is (N, Y);
package Yes_No_IO is new Enumeration_IO (Yes_No); -- Enumeration_IO is in Ada.Text_IO
Answer : Yes_No;
Put(Item => "Does Sophie have a big assignment due in class, True/False? ");
Yes_No_IO.Get(Item => Answer);
SophieAssignment := (Answer = Y);
Get here will set Answer to either Y or N if the user enters the enumeration name (in either case); it will raise Data_Error if something else is entered. I'd prefer the first method if you want better control over how input is handled. For the second, if the user enters "Y Z", Get will return the Y, and the Z is left in the input stream waiting for the next input operation. Also, the first method allows for multiple possible answers better than the second, although you could make it work with an enumeration like
type Yes_No is (N, No, Y, Yes);
(2) To output "Yes" or "No" based on a Boolean, you can use a function as in Keith's answer, or you can set up an array:
type Const_String_Acc is access constant String;
Yes_No_Image : constant array (Boolean) of Const_String_Acc :=
(False => new String' ("No"),
True => new String' ("Yes"));
Put(Item => "Should we have a snow day today? " & Yes_No_Image (SnowDay).all);
To print a Boolean value as "Yes" or "No", just write a function:
function Boolean_Image(B: Boolean) return String is
begin
if B then
return "Yes";
else
return "No";
end if;
end Boolean_Image;
and use it in place of Boolean'Image.
To read a value from the user as Y or y for True, or as N or n for False, just read a Character value and test it to determine which Boolean value to set. Think about how you want to respond if the character the user enters is not any of Y, y, N, or n. You can use Get_Immediate to read a single character without waiting for a newline on input.
type Snow_Day_Type is new Boolean;
function Yes return Snow_Day_Type is (Snow_Day_Type'(True));
function No return Snow_Day_Type is (Snow_Day_Type'(False));
Sometimes, I have a control structure (if, for, ...), and depending on a condition I either want to use the control structure, or only execute the body. As a simple example, I can do the following in C, but it's pretty ugly:
#ifdef APPLY_FILTER
if (filter()) {
#endif
// do something
#ifdef APPLY_FILTER
}
#endif
Also it doesn't work if I only know apply_filter at runtime. Of course, in this case I can just change the code to:
if (apply_filter && filter())
but that doesn't work in the general case of arbitrary control structures. (I don't have a nice example at hand, but recently I had some code that would have benefited a lot from a feature like this.)
Is there any langugage where I can apply conditions to control structures, i.e. have higher-order conditionals? In pseudocode, the above example would be:
<if apply_filter>
if (filter()) {
// ...
}
Or a more complicated example, if a varable is set wrap code in a function and start it as a thread:
<if (run_on_thread)>
void thread() {
<endif>
for (int i = 0; i < 10; i++) {
printf("%d\n", i);
sleep(1);
}
<if (run_on_thread)>
}
start_thread(&thread);
<endif>
(Actually, in this example I could imagine it would even be useful to give the meta condition a name, to ensure that the top and bottom s are in sync.)
I could imagine something like this is a feature in LISP, right?
Any language with first-class functions can pull this off. In fact, your use of "higher-order" is telling; the necessary abstraction will indeed be a higher-order function. The idea is to write a function applyIf which takes a boolean (enabled/disabled), a control-flow operator (really, just a function), and a block of code (any value in the domain of the function); then, if the boolean is true, the operator/function is applied to the block/value, and otherwise the block/value is just run/returned. This will be a lot clearer in code.
In Haskell, for instance, this pattern would be, without an explicit applyIf, written as:
example1 = (if applyFilter then when someFilter else id) body
example2 = (if runOnThread then (void . forkIO) else id) . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000 -- threadDelay takes microseconds
Here, id is just the identity function \x -> x; it always returns its argument. Thus, (if cond then f else id) x is the same as f x if cond == True, and is the same as id x otherwise; and of course, id x is the same as x.
Then you could factor this pattern out into our applyIf combinator:
applyIf :: Bool -> (a -> a) -> a -> a
applyIf True f x = f x
applyIf False _ x = x
-- Or, how I'd probably actually write it:
-- applyIf True = id
-- applyIf False = flip const
-- Note that `flip f a b = f b a` and `const a _ = a`, so
-- `flip const = \_ a -> a` returns its second argument.
example1' = applyIf applyFilter (when someFilter) body
example2' = applyIf runOnThread (void . forkIO) . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000
And then, of course, if some particular use of applyIf was a common pattern in your application, you could abstract over it:
-- Runs its argument on a separate thread if the application is configured to
-- run on more than one thread.
possiblyThreaded action = do
multithreaded <- (> 1) . numberOfThreads <$> getConfig
applyIf multithreaded (void . forkIO) action
example2'' = possiblyThreaded . forM_ [1..10] $ \i ->
print i >> threadDelay 1000000
As mentioned above, Haskell is certainly not alone in being able to express this idea. For instance, here's a translation into Ruby, with the caveat that my Ruby is very rusty, so this is likely to be unidiomatic. (I welcome suggestions on how to improve it.)
def apply_if(use_function, f, &block)
use_function ? f.call(&block) : yield
end
def example1a
do_when = lambda { |&block| if some_filter then block.call() end }
apply_if(apply_filter, do_when) { puts "Hello, world!" }
end
def example2a
apply_if(run_on_thread, Thread.method(:new)) do
(1..10).each { |i| puts i; sleep 1 }
end
end
def possibly_threaded(&block)
apply_if(app_config.number_of_threads > 1, Thread.method(:new), &block)
end
def example2b
possibly_threaded do
(1..10).each { |i| puts i; sleep 1 }
end
end
The point is the same—we wrap up the maybe-do-this-thing logic in its own function, and then apply that to the relevant block of code.
Note that this function is actually more general than just working on code blocks (as the Haskell type signature expresses); you can also, for instance, write abs n = applyIf (n < 0) negate n to implement the absolute value function. The key is to realize that code blocks themselves can be abstracted over, so things like if statements and for loops can just be functions. And we already know how to compose functions!
Also, all of the code above compiles and/or runs, but you'll need some imports and definitions. For the Haskell examples, you'll need the impots
import Control.Applicative -- for (<$>)
import Control.Monad -- for when, void, and forM_
import Control.Concurrent -- for forkIO and threadDelay
along with some bogus definitions of applyFilter, someFilter, body, runOnThread, numberOfThreads, and getConfig:
applyFilter = False
someFilter = False
body = putStrLn "Hello, world!"
runOnThread = True
getConfig = return 4 :: IO Int
numberOfThreads = id
For the Ruby examples, you'll need no imports and the following analogous bogus definitions:
def apply_filter; false; end
def some_filter; false; end
def run_on_thread; true; end
class AppConfig
attr_accessor :number_of_threads
def initialize(n)
#number_of_threads = n
end
end
def app_config; AppConfig.new(4); end
Common Lisp does not let you redefine if. You can, however, invent your own control structure as a macro in Lisp and use that instead.
I'm studying dynamic/static scope with deep/shallow binding and running code manually to see how these different scopes/bindings actually work. I read the theory and googled some example exercises and the ones I found are very simple (like this one which was very helpful with dynamic scoping) But I'm having trouble understanding how static scope works.
Here I post an exercise I did to check if I got the right solution:
considering the following program written in pseudocode:
int u = 42;
int v = 69;
int w = 17;
proc add( z:int )
u := v + u + z
proc bar( fun:proc )
int u := w;
fun(v)
proc foo( x:int, w:int )
int v := x;
bar(add)
main
foo(u,13)
print(u)
end;
What is printed to screen
a) using static scope? answer=180
b) using dynamic scope and deep binding? answer=69 (sum for u = 126 but it's foo's local v, right?)
c) using dynamic scope and shallow binding? answer=69 (sum for u = 101 but it's foo's local v, right?)
PS: I'm trying to practice doing some exercises like this if you know where I can find these types of problems (preferable with solutions) please give the link, thanks!
Your answer for lexical (static) scope is correct. Your answers for dynamic scope are wrong, but if I'm reading your explanations right, it's because you got confused between u and v, rather than because of any real misunderstanding about how deep and shallow binding work. (I'm assuming that your u/v confusion was just accidental, and not due to a strange confusion about values vs. references in the call to foo.)
a) using static scope? answer=180
Correct.
b) using dynamic scope and deep binding? answer=69 (sum for u = 126 but it's foo's local v, right?)
Your parenthetical explanation is right, but your answer is wrong: u is indeed set to 126, and foo indeed localizes v, but since main prints u, not v, the answer is 126.
c) using dynamic scope and shallow binding? answer=69 (sum for u = 101 but it's foo's local v, right?)
The sum for u is actually 97 (42+13+42), but since bar localizes u, the answer is 42. (Your parenthetical explanation is wrong for this one — you seem to have used the global variable w, which is 17, in interpreting the statement int u := w in the definition of bar; but that statement actually refers to foo's local variable w, its second parameter, which is 13. But that doesn't actually affect the answer. Your answer is wrong for this one only because main prints u, not v.)
For lexical scope, it's pretty easy to check your answers by translating the pseudo-code into a language with lexical scope. Likewise dynamic scope with shallow binding. (In fact, if you use Perl, you can test both ways almost at once, since it supports both; just use my for lexical scope, then do a find-and-replace to change it to local for dynamic scope. But even if you use, say, JavaScript for lexical scope and Bash for dynamic scope, it should be quick to test both.)
Dynamic scope with deep binding is much trickier, since few widely-deployed languages support it. If you use Perl, you can implement it manually by using a hash (an associative array) that maps from variable-names to scalar-refs, and passing this hash from function to function. Everywhere that the pseudocode declares a local variable, you save the existing scalar-reference in a Perl lexical variable, then put the new mapping in the hash; and at the end of the function, you restore the original scalar-reference. To support the binding, you create a wrapper function that creates a copy of the hash, and passes that to its wrapped function. Here is a dynamically-scoped, deeply-binding implementation of your program in Perl, using that approach:
#!/usr/bin/perl -w
use warnings;
use strict;
# Create a new scalar, initialize it to the specified value,
# and return a reference to it:
sub new_scalar($)
{ return \(shift); }
# Bind the specified procedure to the specified environment:
sub bind_proc(\%$)
{
my $V = { %{+shift} };
my $f = shift;
return sub { $f->($V, #_); };
}
my $V = {};
$V->{u} = new_scalar 42; # int u := 42
$V->{v} = new_scalar 69; # int v := 69
$V->{w} = new_scalar 17; # int w := 17
sub add(\%$)
{
my $V = shift;
my $z = $V->{z}; # save existing z
$V->{z} = new_scalar shift; # create & initialize new z
${$V->{u}} = ${$V->{v}} + ${$V->{u}} + ${$V->{z}};
$V->{z} = $z; # restore old z
}
sub bar(\%$)
{
my $V = shift;
my $fun = shift;
my $u = $V->{u}; # save existing u
$V->{u} = new_scalar ${$V->{w}}; # create & initialize new u
$fun->(${$V->{v}});
$V->{u} = $u; # restore old u
}
sub foo(\%$$)
{
my $V = shift;
my $x = $V->{x}; # save existing x
$V->{x} = new_scalar shift; # create & initialize new x
my $w = $V->{w}; # save existing w
$V->{w} = new_scalar shift; # create & initialize new w
my $v = $V->{v}; # save existing v
$V->{v} = new_scalar ${$V->{x}}; # create & initialize new v
bar %$V, bind_proc %$V, \&add;
$V->{v} = $v; # restore old v
$V->{w} = $w; # restore old w
$V->{x} = $x; # restore old x
}
foo %$V, ${$V->{u}}, 13;
print "${$V->{u}}\n";
__END__
and indeed it prints 126. It's obviously messy and error-prone, but it also really helps you understand what's going on, so for educational purposes I think it's worth it!
Simple and deep binding are Lisp interpreter viewpoints of the pseudocode. Scoping is just pointer arithmetic. Dynamic scope and static scope are the same if there are no free variables.
Static scope relies on a pointer to memory. Empty environments hold no symbol to value associations; denoted by word "End." Each time the interpreter reads an assignment, it makes space for association between a symbol and value.
The environment pointer is updated to point to the last association constructed.
env = End
env = [u,42] -> End
env = [v,69] -> [u,42] -> End
env = [w,17] -> [v,69] -> [u,42] -> End
Let me record this environment memory location as AAA. In my Lisp interpreter, when meeting a procedure, we take the environment pointer and put it our pocket.
env = [add,[closure,(lambda(z)(setq u (+ v u z)),*AAA*]]->[w,17]->[v,69]->[u,42]->End.
That's pretty much all there is until the procedure add is called. Interestingly, if add is never called, you just cost yourself a pointer.
Suppose the program calls add(8). OK, let's roll. The environment AAA is made current. Environment is ->[w,17]->[v,69]->[u,42]->End.
Procedure parameters of add are added to the front of the environment. The environment becomes [z,8]->[w,17]->[v,69]->[u,42]->End.
Now the procedure body of add is executed. Free variable v will have value 69. Free variable u will have value 42. z will have the value 8.
u := v + u + z
u will be assigned the value of 69 + 42 + 8 becomeing 119.
The environment will reflect this: [z,8]->[w,17]->[v,69]->[u,119]->End.
Assume procedure add has completed its task. Now the environment gets restored to its previous value.
env = [add,[closure,(lambda(z)(setq u (+ v u z)),*AAA*]]->[w,17]->[v,69]->[u,119]->End.
Notice how the procedure add has had a side effect of changing the value of free variable u. Awesome!
Regarding dynamic scoping: it just ensures closure leaves out dynamic symbols, thereby avoiding being captured and becoming dynamic.
Then put assignment to dynamic at top of code. If dynamic is same as parameter name, it gets masked by parameter value passed in.
Suppose I had a dynamic variable called z. When I called add(8), z would have been set to 8 regardless of what I wanted. That's probably why dynamic variables have longer names.
Rumour has it that dynamic variables are useful for things like backtracking, using let Lisp constructs.
Static binding, also known as lexical scope, refers to the scoping mechanism found in most modern languages.
In "lexical scope", the final value for u is neither 180 or 119, which are wrong answers.
The correct answer is u=101.
Please see standard Perl code below to understand why.
use strict;
use warnings;
my $u = 42;
my $v = 69;
my $w = 17;
sub add {
my $z = shift;
$u = $v + $u + $z;
}
sub bar {
my $fun = shift;
$u = $w;
$fun->($v);
}
sub foo {
my ($x, $w) = #_;
$v = $x;
bar( \&add );
}
foo($u,13);
print "u: $u\n";
Regarding shallow binding versus deep binding, both mechanisms date from the former LISP era.
Both mechanisms are meant to achieve dynamic binding (versus lexical scope binding) and therefore they produce identical results !
The differences between shallow binding and deep binding do not reside in semantics, which are identical, but in the implementation of dynamic binding.
With deep binding, variable bindings are set within a stack as "varname => varvalue" pairs.
The value of a given variable is retrieved from traversing the stack from top to bottom until a binding for the given variable is found.
Updating the variable consists in finding the binding in the stack and updating the associated value.
On entering a subroutine, a new binding for each actual parameter is pushed onto the stack, potentially hiding an older binding which is therefore no longer accessible wrt the retrieving mechanism described above (that stops at the 1st retrieved binding).
On leaving the subroutine, bindings for these parameters are simply popped from the binding stack, thus re-enabling access to the former bindings.
Please see the the code below for a Perl implementation of deep-binding dynamic scope.
use strict;
use warnings;
use utf8;
##
# Dynamic-scope deep-binding implementation
my #stack = ();
sub bindv {
my ($varname, $varval);
unshift #stack, [ $varname => $varval ]
while ($varname, $varval) = splice #_, 0, 2;
return $varval;
}
sub unbindv {
my $n = shift || 1;
shift #stack while $n-- > 0;
}
sub getv {
my $varname = shift;
for (my $i=0; $i < #stack; $i++) {
return $stack[$i][1]
if $varname eq $stack[$i][0];
}
return undef;
}
sub setv {
my ($varname, $varval) = #_;
for (my $i=0; $i < #stack; $i++) {
return $stack[$i][1] = $varval
if $varname eq $stack[$i][0];
}
return bindv($varname, $varval);
}
##
# EXERCICE
bindv( u => 42,
v => 69,
w => 17,
);
sub add {
bindv(z => shift);
setv(u => getv('v')
+ getv('u')
+ getv('z')
);
unbindv();
}
sub bar {
bindv(fun => shift);
setv(u => getv('w'));
getv('fun')->(getv('v'));
unbindv();
}
sub foo {
bindv(x => shift,
w => shift,
);
setv(v => getv('x'));
bar( \&add );
unbindv(2);
}
foo( getv('u'), 13);
print "u: ", getv('u'), "\n";
The result is u=97
Nevertheless, this constant traversal of the binding stack is costly : 0(n) complexity !
Shallow binding brings a wonderful O(1) enhanced performance over the previous implementation !
Shallow binding is improving the former mechanism by assigning each variable its own "cell", storing the value of the variable within the cell.
The value of a given variable is simply retrieved from the variable's
cell (using a hash table on variable names, we achieve a
0(1) complexity for accessing variable's values!)
Updating the variable's value is simply storing the value into the
variable's cell.
Creating a new binding (entering subs) works by pushing the old value
of the variable (a previous binding) onto the stack, and storing the
new local value in the value cell.
Eliminating a binding (leaving subs) works by popping the old value
off the stack into the variable's value cell.
Please see the the code below for a trivial Perl implementation of shallow-binding dynamic scope.
use strict;
use warnings;
our $u = 42;
our $v = 69;
our $w = 17;
our $z;
our $fun;
our $x;
sub add {
local $z = shift;
$u = $v + $u + $z;
}
sub bar {
local $fun = shift;
$u = $w;
$fun->($v);
}
sub foo {
local $x = shift;
local $w = shift;
$v = $x;
bar( \&add );
}
foo($u,13);
print "u: $u\n";
As you shall see, the result is still u=97
As a conclusion, remember two things :
shallow binding produces the same results as deep binding, but runs faster, since there is never a need to search for a binding.
The problem is not shallow binding versus deep binding versus
static binding BUT lexical scope versus dynamic scope (implemented either with deep or shallow binding).