[ nice-Bugs-798312 ] local function param namespace

"SourceForge.net" <[email protected]>
Newsgroups gmane.comp.lang.nice.devel
Message-ID <[email protected]>
Bugs item #798312, was opened at 2003-08-31 16:37
Message generated for change (Settings changed) made by igouy
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=112788&aid=798312&group_id=12788

Category: None
Group: None
>Status: Closed
Resolution: None
Priority: 5
Submitted By: Isaac Gouy (igouy)
Assigned to: Nobody/Anonymous (nobody)
Summary: local function param namespace

Initial Comment:
My guess is that this is a feature request?



These comments refer to the code in 

WordfreqIntermediateExample. 



I made the formatLine package function a local function 

(mainly so I could reuse the StringBuffer) and 

discovered that the parameter name 'word' clashed with 

the variable name 'word'. Of course, we can rename the 

parameter in some arbitrary way like 'wordX' (although 

the keyword parameters mean that's not so good and 

perhaps we need to go back and rename the local 

var...).





void main(String[] args){

   var String word;

...



   String formatLine(String wordX, Cell count){

...

      buffer.append(wordX);

...

   }



...   formatLine(wordX: e.getKey(), count: e.getValue()) 



}

----------------------------------------------------------------------

Comment By: Isaac Gouy (igouy)
Date: 2003-09-02 16:51

Message:
Logged In: YES 
user_id=536291

> Is this really problematic?

Now I realize - No, it isn't! 



Because "redeclaration of local variables is not allowed" 

means specifically var/let local to a function or method.



var/let at the 'module level' can be redeclared in function 

parameters and function var/let (and so can var/let imported 

from other 'modules' or other packages).



So it's a local issue which can mostly be avoided by preferring 

top-level functions to local-functions. Certainly explains how 

unconcerned you guys were - sorry for wasting your time.



----------------------------------------------------------------------

Comment By: Daniel Bonniot (bonniot)
Date: 2003-09-02 12:56

Message:
Logged In: YES 
user_id=88952

There is no doubt that if one variable is accessed, it must

be the inner one. However, as I have tried to explain, this

situation is dangerous. This is why Smalltalk issues a

warning, and Java an error.



I think it would be unacceptable for the compiler not to

issue at least a warning in this case. But when there is a

warning, the user is supposed to do something about it if he

can, otherwise you will get more and more warnings, and

ignore them. So why not have an error? Is this really

problematic?



----------------------------------------------------------------------

Comment By: Isaac Gouy (igouy)
Date: 2003-09-02 09:19

Message:
Logged In: YES 
user_id=536291

Being curious, I did a little more research.



In Algol-60, an inner block implicitly gets access to all 

variables accessible in it's immediately surrounding block - 

unless the inner block declares a variable of the same name. 

The innermost binding blocks access to the nonlocal binding. 

(So Pascal didn't originate this, it just followed on from Algol)



I haven't been able to figure out how this worked in BCPL.

----------------------------------------------------------------------

Comment By: Isaac Gouy (igouy)
Date: 2003-09-01 17:07

Message:
Logged In: YES 
user_id=536291

>> Now I've had breakfast

> Funny to hear this when it's 9pm for me :-)

Well it was a late holiday brunch ;-)



> Please detail with sample code 

I had such a strong feeling about this, it's probably something 

that I originally learned in Pascal eons ago ;-)

(All those Pascal derivatives will probably do the same thing, I 

wonder if it's a C - Pascal difference?)



For a while I thought about what a C# or Java example would 

look like, but I think the difference we've come across is not 

one that can be examined in a such limited OO languages for 

a couple of reasons:

- variables would always be inside a class or method

- no local functions within a method or package



Here's some Smalltalk:

   | i j f |

   j := 100.

   i := 22.

   f := [:i | | j | j := i + 20 ]. "this is an anonymous function"

   Transcript 

      show: (f value: j) printString; cr;

      show: i printString; cr;

      show: j printString.



The compiler warns about i & j being 'already defined 

(perhaps in an outer scope)', compiles and gives this result:

   120

   22

   100



I suppose you might consider Smalltalk to be a bizarre 

language, so once more here's Oberon-2 ;-)

(not a bad language for comparison - they were obsessed 

with 'safety')



MODULE MainTest;

   IMPORT Out;



   VAR i: INTEGER; j: SHORTINT;

    

   PROCEDURE Test (VAR i: SHORTINT): INTEGER;

   VAR j: INTEGER; 

   BEGIN 

      j := LONG(i) + 20;

      RETURN j;

   END Test;



BEGIN

   j := 100; 

   i := 22;

   Out.Int(Test(j) ,5); 

   Out.Int(i ,5);

   Out.Int(j ,5);

END MainTest.



XDS Oberon-2 v2.40 [x86, v1.50] - build 20.02.2002

Compiling "maintest.ob2"

no errors, no warnings, lines   20, time  0.01



I:\pls\Oberon2\test>maintest

  120   22  100

----------------------------------------------------------------------

Comment By: Daniel Bonniot (bonniot)
Date: 2003-09-01 12:28

Message:
Logged In: YES 
user_id=88952

> Now I've had breakfast

Funny to hear this when it's 9pm for me :-)



> Seems like I expect 'nested scope'.

Yes, and that's what you get, too, as far as I can see:



  void F(String word){}

  var String word;



This is valid, since the two versions of word are never

alive in the same scope.



  var String word;

  void F(String word){}



Here, the outer word (if it has another name) would normally

be visible inside the local function. With the same name, it

would be shadowed. Since that could be an accident and you

might think wrongly to access the outer one, the compiler

reports the problem.



This is exactly the same in Java (and probably in most

structured languages):

    {

      int foo = 0;

    }

    int foo = 0;

is valid, while

    int foo = 0;

    {

      int foo = 0;

    }

is not.



> It seems that the parameter of functional F doesn't exist 

> beyond the scope of F.



That's normal. You cannot access a function parameter

outside the scope of that function.



> So the name clash of main3 is surprising to me.

There is no clash in main3. It uses a variable that was not

declared. Maybe you forgot 'var' ?



>And of course I don't experience that name clash in other

languages

Please detail with sample code if you still think this is

the case. I don't think so.



> Given that the param and var are local to F, I only "expect"

> that they will have name clashes in that local scope.

But the outside variable is visible inside the function.



> Aside from the bad 'surprise', the main consequence is more 

> debug/editing when a function is moved, and a 'forced' 

> arbitrary naming of vars and params to get around the name 

> clash (rather than express intent).

What about when you move some code from the main function to

the local one? It could silently reffer to a different

variable than the one intended.

Isn't it better to be told about the problem? Sure, there

can be some editing needed, but it is guaranteed to be

local, since the inner function is a local feature.



It will always be confusing to have several variables

shadowing each other. At the point where use define the

inner word, the outer has no meaning. I think it would be

cleaner to make a separate function that takes the map, and

prints the results. That would keep the main function

shorter and cleaner.

----------------------------------------------------------------------

Comment By: Isaac Gouy (igouy)
Date: 2003-09-01 11:05

Message:
Logged In: YES 
user_id=536291

Now I've had breakfast perhaps I'll make more sense.



Seems like I expect 'nested scope'.

----------------------------------------------------------------------

Comment By: Isaac Gouy (igouy)
Date: 2003-09-01 08:33

Message:
Logged In: YES 
user_id=536291

> more important to show different aspects of Nice

I agree! And its important to show a practical style.





> redeclaration of local variables is not allowed

Let me step through what surprises me:



This compiles:

   void main1(String[] args){

      void F(String word){}

      var String word;

   }



but this doesn't:

   void main2(String[] args){

      var String word;

      void F(String word){}

   }



   \test\t.nice: line 3, column 23:

   Symbol word is already defined.

   Previous definition: \test\t.nice: line 2, column 15



1) I hadn't realized declaration order mattered







   void main3(String[] args){

      word = "test";

      void F(String word){}

   }



   \test\t.nice: line 2, column 4:

   word is not declared



2) It seems that the parameter of functional F doesn't exist 

beyond the scope of F. So the name clash of main3 is 

surprising to me. (And of course I don't experience that name 

clash in other languages.)







   void main4(String[] args){

      word = "test";

      void F(){ var String word; }

   }



   \test\t.nice: line 2, column 4:

   word is not declared





   void main5(String[] args){

      var String word;

      void F(){ var String word; }

   }



   \test\t.nice: line 3, column 25:

   Symbol word is already defined.

   Previous definition: \test\t.nice: line 2, column 15



3) Same as #2 but with a variable local to F.





Given that the param and var are local to F, I only "expect" 

that they will have name clashes in that local scope.



Aside from the bad 'surprise', the main consequence is more 

debug/editing when a function is moved, and a 'forced' 

arbitrary naming of vars and params to get around the name 

clash (rather than express intent).



Nice compiler version 0.9.2 (build 2003.09.01, 08:24:05 UTC)



----------------------------------------------------------------------

Comment By: Arjan Boeijink (arjanb)
Date: 2003-09-01 05:30

Message:
Logged In: YES 
user_id=688815

This is not a bug, redeclaration of local variables is not 

allowed because it mostly indicates an error or bad code 

practise.



BTW I changed the code in that example because it 

contained to much optimization tricks. I know the code comes 

form a benchmark but I think it's more important to show 

different aspects of Nice than showing how to squeeze out a 

few percent more perfomance.



----------------------------------------------------------------------

Comment By: Daniel Bonniot (bonniot)
Date: 2003-09-01 01:27

Message:
Logged In: YES 
user_id=88952

Idem, please submit something we can copy paste and compile

(without "..."). It's also good if you can remove irrelevant

parts, so the code is as short as possible.



It's also not clear from your message was is the bug (you

seem to have to identifiers with the same name, isn't a

"clash" expected?), or what feature you request.

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=112788&aid=798312&group_id=12788


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.