user2051561 user2051561 - 11 days ago 4
Scala Question

Scala operator #> causes compilation error but not &> - why?

I have a type inference issue and asked for help here.
The initial problem was due to overload. Once corrected I
still had problems.

So here is the code:

class DPipe[ A ]( a: A ) {
def !>[ B ]( f: A => B ) = Try(f( a ))
def #>[ B, C ]( f: B => C )(implicit ev: A =:= Try[B]) : Try[C] = a.map(f)
//def &>[ B, C ]( f: B => C )( implicit ev: A =:= Try[ B ] ) = a.map( f )
}

object DPipe {
def apply[ A ]( v: A ) = new DPipe( v )
}

object DPipeOps {
implicit def toDPipe[ A ]( a: A ): DPipe[ A ] = DPipe( a )
}


And here are the tests:

object DPipeDebug {

def main( args: Array[ String ] ) {

import DPipeOps._

val r8 = 100.0 !> {x : Double => x / 0.0}
println(r8)
val r9 = r8 #> {x:Double => x* 3.0}
println(r9)
/*
val r8 = 100.0 !> { x: Double => x / 0.0 }
println( r8.get )
val r9 = r8 &> { x: Double => x * 3.0 }
println( r9 )*/

val r10 = (100.0 !> {x : Double => x / 0.0}) #> {x:Double => x* 3.0}
//val r10 = ( 100.0 !> { x: Double => x / 0.0 } ) &> { x: Double => x * 3.0 }

val r11 = 100.0 !> {x : Double => x / 0.0} #> {x:Double => x* 3.0}
//val r11 = 100.0 !> { x: Double => x / 0.0 } &> { x: Double => x * 3.0 }
}

}


As it stands we have the following error in the last code line:

Cannot prove that Double => Double =:= scala.util.Try[Double].
val r11 = 100.0 !> {x : Double => x / 0.0} #> {x:Double => x* 3.0}
^


Notice that in the second last code line, I need only add
the parenthesis to enforce left left-hand associativity
(Scala default). It seems like the
#>
operator tries to
use the function
{x : Double => x / 0.0}
, which indeed is a
Double.

If however I use the "&>" operator, no error occurs. In the
test code below, just flip the comments. So my question is, why
is this happening. Is this something new to Scala 2.12.0?

TIA

Answer

The problem is with the operator precedence. Here are more details: Operator precedence in Scala

It depends on the first character of the operator. # has higher precedence than ! and ! has higher precedence than &.

Hence you get

100.0 !> ({x : Double => x / 0.0} #> {x:Double => x* 3.0})

instead of

(100.0 !> {x : Double => x / 0.0}) #> {x:Double => x* 3.0}
Comments