1. scope of variables
- Posted by coconut Dec 29, 2010
- 3027 views
enum a,b while 1 do integer b -- the scope of this variable should be limited to the while b=1 ?b exit end while
trying to run that code report an arror saying that b is already defined. It's not what I would have expected. In other languages that permit variable declaration inside code block the scope is limited to the block.
I opened a ticket for this. It is a bug.
Jacques
2. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2982 views
enum a,b while 1 do integer b -- the scope of this variable should be limited to the while b=1 ?b exit end while
trying to run that code report an arror saying that b is already defined. It's not what I would have expected. In other languages that permit variable declaration inside code block the scope is limited to the block.
It is defined already. enum b. Euphoria's scoping does not allow multiple definition but its scoping works correctly. For example:
integer a while 1 do integer a end while
That also is an error. Now:
integer a for i = 1 to 5 do integer b = 20 end for ? b
That is also an error, i.e. the ? b is used outside the scope of b, thus b is not defined in that instance.
Jeremy
3. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2921 views
I desagree with you on this. The rules of lexical scoping are so that you can define a variable of the same name inside narrower scope and this new variable will shadow the outer one.
integer a procedure foo() integer a -- this is accepted and this new 'a' shadow the outer one. ... end procedure -- the same should be true with this while 1 do integer a -- this should be accepted and shadow the 'a' at top level. ... end while
look at others languages that implement scoping at block level (at think lua does) and you'll see that it is done as I says.
Jacques
4. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2948 views
I desagree with you on this. The rules of lexical scoping are so that you can define a variable of the same name inside narrower scope and this new variable will shadow the outer one. look at others languages that implement scoping at block level (at think lua does) and you'll see that it is done as I says.
Various languages do this. Euphoria is not one of them. Maybe it should be brought up for discussion as to make it do this in a future version but as of 4.0 this is not a bug, it is its design. I personally feel that shadowing variables is a bad idea and shouldn't be used in code.
To start the dialog, in what situation would it be beneficial to allow duplicate variable names of various types?
Jeremy
5. Re: scope of variables
- Posted by DerekParnell (admin) Dec 30, 2010
- 2940 views
I desagree with you on this. The rules of lexical scoping are so that you can define a variable of the same name inside narrower scope and this new variable will shadow the outer one.
look at others languages that implement scoping at block level (at think lua does) and you'll see that it is done as I says.
I also think that Euphoria should be consistent with many other languages. Namely that 'if', 'else', 'while', 'loop', and 'for' statements begin a new block and that blocks have their own scope.
However this type of lexical scoping is not one of Nature's Axioms and instead is left up to the language designer. So it is perfectly reasonable to leave Euphoria as is, unless we, as a community, decide that it should change.
6. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2939 views
I desagree with you on this. The rules of lexical scoping are so that you can define a variable of the same name inside narrower scope and this new variable will shadow the outer one.
look at others languages that implement scoping at block level (at think lua does) and you'll see that it is done as I says.
I also think that Euphoria should be consistent with many other languages. Namely that 'if', 'else', 'while', 'loop', and 'for' statements begin a new block and that blocks have their own scope.
However this type of lexical scoping is not one of Nature's Axioms and instead is left up to the language designer. So it is perfectly reasonable to leave Euphoria as is, unless we, as a community, decide that it should change.
I agree 100% with Derek on this. Derek, you put it better than I ever could have.
7. Re: scope of variables
- Posted by jaygade Dec 30, 2010
- 2945 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
8. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2936 views
It's not coherent. As you decided to add scoping at block level the same rules should apply as in others structures i.e. functions, procedures, files. Although it's not a rule of nature it make the semantic more coherent.
I hope you will consider changing it in future release.
Jacques
9. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2908 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
Changed in what way? There are two possible options here:
integer a = 10 procedure abc() integer a = 20 -- INVALID, a already exists in a containing scope end procedure
and the other change is to make all scopes work like this
integer a = 10 procedure abc() integer a = 20 ? a end procedure -- procedure output is 20
We have to think carefully about this. I'll ask my question again since it seems to be ignored, what is a valid use of redefining a variable in a more narrow scope? In the directly above synario you have now cut off all possibility of accessing the file wide a. Why would you want to do that? Bearing in mind that in a real application there would not be a file wide variable named a, it would be something useful such with a useful name.
For me it seems much more prudent that if there were to be a change the change to be never to allow a variable inside the same namespace to be redeclared. One may say it's heresy, but please tell me why and give valid examples as to why it is necessary to redefine a variable in a more narrow scope to mean something totally different than what it means in a file wide scope.
Jeremy
10. Re: scope of variables
- Posted by jaygade Dec 30, 2010
- 2906 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
Changed in what way? There are two possible options here:
integer a = 10 procedure abc() integer a = 20 -- INVALID, a already exists in a containing scope end procedure
and the other change is to make all scopes work like this
integer a = 10 procedure abc() integer a = 20 ? a end procedure -- procedure output is 20
The second, of course.
We have to think carefully about this. I'll ask my question again since it seems to be ignored, what is a valid use of redefining a variable in a more narrow scope? In the directly above synario you have now cut off all possibility of accessing the file wide a. Why would you want to do that? Bearing in mind that in a real application there would not be a file wide variable named a, it would be something useful such with a useful name.
I don't think there is a valid use. But I don't think there's much of a valid use for block variables anyway outside of the for loop index variable. If you need privately scoped variables you should be using a procedure or function anyway.
But the feature has been added and it should be consistent with the way that it works in procedures and functions. That is my reason for voting the way I did.
For me it seems much more prudent that if there were to be a change the change to be never to allow a variable inside the same namespace to be redeclared. One may say it's heresy, but please tell me why and give valid examples as to how it is necessary to redefine a variable in a more narrow scope to mean something totally different than what it means in a file wide scope.
Jeremy
You say you wouldn't have a variable "a" as a file-wide variable. Or even a procedure-wide variable if we're working within a procedure block. And yet, you could. Maybe your file is pretty big and you defined a variable "idx" near the top. You cut and paste a block of code from another program you wrote but end up with a name clash because the block defines its own "idx" variable. Maybe the block is really long too and you don't want to go through and change "idx" to "idy" in every instance.
Contrived? Yes. Bad programming practice? Probably. But other features have been added to 4.0 which enable bad programming practices. Either because they are useful in some small circumstances or because they were requested.
Anyway, it's not a feature that I will use. I just think that it should be consistent. That's my reason for my vote.
11. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2896 views
integer a = 10 procedure abc() integer a = 20 -- INVALID, a already exists in a containing scope end procedure
and the other change is to make all scopes work like this
integer a = 10 procedure abc() integer a = 20 ? a end procedure -- procedure output is 20
We have to think carefully about this. I'll ask my question again since it seems to be ignored, what is a valid use of redefining a variable in a more narrow scope? In the directly above synario you have now cut off all possibility of accessing the file wide a. Why would you want to do that? Bearing in mind that in a real application there would not be a file wide variable named a, it would be something useful such with a useful name.
For me it seems much more prudent that if there were to be a change the change to be never to allow a variable inside the same namespace to be redeclared. One may say it's heresy, but please tell me why and give valid examples as to why it is necessary to redefine a variable in a more narrow scope to mean something totally different than what it means in a file wide scope.
Jeremy
I'm going to go against the grain here. I'm fine with this breaking:
for .. integer b end for integer b
That should cause a redefinition error IMVHO. That'd make the behavior consistent and also keep things simple.
The only exception to this rule should be the one that was inherited from pre-4.0 - so locally defining a variable in a file and then redefining it inside a routine is ok.
12. Re: scope of variables
- Posted by DerekParnell (admin) Dec 30, 2010
- 2912 views
To start the dialog, in what situation would it be beneficial to allow duplicate variable names of various types?
I believe it is not a good coding practice because it hinders, rather than enhances, readability of code. When the reader sees 'b = somefunc()' they might get confused if they missed seeing that 'b' was also declared in the local block.
However sometimes when code is 'copy&pasted', shadowed identifiers can get accidentally created - and the code still works. Ideally in that situation, the coder should re-factor the names to better reflect the copied code's new "environment".
13. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2897 views
I don't think there is a valid use. But I don't think there's much of a valid use for block variables anyway outside of the for loop index variable. If you need privately scoped variables you should be using a procedure or function anyway.
This is the main reason why if a change occurs I think it should be the first. Do not allow re-definition of a variable in a child scope, whether that be a procedure, if, for or whatever.
But the feature has been added and it should be consistent with the way that it works in procedures and functions. That is my reason for voting the way I did.
The first solution is making it consistent.
You say you wouldn't have a variable "a" as a file-wide variable. Or even a procedure-wide variable if we're working within a procedure block. And yet, you could. Maybe your file is pretty big and you defined a variable "idx" near the top. You cut and paste a block of code from another program you wrote but end up with a name clash because the block defines its own "idx" variable. Maybe the block is really long too and you don't want to go through and change "idx" to "idy" in every instance.
Contrived? Yes. Bad programming practice? Probably. But other features have been added to 4.0 which enable bad programming practices. Either because they are useful in some small circumstances or because they were requested.
I do not think features were added by mere request. They had to have valid uses. Everything added in 4.0 has a valid use. Everything in programming including a procedure, an if statement and goto can be misused but all have very valid purposes. Re-defining a variable of a different type, cutting off access to higher scope leveled variables I personally do not see a valid reason for. Nor do you it appears. Add it because we can? I don't think that's wise and it has not been the practice thus far w/Euphoria. It shouldn't start to be either.
Obviously quite a few people have not chimed in yet, so I'm sure a lot more discussion to follow!
Jeremy
14. Re: scope of variables
- Posted by jaygade Dec 30, 2010
- 2885 views
I don't think there is a valid use. But I don't think there's much of a valid use for block variables anyway outside of the for loop index variable. If you need privately scoped variables you should be using a procedure or function anyway.
This is the main reason why if a change occurs I think it should be the first. Do not allow re-definition of a variable in a child scope, whether that be a procedure, if, for or whatever.
But the feature has been added and it should be consistent with the way that it works in procedures and functions. That is my reason for voting the way I did.
The first solution is making it consistent.
Consistent with what? Procedures and functions are self-contained pieces of code. By enabling variables to be defined with in certain other blocks, those blocks also become self-contained pieces of code. One thing is like the other. Consistent. The only other way to make it consistent is to remove the ability to define variables in a block at all.
15. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2892 views
Consistent with what? Procedures and functions are self-contained pieces of code. By enabling variables to be defined with in certain other blocks, those blocks also become self-contained pieces of code. One thing is like the other. Consistent. The only other way to make it consistent is to remove the ability to define variables in a block at all.
Maybe my original example was unclear. Here is another of what I consider to be the proper solution
integer file_log_level = log:WARNING procedure abc() integer abc = 20 -- VALID integer file_log_level = log:ERROR -- INVALID if 10 then integer def -- VALID integer abc -- INVALID end if end procedure
i.e. redefinition of any variable in any child scope is invalid. This is consistent and good practice. There is no reason to redefine file_log_level inside of a procedure or any child scope.
Jeremy
16. Re: scope of variables
- Posted by DerekParnell (admin) Dec 30, 2010
- 2872 views
A compromise might be that we allow shadowed identifiers, but make it a warning when it happens.
The other related issue is how does one refer to the enclosing block's identifier if it has been shadowed?
17. Re: scope of variables
- Posted by jaygade Dec 30, 2010
- 2887 views
Consistent with what? Procedures and functions are self-contained pieces of code. By enabling variables to be defined with in certain other blocks, those blocks also become self-contained pieces of code. One thing is like the other. Consistent. The only other way to make it consistent is to remove the ability to define variables in a block at all.
Maybe my original example was unclear. Here is another of what I consider to be the proper solution
integer file_log_level = log:WARNING procedure abc() integer abc = 20 -- VALID integer file_log_level = log:ERROR -- INVALID if 10 then integer def -- VALID integer abc -- INVALID end if end procedure
i.e. redefinition of any variable in any child scope is invalid. This is consistent and good practice. There is no reason to redefine file_log_level inside of a procedure or any child scope.
Jeremy
Then Euphoria should be changed to work that way I guess. I see it as less optimal but acceptable, as long as name clashes were limited to the same file and not across includes. Which I guess it wouldn't with all the different include scopes that euphoria now has.
18. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2878 views
I'm one of those who think that a variable should be declared the closest to it's use and go out of existance as soon as possible. This to avoid naming clash. This for 2 reasons. First we often use the sames names for variables out of habit or because that particular name seem more meaningfull than an other. Secondly human memory is limited and one can't remember what name he gaved to somes top level or public variables a few months or years ago. There is always top levels variables because in euphoria it's the only way to declare a static variables (I'm one who regret it.) So I'm favorable to variable declaration inside code block. But this should obey the sames rules as for others scopes: shadow outer ones. If one declare a variable in while block for exemple and that variable shadow an outer one is it obvious that this is because he doesn't intent to use the outer one inside that block. Normaly a "while" or others similar construct doesn't span hundreds of lines. Short span make it easy to manage variables naming.
Jacques
19. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2895 views
Consistent with what? Procedures and functions are self-contained pieces of code. By enabling variables to be defined with in certain other blocks, those blocks also become self-contained pieces of code. One thing is like the other. Consistent. The only other way to make it consistent is to remove the ability to define variables in a block at all.
Maybe my original example was unclear. Here is another of what I consider to be the proper solution
integer file_log_level = log:WARNING procedure abc() integer abc = 20 -- VALID integer file_log_level = log:ERROR -- INVALID if 10 then integer def -- VALID integer abc -- INVALID end if end procedure
i.e. redefinition of any variable in any child scope is invalid. This is consistent and good practice. There is no reason to redefine file_log_level inside of a procedure or any child scope.
Jeremy
The problem with that is that it could break a lot of pre-existing code. All the way back from the 1.x days.
Since we're post-4.0, we absolutely can not make this change. We can not break existing code.
20. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2884 views
Then Euphoria should be changed to work that way I guess. I see it as less optimal but acceptable, as long as name clashes were limited to the same file and not across includes. Which I guess it wouldn't with all the different include scopes that euphoria now has.
Actually Euphoria's new include scopes help the situation quite a bit I believe. Items can be declared in an include file and exported from that file but not be made global. This reduces the global namespace dramatically. When a name clash exists with an included file, Euphoria already has a way to deal with such a collision, namespaces.
include abc.e as abc -- public sequence a = "Abcdef" include xyz.e as xyz -- public integer a = 112 ? abc:a -- "Abcdef" ? xyz:a -- 112
Jeremy
21. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2881 views
The problem with that is that it could break a lot of pre-existing code. All the way back from the 1.x days.
Since we're post-4.0, we absolutely can not make this change. We can not break existing code.
Maybe provide a with/without option that is on by default because it is a pretty bad practice. i.e.
without strict_naming integer abc = 20 procedure def() sequence abc = "John" ? abc end procedure
Valid since without strict_naming, but by default strict_naming is on.
Jeremy
22. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2889 views
Valid since without strict_naming, but by default strict_naming is on.
Jeremy
A per-file with/without option for backwards compatibility would solve the issue and allow us to make the change, but I can see how it'd make the implementation of the chage greatly more complicated in the parser itself.
23. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2889 views
The problem with that is that it could break a lot of pre-existing code. All the way back from the 1.x days.
Since we're post-4.0, we absolutely can not make this change. We can not break existing code.
Maybe provide a with/without option that is on by default because it is a pretty bad practice. i.e.
without strict_naming integer abc = 20 procedure def() sequence abc = "John" ? abc end procedure
Valid since without strict_naming, but by default strict_naming is on.
Jeremy
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
There is nothing wrong with that rule. If you do that, one will have to constantly use name space qualifier, horrible!
It's better to leave it as it is now than make things even worse.
Jacques
24. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2887 views
Well, let's wait a moment...
I prefer coconut's change most of all.
So does Jaygade.
Derek seems to as well.
Matt seems to be open to the idea as well.
Jeremy seems to be canvasing to look for any opposing opinions. I don't think he's outright opposed to the (so far) generally agreed upon change, but rather trying to look at this from all angles. I think, if no one speaks up opposing coconut's solution, then that is what we'll end up implementing in 4.0.1
What would be worse though, is for us to agree that we should change this in one way, then on Jan 2 get 200 posts saying we need to change it back.
Since it's almost a holiday, let's give it some time to make sure that everyone who's interested has had a chance to speak up, and then go forward from there with coconut's change.
The problem with that is that it could break a lot of pre-existing code. All the way back from the 1.x days.
Since we're post-4.0, we absolutely can not make this change. We can not break existing code.
Maybe provide a with/without option that is on by default because it is a pretty bad practice. i.e.
without strict_naming integer abc = 20 procedure def() sequence abc = "John" ? abc end procedure
Valid since without strict_naming, but by default strict_naming is on.
Jeremy
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
There is nothing wrong with that rule. If you do that, one will have to constantly use name space qualifier, horrible!
It's better to leave it as it is now than make things even worse.
Jacques
25. Re: scope of variables
- Posted by DerekParnell (admin) Dec 30, 2010
- 2894 views
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
BTW, how does one refer to the encompassing var that has been shadowed in other languages?
26. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2867 views
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
BTW, how does one refer to the encompassing var that has been shadowed in other languages?
I guess you know the answer: in PASCAL ( and DELPHI) one use the unit namespace as in euphoria :) . But in pascal and any language I knows about, variables that are declared inside functions have precedence over the ones in outer scopes with same name. It is how euphoria works too and I hope it will stay that way. If it had to be changed I will regret that I started this thread.
Jacques
27. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2886 views
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
BTW, how does one refer to the encompassing var that has been shadowed in other languages?
In the languages that allow it (not all, and not common) you don't. You're cut off from it. There may be an obscure langauge out there that allows parent access, but I don't know of it. Any one else?
I'll research this topic in a bit with some other common languages. I'm not closed to the idea of causing a variable to shadow another, I just think it's a bad language design, bad coding design and has not a single thing going for it. One mentioned not being able to remember a previously defined variable and accidentially creating the same variable name after a few months. That's a pretty poor reason I think. At first run of your program, it will immediately say "Cannot redeclare variable..." and then you'll remember. Thus, we are still down to no valid reasons.
When working with PHP, the only thing I have found when this type of functionality exists is bugs that are hard to track down and it's not a bug here or there. It's a very common bug. Why do we want to open Euphoria up to this possibility w/zero benefit? Some may say "look at goto..." #1. Goto has valid uses and #2. Goto cannot be accidentally used and cause bugs. I could easily (as anyone) accidentally reuse a variable, then a month later see the top level variable and in side of a function begin working and wonder why my top level is not being changed.
If we decide to go this method, at bare minimum a stark warning that is on by default needs to be issued if a variable gets shadowed. This is a poor comprimise because in the end the warning will just make everyone code the right way as an error would have or it will cause all sorts of eu.cfg files to start having warning flags disabled and then one person deploying code thinking all is OK, and another (with out ignoring warnings) complaining the code is buggy. Over all, a poor decision for Euphoria users all around: Let's change the language to allow buggy code for no reason. We might as well insert random gotos in the IL Ok, a bit extreme but not too far
Jeremy
28. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2831 views
It occurs to me that the current behavior is inconsistent with respect to forward referencing.
You can't forward reference inside a procedure.
You can do this at the file level.
This breaks:
procedure x() b = 1 integer b end procedure
This works:
procedure x() b = 1 end procedure x() integer b
But this breaks:
b = 1 integer b
It does seem like routine-scopes are already handled specially. Maybe we can contiue to justify the special treatment of routine-scopes (backwards compatible symbol shadowing remains supported) while changing the rest (so integer b...for...integer b...end for and for...integer b...end for..integer b both break).
On the other hand, it might be easier to make all scoping rules apply equally to all the different scopes.
29. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2850 views
In the languages that allow it (not all, and not common) you don't. You're cut off from it. There may be an obscure langauge out there that allows parent access, but I don't know of it. Any one else?
I'll research this topic in a bit with some other common languages. I'm not closed to the idea of causing a variable to shadow another, I just think it's a bad language design, bad coding design and has not a single thing going for it. One mentioned not being able to remember a previously defined variable and accidentially creating the same variable name after a few months. That's a pretty poor reason I think. At first run of your program, it will immediately say "Cannot redeclare variable..." and then you'll remember. Thus, we are still down to no valid reasons.
When working with PHP, the only thing I have found when this type of functionality exists is bugs that are hard to track down and it's not a bug here or there. It's a very common bug. Why do we want to open Euphoria up to this possibility w/zero benefit? Some may say "look at goto..." #1. Goto has valid uses and #2. Goto cannot be accidentally used and cause bugs. I could easily (as anyone) accidentally reuse a variable, then a month later see the top level variable and in side of a function begin working and wonder why my top level is not being changed.
If we decide to go this method, at bare minimum a stark warning that is on by default needs to be issued if a variable gets shadowed. This is a poor comprimise because in the end the warning will just make everyone code the right way as an error would have or it will cause all sorts of eu.cfg files to start having warning flags disabled and then one person deploying code thinking all is OK, and another (with out ignoring warnings) complaining the code is buggy. Over all, a poor decision for Euphoria users all around: Let's change the language to allow buggy code for no reason. We might as well insert random gotos in the IL Ok, a bit extreme but not too far
Jeremy
Do I understand you well Jeremy? Do you say that inside the same file I should not declare a variable inside un procedure with a name already used at top level. It's permitted right now and I do it sometimes. Bad coding? why? It didn't gave me any headache up to now. If the design of a project is correct a source file is rarely over 5000 lines and it is relatively easy to remember global variables for that particular file and if I need to access a particular top level variable inside a procedure I won't name a local one of the same. The problem of naming is more one of project wide and libraries use than one of a particular file.
// when I compile this with Watcom there is no error not even a warning. // test #include <stdio.h> #include <windows.h> int i=1; void main(){ int i=2; printf("%d\n",i); }Sure the top level i is not accessible but c permit it, pascal permit it. And euphoria permit it. It is ok with me.
Jacques
30. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2865 views
He!He! euphoria is nicer than other languages, I can access shadowed top level variables if I give a namespace to my file. Try this.
namespace test integer i=1 procedure test1() integer i=2 ? test:i ? i end procedure test1()
You see Jeremy there is no problem reusing same name as at top level in a function
It is better leave it as it is now.
Jacques
31. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2818 views
Do I understand you well Jeremy? Do you say that inside the same file I should not declare a variable inside un procedure with a name already used at top level.
Yes.
It's permitted right now and I do it sometimes.
Can you give a few examples?
Bad coding? why?
Yes. You mask a variable of a higher scope level that is there for a reason. If it does not need to be a higher level then it should not be. If it is a higher level, then it should be respected.
It didn't gave me any headache up to now.
It's giving you a problem now? Nothing has changed on this front, it should work as it always has. The only difference is that block statements now create their own scope, if you want to use it, i.e. declare new variables inside of it.
If the design of a project is correct a source file is rarely over 5000 lines and it is relatively easy to remember global variables for that particular file and if I need to access a particular top level variable inside a procedure I won't name a local one of the same. The problem of naming is more one of project wide and libraries use than one of a particular file.
Top level variables should never have names that conflict with procedure level variables. What's the purpose? When names conflict with that from another include, the same rules apply except that it becomes only public members of the included file, which further reduces the possibility of a conflict.
Sure the top level i is not accessible but c permit it, pascal permit it. And euphoria permit it. It is ok with me.
The issue has come up, so we are discussing it. Many people need to chime in, I'm just one. When one was fighting for goto, one argument was giving that language a, b and c all support it so Euphoria should. That was quickly dismissed as an invalid argument. goto had to stand on the merits of its own usefulness. Something as fundamental as scoping needs to stand on its own two feet as well.
Jeremy
32. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2810 views
namespace test integer i=1 procedure test1() integer i=2 ? test:i ? i end procedure test1()
You see Jeremy there is no problem reusing same name as at top level in a function
It is better leave it as it is now.
Yes. Namespaces are nice, but that doesn't make it right. It also does not solve the discussed problem of:
integer abc = 10 if abc > 5 then sequence abc = "John" if equal(abc, "John") then atom abc = 12.3 return abc * 5.8 end if end if
Which is what is being proposed.
Jeremy
33. Re: scope of variables
- Posted by jimcbrown (admin) Dec 30, 2010
- 2844 views
namespace test integer i=1 procedure test1() integer i=2 ? test:i ? i end procedure test1()
You see Jeremy there is no problem reusing same name as at top level in a function
It is better leave it as it is now.
Yes. Namespaces are nice, but that doesn't make it right.
I think, for this case, it makes more sense. You can use a shadowed variable, meaning that one is more likely to use it.
It also does not solve the discussed problem of:
integer abc = 10 if abc > 5 then sequence abc = "John" if equal(abc, "John") then atom abc = 12.3 return abc * 5.8 end if end if
Which is what is being proposed.
Jeremy
I am seeing a lot of reasons to treat this case differently than the above one, at least. In spite of being the same conceptually, it seems that in practice there are big differences.
34. Re: scope of variables
- Posted by coconut Dec 30, 2010
- 2832 views
It occurs to me that the current behavior is inconsistent with respect to forward referencing.
You can't forward reference inside a procedure.
You can do this at the file level.
This breaks:
procedure x() b = 1 integer b end procedure
This works:
procedure x() b = 1 end procedure x() integer b
But this breaks:
b = 1 integer b
It does seem like routine-scopes are already handled specially. Maybe we can contiue to justify the special treatment of routine-scopes (backwards compatible symbol shadowing remains supported) while changing the rest (so integer b...for...integer b...end for and for...integer b...end for..integer b both break).
On the other hand, it might be easier to make all scoping rules apply equally to all the different scopes.
I was thinking that forward reference was applied to functions and procedures only not variables. This is more complex than I though at first...
So Jeremy want to remove the opportunity to redeclare a variable inside a procedure even though we can access the top level one by namespace qualifier. This would surely brake some of my code. Jeremy is suggesting an opting out with
without strict_naming -- if this is adopted it should be clearely mentioned that it should be used only for backward compatiliby. --
I could leave with it as long as the scoping rules are pervasive to all scopes. One rule for all this is democracy This will depart from other languages but as somenone said it is not nature rules.
Better to take the time to think it well.
Jacques
35. Re: scope of variables
- Posted by jeremy (admin) Dec 30, 2010
- 2812 views
So Jeremy want to remove the opportunity to redeclare a variable inside a procedure even though we can access the top level one by namespace qualifier. This would surely brake some of my code.
Yes, that is one proposal. It should be clear that I am not the person to persuade. It is a group effort and I bear no more vote than anyone else. Now, I wouldn't describe it as an opportunity but rather a deep dark trap waiting to snare Euphoria programmers everywhere in due time. Not all, of course, many will be able to weild it just fine and never have issue, others will not be so lucky. I still wonder why we would wish it on anyone for no benefit. Can you provide code that it would break and why it is necessary (or prudent) to have such constructs in your code? It would nice to see some good examples. Maybe it would bring about a different proposal.
Jeremy
36. Re: scope of variables
- Posted by ChrisB (moderator) Dec 31, 2010
- 2776 views
Hi
There seems to be some deeply divided and passionate opinion about this.
This sounds like a moment to put this too a community vote (there are plenty of free voting websites out there).
One of the arguments for allowing this 'shadowing' of variables, and creating a new instance of a variable within a while / for (etc) loop was that it allows Euphoria to behave like other languages.
Euphoria is not like other languages. To allow creating another variable within a loop (or other instances within a function / procedure that has already been defined within that function procedure) is simply asking for trouble. Its just not necessary.
I don't believe that existing code will be broken, as this method has never been allowed.
My vote would be against allowing variable creation within loops(etc).
Chris
37. Re: scope of variables
- Posted by mattlewis (admin) Dec 31, 2010
- 2763 views
Why do you want to change a rule that is accepted in all languages: >>One can redeclare a variable inside a function and shadow an outer one.<<
There is nothing wrong with that rule. If you do that, one will have to constantly use name space qualifier, horrible!
It's better to leave it as it is now than make things even worse.
This!
My take is that we should probably allow the new, smaller scopes to have variables shadowed, as it makes scopes more consistent (i.e., some scopes would no longer be more equal than others).
There is zero probability, I think, for removing any shadowing by routine level vars of file level symbols. Using a configuration option (with/without) is slightly less bad, but an awful idea, I think. It would make coding more difficult to need to check / set this option.
Matt
38. Re: scope of variables
- Posted by mattlewis (admin) Dec 31, 2010
- 2769 views
Jeremy seems to be canvasing to look for any opposing opinions. I don't think he's outright opposed to the (so far) generally agreed upon change, but rather trying to look at this from all angles. I think, if no one speaks up opposing coconut's solution, then that is what we'll end up implementing in 4.0.1
I'm not sure this needs to be put into 4.0.1. Right now, I'd put it into 4.1. Here's why:
- This actually was a design decision (albeit not the best we've ever made).
- It's very easy to work around.
- It will likely require some significant changes to the front end.
Matt
39. Re: scope of variables
- Posted by coconut Dec 31, 2010
- 2746 views
It would nice to see some good examples. Maybe it would bring about a different proposal.
here an example, an editor as a text buffer with cursor position referenced by 2 top level variables bcol and bline and there is a procedure that modify the content of that buffer but must leave cursor position unchanged at exit. all the code elsewhere use bcol and bline to access character in buffer. It make sense to use local variables of same name inside that procedure
sequence buffer -- text buffer sequence bcol -- cursor column sequence bline -- cursro line --insert text at current cursor position and leave cursor where it is. procedure insert_text(sequence text) integer bcol=bcol -- local copy integer bline=bline -- local copy --- code here end procedure -- at exit bcol and bline are preserved without need to restore from a temporary storage
Jacques
40. Re: scope of variables
- Posted by jimcbrown (admin) Dec 31, 2010
- 2734 views
Jeremy seems to be canvasing to look for any opposing opinions. I don't think he's outright opposed to the (so far) generally agreed upon change, but rather trying to look at this from all angles. I think, if no one speaks up opposing coconut's solution, then that is what we'll end up implementing in 4.0.1
He's since made clear that he's firmly against it. (Almost the sole opposing voice.)
I'm not sure this needs to be put into 4.0.1. Right now, I'd put it into 4.1. Here's why:
- This actually was a design decision (albeit not the best we've ever made).
- It's very easy to work around.
- It will likely require some significant changes to the front end.
Matt
If it was not for the significant changs to the front end, I'd argue to do it in 4.0.1 anyways.
41. Re: scope of variables
- Posted by jimcbrown (admin) Dec 31, 2010
- 2761 views
My vote would be against allowing variable creation within loops(etc).
Chris
This was a design decision made way back when it was decided to allow one to declare a variable anywhere inside a routine.
One of the arguments for allowing this 'shadowing' of variables, and creating a new instance of a variable within a while / for (etc) loop was that it allows Euphoria to behave like other languages.
Euphoria is not like other languages. To allow creating another variable within a loop (or other instances within a function / procedure that has already been defined within that function procedure) is simply asking for trouble. Its just not necessary.
I don't believe that existing code will be broken, as this method has never been allowed.
Jeremy has proposed that this be linked to the concept of shadowing a variable in the local file vs a private variable in a routine.
E.g., that this be made illegal:
integer i function s() integer i = 1 return i end function
He's all-or-nothing on this point (well, AFAICS and IMVHO, with statement option aside).
This is what would break existing code (all the way back to 1.x).
This actually raises a counter argument. Euphoria already had this feature. We've had shadowing all the way back since the 1.0 days of Euphoria, yet never had a problem before. Jeremy is saying that allowing shadowing in the new scopes can cause all sorts of bugs - but is there an Euphoria example from the past that demonstrates this?
If not, then why assume that it would cause a problem with the new scopes?
I think comparision with PHP (which does things like scoping quite differently than Euphoria, or C for that matter) is less valid than an Euphoric example.
42. Re: scope of variables
- Posted by irv Dec 31, 2010
- 2729 views
I guess I fail to see the necessity or the utility of this idea.
If I have integer x and integer y defined, but want to use a different x and y within a block, it only takes two additional keystrokes: 'm' and 'y' - as in
integer myx, myy
This has a distinct advantage: when I later read the code, I won't need to wonder whether the original x or y has been involved/changed.
Instead of contrived examples about which we can say "well, yes, I suppose Eu could be changed to work that way", how about an example which shows that variables within a block must have a name identical to an already-declared variable in order to make the code cleaner, clearer, etc...
Just because some other language does it does not mean it was a good idea. For all we know, the language author may have regretted putting that feature in, but didn't want to take the chance of breaking existing code by removing it later.
43. Re: scope of variables
- Posted by ChrisB (moderator) Dec 31, 2010
- 2672 views
My vote would be against allowing variable creation within loops(etc).
Chris
This was a design decision made way back when it was decided to allow one to declare a variable anywhere inside a routine.
One of the arguments for allowing this 'shadowing' of variables, and creating a new instance of a variable within a while / for (etc) loop was that it allows Euphoria to behave like other languages.
Euphoria is not like other languages. To allow creating another variable within a loop (or other instances within a function / procedure that has already been defined within that function procedure) is simply asking for trouble. Its just not necessary.
I don't believe that existing code will be broken, as this method has never been allowed.
Jeremy has proposed that this be linked to the concept of shadowing a variable in the local file vs a private variable in a routine.
E.g., that this be made illegal:
integer i function s() integer i = 1 return i end function
He's all-or-nothing on this point (well, AFAICS and IMVHO, with statement option aside).
This is what would break existing code (all the way back to 1.x).
This actually raises a counter argument. Euphoria already had this feature. We've had shadowing all the way back since the 1.0 days of Euphoria, yet never had a problem before. Jeremy is saying that allowing shadowing in the new scopes can cause all sorts of bugs - but is there an Euphoria example from the past that demonstrates this?
If not, then why assume that it would cause a problem with the new scopes?
I think comparision with PHP (which does things like scoping quite differently than Euphoria, or C for that matter) is less valid than an Euphoric example.
Ah, I see. Well obviously that's absurd. You can't change something that fundamental without expecting a huge backlash. But I still think that 'microscoping' within loops inside a function/procedure is wrong, and would lead to great confusion.
PS - I'm not a language designer, just a simple user.
Chris
44. Re: scope of variables
- Posted by petelomax Dec 31, 2010
- 2701 views
FWIW, I'm against all this willy-nilly declaration of variables anywhere; if you feel the need to declare more variables half way down a routine it is probably a sign that your routine is getting too big. That aside, I just thought of this idiom:
procedure P(...,boolean preserve) if preserve then object wasX = X end if ... if preserve then X = wasX end if end procedure
While I don't much care whether that is right, wrong, or whatever, someone here might want to consider it.
Regards,
Pete
45. Re: scope of variables
- Posted by Fernando Dec 31, 2010
- 2713 views
Do I understand you well Jeremy? Do you say that inside the same file I should not declare a variable inside un procedure with a name already used at top level.
Yes.
Jeremy
IMHO, that would break modularity (Modular Programming) (and consequently difficult maintainability), one of the best concepts of programming, designing,... . For example, a function with no side-effects should work without modification independently where it is placed.
Example: suppose someone has developed a library (lib.e). Many people start to use it. One of them implements the following code:
--file: prg.ex include lib.e ... procedure xyz() sequence table ... end procedure ...
Then, some time later, the library developer decides to improve the library, ADDING a public variable:
--file: lib.e ... public sequence table ...
I think it is desirable that prg.ex still works without any modification. But with the Jeremy's first proposal this would not occur. In general, since the "as" in "include" is optional, many more clashes could occur if namespace is not used and that proposal is implemented.
- Fernando
46. Re: scope of variables
- Posted by jeremy (admin) Dec 31, 2010
- 2659 views
I think it is desirable that prg.ex still works without any modification. But with the Jeremy's first proposal this would not occur. In general, since the "as" in "include" is optional, many more clashes could occur if namespace is not used and that proposal is implemented.
This is not true. Local file rules when it comes to symbol resolution. For example:
lib.e
public integer a = 50
myprog.ex
include lib.e integer a = 90 ? a
The result is 90. If you want access to lib.e's a, then you must qualify it:
include lib.e as lib integer a = 90 ? { a, lib:a }
The result is { 90, 50 }
Thus, someone adding to an include will have no affect on your program.
Jeremy
47. Re: scope of variables
- Posted by jeremy (admin) Dec 31, 2010
- 2641 views
integer i function s() integer i = 1 return i end function
This is a very poor example which does not state reality, well maybe reality in a very poorly coded program. Why would there be a top level i variable? A more meaningful example would be something such as:
sequence current_filename = "john.txt" function get_token() sequence current_filename = "jim.txt" abc_xyz() end function
This goes back to proper variable naming. However, I can see I'm fighting a loosing battle. People want the ability to shadow poorly named variables. To me, it's very unfortunate that we allow such bad practices for no benefit.
Jeremy
48. Re: scope of variables
- Posted by jeremy (admin) Dec 31, 2010
- 2686 views
here an example, an editor as a text buffer with cursor position referenced by 2 top level variables bcol and bline and there is a procedure that modify the content of that buffer but must leave cursor position unchanged at exit. all the code elsewhere use bcol and bline to access character in buffer. It make sense to use local variables of same name inside that procedure
sequence buffer -- text buffer sequence bcol -- cursor column sequence bline -- cursro line --insert text at current cursor position and leave cursor where it is. procedure insert_text(sequence text) integer bcol=bcol -- local copy integer bline=bline -- local copy --- code here end procedure -- at exit bcol and bline are preserved without need to restore from a temporary storage
That's bad practice. You know there is a global (file level) bcol, bline. Now imaging scrolling from the bottom of your file up browsing code trying to figure out why your bcol and bline variables are getting out of sync and you see the bottom end of your routine:
bcol += 10 bline+= 10 set_line("Hello, World!") end procedure
What will you think? You don't even know what method you are in at this point. Now, imagine if you would have named the variables to their real meaning, not simply shadowed a well used, well known name (why else would it be at the file level?):
local_bcol += 10 local_bline+= 10 set_line("Hello, World!") end procedure
Now what do you think? You keep on scanning looking for why your bcol and bline variables are getting screwed up.
Jeremy
49. Re: scope of variables
- Posted by ChrisB (moderator) Dec 31, 2010
- 2688 views
This goes back to proper variable naming. However, I can see I'm fighting a loosing battle. People want the ability to shadow poorly named variables. To me, it's very unfortunate that we allow such bad practices for no benefit.
Jeremy
Hi Jeremy
Surely it is the choice of the coder whether bad practices are used or not. This is the beauty of euphoria - if you want to code like me, you can, if you want to code like a professional, then you also can. You are not forced down a route. I agree that code should be easy to follow and maintain, but it is the responsibility of the coder to enforce this (or not), and IMHO not the responsibilty of the language.
Chris
50. Re: scope of variables
- Posted by useless Dec 31, 2010
- 2633 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
I disagree. If i need a variable, i declare it at the top of the procedure. Gosh, you can declare junk[1..5000] and prolly not run out of nested "decision block" junk[x], and you have the feature that all the junk is available outside that level too.
useless
51. Re: scope of variables
- Posted by jaygade Dec 31, 2010
- 2649 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
I disagree. If i need a variable, i declare it at the top of the procedure.
I do too. I thought that everyone did. I thought that it was required by the language.
Now if your vote is to remove the feature of declaring variables in blocks other than procedures and functions, then that's valid. I never thought that it was much of a feature anyway.
Gosh, you can declare junk[1..5000] and prolly not run out of nested "decision block" junk[x], and you have the feature that all the junk is available outside that level too.
useless
I don't know what you mean.
52. Re: scope of variables
- Posted by mattlewis (admin) Dec 31, 2010
- 2596 views
I think that it should be changed. The current behavior is inconsistent with other languages and unintuitive. One would expect a block started by a loop or an decision block to work the same as a block defined by a procedure or function.
I disagree. If i need a variable, i declare it at the top of the procedure.
I do too. I thought that everyone did. I thought that it was required by the language.
It was required by versions before 4.0. I find that using a scope smaller than the entire routine is very useful, following the general practice to keep a variable scoped as small as possible. It also moves the declaration closer to the point of use.
There's another benefit that relates to euphoria's ability to automatically clean up after a variable when it is fully dereferenced. Resources can be released sooner.
Matt
53. Re: scope of variables
- Posted by jimcbrown (admin) Jan 01, 2011
- 2590 views
I'm not sure this needs to be put into 4.0.1. Right now, I'd put it into 4.1. Here's why:
- It will likely require some significant changes to the front end.
Actually, if it has to wait for 4.1, then we need to reconsider the impact.
coconut's solution (to allow shadowing inside loops, etc) would not break anything, as it's just increasing the range of what is permissible.
Leaving it alone, as-is, would not either.
However, any other solution (not allowing variable redeclaration inside a loop, changing blocks so that one can not declare a variable inside a loop and then again outside a loop) could break 4.0.0 code.
So, either this is serious enough to make it into 4.0.1 (invalidating any program that actually relies on the bad? broken? 4.0.0 behavior) or else we should not change it in a way that could break any future 4.0 program written between now and the release of 4.1
54. Re: scope of variables
- Posted by useless Jan 01, 2011
- 2627 views
Gosh, you can declare junk[1..5000] and prolly not run out of nested "decision block" junk[x], and you have the feature that all the junk is available outside that level too.
useless
I don't know what you mean.
atom junk = 12.7 procedure foo() -- untested, caveats apply! integer x = 100 sequence junk = {} for something = 1 to x do junk &= {} -- now i can use junk[x] -- it's a different junk[] each iteration -- it's saved for use later -- or i can erase it at any time -- it can hold anything -- blah -- blarg end for end procedure -- foo()
The way i understood Turbo Pascal handled procedures and functions, each was pretty much a new program by itself, inheriting variable scope and file handles and such from the main() it was nested in.
I did enjoy being able to nest procedures and functions inside other procedures and functions to limit scope or increase modularity. Euphoria still does not do this. I asked for it years ago. But much like your request to be able to declare variables willy-nilly, in Euphoria i merely make a new include to achieve these goals.
useless
55. Re: scope of variables
- Posted by jimcbrown (admin) Jan 01, 2011
- 2572 views
Gosh, you can declare junk[1..5000] and prolly not run out of nested "decision block" junk[x], and you have the feature that all the junk is available outside that level too.
useless
I don't know what you mean.
But much like your request to be able to declare variables willy-nilly
4.0 supports being "able to declare variables willy-nilly", so these sort of poor ugly hacks are no longer necessary.
56. Re: scope of variables
- Posted by jaygade Jan 01, 2011
- 2523 views
For the record, I have no interest in "declaring variables willy-nilly". I like to declare them at the top of a file or at the top of a procedure.
I haven't found the need to mask a file-level variable in a procedure, but it makes sense to me since other languages work that way. Since unnamed blocks are like procedures I think that it should work the same way.
57. Re: scope of variables
- Posted by jeremy (admin) Jan 01, 2011
- 2498 views
For the record, I have no interest in "declaring variables willy-nilly". I like to declare them at the top of a file or at the top of a procedure.
I haven't found the need to mask a file-level variable in a procedure, but it makes sense to me since other languages work that way. Since unnamed blocks are like procedures I think that it should work the same way.
Declaring variables inside of the scope can make mainteance and readability much easier. It keeps variable definition close to variable use.
i.e.
function copy_file(sequence from_fname, sequence to_fname) integer status status = c_func(hCopyFile, { ... }) if status = BAD then sequence error_message = c_func(hErrMessage, { ... }) log_error(error_message) return { status, error_message } end if return status end function
It can also prevent declaration when not necessary, i.e.
function backup_file(sequence fname) sequence full_fname = absolute_filename(fname) if not file_exists(full_fname) then return { 0, "Source file not found" } end if sequence backup_fname = full_fname & ".bak" if file_exists(backup_fname) then return { 0, "Backup file already exists" } end if integer status = copy_file(full_fname, backup_fname) if status = BAD then sequence error_message = blah() log_failure(error_message) return { status, error_message, full_fname, backup_fname } end if return status end function
Those are just two very simplistic examples. Declaring those at the top of the method declares variables that will not be used most of the time (a valid copy/backup). It also makes the point of definition futher from the point of use making it more difficult to follow when you begin to have hundreds of methods in your program. Code templates also can not be used as much if all variables are declared at the top of the procedure/function, reducing the automation gained by your editor/IDE and increasing potential for bugs. Declaring at the top instead of close to the use also encourages one to "reuse" a variable w/a slightly incorrect name. Another problem with declaring at the top is that the temp variable is not cleared until it goes out of scope, thus your program will use more memory (maybe not an issue for most routines but some it can be significant).
Much more complex examples of how declaring variables close to their use and w/in the blocks they are to be used can be found throughout the standard library, various 4.0 projects and various places in Euphoria code.
Jeremy
58. Re: scope of variables
- Posted by useless Jan 02, 2011
- 2580 views
Gosh, you can declare junk[1..5000] and prolly not run out of nested "decision block" junk[x], and you have the feature that all the junk is available outside that level too.
useless
I don't know what you mean.
But much like your request to be able to declare variables willy-nilly
4.0 supports being "able to declare variables willy-nilly", so these sort of poor ugly hacks are no longer necessary.
Gosh, i misread. I thought 4.0 did NOT allow variables to be declared inside a if-then loop AND thereby shadow a variable outside the loop. My solution is one of many that pseudo-DOES, but i'm just useless again since you tell me 4.0 DOES now allow this.
useless
59. Re: scope of variables
- Posted by mattlewis (admin) Jan 02, 2011
- 2581 views
Gosh, i misread. I thought 4.0 did NOT allow variables to be declared inside a if-then loop AND thereby shadow a variable outside the loop. My solution is one of many that pseudo-DOES, but i'm just useless again since you tell me 4.0 DOES now allow this.
To be clear, variable can be declared inside of if-then, while, for, etc code blocks. But those cannot (currently) shadow names of variables that are in the same routine.
Matt
60. Re: scope of variables
- Posted by jimcbrown (admin) Jan 02, 2011
- 2562 views
Gosh, i misread. I thought 4.0 did NOT allow variables to be declared inside a if-then loop AND thereby shadow a variable outside the loop. My solution is one of many that pseudo-DOES, but i'm just useless again since you tell me 4.0 DOES now allow this.
useless
Ok, I'll bite.
How does your solution allow shadowing?