1. rant // OE scope \\ forked out of 500 Rosetta

Forked from Re: rosettacode 500 milestone passed

It seems it all starts here. Pete and Spock have a small side conversation:

said...

Lastly, your scope rules are off, you allow eg:

for i=1 to ~s do  
   int w 
end for 
w = 0  

which in Phix terminates with "w has not been declared" (obvs. fixed by declaring w before the loop)

Pete

I once analysed the distributions of variables declared inside routines. So few private variables are used on average that it seemed to me scopes are pointless inside routines - particularly when realising that routines should be kept short and single purpose. I made the conscious decision to not include them. However I think it is useful to be able to declare variables at the point in code when they become needed, rather than interrupting the typing flow by inserting them at an earlier point in the text. YMMV but I just don't see the need to have any structural scopes inside routines. Perhaps someone could point out just where i got it wrong.

Spock

[/quote]


said...

I once analysed the distributions of variables declared inside routines. So few private variables are used on average that it seemed to me scopes are pointless inside routines - particularly when realising that routines should be kept short and single purpose. I made the conscious decision to not include them. However I think it is useful to be able to declare variables at the point in code when they become needed, rather than interrupting the typing flow by inserting them at an earlier point in the text. YMMV but I just don't see the need to have any structural scopes inside routines. Perhaps someone could point out just where i got it wrong.

Spock

You need micro scopes because certain curmudgeons use only x,y,i,j,k as the only identifiers in source-code.

A language structure is "a feature that starts with a keyword (like procedure, function, for, if, while, ..., and a few others). Each structure extends up to end <keyword>." Structures act like small detours in the natural flow of code execution. Since they are detours it makes sense that they also have some independent properties like: selective code execution, and scope. Structural scope is "the nested scope that corresponds to the extent of the structure."

For example look at the routines in the standard libary; most have parameters and many have locally declared variables. The main program is cleaner because none of these structural scope identifiers mess with the code you write.

In designing a language you have two choices:

  • find a pattern and stick to it
  • invent a "convenient" syntax for every situation

Stick to a pattern The Lisp languages do everything with nested parenthesis; the ultimate in following one pattern. Euphoria languages identify patterns and then stick with them.

Convenient syntax Conventional languages suffer from random features that seem convenient at the time the language was designed. For example the conventional + operator adds numbers but concatenates strings. The problem is that when you add up all of the "convenient" syntax choices you end up with an overall mess.

The balance between pattern and convenience is personal, which explains why there are thousands of programming languages.

In OpenEuphoria the if statement breaks the simple pattern described. Each branch of the if statement creates a new scope. That means the else keyword both starts and ends a region of scope. It would have been simpler if there was just one scope that extended to end if. Is there a good reason for having separate scopes for each branch?

You could observe that the utility of local scopes in structures is: routine > while > if. But, breaking a pattern based on frequency of use is a bad strategy.



said...

Spock said...

I just don't see the need to have any structural scopes inside routines. Perhaps someone could point out just where i got it wrong.

said...

The only two things that spring to mind are (and you did say "kept short and simple") that in an N-00 line routine

if this then  
   -- <you are adding code here>  
else  
   if that then  
      -- loads more code  
   elsif the_other then  
      integer w  
   else  
      integer W  
      -- <then you add more here>  

First, without local mini-scopes, while working up top you forget there is a w 200 lines further down and add another one -> compilation error. Not exactly what I'd call critical either, and that sort of thing can still happen with scopes.

Second, while working down below, you use w when you meant W, or perhaps that you can't rename/remove w without checking all the rest of the code. No matter how you look at it though, mini-scopes cannot be justified in routines that fit on a single screen.

Pete

Having trouble decoding this.

  • ? N-OO
  • ? example shows if you mention "routine"

I'm assuming the value of a mini-scope is to localize a throw-away local variable. The index variable in a for structure is an example of this kind of thinking. Therefore the mini-scope fits just a single screen (otherwise it is not mini).

Is your example suggesting you want to create a global w or a global W from an if branch?

_tom

new topic     » topic index » view message » categorize

2. Re: rant // OE scope \\ forked out of 500 Rosetta

_tom said...

which explains why there are thousands of programming languages.

Another explanation might be that most of them are rubbish! (especially the famous ones?)

_tom said...

Is there a good reason for having separate scopes for each branch?

It reduces the area of code that you have to scan in order to decide whether a variable has already been declared.
I cannot think of any advantages to scopes across branches, when moving the declaration just above the opening if is what I might call "close enough".

_tom said...

Having trouble decoding this.

  • ? N-OO

"several hundred".

_tom said...
  • ? example shows if you mention "routine"

You lost me there

_tom said...

Is your example suggesting you want to create a global w or a global W from an if branch?

Not at all. I should really have said:
The expense of modifying a compiler to support local scopes cannot be justified if all your routines are small enough to fit on one screen.

I was not suggesting removing any features from OpenEuphoria or Phix, but rather accepting the decision not to add them to Orac.

Pete

new topic     » goto parent     » topic index » view message » categorize

3. Re: rant // OE scope \\ forked out of 500 Rosetta

_tom said...
Spock said...

I once analysed the distributions of variables declared inside routines. So few private variables are used on average that it seemed to me scopes are pointless inside routines - particularly when realising that routines should be kept short and single purpose. I made the conscious decision to not include them. However I think it is useful to be able to declare variables at the point in code when they become needed, rather than interrupting the typing flow by inserting them at an earlier point in the text. YMMV but I just don't see the need to have any structural scopes inside routines. Perhaps someone could point out just where i got it wrong.

Spock

You need micro scopes because certain curmudgeons use only x,y,i,j,k as the only identifiers in source-code.

Interesting that the primary (first) reason given for micro scopes seems to be to add protection against supposedly poor coding habits. I find that having short identifiers can actually help clarity. My programs have a very light feel to them compared to other stuff coded in Eu. Part of that will also be the programming style since I fully concur that routines themselves should be short.

_tom said...

A language structure is "a feature that starts with a keyword (like procedure, function, for, if, while, ..., and a few others). Each structure extends up to end <keyword>." Structures act like small detours in the natural flow of code execution. Since they are detours it makes sense that they also have some independent properties like: selective code execution, and scope. Structural scope is "the nested scope that corresponds to the extent of the structure."

For example look at the routines in the standard libary; most have parameters and many have locally declared variables. The main program is cleaner because none of these structural scope identifiers mess with the code you write.

I had a look at \std (Oct 2010). There is a monster (580 GLOC) in text.e - format(). Of the variables maybe half a dozen were declared inside micro scopes. Surely the correct approach would have been just to refactor the code down into more sane-sized chunks - which wouldn't then need micro scopes..

Spock

new topic     » goto parent     » topic index » view message » categorize

4. Re: rant // OE scope \\ forked out of 500 Rosetta

Very helpful Pete and Spock.

I am still trying to develop a neat and tidy description of scope. I notice that scope has these dimensions:

Identifier creation style:

  • loose
  • tight

Scope is used by:

  • variables
  • routines
  • labels

Scope by place:

  • sub-space
  • file
  • chained files
  • global
  • built-in

Scope by portion:

  • waterfall
  • flood

Scope by properties:

  • blend
  • shadow

It looks like mini-scopes can join goto as fuel for many rants.

_tom

new topic     » goto parent     » topic index » view message » categorize

5. Re: rant // OE scope \\ forked out of 500 Rosetta

I have found an analogy that seems to work in explaining scope.

Water vs Computer Code

Space is "is where you write your source-code." The Interpreter is a computer program so this is the starting space for all programs. The Interpreter space contains built-in routines like print or rand. Each file in the standard library is also a space. The file where you type your program is another space. Useful programs are build from several spaces.

Scope is "where your code can do something because identifiers are visible." The general rule is that an identifier must be declared before it can be used in a statement. Before the declaration an identifier is not visible or out of scope; after a declaration an identifier is visible or in scope. There are rules to learn because scope can equal the available space or can be a small restricted area of space.

I will use the properties of water to explain the properties of space and scope. Space: a bottle to hold water; space: a file to hold identifiers. Scope: how water fills a bottle; scope: how identifiers fill a file.

A water bottles and files are alike; all bottles work work the same; all files work the same. The purpose of a bottle is to hold water; the purpose of a file is to hold identifiers. A bottle is water-tight; a file is identifer-tight. For more water you can get more bottles; for more identifiers you can get more files. You can pour water into a bottle (the water you have does not leak out); you can add identifiers from another file (identifiers you already have do not leak out). You can choose to pour water from a bottle (a controlled leak); you can choose to let identifiers leave a file (a controlled leak). Flooding a bottle fills it up to the top; some scopes (routines) can flood identifiers to the top a file. A waterfall fills only the bottom of a bottle; some scopes (variable) add identifiers only to the bottom of a file. It is possible to mix water from all bottles together; it is possible for global identifiers to apply to all files.

The analogy of water and identifiers is a start in understanding how identifiers work in source-code.

_tom

new topic     » goto parent     » topic index » view message » categorize

6. Re: rant // OE scope \\ forked out of 500 Rosetta

_tom said...

I have found an analogy that seems to work in explaining scope.

...

The analogy of water and identifiers is a start in understanding how identifiers work in source-code.

Sorry Tom, but my mind must work differently. I read this many times and each time I got more and more confused about the topic. And I KNOW identifiers! Also, I have some fundamental disagreements about the assertions mentioned in the analogy.

If the analogy helps someone then good, but it wouldn't be much use for me.

new topic     » goto parent     » topic index » view message » categorize

7. Re: rant // OE scope \\ forked out of 500 Rosetta

In case it helps, this is what I wrote in the glossary section of phix.chm:

The term scope is a general concept used when describing how the compiler resolves references to identifiers. In most cases it is simple and intuitive, involving nothing more than plain old common sense. The scope of an identifier is where, in terms of which lines of code, it can be referenced. The scope of a variable starts at the point of declaration and ends at the end of the declaring block, routine, file, or in the case of globals, on the last line of the main file. The scope of a routine is anywhere in the file it is declared in, or in the case of global routines, anywhere in the entire application. Namespaces and explicit forward declarations can be used to further qualify and clarify matters.

I've just added: It may help to think of "in scope" as meaning "does not cause a compilation error".

Pete

new topic     » goto parent     » topic index » view message » categorize

8. Re: rant // OE scope \\ forked out of 500 Rosetta

DerekParnell said...
_tom said...

I have found an analogy that seems to work in explaining scope.

...

The analogy of water and identifiers is a start in understanding how identifiers work in source-code.

Sorry Tom, but my mind must work differently. I read this many times and each time I got more and more confused about the topic. And I KNOW identifiers! Also, I have some fundamental disagreements about the assertions mentioned in the analogy.

If the analogy helps someone then good, but it wouldn't be much use for me.

The analogy does need more work. The reason for you "confusion" is that you are a programmer of long standing, and I am trying to create an explanation for new non-programmers--and not doing it well.


scope rant, improved


A computer program is written as a plain text file.

Fig. 1 : your program file myprog.ex

 ┌╴╴╴╴╴╴╴╴┐ 
 │        │ 
 └╶╴╴╴╴╴╴╴┘ 

Inside the file is a space where you type your source-code.

Since this is a Euphoria program, your program file (and its source-code space) is part of a larger Euphoria space that belongs to the Interpreter. Euphoria space gives you built-in procedures and functions; the built-ins work all the time anywhere you type.

Fig. 2 : myprog.ex inside Euphoria space

 ┌╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ Interpreter space 
 │                       │    
 │ ┌╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐    │ 
 │ │  Program space │    │      
 │ └╶╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘    │ 
 │                       │ 
 └╶╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ 

The basic rule in Euphoria is "declare all identifiers before using them in a statement; declare variables, procedures, functions, types before you need to use them." If you follow this basic rule you will not get into too much trouble.

Scope is where, in space, you can use an identifier in a statement. So, if you follow the basic rule of declaring everything before using you don't have think about scope very much, things just work.

  • In-scope things work.
  • Out-of-scope things do not work.

The scope of a variable is from the declaration to the end of space.

Fig. 3 : scope for a variable

 ┌╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ 
 │                    │     out-of-scope 
 │                    │ 
 │ atom x = 2.4       │ <-- variable declaration 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │     in-scope 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 └╶╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ 

Variable scope is like a waterfall, space from the declaration to the end of space is in-scope.

The scope of a routine (procedure, function, type) is special. The entire space, including inside the routine, is in-scope. Routine scope is like a flood filling all the available space; an identifier for a routine is in-scope for the entire file. If you follow the basic rule declare everything before using to don't have to think about how routine scope; it just works.

Fig. 4 : scope for a routine

 ┌╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┐ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ in-scope 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ procedure foo()    │ <-- routine declaration 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ in-scope 
 │ end procedure      │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ in-scope 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 │ ░░░░░░░░░░░░░░░░░░ │ 
 └╶╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴╴┘ 

Why is routine scope special?

Calling a routine from anywhere in a file space is great because:

  • one routine can call another routine (even if it declared later in the program)
  • a routine can call itself (which allows recursive programming)

A "waterfall" naturally starts at the top of the cliff and drops to the bottom. Variable scope is the same, it starts at the point of declaration and drops to the bottom of you programming space.

In a "flood" water is everywhere. Routine scope (procedure, function, type) "fills" ("floods") the entire programming space.

As a sailer, this makes perfect sense to me. I have tested waterfall and flood conditions using a dingy.

_tom

new topic     » goto parent     » topic index » view message » categorize

9. Re: rant // OE scope \\ forked out of 500 Rosetta

More Space

It is natural to write large programs made up of small files. When you include a file from the standard library this is what you are doing.

A large program made up of small files:

Here are two files (two spaces) that will be used to make one program. Both are inside the Euphoria Interpreter space so the each can use all of the built-in routines.

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐Interpreter 
│      ┌╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │           │     │           │    │ 
│      └╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
		two independent files 
 

By default, what is written in one file is invisible all other files. Think of each file space as being water-tight and no identifiers "leak" out of that file.

To build a larger program out of smaller files you must include each file.

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │include myinc.e │     │atom x     │    │ 
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 
	  x is out-of-scope 
 
 

The identifiers in each file remain invisible to each other (still water-tight). You need an extra step before included identifiers become visible; you must let identifiers leave a file space with a special keyword like global. You must create a "leak" so identifiers can flow out of a file space.

Included Variable

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │include myinc.e │     │global atom x │    │ 
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 
 
 

The scope for "x" now looks like:

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │                │     │              │    │ 
│      │include myinc.e │     │global atom x │    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░│    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░│    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░│    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░│    │ 
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 
	   x is in-scope 
 

For a variable, the include statement acts like the declaration point for the included identifier "x". The scope for both files still follows the "waterfall" idea of scope goes from the declaration to the end of space.

Included Routine

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │include myinc.e │     │procedure foo() │    │ 
│      │                │     │                │    │  
│      │                │     │end procedure   │    │  
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 

The identifiers is each file remain invisible to each other; the file spaces are "water-tight".

To make an identifier visible to another file you need a special keyword like global.

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │include myinc.e │     │global procedure foo() │    │ 
│      │                │     │                       │    │  
│      │                │     │end procedure          │    │  
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 

The scope for the procedure foo now looks like:

┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐ 
│      ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐     ┌╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┐    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░░░░░░░░░░│    │  
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░░░░░░░░░░│    │  
│      │include myinc.e │     │global procedure foo() │    │ 
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░░░░░░░░░░│    │  
│      │░░░░░░░░░░░░░░░░│     │end procedure          │    │  
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░░░░░░░░░░│    │  
│      │░░░░░░░░░░░░░░░░│     │░░░░░░░░░░░░░░░░░░░░░░░│    │  
│      └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘     └╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘    │ 
└╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶╶┘ 
 
       myprog.ex             myinc.e 
 

Like all routines, the procedure foo is visible everywhere because scope "floods" the available space.


I have to get at least a grade of 1/10 from Derek Parnell to declare success. So I will keep trying.

_tom

new topic     » goto parent     » topic index » view message » categorize

10. Re: rant // OE scope \\ forked out of 500 Rosetta

_tom said...

I have to get at least a grade of 1/10 from Derek Parnell to declare success. So I will keep trying.

Haha ... I'll read through it tonight and give my not-so-humble opinions. I'm glad you are enthused enough to try and tackle this topic.

new topic     » goto parent     » topic index » view message » categorize

11. Re: rant // OE scope \\ forked out of 500 Rosetta

Not a fan of the water-space model to explain scope. Seems just way to complicated. Of course that might not be able to be avoided.

I'll give it a bit more thought and see if I can come up with a simple way of explaining scopes in OpenEuphoria.

new topic     » goto parent     » topic index » view message » categorize

12. Re: rant // OE scope \\ forked out of 500 Rosetta

DerekParnell said...

Not a fan of the water-space model to explain scope. Seems just way to complicated. Of course that might not be able to be avoided.

I'll take 0/10 and call it a pass (seems like a generous score given the state of education here...).

The model gets very messy when you consider include files that include files.

Space has to be explained somehow because of the namespace keyword, and the include ... as [namespace prefix] way include files are designed.

Then, once you know what "space" is, you must learn "scope".

Then it follows that a block (say in a loop or routine) is a subspace with new scope features.

Again, this gets messy and hard to diagram.

petelomax said...

I've just added: It may help to think of "in scope" as meaning "does not cause a compilation error".

I was trying "in-scope things work".

This is the pragmatic model that programmers have in their head and they don't think about it. But, how does one explain this to someone new?

The good thing about Euphoria languages is that the Interpreter lets you find and fix scope errors quickly.

_tom

new topic     » goto parent     » topic index » view message » categorize

13. Re: rant // OE scope \\ forked out of 500 Rosetta

I wonder if "line of sight" might be a more appropriate metaphor.

You've got rooms in buildings with doors and windows, and walls and hedges and fences and hills and mountains. You can also "cheat" with cctv, and maybe using a namespace is analogous to switching to a specific camera so you know you're looking in the right area, and you can see things that you wouldn't normally be able to see.

It is important that when you are tinkering around in your shed you do not accidentally pick up some critical nut and bolt from a nuclear reactor 20 miles away. Of course in the real world that would be physically impossible, but within a computer those kind of "obvious" barriers actually have to be created artificially. Scopes are the way the compiler models just that sort of requirement.

Paradoxically, scopes can be difficult to describe and/or understand, precisely because they are inherently obvious.

Pete

new topic     » goto parent     » topic index » view message » categorize

14. Re: rant // OE scope \\ forked out of 500 Rosetta

petelomax said...

I wonder if "line of sight" might be a more appropriate metaphor.

...

Paradoxically, scopes can be difficult to describe and/or understand, precisely because they are inherently obvious.

Pete

Physical models don't quite work with scope. But, the "line-of-sight" model has promise.

Line-of-sight

When you write a computer program it looks like this to you:

atom x = 0 
atom sum = 0 
 
while 1 do 
	x += 1 
	sum += x 
	if x > 5 then exit end if 
end while 
 
? sum 
 
--> 21 

When you look a a landscape what you see is something like this:

 
...................................   horizon (end of space) 
 
 
	                                 ^ 
 
				      ^ 
				     / \ 
                                      |   
				 
		               ^ 
		              / \ 
		             /___\ 
                               | 
 
 
                            ^    
			   / \ 
			  /   \ 
			 /     \ 
			/       \ 
			________ 
			    | 
 
  0    
 -|-   
 / \   you, looking at a landscape full of trees 
 

What the same program looks like to an interpreter is:

-- look towards the horizon 
                                                                
                                                                 ^   all the way to end of space 
			 ? sum                                   │  
		     end while                                   │ 
                if x>5 then exit end if                          │  
   	    sum += x                                             │   
        x += 1                                                   │ 
     while 1 do                                                  │ 
  atom sum = 0                                                   │ 
atom x = 0                            -- you can "see" x here ---┘             
 
 
 
 
                            "x" does not exist yet, you can't see it, out-of-scope 
 
 
 
--start here 
 
 

An identifier does not exist until you make a declaration; if it does not exist you can not see it.

If the Interpreter can "see" it then it is "ok", things are in-scope and things work. If the Interpreter can not "see" an identifier, then it is out-of-scope and it crashes.

The "line-of-sight" model should work for a lot of people (if their mind is flexible enough to to flip things about).

_tom

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu