val label = Try("here_a").getOrElse("here_b")
In the case where here_a is not found, this is not falling back to here_b. Why is the .getOrElse not functioning?
Thanks #jwvh. These values are sting files paths and thus the exception is the following Exception in thread "main" java.io.FileNotFoundException:
As per Andrew James Ramirez's comment I tried this but issue persists.
Try(throw new Exception("FAIL here_a")).getOrElse("here_b")
I have also tried
Try(throw new Exception("FileNotFoundException here_a")).getOrElse("here_b")
Edit
It seems I may have oversimplified this question for SO. Some more context. The string is actually a file path. Perhaps this is making a difference?
Effectively, a json file may be found in one of two possible locations. I thus wish to try the first location and if a java.io.FileNotFoundException is returned, fall back on the second location. This is what I presently have:
val input_file = Try(throw new Exception("FAIL location_a/file_a.json")).getOrElse("location_b/file_a.json")
Edit V2
I am embarrassed to say that I found the simple error. I am running this scala code on spark and I forgot to repackage in between testing. sbt package was all that was required. :-/
I think you misunderstood Try. and .getOrElse
Definition of Try :
The Try type represents a computation that may either result in an exception, or return a successfully computed value. It's similar to, but semantically different from the scala.util.Either type.
scala> Try("here_a")
res1: scala.util.Try[String] = Success(here_a)
scala> Try("here_a").get
res2: String = here_a
scala> Try(throw new Exception("FAIL here_a")).getOrElse("here_b")
res3: String = here_b
scala>
It only fails if you throw Exception. null is still a value.
Try() returns either a Success(x) or a Failure(e), where x is the successful value returned and e is the exception that was thrown. getOrElse() unwraps the Success or supplies a default value.
If you're not getting the "OrElse" then your code isn't throwing a catchable exception.
It works as you expect it should.
$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
Type in expressions for evaluation. Or try :help.
scala> val label = Try(throw new RuntimeException("here_a")).getOrElse("here_b")
label: String = here_b
Please provide more context in your question if you feel this answer is insufficient.
Related
In Scala REPL I can use Seq[String]() as a default value for a parameter of type Seq[T].
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int
scala> d()
res0: Int = 12
Trying the same in IDEA, it complains “Seq[String] doesn't conform to expected type Seq[T]”. Why?
IntelliJ IDEA 2016.2.4
Scala Plugin 2016.2.1
Scala 2.11.7
Note 1: Sorry, I know that my example function does not make much sense. However, my real (and useful) function is unnecessarily complex to post it here.
Note 2: At first, instead of type T my type name in the example was Any which was not a good idea (because it shadowed scala.Any) and caused some confusion. Thus I fixed that.
When you say def d[Any], the Any here is a generic place holder. It does not point to class Any in scala. It basically shadows the Any class defined globally in scala. So, when you assign Seq[String] to Seq[Any], the compiler does not know any relation between String and Any. Note that Any could be replaced with any character / word as generic place holder. The result would be the same.
Now coming, to why this works in REPL, I am not exactly sure why REPL accepts if Seq[String] when given as a default value, but I was able to reproduce the error in repl when I do the same operation inside the method body.
The following code in REPL throws error:
def d[Any](foo: Seq[Any]) = {
val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found : Seq[String]
required: Seq[Any]
val a: Seq[Any] = Seq[String]()
^
I am not sure why REPL was not able to catch the error while given as a default argument.
One alternative theory is, in general when you use generics, the value of the type will be determined based on the caller. For example,
def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String
So, when you give default value, it assigns the value of String to Any. hence the compilation success.Intellij's Type Checker works based on the first theory and shows an error. But strangely as someone pointed out earlier, the compilation succeeds.
This is my code:
bufferedWriter.write(Play.current.configuration.getString("play.compile.c.command").get.replace("{objectname}", registerdJobDetails.executableNm.mkString.split('.')(0)).replace("{executablename}", getExecutableFolderName(jobId) + registerdJobDetails.executableNm))
bufferedWriter.newLine()
bufferedWriter.write(Play.current.configuration.getString("play.runable.c.command").get.replace("{objectname}", registerdJobDetails.executableNm.mkString.split('.')(0)))
only the first line is getting written but the other lines is not getting written.
I am getting the error as
java.util.NoSuchElementException: None.get
Most likely is that your problem is that Play.current.configuration.getString("play.runable.c.command") Has type Option[String] and are calling the get method on Option which pretty much should never be called. The world would be a better place if this method didn't even exist. I digress.
If this call to getString returns None, then the call to get throws an exception that there is no value to get.
It seems that Play.current.configuration.getString("play.runable.c.command")is returning a None which will throw an exception when calling get.
this should never be done! Use a combination of map and getOrElse to avoid unexpected behaviour. For instance:
val runableConfig = Play.current.configuration.getString("play.runable.c.command")
val s = runableConfig.map {
case runable =>
runable.replace("{objectname}", registerdJobDetails.executableNm.mkString.split('.')(0)
}.getOrElse("NO CONFIG FOUND")
bufferedWriter.write(s)
or you can even make the bufferedWriter.write(s) inside the map.
If you are not aware, the map method executes when the Option is defined (it's a Some(x)) and ignores when the Option is a None
Note: if it's returning a None try to debug that. Verify that you have no typos and that you are reading the right configuration file
If I create a Scala Worksheet in Eclipse as follows:
object negative {
2.toString //> res0: String = 2
(2).toString //> res1: String = 2
// compile error
(-2).toString
}
the final line causes a compile error:
';' expected but ')' found. illegal start of simple expression
However, the same three lines compile and run fine within a normal Scala source file.
Why does this not work in the worksheet?
This is using Eclipse 3.7.2, Scala IDE 3.0.0.v-2_10, Scala Worksheet 0.1.4.v-2_10
[Updated: this question originally used toBinaryString, but the problem occurs even with toString, so I have simplified it]
It is a bug. The code in the main object (the first one) of a worksheet is instrumented before being executed. In the 2 mentioned case, the result of the instrumentation is not valid Scala code.
But it is only a problem if the code is at the top level in the main object. If the code is moved to a function or a different object in the same file, it works fine.
Eclipse worksheets are quite beta; for example last I checked, it couldn't handle a #tailrec decoration on a function.
So this is most probably a bug or limitation in Eclipse. After all, the feature seems quite new, and there are many other bugs.
(-2).toBinaryString
gives same error for me.
Note that java.lang.Integer.toBinaryString(-2)works just fine.
Here are two REPL sessions (inspired by this question, although my question is different):
Welcome to Scala version 2.9.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def ignore(it: String) = 42
ignore: (it: String)Int
scala> ignore(null.asInstanceOf[Nothing])
res0: Int = 42
And:
Welcome to Scala version 2.10.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def ignore(it: String) = 42
ignore: (it: String)Int
scala> ignore(null.asInstanceOf[Nothing])
java.lang.NullPointerException
at .<init>(<console>:9)
at .<clinit>(<console>)
at .<init>(<console>:7)
at .<clinit>(<console>)
at $print(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
...
The only difference is that the first is Scala 2.9.2 and the second is 2.10.0.
Can someone point to the changes in 2.10 that lead to this new behavior?
I know that casting to Nothing is a silly thing to do, and that the answer might be "this is all undefined behavior so just stop doing that", but it looks like the kind of thing that could potentially have implications for upgraders, and I don't remember running into any discussions of changes that would explain this.
Since Scala treats null differently from the None case on an option, even a null value of Nothing is problematic--there should be exactly zero instances of Nothing, not one instance that may or may not break depending on how you use it.
Thus, I cannot see how the old behavior is anything but a bug. It should be mentined in the release notes that it was fixed, but relying on .asInstanceOf[Nothing] to do anything save throw an exception is sufficiently contrary to type-sanity that I don't think anything more is needed. (In fact, I don't even think the release note is needed.)
This looks like an issue just with the console, not with the language. If you run this small application which invokes the exact same method, scala 2.10 doesn't have a problem with it.
object Test extends App {
override def main(args: Array[String]) {
println(takesString(null.asInstanceOf[Nothing]))
}
def takesString(a: String) = 42
}
To simplify your example from above, you could just type
null.asInstanceOf[Nothing]
and the console would give you the same error. I presume it has something to do with printing out the type.
Update: Looks like I accidentally ran against 2.9.2. Still fails as a script in 2.10 RC5 as the author points out in comment.
I know you are not expecting the answer "this is all undefined behavior, so (...)", but when you add "thing that could potentially have implications for upgraders", I must remember (even if it's obvious) that people can't rely or expect anything of the result of a thing that has undefined behavior, by its own definition.
In the specific case you mentioned, I don't think it is undefined behavior: it should throw an exception. Nothing is a subclass of Null, not the other way around - my first expectation, without testing, was that the line null.asInstanceOf[Nothing] would throw a ClassCastException, as null is not a Nothing. However, you can see that null is a special instance (as it is in Java). Try running:
scala> "aaa".asInstanceOf[Nothing]
java.lang.ClassCastException: java.lang.String cannot be cast to scala.runtime.N
othing$
at .<init>(<console>:8)
at .<clinit>(<console>)
My guess is that it happens because internally, obj.asInstanceOf[T] calls obj.getClass() in order to check the cast at runtime. As calling any method on null throws a NullPointerException, that exception is thrown before ClassCastException.
Back to your specific question, it seems that Scala 2.9.2 handles in a (very) special way that specific case. Running a few more tests:
scala> ignore(3.asInstanceOf[String])
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Stri
ng
at .<init>(<console>:9)
at .<clinit>(<console>)
scala> ignore({ println("test"); "aaa" })
test
res6: Int = 42
You can see that the argument is always being evaluated, save for your case. Scala 2.10 definitely has the most consistent behavior. However, this issue should not affect any developer upgrading to Scala 2.10; I can't see any case where obj.asInstanceOf[Nothing] is correct code.
It seems that using type aliases confuses the Scala type inferencer or the compiler. Indeed trying to compile
import scalaz.OptionT.optionT
type Foo[A] = Option[Option[A]]
val x: Foo[Int] = Some(Some(3))
optionT(x)
results in the strange error
java.lang.IllegalArgumentException: transpose requires all collections have the same size
Due to my limited experience with Scala, I am not sure whether I should file a bug for this, ot if this is the expected behaviour.
Is this really a bug or the expected behaviour?
Having just tested that myself that IllegalArgumentException is the compiler bailing out, which would be a bug.
I also tested this and it really seems like a bug, you should report that to the scala team. You can however fix this, by giving the compiler a hint:
val x: Foo[Int] = Some(Some(4))
val y = optionT[Option](x)
y: scalaz.OptionT[Option,Int] = OptionT(Some(Some(3)))