まあ、試してみりゃすぐわかる話なんだけど、
val p = println _ p()
の方が正解。で、println(_)は(x) => println(x)のシンタックスシュガーなんだけど、xの引数の型が推論できないので、コンパイルエラーになっちゃうのであった。だから、実は
val p: String => Unit = println(_) p("FOO")
のようにして、型を明示してやればコンパイルを通る。
一方、println _の方は、メソッドから対応する関数オブジェクトに変換するための構文であり、println _の結果にあいまい性が無ければOKなので、コンパイルを通る。あいまい性がある場合というのは、たとえば
class A { def f(x: Int) = x def f(x: Double) = x } val a = new A val f = a.f _ //a.f _はあいまい
のような場合で、このとき、a.fはf(Double)を指しているのか、それともf(Int)を指しているのかがあいまいになる。
この場合、
a.f _:(Int => Int) // a.f _:Intではない
のように変換先の型を明示してやることで、コンパイルを通るようになる。