Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In OOP, static scope means the scope is linked to the class, and instance scope is linked to a specific instance of the class.

Some languages support static locals, which allow a value to be retained from one call of a function to another, however still in static scope.

As you might conclude from some other posts by me here, you can tell I'm a big fan of encapsulation.

Sometimes I use a certain instance variable within a class, only within one method. E.g. a flag indicating whether a certain method has already been called. My convention (following good standards) is to place these variables right before the function, close to their usage. Ideally, I would be able to place them within the function scope. Following the naming scheme of static locals, let's call this hypothetical scope function locals.

Darien reworded this very clearly in a comment:

Ah, so what you really want is something beyond even private protection, which is so closely protected that it is only visible to a single method within a single instance.

Now I know you could say, following the Single Responsibility Principle, this method and the associated variables should most likely be split into a separate class. To verify this - and I challenge you to do the same - I looked into some random code files and quickly found source files (even < 100 lines) where such a 'function local' could be used.

Actually, C# offers a solution to this for one common scenario out of the box. Auto-implemented properties hide the backing field.

This idea might be far-fetched, but somehow I feel it would make sense. Does anybody know of any language which supports this?

share|improve this question
    
Just found this relevant topic on SO: stackoverflow.com/q/4986023/590790 –  Steven Jeuris Jun 7 '11 at 0:47
2  
I can't decide if what you're asking for is syntactic sugar, or protection-itis. When I write OOP code, I try to make sure the object protects anyone who might try to use it from doing something stupid and blowing things up. If you're editing your finished object, it better only be for maintenance to fix bugs here and there. Protecting yourself from yourself is impractical, as you could always just drop the protection level manually because "it seemed like a good idea at the time". –  zzzzBov Jun 7 '11 at 4:21
    
@zzzzBov: Encapsulation is not only about protection, but also about providing abstractions. There is an added benefit in being able to indicate a variable is used from only one place. Your scope is less 'polluted'. E.g. consider a class with 10 functions, all using an instance variable only they access. The class only has 1 or a couple instance variables which are reused in more functions. Those 10 (the more, the more distracting) pop up in autocompletion in every other function. In order to work on one function, you are distracted by state of others. –  Steven Jeuris Jun 7 '11 at 5:29
    
You can do it in Java, but it requires a bit of work. Specifically, you'd have to create an annotation to label the field and then an annotation processor to enforce the scope. –  Peter Taylor Jun 7 '11 at 7:41
1  
@Steven Jeuris, I know that I personally have a tendency to over-abstract things. I'm not disagreeing that a personal scope wouldn't be useful (read: convenient), but I feel that most of those cases could be solved in another manner that more closely relates to what you want to do. In the case of a flag for every method, you could create an associative array of flags and check flags[fnName] because you wont have collisions on the names of functions. –  zzzzBov Jun 7 '11 at 13:11
show 3 more comments

4 Answers

This idea might be far-fetched, but somehow I feel it would make sense. Does anybody know of any language which supports this?

The wiki link you posted mentions Perl and Ruby, but I'd add PHP:

function test()
{
    static $a = 0;
    echo $a; // Prints a different number each time test() is called
    $a++;
}

Edit: A possible "fake instance-method-local" solution, albeit a memory-use risk:

class Foo(){
    function test(){
        static $a = array();
        if(!array_key_exists($this,$a)){
            $a[$this] = 0;
        }
        echo $a[$this]; // Prints a different number each time test() is called per instance
        $a[$this] += 1;
    }
}

Edit2: Looking back at that last block... It adds more ways to make a typo and introduce bugs than it helps you with encapsulation. Unless you have good syntactic sugar, the capability simply isn't worth it.

share|improve this answer
    
@Darien: isn't that a static local? Meaning if you place it in a class, every call to test() (regardless of the instance) would use the same $a? –  Steven Jeuris Jun 7 '11 at 0:35
    
Maybe I misunderstood, isn't that what you were looking for, except in a language that required no declarations or other references outside the method-body? –  Darien Jun 7 '11 at 0:38
    
@Darien: I updated the question: "Sometimes I use a certain instance variable within a class, only within one method." –  Steven Jeuris Jun 7 '11 at 0:40
2  
Ah, so what you really want is something beyond even private protection, which is so closely protected that it is only visible to a single method within a single instance. –  Darien Jun 7 '11 at 0:42
    
@Darien: Very well put! I added it to the question. –  Steven Jeuris Jun 7 '11 at 0:44
show 1 more comment

I've wanted the same thing in the past. It's easiest in a dynamic language, where it's possible to associate the data with the instance at runtime.

In C++, which is statically typed, the compiler must be able to deduce the size of a class given only its declaration; with instance-local variables declared inside method definitions, the compiler can no longer do this. C# could potentially handle it (as could Java) because the declaration and definition are not decoupled as they are in C++.

A hypothetical C++-esque solution would associate instance variables with particular methods:

class Example {
public:

    void method_the_first();
    void method_the_other();

    // Externally accessible as "this->method_the_first::spam".
    int method_the_first()::spam;

private:

    // Not externally accessible.
    int method_the_other()::eggs;

};

You could also assume that all method-static data is private:

class Example {
public:

    void { int spam; } method_the_first();
    void { int bar; } method_the_other();

};
share|improve this answer
    
I actually just created a working, albeit hacky, solution in C#. –  Steven Jeuris Jun 7 '11 at 1:40
add comment

In Python it's easy:

class TheClass(object):
    def __init__(self):
        def closure(times_called):
            def new_func():
                self.func = closure(times_called + 1)
                """ other stuff goes here """
                return times_called
            return new_func
        self.func = closure(1)

o = TheClass()

print o.func()
print o.func()
print o.func()

gives:

1
2
3

Normally, methods in Python are functions that are stored (by reference) in the class dict. If a "static" variable would be bound to such a function, then all instances would share the same variable. The solution is to give every instance its own version of the method in the form of an instance attribute, which is stored (by reference) in the instance dict, like any other instance variable. The creation of this method (new_func()) is wrapped in a closure that binds the "function-static" variable (times_called). Every call of the method also creates a new version of the method. It's a very Lispy (Lispish? Lispsome?) thing, though. In Lisp, state and state transitions are often wrapped in a similar way.

Also, the concept of a static scope is not inherent to OO. There's no static scope in Python, for example. Just package, module, function and class scope, and classes are also objects. The idea of a static scope, to me, is quite un-OO. OO is all about state and polymorphism. Polymorphic messages can be implemented without classes but instead with Multi-Methods, Prototypes, Type Constructors a la Haskell, ..., and state and state transitions with closures. Lexical scoping is nice, though. Python doesn't have it, but instead the global and nonlocal keywords, which are just crutches instead of the real thing.

Anyway, I'd not use the solution above, but instead put the state in an instance attribute, where it belongs in Python. Im not very concerned with strong encapsulation. If I were, I wouldn't be using Python, where there's no concept of privacy at all. It's a Dutch language! They have nude beaches!

share|improve this answer
add comment

It can be done in C# as well, and possibly other languages which support lambdas! Although the following is still pretty experimental, it works.

Test instance1 = new Test();
Test instance2 = new Test();

instance1.SomeFunction();  // functionLocal = 1, staticLocal = 1
instance1.SomeFunction();  // functionLocal = 2, staticLocal = 2
instance2.SomeFunction();  // functionLocal = 1, staticLocal = 3
instance2.SomeFunction();  // functionLocal = 2, staticLocal = 4

class Test
{ 
    public void SomeFunction()
    {
        // 'function local' as discussed in the question
        Local<int> functionLocal = Local<int>.Instance( () => this );
        // static local, normally not possible in c#
        Local<int> staticLocal = Local<int>.Static( () => {} );

        functionLocal.Value += 1;
        staticLocal.Value += 1;
    }
}

The lambda is only created once, allowing to link the place where it was created to its scope. The variables are stored in the Local<T> class as Local<T> instances, in a static context.

Static locals aren't supported in C#, but by linking the instance to the passed lambda, the correct scope can be found.

The 'function locals' are possible with a bit more effort by using a lambda which returns the current 'instance' scope as well.

An implementation of Local<T> can be found on this relevant SE question.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.