What is the shortest notation to define an operator as a method alias in Scala? - scala

Given the generic register method below I would like to define the := operator as a symbolic alias.
def register[Prop <: Property[_]](prop: Prop): Prop
#inline
final def :=[Prop <: Property[_]] = register[Prop] _
Originally I wanted to write something like this:
val := = register _
But that gives me the function signature Nothing => Nothing. My next attempt was to parameterize it with the type Prop but that apparently works only if I make it a def, which can take type parameters and pass them onwards.
Ideally I would like to omit the #inline annotation but I am not sure what object code the Scala compiler makes out of it.
Most important my goal is it not to have the := method duplicate all parts of the register method's signature except for the name and then simply let the former delegate to the latter.

def :=[Prop <: Property[_]](prop: Prop) = register(prop)
should work.

I don't believe that there's any way to achieve what you're after (basically what alias gives you in Ruby) in Scala as it currently stands. The autoproxy plugin is an attempt to address this kind of problem, but it's not really ready for production use yet due to various issues with generating code in compiler plugins.

You can do this:
def := : Prop => Prop = register
So basically here you define a function of type (Prop => Prop) that just references another function.

Related

Scala: Cats, OptionT[Future, T] and ApplicativeError

Some time ago I've started using Cats and found OptionT very useful to work with Future[Option[T]] in most cases. But I faced with one drawback, to use AplicativeError I need to define type alias type FutureOption[T] = OptionT[Future, X] to matching F[_] required by AplicativeError and explicitly specify the type of my expression as FutureOption[T].
type FutureOption[T] = OptionT[Future, T] // definition to match F[_] kind
val x = OptionT.liftF(Future.failed(new Exception("error"))) : FutureOption[String] // need to specify type explicitly
x.recover {
case NonFatal(e) => "fixed"
}
If I remove type definition and explicit type specification of my expression the recover will not be available because OptionT[Future, T] don't match F[_], so it can't be converted implicitly to AplicativeErrorOps.
Unfortunately, the example below won't work because there is no recover method.
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.recover {
case NonFatal(e) => "fixed"
}
Is there any way to avoid such kind of boilerplate code? At least I want to avoid specifying expression types as FutureOption[T] explicitly.
In addition to the other answer, I would like to suggest that you make sure you have -Ypartial-unification enabled for your build.
This is a fix for partial unification of type constructors. You can find a more detailed explanation about the fix here.
With partial unification enabled the code you provided in your question compiles fine. Please note that if you're using an IDE (e.g. Intellij) you might get "false negatives" (the code is underlined as incorrect and code completion doesn't work), but the scalac/sbt/gradle will compile it just fine.
Yes, there are at least two ways to cope with the type ascription.
using type lambdas (this can be intimidating):
val a: { type λ[A] = OptionT[Future, A] }#λ
using a compiler plugin like kind-projector, example usage:
val a: Lambda[A => OptionT[Future, A]]
But if you wanted to call Future's recover, you can always do:
val x = OptionT.liftF(Future.failed(new Exception("error")))
x.value.recover ...

Why does passing some functions in scala require _

Getting to know scala better, I came across a behaviour I cannot explain.
The below code works fine:
def triple(x: Double) = 3 * x
Array(3.14,1.42,3.9).map(triple)
However, If I call the scala ceil function in math library then I will need to pass an _ for it to work
def valueAtOneQuarter(f: (Double)=> Double) = f(0.25)
valueAtOneQuarter(sqrt _)
What is special about the _ in this context from the function call in the earlier piece of code.
The underscore is actually expanded to a function.
So sqrt _ gets turned into the function a => sqrt(a).
You will notice that this expanded function matches the parameter type f of the valueatonequarter method.
In more general terms, the underscore is sometimes needed to flag to the compiler to turn the method (a method is declared using def) into a function (methods and functions are similar but not the same thing). The compiler will attempt to automatically convert the method to a function for you but in some cases it needs additional pointers (like an explicit type declaration or _). See here for a full explanation of eta expansion and partial functions: https://medium.com/#sinisalouc/on-method-invocations-or-what-exactly-is-eta-expansion-1019b37e010c
A method and a function are not the same in Scala.
You define a method this way:
def method(x:Double):Double = ...
But you define a function using this way:
val func = (x: Double):Double => {...}
when you pass a function as a parameter to a method it must be a function, but not a method.
So you must use underscore to make a function from a method.
Sometimes Scala uses “Eta Expansion” capability to automatically convert the method into a function. But in some cases you must do it manually
Answering since the existing answers don't really explain when _ is needed, just "sometimes" or "in some cases".
A very important concept to understand in Scala is expected type. In your first example the expected type for argument of map is Double => B with some unknown B; in the second it's Double => Double. When the expected type is a function type and a method name is passed, it'll be automatically converted to a function. So, as comments say, the second example works without _. It's only necessary where there is no expected type, say
val f = sqrt _
There can also be issues when the method is overloaded, but there just adding _ generally won't work either; instead, you'll specify the argument type to show which method is used, e.g. max(_: Int, _: Int) or max(_: Double, _: Double).
Thanks seems _ has different meaning in different context in scala
Yes, quite a few: What are all the uses of an underscore in Scala?

Generically obtain a Scala type's manifest

Is there a way to generically obtain a Scala type's manifest? For example, if I only have a Class reference to work with, is there a way I can obtain its corresponding manifest?
Scala's built-in implicitly[T] will get you an implicit value of type T (if one exists). So implicitly[Manifest[T]] will return a Manifest for type T.
If you have a Class reference, you can get the Manifest for the Class like this:
def manifestFor[T: Manifest](c: Class[T]) = implicitly[Manifest[T]]
class Foo
val x = new Foo
manifestFor(x.getClass)
//scala.reflect.Manifest[_ <: Foo] = _ <: Foo
The Manifest's type is _ <: Foo instead of just Foo, but they are equal.
implicitly[Manifest[Foo]] == manifestFor(x.getClass)
//Boolean = true
Well, I was trying to do something similar, but reflectively. I had no class symbol at compile time available. I had to use this code, not so obvious from the scaladocs, whith multiple non-obvious and misleading methods present near that point, so that it would likely be useful to others out there.
Manifest.classType(Class.forName(className))

About Scala's assignments and setter methods

Edit: The bug which prompted this question has now been fixed.
In the Scala Reference, I can read (p. 86):
The interpretation of an assignment to
a simple variable x = e depends on the
definition of x. If x denotes a
mutable variable, then the assignment
changes the current value of x to be
the result of evaluating the
expression e. The type of e is
expected to conform to the type of x.
If x is a parameterless function
defined in some template, and the same
template contains a setter function
x_= as member, then the assignment x =
e is interpreted as the invocation
x_=(e) of that setter function.
Analogously, an assignment f .x = e to
a parameterless function x is
interpreted as the invocation f.x_=(e).
So, for instance, something like this works fine:
class A {
private var _a = 0
def a = _a
def a_=(a: Int) = _a = a
}
I can then write
val a = new A
a.a = 10
But if I define the class like this, adding a type parameter to method a:
class A {
private var _a = 0
def a[T] = _a
def a_=(a: Int) = _a = a
}
then it doesn't work any more; I get an error: reassignment to val if I write a.a = 10. Funny enough, it still works with no type parameter and an implicit parameter list, for instance.
Arguably, in this example, the type parameter is not very useful, but in the design of DSLs, it would be great to have the setter method called even if the getter has type parameters (and by the way, adding type parameters on the setter is allowed and works fine).
So I have three questions:
Is there a workaround?
Should the current behavior be considered a bug?
Why does the compiler enforce a getter method to allow using the syntactic sugar for the setter?
UPDATE
Here's what I'm really trying to do. It's rather long, sorry, I meant to avoid it but I realized it was more confusing to omit it.
I'm designing GUIs with SWT in Scala, and having huge fun using Dave Orme's XScalaWT, which immensely reduces the amount of needed code. Here's an example from his blog post on how to create an SWT Composite that converts °C to °F degrees:
var fahrenheit: Text = null
var celsius: Text = null
composite(
_.setLayout(new GridLayout(2, true)),
label("Fahrenheit"),
label("Celsius"),
text(fahrenheit = _),
text(celsius = _),
button(
"Fahrenheit => Celsius",
{e : SelectionEvent => celcius.setText((5.0/9.0) * (fahrenheit - 32)) }
),
button(
"Celsius -> Fahrenheit",
{e : SelectionEvent => fahrenheit.setText((9.0/5.0) * celsius + 32) })
)
)
The argument to each of the widget-constructing methods is of type (WidgetType => Any)*, with a few useful implicit conversions, which for instance allow to directly specify a string for widgets that have a setText() method. All constructor functions are imported from a singleton object.
In the end, I'd like to be able to write something along these lines:
val fieldEditable = new WritableValue // observable value
composite(
textField(
editable <=> fieldEditable,
editable = false
),
checkbox(
caption = "Editable",
selection <=> fieldEditable
)
)
This would bind the editable property of the textfield to the selection of the checkbox through the WritableValue variable.
First: named arguments are not applicable here, so the line editable = false has to come from somewhere. So, along the widget-constructing methods in the singleton object, I could write, conceptually,
def editable_=[T <: HasEditable](value: Boolean) = (subject: T) => subject.setEditable(value)
... but this works only if the getter is also present. Great: I'd need the getter anyway in order to implement databinding with <=>. Something like this:
def editable[T <: HasEditable] = new BindingMaker((widget: T) => SWTObservables.observeEditable(widget))
If this worked, life would be good because I can then define <=> in BindingMaker and I can use this nice syntax. But alas, the type parameter on the getter breaks the setter. Hence my original question: why would this simple type parameter affect whether the compiler decides to go ahead with the syntactic sugar for calling the setter?
I hope this makes it a bit clearer now. Thanks for reading…
UPDATE Deleted the entire previous answer in light of new information.
There's a lot of very odd stuff going on here, so I'm going try try and explain my understanding of what you have so far:
def editable_=[T <: HasEditable](value: Boolean) = (subject: T) => subject.setEditable(value)
This is a setter method, and exists purely so that it can give the appearance of beinng a named parameter
in your DSL. It sets nothing and actually returns a Function.
textField(
editable <=> fieldEditable,
editable = false
)
This is calling the textField factory method, with what looks like a named param, but is actually the setter method defined previously.
Amazingly, the approach seems to work, despite my initial concern that the compiler would recognize this as a named parameter and produce a syntax error. I tested it with simple monomorphic (non-generic) methods, though it does require the getter method to be defined for the setter to be seen as such - a fact that you've already noted.
Some amount of "cleverness" is often required in writing a DSL (where it would otherwise be totally forbidden), so it's no surprise that your original intent was unclear. This is perhaps a completely new technique never before seen in Scala. The rules for setter and getter definitions were based on using them as getters and setters, so don't be surprised if things crack a little when you push at the boundaries like this.
It seems the real problem here is the way you're using type params. In this expression:
def editable_=[T <: HasEditable](value: Boolean) = (subject: T) => subject.setEditable(value)
The compiler has no way of inferring a particular T from the supplied argument, so it will take the most general type allowed (HasEditable in this case). You could change this behaviour by explicitly supplying a type param when using the method, but that would seem to defeat the entire point of what you're seeking to achieve.
Given that functions can't be generic (only methods can), I doubt that you even want type bounds at all. So one approach you could try is to just drop them:
def editable_=(value: Boolean) = (subject: HasEditable) => subject.setEditable(value)
def editable = new BindingMaker((widget: HasEditable) => SWTObservables.observeEditable(widget))

Spurious ambiguous reference error in Scala 2.7.7 compiler/interpreter?

Can anyone explain the compile error below? Interestingly, if I change the return type of the get() method to String, the code compiles just fine. Note that the thenReturn method has two overloads: a unary method and a varargs method that takes at least one argument. It seems to me that if the invocation is ambiguous here, then it would always be ambiguous.
More importantly, is there any way to resolve the ambiguity?
import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._
trait Thing {
def get(): java.lang.Object
}
new MockitoSugar {
val t = mock[Thing]
when(t.get()).thenReturn("a")
}
error: ambiguous reference to overloaded definition,
both method thenReturn in trait OngoingStubbing of type
java.lang.Object,java.lang.Object*)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
and method thenReturn in trait OngoingStubbing of type
(java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object]
match argument types (java.lang.String)
when(t.get()).thenReturn("a")
Well, it is ambiguous. I suppose Java semantics allow for it, and it might merit a ticket asking for Java semantics to be applied in Scala.
The source of the ambiguitity is this: a vararg parameter may receive any number of arguments, including 0. So, when you write thenReturn("a"), do you mean to call the thenReturn which receives a single argument, or do you mean to call the thenReturn that receives one object plus a vararg, passing 0 arguments to the vararg?
Now, what this kind of thing happens, Scala tries to find which method is "more specific". Anyone interested in the details should look up that in Scala's specification, but here is the explanation of what happens in this particular case:
object t {
def f(x: AnyRef) = 1 // A
def f(x: AnyRef, xs: AnyRef*) = 2 // B
}
if you call f("foo"), both A and B
are applicable. Which one is more
specific?
it is possible to call B with parameters of type (AnyRef), so A is
as specific as B.
it is possible to call A with parameters of type (AnyRef,
Seq[AnyRef]) thanks to tuple
conversion, Tuple2[AnyRef,
Seq[AnyRef]] conforms to AnyRef. So
B is as specific as A. Since both are
as specific as the other, the
reference to f is ambiguous.
As to the "tuple conversion" thing, it is one of the most obscure syntactic sugars of Scala. If you make a call f(a, b), where a and b have types A and B, and there is no f accepting (A, B) but there is an f which accepts (Tuple2(A, B)), then the parameters (a, b) will be converted into a tuple.
For example:
scala> def f(t: Tuple2[Int, Int]) = t._1 + t._2
f: (t: (Int, Int))Int
scala> f(1,2)
res0: Int = 3
Now, there is no tuple conversion going on when thenReturn("a") is called. That is not the problem. The problem is that, given that tuple conversion is possible, neither version of thenReturn is more specific, because any parameter passed to one could be passed to the other as well.
In the specific case of Mockito, it's possible to use the alternate API methods designed for use with void methods:
doReturn("a").when(t).get()
Clunky, but it'll have to do, as Martin et al don't seem likely to compromise Scala in order to support Java's varargs.
Well, I figured out how to resolve the ambiguity (seems kind of obvious in retrospect):
when(t.get()).thenReturn("a", Array[Object](): _*)
As Andreas noted, if the ambiguous method requires a null reference rather than an empty array, you can use something like
v.overloadedMethod(arg0, null.asInstanceOf[Array[Object]]: _*)
to resolve the ambiguity.
If you look at the standard library APIs you'll see this issue handled like this:
def meth(t1: Thing): OtherThing = { ... }
def meth(t1: Thing, t2: Thing, ts: Thing*): OtherThing = { ... }
By doing this, no call (with at least one Thing parameter) is ambiguous without extra fluff like Array[Thing](): _*.
I had a similar problem using Oval (oval.sf.net) trying to call it's validate()-method.
Oval defines 2 validate() methods:
public List<ConstraintViolation> validate(final Object validatedObject)
public List<ConstraintViolation> validate(final Object validatedObject, final String... profiles)
Trying this from Scala:
validator.validate(value)
produces the following compiler-error:
both method validate in class Validator of type (x$1: Any,x$2: <repeated...>[java.lang.String])java.util.List[net.sf.oval.ConstraintViolation]
and method validate in class Validator of type (x$1: Any)java.util.List[net.sf.oval.ConstraintViolation]
match argument types (T)
var violations = validator.validate(entity);
Oval needs the varargs-parameter to be null, not an empty-array, so I finally got it to work with this:
validator.validate(value, null.asInstanceOf[Array[String]]: _*)