Setting instance vars with apply - scala

With Array it's possible to get and set elements with val i = xs(0) and xs(0) = i syntax. How to implement this functionality in my own class? So far I was only able to implement getting the values.
class Matrix(val m : Int, val n : Int) {
val matrix = Array.ofDim[Double](m, n)
def apply(i:Int)(j:Int) = matrix(i)(j)
}
UPDATE: Thanks to Mauricio for answer about update method. That's the final version
class Matrix(val m:Int, val n:Int) {
private val matrix = Array.ofDim[Double](m, n)
def apply(i:Int) = new {
def apply(j:Int) = matrix(i)(j)
def update(j:Int, v:Double) = { matrix(i)(j) = v }
}
}
it("matrix") {
val m = new Matrix(3, 3)
m(0)(1) = 10.0
val x = m(0)(1)
x should equal(10.0)
x.isNegInfinity should be (false) // Implicits for Double work!
}

You need to declare an update method:
class Matrix(val m : Int, val n : Int) {
private val matrix = Array.ofDim[Double](m, n)
def apply(i:Int)(j:Int) = matrix(i)(j)
def update( i : Int, j : Int, value : Double) {
matrix(i)(j) = value
}
}
val m = new Matrix( 10, 10 )
m(9, 9) = 50

Related

Cannot create constructor with logic in Scala program?

I have the following program:
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
this(num, 1) // problem here
else
this(num, input(1).toInt) // problem here
}
}
I tried to create the constructor with some logic. However, I cannot due to
'Rational' does not take parameters
What's the problem?
Try to introduce a helper method
import scala.util.matching.Regex
def gcd(i: Int, i1: Int): Int = BigInt(i).gcd(BigInt(i1)).toInt
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
def this(n: Int) = this(n, 1)
def this(s: String) = {
this(Rational.transformStr(s)._1, Rational.transformStr(s)._2)
}
}
object Rational {
// helper method
def transformStr(s: String): (Int, Int) = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
(num, 1)
else
(num, input(1).toInt)
}
}
or better, factory methods (because constructors have many limitations)
class Rational(n: Int, d: Int) {
require(d != 0)
private val g = gcd(n.abs, d.abs)
val numer = n / g
val denom = d / g
}
object Rational {
// factory methods
def apply(n: Int) = new Rational(n, 1)
def apply(s: String): Rational = {
val regex: Regex = "^([+-]?(\\d+|\\d*\\.?\\d+)|\\d*\\/?\\d+)$".r
if (!regex.matches(s)) throw new NumberFormatException()
val input: Array[String] = s.split("\\.|\\/")
val num: Int = input(0).toInt
if (input.length equals 1)
new Rational(num, 1)
else
new Rational(num, input(1).toInt)
}
}
Executing code in overloaded constructor prior to calling this()
By the way, you can also use default values
class Rational(n: Int, d: Int = 1 /*default*/ ) {
// ...
}
object Rational {
def apply(s: String): Rational = ???
}

How to pass a scala class as an object into a function parameter?

How do I run the refint1 function? I've triedvar x = new RefInt(5) and then doing scala> argpass.refint1(x)but get a found: RefInt, required : argpass.RefInt => Unit error in the console.
object argpass{
class RefInt (initial : Int) {
private var n : Int = initial
def get () : Int = n
def set (m : Int) : Unit = { n = m}
}
def refint1 ( f: RefInt => Unit) : (Int, Int, Int) = {
var x = new RefInt(5)
val first = f(x)
val firstget = x.get
val sec = f(x)
val secget = x.get
val third = f(x)
val thirdget = x.get
(firstget, secget, thirdget)
}
//How do i run the refint1 function?
As Luis said in the comments, f returns Unit, which is basically void. This should solve your problem:
class RefInt(initial: Int) {
var n: Int = initial
def get(): Int = n
def set(m: Int): Unit = { n = m }
}
def refint1(f: RefInt => Unit): (Int, Int, Int) = {
var x = new RefInt(5)
f(x)
val firstget = x.get
f(x)
val secget = x.get
f(x)
val thirdget = x.get
(firstget, secget, thirdget)
}
That being said, I think you can improve your design a little bit. Here's a different approach to solve the same problem:
case class RefInt(initial: Int)
def refInt1(initial: RefInt, f: RefInt => RefInt) : (Int, Int, Int) = {
val x0 = f(initial)
val x1 = f(x0)
val x2 = f(x1)
(x0.initial, x1.initial, x2.initial)
}
println(refInt1(RefInt(5), ri => ri.copy(ri.initial * 2)))

scala trait members and derivated variables

Hi am trying to write a simple hill climbing algorithm in scala .
I have State and HillClimbing that are traits.
I define them as concrete classes when I apply them to the Graph problem.
In GraphHillClimbing I receive two errors. This is because I use GraphState instead of State (observe that GraphState is also a State).
How can I solve this?
trait State {
val loc = 0
def neighbours: List[State]
def get_loc():Int = return loc
}
class GraphState(loc:Int, g: Map[Int, List[Int]]) extends State {
def neighbours():List[GraphState] =
{
def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
{
if(l.isEmpty) acc
else {
val new_neig = new GraphState(l.head, g)
neighboursAcc(l.tail, List(new_neig) ++ acc, g)
}
}
neighboursAcc(g(loc), List(), g)
}
}
trait HillClimbing {
val max_iteration = 4
val start:State
def cost(state:State):Double
private def argmin(costs:List[Double]):Int = {
val best = costs.min
costs.indexOf(best)
}
private def next_best(states:List[State]):State = {
val costs = states map(x => cost(x))
val pos = argmin(costs)
states(pos)
}
def minimize():State = {
def minimizeAcc(iteration:Int, state:State):State =
{
if(iteration > max_iteration) state
else {
val neigs = state.neighbours
val next_state = next_best(neigs)
minimizeAcc(iteration+1, next_state)
}
}
minimizeAcc(0, start)
}
}
class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {
// ERROR 1 = start was State and now it is GraphState
// ERROR 2 = cost should take a State
def cost(current_state:GraphState):Double = {
val distance = goal.get_loc() - current_state.get_loc()
if(distance > 0 ) distance
else -distance
}
}
object RunHillClimbing {
def main(args: Array[String]) {
val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))
val start = new GraphState(1, G)
val goal = new GraphState(6, G)
val hc = new GraphHillClimbing(start, goal)
print(hc.minimize())
}
}
I think this can be solved using some type parameters with type bounds.
Also in your constructor for GraphHillClimbing you should use val to indicate that the parameter start is the concrete implementation of the abstract start.
trait State[+Self] {
Self =>
def loc:Int
def neighbours: List[Self]
def get_loc():Int = return loc
}
class GraphState(val loc:Int, g: Map[Int, List[Int]]) extends State[GraphState] {
def neighbours():List[GraphState] =
{
def neighboursAcc(l:List[Int], acc:List[GraphState], g:Map[Int, List[Int]]):List[GraphState] =
{
if(l.isEmpty) acc
else {
val new_neig = new GraphState(l.head, g)
neighboursAcc(l.tail, List(new_neig) ++ acc, g)
}
}
neighboursAcc(g(loc), List(), g)
}
}
trait HillClimbing[T<:State[T]] {
val max_iteration = 4
val start:T
def cost(state:T):Double
private def argmin(costs:List[Double]):Int = {
val best = costs.min
costs.indexOf(best)
}
private def next_best(states:List[T]):T = {
val costs = states map(x => cost(x))
val pos = argmin(costs)
states(pos)
}
def minimize():T = {
def minimizeAcc(iteration:Int, state:T):T =
{
if(iteration > max_iteration) state
else {
val neigs = state.neighbours
val next_state = next_best(neigs)
minimizeAcc(iteration+1, next_state)
}
}
minimizeAcc(0, start)
}
}
class GraphHillClimbing(val start:GraphState, goal:GraphState) extends HillClimbing[GraphState] {
def cost(current_state:GraphState):Double = {
val distance = goal.get_loc() - current_state.get_loc()
if(distance > 0 ) distance
else -distance
}
}
object RunHillClimbing {
def main(args: Array[String]) {
val G = Map[Int, List[Int]](1->List(2, 4, 5), 2->List(1, 3, 4), 3->List(2, 6), 4->List(1, 2, 5), 5->List(1, 4), 6->List(3))
val start = new GraphState(1, G)
val goal = new GraphState(6, G)
val hc = new GraphHillClimbing(start, goal)
print(hc.minimize())
}
}
What I get:
error: class GraphHillClimbing needs to be abstract, since:
it has 2 unimplemented members.
/** As seen from class GraphHillClimbing, the missing signatures are as follows.
* For convenience, these are usable as stub implementations.
*/
def cost(state: this.State): Double = ???
val start: this.State = ???
class GraphHillClimbing(start:GraphState, goal:GraphState) extends HillClimbing {
^
Replace GraphState in the class with State, because inheritance
demands you'll have to handle State not GraphState.
Then replace
val loc = 0
with
def loc = 0
So you can overwrite it in GraphState.

apply method is not being called

I have a break point set at line s = new Array(capacity) but it seems like the apply method is not being called. Have I implemented it correctly ?
object StacksAndQueuesTest {
def main(args: Array[String]) {
val f = new FixedCapacityStackOfStrings(3)
println(f.isEmpty);
}
}
class FixedCapacityStackOfStrings(capacity : Int) {
var s : Array[String] = _
var N : Int = 0
def isEmpty : Boolean = {
N == 0
}
def push(item : String) = {
this.N = N + 1
s(N) = item
}
def pop = {
this.N = N - 1
val item : String = s(N)
/**
* Setting this object to null so
* that JVM garbage collection can clean it up
*/
s(N) = null
item
}
object FixedCapacityStackOfStrings {
def apply(capacity : Int){
s = new Array(capacity)
}
}
}
In your case the companion object may not be of much help except to avoid newoperator
class FixedCapacityStackOfStrings(capacity: Int) {
var s: Array[String] = new Array(capacity)
var N: Int = 0
def isEmpty: Boolean = {
N == 0
}
def push(item: String) = {
this.N = N + 1
s(N) = item
}
def pop = {
this.N = N - 1
val item: String = s(N)
/**
* Setting this object to null so
* that JVM garbage collection can clean it up
*/
s(N) = null
item
}
}
object FixedCapacityStackOfStrings {
def apply(capacity: Int) = {
println("Invoked apply()")
new FixedCapacityStackOfStrings(capacity)
}
def main(args: Array[String]){
val f = FixedCapacityStackOfStrings(5)
println(f)
}
}
And then you can use it like
val f = FixedCapacityStackOfStrings(5)
For the calling object 'FixedCapacityStackOfStrings' to see the .isEmpty method I needed to use :
def apply(capacity: Int) : FixedCapacityStackOfStrings = {
new FixedCapacityStackOfStrings(capacity)
}
instead of
def apply(capacity: Int) {
new FixedCapacityStackOfStrings(capacity)
}

Topological sorting of lists related to a graph in Scala

I have a graph structure as follows:
class Graph {
private var nodes: Set[Node] = Set.empty[Node]
def addEdges(edges: (Node, Node)*) {
for ((a, b) <- edges) {
nodes ++= List(a, b)
a addDst b
}
}
override def toString = {
val sb = new StringBuilder
for (node <- nodes if node.dst.toList.sortWith(ordered).nonEmpty)
sb ++= "%s -> %s\n" format (node.toString, node.dst.mkString(", "))
sb.toString
}
def ordered(a: Node, b: Node): Boolean = {
var dst = a.dst
while (dst.nonEmpty) {
if (dst contains b)
return true
dst = dst.flatMap(_.dst)
}
return false
}
}
trait Node {
def dst = _dst
private var _dst: Set[Node] = Set.empty[Node]
def addDst(that: Node) {
this._dst += that
}
}
class CharNode(val n: Char) extends Node {
override def toString = n.toString
}
Now I want to sort a list containing other class instances which contain nodes topologically related to the graph:
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sortWith { case (o1, o2) => graph.ordered(o1.node, o2.node) }.mkString("\n"))
}
I'm using sortWith on a List with the ordered-method of the graph.
The output is:
Other(wb2,f)
Other(wa1,d)
Other(wb1,e)
this is wrong, because f is after e in the graph.
So why is this wrong? Is the ordered-method wrong? Or did I do other mistakes?
Thanks in advance.
If you quickly "debug" your Graph.ordered method:
def ordered(a: Node, b: Node): Boolean = {
println("[ordered] a = %s, b = %s".format(a, b))
var dst = a.dst
while (dst.nonEmpty) {
if (dst contains b)
return true
dst = dst.flatMap(_.dst)
}
return false
}
you'll notice that f and e are not compared directly:
[ordered] a = d, b = f
[ordered] a = f, b = d
[ordered] a = e, b = d
[ordered] a = d, b = e
Taking the comment of MvG into account, I assume that this is due to the assumption that the ordering is total - which yours isn't. However, I wasn't able to find a reference that makes this assumption explicit, neither for any SeqLike method, which is where sortWith comes from, nor for java.util.Arrays.sort, which sortWith seems to use internally.
I came up with implementing an Ordering based on an topological sort of the graph:
object Main extends App {
val graph = new Graph
val d = new CharNode('d')
val e = new CharNode('e')
val f = new CharNode('f')
val g = new CharNode('g')
val i = new CharNode('i')
val l = new CharNode('l')
graph.addEdges(
d -> l,
e -> i,
i -> f,
f -> g
)
case class Other(s: String, node: Node)
val other = List(Other("wb2", f), Other("wa1", d), Other("wb1", e))
println(other.sorted(graph.ordering[Other](_.node)).mkString("\n"))
}
class Graph {
private var nodes: Set[Node] = Set.empty[Node]
def addEdges(edges: (Node, Node)*) {
for ((a, b) <- edges) {
nodes ++= List(a, b)
a addDst b
}
}
def ordering[T](f: T => Node = (x: Node) => x) = {
import collection.mutable
val inDegrees = mutable.HashMap.empty ++ nodes.map(n => n -> n.src.size)
val sorted = new mutable.ListBuffer[Node]()
val zeroInDegree = mutable.Stack[Node]()
zeroInDegree pushAll inDegrees.filter(_._2 == 0).keys
while (zeroInDegree.nonEmpty) {
val next = zeroInDegree.pop
sorted += next
for (after <- next.dst) {
val count = inDegrees(after) - 1
if (count == 0) zeroInDegree push after
inDegrees(after) = count
}
}
assert(sorted.toSet == nodes)
new Ordering[T] {
val lookup = (sorted zipWithIndex).toMap
def compare(a: T, b: T) = lookup(f(a)) compare lookup(f(b))
}
}
}
trait Node {
var dst: Set[Node] = Set.empty[Node]
var src: Set[Node] = Set.empty[Node]
def addDst(that: Node) {
this.dst += that
that.src += this
}
}
class CharNode(val n: Char) extends Node {
override def toString = n.toString
}