Overriding course functions in Scala

I got the impression that this

// short syntax def foo(bar: Bar)(baz: Baz): Quux 

was syntactic sugar for this

 // long syntax def foo(bar: Bar): (Baz) => Quux 

But I can't mix them when it comes to inheritance. The whole tree must be defined either by short syntax or by long syntax; never both.

For instance:

 case class Context case class Work trait ContextualWorker { def workWithContext(ctxt: Context)(work: Work): Traversable[Work] } class ShortConcreteWorker extends ContextualWorker { override def workWithContext(ctxt: Context)(work: Work) = Nil } class LongConcreteWorker extends ContextualWorker { // error on next line: method workWithContext overrides nothing <------------- override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = { val setupCode = 1 { work => Nil } } } 

If I changed the trait to use long syntax, then ShortConcreteWorker will not compile.

Is there a reason why they are not interchangeable / inheritable? How did you get around it?

Currently, the most flexible approach is to define a tree in long syntax, possibly delegating an implementation class to ShortConcreteWorker as follows:

 case class Context case class Work trait ContextualWorker { def workWithContext(ctxt: Context): (Work) => Traversable[Work] } class ShortConcreteWorker extends ContextualWorker { override def workWithContext(ctxt: Context) = workWithContextImpl(ctxt)_ private def workWithContextImpl(ctxt: Context)(work: Work) = Nil } class LongConcreteWorker extends ContextualWorker { override def workWithContext(ctxt: Context): (Work) => Traversable[Work] = { val setupCode = 1 { work => Nil } } } 
+6
source share
1 answer

The two methods described quite simply have different signatures. REPL confirms this:

 scala> def foo1(a: Int)(b: Int): Int = a + b foo1: (a: Int)(b: Int)Int scala> def foo2(a: Int): (Int => Int) = (b: Int) => a + b foo2: (a: Int)Int => Int 

The first function, which requires two arguments given in separate argument lists, returns Int . The second is a function that takes one argument and returns a function from Int to Int . Although the two things are conceptually similar, they are essentially different designs, and Scala views them as such.

This is not limited to functions with multiple argument lists. Here it works as follows:

 scala> def foo3(a: Int): Int = a + 1 foo3: (a: Int)Int scala> def foo4: (Int => Int) = (a: Int) => a + 1 foo4: Int => Int 

Please note that there are various consequences for use. With foo2 , since it takes only one argument, we can call it only one argument. However, foo1 requires two arguments, so we cannot just call it one. However, you can use the _ syntax to convert it to a called function.

 foo2(2) // Int => Int = <function1> foo1(2) // error: missing arguments for method foo1 foo1(2) _ // Int => Int = <function1> 

So, to answer your question directly: the reason they are not interchangeable is that they do not match. If they were the same, we could call them the same. If you could change the signature to an extension, how does Scala know which call syntax to allow? The way to get around is simply to make the signatures consistent.

+5
source

Source: https://habr.com/ru/post/914580/


All Articles