I have defined a class in Scala (2.9.1) as follows:
class A(val neighbors: Array[Option[A]]) {
def this() = this(new Array[Option[A]](6))
// class code here ...
}
My problem is that neighbors is initialized with nulls, when I would like it to be initialized with None. I tried this, but the compiler complains with the error message "not found: type None":
class A(val neighbors: Array[Option[A]]) {
def this() = this(new Array[None](6))
// class code here ...
}
I can do this, which gives the desired behavior, but it doesn't seem very elegant:
class A(val neighbors: Array[Option[A]]) {
def this() = this(Array(None, None, None, None, None, None))
// class code here ...
}
So, my question is, what is the best way to do this?
EDIT: I am referring to the behavior when new A() is called.
The easiest way to do this would be
Array.fill(6)(None:Option[A])
Additionally you can change your class's constructor to take a default parameter like this:
class A(val neighbors: Array[Option[A]] = Array.fill(6)(None))
Maybe like this?
def this() = this(Array.fill(6) {Option.empty})
Related
I have a helper class which creates instance of another class
class TestEnv {
val questionsController = new QuestionsController(...)
}
I am unit testing QuestionsController and have created a basic test case
class QuestionsControllerUnitSpec extends PlaySpec with BeforeAndAfterAll with BeforeAndAfterEach with OneAppPerSuiteWithComponents{
override def beforeEach() = {
println("------------new test -----------------")
}
override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._
lazy val router: Router = Router.from({
case GET(p"/") => defaultActionBuilder {
Results.Ok("success!")
}
})
}
"Question Controller " should {
"be created" in {
val testEnv = new TestEnv(components = components)
val qc:QuestionsController = testEnv.questionsController
qc mustBe defined //I get compilation error
}
}
}
I get the following compilation error
Error:(52, 10) could not find implicit value for parameter definition: org.scalatest.enablers.Definition[controllers.QuestionsController]
qc mustBe defined
Error:(52, 10) not enough arguments for method mustBe: (implicit definition: org.scalatest.enablers.Definition[controllers.QuestionsController])org.scalatest.Assertion.
Unspecified value parameter definition.
qc mustBe defined
I checked the definition of mustBe in MustMatchers.class. It is defined as def mustBe(right : org.scalatest.words.DefinedWord)(implicit definition : org.scalatest.enablers.Definition[T]) : org.scalatest.Assertion = { /* compiled code */ }
Why am I getting the error.
defined matcher syntax can be used with user defined types if we provide implicit implementation of Definition trait. For example, say we have a user defined class
class Foo {
val bar = 3
}
and we provide implicit definition
implicit val fooDefinition = new Definition[Foo] {
override def isDefined(foo: Foo): Boolean = foo.bar != null
}
then we can use defined syntax
(new Foo()) mustBe defined
If similar implicit implementation of Definition[QuestionsController] is provided, then the compiler error should be resolved.
I am happy to accept a different answer if it can provide more accurate answer. I suppose I am testing the wrong thing. What I am doing is similar to declaring an integer and checking if the integer exists! Instead I should be checking the value of the integer.
About matchers, more information is at http://doc.scalatest.org/3.0.1/#org.scalatest.MustMatchers. More information on Definition is on http://doc.scalatest.org/3.0.1/#org.scalatest.enablers.Definition
From array.scala of scala-2.10.4, The Array is defined as
final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {
/** The length of the array */
def length: Int = throw new Error()
def apply(i: Int): T = throw new Error()
def update(i: Int, x: T) { throw new Error() }
override def clone(): Array[T] = throw new Error()
}
Please note, the apply method will throw an exception! And for the accompany object Arrry, I find the following codes:
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
I know there is an implicit parameter which is ClassTag[T], what make me surprised is how
new Array[T] (xs.length)
is compiled. By decompiling the Array.class, I find that line is translated to :
public <T> Object apply(Seq<T> xs, ClassTag<T> evidence$2)
{
// evidence$2 is implicit parameter
Object array = evidence$2.newArray(xs.length());
...
}
I am really confused by this kind of translation, what is the rule under the hood?
Thanks
Chang
The Scala Array Class is just a fake wrapper for the runtime so you can use arrays in Scala. You're probably confused because those methods on the Array class throw exceptions. The reason they did this is so that if you actually end up using the fake class it blows up since really it should be using the java runtime array, which does not have a proper container class like Scala. You can see how the compiler handles it here. When your using arrays in Scala you're probably also using some implicits from predef like ArrayOps and WrappedArray for extra helper methods.
TLDR: Scala compiler magic makes arrays work with the java runtime under the hood.
On the JVM arrays are exempt from type-erasure, e.g. at runtime instead of Array[_] there is a difference between Array[Int], Array[String] and Array[AnyRef] for example. Unlike Java, Scala can handle this mostly transparently, so
class Foo {
val foo = new Array[Int](123)
}
has a direct byte-code invocation for creating the integer array, whereas
class Bar[A](implicit ev: reflect.ClassTag[A]) {
val bar = new Array[A](123)
}
is solved by using the implicit type evidence parameter of type ClassTag[A] so that at runtime the JVM can still create the correct array. This is translated into the call you saw, ev.newArray(123).
How do you define a static extension method in Kotlin? Is this even possible? I currently have an extension method as shown below.
public fun Uber.doMagic(context: Context) {
// ...
}
The above extension can be invoked on an instance.
uberInstance.doMagic(context) // Instance method
but how do I make it static method like shown below.
Uber.doMagic(context) // Static or class method
To achieve Uber.doMagic(context), you can write an extension to the companion object of Uber (the companion object declaration is required):
class Uber {
companion object {}
}
fun Uber.Companion.doMagic(context: Context) { }
This is what the official documentation says:
Kotlin generates static methods for package-level functions. Kotlin
can also generate static methods for functions defined in named
objects or companion objects if you annotate those functions as
#JvmStatic. For example:
Kotlin static methods
class C {
companion object {
#JvmStatic fun foo() {}
fun bar() {}
}
}
Now, foo() is static in Java, while bar() is not:
C.foo(); // works fine
C.bar(); // error: not a static method
I actually had this exact question 30 minutes ago, so I started digging around and couldn't find any solution or workaround for this, BUT while searching I found this section on the Kotlinglang website that states that:
Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null.
So then I had the craziest idea ever, why not define an extension function with a nullable receiver (without actually using that receiver) and then call it on a null object!
So I tried that, and it worked pretty well, but it looked so ugly. It was like this:
(null as Type?).staticFunction(param1, param2)
So I went around that by creating a val in my extensions file of the receiver type that had a value of null and then use it in my other class.
So, as an example, here is how I implemented a "static" extension function for the Navigation class in Android:
In my NavigationExtensions.kt file:
val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(#IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
//This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}
In the code that uses it:
SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)
Obviously, this isn't a class name, it is just a variable of the class type that has a null value. This is obviously ugly on the extension maker side (because they have to create the variable) and on the developer side (because they have to use the SType format instead of the actual class name), but it is the closest that can be achieved right now compared to actual static functions. Hopefully, the Kotlin language makers will respond to the issue that was created and add that feature in the language.
Since I keep coming across this when searching, here's a different approach I haven't seen anyone mention that works in a static way and it works with generics!
Extension definitions:
// Extension function
fun <T> KClass<T>.doSomething() = /* do something */
// Extension Property
val <T> KClass<T>.someVal get() = /* something */
Usage:
MyType::class.doSomething()
MyType::class.someVal
As you can see, the trick is attaching the extension function to the KClass of the type instead since that can be referenced statically.
You can create a static method with using Companion object like:
class Foo {
// ...
companion object {
public fun bar() {
// do anything
}
}
}
and then you can call it like:
class Baz {
// ...
private fun callBar() {
Foo.bar()
}
}
Recomend you to look at this link. As you can see there, you just should declare method at the top-level of the package (file):
package strings
public fun joinToString(...): String { ... }
This is equal to
package strings;
public class JoinKt {
public static String joinToString(...) { ... }
}
With constans everything are the same. This declaration
val UNIX_LINE_SEPARATOR = "\n"
is equal to
public static final String UNIX_LINE_SEPARATOR = "\n";
I also required the ability to extend a Java object with a static method and found the best solution for me was to create a Kotlin object that extended the Java class and add my method there.
object Colour: Color(){
fun parseColor(r: Int?, g: Int?, b: Int?) = parseColor(String.format("#%02x%02x%02x", r, g, b))
}
invocation:
val colour = Colour.parseColor(62, 0, 100)
I'm also quite fond of having the possibility to add static extension methods in Kotlin. As a workaround for now I'm adding the exntension method to multiple classes instead of using one static extension method in all of them.
class Util
fun Util.isDeviceOnline(context: Context): Boolean {
val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connMgr.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
To create an extension method in kotlin you have to create a kotlin file(not a class) then declare your method in the file
Eg:
public fun String.toLowercase(){
// **this** is the string object
}
Import the function in the class or file you are working on and use it.
I'm currently trying to figure out the depths of Scala's type system and Scala reflection.
I have the following example code (my real code is more complex and makes more sense, but boils down to this):
abstract class Node
class Foo extends Node
case class ArrayFoo(var subs : Array[Foo]) extends Foo
case class IntFoo(i : Integer) extends Foo
object Main {
def DoSomething(node : AnyRef) : AnyRef = { // Fix this function?
// do some stuff
node
}
def SetArrayWithReflection(n : Node, a : AnyRef) = {
if (a.isInstanceOf[Array[AnyRef]]) {
val arrayA = a.asInstanceOf[Array[AnyRef]].map(f => DoSomething(f)) // FIX this call?
val getter = n.getClass.getMethods.find(p => p.getName == "subs")
val setter = n.getClass.getMethods.find(p => p.getName == "subs_$eq")
if (setter == None) println("Method not found!") else {
println(f"would need to downcast from ${arrayA.getClass.getComponentType} to ${getter.get.getReturnType.getComponentType}")
setter.get.invoke(n, arrayA) // Error happens here
}
}
}
def main(args : Array[String]) : Unit = {
val my = ArrayFoo(Array(IntFoo(1), IntFoo(2), IntFoo(3)))
val newArray = Array(IntFoo(10), IntFoo(20), IntFoo(30))
SetArrayWithReflection(my, newArray)
my.subs.foreach(f => println(f))
}
}
The output I'm getting is:
would need to downcast from class java.lang.Object to class Foo
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at Main$.SetArrayWithReflection(Main.scala:19)
at Main$.main(Main.scala:27)
at Main.main(Main.scala)
Via reflection, I try to call a method expecting an Array[Object] with an Array[Foo], which obviously has to fail.
My question is: How can I downcast or create a suitable Array for method invocation?
The same code does work for Lists, however. I suppose this is due to type erasure which does not happen on Arrays.
Thanks in advance,
Velines
You can't downcast an Array[Object] to Array[Foo]. The simplest way to create the array you need is
val arrayFoo = Array.ofDim[Foo](arrayA.length)
System.arraycopy(arrayA, 0, arrayFoo, 0, arrayA.length)
See System.arraycopy.
I want to find a way to only allow certain objects into an array that have a certain word in thier class name. Or at least find the optimal way of doing something like this. Heres the details. I have an Array that stores all the objects dropped into a cart.
function addProductToArray (e:MouseEvent):void{
currMC = (e.target as MovieClip);
myCart.itemsInCart.push(currMC);
trace(myCart.itemsInCart);}
If, for example, I drop an [object BreadGrain] and a [object PastaGrain].
trace(myCart.itemsInCart);// would trace [object BreadGrain],[object PastaGrain].
Easy, no problems there. But what do I do if I only want to allow 2 objects with "Grain" in their Classname into the array? I want to do this so that the user can only drop 2 of each type of food into the 'cart'. The types of food are Grain, Fruit, Vegetable, Meats etc and I've appended the type of food to the end of the Classname, hopefully so that I can use it to detect what type of food it is and stop it from being added over the limit as well as displaying an error. i.e "You already have 2 Grain products".
I hope that makes sense. Anyway, i've found that works well to a degree:
if (currMC is BreadGrain) {
myCart.itemsInCart.push(currMC);
} else {
// error message code here
}
BUT I have several products and I don't want to have to write a if/else or switch statement for them all. I was hoping to do this dynamically with something similar to:
//this is an example of the logic
if (currMC classNameContainsTheWord "Grain" AND myCart.itemsInCart DoesNotContainMoreThan 2 Grain Objects) {
myCart.itemsInCart.push(currMC);
} else {
// error message code here
}
I'm stumped. Even just a "Dude, you are doing this all wrong" would help. Thanks.
You can get the class name of any object with the getQualifiedClassName function. Then you could try to match strings agains a certain pattern, with a RegExp or you could also just check if the class name contains some substring.
That said, I think a better approach could be using either a common base class or an interface.
// assuming your objects extend MovieClip
public class Grain extends MovieClip{
public function Grain() {
super();
}
public function someCommonMethodToAllGrains():void {
}
}
or
// It's customary to prefix interfaces name with an "I" in AS;
// I'm not doing it here so the code works for both a base class and an interface
public interface Grain {
function someCommonMethodToAllGrains():void;
}
Then, if you went with the base class:
public class BreadGrain extends Grain {
public function BreadGrain() {
super();
}
override public function someCommonMethodToAllGrains():void {
// if this makes sense for your object...
super.someCommonMethodToAllGrains();
}
}
public class PastaGrain extends Grain {
public function PastaGrain() {
super();
}
override public function someCommonMethodToAllGrains():void {
// if this makes sense for your object...
super.someCommonMethodToAllGrains();
}
}
Or, with the interface
public class BreadGrain extends MovieClip implements Grain {
public function BreadGrain() {
super();
}
public function someCommonMethodToAllGrains():void {
}
}
public class PastaGrain extends MovieClip implements Grain {
public function PastaGrain() {
super();
}
public function someCommonMethodToAllGrains():void {
}
}
If these objects are MovieClips, perhaps it's less tedious to use a base class, because otherwise you'd have to cast your objects back to MovieClip (or DisplayObject) any time you want to add them to the display list (or remove them). By the way, that's because someone at Adobe forgot to include an IDisplayObject interface and have the display list API accept objects that implemented this interface instead of a half-assed abstract class that you can't derive directly anyway (a.k.a. DisplayObject); this would have make it easier to treat display objects as interfaces, but I digress).
Anyway, either with an interface or a common base class you could do your validation with the is operator, but you'd just have to check for one type: Grain.
if(theObject is Graing && theArray.lenght <= 2) {
theArray.push(theObject);
}
You could also take this further and use a Vector instead of an Array. A Vector works almost the same as an Array, but it's strictly typed, so you could do:
var items:Vector.<Grain> = new Vector.<Grain>();
items.push(grainObject);
You'll get a compile time error if you try to add an object that does not extend/implement Grain.
Vectors are available for Flash Player 10 and you'd need Flash CS4, though (if you're using the Flash IDE; otherwise, I think you'd need at least the 3.2 SDK to compile).
Hm. I think you're going to need something a bit more complex to make this work properly. You're actually asking a two-part question: how to keep track of stuff, and how to identify stuff. I'll start with the easy bit, keeping track.
DISCLAIMER: My AS3 is pretty rusty, but at least the theory should be sound, even if the implementation might be a bit off.
First, you'd want to define the limits for each type of food, thus:
var dctLimits = new Object(); // not really a Dictionary, but we'll use it like one
dctLimits[ "grain" ] = 3;
dctLimits[ "meat" ] = 5;
...
Then, you want to keep count of objects you're adding to your cart
var dctCount = new Object();
dctCount[ "grain" ] = 0;
dctCount[ "meat" ] = 0;
...
Then, when you add a new object, first check its type against the relevant count. If the counter is less than the limit, let it in and increment the counter:
var type:String = getFoodTypeForObject( currMc );
if( dctCount[ type ] < dctLimit[ type ] ){
items.push( currMc );
dctCount[ type ]++;
} else {
// throw error
}
You'll notice that I've created an imaginary function, getFoodTypeForObject(). This is the trickier bit: identification.
You could implement your example logic like so:
function getFoodTypeForObject( currMc ){
if( getQualifiedClassName( currMc ).indexOf( "Grain" ) > -1 ){
return( "grain" );
} else if( getQualifiedClassName( currMc ).indexOf( "Meat" ) > -1 ){
return( "meat" );
}
...
}
Where classNameContainsTheWord is achieved with a combination of getQualifiedClassName and indexOf, but better would be to use a common base class, as suggested by Juan Pablo Califano. I'd suggest a slightly different style though:
public class CartItem extends MovieClip{
public var isGrain:Boolean;
public var isMeat:Boolean;
public function CartItem() {
super();
}
}
use that as the base Class for your cart item MCs, then set those boolean properties on the instances of MCs on your stage. Then, you can detect the type of something like this:
function getFoodTypeForObject( object ){
if( object.isGrain ){
return( "grain" );
} else if( object.isMeat ){
return( "meat" );
}
...
}
Cleaner than all that classname business, and has the added benefit that you can set something's properties independent of its class name.
It's not perfect; for instance, you'd need something more advanced if you needed a lot of properties, but it should be enough for you to keep going.
Uni had me doing other stuff for a while but finally I can get back into my game project.
I've got it working. I used Juan Pablo Califano's method. I did initially use Henry Cooke's because I wanted to get away with making a .AS file for each food (i.e. apple.as, cereal.as, bread.as, oranges.as). With Henry Cooke's method I created a
`var foodTypeLimit:Object = new Object();
foodTypeLimit["grain"]=2;
foodTypeLimit["fruit"]=2;
And var foodTypeCount:Object = new Object();
etc etc
`
For each food type. Then used the:
var type:String = getFoodTypeForObject( currMc );
if( foodTypeCount[ type ] < foodTypeLimit[ type ] ){
items.push( currMc );
foodTypeCount[ type ]++;
} else {
// throw error
}
As suggested. The function returned the string and viola it worked fine. However because my foodTypeCount variables (for example foodTypeCount["grain"]=0;) was inside the function, every time the function called these were set to 0 so the increment never got above with each call. So I thought, ok, i'll put these foodTypeCount variables outside of the function along with the instantiation of the var foodTypeCount:Object = new Object(); BUT NO, I kept getting the:
Error #1120: Access of undefined property foodTypeObject.
Even though it was right under the freakin declaration. I get i'm just too noob to understand why this is so. Anyway, for this reason (the lack of incrementation, which was essential to this function) I bit the bullet and used Juan Pablo Califano's way.
First I wrote out the classes like so:
public class Bread extends MovieClip implements Grain {
public function Bread() {
super();
}
public function someCommonMethodToAllGrains():void {
}
}
And then added the interface
`public interface Grain {
function someCommonMethodToAllGrains():void;
}
`
And now my function looks something like this:
if(currMC is Grain){
if(grainCount<2){
addProductToBasket();
grainCount++;
} else {
notAllowed("Grain");
}
}
function addProductToBasket(){
removeChild(currMC);
basketArray.push(currMC);
//remove listeners set mc to null etc
}
function notAllowed(foodType:String){
error.text="Sorry but you already have 2"+foodType+"products";
}
I tried to put all this into a switch. For example:
switch(currMC){
case is Grain:
//do this
break;
}
The above implementation didn't work. Perhaps switch statements probably aren't meant to be used that way. idk. :S
Anyway, thanks for the really great answers guys, this is my favorite site to come to for answers to life the universe and everything.