scalajs-react ComponentScope unification - scala

I have some state-modifying tasks needed to be run inside componentDidMount as well inside button click handlers defined in renderS method.
Tasks have a lot of common code so i've decided to join them inside one class, that receives scope and applies necessary actions.
Trouble is: inside renderS method i have access to ComponentScopeU[...] and inside componentDidMount i have ComponentScopeM[...]
I've found that to access .props i need to verify my scope have supertrait ComponentScope_P[...], to access .state my scope should have supertrait ComponentScope_S[...] and to have ability to .modState i should pass implicitly CompStateAccess[...].
So currently i have code like this
case class State(...)
type ScopePS = ComponentScope_P[Int] with ComponentScope_S[State]
type StateAccess[C] = CompStateAccess[C, State]
implicit class MyActions[T <: ScopePS : StateAccess](scope: T) {...}
It's working but i wonder how could this be simplified, i.e. how could props\state be accessed inside renderS and componentDidMount via common code?

Related

FactoryBot: Check if trait has been passed in

I am trying to put a conditional piece of logic into a factory that will only run if a specific trait has been passed in as an argument. I am inside the to_create block so have access to the instance and the evaluator. Do either of them have a method that returns which traits, if any, have been passed in?

How Scala App trait and main works internally?

Hi I'm newbie in Scala.
As far as I know there are 2ways to make entry point in scala, one is define main method with object and the other is extending App trait.
I wondered how App trait works, so I checked the source for App trait, but there are full of confusing code...
The code said that the App has initCodes which are extended from App trait, and these are added in delayedInit method that inherited from DelayedInit. Also the App trait has main method, which will be entry point.
But the What confusing me are
Who call delayedInit? Is it called before the main method is called?(I guess Yes)
Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.
Where can I check these knowledge? I tried to search in document but I couldn't
Who call delayedInit? Is it called before the main method is called?(I guess Yes)
The delayedInit would be called automatically by the Scala compiler as the initialisation code of the object/class that extends the DelayedInit trait. I expand more on this answer below.
Why initCodes is ListBuffer not a element? I think there is only one entry point in application, so I don't think it should be plural.
Because it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. An example is also provided below.
Where can I check these knowledge? I tried to search in document but I couldn't.
I got to learn about the dynamics by reading the Scala docs and the links it points to. For example this https://github.com/scala/scala/releases/tag/v2.11.0 and https://issues.scala-lang.org/browse/SI-4330?jql=labels%20%3D%20delayedinit%20AND%20resolution%20%3D%20unresolved
I would now try to expatiate more on the answer above by going into more details into the workings of DelayedInit, and how the JVM specifies entry points to programs.
First of all, we have to understand that when Scala is run on the JVM, it still has to adhere to the JVM requirement for defining the entry point to your program, which is to provide the JVM with a class with a main method with signature of public static void main(String[]). Even though when we use the App trait, it might appear as if we are getting away from do this, but this is just an illusion, the JVM still needs to have access to a method with the signature public static void main(String[]). It is just that by extending App together with the mechanism of DelayedInit, Scala can provide this method on our behalf.
Second, it is also good to reiterate that code snippets found in the body of a class (or object) definition, would be the initialisation code of such a class/object and would be executed automatically when such is instantiated. In Java, it is more or less the code you put in the constructor block.
So for a class:
class Foo {
// code.
def method = ???
}
Whatever code is, it will be executed automatically when you call new Foo.
In case of an object
object Foo {
// code.
def method = ???
}
The code will be executed automatically without you having to call new since Scala would automatically make a singleton instance called Foo available for you.
So basically if anything is in the body definition, it gets executed automatically. You do not need to explicitly execute it.
Now to the DelayedInit trait. One thing to be aware of is that it provides us a mechanism to perform what can be called a compiler trick, where certain part of our code gets rewritten. This is one of the reason why it could be confusing to reason about. Because when you use it, what actually gets executed by the Scala compiler is not the code you reading but a slight modification of it. To understand what is going on, you then need to understand the ways the compiler alters the code.
The trick, the DelayedInit trait allows us to perform is to take the code that is part of the body of a class/object definition and turn it, into an argument that is passed by name, to the method delayedInit defined on DelayedInit.
Basically it rewrites this:
object Foo {
// some code
}
into
object Foo {
// delayedInt({some code})
}
This means instead of having // some code executed automatically, delayedInt is the method that is called automatically with // some code passed to it as arguments.
So anything that extends DelayedInit would have its initialisation code replaced by the method call delayedInt with the initialisation code passed as an argument. Hence why nobody needs to explicitly call the delayedInt method.
Now let use see how this then tie to the App trait and how the App trait is used to provide the entry point to a Scala application.
As you will notice, the delayedInit method on the DelayedInit trait does not provide any implementation. Hence the actual behaviour of delayedInit when it is called needs to be provided by something else that extends DelayedInit.
The App trait is such an implementation. And what does the App trait do? Two important thing related to the topic of discussion:
It provides an implementation of delayedInit which takes the initialisation code it is passed, and puts it in a ListBuffer.
It provides the main method def main(args: Array[String]) which satisfy the requirement of the JVM to have a method with public static void main(String[]) to serve as the entry point to a program. And what this main method does, is to execute whatever code placed in the ListBuffer.
The above characteristics of the App trait means that any object/class that extends it would have its initialisation code passed to delayedInit, which would then add it into a ListBuffer, and then the object/class extending it would now have a main method, which when called (most of the time by the JVM as the entry point) would run through the code in the ListBuffer and execute it.
Basically it turns this:
object Foo {
// some code
}
into this
object Foo {
// the implementation of delayedInt is to put `// some code` into a list buffer
delayedInt (// some code)
def main(args: Array[String]) = {
// the implementation below just runs through and execute the code found in list buffer that would have been populated by the call to delayedInt and
???
}
}
So why have a List buffer to store the code to be executed? Because, as I said above it is possible to have a hierarchy of classes, where the initialisation code of each class in the hierarchy gets executed as part of executing the program. To see this in action.
Given the following code snippet:
class AnotherClass {
println("Initialising AnotherClass")
}
trait AnotherTrait {
println("Initialising AnotherTrait")
}
trait YetAnotherTrait {
println("Initialising YetAnotherTrait")
}
object Runner extends AnotherClass with AnotherTrait with YetAnotherTrait with App {
println("Hello world")
}
When run would output the following:
Initialising AnotherClass
Initialising AnotherTrait
Initialising YetAnotherTrait
Hello world
So the individual initialisation code in the hierarchy that consists of AnotherClass, AnotherTrait and YetAnotherTrait gets added to the initCode list buffer, via the delayedInit method of the App trait, and then they get executed by the main method also provided by the App trait.
As you would have noticed by peeking into the source code, the whole mechanism of DelayedInt is deprecated and schedule for removal in the future.
delayedInit:-
The init hook. This saves all initialization code for execution within
main. This method is normally never called directly from user code.
Instead it is called as compiler-generated code for those classes and
objects (but not traits) that inherit from the DelayedInit trait and
that do not themselves define a delayedInit method.
App scala
delayedInit is deprecated since 2.11.0. Also, it has some outstanding bugs which are not fixed.
initCodes:-
I am not sure about the reason for defining the initCodes as ListBuffer.

Scala Argument Capture of External Class

So I want to check arguments that I send to an external class that I do not control. The external class is assumed tested, I simply want to test if I passed it the right parameters. I have tried some combination of ArgumentCaptor etc, but not much luck
import org.ABC.ExternalClass
case class Foo(i:Int, j: Int...) {
val EC = CreateExternalClass()
def CreateExternalClass(): ExternalClass = {
new ExternalClass (i, j, ....many parameters)
}
}
I think you are getting things wrong here: you can only use an ArgumentCaptor on calls to mocked objects. You can't use them to "intercept" arbitrary calls between all kinds of objects.
Meaning: you could only use an ArgumentCaptor if you would be using a mocked ExternalClass object. But then you would not need to capture, as you probably could do simply method call argument verification.
But of course, you can't use Mockito to mock that call to new in your production class. The options you have:
Turn to PowerMockito or JMockit; frameworks that allow to mock calls to new. Not recommended.
Rework your production code to not do that call to new. Probably not helpful here; as this class might already be a wrapper around that external class
Go for checking on the created object: check if you could use getter methods to simply query the newly created object to have the values that you expect to show up inside

Scala Action method in Play 2

I am pretty new to Scala and I am learning Play as well. I see the following construct used in Play
def list = Action {
val products = Product.findAll
Ok(views.html.products.list(products))
}
I am confused as to what
Action {}
does. Is Action the returned value of the method? What is this construct called if I want to know more about it?
This construction called factory method enhanced via scala apply sugar
Action in this reference is the companion object, which could be called singleton, but in fact along with very specific singleton type Action$ it methods reflected as static methods of Action.
As we can read object Action extends ActionBuilder[Request] which have plenty of apply methods constructing values of Action type.
Curly braces here presents nullary function which is null-parameter closure and often named so in different languages like ruby or groovy. It's just multiline block of code which produces something at the end.

Different field instances in class and parent/Call super constructor with method

I am trying to call the super constructor from a class using a method. The whole setup looks like this:
class Straight(hand: Hand) extends Combination(Straight.makeHandAceLowIfNeeded(hand), 5)
object Straight {
private def makeHandAceLowIfNeeded(hand: Hand): Hand = {
...
}
}
While this does compile, it has some rather odd runtime behaviour. While debugging, I noticed that the Straight instances have the "hand" property defined twice. Can somebody tell me what is going on, and what the proper way is to call the super constructor with different arguments?
In my use case, I want to call the super constructor with a modified hand in which I replaced a card compared to the original constructor argument.
Debugger screenshot with duplicate field:
.
It's a perfectly fine way to call the superclass constructor. These are two private fields and they don't conflict, though you can rename one of them to avoid confusion during debugging (or if you want to access the superclass' value from the subclass). However, the field should only be generated for a class parameter if it's used outside a constructor, and in your case it doesn't appear to be. Did you simplify the definition of Straight?