scala - Why does a unary operator enable a ()=>X implicit conversion? -


i encounter issue implicit ()=>x conversion happens when define , use unary operator. below minimal example:

class gate {   def unary_!(): gate = }  class foo {   private def foo(f: () => gate) = 1   val gate = new gate    // compiles, -xprint:typer shows becomes   //   foo.this.foo({   //     (() => foo.this.gate.unary_!())   //   })   foo(!gate)    // not compile,   //  error: type mismatch;   //  found   : gate   //  required: () => gate   //  foo(gate)   foo(gate) } 

where () => gate conversion happens , why happen unary_!?


edited

thanks answer! raised question because eta expansion (from x () => x blocks implicit conversion defined x , wanted happen. removing unnecessary parentheses unary_! solves problem us. thanks!

this eta-expansion, turns method function.

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#eta-expansion

the trigger expected type function.

the link ambiguous in spec, expansion @ 6.26.5.

compare these 2 forms:

scala> foo(gate.unary_!()) <console>:11: error: type mismatch;  found   : gate  required: () => gate               foo(gate.unary_!())                               ^  scala> foo(gate.unary_!) res3: int = 1 

the first case application of function. doesn't type check.

what second case? instead of adding parens implicitly turn application, first eta-expand make function, type checks.

it's been suggested adding parens ("empty application" in spec) should come first, behave same first case.

here's spec wording how prefix op handled:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#prefix-operations

a prefix operation op;e consists of prefix operator op, must 1 of identifiers ‘+’, ‘-’, ‘!’ or ‘~’. expression op;e equivalent postfix method application e.unary_op.

but example shows it's member selection, not application.

here's counterexample without parens on method definition:

scala> class gate { def unary_! : gate = } defined class gate  scala> def foo(f: () => gate) = 1 foo: (f: () => gate)int  scala>   val gate = new gate gate: gate = gate@2db0f6b2  scala> foo(!gate) <console>:11: error: type mismatch;  found   : gate  required: () => gate               foo(!gate)                   ^ 

there simple evaluation first, first conversion in 6.26.2.

more examples on related ticket.

a comment there on linked ticket suggests not changing order of implicits, disabling eta-expansion case:

i'd inclined go further , deprecate eta-expansion given expected type of function0, , avoid triggering sam types of same shape outset.

which bad, because have made nice little puzzler.


Popular posts from this blog

c# - ODP.NET Oracle.ManagedDataAccess causes ORA-12537 network session end of file -

matlab - Compression and Decompression of ECG Signal using HUFFMAN ALGORITHM -

utf 8 - split utf-8 string into bytes in python -