How to pass a class as an function argument in scala? - scala

The problem is the following:
There is a module with such function
def testExceptions(toTest: MyClass): Unit = {
val isException = try {
toTest.increaseValue(-200);
false
} catch {
case e: Exception => true
}
if (isException) {
// some actions
} else {
// another actions
}
}
This function is importing in the file where MyClass is defined. It has such view
class MyClass(var value: Int) {
def show(): Unit = {
println(s"Value: $value")
}
def increaseValue(dv:Int): Unit = {
if(dv <= 0) { throw new IllegalArgumentException }
else { value += dv }
}
}
But I cannot pass MyClass object to the module function testExceptions because it is undefined in the file where this function exists. If I define MyClass in this file, it will be used in the testExceptions.
I will be grateful any help solving my confusion.

How to pass a class as an function argument in scala?
You can't. You can only pass objects as arguments. Classes are not objects, classes are types.
You can use reflection to get a proxy object that represents a type and pass that as an argument, though.
But I cannot pass MyClass object […]
That is because MyClass is not an object, it is a class. You cannot pass a class or any other type as an argument, only objects.
to the module function testExceptions
Note that testExceptions is defined to take an argument that is a value of type MyClass, it does not take MyClass itself as an argument. You need to instantiate an object of MyClass and pass that as an argument.

Related

How do you define an enum that can only be created by its companion object? (think smart constructors)

I've tried making the constructor private, like this:
enum X {
case Stuff private (value: Int)
}
object X {
def stuff(s: String) =
X.Stuff(performSomeValidationAndCalculation(s))
}
but it complains:
method apply cannot be accessed as a member of Playground.X.Stuff.type from module class X$
I would like to force callers to use the smart constructor to prevent an invalid enum from being instantiated and to limit the number of introduction forms.
Just add the class name to private to limit the scope:
enum X {
case Stuff private[X] (value: Int)
}
object X {
def stuff(s: String) =
X.Stuff(s.toInt)
}
Sample working code: https://scastie.scala-lang.org/hUPECAJFSzqAus6c5slBHQ

kotlin's javaclass.isPrimitive fails if parameter compile-time is not actual type

The following code
fun foo(value:Double) {
if(!value.javaClass.isPrimitive) {
println("try again")
return
}
}
println("that's nice")
}
fun main() {
foo(0.0)
}
displays:
"that's nice"
but setting value type as Any:
fun foo(value:Any) {
if(!value.javaClass.isPrimitive) {
println("try again")
return
}
println("that's nice")
}
fun main() {
foo(0.0)
}
will display: "try again"
even though valueruntime type is Double,
link for testing : https://pl.kotl.in/HkghkAkF4
quote from https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/java-class.html:
inline val T.javaClass: Class
Returns the runtime Java class of this object
which from https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#isPrimitive should give me right
EDIT: removed unnecessary run{}
When you declare the type as Double, that's a primitive double (rather than the Double wrapper class).
When you declare the type as Any, the method then accepts any object as a parameter, so even if you pass in a primitive double, it will be auto-boxed into a wrapper object for Double and will no longer be a primitive.
You can see this by running this snippet on play.kotlinlang.org:
fun main() {
useDouble(3.0)
useAny(3.0)
}
fun useDouble(value: Double) = println("${value.javaClass.name}")
fun useAny(value: Any) = println("${value.javaClass.name}")
Prints:
double
java.lang.Double
isn't there a method like "isPrimitive" for wrapper classes
Not directly, but you can check whether a value belongs to a wrapper class by
value::class.javaPrimitiveType != null
Or if you just have a clazz: Class<T>,
clazz.kotlin.javaPrimitiveType != null

Get type of an object in a Haxe macro

I would like to get the class of an object in a macro so that I can access its static variables:
// autoBuild macro adds static field "id_ : Int" to all subclasses
class Base {
}
class Child1 extends Base {
public function new() {}
}
class Child2 extends Base {
public function new() {}
}
class Container {
public function addChild(index: Int, object: Base) {}
macro function add(object: ???) {
// find out class of on object
// ???
// var id = class.id_;
this.addChild(id, object);
}
}
Desired usage:
var c = new Container();
c.add(new Child1());
c.add(new Child2());
You can use Context.typeof() to get the expression's type - then you need to do a bit of pattern matching to find out the type's name. The following only works with classes because it only matches TInst, but could be extended:
import haxe.macro.Context;
import haxe.macro.Expr;
class Container {
// [...]
public macro function add(self:Expr, object:Expr):Expr {
var name = switch (Context.typeof(object)) {
case TInst(_.get() => t, _): t.name;
case _: throw "object type not found";
}
return macro $self.addChild($i{name}.id_, $object);
}
}
This will generate the following code:
var c = new Container();
c.addChild(Child1.id_, new Child1());
c.addChild(Child2.id_, new Child2());
Note that accessing _id via it's unqualified name is only safe if it's actually imported (or toplevel) - in practice you'd want to use t.pack in combination with $p{} to generate the fully qualified path.

How to initialize a field by calling a method

The following class refuses to compile:
class InitTest { // Class 'InitTest' must either be declared abstract
// or implement abstract member 'v: Int'
var v: Int
def int(v : Int) = {
this.v = v
}
}
I was kind of surprise by that we can't just leave values "uninitialized". In Java, it would be assigned with null. In Scala, it does not compile. How to do this in Scala?
You can do this:
class InitTest {
var v: Int = _
def int(v : Int) = {
this.v = v
}
}
Since v has a value type, there is no way of assigning null to it. However, Scala lets you use _ to represent the "zeroed" value. For numbers, that is zero and for pointers that is null. Good way of representing uninitialized values.

Pointer on method in a tuple causes an error when calling the method through the tuple

In my class, I have an array of tuples with inside a string and two pointer on method.
I don't know why, but when I want to call a method stored into my tuple I've got this error message:
Missing argument for parameter #1 in call
My class:
class toto
{
let funcs = [("a", a, aa), ("b", b, bb)]
func a()
{
}
func aa()
{
}
func b()
{
}
func bb()
{
}
func test()
{
for (key, func1, func2) in funcs
{
func1() // The error displayed: Missing argument for parameter #1 in call
}
}
}
Any suggestions ?
You have to pass a reference to self in your function call:
func1(self)()
The pointer to a class function that you store in the array doesn't include information about the instance of the class it belongs to (or better the class instance where the function is executed). In order to make it work you have to provide a context (i.e. a reference to an instance of the class), which in this case is self.
Take a look at curried functions