Naming lambdas in LLVM Coding Standards

The LLVM Coding Standards documents only mentions lambdas when it comes to formatting the lambda body.
However, I could not find any guidance about what capitalization we should use when it comes to naming a lambda variable.

  • Variable names should be nouns (as they represent state). The name should be camel case, and start with an upper case letter (e.g. Leader or Boats).
  • Function names should be verb phrases (as they represent actions), and command-like function should be imperative. The name should be camel case, and start with a lower case letter (e.g. openFile() or isFoo()).

I believe, I should name my lambda variable as if it was a function, since it encodes some operation, thus it deserves a verb.

That being said, I should use the isCommutative instead of IsCommutative in the following example:

const auto isCommutative = [](BinaryOperatorKind Op) {
  return true /*TODO*/;
};

On the other hand, .clang-tidy sets the readability-identifier-naming.FunctionCase: camelBack and readability-identifier-naming.VariableCase: CamelCase, thus using isCommutative would trigger the corresponding warning.

This topic raised a couple of questions in me:

  • Which casing should we prefer for lambda variables?
  • Should we educate the readability-identifier-naming about recognizing lambda variables?
  • How should we generalize, let’s say a lambda initializes an llvm::function_ref<> or std::function variable?
  • Should the Coding Standards document mention this in the naming paragraph to make this decision explicit?

@clattner

I remember there was a discussion on this very topic few months (or years?) ago and the consensus then matched your preference here (i.e. isCommutative rather than IsCommutative). And thus later code are adopting that convention.

So I would +1 on this one.

Good question, I don’t remember if the previous discussion covered llvm::function_ref or not. Personally I think we should also use function casing for llvm::function_ref for consistency.

We probably should do this.

My impression was that lambdas should be formatted as variables, and all code I’ve written and reviewed in recent years has followed that convention. I do recall seeing a discussion, but I don’t recall when and I certainly don’t recall the consensus being to use function-casing style (so I’d write IsCommutative as an example).

My logic for casing is that a lambda is more-or-less the same as a class with an operator() method. Imagine the following snippet:

class CommutativeFn {
  bool operator()(BinaryOperatorKind Op) { return true; }
};

bool functorClass(...) {
  CommutativeFn IsCommutative; // what should this variable's casing be?
  return IsCommutative(...);
}

bool lambdaFunction(...) {
  const auto isCommutative = [](BinaryOperatorKind Op) { // what should this casing be?
    return true;
  };
  return isCommutative(...);
}

bool functionRef(function_ref<bool(BinaryOperatorKind)> IsCommutative, ...) { // what should this casing be?
  return IsCommutative(...);
}

bool isCommutativeFunc(BinaryOperatorKind Op) { return true; }

We have four different situations. I would argue that only the fourth of these (the pure function case) is a function, as opposed to a function object. If you were to argue that the first case should actually also use lower-case, then I would counter with a question: at what point does a class with an operator() stop using that style? How much state/other behaviours/… does it need?

Aside: this is a perfect demonstration as to why it doesn’t make sense to use different casing styles for functions and variables, because they are largely interchangeable in the general sense.

Here the previous discussion: RFC: should we spell lambdas like functions?

1 Like

Thanks @mehdi_amini, that’s the one I was thinking of.

Skimming through the discussion, it sounds like there were a fair number of people who preferred UpperCamelCase for lambdas (and any function object essentially), but I don’t think a consensus was reached either way.

If clang-tidy is specifying a specific scheme already, I suggest that’s our de facto standard and we should document that, unless there’s strong push back in the other direction?

I’m in the “they are variables” camp. Although I wouldn’t object to verbs as names.

I am also in keeping the UpperCamelCase convention. We would end up with a table

  • the type is bool → use this convention
  • the type is a callable → use this convention
  • the type is a class → use this convention

Why are lambdas special?

I think we should continue to take a literal and syntactic interpretation of the coding standards, meaning lambda variables should use leading upper case characters like other variables.

If we add special cases for certain kinds of variables, then we have to ask if those rules extend to other callable variables such as std::function, llvm::function_ref, plain function pointers, etc. That seems more ambiguous than the current rules, which are straightforward.

I think people should feel free to use verbs in names as much as they like.

1 Like