[SOLVED] Extra brackets make error as "missing parameter type for expanded function"

Hi,

The following line works well and returns correct result:
(1 to 5).filter(_ % 2 == 0)

I add brackets to make sure the remainder is done before check “is equals” like the following line. Yes I know the operator precedence of % is higher than the one of ==. I just have “bad” behavior to build explicit calculation.
(1 to 5).filter((_ % 2) == 0)

However I got the following error (the error is pointed to character ‘_’):
error: missing parameter type for expanded function ((<x$1: error>) => x$1.$percent(2))

It seems such error doesn’t matter the parameter is placeholder or named variable, the function is in block by ‘{’ / ‘}’ or ‘(’ / ‘)’. It’s appreciated somebody can point out the root cause – it’s really strange for me :frowning:

Best Regards,

This is a classic pitfall. The underscore notation for functions only works for “simple expressions”, and while I’m not entirely sure what a simple expression is, in my experience it often picks the inner-most parentheses.

So, this:

*(1 to 5).filter(_ % 2 == 0)*

will be expanded as expected to

(1 to 5).filter(i => i % 2 == 0)

This typechecks correctly, because filter expects a function Int => B, so it finds that i is of type Int, and then so is i %2

However, this:

*(1 to 5).filter((_ % 2) == 0)*

will be expanded to

(1 to 5).filter((i => i % 2) == 0)

Note that (i => i %2) is a function, not a function call, and all the compiler knows about that function is that it is compared to 0, so it doesn’t know what the argument type for the function should be. Also, the argument to filter is of type Boolean, but filter expects Int => Boolean

2 Likes

Hi curoli:

OK (_ % 2) will be a function instead of value(or function call as you mentioned)! That made sense. Yes what I did will get type Boolean, that is the root cause.

Your explanation is very clear and detailed. Thanks a lot for your kind and prompt help!

Best Regards,

My advice is to minimise the use of underscore notation.

For example, I also prefer to be explicit about the precedence of mathematical operations so the code is clearer, the same argument goes for named parameters.

foo.filter(x => (x % 2) == 0)

I only use the _ for things like foo.map(_.bar) or foo.reduce(_ + _)

1 Like

Yes totally agree with your comments! My philosophy is clear and readable lines are better codes (maybe that is why I’m not master now :joy:).

I like your code

foo.filter(x => (x % 2) == 0)

that is the style I will follow. Thank you again!

Best Regards,