A question about good naming style


#1

I’ve just started learning Reason today, because I want to play with Reprocessing. I came across a piece of code that threw me, because of the re-use of a variable name, and I wanted to check whether this is considered good style.

For full context, the entire source code of this file (it’s not vary large) is here on Github

Below is the code of the function that confused me. It draws a square on the screen. You can see that it takes an argument squarePos, and inside it has a named let binding (sorry if this is the wrong terminology) that’s also called squarePos:

let (x, y) as squarePos = [...]

I get that these two squarePos mean the same thing (the position of the square) but it surprised me a little to see the name being reused. Is this a good pattern for when a function takes a parameter and then returns something that means the same thing, but possibly with new values? Or would the internal squarePos be better named updatedSquarePos or something like that?

let draw = (squarePos, env) => {
  background(color(~r=150, ~g=255, ~b=255, ~a=255), env);
  let (sx, sy) = squarePos;
  let (px, py) = pmouse(env);
  let (x, y) as squarePos =
    if (mousePressed(env) && px > sx && px < sx + squareSize && py > sy && py < sy + squareSize) {
      let (mx, my) = mouse(env);
      let dx = mx - px;
      let dy = my - py;
      (sx + dx, sy + dy)
    } else {
      squarePos
    };
  rect(~pos=(x, y), ~width=squareSize, ~height=squareSize, env);
  squarePos
};

#2

Hi, in OCaml and Reason it’s fairly idiomatic to reuse the same name. Some people don’t like it because it can be confusing, but the argument for it is that it’s better than e.g. squarePos1, squarePos2,…

When we rebind a name like this, we do need to check and make sure that the rest of the scope is definitely not expecting to use the old binding, since that becomes invisible. So that is also another point against rebinding.


#3

Thanks, that makes sense :slight_smile:


#4

Yeah if you get used to it, it’s a simple way to “throw out” a variable in favor of a new one which has the exact semantic meaning and type.
We do this a lot for state in Reprocessing. So you’ll see code like this where we just shadow the variable state throughout the program but never mutate it. It works pretty well for us.