how to iterate over the properties of object in scala? - scala

Is there some way i can iterate over the properties of object and get the name and value both while iterating.
I know about the product iterator, but using that I only get the property value not the name of the property at the same time.

Unless you are building tooling for programmers developing scala, it is very probable that you should be using a Map instead of an object.
eg:
val myObject: Map[String, Any] =
Map("prop1" -> 1, "prop2" -> "string", "prop3" -> List(1, 2, 3))
for ((key, value) <- myObject) {
println(key, value)
}
If you are building tooling or you can't just swap out the object for a map, you can use reflection as mentioned in the other answers.

Just don't do it!
Use another design: Scala is not PHP or Python or Perl; it's a statically typed functional language with a very expressive type system; such reflection (runtime inspection) is not needed 99.9% of the time and should be avoided for reasons of safety, correctness and performance.

I think, there is no way to do it without using reflection. (See for example here: Getting public fields (and their respective values) of an Instance in Scala/Java)
An other option is using Apache FieldUtils: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/reflect/FieldUtils.html But again it uses reflection in background.

Related

How to find max date from stream in scala using CompareTo?

I am new to Scala and trying to explore how I can use Java functionalities with Scala.
I am having stream of LocalDate which is a Java class and I am trying to find maximum date out of my list.
var processedResult : Stream[LocalDate] =List(javaList)
.toStream
.map { s => {
//some processing
LocalDate.parse(str, formatter)
}
}
I know we can do easily by using .compare() and .compareTo() in Java but I am not sure how do I use the same thing over here.
Also, I have no idea how Ordering works in Scala when it comes to sorting.
Can anyone suggest how can get this done?
First of all, a lot of minor details that I will point out since it seems you are pretty new to the language and I expect those to help you with your learning path.
First, avoid var at all costs, especially when learning.
While mutability has its place and is not always wrong, forcing you to avoid it while learning will help you. Particularly, avoid it when it doesn't provide any value; like in this case.
Second, this List(javaList) doesn't do what you think it does. It creates a single element Scala List whose unique element is a Java List. What you probably want is to transform that Java List into a Scala one, for that you can use the CollectionConverters.
import scala.jdk.CollectionConverters._ // This works if you are in 2.13
// if you are in 2.12 or lower use: import scala.collection.JavaConverters._
val scalaList = javaList.asScala.toList
Third, not sure why you want to use a Scala Stream, a Stream is for infinite or very large collections where you want all the transformations to be made lazily and only produce elements as they are consumed (also, btw, it was deprecated in 2.13 in favour of LazyList).
Maybe, you are confused because in Java you need a "Stream" to apply functional operations like map? If so, note that in Scala all collections provide the same rich API.
Fourth, Ordering is a Typeclass which is a functional pattern for Polymorphism. On its own, this is a very broad question so I won't answer it here, but I hope the two links provide insight.
The TL;DR; is simple, it is just that an Ordering for a type T knows how to order (sort) elements of type T. Thus operations like max will work for any collection of any type if, and only if, the compiler can prove the existence of an Ordering for that type if it can then it will pass such value implicitly to the method call for you; again the implicits topic is very broad and deserves its own question.
Now for your particular question, you can just call max or maxOption in the List or Stream and that is all.
Note that max will throw if the List is empty, whereas maxOption returns an Option which will be empty (None) for an empty input; idiomatic Scala favour the latter over the former.
If you really want to use compareTo then you can provide your own Ordering.
scalaList.maxOption(Ordering.fromLessThan[LocalDate]((d1, d2) => d1.compareTo(d2) < 0))
Ordering[A] is a type class which defines how to compare 2 elements of type A. So to compare LocalDates you need Ordering[LocalDate] instance.
LocalDate extends Comparable in Java and Scala conveniently provides instances for Comparables so when you invoke:
Ordering[java.time.LocalDate]
in REPL you'll see that Scala is able to provide you the instance without you needing to do anything (you could take a look at the list of methods provided by this typeclass).
Since you have and Ordering in implicit scope which types matches the Stream's type (e.g. Stream[LocalDate] needs Ordering[LocalDate]) you can call .max method... and that's it.
val processedResult : Stream[LocalDate] = ...
val newestDate: LocalDate = processedResult.max

Scala: Invoking Standard Methods on Wrapper Maps After Java to Scala Conversion

I have two java maps which map a String to a set of Strings.
I want to convert the java maps to Scala and "add" map1 to map2 such that if they both have the same keys the value in the resultant map will be the union of the 2 value sets. I found a nice solution for the map addition:
map1 ++ map2.map { case (k,v) => k -> (v ++ map1.getOrElse(k,v))}
The issue happens when I convert the java maps to Scala via the 'asScala' call. When we do this conversation we get:
After the conversion to Scala, I am no longer able to run the solution above on these wrapper collections. The ++ operation on the map is still defined. However the SetWrapper class does not define a ++ operation. As far as I can tell the SetWrapper does not define any operations at all! Here is the full definition from the docs:
SetWrapper seems to extend an abstract class and does not define any of the functionality.
How can I get around this issue? Is there another conversation step to a real Set object?
JMapWrapper wraps a Java Map in a Scala Map; SetWrapper wraps a Scala Set in a Java Set. So it has Java's methods for Set, not Scala's.
You don't provide types, but it appears you start with a java.util.Map[SomeKey, java.util.Set[SomeType]]. Calling asScala on it will only convert the outer Map, not its values. You can fix this by using javaMap.asScala.mapValues(_.asScala) (with the usual caveat that it will call asScala each time a value is accessed; use .map instead if this isn't acceptable).

apply method on Map object?

First of all let me apologize in advance for what is my very first question posted on stack overflow and probably a quite stupid one.
Since a Map in scala is instantiated using the following syntax:
val myMap=Map(1->”value1”,2->”value2”)
I was expecting the Map object from scala.collection.immutable to provide an apply method with a signature roughly looking like:
def apply[A,B](entries :(A,B)*):Map[A,B]
Obviously I should be blind, but I can’t find such a method. Where is it defined ?
Furthermore, could someone give me information about the purpose of the Map1, Map2, Map3, Map4 classes defined in the Map object ? Should they be used by the developer or are they only used internally by the language and/or the compiler ? Are they related somehow to the map instantiation scheme i was asking about above ?
Thanks in advance for your help.
apply looks like it is defined on scala.collection.generic.GenMapFactory, a superclass of scala.collection.immutable.Map. For some reason, Scaladoc simply ignores this method for 2.9.2. (As Rogach notes, it was there in 2.9.1.)
Map1…Map4 (together with EmptyMap, which is private) are simply optimisations. These are defined inside Map.scala and really just hold up to four keys and values directly without any further indirection. If one tries to add to a Map4, a HashMap will automatically be created.
You normally do not need to create a Map[1-4] manually:
scala> Map('a -> 1)
res0: scala.collection.immutable.Map[Symbol,Int] = Map('a -> 1)
scala> res0.isInstanceOf[scala.collection.immutable.Map.Map1[_,_]]
res1: Boolean = true

Scala Case Class Map Expansion

In groovy one can do:
class Foo {
Integer a,b
}
Map map = [a:1,b:2]
def foo = new Foo(map) // map expanded, object created
I understand that Scala is not in any sense of the word, Groovy, but am wondering if map expansion in this context is supported
Simplistically, I tried and failed with:
case class Foo(a:Int, b:Int)
val map = Map("a"-> 1, "b"-> 2)
Foo(map: _*) // no dice, always applied to first property
A related thread that shows possible solutions to the problem.
Now, from what I've been able to dig up, as of Scala 2.9.1 at least, reflection in regard to case classes is basically a no-op. The net effect then appears to be that one is forced into some form of manual object creation, which, given the power of Scala, is somewhat ironic.
I should mention that the use case involves the servlet request parameters map. Specifically, using Lift, Play, Spray, Scalatra, etc., I would like to take the sanitized params map (filtered via routing layer) and bind it to a target case class instance without needing to manually create the object, nor specify its types. This would require "reliable" reflection and implicits like "str2Date" to handle type conversion errors.
Perhaps in 2.10 with the new reflection library, implementing the above will be cake. Only 2 months into Scala, so just scratching the surface; I do not see any straightforward way to pull this off right now (for seasoned Scala developers, maybe doable)
Well, the good news is that Scala's Product interface, implemented by all case classes, actually doesn't make this very hard to do. I'm the author of a Scala serialization library called Salat that supplies some utilities for using pickled Scala signatures to get typed field information
https://github.com/novus/salat - check out some of the utilities in the salat-util package.
Actually, I think this is something that Salat should do - what a good idea.
Re: D.C. Sobral's point about the impossibility of verifying params at compile time - point taken, but in practice this should work at runtime just like deserializing anything else with no guarantees about structure, like JSON or a Mongo DBObject. Also, Salat has utilities to leverage default args where supplied.
This is not possible, because it is impossible to verify at compile time that all parameters were passed in that map.

Why do Scala immutable HashMap methods return a Map?

I am having problems using the update method of scala.collection.immutable.HashMap.I don't see the reason it returns a Map instead of a HashMap. How do I get a new HashMap with a new key-value pair added?
That's the expected behavior. HashMap is most useful as a specific implementation of Map involving using a hash table for lookups.
Usually, you'd say var values: Map[String, Any] = new HashMap, and then sit back and use it as if it's a plain ol' immutable Map.
Do you have a reason for your code to know that it's a HashMap after you've new'd it as above?
If you're using 2.7 this is because over time the collections library has become inconsistent with various implementation class not specializing the return types of some methods. This is one of the things that is fixed in the collections library redesign for 2.8.
If you're using 2.8, this is because the update method is deprecated and you should use updated instead. This correctly specializes the return value.
scala> HashMap(1->1, 2->2, 3->3, 4->4).updated(1,3)
res4: scala.collection.immutable.HashMap[Int,Int] = Map((2,2), (4,4), (1,3), (3,3))
In 2.7.x, it returns a Map because it might be a ListMap or TreeMap or whatever, and it was deemed to be too much work to redefine the methods each time.
In 2.8.x, it should return a HashMap--but you have to use updated (update is deprecated).