procedural language understanding - static vs dynamic scoping - scope

I am having trouble understanding the answer to a homework we got back. I believe I am getting confused on the concepts of functions being "nested", but maybe that is wrong. I am looking for some help in regards to following the assignment of dynamic and static scoping values from the following code.
x : integer -- global
procedure set_x(n : integer)
x := n
end
procedure print_x
write_integer(x)
end
procedure first
set_x(1)
print_x
end
procedure second
x : integer
set_x(2)
print_x
end
// program starts here
set_x(0)
first()
print_x
second()
print_x
Static Scoping Output: 1122
Dynamic Scoping Output: 1121
My thoughts as I go through each one:
Static:
Run set_x(0), this makes a local variable due to the parameter of n, but since we set x to n without declaring x locally (int x =..) we then update the global x to 0.
Run first(), which does set_x(1), which following the same logic updates x to 1 globally. we then run print_x within first which prints the global x of 1.
Run print_x, which just re-prints 1.
Run second() we locally declare x and run set_x(2), which goes updates 2 to n. (because of the set, not the second procedure, right? We then run its print_x procedure which prints the 2.
Run print_x which again just dumps out the 2.
Resulting in 1122
Dynamic (more confused on this one)
Run set_x(0) which sets the x and global x to 0.
Run first() we hit set_x again and update x to 1. We print 1.
Run print_x We re-print 1.
Run second() We locally make x, we run set_x(2), and set global x to 2. We then print 2.
Run print_x Finally we re-print again and here is where I guessed 2, but the answer should 1.
My guess 1122, actual answer is 1121
I am confused on that last part of the dynamic and why it is a 1, and not a 2.

It's kind of hard to follow your reasoning in some places, because you don't say which x you think is being printed or updated, and that's pretty much the whole ball of wax.
The big thing to remember is that static scoping (also called lexical scoping) is fully determined at compile-time. Where something is defined determines its static scope.
Dynamic scoping is of course the converse; it's determined at run-time. Where something executes determines its dynamic scope.
So, take a look at the set_x procedure. It has no local x of its own, and it's defined in the global scope, so under static scoping, it can only ever update the global x. This is true no matter where it is called, even within the second procedure.
Under dynamic scoping, however, the set_x call within second updates the x which is local to second, leaving the global x unchanged.
Notice that the very last print_x call will always print the global x, regardless of the scoping rules (because the print_x procedure is defined in the global scope, and the call to print_x is executed in the global scope). So the difference is that with static scoping, global x is 2 at the end of the program; but with dynamic scoping, global x is 1.

Related

PyQT QPushButton Connection Problem - Wrong function being called [duplicate]

Im trying to build a calculator with PyQt4 and connecting the 'clicked()' signals from the buttons doesn't work as expected.
Im creating my buttons for the numbers inside a for loop where i try to connect them afterwards.
def __init__(self):
for i in range(0,10):
self._numberButtons += [QPushButton(str(i), self)]
self.connect(self._numberButtons[i], SIGNAL('clicked()'), lambda : self._number(i))
def _number(self, x):
print(x)
When I click on the buttons all of them print out '9'.
Why is that so and how can i fix this?
This is just, how scoping, name lookup and closures are defined in Python.
Python only introduces new bindings in namespace through assignment and through parameter lists of functions. i is therefore not actually defined in the namespace of the lambda, but in the namespace of __init__(). The name lookup for i in the lambda consequently ends up in the namespace of __init__(), where i is eventually bound to 9. This is called "closure".
You can work around these admittedly not really intuitive (but well-defined) semantics by passing i as a keyword argument with default value. As said, names in parameter lists introduce new bindings in the local namespace, so i inside the lambda then becomes independent from i in .__init__():
self._numberButtons[i].clicked.connect(lambda checked, i=i: self._number(i))
UPDATE: clicked has a default checked argument that would override the value of i, so it must be added to the argument list before the keyword value.
A more readable, less magic alternative is functools.partial:
self._numberButtons[i].clicked.connect(partial(self._number, i))
I'm using new-style signal and slot syntax here simply for convenience, old style syntax works just the same.
You are creating closures. Closures really capture a variable, not the value of a variable. At the end of __init__, i is the last element of range(0, 10), i.e. 9. All the lambdas you created in this scope refer to this i and only when they are invoked, they get the value of i at the time they are at invoked (however, seperate invocations of __init__ create lambdas referring to seperate variables!).
There are two popular ways to avoid this:
Using a default parameter: lambda i=i: self._number(i). This work because default parameters bind a value at function definition time.
Defining a helper function helper = lambda i: (lambda: self._number(i)) and use helper(i) in the loop. This works because the "outer" i is evaluated at the time i is bound, and - as mentioned before - the next closure created in the next invokation of helper will refer to a different variable.
Use the Qt way, use QSignalMapper instead.

Declaring variables inside a function python

For some reason I keep getting error in my code stating that my variables have not been declared. This only happens when I try to declare them in a function and not outside.
example
x, y = 105,107
print (x,y)
the above line of code works and gives me the output 105 107
but when I do this below
def fun1():
x, y = 105,107
print (x,y)
I get NameError: name 'x' is not defined
need help to understand what's happening.
One of the main utilities of functions is exactly the way they allow one
to isolate variables - no worries about clashing names for the code
in various functions - once a function works properly, it is done.
But if one needs to expose variables that populated inside functions to
the outside world, it is possible with the keyword "global". Notice that this
is in general considered bad practice, and even for small scripts,
there are often better solutions. But, common sense should always be the rule:
def fun1():
global x, y
x, y = 105, 107
fun1()
print(x, y)
Note that your code had another incorrect assumption: code
inside function bodies is not executed unless the function is called -
so, in the example in your question, even if you had declared
the variables as global, the print call would still
raise the same error, since you are not executing the line
that defines these variables by calling the function.
Now, you've learned about "globals" - next step is forget it
exists and learn how to work with variables properly encapsulated
inside functions, and when you get to some intermediate/advanced
level, then you will be able to judge when "globals" might actually
do more good than harm (which is almost never).

How a function in python can access the values which are declared outside its block and never passed as arguments during its call?

I have written a Python code in which a function without parameters can access the variable declared outside its scope. I want to know how Python interpreter can access this variable without giving any error like other programming languages(e.g. JAVA).
# Code 1:
def A():
# count accessed inside function
print(count)
# count declared outside function A
count = 23
A()
Output of code 1:
23
There is a bonus question also. In Python, if we declare any variable inside the loop then how it can used outside the loop. Because, as we know that the scope of any variable will remain under the block in which it is defined.
# Code 2:
for i in range(1):
# num declared inside for loop block
num = 23
# num can be accessed outside for loop block.
print(num)
Output of code 2: 23
Variable scope is inside-out. When you call a variable from inside a local scope like a function, first Python checks if there's a variable with that name in the local scope. If it doesn't find one, it expands the scope it checks in to the next outer scope. In your case, this is the global scope, the top-most level of scope. Declaring something absent of any context like a function or method defaults to the global scope, so that's where count lives.
If you want to be clear about which count it is you're referencing, you can add nonlocal count or global count to your function definition, making it explicit that you're referencing the a different scope.
Bonus question -- You can't reference a locally-scoped variable outside of its scope, so it doesn't work in reverse, sorry. However in your example you're using a loop, which does not have its own scope in Python (but Julia does, so if you ever make that switch heads up).

Turn ALL current workspace variables into global variables

I have an aged code from different authors who use global variables over many years and the following challenge: I imported several (>200) variables from an excel file. They are not inside a function and they are not designated as global. For the function to work, they have to be because there is one function1 which calls a function 2. Function 1 is called once only while function 2 is called >10000 times, so I wish anything global to be inside function 1. How can I easily turn all of them into global variables and pass them to function 2?
example (scheme)
% function1
% global *other variables exist here already*
% this function calls function2 at a certain point further below
L=whos
save L % some variables a b c ... are parameters in function2
% function2
% global *other variables exist here already*
load L % i dont want to load my workspace everytime, I rather wish to just access global variables a b c...
% the problem is that my variables sometimes change name and I want to have
% them all global in an automatic way. Or live with a workaround.
Thank you for your patience and I am ready to take questions!
UPDATE I:
I managed a workaround with which im not entirely happy because it involves manual manipulation in the code. So it is a temporary solution at best.
% lets say you have some workspace variables and you save them under this name, and then load them:
load workspacevars.mat;
L=who % gives you those variable's names as string column
L=L' % and in a form that makes you able to use it as global (as row)
% unfortunately using global L doesnt work for me. any ideas?
% I had to go to L in the workspace, and click and drag the resulting long string into a text editor.
% there, I removed the braces {} and the '' because this is how global likes to have their variables: pure.
% finally it looks like this: global var1 var2 var3 ....
The answer is, use structure files instead of globals.
once the struct is created, (c.constant1, c.constant2...), you just give the function in question c. I used to work with workspace a lot, which explains why I save my workspace and load it once (not many times since constants dont change) so this is how it looks for me:
mainfunction
c.constant1=1;
save c.mat
[Time,Results] = ode15s(#(x, c) f1(x, c),[0 c.length],x0,options)
end
function [OUTPUT] = f1(t, x, c)
load c.mat
end
inputs are x and c and they can be freely shared between both the main and the subfunction. If constants should change due to some events in the function, they may be saved with an if conditions inside the subfunction and are reloaded in the next iteration of the code (but this is another issue adressed here: Change a constant in ODE calculations under particular conditions with a flag)

Scope of functions and variables within a function and/or let statement for lisp

I'm having some trouble understanding the scope of variables and functions when defined inside a function call. I tried searching for this scope, but could not find a suitable answer (or maybe was searching for the wrong thing), so I decided to write a few functions to test things myself:
(defun test-scope1 ()
(setf myvar 1)
(defun set-var1 ()
(setf myvar 2))
(set-var1))
With this function I just wanted to see if anything gets set global. I would expect myvar and set-var to be defined globally because I have no scope here. As expected, before calling (test-scope1) the commands myvar and (set-var) give me errors. After calling (test-scope1), I can run myvar and (set-var) in the interpreter to yield 2.
Thinking to myself it would be nice to encapsulate my variables, I decided to add a let inside my function, therefore getting my next test:
(defun test-scope2 ()
(let ((myvar 10))
(defun set-var2 ()
(setf myvar 20))
(set-var2)))
I would expect myvar to be stuck in the scope of the let block, but wouldn't be able to guess for set-var2. It could be stuck in the let block or it could be defined globally. After running (test-scope2) I try to access myvar and get 2. That means this new function has its own myvar since it's still 2 from the previous function. I try running (set-var2)and get 20.
I'm not completely surprised that the function is defined globally after being run in the let block, but now I'm very confused what myvar variable its accessing. Since it didn't change my global copy of myvar, it would seem there's some variable floating around it still refers to.
Now I want to see if I can manipulate that floating variable, so I create this third function.
(defun test-scope3 ()
(let ((myvar (if (ignore-errors myvar)
myvar
100)))
(defun set-var3 ()
(setf myvar (+ myvar 100)))
(set-var3)))
Instead of just setting the variable to a fixed value, I want to increment it based on the previous value. I check two things here. The first is when test-scope3 is called. I wanted to see if I could pull up a "previous value" of myvar, since if it's floating around somewhere maybe I can access it again. It probably wouldn't be good practice, but that's not the point here. Ignore-errors is there in case there wasn't really a previous value floating around, in which case I choose a default of 100.
The second thing I test is to have set-var3 add 100 to the previous the value of myvar. I want to see if this will adjust that floating variable, or if somehow is something static. I have no idea what my function "should" return.
After running (test-scope3) I'm completely surprised to see 102. So apparently my test-scope3 found the value of myvar from running test-scope1. But, after checking the value of myvar in the interpreter, it is still 2. Next I run (set-var3) and get a return value of 202. Okay, so it added 100 again to my previous value. Calling it again returns 302 and so on. But, calling (test-scope3) again resets this value back down to 102.
I wrote one more function as a double nested let command. I just ran this in two ways: with no myvar definition for the let arguments. This function returns 10002. Then, I tried setting the local myvar to 50 and had 1050 return.
(defun test-scope4 ()
(let () ; or ((myvar 50))
(let ((myvar (if (ignore-errors myvar)
myvar
2000)))
(defun set-var4 ()
(setf myvar (+ myvar 1000)))
(set-var4))))
So, with all this together, here are some of my specific questions:
When I do a defun inside another defun, even in a let block, why does that function become accessible globally?
When I call set-var#, what variables (or within what scope) is this accessing? Or maybe more appropriately, when I define a function inside another statement, what am I actually binding?
When I use the variable myvarin a function, where does this pull from? From my 4th example conjecture is that it looks for the symbol myvar in the current scope, then checks up one level higher until it finds a value for it.
Sorry if everything was very wordy and my questions ill-formed. I tried to investigate things to the best of my ability. Really this all leads to my real question, which after writing everything up I realize might be beyond the scope (no pun intended) of this question as I've set it up so far.
The issue of hiding my inner functions as given above could be handled with a lambda expression; however, what I'd really love to do is to have a recursive function inside of a bigger block that uses the block to store values without feeding them directly into the function. To my knowledge, this is not possible with a lambda expression. For example, consider the following function which does this.
(defun outer-function (start)
(let ((x start))
(defun increment-to-ten ()
(setf x (+ x 1))
(if (< x 10)
(increment-to-ten)))
(increment-to-ten)
(print x)))
Which could be instead implemented recursively with arguments as
(defun increment-to-ten-recursive (x)
(if (< x 10)
(increment-to-ten-recursive (+ x 1))
10))
If there's a solution for this, that would be great, or if my thinking is completely wrong and there's a better way to do this that would be great to. It just seems convenient to have a block store data for you and then just call a recursive function with no arguments to work on that data.
Why it is difficult to discuss the effects you see:
You are doing things which are undefined in Common Lisp: setting undeclared variables in test-scope1: myvar. It's from then on unclear how the following code behaves.
Undeclared Variables
It is undefined what effect it has when an undeclared variable foo is set. Implementations allow it. Some will warn. SBCL:
* (setf foo 10)
; in: SETF FOO
; (SETF FOO 10)
; ==>
; (SETQ FOO 10)
;
; caught WARNING:
; undefined variable: FOO
;
; compilation unit finished
; Undefined variable:
; FOO
; caught 1 WARNING condition
Global variables are defined with DEFPARAMETER and DEFVAR. Local variables are defined by LET, LET* and by functions parameters. Since DEFPARAMETER and DEFVAR define global special (using dynamic binding) variables, it is common to write them as *some-variable* - note the * around it, which are part of the symbol name and not special syntax. It's a convention for special variables.
Nested DEFUNs
Nested DEFUNs are not used in Common Lisp. DEFUN is a top-level form, which sets a global function. To define local functions use FLET and LABELS. You can nest DEFUN forms, but it is bad style and you won't find it used in actual Lisp code. Don't nest DEFUN forms. Note: this is different from Scheme, where one can nest DEFINE forms. Since nested DEFUNs are not used, it makes little sense to discuss the effects. Convert the examples to use local functions defined by FLET or LABELS.
When I do a defun inside another defun, even in a let block, why does that function become accessible globally?
Because DEFUN defines global functions. That's its purpose.
You need to rewrite your examples to make it possible to discuss the effects:
declare all variables
don't use nested DEFUNs
We could try to understand the code you have in your current examples, but much depends on the implementation and the sequence of actions. We are either not in the realm of portable Common Lisp or doing stuff (nested DEFUNs), which has no practical use in Common Lisp.
As Rainer explained, the answer to your first question is that defun defines global functions. Use labels to define local functions.
Rainer is also right about much being dependent on the configuration of your lisp. Many Lisps know about two types of scope, lexical and dynamic. Lexical scope is the one you can see when you look at a page of code, and what you're used to from most other programming languages. Dynamic scope is what you get when you a lisp looks for the value of a variable in the environment where the function was called instead of the one where it was defined.
Finally, your code makes usse of closures. When you put a lambda (defun) inside a let, you create a closure, e.g. your variables "hang or float around" for the function to use in the future even when the function that contains them returns to it's caller.
So here's what might be going on (as Rainer said, it's hard to know since you're doing things that usually aren't done, such as nesting defuns):
So... probably, test-scope1 uses a global myvar and it's set-var references the global myvar since we are dealing with lexical scope. test-scope2 builds a closure, which creates a myvar with lexical scope only accessible to set-var2. Since this myvar has lexical scope, the call to set-var in test-scope2 will not use this myvar but still the global one.
I'm not sure why calling test-scope3 gets you 102, since test-scope3 just calls set-var, which should set the global myvar to 2, not 102. The only code that could explain 102 is in set-var3, and this isn't being called when you call test-scope3. Here's what might be going on if you got 2 instead of 102 when calling test-scope3:
(defun test-scope3 ()
(let ((myvar (if (ignore-errors myvar)
myvar
100)))
(defun set-var3 ()
(setf myvar (+ myvar 100)))
(set-var)))
With the let, you create a local binding for myvar with lexical scope, but you refer to the global myvar in it's binding form - the (if (ignore-errors myvar) myvar). Later on you call set-var, which should again reference the global myvar since test'scope3's let uses lexical scope for the binding of myvar. Then, wen you call set-var3 for the first time, it takes the myvar bound by the above let, which currently has a value of 2, and adds 100 to it. When you call it the second time, you again add 100 to the lexically bound myvar which still hangs around in the closure you built in test-scope3, and so on. But when you call test-scope3 again, you create a new closure (but replace the old one because you use defun to give the same name to it...) which again sets the initial value of the closed-over myvar to the value of the global myvar, which is 2.
I suggest you read Paul Graham's excellent ANSI Common Lisp and On Lisp, which explain special variables (dynamic scope), lexical scope and closures in depth.
Here's how you might have several closures share variables:
(let ((myvar 0))
(defun reset ()
(setf myvar 0)
(defun inc ()
(setf myvar (+ myvar 1))))
This builds two closures and makes them share myvar, and since myvar has lexical scope you can't access this copy of myvar from anywhere else. So you've basically given exclusive control of myvar to reset and inc.
This could be one way to build your recursive function that doesn't need a value passed into it with each iteration.

Resources