Duplicate variables in classes will now be a compile time error. Quark/Class authors beware!

#7340 Has made it a compile error to have variables with identical names in classes. This means classes that previously did this (probably by mistake) will need to be rewritten.

A {
   var a, a; // <-- now a compile error
}

This is obviously wrong above, but when you have inheritance things gets less obvious — this is also where the bugs start arising!

A {
	var <a = 1;
	getA { ^a }
}

B : A {
	var <a = 2;
	getA { ^a } // << turns out this 'a' is A.a, not B.a.
}

// as expected
A().a // 1
A().getA // 1

// not as expected
B().a // 2 // << yet this one is B.a ??
B().getA // 1  // << A.a

This is now a compile time error and the class library will not compile.

ERROR: Found duplicate instance variable name 'a'
  in file '/home/jordan/.repo/SuperCollider/SCClassLibrary/Common/Core/Object.sc'
  line 7 char 7:

  	var <a = 2;
         
  	getA { ^a } 

Fixing this is left up to the author…

…but, hopefully, this is trivial and you can just remove the duplicate.

Just wanted to announce this somewhere and give people a heads up that this change is incoming.

If anyone finds a duplicate that isn’t trivial to fix, do let me know and I will see what can be done about it!

Some things to watch out for:

  • Read and write access, what happens when the access is different, which variable did it alter previously?
  • super.newCopyArgs, which variable was actually getting the value?
  • Serialisation/archiving what happened previously?

If anyone finds some code where they actually relied on this behaviour, please reach out as well, it would be good to see if we can find a work around.

Jordan

1 Like

Will this be backported to SC 3.14? (I wouldn’t object…)

Thanks, Stefan

Hi, I sometimes overwrite vars in subclasses to give them a different default value. Any advice on an alternative for this? I mean I can think of workarounds, but it is a kind of elegant to do it…

That is a little awkward to do. I’d use keyword args and newCopyArgs (but then again, I’m biased)…

Base {
	var <>a = 'ImA', <>b = 'ImB';
    *new { |...args, kwargs|
        ^super.superPerformArgs(\newCopyArgs, args, kwargs);
    }
}

Derived : Base {
    *new {  ^super.new(b: 'NewB')  }
}

Derived().b == 'NewB'

I don’t think this will be back ported, it is looking more likely this will be made a warning in the next version, and an error in the following.

Ok, following the discussion on Github that makes sense for me too. Probably better to first make it a warning in SC 3.15 and then an error in SC 3.16. A warning is useful too as it’s a valuable hint on where I’ve (unintentionally) declared a duplicate variable (can’t think of a situation where I’d do that on purpose).