I am beginner of Scala, I try to make a class and use of it, which class has variables (var) and some processing (in def). I write class like as follows;
class Example() {
var ExampleVar0 = 0
var ExampleVar1 = 0
def ExampleProcessing(_arg0: Int, _arg1: Int) : (Int, Int) = {
ExampleVar0 = _arg0 + 1
ExampleVar1 = _arg1 - 1
(ExampleVar0*2, ExampleVar1/2)
}
}
I want to initialize ExampleVar* and to keep and update the value. I use the class in other class;
var result0
var result1
val exp = Example()
exp.ExampleProcessing(5, 6)(result0, result1)
The both of result0 and result1 is zero, seems always write with zero by statement of the var ExampleVar0 = 0. I checked the value of the var (println(exp.ExampleVar0.toString)) then it is always zero. I might misunderstand about initialization of var.
Could you please point out where is my misunderstand and how to solve it?
You appear to be using result0 and result1 as method parameters, which does not look right. Try this:
val exp = Example()
val (result0, result1) = exp.ExampleProcessing(5, 6)
In this case the var does not seem to be relevant or necessary, but I will give the usual warning that it is best to avoid var and use immutable data structures.
Related
I have tried all of the following for scala.collection.mutable.SortedSet:
var s = SortedSet[Array[Int]]
var s = SortedSet[Array[Int]]()
var s = new SortedSet[Array[Int]]
var s = new SortedSet[Array[Int]]()
var s = SortedSet[Array]
var s = SortedSet[Array]()
var s = new SortedSet[Array]()
I don't know why it has to be so hard to just declare this stuff in Scala. All I want is a sorted set of Int-arrays.
SortedSet is not a "default" collection, therefore not defined in Predef.
First import it then it should work:
import scala.collection.SortedSet
val s = SortedSet[Array[Int]]()
Next to this you need an implicit ordering defined:
implicit val arrayOrdering = new Ordering[Array[Int]] {
override def compare(x: Array[Int], y: Array[Int]): Int = ???
// Implement whatever you mean by one array is greater than the other array
}
Also be careful with Array-s as that is a Java array, so it does not have the equals and hashcode methods overridden and does not look at value equality, but rather reference equality.
I declared a variable outside the function like this:
var s: Int = 0
passed it such as this:
def function(s: Int): Boolean={
s += 1
return true
}
but the error lines wont go away under the "s +=" for the life of me. I tried everything. I am new to Scala btw.
First of all, I will repeat my words of caution: solution below is both obscure and inefficient, if it possible try to stick with values.
implicit class MutableInt(var value: Int) {
def inc() = { value+=1 }
}
def function(s: MutableInt): Boolean={
s.inc() // parentheses here to denote that method has side effects
return true
}
And here is code in action:
scala> val x: MutableInt = 0
x: MutableInt = MutableInt#44e70ff
scala> function(x)
res0: Boolean = true
scala> x.value
res1: Int = 1
If you just want continuously increasing integers, you can use a Stream.
val numberStream = Stream.iterate(0)(_ + 1).iterator
That creates an iterator over a never-ending stream of number, starting at zero. Then, to get the next number, call
val number: Int = numberStream.next
I have also just started using Scala this was my work around.
var s: Int = 0
def function(s: Int): Boolean={
var newS = s
newS = newS + 1
s = newS
return true
}
From What i read you are not passing the same "s" into your function as is in the rest of the code. I am sure there is a even better way but this is working for me.
You don't.
A var is a name that refers to a reference which might be changed. When you call a function, you pass the reference itself, and a new name gets bound to it.
So, to change what reference the name points to, you need a reference to whatever contains the name. If it is an object, that's easy enough. If it is a local variable, then it is not possible.
See also call by reference, though I don't think this question is a true duplicate.
If you just want to increment a variable starting with 3
val nextId = { var i = 3; () => { i += 1; i } }
then invoke it:
nextId()
I'm currently learning Scala, and just discovered the way to create custom field getters/setters. I have a simple example working:
class Thing(private val a:Int){
override def toString = "Thing[" + a + "]"
private var _value = a
def value = _value
def value_= (newVal:Int) = _value = newVal
}
On the console I can do:
scala> var t = new Thing(2)
t: dylan.code.Thing = Thing[2]
scala> t.value
res1: Int = 2
scala> t.value = 3
scala> t.value
res2: Int = 3
Now I'm trying to bring this concept to a slightly more complicated example; I'll try to whittle the code down to what's relevant:
abstract class CellExpression[Type] extends Publisher[CellUpdateEvent[Type]] with Subscriber[CellUpdateEvent[Type], CellExpression[Type]]{
protected var cachedValue: Type = recalculateValue()
protected def recalculateValue(): Type
protected def changeValue(newValue: Type):Unit = {
val oldValue = value()
if(newValue != oldValue){
cachedValue = newValue
publish(new CellUpdateEvent(this, oldValue, newValue))
}
}
def value() = cachedValue
def notify(pub: CellExpression[Type], event: CellUpdateEvent[Type]) = changeValue(recalculateValue())
}
//....
class CellVariable[Type](private val initialValue:Type) extends CellExpression[Type]{
cachedValue = initialValue
protected def recalculateValue() = { cachedValue }
override def toString = "CellVariable[" + value + "]"
def value_= (newValue:Type) = {changeValue(newValue)}
}
As far as I can tell, I've done what I need to in order to be able to treate value as a field via its getter and setter. But when I try it out in the console, I get:
scala> var i = new CellVariable(2)
i: dylan.code.CellVariable[Int] = CellVariable[2]
scala> i.value = 3
<console>:11: error: reassignment to val
i.value = 3
^
What have I done wrong, and how can I fix it?
I actually stumbled onto the solution.
The line where I declare my value function: def value() = cachedValue is the culprit.
If I remove the parentheses to make the line def value = cachedValue everything seems to work as I expected.
You cannot change values in Scala. A value is assigned once and only once. If you want to do this then you need to use variables instead of values. In other words, change the declaration from val to var.
The problem is inside one of your class definitions and may be on a line without val because I believe that if you neglect to declare a name, then Scala assumes that it is a value and therefore immutable.
Not sure what you want getters and setters for though. Scala enables you to ignore all of that Java overhead.
It is probably the line that says cachedValue = initialValue because it is not declared with var anywhere in that class. The definition in the other class is a different name because it is in a different scope. You would have to say something like class.varname to change a variable defined in another class.
I'm still learning Scala, but one thing I thought was interesting is that Scala blurs the line between methods and fields. For instance, I can build a class like this...
class MutableNumber(var value: Int)
The key here is that the var in the constructor-argument automatically allows me to use the 'value' field like a getter/setter in java.
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
If I want to add constraints, I can do so by switching to using methods in place of the instance-fields:
// require all mutable numbers to be >= 0
class MutableNumber(private var _value: Int) {
require(_value >= 0)
def value: Int = _value
def value_=(other: Int) {
require(other >=0)
_value = other
}
}
The client side code doesn't break since the API doesn't change:
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
My hang-up is with the named-parameter feature that was added to Scala-2.8. If I use named-parameters, my API does change and it does break the api.
val num = new MutableNumber(value=5) // old API
val num = new MutableNumber(_value=5) // new API
num.value = 6
println(num.value)
Is there any elegant solution to this? How should I design my MutableNumber class so that I can add constraints later on without breaking the API?
Thanks!
You can use the same trick that case classes do: use a companion object.
object Example {
class MutableNumber private (private var _value: Int) {
require (_value >= 0)
def value: Int = _value
def value_=(i: Int) { require (i>=0); _value = i }
override def toString = "mutable " + _value
}
object MutableNumber {
def apply(value: Int = 0) = new MutableNumber(value)
}
}
And here it is working (and demonstrating that, as constructed, you must use the object for creations, since the constructor is marked private):
scala> new Example.MutableNumber(5)
<console>:10: error: constructor MutableNumber cannot be accessed in object $iw
new Example.MutableNumber(5)
^
scala> Example.MutableNumber(value = 2)
res0: Example.MutableNumber = mutable 2
scala> Example.MutableNumber()
res1: Example.MutableNumber = mutable 0
Thanks for the answer! As an aside, I think the Scala-guys might be aware that there's an issue:
What's New in Scala 2.8: Named and Default Parameters
...
Until now, the names of arguments were a somewhat arbitrary choice for library developers, and weren't considered an important part of the API. This has suddenly changed, so that a method call to mkString(sep = " ") will fail to compile if the argument sep were renamed to separator in a later version.
Scala 2.9 implements a neat solution to this problem, but while we're waiting for that, be cautious about referring to arguments by name if their names may change in the future.
http://www.artima.com/scalazine/articles/named_and_default_parameters_in_scala.html
class MutableNumber {
private var _value = 0 //needs to be initialized
def value: Int = _value
def value_=(other: Int) {
require(other >=0) //this requirement was two times there
_value = other
}
}
you can modify all members of any class within curly braces
val n = new MutableNumber{value = 17}
I have a class where I like to initialize my var by reading a configfile, which produces intermediate objects/vals, which I would like to group and hide in a method.
Here is the bare minimum of the problem - I call the ctor with a param i, in reality a File to parse, and the init-method generates the String s, in reality more complicated than here, with a lot of intermediate objects being created:
class Foo (val i: Int) {
var s : String;
def init () {
s = "" + i
}
init ()
}
This will produce the error: class Foo needs to be abstract, since variable s is not defined. In this example it is easy to solve by setting the String to "": var s = "";, but in reality the object is more complex than String, without an apropriate Null-implementation.
I know, I can use an Option, which works for more complicated things than String too:
var s : Option [String] = None
def init () {
s = Some ("" + i)
}
or I can dispense with my methodcall. Using an Option will force me to write Some over and over again, without much benefit, since there is no need for a None else than to initialize it that way I thought I could.
Is there another way to achieve my goal?
var s : Whatever = _ will initialize s to the default value for Whatever (null for reference types, 0 for numbers, false for bools etc.)
Instead of creating separate methods for initialization, you should perform the initialization using the following way :
class Foo(val i: Int) {
var s: String = {
var s0 = " "
s0 += i
// do some more stuff with s0
s0
}
var dashedDate = {
val dashed = new SimpleDateFormat("yy-MM-dd")
dashed.format(updated)
}
// Initializing more than one field:
var (x, y, z) = {
var x0, y0, z0 = 0
// some calculations
(x0, y0, z0)
}
}
Honestly, why are you using var? Why not just do:
val rootObject = readFile(filename)
This would make the most sense to me.