This is a particularly un-Googleable query, but what is being represented when a function is defined with multiple equal signs on a single line such as in the following:
def x_=(x: Int): Unit = internal = x
That line in isolation is the setter portion of the getter/setter pattern in scala classes. A full example might look like this:
class Foo {
private var internal: Int = 0
def x = internal
def x_=(x: Int): Unit = internal = x
}
The def x is the getter for private variable internal, while def x_(x: Int) is the setter. The effect is that through the magic of syntactic sugar the x member can be used on the left hand side of an assignment and will then set internal to the right hand side like this:
val foo = new Foo()
foo.x = 15
println(foo.x) // 15
The _=(x: Int) invokes the syntactic sugar of assignment, but it could just as well be called directly like this:
val foo = new Foo()
foo.x_=(15)
println(foo.x) // 15
As you can see, the former call is really just the latter method call with the underscore and parentheses omitted from the signature.
Related
I'm trying to pass a parameter by reference and update in a function.
object CallByName {
private def inc(x: => Int): Unit = {
x += 1
}
def main(args: Array[String]): Unit = {
var x = 0
inc(x)
println(x)
}
}
But x+=1 is marked as an error:
Reassignment to val
I've come across this statement:
Mutating the input parameters is often seen as bad style and makes it
harder to reason about code.
Then how can I alternatively achieve what I want?
Mutating the input parameters is often seen as bad style and makes it harder to reason about code.
This is very true and, in my opinion, should be followed at all times.
pass a parameter by reference
x: => Int is not a parameter by reference, it is a by-name parameter.
Then how can I alternatively achieve what I want?
private def inc(x: Int): Int = {
x + 1
}
var x = 0
x = inc(x)
If you do insist on changing input parameter, you can use AtomicInteger for example and mutate it within your inc method.
I'm trying to pass a parameter by reference and update in a function.
Scala does not support pass-by-reference. The default is pass-by-value, and it is possible to explicitly define individual parameters as call-by-name, but those are the only two modes supported.
object CallByName {
private def inc(x: => Int): Unit = {
x += 1
}
}
That's not pass-by-reference, that is call-by-name. Check out the name of the object, it says so right there: CallByName.
Then how can I alternatively achieve what I want?
Unfortunately, you don't say what you want to achieve, so it's impossible to say. The only thing you do say is that you want pass-by-reference, and for that, the answer is simple:
You can't. Scala does not support pass-by-reference, period.
is there a nice possibilyt to assign the values of a tuple to single variables? Here is what i want to do but it throws an error:
var a : Int = _
var b : Int = _
def init() {
(a,b) = getTuple() // returns (Int, Int)
}
def someFunction = {
// use a here
}
def someOtherFunction = {
// use b here
}
Error: ';' expected but '=' found.
(a, b) = getTuple()
Do i really have to do this ._1 and ._2 thing?
val tuple = getTuple() // returns (Int, Int)
a = tuple._1
b = tuple._2
Thanks for answering.
As you can see in Section 6.15 Assignments of the Scala Language Specification, the lefthand-side of an assignment expression must be either a bare identifier:
foo = ???
// either an assignment to a local mutable `var` or syntactic sugar for:
foo_=(???)
a member access:
foo.bar = ???
// syntactic sugar for:
foo.bar_=(???)
or a method call:
foo(bar) = ???
// syntactic sugar for:
foo.update(bar, ???)
Pattern Matching is only available for value definitions (see Section 4.1 Value Declarations and Definitions) and variable definitions (see Section 4.2 Variable Declarations and Definitions).
So, both of the following would be legal:
var (a, b) = getTuple()
val (a, b) = getTuple()
By the way, there are a number of highly non-idiomatic things in your code:
It is highly unusual to pass an empty argument list to a method call. Normally, methods that have no parameters should have no parameter lists instead of an empty parameter list. The only exception are methods that have side-effects, where the empty parameter list serves as kind of a "warning flag", but methods which have side-effects are highly non-idiomatic as well. So, getTuple should be defined and called like this:
def getTuple = ???
getTuple
instead of
def getTuple() = ???
getTuple()
On the other hand, if the method does have side-effects, it shouldn't be called getTuple because that implies that the method "gets" something, and there is no indication that it also changes something.
In Scala, getters and setters are not called getFoo and setFoo but rather foo and foo_=, so the method should rather be called tuple.
Mutable variables are highly non-idiomatic as well, they should probably rather be vals.
Tuple destructuring is an opaque call to unapply method of TupleN[T1, ..., Tn] companion object, aka extractor object.
As the documentation suggests, one can only have a variable initialization with an extractor object, but not assignment.
So, the only possible way is to use it like this:
def getTuple = (1,2)
def main() = {
val (a,b) = getTuple
// use a,b
}
The fact that you use a var may be the sign you have a design flaw. Try to refactor your code or specify the exact problem you're trying to solve with the var to justify its usage (although what you're trying to do with extractor is still impossible)
I'm learning Scala and I don't really understand the following example :
object Test extends App {
def method1 = println("method 1")
val x = {
def method2 = "method 2" // method inside a block
"this is " + method2
}
method1 // statement inside an object
println(x) // same
}
I mean, it feels inconsistent to me because here I see two different concepts :
Objects/Classes/Traits, which contains members.
Blocks, which contains statements, the last statement being the value of the block.
But here we have a method part of a block, and statements part of an object. So, does it mean that blocks are objects too ? And how are handled the statements part of an object, are they members too ?
Thanks.
Does it mean that blocks are objects too?
No, blocks are not objects. Blocks are used for scoping the binding of variables. Scala enables not only defining expressions inside blocks but also to define methods. If we take your example and compile it, we can see what the compiler does:
object Test extends Object {
def method1(): Unit = scala.Predef.println("method 1");
private[this] val x: String = _;
<stable> <accessor> def x(): String = Test.this.x;
final <static> private[this] def method2$1(): String = "method 2";
def <init>(): tests.Test.type = {
Test.super.<init>();
Test.this.x = {
"this is ".+(Test.this.method2$1())
};
Test.this.method1();
scala.Predef.println(Test.this.x());
()
}
}
What the compiler did is extract method2 to an "unnamed" method on method2$1 and scoped it to private[this] which is scoped to the current instance of the type.
And how are handled the statements part of an object, are they members
too?
The compiler took method1 and println and calls them inside the constructor when the type is initialized. So you can see val x and the rest of the method calls are invoked at construction time.
method2 is actually not a method. It is a local function. Scala allows you to create named functions inside local scopes for organizing your code into functions without polluting the namespace.
It is most often used to define local tail-recursive helper functions. Often, when making a function tail-recursive, you need to add an additional parameter to carry the "state" on the call stack, but this additional parameter is a private internal implementation detail and shouldn't be exposed to clients. In languages without local functions, you would make this a private helper alongside the primary method, but then it would still be within the namespace of the class and callable by all other methods of the class, when it is really only useful for that particular method. So, in Scala, you can instead define it locally inside the method:
// non tail-recursive
def length[A](ls: List[A]) = ls match {
case Nil => 0
case x :: xs => length(xs) + 1
}
//transformation to tail-recursive, Java-style:
def length[A](ls: List[A]) = lengthRec(ls, 0)
private def lengthRec[A](ls: List[A], len: Int) = ls match {
case Nil => len
case x :: xs => lengthRec(xs, len + 1)
}
//tail-recursive, Scala-style:
def length[A](ls: List[A]) = {
//note: lengthRec is nested and thus can access `ls`, there is no need to pass it
def lengthRec(len: Int) = ls match {
case Nil => len
case x :: xs => lengthRec(xs, len + 1)
}
lengthRec(ls, 0)
}
Now you might say, well I see the value in defining local functions inside methods, but what's the value in being able to define local functions in blocks? Scala tries to as simple as possible and have as few corner cases as possible. If you can define local functions inside methods, and local functions inside local functions … then why not simplify that rule and just say that local functions behave just like local fields, you can simply define them in any block scope. Then you don't need different scope rules for local fields and local functions, and you have simplified the language.
The other thing you mentioned, being able to execute code in the bode of a template, that's actually the primary constructor (so to speak … it's technically more like an initializer). Remember: the primary constructor's signature is defined with parentheses after the class name … but where would you put the code for the constructor then? Well, you put it in the body of the class!
What exactly is the difference between:
scala> def foo = 5
foo: Int
and
scala> def foo() = 5
foo: ()Int
Seems that in both cases, I end up with a variable foo which I can refer to without parenthesis, always evaluating to 5.
You're not defining a variable in either case. You're defining a method. The first method has no parameter lists, the second has one parameter list, which is empty. The first of these should be
called like this
val x = foo
while the second should be called like this
val x = foo()
However, the Scala compiler will let you call methods with one empty parameter list without the parentheses, so either form of call will work for the second method. Methods without parameter lists cannot be called with the parentheses
The preferred Scala style is to define and call no-argument methods which have side-effects with the parentheses. No-argument methods without side-effects should be defined and called without the parentheseses.
If you actually which to define a variable, the syntax is
val foo = 5
Before anything else is said, def does not define a field, it defines a method.
In the second case, you can omit parenthesis because of a specific feature of Scala. There are two differences of interest here: one mechanical, and one of recommended usage.
Beginning with the latter, it is recommended usage to use empty parameter list when there are side effects. One classic example is close(). You'd omit parenthesis if there are no side effects to calling the element.
Now, as a practical difference -- beyond possible weird syntactic mix-ups in corner cases (I'm not saying there are, just conjecturing) -- structural types must follow the correct convention.
For example, Source had a close method without parenthesis, meaning a structural type of def close(): Unit would not accept Source. Likewise, if I define a structural method as def close: Unit, then Java closeable objects will not be accepted.
What does it mean when I use def to define a field in Scala
You can't define a field using def.
Seems that in both cases, I end up with a variable foo which I can refer to without parenthesis, always evaluating to 5.
No, in both cases you end up with a method foo, which you can call without parentheses.
To see that, you can use javap:
// Main.scala
object Main {
def foo1 = 5
def foo2() = 5
}
F:\MyProgramming\raw>scalac main.scala
F:\MyProgramming\raw>javap Main
Compiled from "main.scala"
public final class Main extends java.lang.Object{
public static final int foo2();
public static final int foo1();
}
However, see http://tommy.chheng.com/index.php/2010/03/when-to-call-methods-with-or-without-parentheses-in-scala/
Additionally to the answers already given I'd like to stress two points:
The possibility to define methods without a parameter list is a way to realize the Uniform Access Principle. This allows to hide the difference between fields and methods, which makes later implementation changes easier.
You can call a method defined as def foo() = 5 using foo, but you can't call a method defined as def foo = 5 using foo()
I'm surprised that nobody mentioned anything about the laziness difference.
While val is evaluated only once at the time of definition, def is evaluated only when we access it and evaluated every-time we access it. See example below:
scala> def foo = {
| println("hi")
| 5
| }
foo: Int
scala> val onlyOnce = foo
scala> def everyTime = foo
scala> onlyOnce
res0: Int = 5
scala> onlyOnce
res1: Int = 5
scala> everyTime
hi
res2: Int = 5
scala> everyTime
hi
res3: Int = 5
I have some Scala code that does something nifty with two different versions of a type-parameterized function. I have simplified this down a lot from my application but in the end my code full of calls of the form w(f[Int],f[Double]) where w() is my magic method. I would love to have a more magic method like z(f) = w(f[Int],f[Double]) - but I can't get any syntax like z(f[Z]:Z->Z) to work as it looks (to me) like function arguments can not have their own type parameters. Here is the problem as a Scala code snippet.
Any ideas? A macro could do it, but I don't think those are part of Scala.
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// want something like this: def z[Z](f[Z]:Z=>Z) = w(f[Int],f[Double])
// a type parameterized function that takes a single type-parameterized function as an
// argument and then speicalizes the the argument-function to two different types,
// i.e. a single-argument version of w() (or wrapper)
}
}
You can do it like this:
trait Forall {
def f[Z] : Z=>Z
}
def z(u : Forall) = w(u.f[Int], u.f[Double])
Or using structural types:
def z(u : {def f[Z] : Z=>Z}) = w(u.f[Int], u.f[Double])
But this will be slower than the first version, since it uses reflection.
EDIT: This is how you use the second version:
scala> object f1 {def f[Z] : Z=>Z = x => x}
defined module f1
scala> def z(u : {def f[Z] : Z=>Z}) = (u.f[Int](0), u.f[Double](0.0))
z: (AnyRef{def f[Z]: (Z) => Z})(Int, Double)
scala> z(f1)
res0: (Int, Double) = (0,0.0)
For the first version add f1 extends Forall or simply
scala> z(new Forall{def f[Z] : Z=>Z = x => x})
If you're curious, what you're talking about here is called "rank-k polymorphism." See wikipedia. In your case, k = 2. Some translating:
When you write
f[X](x : X) : X = ...
then you're saying that f has type "forall X.X -> X"
What you want for z is type "(forall Z.Z -> Z) -> Unit". That extra pair of parenthesis is a big difference. In terms of the wikipedia article it puts the forall qualifier before 2 arrows instead of just 1. The type variable can't be instantiated just once and carried through, it potentially has to be instantiated to many different types. (Here "instantiation" doesn't mean object construction, it means assigning a type to a type variable for type checking).
As alexy_r's answer shows this is encodable in Scala using objects rather than straight function types, essentially using classes/traits as the parens. Although he seems to have left you hanging a bit in terms of plugging it into your original code, so here it is:
// this is your code
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// This is new code
trait ForAll {
def g[X](x : X) : X
}
def z(forall : ForAll) = w(forall.g[Int], forall.g[Double])
z(new ForAll{def g[X](x : X) = f(x)})
}
}
I don't think what you want to do is possible.
Edit:
My previous version was flawed. This does work:
scala> def z(f: Int => Int, g: Double => Double) = w(f, g)
z: (f: (Int) => Int,g: (Double) => Double)Unit
scala> z(f, f)
But, of course, it is pretty much what you have.
I do not think it is even possible for it to work, because type parameters exist only at compile-time. At run time there is no such thing. So it doesn't make even sense to me to pass a parameterized function, instead of a function with the type parameters inferred by Scala.
And, no, Scala has no macro system.