Access to global variables in IJ Macro functions

Hi @aklemm @ctrueden @haesleinhuepf @imagejan @Fabrice_Cordelieres @Wayne ,

I am preparing for an IJ Macro course and got caught by surprise. I constructed below beautiful example, but it behaves more as in real life than as in Java, i.e. the result is “old salary = 10” and “new salary = 10”.
Looks like IJ Macro functions only have read access to global variables but no write access. Is that the how it is?

salary = 10;
incrementSalary( 10 );
print( "new salary = " + salary );

function incrementSalary( raise )
{
    print( "old salary = " + salary );
	salary = salary + raise;
}

Even weirder is the behaviour below (maybe connected to the behaviour above).

incrementSalary( 10 );

function incrementSalary( raise )
{
	xxx = xxx + raise;
	print( "hello" );
}

This prints “hello”, but does not throw an error, even though xxx as never been defined.


Any ideas? Am I making a mistake?

Thank you for your time and help!

2 Likes

Hi @Christian_Tischer,

have you tried with the var statement (documentation)?

Furthermore, I honestly think we should teach avoiding global variables to students. Global variables do not reflect best practice for programming in the 21st century. Further reading:

I hope that helps!

Cheers,
Robert

4 Likes

Ok, in fact this works (prints 20):

var salary = 10;
incrementSalary( 10 );
print( "new salary = " + salary );

function incrementSalary( raise )
{
	print( "old salary = " + salary );
	salary = salary + raise;
}

But this is confusing isn’t it?!

  1. why does one only need var for the global variables?
  2. why is var only necessary for write access but not for read access?

But I don’t think we can completely avoid talking about global variables, because newbies will for sure at some point make the mistake of accessing a global variable from inside a functions, e.g. when copy and pasting code into a function. I mean this happens to the best of us, right?
So, maybe show it but then say: Do not do it! ?!

Ok, and regarding the other issue:

x = x + 10;
x = 3 * x
print( x );

Variables seem to be indeed instantiated on the fly! Above example prints 30. Are there other programming languages that behave like this? Anyway, probably something to even avoid showing during teaching??! [EDIT: this is in fact considered a bug and not a feature, see @Wayne’s response below].

1 Like

Yes. Tell them a function is some kind of an independent program that shouldn’t access variables of other programs. Otherwise, the programs (and the programmer) get confused. You may also show them a confusing example.
I have such confusing examples in my python course to make students aware of execution-order issues in Jupyter Notebooks. That’s btw also an issue related to global variables.

3 Likes

That’s indeed a good example. I would almost say: don’t use notebooks for production code…

2 Likes

This is a bug that is fixed in the ImageJ 1.53c62 daily build. The statement “v=v+10;” now generates

Undefined variable in line 1
v = <v> + 10;
5 Likes

Regarding question #2, my understanding is that in the macro language the input argument of a function, if not defined as a global variable, is passed by value, i.e. inside the function it is just a copy, unless it is an array. In this case it is passed by reference, which means that its content can be modified inside the function. This is similar to other languages, e.g. Python when using lists.
Just compare the results of the following two scripts, conceptually equivalent

salary = 10;
incrementSalary( salary, 10 );

print("new salary = ", salary);

function incrementSalary(s, r)
{
print( "old salary = ", s);
s = s + r;
}

versus

salary = newArray(1);
salary[0] = 10;
incrementSalary( salary, 10 );

print("new salary = ", salary[0])

function incrementSalary(s, r)
{
print( "old salary = ",s[0] );
s[0]= s[0] + r;
}

The first one will return 10, while the second 20.

2 Likes

Thanks! Very good point, that makes a lot of sense! In the light of this I feel the behaviour is actually somewhat logical!

Hi @Christian_Tischer!

As is described in the docs cited by @haesleinhuepf, the var statement seems to be most relevant in a macro collection file, where you have to keep tabs on certain variables between each on-demand execution of different blocks of code. It is a simple way to have non-volatile states within a session (btw, are there any others I might be missing?). I am a confessed heavy user of that functionality in this forum.

But as Robert also points out, it is not a good idea to use them in other contexts, as it’s quite easy to run into problems.

Cheers,
Nico