What is the Scala equivalent of this Java code, where someMethodThatMightThrowException is defined elsewhere?
class MyClass {
String a;
String b;
MyClass() {
try {
this.a = someMethodThatMightThrowException();
this.b = someMethodThatMightThrowException();
} finally {
System.out.println("Done");
}
}
}
class MyClass {
private val (a, b) =
try {
(someMethodThatMightThrowException(),
someMethodThatMightThrowException())
} finally {
println("Done")
}
}
try is an expression in Scala, so you can use it's value. With tuples and pattern matching you can use statement to get more than one value.
Alternatively you could use almost the same code as in Java:
class MyClass {
private var a: String = _
private var b: String = _
try {
a = someMethodThatMightThrowException()
b = someMethodThatMightThrowException()
} finally {
println("Done")
}
}
with companion object
case class MyClass(a: String, b: String)
object MyClass {
def apply() = try {
new MyClass(
a = someMethodThatMightThrowException(),
b = someMethodThatMightThrowException()
)
} finally {
println("Done")
}
}
with constructor overload a little bit harder, because we can't wrap this(...):
def tryIt[T](something: => T) = try{
something
} finally {
println("Done")
}
case class MyClass(a: String, b: String) {
def this() = this(
tryIt(someMethodThatMightThrowException),
tryIt(someMethodThatMightThrowException)
)
}
What is a or b assigned if an exception occurs? Wrap a and b in a Try to handle the exceptional cases. You can also pattern match on these to extract values.
scala> class MyClass(val a: Try[String], val b: Try[String])
defined class MyClass
scala> new MyClass(Try("foo"(0).toString), Try("foo"(3).toString))
res0: MyClass = MyClass#6bcc9c57
scala> res0.a
res1: scala.util.Try[String] = Success(f)
scala> res0.b
res2: scala.util.Try[String] = Failure(java.lang.StringIndexOutOfBoundsException: String index out of range: 3)
scala> res0.a.get
res3: String = f
scala> res0.b.get
java.lang.StringIndexOutOfBoundsException: String index out of range: 3
at java.lang.String.charAt(String.java:658)
...
Edits for comment. Uses default argumens for a and b.
null is bad but that's what you asked for. See Option
class MyClass(val a: Try[String] = null, val b: Try[String] = null)
scala> new MyClass(Success("a"))
res50: MyClass = MyClass#625aaaca
scala> res50.a
res51: scala.util.Try[String] = Success(a)
scala> res50.b
res52: scala.util.Try[String] = null
scala> new MyClass(b = Success("b"))
res53: MyClass = MyClass#68157e85
scala> res53.a
res54: scala.util.Try[String] = null
scala> res53.b
res55: scala.util.Try[String] = Success(b)
How about something closer to:
scala> def foo = ???
foo: Nothing
scala> :pa
// Entering paste mode (ctrl-D to finish)
case class Foo(a: String = Foo.afoo, b: String = Foo.bfoo)
object Foo {
import util._
def afoo = Try (foo) recover { case _ => "a" } get
def bfoo = Try (foo) recover { case _ => "b" } get
}
// Exiting paste mode, now interpreting.
warning: there were 2 feature warning(s); re-run with -feature for details
defined class Foo
defined object Foo
scala> Foo()
res0: Foo = Foo(a,b)
Related
I am trying to create a generic class that only accepts java.math.BigDecimal or Long. Here is the code:
class myClass[T]()
{
def display( x : T) = {
println(x.doubleValue())
}
}
val input = new java.math.BigDecimal(100)
// val input = 100L
val x = new myClass[java.math.BigDecimal]()
x.display(input)
Clearly I will have this error: ScalaFiddle.scala:22: error: value doubleValue is not a member of type parameter T.
I tried playing with implicit conversion, view bound, and context bound for hours. No result so far. Is there any way I can force Scala to believe me that T has method .doubleValue()? (java.big.Decimal and Long both has .doubleValue() method, but they don't share same super-class)
Try structural type bound
class myClass[T <: {def doubleValue(): Double}]
or type class
trait HasDoubleValue[T] {
def doubleValue(t: T): Double
}
object HasDoubleValue {
implicit val long: HasDoubleValue[Long] = t => t.doubleValue
implicit val bigDecimal: HasDoubleValue[BigDecimal] = t => t.doubleValue
}
implicit class DoubleValueOps[T: HasDoubleValue](x: T) {
def doubleValue(): Double = implicitly[HasDoubleValue[T]].doubleValue(x)
}
class myClass[T: HasDoubleValue]
In Dotty (Scala 3) we might use union types, for example,
class myClass[T <: (Long | java.math.BigDecimal)]() {
def display(x: T) =
println(
x match {
case t: Long => t.doubleValue
case t: java.math.BigDecimal => t.doubleValue
}
)
}
new myClass().display(new java.math.BigDecimal(100)) // OK
new myClass().display(100L) // OK
new myClass().display("100") // Error
scala> class C private (n: Number) {
| def this(i: Long) = this(i: Number)
| def this(b: BigDecimal) = this(b: Number)
| def d = n.doubleValue
| }
defined class C
scala> new C(42L).d
res0: Double = 42.0
scala> new C(BigDecimal("123456789")).d
res1: Double = 1.23456789E8
or with a type parameter
scala> class C[A <: Number] private (n: A) { def d = n.doubleValue ; def a = n } ; object C {
| def apply(i: Long) = new C(i: Number) ; def apply(b: BigDecimal) = new C(b) }
defined class C
defined object C
So I am attempting to grab the types of each field in a Scala object class:
package myapp.model
object MyObject {
val theInt: Option[Int]
}
Using the ReflectionHelper so graciously provided by Brian in this post. I use getFieldType but it returns Option[Object] instead of what it is, which is Option[Int]. The example code in that answer works for a case class, for example:
package myapp.model
case class Person(
name: String,
age: Option[Int]
)
scala> ReflectionHelper.getFieldType("myapp.model.Person", "age") // int
res12: Option[reflect.runtime.universe.Type] = Some(Option[Int])
However, if I run getFieldType on a Scala object field, we get this:
scala> ReflectionHelper.getFieldType("myapp.model.MyObject$", "theInt")
res10: Option[reflect.runtime.universe.Type] = Some(Option[Object])
What is different about Scala objects that causes this behavior and how can I get getFieldType to return Option[Int] instead of Option[Object] like it does for the case class?
Here is the ReflectionHelper from the other question for convenience:
import scala.reflect.runtime.{ universe => u }
import scala.reflect.runtime.universe._
object ReflectionHelper {
val classLoader = Thread.currentThread().getContextClassLoader
val mirror = u.runtimeMirror(classLoader)
def getFieldType(className: String, fieldName: String): Option[Type] = {
val classSymbol = mirror.staticClass(className)
for {
fieldSymbol <- classSymbol.selfType.members.collectFirst({
case s: Symbol if s.isPublic && s.name.decodedName.toString() == fieldName => s
})
} yield {
fieldSymbol.info.resultType
}
}
def maybeUnwrapFieldType[A](fieldType: Type)(implicit tag: TypeTag[A]): Option[Type] = {
if (fieldType.typeConstructor == tag.tpe.typeConstructor) {
fieldType.typeArgs.headOption
} else {
Option(fieldType)
}
}
def getFieldClass(className: String, fieldName: String): java.lang.Class[_] = {
// case normal field return its class
// case Option field return generic type of Option
val result = for {
fieldType <- getFieldType(className, fieldName)
unwrappedFieldType <- maybeUnwrapFieldType[Option[_]](fieldType)
} yield {
mirror.runtimeClass(unwrappedFieldType)
}
// Consider changing return type to: Option[Class[_]]
result.getOrElse(null)
}
}
Try
import scala.reflect.runtime.universe._
import scala.reflect.runtime
val runtimeMirror = runtime.currentMirror
runtimeMirror.staticClass("myapp.model.Person").typeSignature
.member(TermName("age")).typeSignature // => Option[Int]
runtimeMirror.staticModule("myapp.model.MyObject").typeSignature
.member(TermName("theInt")).typeSignature // => Option[Int]
This is what I want to do -
class A(some args) {
var v: SomeType = null
def method1(args) = {
v = something1
...
method3
}
def method2(args) = {
v = something2
...
method3
}
def method3 = {
// uses v
}
}
In this specific case method1 and 2 are mutually exclusive and either one of them is called exactly once in the lifetime of an instance of A. Also, v is assigned once. I would prefer making it a val. But since I need method2 or method3's context to initialize v, I can't do that in the constructor.
How can achieve this "val" behavior? I can think of modifying method1 and method2 to apply methods, but I don't like the idea. Moreover, method1 and 2 have the same argument signature (hence apply would need some more info to distinguish the 2 types of calls).
An important question is: what exactly do you call "val behavior"? To me "val behavior" is that is assigned once immediately when it is declared, which can be enforced statically. You seem to want to enforce that v is not assigned twice. You possibly also want to enforce it is never read before it is assigned. You could create a very small helper box for that:
final class OnceBox[A] {
private[this] var value: Option[A] = None
def update(v: A): Unit = {
if (value.isDefined)
throw new IllegalStateException("Value assigned twice")
value = Some(v)
}
def apply(): A = {
value.getOrElse {
throw new IllegalStateException("Value not yet assigned")
}
}
}
and now your snippet:
class A(some args) {
val v = new OnceBox[SomeType]
def method1(args) = {
v() = something1
...
method3
}
def method2(args) = {
v() = something2
...
method3
}
def method3 = {
// uses v
v()
}
}
Oh and, just kidding, but Ozma has single-assignment vals built-in :-p
Similar idea to the other answer, but instead of subtypes, a field.
scala> :pa
// Entering paste mode (ctrl-D to finish)
class A {
private[this] var context: Int = _
lazy val v: String =
context match {
case 1 => "one"
case 2 => "two"
case _ => ???
}
def m1() = { context = 1 ; v }
def m2() = { context = 2 ; v }
}
// Exiting paste mode, now interpreting.
defined class A
scala> val a = new A
a: A = A#62ce72ff
scala> a.m2
res0: String = two
scala> a.m1
res1: String = two
Something like this maybe:
class A private (mtdType: Int, ...) {
val v = mdtType match {
case 1 => method1(...)
case 2 => method2(...)
}
}
object A {
def withMethod1(...) = new A(1, ...)
def withMethod2(...) = new A(2, ...)
}
Or, another possibilty:
sealed trait A {
val v
def method3 = println(v)
}
class Method1(...) extends A {
val v = method1(...)
}
class Method2(...) extends A {
val v = method2(...)
}
I have two functions that take one argument, a String. I was to apply either one or the other based on some condition. This is what I attempted:
def foo(s: String) = { ... }
def bar(s: String) = { ... }
(if (condition) foo else bar)("baz")
But I get an error like this:
<console>:10: error: missing arguments for method foo;
follow this method with `_' if you want to treat it as a partially applied function
(if (true) foo else bar)("baz")
^
I tried writing foo_ but of course I got error: not found: value foo_. What's the correct way to express this idiom in Scala?
You need a space between the method name and the underscore. This works fine:
def foo(s: String) = s + "-FOO"
def bar(s: String) = s + "-BAR"
val condition = true
(if (condition) foo _ else bar _)("baz")
// res0: String = baz-FOO
The underscore after the method name tells Scala that you want to want to pass the method as a higher-level function. From what I understand, this is a way to disambiguate whether you want to pass a method as a function or pass the result of a method with no arguments. For example:
def f = 1
val x = Some(f)
What should the type of x be? Will it be Some[Int] or Some[()=>Int]? It should default to the former, but if you want the latter you can use the underscore notation:
val y = Some(f _)
You have to deal with all this underscore nonsense because Scala methods aren't functions. If you declare foo and bar as functions rather than methods then your original code works as-is:
val foo = (s: String) => s + "-FOO"
val bar = (s: String) => s + "-BAR"
val condition = false
(if (condition) foo else bar)("baz")
// res1: String = baz-BAR
There are several things I want to mention:
def foo(s: String) = { ... }
def bar(s: String) = { ... }
foo and bar are not functions, there are just normal method. Also, def f = 3 is also a method not function.
(if (condition) foo else bar)("baz") obviously, this statement need foo and bar to be a function because of ("baz") argument.
as #wendao mentioned to use _ to change method to function. I think the simplest solution is to define foo and bar as a function.
def foo: String => String = { value =>
"Hi " + value
}
def bar: String => String = { value =>
"farewell " + value
}
val x: Some[String => String] = Some(foo)
(if (true) foo else bar)("John") // Hi John
It doesn't know that what you actually want to return a function, you'd have to tell it that what you want is a by-name parameter:
def foo(x : String) = x //> foo: (x: String)String
def bar(x : String) = x //> bar: (x: String)String
val condition = true //> condition : Boolean = true
val result : String => String = if (condition) foo else bar
//> result : String => String = <function1>
result("something") //> res0: String = something
This is a little more absurd:
scala> var b = true
b: Boolean = true
scala> def f(s: String) = s"f+$s"
f: (s: String)String
scala> def g(s: String) = s"g+$s"
g: (s: String)String
scala> import Function._ ; import PartialFunction._
import Function._
import PartialFunction._
scala> unlift(condOpt(_: String) { case s if b => f(s) }) applyOrElse ("hi", g)
res0: String = f+hi
scala> b = false
b: Boolean = false
scala> unlift(condOpt(_: String) { case s if b => f(s) }) applyOrElse ("hi", g)
res1: String = g+hi
What is the simplest way to convert a java.util.IdentityHashMap[A,B] into a subtype of scala.immutable.Map[A,B]? I need to keep keys separate unless they are eq.
Here's what I've tried so far:
scala> case class Example()
scala> val m = new java.util.IdentityHashMap[Example, String]()
scala> m.put(Example(), "first!")
scala> m.put(Example(), "second!")
scala> m.asScala // got a mutable Scala equivalent OK
res14: scala.collection.mutable.Map[Example,String] = Map(Example() -> first!, Example() -> second!)
scala> m.asScala.toMap // doesn't work, since toMap() removes duplicate keys (testing with ==)
res15: scala.collection.immutable.Map[Example,String] = Map(Example() -> second!)
Here's a simple implementation of identity map in Scala. In usage, it should be similar to standard immutable map.
Example usage:
val im = IdentityMap(
new String("stuff") -> 5,
new String("stuff") -> 10)
println(im) // IdentityMap(stuff -> 5, stuff -> 10)
Your case:
import scala.collection.JavaConverters._
import java.{util => ju}
val javaIdentityMap: ju.IdentityHashMap = ???
val scalaIdentityMap = IdentityMap.empty[String,Int] ++ javaIdentityMap.asScala
Implementation itself (for performance reasons, there may be some more methods that need to be overridden):
import scala.collection.generic.ImmutableMapFactory
import scala.collection.immutable.MapLike
import IdentityMap.{Wrapper, wrap}
class IdentityMap[A, +B] private(underlying: Map[Wrapper[A], B])
extends Map[A, B] with MapLike[A, B, IdentityMap[A, B]] {
def +[B1 >: B](kv: (A, B1)) =
new IdentityMap(underlying + ((wrap(kv._1), kv._2)))
def -(key: A) =
new IdentityMap(underlying - wrap(key))
def iterator =
underlying.iterator.map {
case (kw, v) => (kw.value, v)
}
def get(key: A) =
underlying.get(wrap(key))
override def size: Int =
underlying.size
override def empty =
new IdentityMap(underlying.empty)
override def stringPrefix =
"IdentityMap"
}
object IdentityMap extends ImmutableMapFactory[IdentityMap] {
def empty[A, B] =
new IdentityMap(Map.empty)
private class Wrapper[A](val value: A) {
override def toString: String =
value.toString
override def equals(other: Any) = other match {
case otherWrapper: Wrapper[_] =>
value.asInstanceOf[AnyRef] eq otherWrapper.value.asInstanceOf[AnyRef]
case _ => false
}
override def hashCode =
System.identityHashCode(value)
}
private def wrap[A](key: A) =
new Wrapper(key)
}
One way to handle this would be change what equality means for the class, e.g.
scala> case class Example() {
override def equals( that:Any ) = that match {
case that:AnyRef => this eq that
case _ => false
}
}
defined class Example
scala> val m = new java.util.IdentityHashMap[Example, String]()
m: java.util.IdentityHashMap[Example,String] = {}
scala> m.put(Example(), "first!")
res1: String = null
scala> m.put(Example(), "second!")
res2: String = null
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._
scala> m.asScala
res3: scala.collection.mutable.Map[Example,String] = Map(Example() -> second!, Example() -> first!)
scala> m.asScala.toMap
res4: scala.collection.immutable.Map[Example,String] = Map(Example() -> second!, Example() -> first!)
Or if you don't want to change equality for the class, you could make a wrapper.
Of course, this won't perform as well as a Map that uses eq instead of ==; it might be worth asking for one....