Scala - Function's implicit return type - scala

I am new to scala, and got a little doubt about function definition & default return type.
Here is a function definition:
def wol(s: String) = s.length.toString.length
The prompt says it's:
wol: (s: String)Int
But, the code didn't specify return type explicitly, shouldn't it default to Unit, which means void in Java.
So, what is the rules for default return type of a Scala function?

The return type in a function is actually the return type of the last expression that occurs in the function. In this case it's an Int, because #length returns an Int.
This is the work done by the compiler when it tries to infer the type. If you don't specify a type, it automatically gets inferred, but it's not necessarily Unit. You could force it to be that be stating it:
def wol(s: String): Unit = s.length.toString.length
EDIT [syntactic sugar sample]
I just remembered something that might be connected to your previous beliefs. When you define a method without specifying its return type and without putting the = sign, the compiler will force the return type to be Unit.
def wol(s: String) {
s.length.toString.length
}
val x = wol("") // x has type Unit!
IntelliJ actually warns you and gives the hint Useless expression. Behind the scene, the #wol function here is converted into something like:
// This is actually the same as the first function
def wol(s: String): Unit = { s.length.toString.length }
Anyway, as a best practice try to avoid using this syntax and always opt for putting that = sign. Furthermore if you define public methods try to always specify the return type.
Hope that helps :)

Related

why = is optional in def in Scala

Both of the following function definations compile even though one uses = and other doesn't. Why? Is there an advantage of this behaviour?
def 1
def doWork(index:Int) = {
sleep((math.random*1000).toLong);
index;
}
def 2
def doWork(index:Int) {
sleep((math.random*1000).toLong);
index;
}
def 1 is what you want to use.
def 2 is called procedure syntax (discouraged) and actually means this:
def doWork(index:Int): Unit = {
sleep((math.random*1000).toLong)
index
}
So it's probably now what you want (since it doesn't return anything).
Not including an = sign declares a procedure. Procedures return Unit, i.e., don't return a value at all. As explained in the Scala language specification (from the link above):
A procedure definition is a function definition where the result type and the equals sign are omitted; its defining expression must be a block. E.g., def f(ps) {stats} is equivalent to def f(ps): Unit = {stats}.
In your second case, the return value simply gets suppressed to turn a function that returns Int into a procedure that returns Unit. While doing so, the compiler should issue a warning similar to
warning: a pure expression does nothing in a statement position
This should let you know that something fishy is going on, i.e., there is a statement that would normally result in the block returning a value (index; in your case), but it goes unused.
When you don't use "=" with def, it means your defined function will return unit.
And in the second function, you don't use "=", that means the defined function will return unit, but your function is returning index.
That's why it throws warning as it expects unit and discard the value.
Thanks

Scala: getting rid of type argument in a function

Suppose I have a function defined in the following way:
def fun[T](somevar: SomeType[T]) = {
// some action
}
Is there a way to git rid of type parameter [T] and just use it as
def fun(somevar: SomeType[T]) = {
// some action
}
I mean, the type information should already be available inside someVar, no? Why not use them somehow?
The purpose of your question is unclear.
The users of your function (the client code) don't need to worry about the type parameter. They can just call fun(myvar).
If the type T is immaterial to the body of fun() then it can be dropped: SomeType[_]
But if T is meaningful to the workings of the function then the compiler has to be told that it is a type parameter. Just seeing this, SomeType[T], the compiler can't infer that T is now a type parameter. It will, instead, look for a definition of T outside of fun() and, not finding it, will throw an error.
This would be problematic because what you're removing was never actually redundant. When the function is defined as def fun[T](...), T is defined as a new type variable. Otherwise, it refers to a type or type variable defined somewhere else. You seem to think that
def fun(somevar: SomeType[T]) { ... }
should mean that T is a new type variable. Is that always the case, though? Not in this code:
trait T { ... }
def fun(somevar: SomeType[T]) { ... }
So where do we go from there? Define new type variables whenever a type name is referred to that hasn't been defined before? That would turn the following compile-time errors truly weird. (Or worse, sometimes allow them to compile?)
def fun(somevar: SomeType[Integr]) { ... }
class C[Thing] {
def g(x: List[Think]) = ...
}
For the compile-time type-checking philosophy of Scala, that way lies madness.
Unless you want T to be a specific type, no, there is not. The method signature wouldn't be valid without it. What somevar knows is irrelevant.
You can't do this. Compiler needs to know what is type T. If you don't care about SomeType type parameter, you can use this form:
def fun(somevar: SomeType[_]) = {
// some action
}

avoid type conversion in Scala

I have this weird requirement where data comes in as name ->value pair from a service and all the name-> value type is string only (which really they are not but that's how data is stored)
This is a simplified illustration.
case class EntityObject(type:String,value:String)
EntityObject("boolean","true")
now when getting that EntityObject if type is "boolean" then I have to make sure value is not anything else but boolean so first get type out and check value and cast value to that type. e.g in this case check value is boolean so have to cast string value to boolean to validate. If it was anything else besides boolean then it should fail.
e.g. if data came in as below, casting will fail and it should report back to the caller about this error.
EntityObject("boolean","1")
Due to this weird requirement it forces type conversion in validation code which doesn't look elegant and against type safe programming. Any elegant way to handle this in scala (may be in a more type safe manner)?
Here is where I'm going to channel an idea taken from a tweet by Miles Sabin in regards to hereogenous mappings (see this gist on github.) If you know the type of object mapping names a head of time you can use a nifty little trick which involves dependent types. Hold on, 'cause it's a wild ride:
trait AssocConv[K] { type V ; def convert: String => V }
def makeConv[V0](name: String, con: String => V0) = new AssocConv[name.type]{
V = V0
val convert = con
}
implicit val boolConv = makeConv("boolean", yourMappingFunc)
def convEntity(name: String, value: String)(implicit conv: AssocConv[name.type]): Try[conv.V] = Try{ conv.convert(value) }
I haven't tested this but it "should" work. I've also enclosed it in a Scala Try so that it catches exceptions thrown by your conversion function (in case you're doing things like _.toInt as the converter.)
You're really talking about conversion, not casting. Casting would be if the value really were an instance of Boolean at runtime, whereas what you have is a String representation of a Boolean.
If you're already working with a case class, I think a pattern matching expression would work pretty well here.
For example,
def convert(entity : EntityObject) : Any = entity match {
case EntityObject("boolean", "true") => true
case EntityObject("boolean", "false") => false
case EntityObject("string", s) => s
// TODO: add Regex-based matchers for numeric types
}
Anything that doesn't match one of the specified patterns would cause a MatchError, or you could put a catchall expression at the end to throw your own exception.
In this particular example, since the function returns Any, the calling coffee would need to do an actual type cast to get the specific type, but at least by that point all validation/conversion would have already been performed. Alternatively, you could just put the code that uses the values directly into the above function and avoid casting. I don't know what your specific needs are, so I can't offer anything more detailed.

When is a return type required for methods in Scala?

The Scala compiler can often infer return types for methods, but there are some circumstances where it's required to specify the return type. Recursive methods, for example, require a return type to be specified.
I notice that sometimes I get the error message "overloaded method (methodname) requires return type", but it's not a general rule that return types must always be specified for overloaded methods (I have examples where I don't get this error).
When exactly is it required to specify a return type, for methods in general and specifically for overloaded methods?
The Chapter 2. Type Less, Do More of the Programming Scala book mentions:
When Explicit Type Annotations Are Required.
In practical terms, you have to provide explicit type annotations for the following situations:
Method return values in the following cases:
When you explicitly call return in a method (even at the end).
When a method is recursive.
When a method is overloaded and one of the methods calls another. The calling method needs a return type annotation.
When the inferred return type would be more general than you intended, e.g., Any.
Example:
// code-examples/TypeLessDoMore/method-nested-return-script.scala
// ERROR: Won't compile until you put a String return type on upCase.
def upCase(s: String) = {
if (s.length == 0)
return s // ERROR - forces return type of upCase to be declared.
else
s.toUpperCase()
}
Overloaded methods can sometimes require an explicit return type. When one such method calls another, we have to add a return type to the one doing the calling, as in this example.
// code-examples/TypeLessDoMore/method-overloaded-return-script.scala
// Version 1 of "StringUtil" (with a compilation error).
// ERROR: Won't compile: needs a String return type on the second "joiner".
object StringUtil {
def joiner(strings: List[String], separator: String): String =
strings.mkString(separator)
def joiner(strings: List[String]) = joiner(strings, " ") // ERROR
}
import StringUtil._ // Import the joiner methods.
println( joiner(List("Programming", "Scala")) )
The two joiner methods concatenate a List of strings together.
The first method also takes an argument for the separator string.
The second method calls the first with a “default” separator of a single space.
If you run this script, you get the following error.
... 9: error: overloaded method joiner needs result type
def joiner(strings: List[String]) = joiner(strings, "")
Since the second joiner method calls the first, it requires an explicit String return type. It should look like this:
def joiner(strings: List[String]): String = joiner(strings, " ")
Basically, specifying the return type can be a good practice even though Scala can infer it.
Randall Schulz comments:
As a matter of (my personal) style, I give explicit return types for all but the most simple methods (basically, one-liners with no conditional logic).
Keep in mind that if you let the compiler infer a method's result type, it may well be more specific than you want. (E.g., HashMap instead of Map.)
And since you may want to expose the minimal interface in your return type (see for instance this SO question), this kind of inference might get in the way.
And about the last scenario ("When the inferred return type would be more general than you intended"), Ken Bloom adds:
specify the return type when you want the compiler to verify that code in the function returns the type you expected
(The faulty code which triggers a "more general than expected return type was:
// code-examples/TypeLessDoMore/method-broad-inference-return-script.scala
// ERROR: Won't compile. Method actually returns List[Any], which is too "broad".
def makeList(strings: String*) = {
if (strings.length == 0)
List(0) // #1
else
strings.toList
}
val list: List[String] = makeList() // ERROR
, which I incorrectly interpreted and List[Any] because returning an empty List, but Ken called it out:
List(0) doesn't create a list with 0 elements.
It creates a List[Int] containing one element (the value 0).
Thus a List[Int] on one conditional branch and a List[String] on the other conditional branch generalize to List[Any].
In this case, the typer isn't being overly-general -- it's a bug in the code.
)

Simple Type Inference in Scala

I have been looking at type inference in Scala and there are a couple of things I'd like to understand a bit better around why expression/method-return types have to be explicitly declared in a few cases.
Explicit return declaration
Example (works if return keyword is ommitted):
def upCase(s: String) = {
if (s.length == 0)
return s // COMPILE ERROR - forces return type of upCase to be declared.
else
s.toUpperCase()
}
Why can't I use the explicitly typed parameter as a return value without declaring the return type? And that's not only for direct parameter references, just for any 'type-inferable' expression.
Method overloading
Example (fails to compile when the second joiner method is added):
def joiner(ss: List[String], sep: String) = ss.mkString(sep)
def joiner(ss: List[String]) = joiner(strings, " ") // COMPILE ERROR WHEN ADDED
Well most obvious answer is: because it stated in specification see part 6.20 of scala reference. But why it was designed this way is indeed very intresting question. I suspect it connected to the fact that compiler can't predict that expression will be the last one, since return changes execution flow.
EDIT:
Consider if return doesn't require explicit return type following code:
def bar() = {
if(guard())
return "SS"
else if(gurard1())
return true
2
}
that return type should bar have in this situation? Well there is option with most common supertype, but I think it will get us to returning Any in many cases. Well this is just my thoughts which may be totally incorrect =)
The type of a function or method is inferred from the type of its last statement. Usually, that's an expression.
Now, "return" breaks the control flow. It is an "immediate interrupt", so to speak. Because of that, the normal rules used to infer the type of an expression can't be used anymore. It still could be done, of course, but I'm guessing the cost in compiler complexity was deemed to high for the return.
Here's an example of how the flow is broken:
def toNumber(s: String) = {
if (s == null)
return ""
if (s matches """\d+""")
s.toInt
else
0
}
Normally, the type of the second if statement would be used to infer the type of the whole function. But the return on the first if introduces a second return point from the function, so this rule won't work.
Type inference infers the return type of a method when it can, which is more or less in any case that the method isn't recursive.
Your example would work if you changed it to:
def upCase(s: String) = {
if (s.length == 0)
s // note: no return
else
s.toUpperCase()
}
I don't know offhand why the return changes this.
Disclaimer - this answer was directed to the question as it was originally posted
Scala's type inference already does infer the return type of a method / expression:
scala> def foo(s : String) = s + " Hello"
foo: (String)java.lang.String
scala> var t = foo("World")
t: java.lang.String = World Hello
and:
scala> def bar( s : String) = s.toInt
bar: (String)Int
scala> var i = bar("3")
i: Int = 3
and:
scala> var j = if (System.getProperty("user.name") == "oxbow") 4 else "5".toInt
j: Int = 5
EDIT - I didn't realize that the inclusion of the return keyword meant that the return type of an expression had to be explicitly declared: I've pretty much stopped using return myself - but it's an interesting question. For the joiner example, the return type must be declared because of overloading. Again, I don't know the details as to why and would be interested to find out. I suspect a better-phrased question subject would elicit an answer from the likes of James Iry, Dan Spiewak or Daniel Sobral.
I suspect the method overloading (lack of) inference is related to the similar problem with recursive calls, because if the overloaded methods doesn't call each other, it works perfectly:
def joiner1(ss: List[String], sep: String) = ss.mkString(sep)
def joiner(ss: List[String], sep: String) = ss.mkString(sep)
def joiner(ss: List[String]) = joiner1(ss, " ")
There's two overloaded joiner methods, but the types are inferred correctly the code compiles.