scala 2.10 - Stringbuilder constructor not working - scala

I came across this issue when I was trying to form strings build with Integers. I used scala's Stringbuilder and see this weird behavior.
println(new StringBuilder(1).append(2).append(3))
>23
println(new StringBuilder(1.toString()).append(2).append(3))
>123
Am I doing something wrong or just implicit conversion not taking place in constructor argument and ignores it silently.

The constructor takes an Int for starting capacity, which is why you don't see it as output in your string:
def this(capacity: Int) = this(capacity, "")

You are using 2 different constructors:
StringBuilder(int capacity): Constructs a string builder with no characters in it and an initial capacity specified by the capacity argument.
StringBuilder(String str): Constructs a string builder initialized to the contents of the specified string.
So new StringBuilder(1) returns an empty new StringBuilder of initial capacity 1.

Related

Why can I concatenate String and Int in Scala?

I'm trying out some things in Scala, coming from Python. Since Scala is a lot more strict about keeping types consistent, I was surprised to find out that I can do the following concatenation, which would blow up in Python:
def adder(one:Any, two:String) = {one+two}
adder("word", "suffix")
res13: String = wordsuffix
But also:
val x:Int = 1
adder(x, "suffix")
res12: String = 1suffix
So it just transforms an Int into a String w/out telling me. What is this called and what is the logic behind it?
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
I know this is not very specific and if this is too broad, I'll gladly retract the question.
There is an implicit class in scala.Predef that operates on objects of any type
implicit final class any2stringadd[A](private val self: A) extends AnyVal {
def +(other: String): String = String.valueOf(self) + other
}
That implements Any + String (as you have defined it in adder). As rogue-one mentioned, there is also a method for concatenating String + Any defined in StringOps. If you tried to do Any + Any it would fail because it's expecting a String as the argument.
So it just transforms an Int into a String w/out telling me
Scala is converting your Int into a String, but it's not a type conversion because Int cannot be coerced into a String. You can observe that by trying something like this:
def foo(str: String) = ???
foo(5) // Type mismatch: expected: String, actual: Int
That will fail to compile because Scala can't magically coerce an Int into a String.
what is the logic behind it?
See implicit classes
And what is the benefit of this? I feel it can come back to bite me, e.g. when dealing with user input to a function.
It's a convenience method that's very specific to String and concatenation. This feature is implemented in Java, so I believe it was implemented in Scala to maintain source compatibility. My example above shows that (except in this specific case), user input to a function will respect the types defined on the function.
It's called implicit conversion (or implicit typecasting)
The purpose - convenience so you don't have to do everything manually. Most high-level languages will do that with the most used generics like strings, ints, bools...
You can check scala.Predef to see all the methods used when implicitly converting types, and you can take control of it using scala.language.implicitConversions. Read more at Scala Documentation.
This String concatenation not only works for Int but for any data-type. For instance
scala> case class Elephant(value: String)
defined class Elephant
scala> "Hello" + Elephant("elephant")
res2: String = HelloElephant(elephant)
This is because of the method + defined in StringOps (via Predef) class that accepts argument of type Any. So it is a method that is made available to a String object via implicit conversion that takes an argument of type Any. so "Hello" + Elephant("elephant") is actually "Hello".+(Elephant("elephant"))

Trying to skip implicit parameter list

I'd like to call a function returned by a function with an implicit parameter, simply and elegantly. This doesn't work:
def resolveA(implicit a: A): String => String = { prefix =>
s"$prefix a=$a"
}
case class A(n: Int)
implicit val a = A(1)
println(resolveA("-->")) // won't compile
I've figured out what's going on: Scala sees the ("-->") and thinks it's an attempt to explicitly fill in the implicit parameter list. I want to pass that as the prefix argument, but Scala sees it as the a argument.
I've tried some alternatives, like putting an empty parameter list () before the implicit one, but so far I've always been stopped by the fact that Scala thinks the argument to the returned function is an attempt to fill in the implicit parameter list of resolveA.
What's a nice way to do what I'm trying to do here, even if it's not as nice as the syntax I tried above?
Another option would be to use the apply method of the String => String function returned by resolveA. This way the compiler won't confuse the parameter lists, and is a little shorter than writing implicltly[A].
scala> resolveA[A].apply("-->")
res3: String = --> a=A(1)

scala hashmap get string value returns some()

val vJsonLoc = new HashMap[String, String]();
def getPrevJson(s:String) = vJsonLoc.get(s)
val previousFile = getPrevJson(s"/${site.toLowerCase}/$languagePath/$channel/v$v/$segment")
this returns
Some(/Users/abc/git/abc-c2c/)
on trying to append string previousFile + "/" + index + ".json"
the result is Some(/Users/abc/git/abc-c2c/)/0.json when the desired result is /Users/abc/git/abc-c2c/0.json
Guess this is some concept of Option that have not understood. New to scala.
As you pointed out, you're getting back an Option type, and not a direct reference to the String contained in your data structure. This is a very standard Scala practice, allowing you to better handle cases where an expected value might not be present in your data structure.
For example, in Java, this type of method typically returns the value if it exists and null if it doesn't. This means, however, subsequent code could be operating on the null value and thus you'd need further protection against exceptions.
In Scala, you're getting a reference to an object which may, or may not, have the value you expect. This is the Option type, and can be either Some (in which case the reference is accessible) or None (in which case you have several options for handling it).
Consider your code:
val vJsonLoc = new HashMap[String, String]();
def getPrevJson(s:String) = vJsonLoc.get(s)
val previousFile = getPrevJson(s"/${site.toLowerCase}/$languagePath/$channel/v$v/$segment")
If the HashMap returned String, your previousFile reference could point to either a null value or to a String value. You'd need to protect against a potential exception (regular practice in Java).
But in Scala, get is returning an Option type, which can be handled in a number of ways:
val previousFile = getPrevJson("your_string").getOrElse("")
//or
val previousFile = getPrevJson("your_string") match {
case Some(ref) => ref
case None => ""
}
The resulting reference previousFile will point to a String value: either the expected value ("get") or the empty string ("OrElse").
Scala Map on get returns Option. Use vJsonLoc(s) instead of vJsonLoc.get(s)

How to transfer String type to Object type in Scala

I am writing scala application, and want to utilize my java library. I have java API function that takes inputs as Object; however, the scala application that calling such function has input type as string. my code is as following:
val data = Array("foo", "bar")
val dataSource = new MyJavaAPIDataProvider(data)
Because I am using MyJavaAPIDataProvider(Object[] data), the scala code keeps telling me type mismatch. How do I change my scala code data array from a string array to Object array? Thanks
You have to cast the array to Array[Object]
val objs = data.asInstanceOf[Array[Object]]
val dataSource = new MyJavaAPIDataProvider(objs)
Edit:
to complete this answer with Seth Tisue's comment, you also can use:
val data = Array[AnyRef]("foo", "bar")
To avoid having to cast. AnyRef is equivalent to Java's Object.
Based on that, another possibility that comes to my mind is to create an array of AnyRef with the elements of your string array, like this:
Array[AnyRef](data: _*)

Scala def in an object - naming convention upper case camel case?

Given the conventions here: http://docs.scala-lang.org/style/naming-conventions.html
Blockquote
Constant names should be in upper camel case. That is, if the member is final, immutable and it belongs to a package object or an object, it may be considered a constant (similar to Java’s static final members)
Does that mean that a def should fall in that category too? Especially if functionally pure. For example a Parse method:
object Parser{def Parse(string: String): AnyRef = ??? }
No, it shouldn't.
That explanation is mostly a simplification of the concept of a stable value. A stable value is something that you can trust to always have the same value, and it is how Scala introduces dependent types (aka, in Scala, as path-dependent types).
There are a number of rules for what is a stable value, which is why a simpler explanation is resorted to in the style guide. One specific rule is that it has to be a val -- var and def are not acceptable. A var is not acceptable because the value can change at any time, and a def is not acceptable because it may return different values each time it is called (even if it receives no parameters).
Also related to this is the fact that you can override a def with a val, but not vice versa.
So only val qualifies as constants.
Also of interest, Scala optimizes final val declarations when you do not declare a type, like this:
object Constants {
final val Zero = 0
}
That will cause Scala to replace instances of Zero with 0. In fact, if you recompile Constant changing the value of Zero from 0 to something else, any code making reference to Constants.Zero that has been compiled before will still use 0.
If, on the other hand, you had declared it as final val Zero: Int = 0, that would not happen.
No. Method names should start with a lowercase letter.
No.
Refering to the naming conventions:
Textual (alphabetic) names for methods should be in the camelCase
style with the first letter lower-case:
def myFairMethod = ...
Upper case names are meant for constants.
Method, Value and variable names should be in lower camel case:
val myValue = ...
def myMethod = ...
var myVariable
So in your case it'll be:
object Parser {
def parse(string: String): AnyRef = ???
}