2015-10-20 2 views
2

Я играл немного с заполнителем и обнаружил странный случай:Scala: заполнитель внутри кортежа

val integers = Seq(1, 2) 
val f = (x:Int) => x + 1 
integers.map((_, f(_))) 

который возвращает

Seq[(Int, Int => Int)] = List((1,<function1>), (2,<function1>)) 

Я ожидал

Seq[(Int, Int)] = List((1, 2), (2, 3)) 

Если я внести следующие изменения: все работает должным образом:

integers.map(i => (i, f(i))) 

Любая идея, почему функция f не применяется во время отображения?

ответ

3

Компилятор Scala не может читать ваш разум, поэтому синтаксис заполнителя _ полезен только в очень простых выражениях.

В вашем примере:

integers.map((_, f(_))) 

он оценивает f(_) как отдельную подвыражении, так что вы в конечном итоге с чем-то эквивалентным к этому:

x => (x, y => f(y)) 

Даже если компилятор не сделал обработать f(_) как свое собственное подвыражение, результат будет не таким, как то, что вы хотите:

integers.map(i => (i, f(i))) 

Вы хотите, чтобы оба экземпляра _ обрабатывались как один и тот же аргумент, а не то, как работает _. Каждое вхождение _ в выражении всегда рассматривается как уникальный аргумент.

5

Подчеркивание стоит только для переданного аргумента. Таким образом, в integers.map((_, f(_))) 1-й _ является значением от integers, но второй _ имеет автономное значение «частично примененной функции».

Если ваша анонимная функция принимает 2 (или более) аргумента, то вы можете использовать символы подчеркивания (или более), но каждый из них принимает свой аргумент только один раз.

+1

Другими словами @Francis ваша программа эквивалентна: 'val integers = Seq (1, 2); val f = (x: Int) => x + 1; val g = f (_); integers.map ((_, g)) ' – mjaskowski

Смежные вопросы