I'm trying to create a tree object and find the height of a TreeNode but I'm having trouble figuring out how to run the code.
class Tree[A] {
class TreeNode(var _value: A, var _left: TreeNode,
var _right: TreeNode)
def height(root: TreeNode) = {
def helper(curr: TreeNode, d: Int): Int = {
if (root == null) d
else {
val leftDepth = helper(curr._left,d+1)
val rightDepth = helper(curr._right,d+1)
leftDepth max rightDepth
}
}
helper(root,-1)
}
}
def main(args: Array[String]) : Unit = {
var a: Tree[Int] = new Tree()
a.height(10)
}
I'm getting the error:
Type mismatch, Required: Tree[Int]#TreeNode
Found: Int
and I'm not sure how to create a TreeNode that can be passed to height along with the helper to calculate the height
Related
I have an array of Any (in real life, it's a Spark Row, but it's sufficient to isolate the problem)
object Row {
val buffer : Array[Any] = Array(42, 21, true)
}
And I want to apply some operations on its elements.
So, I've defined a simple ADT to define a compute operation on a type A
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
Given that I have a list of all operations and I know which operation is to apply to each element, let's use these operations.
object GenericsOp {
import Row._
val ops = Seq(Count, Exist)
def compute() = {
buffer(0) = ops(0).compute(ops(0).cast(buffer(0)))
buffer(1) = ops(0).compute(ops(0).cast(buffer(1)))
buffer(2) = ops(1).compute(ops(1).cast(buffer(2)))
}
}
By design, for a given op, types are aligned between cast and combine. But unfortunately the following code does not compile. The error is
Type mismatch, expected: _$1, actual: AnyVal
Is there a way to make it work ?
I've found a workaround by using abstract type member instead of type parameter.
object AbstractOp extends App {
import Row._
trait Op {
type A
def compute(a: A) : A
}
case object Count extends Op {
type A = Int
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op {
type A = Boolean
override def compute(a: Boolean): Boolean = a
}
val ops = Seq(Count, Exist)
def compute() = {
val op0 = ops(0)
val op1 = ops(1)
buffer(0) = ops(0).compute(buffer(0).asInstanceOf[op0.A])
buffer(1) = ops(0).compute(buffer(1).asInstanceOf[op0.A])
buffer(2) = ops(1).compute(buffer(2).asInstanceOf[op1.A])
}
}
Is there a better way ?
It seems that your code can be simplified by making Op[A] extend Any => A:
trait Op[A] extends (Any => A) {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
def apply(a: Any): A = compute(cast(a))
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i)(buffer(i))
}
println(buffer.mkString("[", ",", "]"))
}
}
Since it's asInstanceOf everywhere anyway, it does not make the code any less safe than what you had previously.
Update
If you cannot change the Op interface, then invoking cast and compute is a bit more cumbersome, but still possible:
trait Op[A] {
def cast(a: Any) : A = a.asInstanceOf[A]
def compute(a: A) : A
}
case object Count extends Op[Int] {
override def compute(a: Int): Int = a + 1
}
case object Exist extends Op[Boolean] {
override def compute(a: Boolean): Boolean = a
}
object AbstractOp {
val buffer: Array[Any] = Array(42, 21, true)
val ops: Array[Op[_]] = Array(Count, Count, Exist)
def main(args: Array[String]): Unit = {
for (i <- 0 until buffer.size) {
buffer(i) = ops(i) match {
case op: Op[t] => op.compute(op.cast(buffer(i)))
}
}
println(buffer.mkString("[", ",", "]"))
}
}
Note the ops(i) match { case op: Opt[t] => ... } part with a type-parameter in the pattern: this allows us to make sure that cast returns a t that is accepted by compute.
As a more general solution than Andrey Tyukin's, you can define the method outside Op, so it works even if Op can't be modified:
def apply[A](op: Op[A], x: Any) = op.compute(op.cast(x))
buffer(0) = apply(ops(0), buffer(0))
Say I have this situation
class Pipe {
var vel = 3.4
var V = 300
var a = 10.2
var in = ???
var TotV = V+in
var out = TotV*a/vel
}
val pipe1 = new Pipe
val pipe2 = new Pipe
The in variable is were my problem is, what i'd like to do is get the out variable from pipe1 and feed that in as the in variable for pipe 2 effectively to join the two pipes but I cant figure out if this is even possible in the same class. So I can do it manually but need to know if its possible to do in the class.
pipe2.in = pipe1.out
my attempted fix was to add an ID field then try and use that to reference an instance with a higher id field but that doesnt seem doable. ie
class Pipe(id:Int) {
var vel = 3.4
var V = 300
var a = 10.2
var in = Pipe(id+1).out //this is the sticking point, I want to reference instances of this class and use their out value as in value for instances with a lower ID
var TotV = V+in
var out = TotV*a/vel
}
any help would be appreciated
You can do this by defining a companion object for the class and passing in the upstream pipe as an optional parameter to the factory method, then extracting its in value and passing it to the class constructor, as follows:
object Pipe {
def apply(upstreamPipe: Option[Pipe]): Pipe = {
val inValue = upstreamPipe match {
case Some(pipe) => pipe.out
case None => 0 // or whatever your default value is
new Pipe(inValue)
}
You would then call
val pipe1 = Pipe(None)
val pipe2 = Pipe(Some(pipe1))
Unfortunately your question is not clear now. Under certain assumptions what you describe looks like what is now called "FRP" aka "Functional Reactive Programming". If you want to do it in a serious way, you probably should take a look at some mature library such as RxScala or Monix that handle many important in the real world details such as error handling or scheduling/threading and many others.
For a simple task you might roll out a simple custom implementation like this:
trait Observable {
def subscribe(subscriber: Subscriber): RxConnection
}
trait RxConnection {
def disconnect(): Unit
}
trait Subscriber {
def onChanged(): Unit
}
trait RxOut[T] extends Observable {
def currentValue: Option[T]
}
class MulticastObservable extends Observable with Subscriber {
private val subscribers: mutable.Set[Subscriber] = mutable.HashSet()
override def onChanged(): Unit = subscribers.foreach(s => s.onChanged())
override def subscribe(subscriber: Subscriber): RxConnection = {
subscribers.add(subscriber)
new RxConnection {
override def disconnect(): Unit = subscribers.remove(subscriber)
}
}
}
abstract class BaseRxOut[T](private var _lastValue: Option[T]) extends RxOut[T] {
private val multicast = new MulticastObservable()
protected def lastValue: Option[T] = _lastValue
protected def lastValue_=(value: Option[T]): Unit = {
_lastValue = value
multicast.onChanged()
}
override def currentValue: Option[T] = lastValue
override def subscribe(subscriber: Subscriber): RxConnection = multicast.subscribe(subscriber)
}
class RxValue[T](initValue: T) extends BaseRxOut[T](Some(initValue)) {
def value: T = this.lastValue.get
def value_=(value: T): Unit = {
this.lastValue = Some(value)
}
}
trait InputConnector[T] {
def connectInput(input: RxOut[T]): RxConnection
}
class InputConnectorImpl[T] extends BaseRxOut[T](None) with InputConnector[T] {
val inputHolder = new RxValue[Option[(RxOut[T], RxConnection)]](None)
private def updateValue(): Unit = {
lastValue = for {inputWithDisconnect <- inputHolder.value
value <- inputWithDisconnect._1.currentValue}
yield value
}
override def connectInput(input: RxOut[T]): RxConnection = {
val current = inputHolder.value
if (current.exists(iwd => iwd._1 == input))
current.get._2
else {
current.foreach(iwd => iwd._2.disconnect())
inputHolder.value = Some(input, input.subscribe(() => this.updateValue()))
updateValue()
new RxConnection {
override def disconnect(): Unit = {
if (inputHolder.value.exists(iwd => iwd._1 == input)) {
inputHolder.value.foreach(iwd => iwd._2.disconnect())
inputHolder.value = None
updateValue()
}
}
}
}
}
}
abstract class BaseRxCalculation[Out] extends BaseRxOut[Out](None) {
protected def registerConnectors(connectors: InputConnectorImpl[_]*): Unit = {
connectors.foreach(c => c.subscribe(() => this.recalculate()))
}
private def recalculate(): Unit = {
var newValue = calculateOutput()
if (newValue != lastValue) {
lastValue = newValue
}
}
protected def calculateOutput(): Option[Out]
}
case class RxCalculation1[In1, Out](func: Function1[In1, Out]) extends BaseRxCalculation[Out] {
private val conn1Impl = new InputConnectorImpl[In1]
def conn1: InputConnector[In1] = conn1Impl // show to the outer world only InputConnector
registerConnectors(conn1Impl)
override protected def calculateOutput(): Option[Out] = {
for {v1 <- conn1Impl.currentValue}
yield func(v1)
}
}
case class RxCalculation2[In1, In2, Out](func: Function2[In1, In2, Out]) extends BaseRxCalculation[Out] {
private val conn1Impl = new InputConnectorImpl[In1]
def conn1: InputConnector[In1] = conn1Impl // show to the outer world only InputConnector
private val conn2Impl = new InputConnectorImpl[In2]
def conn2: InputConnector[In2] = conn2Impl // show to the outer world only InputConnector
registerConnectors(conn1Impl, conn2Impl)
override protected def calculateOutput(): Option[Out] = {
for {v1 <- conn1Impl.currentValue
v2 <- conn2Impl.currentValue}
yield func(v1, v2)
}
}
// add more RxCalculationN if needed
And you can use it like this:
def test(): Unit = {
val pipe2 = new RxCalculation1((in: Double) => {
println(s"in = $in")
val vel = 3.4
val V = 300
val a = 10.2
val TotV = V + in
TotV * a / vel
})
val in1 = new RxValue(2.0)
println(pipe2.currentValue)
val conn1 = pipe2.conn1.connectInput(in1)
println(pipe2.currentValue)
in1.value = 3.0
println(pipe2.currentValue)
conn1.disconnect()
println(pipe2.currentValue)
}
which prints
None
in = 2.0
Some(905.9999999999999)
in = 3.0
Some(909.0)
None
Here your "pipe" is RxCalculation1 (or other RxCalculationN) which wraps a function and you can "connect" and "disconnect" other "pipes" or just "values" to various inputs and start a chain of updates.
I need to implement function to. I have the following working code:
object Main {
val m = 0
val km = 1
implicit def wrapM(v: Int) = new {
def m = v
}
implicit def wrapKm(v: Int) = new {
def km = v * 1000
}
implicit class toWrap(fromVal: Int) {
def too (value: Int): Double = {
if (value.equals(km)) {
fromVal / 1000.0
} else {
0
}
}
}
def main(args:Array[String])
{
println(53.m too km)
}
}
But there is one problem. I use too name, instead of to. If I rename it to to, then I get the error:
Error:(30, 16) type mismatch;
found : Int
required: ?{def to(x$1: ? >: Int): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method intWrapper in class LowPriorityImplicits of type (x: Int)scala.runtime.RichInt
and method toWrap in object Main of type (fromVal: Int)Main.toWrap
are possible conversion functions from Int to ?{def to(x$1: ? >: Int): ?}
println(53.m to km)
^
It is due to the fact, that there is one other function to - scala.runtime.RichInt#to.
Scala does not allow define two implicits with same arguments set in one context....
But there is a way. You should work with different type in toWrap implicit , instead of standard scala Int.
Check sample below.
My idea is to implement method to for some wrapper class IntWrap instead of standard Int
case class IntWrap(v: Int) {
}
val m = 0
val km = 1
implicit def wrapM(v: Int) = new {
def m = IntWrap(v)
}
implicit def wrapKm(v: Int) = new {
def km = v * 1000
}
implicit class toWrap(fromVal: IntWrap) {
def to(value: Int): Double = {
if (value.equals(km)) {
fromVal.v / 1000.0
} else {
0
}
}
}
def main(args:Array[String])
{
println(53.m to km)
}
This is what I tried. Depends on what does user put into the function I want to add String or Double to new Chunk.
package org.apache.spark.h2o.utils
import water.fvec.{NewChunk, Frame, Chunk}
import water._
import water.parser.ValueString
class ReplaceNa[T >: Any](a: T) extends MRTask{
override def map(c: Chunk, nc: NewChunk): Unit = {
for (row <- 0 until c.len()) {
a match{
case s: ValueString if(c.isNA(row)) => nc.addStr(s)
case d: Double if(c.isNA(row)) => nc.addNum(d)
}
}
}
}
But I got error
error: value outputFrame is not a member of Nothing
pred.add(new ReplaceNa(3).doAll(1, pred.vec(4)).outputFrame(Array("s"), null))
Thanks for your help!
I have several comments:
check for NA outside the switch branch
you are missing non-NA case hence you are generating vector which is shorter than input vector (i expect you would like to generate the same length vector)
Regarding generics, you need to provide type specialization. For example, something like the following snippet:
class ReplaceNA[T](val value: T)(implicit add: TAdd[T]) extends MRTask[ReplaceNA[T]] {
override def map(c: Chunk, nc: NewChunk): Unit = {
for (row <- 0 until c.len()) {
// Replace NAs by given value
if (c.isNA(row)) {
add.addValue(nc, value)
} else {
// Do something with default value
nc.addNA()
}
}
}
}
trait TAdd[T] extends Serializable {
def addValue(nc: NewChunk, value: T)
}
object TAdd extends Serializable {
implicit val addDouble = new TAdd[Double] { def addValue(nc: NewChunk, value: Double) = nc.addNum(value) }
implicit val addFloat = new TAdd[Float] { def addValue(nc: NewChunk, value: Float) = nc.addNum(value) }
implicit val addValueString = new TAdd[ValueString] { def addValue(nc: NewChunk, value: ValueString) = nc.addStr(value) }
}
In response to my question How to develop macro to short-circuit null? someone pointed me to an earlier long thread with many answers, the most compelling of which to was https://stackoverflow.com/a/5569905 . But it doesn't quite work with Scala AnyVal "primitives" like Int:
object TestOp {
class SafeDereference[A](obj: A) {
def ?[B >: Null](function: A => B): B = if (obj == null) null else function(obj)
}
implicit def safeDereference[A](obj: A) = new SafeDereference(obj)
class C {
def getValue: Int = 0
}
def main(args: Array[String]) {
val c = new C
val x:Int = c ? (_.getValue)
}
}
gives a compilation error of:
[error] TestOp.scala:14: type mismatch;
[error] found : Any
[error] required: Int
[error] val x:Int = c ? (_.getValue)
[error] ^
[error] one error found
[error] {file:/home/mmalak/streaming-demo/}default-ae36bd/compile:compile: Compilation failed
A workaround is to replace val x:Int with val x:java.lang.Integer, and that will compile. Is there a way to improve SafeDereference above so that val x:Int is allowed?
Additional information
The following produces the desired output. The question now becomes how to move the typecasts into SafeDereference, and how to handle all the other Scala "primitives" (Boolean etc).
object TestOp {
class SafeDereference[A](obj: A) {
def ?[B >: Null](function: A => B): B = if (obj == null) null else function(obj)
}
implicit def safeDereference[A](obj: A) = new SafeDereference(obj)
class C {
def getValue: Int = 0
}
def main(args: Array[String]) {
val c:C = null
val x = (c ? (_.getValue)).asInstanceOf[java.lang.Integer].asInstanceOf[Int]
println("x="+x)
}
}
outputs, as desired:
x=0
You could do something like this. The Zero trait allows you to determine the zero value for any object that is not nullable. In this case I added one for Numeric types:
object TestOp {
trait Zero[T] {
def apply(): T
}
object Zero {
implicit def zeroNull[B >: Null] =
new Zero[B] { def apply = null }
implicit def zeroNumeric[B: Numeric] =
new Zero[B] { def apply = implicitly[Numeric[B]].zero }
}
implicit class SafeDereference[A](obj: A) {
def ?[B](function: A => B)(implicit zero: Zero[B]): B =
if (obj == null) zero() else function(obj)
}
class C {
def getValue: Int = 0
def getSomething: C = new C
}
def main(args: Array[String]) {
val c = new C
val x = c ? (_.getValue)
val y = c ? (_.getSomething)
}
}
Edit
For Boolean you would add something like this:
implicit def zeroBoolean[B >: Boolean] =
new Zero[B] { def apply = false }