In Scala.js, how would you traverse object graphs navigationally? - scala

Suppose that you want to traverse an object graph in a navigational way, similar to the way we traverse file systems.
For example, imagine you have an object graph that supports this expression:
var x = objName.foo.bar.baz.fieldName
We can encode this data access expression as a path as follows:
"objName/foo/bar/baz/fieldName"
By breaking this path into segments, we can easily traverse an object graph in JavaScript because in addition to the traditional dot notation, it also supports the array access notation: objName["foo"]["bar"]["baz"]["fieldName"].
In Java or JVM Scala, we can use reflection to traverse object graphs, but how would you follow these kinds of paths to traverse object graphs of Scala objects in the Scala.js environment?
In other words, given a path similar in form to URIs, how would you walk through Scala.js objects, and fields?

You could surely use a macro to convert a constant String representation to an accessor at compile-time, but I guess you want to be able to do this at run-time for arbitrary strings.
If the goal is to be able to pass around partially constructed paths, then this is just a matter of passing accessor functions around. You could use something like this to make it prettier:
class Path[+A](private val value: () => A) {
def resolve: A = value()
def /[B](f: A => B): Path[B] = new Path(() => f(resolve))
}
implicit class PathSyntax[A](val a: A) extends AnyVal {
def /[B](f: A => B): Path[B] = new Path(() => a) / f
}
object Foo {
val bar = Bar
}
object Bar {
val baz = Baz
}
object Baz
The syntax is not exactly as pretty, but this is now typesafe and not too bad looking:
val barPath: Path[Bar.type] = Foo / (_.bar)
val bazPath: Path[Baz.type] = barPath / (_.baz)
Against, this would need more work, eg. there is no proper equality/comparison between Paths.
If you want to stick with your approach, I'm not aware of a direct solution. However, I would argue that the whole point of using ScalaJS is to keep strong types and avoid any pattern that could lead to runtime errors that the compiler could have prevented had you let it do its job.

Related

Scala How to create an Array of defs/Objects and the call those defs in a foreach?

I have a bunch of Scala objects with def's that do a bunch of processing
Foo\CatProcessing (def processing)
Foo\DogProcessing (def processing)
Foo\BirdProcessing (def processing)
Then I have a my main def that will call all of the individual Foo\obj defProcessing. Passing in common parameter values and such
I am trying to put all the list of objects into an Array or List, and then do a 'Foreach' to loop through the list passing in the parameter values or such. ie
foreach(object in objList){
object.Processing(parametmers)
}
Coming from C#, I could do this via binders or the like, so who would I manage this is in Scala?
for (obj <- objList) {
obj.processing(parameters) // `object` is a reserved keyword in Scala
}
or
objList.foreach(obj => obj.processing(parameters))
They are actually the same thing, the former being "syntactic sugar" for the latter.
In the second case, you can bind the only parameter of the anonymous function passed to the foreach function to _, resulting in the following
objList.foreach(_.processing(parameters))
for comprehensions in Scala can be quite expressive and go beyond simple iteration, if you're curious you can read more about it here.
Since you are coming from C#, if by any chance you have had any exposure to LINQ you will find yourself at home with the Scala Collection API. The official documentation is quite extensive in this regard and you can read more about it here.
As it came up in the comments following my reply, you also need the objects you want to iterate to:
have a common type that
exposes the processing method
Alternatively, Scala allows to use structural typing but that relies on runtime reflection and it's unlikely something you really need or want in this case.
You can achieve it by having a common trait for your objects, as in the following example:
trait Processing {
def processing(): Unit
}
final class CatProcessing extends Processing {
def processing(): Unit = println("cat")
}
final class DogProcessing extends Processing {
def processing(): Unit = println("dog")
}
final class BirdProcessing extends Processing {
def processing(): Unit = println("bird")
}
val cat = new CatProcessing
val dog = new DogProcessing
val bird = new BirdProcessing
for (process <- List(cat, dog, bird)) {
process.processing()
}
You can run the code above and play around with it here on Scastie.
Using a Map instead, you can do it as such. (wonder if this works through other types of lists)
val test = Map("foobar" -> CatProcessing)
test.values.foreach(
(movie) => movie.processing(spark)
)

Does Scala's Vector add any new methods on top of those provided by Seq and other superclasses?

Are there any methods in Scala's Vector that are not declared by its superclasses like AbstractSeq?
I am working on providing language localization (translation) for a learning environment/IDE built on top of Scala called Kojo (see kojo.in). I have translated most commonly used methods of Seq. Vector inherits them automatically, so I don't need to duplicated the translation code (keeping DRY). E.g.,
implicit class TurkishTranslationsForSeqMethods[T](s: Seq[T]) {
def başı: T = s.head
def kuyruğu: Seq[T] = s.tail
def boyu: Int = s.length
def boşMu: Boolean = s.isEmpty
// ...
}
implicit class TranslationsForVectorMethods[T](v: Vector[T]) {
??? // what to translate here?
}
Hence the question. Maybe, more importantly, is there a way to find out such novel additions for any class without having to do a manual diff?
The scaladoc provides a way to filter methods to not see the ones inherited from Seq for instance: https://www.scala-lang.org/api/current/scala/collection/immutable/Vector.html a'd click on "Filter all members".
Or, probably easier, IDEs usually provide a "Hierarchy" view of a class and its methods that would give you the information quickly.

Why this map function does not give traits' simple names

I try to get names of all trait a class extends using getInterfaces which returns an array of trait's names. When I manually access each member of the array, the method getName returns simple names like this
trait A
trait B
class C() extends A, B
val c = C()
val arr = c.getClass.getInterfaces
arr(0).getName // : String = A
arr(1).getName // : String = B
However, when I use map function on arr. The resulting array contains a cryptic version of trait's names
arr.map(t => t.getName) // : Array[String] = Array(repl$.rs$line$1$A, repl$.rs$line$2$B)
The goal of this question is not about how to get the resulting array that contains simple names (for that purpose, I can just use arr.map(t => t.getSimpleName).) What I'm curious about is that why accessing array manually and using a map do not yield a compatible result. Am I wrong to think that both ways are equivalent?
I believe you run things in Scala REPL or Ammonite.
When you define:
trait A
trait B
class C() extends A, B
classes A, B and C aren't defined in top level of root package. REPL creates some isolated environment, compiles the code and loads the results into some inner "anonymous" namespace.
Except this is not true. Where this bytecode was created is reflected in class name. So apparently there was something similar (not necessarily identical) to
// repl$ suggest object
object repl {
// .rs sound like nested object(?)
object rs {
// $line sounds like nested class
class line { /* ... */ }
// $line$1 sounds like the first anonymous instance of line
new line { trait A }
// import from `above
// $line$2 sounds like the second anonymous instance of line
new line { trait B }
// import from above
//...
}
}
which was made because of how scoping works in REPL: new line creates a new scope with previous definitions seen and new added (possibly overshadowing some old definition). This could be achieved by creating a new piece of code as code of new anonymous class, compiling it, reading into classpath, instantiating and importing its content. Byt putting each new line into separate class REPL is able to compile and run things in steps, without waiting for you to tell it that the script is completed and closed.
When you are accessing class names with runtime reflection you are seeing the artifacts of how things are being evaluated. One path might go trough REPLs prettifiers which hide such things, while the other bypass them so you see the raw value as JVM sees it.
The problem is not with map rather with Array, especially its toString method (which is one among the many reasons for not using Array).
Actually, in this case it is even worse since the REPL does some weird things to try to pretty-print Arrays which in this case didn't work well (and, IMHO, just add to the confusion)
You can fix this problem calling mkString directly like:
val arr = c.getClass.getInterfaces
val result = arr.map(t => t.getName)
val text = result.mkString("[", ", ", "]")
println(text)
However, I would rather suggest just not using Array at all, instead convert it to a proper collection (e.g. List) as soon as possible like:
val interfaces = c.getClass.getInterfaces.toList
interfaces .map(t => t.getName)
Note: About the other reasons for not using Arrays
They are mutable.
Thet are invariant.
They are not part of the collections hierarchy thus you can't use them on generic methods (well, you actually can but that requires more tricks).
Their equals is by reference instead of by value.

How to get reflected runtime Method from AnyRef object?

I am trying to get the reflected runtime method in an instance but it is not shown in the decls result:
val foo: AnyRef = new Object {
def bar = 1
}
typeOf[foo.type].decls //Does not contain bar method
I tried to use Java reflection class and it works:
foo.getClass.getDeclaredMethods //It contains bar method
But I prefer to work with MethodSymbols and Scala Type than Java Class and Method reflection. How can I get the reflected MethodSymbol?
I want an method to look up an object passed as AnyRef for a method bar and call it. Something like below:
def getBarMethodFromObj(obj: AnyRef): MethodSymbol = {
//typeOf(obj).decl(TermName("bar")) this doesn't work
}
I cannot use trait because bar can have different argument and return types and numbers. As Scala does not support varadic generic arguments, I plan to use reflection to find the method and call, but this cannot be done in Scala as well. I am currently use Java solution:
val bar = foo.getClass.getDeclaredMethods.find(_.getName == "bar")
bar.invoke(foo, params: _*)
However Java reflection does not retain generic types as it creates problem for List and Map, etc. So I want to know if I can implement this in Scala, or is there any coming solution
I don't know what you're trying to do, but removing the AnyRef annotation makes your code work:
val foo = new { def bar = 1 }
typeOf[foo.type].decls // Contains bar method
If you need a type annotation (for example, in a method signature), you can use the same structural type that the compiler infers:
val foo: { def bar: Int } = new { def bar = 1 }
If you want to get the full list of methods from another method without knowing the exact type except via generics, you may be interested in TypeTag:
import scala.reflect.runtime.universe.{ TypeTag, typeTag }
val foo = new { def bar = 1 }
def getMethods[T: TypeTag](t: T) = typeTag[T].tpe.decls
getMethods(foo) // Contains bar
If you can't use TypeTag (maybe because you can't make API changes), then you're probably best off using the Java reflection API. The Scala reflection API is generally designed to use type information, so it may not work for you if you only know the type is AnyRef.
In response to your edit:
I cannot use trait because bar can have different argument and return types and numbers.
Sure you can:
trait Foo[A, B] {
def bar(a: A): B
}
If you need multiple arguments, just have bar take a tuple instead. If you need to do some list manipulation that tuples don't support, you might consider learning about HLists and shapeless.
However Java reflection does not retain generic types...
Well, no runtime-only reflection API will help you there. There is simply no way to find out what generic parameters an AnyRef has at runtime, as that information doesn't exist on the JVM. Use TypeTags, or use a trait in the manner described above.

Why do you need Arbitraries in scalacheck?

I wonder why Arbitrary is needed because automated property testing requires property definition, like
val prop = forAll(v: T => check that property holds for v)
and value v generator. The user guide says that you can create custom generators for custom types (a generator for trees is exemplified). Yet, it does not explain why do you need arbitraries on top of that.
Here is a piece of manual
implicit lazy val arbBool: Arbitrary[Boolean] = Arbitrary(oneOf(true, false))
To get support for your own type T you need to define an implicit def
or val of type Arbitrary[T]. Use the factory method Arbitrary(...) to
create the Arbitrary instance. This method takes one parameter of type
Gen[T] and returns an instance of Arbitrary[T].
It clearly says that we need Arbitrary on top of Gen. Justification for arbitrary is not satisfactory, though
The arbitrary generator is the generator used by ScalaCheck when it
generates values for property parameters.
IMO, to use the generators, you need to import them rather than wrapping them into arbitraries! Otherwise, one can argue that we need to wrap arbitraries also into something else to make them usable (and so on ad infinitum wrapping the wrappers endlessly).
You can also explain how does arbitrary[Int] convert argument type into generator. It is very curious and I feel that these are related questions.
forAll { v: T => ... } is implemented with the help of Scala implicits. That means that the generator for the type T is found implicitly instead of being explicitly specified by the caller.
Scala implicits are convenient, but they can also be troublesome if you're not sure what implicit values or conversions currently are in scope. By using a specific type (Arbitrary) for doing implicit lookups, ScalaCheck tries to constrain the negative impacts of using implicits (this use also makes it similar to Haskell typeclasses that are familiar for some users).
So, you are entirely correct that Arbitrary is not really needed. The same effect could have been achieved through implicit Gen[T] values, arguably with a bit more implicit scoping confusion.
As an end-user, you should think of Arbitrary[T] as the default generator for the type T. You can (through scoping) define and use multiple Arbitrary[T] instances, but I wouldn't recommend it. Instead, just skip Arbitrary and specify your generators explicitly:
val myGen1: Gen[T] = ...
val mygen2: Gen[T] = ...
val prop1 = forAll(myGen1) { t => ... }
val prop2 = forAll(myGen2) { t => ... }
arbitrary[Int] works just like forAll { n: Int => ... }, it just looks up the implicit Arbitrary[Int] instance and uses its generator. The implementation is simple:
def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary
The implementation of Arbitrary might also be helpful here:
sealed abstract class Arbitrary[T] {
val arbitrary: Gen[T]
}
ScalaCheck has been ported from the Haskell QuickCheck library. In Haskell type-classes only allow one instance for a given type, forcing you into this sort of separation.
In Scala though, there isn't such a constraint and it would be possible to simplify the library. My guess is that, ScalaCheck being (initially written as) a 1-1 mapping of QuickCheck, makes it easier for Haskellers to jump into Scala :)
Here is the Haskell definition of Arbitrary
class Arbitrary a where
-- | A generator for values of the given type.
arbitrary :: Gen a
And Gen
newtype Gen a
As you can see they have a very different semantic, Arbitrary being a type class, and Gen a wrapper with a bunch of combinators to build them.
I agree that the argument of "limiting the scope through semantic" is a bit vague and does not seem to be taken seriously when it comes to organizing the code: the Arbitrary class sometimes simply delegates to Gen instances as in
/** Arbirtrary instance of Calendar */
implicit lazy val arbCalendar: Arbitrary[java.util.Calendar] =
Arbitrary(Gen.calendar)
and sometimes defines its own generator
/** Arbitrary BigInt */
implicit lazy val arbBigInt: Arbitrary[BigInt] = {
val long: Gen[Long] =
Gen.choose(Long.MinValue, Long.MaxValue).map(x => if (x == 0) 1L else x)
val gen1: Gen[BigInt] = for { x <- long } yield BigInt(x)
/* ... */
Arbitrary(frequency((5, gen0), (5, gen1), (4, gen2), (3, gen3), (2, gen4)))
}
So in effect this leads to code duplication (each default Gen being mirrored by an Arbitrary) and some confusion (why isn't Arbitrary[BigInt] not wrapping a default Gen[BigInt]?).
My reading of that is that you might need to have multiple instances of Gen, so Arbitrary is used to "flag" the one that you want ScalaCheck to use?