Is it possible to initialize a class parameter with a function in Scala?
Example:
def square(x: Int) = x*x
class Foo(val x: Int = square(x))
This doesn't compile but I hope you get the idea.
Hard to guess what you're trying to achieve, but let me have a go:
class Foo private (val x: Int)
object Foo {
def apply(x: Int) = new Foo(square(x))
}
Note that if you try this in the REPL, you must enter both the class and its companion object at the same time (in paste mode, via :pa), or the object Foo won't have access to the private class constructor.
This applies the square function to the parameter x before creating a Foo instance:
scala> Foo(3).x
res1: Int = 9
This is not possible because you try to calculate x based on x (without having any kind of base case). You could do the following:
class Foo(_x: Int) {
val x = square(_x)
}
println(new Foo(10).x) // 100
EDIT
You could also generalise this and implicitly pass a function to the class constructor that transforms x:
implicit val square = (x: Int) => x*x
class Foo(private val _x: Int)(implicit f: Int => Int) {
val x = f(_x)
}
println(new Foo(10).x) // 100
This unfortunately doesn't compile as-is (Scala 2.9.2, 2.10.0), because there is another implicit in scope (Predef.conforms). I don't know how to overcome this ambiguity, but it should certainly be possible.
Here it is.. you can initialize a class with a function ! :)
class Foo(f : Int => Int)
def square(x : Int) = x*x
val foo = new Foo(square)
Or Probably you must be looking for this.
class Foo(f : Int => Int, _p1 : Int){
val p1 = f(_p1)
}
def square(x : Int) = x*x //> square: (x: Int)Int
def add2(x : Int) = x+2 //> add2: (x: Int)Int
val fooSqr = new Foo(square,5)
fooSqr.p1 //> res0: Int = 25
val fooAdd2 = new Foo(add2,5)
fooAdd2.p1 //> res1: Int = 7
In general you can use arbitrary expressions when defining the default value (source).
Your problem is that you can not use x on the right hand side of the initialization, because x is probably neither declared nor initialized at that point.
Related
I have the following class definition and list
class myclass{
val val1: Int = 1
val val2: Int = 2
...
}
val mylist = List(a: myclass, b: myclass, c: myclass, d: myclass)
How can I convert the next line of code to underscore notation
mylist.foldLeft(0)((x,y) => x + y.val1 * y.val2)
I know that the next line doesn't work:
(0 /: mylist)(_ + _.val1 * _.val2)
This is because the first _ is refered to x and the second is referred to y, but the third _ scala doesn't know which variable is referred, my question is if there is a way that this works
This isn't too crazy:
scala> case class C(v: Int, w: Int)
defined class C
scala> val cs = List(C(1,2),C(3,4))
cs: List[C] = List(C(1,2), C(3,4))
scala> cs.iterator.map(c => c.v*c.w).foldLeft(0)(_+_)
res0: Int = 14
It expresses that the operations are independent. Iterating avoids an intermediate list.
I'm trying to mock a function like
def foo(x: A, y: B, z: C = blah)
where blah is a java connection object that I don't want to create on the spot
However when I try to stub it like
(object.foo _)
.stubs(a, b)
It errors out and says overloaded method value stubs with alternatives...
because it's looking for the third parameter. Is there anyway to get around this.
I agree with Matt, but want to point out there is a wildcard syntax in ScalaMock (*) - http://scalamock.org/user-guide/matching/
trait Foo {
def foo(x: Int, y: Int, z: Int = 0): Int
}
val a: Int = ???
val b: Int = ???
val m = mock[Foo]
m.foo _ stubs(a, b, *)
You can use a wildcard when you're stubbing out your method.
The following test passes and I think is what you're looking for:
class DefaultParameterTest extends FlatSpec with Matchers with MockFactory {
class A {
def foo(x: Int, y: Int, z: Int = 0): Int = 0
}
it should "work with a default parameter" in {
val bar = mock[A]
(bar.foo _).stubs(1, 2, _: Int).returning(5)
bar.foo _ expects(1, 2, 0) returning 5 once()
bar.foo(1, 2)
}
}
I have a template using a valueObject that might be one of two flavours depending on where it is used in our app. So I am importing it as an Either:
valueObject: Either[ ObjectA, ObjectB ]
Both objects have an identically named property on them so I would like to retrieve it just by calling
valueObject.propertyA
Which doesn't work.
What is the most concise/ best way of doing this?
Assuming the two objects have the same type (or a supertype / trait) that defines that property - you can use merge which returns left if it exists and right otherwise, with the lowest common type of both:
scala> class MyClass {
| def propertyA = 1
| }
defined class MyClass
scala> val e1: Either[MyClass, MyClass] = Left(new MyClass)
e1: Either[MyClass,MyClass] = Left(MyClass#1e51abf)
scala> val e2: Either[MyClass, MyClass] = Right(new MyClass)
e2: Either[MyClass,MyClass] = Right(MyClass#b4c6d0)
scala> e1.merge.propertyA
res0: Int = 1
scala> e2.merge.propertyA
res1: Int = 1
Using fold
Assuming the two objects do not share a common supertype that holds the property/method, then you have to resort to fold:
scala> case class A(a: Int)
defined class A
scala> case class B(a: Int)
defined class B
scala> def foldAB(eab: Either[A,B]): Int = eab.fold(_.a,_.a)
foldAB: (eab: Either[A,B])Int
scala> foldAB(Left(A(1)))
res1: Int = 1
scala> foldAB(Right(B(1)))
res2: Int = 1
Pattern matching
Another possibility is to use pattern matching:
scala> def matchAB(eab: Either[A,B]): Int = eab match { case Left(A(i)) => i; case Right(B(i)) => i}
matchAB: (eab: Either[A,B])Int
scala> matchAB(Left(A(1)))
res3: Int = 1
scala> matchAB(Right(B(1)))
res4: Int = 1
Is it possible to swap the arguments of a constructor?
Consider the following example:
case class Foo(a:Int, b:Int) {
if (a > b) {
val tmp = a
a = b
b = tmp
}
}
The compiler throws an error because I reassign to val a at line 4 which is perfectly fine. However, I need immutable objects. Therefore, declaring a and b as variables is not an option.
Is there a known pattern how to solve this problem?
Make an inner swap method:
case class Foo(a: Int, b: Int) {
def ifSwap = if (a > b) Foo(b, a) else this
}
val f1 = Foo(1,2).ifSwap // the result is Foo(1,2)
val f2 = Foo(2,1).ifSwap // the result is Foo(1,2)
If you want to preserve immutability then to change state you need either return new instance on each modification, or use some hardcore ways like Lenses, State,
Records, etc... And as Prof. Odersky told on SD'13 talk, there are situations when you shouldn't be afraid of vars
I suppose what you want to achieve that every instance of Foo has ordered its pair of values, is that right?
One possibility is not to make the class case and instead define its construction and extraction yourself. The class won't inherit from product, no pretty default toString etc., but otherwise it's usable just as a case class:
class Foo private (val a: Int, val b: Int);
object Foo {
def apply(a: Int, b: Int): Foo =
if (a < b)
new Foo(a, b)
else
new Foo(b, a)
def unapply(f: Foo): Option[(Int,Int)] = Some((f.a, f.b))
}
// test:
def printFoo(f: Foo) = f match {
case Foo(x, y) => println(x + ", " + y);
}
printFoo(Foo(1,2))
printFoo(Foo(3,2))
See also:
How to override apply in a case class companion
Scala: is it possible to override default case class constructor?
Overload constructor for Scala's Case Classes?
It appears you can make the case class constructor private! Extending on #PetrPudlák answers, I make the constructor private and define a foo helper to create the case class objects:
case class Foo private (a: Int, b: Int)
object Foo {
def foo(x: Int, y: Int) = if (x > y) Foo(y, x) else Foo(x, y)
}
Then I just use foo to instantiate the well formed Foo objects and the rest of the case class functionality works as expected (equality, hashcode, unapply):
import Foo._
foo(1, 2) //> res0: worksheets.so.Foo = Foo(1,2)
foo(2, 1) //> res1: worksheets.so.Foo = Foo(1,2)
foo(3, 4) == foo(4, 3) //> res2: Boolean = true
// Foo(4, 2) does not compile
// extractor/pattern matching works:
val Foo(a, b) = foo(10,1) //> a : Int = 1
//| b : Int = 10
You could also name foo as something more meaningful like OrderedFoo or NormalFoo.
scala> :paste
// Entering paste mode (ctrl-D to finish)
object Foo {
def swapped(b: Int, a: Int) = Foo(a=a, b=b)
}
case class Foo(a: Int, b: Int)
// Exiting paste mode, now interpreting.
defined module Foo
defined class Foo
scala> Foo.swapped(1, 2) == Foo(2, 1)
res0: Boolean = true
I am new to Scala, and trying to understand the following codes (derived from an example in the Beginning Scala book)
scala> def w42(f: Int => Int) = f(42) //(A)
w42: (f: Int => Int)Int
scala> w42 (1 +) //(B)
res120: Int = 43
I do not understand how "1 +" at point (B) is consider as a function (take 1 Int parameter, and return an Int) that satisfies the w42 definition at point (A)?
Would you mind please explain or point me to some documents that have the answer?
Simple. In Scala 1 + 2 is just a syntax sugar over 1.+(2). This means Int has a method named + that accepts Int:
final class Int extends AnyVal {
def +(x: Int): Int = //...
//...
}
This is why you can use 1 + as if it was a function. Example with less unexpected method naming:
scala> def s42(f: String => String) = f("42")
s42: (f: String => String)String
scala> s42("abc".concat)
res0: String = abc42
BTW Technically speaking, eta-expansion is also involved to convert method to a function.