Any idea how I can avoid these repeated class parameters?
abstract class XClass( var x: Int, var y: Int, var w: Int, var h: Int) {...}
abstract class MXClass( var xS: Int, var yS: Int, var wS: Int, var hS: Int)
extends XClass (xS, yS, wS, hS)
class PXClass( var xP: Int = 0, var yP: Int = 0, var wP: Int = 0, var hP: Int = 0)
extends MXClass (xP, yP, wP, hP)
def draw(g: Graphics2D) {
g fillRect (x, y, w, h)
}
then I have something like this in a GUI:
g setColor black
val cc = new PXClass(200, 300, 10, 10)
cc.draw(g)
So I am giving those parameters as they are needed in the GUI!
Thanks
According to what you said:
the XClass is a Piece class and MXClass is a MovablePiece then PXClass is RectanglePiece class. Then I need Piece class to extend by StationaryPiece, thus I am trying to have some movable and statinary pieces in a BoardPanel of different shapes. – Val 18 mins ago
Let's just start out by defining them one by one — let's not use any inheritance because it's not immediately obvious it's even needed; you can come back to inheritance (or some other type of polymorphism) when needed but trust me it's never actually needed:
sealed trait Shape
case object Rectangle extends Shape
case object Square extends Shape
case object Circle extends Shape
case class Dimensions(x: Int, y: Int, w: Int, h: Int)
case class Piece(shape: Shape, dim: Dimensions, isMovable: Boolean = true)
val squarePiece = Piece(Square, Dimensions(x = 100, y =. 200, w = 20, h = 20))
val circularPiece = Piece(Circular, Dimensions(x = 0, y = -100, w = 40, h = 40))
val immovableRectPiece = Piece(Rectangle, Dimensions(...), isMovable = false)
and then you can define a function to take any piece and draw it:
def draw(piece: Piece) = piece.shape match {
case Rectangle => ...
case Square => ...
case Circle => ...
}
...and methods for binary functions:
case class Piece(...) {
def collidesWith(other: Piece) = ...
def overlapsWith(other: Piece) = ...
}
then:
draw(immovablePiece)
if (piece1 collidesWith piece2) ...
if (piece1 overlapsWith piece2) ...
You're free to make draw a method of Piece as well, but it doesn't really matter — if you manage to avoid inheritance, all methods become equivalent to plain functions anyway.
There is no need to use inheritance (i.e. subtype polymorphism); it's always best to start out with mathematically purer concepts and avoid extends altogether. If you consider the code I've demonstrated, you'll realise that it gives you a way to compose bits and pieces instead of providing monolithic types; it also allows you to convert one type of piece to another by providing an alternative value for an attribute — this is not possible with inheritance; it's not possible to change the type of an object once created.
val immovableCirclePiece = circularPiece.copy(isMovable = false)
Note that the Shape inheritance tree starting with that sealed trait is not the same as regular inheritance — what it does it defines an Algebraic Data Type, which in this case resembles quite closely what would be an enum in Java.
Furthermore, you could try to extract the data that is relevant to drawing/rendering and put it all in a, say, Representation class that holds both the Point as well as a rendering function to draw specific shapes. Feel free to ask for clarification — there's a lot to say and I'm only trying to get you started with designing your programs in a more sophisticated manner :)
Just write:
class PXClass extends MXClass (0, 0, 0, 0)
Related
I'm trying to dynamically create a chain of functions to perform on a numeric value. The chain is created at runtime from text instructions.
The trick is that the functions vary in what types they produce. Some functions produce a Double, some produce a Long.
Update
The core issue is that I have a massive amount of data to process, but different values require different processing. In addition to the data I have specifications on how to extract and manipulate values to their final form, such as applying a polynomial, using a lookup table, changing the binary format (like 2s Compliment), etc. These specs are in a file of some sort (I'm creating the file form a database, but that's not important to the conversation), and I can apply these specs to multiple data files.
so with functions (these are just exmaples; there are tons of them):
def Multiply(input: Long, factor:Double):Double = input*factor
def Poly(input:Double, co:Array[Double]):Double = // do some polynomial math
I can manually create a chain like this:
val poly = (x: Double) => EUSteps.Poly(x,Array[Double](1,2))
val mult = (x: Long) => EUSteps.Multiply(x, 1.5)
val chain = mult andThen poly
And if I call chain(1) I get 4
Now I want to be able to parse a string like "MULT(1.5);POLY(1,2)" and get that same chain. The idea is that I can define the chain however I want. Maybe its "MULT(1.5);MULT(2);POLY(1,2,3)." for example. So I can make the functions generic, like this:
def Multiply[A](value: A, factor:Double)(implicit num: Numeric[A]) = num.toDouble(value)*factor
def Poly[A](value:A, co:Array[Double])(implicit num: Numeric[A]) = { // do some poly math
Parsing the string isn't hard as it's very simple.
How can I build the chain dynamically?
If it helps, the input is always going to be Long for the first step in the chain. The result could be Long or Double, and I'm OK with it if I have to do two versions based on the end result, so one that goes Long to Long, the other that goes Long to Double.
What I've tried
If I define my functions as having the same signature, like this:
def Multiply(value: Double, factor:Double) = value*factor
def Poly(value:Double, co:Array[Double]) = {
I can do it as part of a map operation:
def ParseList(instruction:String) = {
var instructions = instruction.split(';')
instructions.map(inst => {
val instParts = inst.split(Array(',','(',')'))
val instruction = instParts(0).toUpperCase()
val instArgs = instParts.drop(1).map(arg => arg.toDouble)
instruction match {
case "POLY" => (x: Double) => EUSteps.Poly(x,instArgs)
case "MULTI" => (x: Double) => Multiply(x,instArgs(0))
}
}).reduceLeft((a,b) => a andThen b)
However, that breaks as soon as I change one of the arguments or return types to Long:
def Multiply(value: Long, factor:Double) = value*factor
And change my case
instruction match {
case "POLY" => (x: Double) => EUSteps.Poly(x,instArgs)
case "MULTI" => (x: Long) => Multiply(x,instArgs(0))
}
}).reduceLeft((a,b) => a andThen b)
Now the Reduce is complaining because it wanted Double => Double instead of Long => Double
Update 2
The way I solved it was to do what Levi suggested in the comments. I'm sure this is not very Scala-y, but when in doubt I go back to my OO roots. I suspect there is a more elegant way to do it though.
I declared an abstract class called ParamVal:
abstract class ParamVal {
def toDouble(): Double
def toLong(): Long
}
Then Long and Double types to go with it that implement the conversions:
case class DoubleVal(value: Double) extends ParamVal {
override def toDouble(): Double = value
override def toLong(): Long = value.toLong
}
case class LongVal(value: Long) extends ParamVal {
override def toDouble(): Double = value.toDouble
override def toLong(): Long = value
}
This lets me define all function inputs as ParamVal, and since each one expects a certain input type it's easy to just call toDouble or toLong as needed.
NOTE: The app that creates these instructions already makes sure the chain is correct.
Some ideas:
Analyze the string chain upfront and figure out what will be the type of the final result and then use it for all steps all along. You will need a family of functions for each type.
Try to use Either[Long, Double] in the reduce part.
Lets say i have a class with chaining functions
class Vehicle {
protected var position: (Int, Int) = (0, 0)
def moveLeft(meters: Int): Vehicle = {
position = position._1 - meters -> position._2
this
}
def moveForward(meters: Int): Vehicle = {
position = position._1 -> (position._2 + meters)
this
}
}
so each method returns instance itself
Now i want to inherit Vehicle and add some method to new class
class Helicopter extends Vehicle {
protected var verticalDimension: Int = 0
def flyIntoTheSky(meters: Int): Helicopter = {
verticalDimension += meters
this
}
}
If i will create a new class instance and call any functions from parent, for example
new Helicopter().moveLeft(10).moveForward(20)
i will not be able to call new class method flyIntoTheSky because methods return type is Vehicle, and Vehicle does not know anything about methods of Helicopter.
2 obvious ways to solve it:
Either using asInstanceOf
new Helicopter()
.moveLeft(10)
.moveForward(20).asInstanceOf[Helocopter]
.flyIntoTheSky(10000)
either overriding each and avery parental method in new class
Both ways are not looking nice, i would prefer to leave all this type issues to Vehicle class and forget about it, so i found(as i hoped) the solution, rewriting methods like this
def moveLeft[T](meters: Int, vehicle: T = this): T = {
position = position._1 - meters -> position._2
this.asInstanceOf[T]
}
so i expected that return type will be taken from method's second parameter vehicle, which always equals to default value "this", and will return the value of current type. But unfortunately
new Helicopter().moveLeft(10)
still returns value of type Vehicle
res0: Vehicle = Helicopter#1de81c37
So the first question: why it doesn't work as i expected. And the second: is there are any beautiful way to solve this problem
Thank you
PS In google i found this solution in Java
https://www.andygibson.net/blog/article/implementing-chained-methods-in-subclasses/
, but i dont know java and can not translate it in scala
If the method always returns this you can give it return type this.type.
def moveLeft(meters: Int): this.type = {
position = position._1 - meters -> position._2
this
}
Addressing comment
strange, i cant get sense. If this.type refers to Helicopter why def
moveLeft[T](meters: Int, vehicle: T = this): T refers still to Vehicle
Note that this and this.type exist in two separate worlds, although this.type is "encroaching" on the value world as I will attempt to explain bellow. The former is a value whilst latter is a type, although a special kind of type. The type of expression this is not this.type, instead according to SLS:
The expression this... stands for the object being defined by the innermost
template or compound type enclosing the reference. If this is a
compound type, the type of this is that compound type. If it is a
template of a class or object definition with simple name 𝐶, the type
of this is the same as the type of 𝐶.this.
The innermost enclosing class of this in def moveLeft[T](meters: Int, vehicle: T = this): T is in fact Vehicle, therefore the static type of this is Vehicle.
Now consider type this.type:
this . type
| | |
value dot notation type
\ /
-------------------------------
|
value-dependent type
Notice the dot notation . which is used on a value, that is, if this was not a value then we would use # notation like so this#type. However it is indeed a value, which means type type depends on value this. Now, what value does it depend on? Well, no pun intended, it depends. Given the expression new Helicopter() it depends on the value (object) referred to by new Helicopter(), whilst given the expression new Car() it depends on the value referred to by expression new Car(). Important to understand here is that despite the fact that now this.type seems to be "changing" depending on a value, it is still a static type proper, meaning there is no runtime type-checking shenanigans.
I believe the source of confusion stems from the fact that we know, given new Helicopter(), in both cases, this refers to object of class Helicopter at runtime, however the key is to understand what static types can compiler determine, which in turn yields what members are invokable. In the case of this.type the compiler can determine the narrowest possible value-dependent singleton type uniquely inhabited by this very value.
As a side-note here is my attempt using shapeless lenses:
import shapeless._
case class Position(x: Double, y: Double, z: Double = 0)
sealed trait Vehicle
case class Car(p: Position) extends Vehicle
case class Plane(p: Position) extends Vehicle
object Vehicle {
implicit val carPosLens = lens[Car].p
implicit val planePosLens = lens[Plane].p
}
implicit class Move[T <: Vehicle](v: T) {
def moveX(d: Double)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(x = p.x + d))
def moveY(d: Double)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(y = p.y + d))
}
implicit class Fly[T <: Plane](v: T) {
def moveZ(d: Int)(implicit ev: Lens[T, Position]): T = ev.modify(v)(p => p.copy(z = p.z + d))
}
Plane(Position(0,0,0)).moveX(42).moveY(-3.142).moveZ(11)
Car(Position(0,0)).moveX(1)
which outputs
res0: Plane = Plane(Position(42.0,-3.142,11.0))
res1: Car = Car(Position(1.0,0.0,0.0))
I have a ListBuffer declared like this:
var distances_buffer: ListBuffer[List[Any]] = ListBuffer.empty[List[Any]]
and I am trying to fill it with data like this:
for(current <- 0 to training_list_length - 1){
//A and B are examples
distances_buffer(current) ++= List[Any](A,B)
}
However I get the following error:
java.lang.IndexOutOfBoundsException: 0
What am I missing?
EDIT! More Info:
I have a list (Named: training_list) of points and their class. (x, y, class) :
training_list : List[((Double, Double, String))]
I also have an extra point with a x and a y value given.
My goal is to calculate the euclidean distance of the extra point from each point inside the training list, and create a result which look like this:
//example
List((x: Double, y: Double, class: String), distance: String)
List((4.3,3.0,Iris-setosa), 1.2529964086141665), (4.4,3.0,Iris-setosa), 1.341640786499874)...
As you can see, in the list I want to include the coordinates of the point (from the training_list), the class of the point and also the distance.
for(current <- 0 to training_list_length - 1){
val dist = eDistance(test_x, test_y, training_x(current), training_y(current))
distances_buffer += ListBuffer[Any](training_result(current),dist)
}
After the creation of this list I want to sort it based on the distances. Also stuck here!
It seems, for the way you name things, that you come from a Python background.
I would advice you to study a little bit about Scala first, since we are very different.
Not only on style things (like camel case vs dash case), but on more fundamental things like:
A strong and static type system. Thus, things like Any are usually a code smell and for 99.99% of cases, completely unnecessary.
A mix between OOP & FP. So, you do not necessary have to become an FP expert, but there some things that are idiomatic even in the OOP side of Scala, like immutability and common operations (higher order functions) like map, flatMap, filter & reduce.
Our List is very different from the Python one, accessing an element by index is O(n) (in Python it would be O(1)). A Python list is more like an Array that can be resized.
Also, we do not really have a for loop. We have something called for comprehension which is nothing more than syntactic sugar for calls to map, flatMap, filter & in some cases foreach.
The list could go on, but I think my point is clear.
Scala is not only new syntax, is a different way to program.
Anyways, here is an idiomatic way to solve your problem.
(Not necessary this is the best way, there are many variations that can be done)
// First lets create some custom types / classes to represent your data.
final case class Point(x: Double, y: Double)
final case class ClassifiedPoint(point: Point, clazz: String)
// Lets define the Euclidean distance function.
def euclideanDistance(p1: Point, p2: Point): Double =
math.sqrt(
math.pow((p1.x - p2.x), 2) +
math.pow((p1.y - p2.y), 2)
)
}
// This is what you need.
// Note that I made it somewhat more generic that is has to be.
// For example, instead of using the euclidean distance function directly on the body,
// we receive the distance function to use.
// Also, I use a technique called currying to split the arguments in different lists,
// This allows the caller to partially apply them.
def computeDistance(distanceFun: (Point, Point) => Double)
(trainingList: List[ClassifiedPoint])
(referencePoint: Point): List[(ClassifiedPoint, Double)] =
trainingList.map { classifiedPoint =>
val distance = distanceFun(classifiedPoint.point, referencePoint)
classifiedPoint -> distance
}
Which you can use like this.
val trainingList = List(
ClassifiedPoint(Point(x = 4.3d, y = 3.0d), clazz = "Iris-setosa"),
ClassifiedPoint(Point(x = 4.4d, y = 3.0d), clazz = "Iris-setosa")
)
// Partial application to create a new function.
val computeEuclideanDistance = computeDistance(euclideanDistance) _
computeEuclideanDistance(trainingList, Point(x = 3.0d, y = 0.0d))
// res: List[(ClassifiedPoint, Double)] =
// List(
// (ClassifiedPoint(Point(4.3, 3.0), "Iris-setosa"), 3.269556544854363),
// (ClassifiedPoint(Point(4.4, 3.0), "Iris-setosa"), 3.3105890714493698)
// )
As suggested by Luis, Any and var are to be avoided if possible, so here is an example that might nudge you to consider a different approach
case class Point(x: Double, y: Double, `class`: String)
def distance(a: Point, b: Point): Double =
math.hypot(a.x - b.x, a.y - b.y)
val targetPoint = Point(1,2,"Extra-point")
val training_list : List[((Double, Double, String))] = List((4.3,3.0,"Iris-setosa"), (4.4,3.0,"Iris-setosa"))
val points = training_list.map(Point.tupled)
val unsortedPoints: List[(Point, Double)] = points.map(point => (point, distance(point, targetPoint)))
unsortedPoints.sortBy(_._2)
which outputs
res0: List[(Point, Double)] = List((Point(4.3,3.0,Iris-setosa),3.4481879299133333), (Point(4.4,3.0,Iris-setosa),3.5440090293338704))
I have copied distance calculation from Xavier.
I am trying to make a RDD of k-nearest neighbors from points inside each Bounding Box. I have these case classes inside the object KNN:
object KNN extends App{
def buildtree(points: Seq[Seq[T]], depth: Int = 0): Option[KdNode[T]]
case class BoundingBox[T](lowerleft_X: T, lowerleft_Y: T, upperright_X: T, upperright_Y: T)
case class KdNode[T](value: Seq[T], left: Option[KdNode[T]], right: Option[KdNode[T]], axis: Int)
{
def Knearest(to: Seq[T]): Seq[Nearest[T]] = {....}
}
case class Nearest[T](value: Seq[T], to: Seq[T], distance: Double)
}
First, I made a Pair RDD of kdtree with key = BoundingBox and Value = Option[KdNode[T]] by using the below line of code. Here, buildtree is a function defined inside the object and PointsRDD is also a PairRDD. This works fine:
val kdtree = PointsRDD.mapValues(p => buildtree(p))
Type of kdtree is RDD[BoundingBox[T],Option[KdNode[T]].
Then, when I try to call the Knearest function on kdtree, the Knearest symbol is not recognized.
I am trying to call Knearest using mapValues and also tried it in a for loop, but both approaches do not work, that is it gives the error "cannot resolve symbol Knearest" (error for both; for loop and mapValues)
val knn = kdtree.mapValues(node => Knearest(node))
for (kd <- kdtree; knearest = kd Knearest to)
where, to is the point from which k-nearest neighbors are to be searched.
I am doing something wrong here, but I cannot figure out what, since I am fairly new to Scala. Please help in this regard. Thanks.
I have the something akin to the following code (only with more parameters) in a program I am developing:
class Particle {
//variables
def this(position: Position2D, velocity: Vector2D) = {
this()
//constructors
}
def this(xPos: Double, yPos: Double, magnitude: Double, angle: Double) = {
this(new Position2D(xPos, yPos), new Vector2D(magnitude, angle))
}
}
And I would like to make it so that the program is able to accept the Position2D object for the first parameter and two Doubles for the second parameter, or two Doubles for the first parameter and a Vector2D object for the 2nd parameter, without creating more this statements for each combination of parameters. I know that it's possible to use something like:
def this(posObj: Either[Position2D, Array[Double]], velObj: Either[Vector2D, Array[Double]]) = {...}
And then test to see what type posObj and velObj are; however, I was curious if there was a way to do this without requiring the 2nd part of the Either to be just one item such as an Array, so that you could initialize Particle like the following:
val a = new Particle(new Position(3, 6), 30, 5)
val b = new Particle(3, 6, new Vector2D(30, 5))
val c = new Particle(new Position(3, 6), new Vector2D(30, 5))
val d = new Particle(3, 6, 30, 5)
The short answer is no, the constructors are rigid in the sense that the number of parameters (assuming you don't want them in a Seq) for a method (or constructor in this case) has to be quite specific.
Potentially by enclosing the naked pairs in a Tuple2 and creating a typeclass instance to unpack each this would be possible, but it would be an order of magnitude more complicated than just adding the constructors.
A possible solution for this would be to create your class with 2 parameter lists in the constructor, one taking the Position2D and one taking the Vector2D and then create implicit conversions from Tuple2 to both of them:
case class Vector2D(x: Double, y: Double)
case class Position2D(x: Double, y: Double)
implicit def tuple2Vector2D(t: (Double,Double)): Vector2D = Vector2D(t._1, t._2)
implicit def tuple2Position2D(t: (Double,Double)): Position2D = Position2D(t._1, t._2)
class Particle(val v: Vector2D)(val p: Position2D)
scala> new Particle(1.1,3.1)(6.1,0.3)
res15: Particle = Particle#15a74f84
scala> new Particle(new Vector2D(1.1,3.1))(6.1,0.3)
res16: Particle = Particle#47283198
scala> new Particle(1.1,3.1)(new Position2D(6.1,0.3))
res17: Particle = Particle#2571e404
scala> new Particle(new Vector2D(1.1,3.1))(new Position2D(6.1,0.3))
res18: Particle = Particle#38be7bc0