Because we support access to non-functions in classes in Pike. If we'd think functions are good enough to access constant values then we'd reasonably also apply the same approach to variables and therefore force all variables to be private, or at least protected. From a OO-theoretical point of view that'd make the language more clean.
I don't see how this follows. Are you referring to the fact that constants can be accessed without adding "()", and that removing this, we should also remove the possibility to access variables without "()"? In that case, I did not suggest removing the ()s. Simple use a getter function.
int `x() { return 3; }
makes "x" accessible in exactly the same way as
constant x=3;
does. Well, apart from the fact that you currently can't call functions in class-values, but that is a bug we could fix. Other major OO languages allow it.
In the case of variables, we conceptually get default getters and setters for non-private variables unless they are overridden. I don't see any reason to change that.
[...] More importantly it saves unnecessary function calls,
That sounds like an implementation detail that could be handled by the optimizer.
and it's more convenient when there is a substantial risk that the identifier doesn't exist at all. That's why Error.Generic uses constants:
class MyError { inherit Error.Generic; constant error_name = "MyError"; // ... }
mixed err = catch (blabla()); if (objectp (err) && err->error_name == "MyError") my_error_handling (err); else throw (err);
If we'd be forced to use functions here then the error test would become even clumsier:
if (objectp (err) && functionp (err->error_name) && err->error_name() == "MyError") ...
Again, define `error_name rather than error_name, and you can still use the more conveient variant.