Scala中By-name parameter相关疑问:myAssert参数机制困惑
myAssert and By-Name Parameters in Scala Let's break down how the myAssert function works, and why by-name parameters are such a nice improvement here.
First, let's look at the original implementation:
var assertionsEnabled = true def myAssert(predicate: () => Boolean) = if (assertionsEnabled && !predicate()) throw new AssertionError myAssert(() => 5 > 3)
How myAssert's parameter works
The parameter predicate: () => Boolean is a function type—it expects you to pass in a no-argument function that returns a Boolean.
When you call myAssert(() => 5 > 3), you're creating an anonymous function (() => 5 > 3) and passing it as the argument. Inside myAssert, we have to explicitly call this function with predicate() to run the expression 5 > 3 and get its Boolean result.
This works, but it's clunky—having to wrap every assertion expression in () => ... gets tedious fast.
Enter By-Name Parameters
Scala's by-name parameters fix this verbosity. Here's the improved version:
def byNameAssert(predicate: => Boolean) = if (assertionsEnabled && !predicate) throw new AssertionError byNameAssert(5 > 3)
The predicate: => Boolean syntax defines a by-name parameter. Here's what makes it different:
- You can pass a raw expression (like
5 > 3) directly, no need to wrap it in an anonymous function. The compiler handles that wrapping for you behind the scenes. - The expression isn't evaluated immediately when you call the function. Instead, it's evaluated only when it's used inside the function body (in this case, when we check
!predicate). - If the expression is used multiple times in the function, it will be re-evaluated each time (unlike a function parameter, which is a single function instance that you can call multiple times).
Key Difference Between the Two Approaches
- For
myAssert's function parameter: The anonymous function is created at call time, even ifassertionsEnabledisfalse(though we won't call it in that case). - For the by-name parameter: The expression
5 > 3isn't evaluated at all ifassertionsEnabledisfalse—the compiler only generates code to evaluate it when needed.
In short, myAssert uses an explicit function parameter to enable delayed execution of the assertion check, while by-name parameters are a syntax sugar that makes this pattern cleaner and more readable.
内容的提问来源于stack exchange,提问作者Mandroid

