Declaring an equation as a global variable

Hi all, Can you before set up declare an equation as a global variable. e.g. x =y+4? So that in your main program wherever y is given a value, x is automatically determined. If y=2 then x =6.
I would say yes. But a google search doesn't give any guidance so I may be wrong. It certainly would be useful especially if it worked for more complex equations. There could be a limit on its complexity.
I know some of you may say try it. But it is surprising that there seems to be no guidance on this anywhere considering its importance. I may of course be completely wrong on this as I so often am.
Another example. x=(digital read(9)). Every time x appears in the main program its value is automatically determined by the global variable.

Do you mean something like this ?

#define x_calc y + 4

void setup()
{
  Serial.begin(115200);
  int y = 2;
  Serial.println(x_calc);
  y = 123;
  Serial.println(x_calc);
}

void loop()
{
}

may be a "better" version as

#define x_calc (y + 4)

otherwise

  Serial.println(x_calc * 10);

would not give you want you want


@petercl14
using macros like this is fun but discouraged. you could use a function and make it clear that the result depends on y

inline long myFunction(long y) {return y+4;}

then you would call myFunction(y) wherever needed

if the intention is to save the overhead of a function call in C++ you could define an inline function, e.g.

inline int x_calc(int y) {
  return y + 4;
}

void setup()
{
  Serial.begin(115200);
  int y = 2;
  Serial.println(x_calc(y));
  y = 123;
  Serial.println(x_calc(y));
}

void loop(){}

a run gives

09:13:34.464 -> 6
09:13:34.464 -> 127

the idea is that the function body is generated at each point when it is called saving the overhread of a function call
clearly do not use it if the function code is longer than a few statements
note that inline is a request to the compiler - it can ignore it

Personally I don't think that I would use a #define in any case as, problems aside, they tend to hide what the program is really doing as illustrated by your example problem

Although we do not have a real example of the problem that @petercl14 is trying to solve it implies that the calculation must be done multiple times in the sketch to warrant using a #define or a function to do it. If so, then there may be opportunities to improve the sketch in other ways

Therefore,
may be a "better" version as
===> might be a "better" version as

I actually meant "maybe" (because I'm not convinced it's better, using a function is the better way)

Yes, with a lambda expression:

auto calc = [](int16_t x) {
  return x + 4;
};

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println(calc(4));
  Serial.println(calc(6));
}

void loop() {
}

Or with a function pointer:

int16_t calc(int16_t x);
int16_t (*functPtr)(int16_t) = calc;

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println(functPtr(4));
  Serial.println(functPtr(6));
}

void loop() {
}

int16_t calc(int16_t x) {
  return x + 4;
}

Yes the calculation must be done multiple times. Tried many other things like a subroutine none of which worked in the sketch.

Short answer is "no", other than defining a function that does the calculation, and calling that function whenever you need the value updated. Variables do NOT updated magically on their own.

Well we would have to see one of your attempt at using a function (no subroutine in C++ terminology) to tell you where you got it wrong.

yes for "short".

longer answer could be that with an OO approach you could overload the cast operator to allow an object identifier to be used where โ€” say a long โ€” would be needed and return always the result of some hidden math in the overloaded method

something like this

template <typename T>
class AutoCalcNumber {
  public:
    T& val;
    AutoCalcNumber(T& x) : val(x) {}
    operator T() const {
      return val + 10;
    };
};

long x;
AutoCalcNumber<long> y(x);

void setup() {
  Serial.begin(115200);
  x = 10;
  Serial.println(y); // will print 20
  x = 20;
  Serial.println(y); // will print 30
  long z = y * 2;
  Serial.println(z); // will print 60 but z won't evolve when x evolves. One time evaluation
}

void loop() {}

Or, as I mentioned, a lambda expression. Trouble is, @petercl14 has provided such a poor problem description that it's impossible to know what's really needed.

long x;
auto y = []() -> long {return x + 10;};

void setup() {
  Serial.begin(115200);
  delay(1000);

  x = 10;
  Serial.println(y());
  x = 20;
  Serial.println(y());
  long z = y() * 2;
  Serial.println(z);
}

void loop() {
}

well, it's just like a function, you have to add the () after the "variable's" name which you don't have if you overload the cast operator

We really need to see some code from the OP. Seeing as they have explicitly stated that they cannot get the code to work using a subroutine (presumably meaning a function), the probability of suddenly being able to magically write that working function and placing it in a less-common construct than an ordinary function is fairly remote.

agreed, a function is the way to go as said in #3
the rest is for the fun as OP seems to be MIA...

As the examples in the thread show, there are ways to achieve a facsimile of this, but taking the question literally, no you can't. Further, you really wouldn't want to in practice because if you had a lot of such things going on, your code would be a nightmare to debug. You could probably also set up some nasty circular dependency that would throw your code into an infinite loop.

I did read a proposal for a language many years ago that would do exactly what you're asking, but as far as I know, it was never actually implemented, likely because of the horrendous complexity and debugging issues that would ensue.

it feels like excel and cells evaluation

Yes function is in subroutine. Subroutine is not in 'void loop' just as in an interrupt call. Problem
solved by making subroutine much briefer in this case. Would not work when the subroutine was longer.

Well I am using a subroutine in Arduino. There may be no subroutine in C++. I guess Arduino is not exactly the same as C++. call to subroutine in main program 't=read_sensor(); The subroutine is 'double read_sensor(){ here is the function}