Static variables !

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Static variables !

Lozminda
Static variables, I've been having a lot of trouble with this too.

In psuedo/jack-ish code

Main
{
  MyClass z,y;
  // So z.MyStatic should equal 4500 but I want y.MyStatic = 5500;
}


class My Class
{
  static int MyStatic

  method new()
  {
     let MyStatic = 4500; // Initialise MyStatic but  only once
     return;
}

method SomeOtherMethod()
{
  let MyStatic = MyStatic + 1000;
  return;
}

I have tried a lot of things, using getters and setters to access them and all kinds of other stuff but either MyStatic is 4500 or I get an error.
I'm expecting (and perhaps this is the trouble) 'static' to be like the C family of languages version of static, which is slightly implied by figure 9.7.
(for example...      https://www.geeksforgeeks.org/static-variables-in-c/)
Is it possible to assign a starting value to a static just once and then each subsequent object increments static and then the next object gets the incremented value..And how would I implement that ?

Thanks yet again, hopefully that should be it for a while (famous last words


Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

WBahn
Administrator
Lozminda wrote
Static variables, I've been having a lot of trouble with this too.

In psuedo/jack-ish code

Main
{
  MyClass z,y;
  // So z.MyStatic should equal 4500 but I want y.MyStatic = 5500;
}
Then you want z and y to have DIFFERENT variables called MyStatic, which means you want them to be field variables and not static variables. Static variables are a single instance of a variable visible to all functions and methods of a class.

<quote>
class My Class
{
  static int MyStatic

  method new()
  {
     let MyStatic = 4500; // Initialise MyStatic but  only once
     return;
}

method SomeOtherMethod()
{
  let MyStatic = MyStatic + 1000;
  return;
}

This shouldn't be a problem, but after invoking SomeOtherMethod, MyStatic will be 1000 larger for EVERY user of that variable.

Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
This post was updated on .
Then you want z and y to have DIFFERENT variables called MyStatic, which means you want them to be field variables and not static variables. Static variables are a single instance of a variable visible to all functions and methods of a class.

No, I want MyStatic to be shared by z and y...

This shouldn't be a problem, but after invoking SomeOtherMethod, MyStatic will be 1000 larger for EVERY user of that variable.

I don't know what you mean by EVERY user of that variable. "user" you mean object ?

I think what your saying is that everytime an object of MyClass calls SomeOtherMethod MyStatic will be 1000 larger. Yes, that's what I want.

I have managed to get something to work, it is extremely ugly an I can't believe that what I've coded is the correct solution. It involves three other variables, passing a variable to the constructor and using a getter (ugg). I can post the code if you'd like, however:
Here's a quick example in C

int fun()
{
  static int count = 0;
  count++;
  return count;
}
   
int main()
{
  printf("%d ", fun());
  printf("%d ", fun());
  printf("%d ", fun());  
  printf("%d ", fun());
  return 0;
}

Ouput 1,2,3,4

Everytime fun is called count goes up by one, static int count = 0 is only 'read' once. (I know it's not in a class, it's the behaviour of count that i'm looking for.  Initialise once, increment on subsequent calls ignoring static int count = 0

I was hoping you might post an example of how to implement the above behaviour just to save me a little time please or point me to a better example than the book (or any of the jack progs that come with it for that matter)?
I can post what I've done, but it'll take half an hour to edit into something sensible, then there'll be some back and forth no doubt, and I've already taken up a lot of our time (personally getting to this point (including our previous chat re class/method/libraries) a good days work, 8-10hrs) and basically I'm running out of time very unfortunately. The real world is interfering with my learning !

I'm running out of languages to say thank you in, Merci !

PS I can't find any examples of the behaviour I want in Jack, believe me I've looked. Many examples use the static keyword, but they seem to be using like the C const, rather than static.

PPs I appreciate the C example is not the best, but in the light of our previous conversation hopefully that makes sense, the shared static incrementing when any object of the same class increments it. The problem is the initialisation only once
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

WBahn
Administrator
Lozminda wrote
Then you want z and y to have DIFFERENT variables called MyStatic, which means you want them to be field variables and not static variables. Static variables are a single instance of a variable visible to all functions and methods of a class.

No, I want MyStatic to be shared by z and y...
Then I don't know what you meant by

MyClass z,y;
// So z.MyStatic should equal 4500 but I want y.MyStatic = 5500;
If MyStatic is SHARED by z and y, how can z.MyStatic equal 4500 while y.MyStatic equal 5500?
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
Because a method has altered it and the new value is now something different.

jack Static is not what C programmers would call const is it ?
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
In reply to this post by Lozminda
Maybe this is better...

 Static variables are a single instance of a variable visible to all functions and methods of a class.


How do I code that so that the static is initiated once  and assigned a value (when the first object is created) but then Isn't re-initiated on the creation of subsequent objects?
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

WBahn
Administrator
In reply to this post by Lozminda
Lozminda wrote
Because a method has altered it and the new value is now something different.
So what do you expect z.MyStatic to now be?

jack Static is not what C programmers would call const is it ?
It's pretty much, but not exactly, what a static variable in C is. Keep in mind that what 'static' means in C is somewhat dependent on where in the program that keyword is used.

But for cases where you define a local variable in a function to be static, then that variable is "statically allocated" (hence the name) meaning that it's lifetime lasts from the beginning of the program to the end of the program.

It is NOT a const (unless you add that modifier) and you can change it all day long. But it's value is retained from one invocation of a function to the next.

Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
Great we agree at this point...
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
What I should have said (had to leave and was being hastey)

Is that I agree with your C definition of static.

From what I can work out jack.static is different from C_Family.static. I'm going to have another go at explaining what I'm trying to understand later/express in Jack, in simpler terms, as I haven't got an answer to my question. Unfortunately I don't have time now, it'll have to be later. Thanks for your efforts, hopefully we'll get it hammered out during the week/next weekend.

Also getting this definition/utilisation sorted will help me with the later projects (i'd imagine) and Might help others with a C/C++ background too (Maybe).

If anyone else happens to be reading this and understands the question that I'm asking maybe a third point of view would be helpful.

Thanks WBahn for you time and efforts, an anyone else that wants to contribute !

Lozminda



Ps I signed off but then thought I'll look for a quick example online in C++

class Box {
   public:
      static int objectCount;
     
      // Constructor definition
      Box(double l = 2.0, double b = 2.0, double h = 2.0) {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         
         // Increase every time object is created
         objectCount++;
      }
      double Volume() {
         return length * breadth * height;
      }
     
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void) {
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
}

Box.objectCount increments everytime an object of type Box is created. Is it possible to do this in Jack, and could i have a code example in Jack of how to do it please.  I don't think I can express myself any clearer, but I've got a week if not.
All the best
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

WBahn
Administrator
In reply to this post by Lozminda
Lozminda wrote
Maybe this is better...

 Static variables are a single instance of a variable visible to all functions and methods of a class.


How do I code that so that the static is initiated once  and assigned a value (when the first object is created) but then Isn't re-initiated on the creation of subsequent objects?
I would do this the same way that several of the o/s libraries are initialized. Create an init() function that is called at the beginning of the program (the person writing the program has to remember to do is) that sets the value of the static variables.

If you wanted to avoid this and make it invisible to the user, you could create an additional static variable that your constructor checks looking for a specific sentinel value, such as 4242. So your init() code might look like:

function void init()
{
   if (initFlag = 4242)
   {
      return;
   }
   myStatic = 1000;
   ...
}

and your constructor might look like

constructor MyClass new(...)
{
   do MyClass.init();
   ...
}

Since the initial values of static variables is unknown (IIRC), you are relying on it being very unlikely that the initFlag variable will just happen to be equal to 4242 by random change during the power on process (you have about a 1 in 65,000 chance of being unlucky enough for this assumption to be wrong).

Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
Hi

Apologies for the delay, paid work got in the way ! I've managed too code a slightly less ugly (but still ugly) implementation of the static behaviour i'm trying 'to get'

constructor MyClass new(String inputString, bool  IsThisTheFirst_TimeAnObect_of_thisClassHasBeenConstructed )
{
 
  if (IsThisTheFirst_TimeAnObect_of_thisClassHasBeenConstructed ) let MyStatic = StartingValue;
   ...
}

And in the main function

{
   var MyClass a, b, c;
   let a = MyClass.new("SomeInput", true);                   // It works, but not ideal
   let b = MyClass.new("SomeInput", false);
   let c = MyClass.new("SomeInput", false);
}

It was partially inspired by your reply (WBahn) but I couldn't quite understand what your code was saying....
(I appreciate that you don't want to hand the answer on a plate in true N2T style..)

function void init()                    // This clearly isn't a method in MyClass. It will almost always return myStatic as 1000.
{                                               //  but as it's not a method in MyClass it Doesn't have access to myStatic. Ok so a getter
   if (initFlag = 4242)                // and setter is used, but MyClass has to be initialised with var, then call void init, then
   {                                            // call the constructor ?
      return;
   }
   myStatic = 1000;
                 // This should be ??:     let myStatic = MyClass.set_myStatic(1000);
   ...
}

and your constructor might look like

constructor MyClass new(...)
{
   do MyClass.init();
   ...
}


So here is my jack version based on your suggestion..

MyClass.jack:
class MyClass
{
   static int MyStatic;
   field int MyInt;

   constructor MyClass new()
   {
      let MyInt = 4;
      let MyStatic = MyStatic + 1000;
      return this;
   }

   method int getMyStatic() { return MyStatic;}
   method int setMyStatic(int value)
   {
      let MyStatic = value;
      return MyStatic;
   }
}


Init.jack
class Init
{
   function void init()
   {
      var int initFlag;
      if (initFlag = 4242)
      {
         return;
      }
      let MyClass.MyStatic = 1000;
      return;
   }
}


Main.jack
class Main
{
   function void main()
   {

        var MyClass x,y,z;
        do Init.init();
        let x = MyClass.new();
        let y = MyClass.new();
        let z = MyClass.new();

      return;
   }
}


And the errors I'm getting from the compiler
In Init.jack (line 10): In subroutine init: MyClass is not defined as a field, parameter or local or static variable
In Init.jack (line 10): In subroutine init: Expected [ or =


Is essentially because I can't access MyStatic if it's a member of MyClass....

At the end of the day my implementation works, but is not elegant. I can't get your implementation to work and I think this is due to me either
1) not understanding something about Jack ?
2) not understanding something about the implementation of your code ?
3) or maybe that code is wrong ? I.e. the idea you can initialise a static using a non member function as part of a constructor ? Maybe ?

The reason for this is
a) I'm trying to understand jack.
b) Trying to understand what you're trying to get across .

I'm sure there's lots I'm missing, and would like to know (if you have time) what you were trying to implement.
Kind regards, Lozminda

ps
I mean why have that function init ? (I know you say to initialise the static, but then just have let MyStatic = 1000) . When you declare var int Init, Init is zero, quoting:
 7.2.6 VM Programming Examples
(iii) the local variables that it is supposed to use are initialized to 0 and located in the local segment.

When I printInt(Init) it is indeed 0 and therefore  

      if (initFlag = 4242)
      {
         return;
      }


is completely redundant no ? Surely I'm wrong ?
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

WBahn
Administrator
Lozminda wrote
Hi

Apologies for the delay, paid work got in the way ! I've managed too code a slightly less ugly (but still ugly) implementation of the static behaviour i'm trying 'to get'

constructor MyClass new(String inputString, bool  IsThisTheFirst_TimeAnObect_of_thisClassHasBeenConstructed )
{
 
  if (IsThisTheFirst_TimeAnObect_of_thisClassHasBeenConstructed ) let MyStatic = StartingValue;
   ...
}

And in the main function

{
   var MyClass a, b, c;
   let a = MyClass.new("SomeInput", true);                   // It works, but not ideal
   let b = MyClass.new("SomeInput", false);
   let c = MyClass.new("SomeInput", false);
}
If you want the value of MyStatic associated with instances a to not be the same value that is associated with b and for those to not be the same value associated with c, then you cannot use a static variable because a static variable means that you have ONE variable that is accessed by all three. ANY of the three can change it, but that change is see by ALL of the other instances.

Let's say that you want to assign street addresses automatically when you create new houses with the first one starting at 12100 and each on after than going up by 50. This is easy to do. You have ONE static variable that you call an initialization function to set it to 12100 and then the constructor copies the current value into a field variable and increments the static value.

class House
{
   static int nextAddress;
   field int address;

   function void init()
   {
      let nextAddress = 12100;
   }

   constructor void new()
   {
      let address = nextAddress;
      let nextAddress = nextAddress + 50;
   }
}

Now you just call House.init() once sometime before you create your first house.

nextAddress is a static variable. It is visible to all functions and methods in the House class.

address is a field variable. There is a separate variable for EACH instance of the object and ONLY methods can access the one associated with the instance it is called from.

NONE of these are automatically initialized to zero. That ONLY happens for local variables.
Reply | Threaded
Open this post in threaded view
|

Re: Static variables !

Lozminda
Awesome, thank you very much.

The block in my understanding was for some reason I thought one couldn't have methods and functions in the same class, hence me having an Init class in my example and not understanding how in your example a function init could be called in MyClass.

And to be fair to the course, in Fraction (an example supplied in the Project 9 folder), the class fraction has both methods and functions in that class. So my bad as they say.

Ah ha, it's all so clear now !

Thanks again for your perseverance.

Lozminda