Scala equivalent of C#’s extension methods? - scala

In C# you can write:
using System.Numerics;
namespace ExtensionTest {
public static class MyExtensions {
public static BigInteger Square(this BigInteger n) {
return n * n;
}
static void Main(string[] args) {
BigInteger two = new BigInteger(2);
System.Console.WriteLine("The square of 2 is " + two.Square());
}
}}
How would this simple extension method look like in Scala?

The Pimp My Library pattern is the analogous construction:
object MyExtensions {
implicit def richInt(i: Int) = new {
def square = i * i
}
}
object App extends Application {
import MyExtensions._
val two = 2
println("The square of 2 is " + two.square)
}
Per #Daniel Spiewak's comments, this will avoid reflection on method invocation, aiding performance:
object MyExtensions {
class RichInt(i: Int) {
def square = i * i
}
implicit def richInt(i: Int) = new RichInt(i)
}

Since version 2.10 of Scala, it is possible to make an entire class eligible for implicit conversion
implicit class RichInt(i: Int) {
def square = i * i
}
In addition, it is possible to avoid creating an instance of the extension type by having it extend AnyVal
implicit class RichInt(val i: Int) extends AnyVal {
def square = i * i
}
For more information on implicit classes and AnyVal, limitations and quirks, consult the official documentation:
http://docs.scala-lang.org/overviews/core/implicit-classes.html
http://docs.scala-lang.org/overviews/core/value-classes.html

This would be the code after Daniel's comment.
object MyExtensions {
class RichInt( i: Int ) {
def square = i * i
}
implicit def richInt( i: Int ) = new RichInt( i )
def main( args: Array[String] ) {
println("The square of 2 is: " + 2.square )
}
}

In Scala we use the so-called (by the inventor of the language) Pimp My Library pattern, which is much discussed and pretty easy to find on the Web, if you use a string (not keyword) search.

Scala 3 now has extension methods. Functionally it seems similar as expected to C# and Kotlin.
https://dotty.epfl.ch/docs/reference/contextual/extension-methods.html
https://github.com/scala/scala
https://github.com/lampepfl/dotty
A recent (as of this post) pull shows the syntax being simplified. Stable version as of this post is still 2.x. But there is a 3.xRC, and I noticed Jetbrains already supports it in Idea, partially I assume.

Related

Way to enhance a class with function delegation

I have the following classes in Scala:
class A {
def doSomething() = ???
def doOtherThing() = ???
}
class B {
val a: A
// need to enhance the class with both two functions doSomething() and doOtherThing() that delegates to A
// def doSomething() = a.toDomething()
// def doOtherThing() = a.doOtherThing()
}
I need a way to enhance at compile time class B with the same function signatures as A that simply delegate to A when invoked on B.
Is there a nice way to do this in Scala?
Thank you.
In Dotty (and in future Scala 3), it's now available simply as
class B {
val a: A
export a
}
Or export a.{doSomething, doOtherThing}.
For Scala 2, there is unfortunately no built-in solution. As Tim says, you can make one, but you need to decide how much effort you are willing to spend and what exactly to support.
You can avoid repeating the function signatures by making an alias for each function:
val doSomething = a.doSomething _
val doOtherthing = a.doOtherThing _
However these are now function values rather than methods, which may or may not be relevant depending on usage.
It might be possible to use a trait or a macro-based solution, but that depends on the details of why delegation is being used.
Implicit conversion could be used for delegation like so
object Hello extends App {
class A {
def doSomething() = "A.doSomething"
def doOtherThing() = "A.doOtherThing"
}
class B {
val a: A = new A
}
implicit def delegateToA(b: B): A = b.a
val b = new B
b.doSomething() // A.doSomething
}
There is this macro delegate-macro which might just be what you are looking for. Its objective is to automatically implement the delegate/proxy pattern, so in your example your class B must extend class A.
It is cross compiled against 2.11, 2.12, and 2.13. For 2.11 and 2.12 you have to use the macro paradise compile plugin to make it work. For 2.13, you need to use flag -Ymacro-annotations instead.
Use it like this:
trait Connection {
def method1(a: String): String
def method2(a: String): String
// 96 other abstract methods
def method100(a: String): String
}
#Delegate
class MyConnection(delegatee: Connection) extends Connection {
def method10(a: String): String = "Only method I want to implement manually"
}
// The source code above would be equivalent, after the macro expansion, to the code below
class MyConnection(delegatee: Connection) extends Connection {
def method1(a: String): String = delegatee.method1(a)
def method2(a: String): String = delegatee.method2(a)
def method10(a: String): String = "Only method I need to implement manually"
// 96 other methods that are proxied to the dependency delegatee
def method100(a: String): String = delegatee.method100(a)
}
It should work in most scenarios, including when type parameters and multiple argument lists are involved.
Disclaimer: I am the creator of the macro.

Type class pattern: simulacrum boosted method not found

I have a requirement to be able to count number of times AtomicReference[V].get is called in a class that has as field an array of wildcarded atomic references.
To that end, first, I've extended java's AtomicReference[V]:
import java.util.concurrent.atomic.{AtomicInteger => AInt, AtomicReference => ARef}
class MyAtomicReference[V] extends ARef[V]{
private val getCounter: AInt = new AInt(0)
def getAndListen(): V = {
getCounter.getAndIncrement()
super.get()
}
def counter(): Int = getCounter.get()
def resetCounter(): Unit = getCounter.set(0)
}
Then I've added trait AtomicRefCounter which declares the method that I would wish to invoke:
import simulacrum.typeclass
#typeclass trait AtomicRefCounter [R[_], T] {
def countGets(container: R[T]): Int
}
Lastly, I've defined a default AtomicArrayRefCounter in the object DefaultAtomicRefCounters:
object DefaultAtomicRefCounters {
implicit val arrayOfAtomicsTraverser = new AtomicRefCounter[Array, MyAtomicReference[_]] {
override def countGets(container: Array[MyAtomicReference[_]]): Int = container map(_.counter()) sum
}
}
Despite that when I try to call the traverseAtomics() on a corresponding array in a test, I do not see it (I am using Intellij IDEA):
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
pool.buckets.countGet
}
A piece of advice on what I am missing would really help. Usage of simulacrum is not mandatory - if you feel you know how to solve this without it, I would love to hear that.
update:
This is how the buckets are implemented:
class Pool[T] {
type TimeStampedList = (List[T], Long)
val parallelism: Int = Runtime.getRuntime.availableProcessors * 32
val buckets = new Array[MyAtomicReference[TimeStampedList]](parallelism)
...
I think, you might have gotten wrong how implicits work.
If I read everything correctly, then in your code
implicitly[AtomicRefCounter[Array, MyAtomicReference[_]]].countGets(pool.buckets)
should work.
I you wanted to call countGets on the Array you should use the EnrichMyLibrary pattern.
object DefaultAtomicRefCounters {
implicit class RichArray(private underlying: Array[MyAtomicReference[_]] extends AnyVal {
def countGets: Int = underlying.map(_.counter()).sum
}
}
As disappointing as it is, I couldn't make it work with simulacrum annotation, so I've followed Sascha's advise. I just modified slightly his second example (I couldn't get it to work with implictly) so it compiles and works:
object TraditionalConcurrencyHelpers {
implicit class CountArrayAtomicGetsOps(wrapper: Array[MyAtomicReference[(List[Int], Long)]]) {
def countGets()(implicit atomicRefCounter: AtomicRefCounter[Array, MyAtomicReference[(List[Int], Long)]]): Int = atomicRefCounter.countGets(wrapper)
}
}
With this I have no problem calling countGets on the array:
behavior of "removeO1"
"method" should "remove an element from the pool with time O(1)" in new IntPoolBuilder {
import TraditionalConcurrencyHelpers._
import org.learningconcurrency.traditional_concurrency.helpers.DefaultAtomicRefCounters._
//call pool.removeO1 (not implemented yet)
pool.buckets.countGets() shouldEqual 1
}

Scala forward or delegate methods to encapsulated object

Is there any possibility to implicitly forward some of class methods to encapsulated object?
case class Entity(id: Int, name: String,) {
private lazy val lastScan = new LastScan
def getLastScanDate = lastScan.getLastScanDate
def updateLastScanDate = lastScan.updateLastScanDate
}
I want to avoid creating def updateLastScanDate = lastScan.updateLastScanDate just to forward methods to wrapped object.
In the plain language this is not possible. There used to be a compiler plugin by Kevin Wright to achieve this automatic delegation.
He seems to be working on an Autorproxy "Rebooted" version now that is macro based, making it straight forward to include in your project. I'm pasting here an example from its test sources:
trait Bippy {
def bippy(i : Int): String
}
object SimpleBippy extends Bippy {
def bippy(i: Int) = i.toString
}
#delegating class RawParamWrapper(#proxy pivot: Bippy)
val wrapper = new RawParamWrapper(SimpleBippy)
assert(wrapper.bippy(42) == "42")

Accessibility of primary constructor parameters in scala

I am having hard time to understand the concept of primary constructor and it's parameters. What I have understood till now is: if we define a class as following
class Example(a: Int, b: Int)
Scala compiler generates a primary constructor of the class Examples with the above two parameters. But, it doesn't defines fields a and b in the class Example's definition. But if we define
class Example(val a: Int, val b: Int)
scala compiler generates the primary constructor as above and adds two fields in the class definition.
Now the problem comes when I am trying an example like
class PrimaryConstructor(a: Int, b: Int){
override def toString() = "PrimaryConstructor(" + this.a + ", " + this.b + ")"
}
The above code compiles well even if there is no fields named either a or b. I am not able to understand that if there are no any fields as such then how I am able to access them using this: the current object reference.
object Main{
def main(args: Array[String]){
val primaryConstructor = new PrimaryConstructor(1, 2)
println(primaryConstructor.a)
}
}
While if I try to access them from out side the class definition as above, I get the following error message after compilation.
error: value a is not a member of PrimaryConstructor
println(primaryConstructor.a)
I can understand this. But, how can I access those fields using this? Please help me to understand this.
It basically generates a private val, so
class A(a:Int) {
def func = a
}
and
class A(private[this] val a:Int) {
def func = a
}
are equivalent. This may not be entirely true if you omit the function.
When a constructor parameter is referred outside the constructor body ( such as in example func above ), Scala generates a private[this] val, otherwise not.
You can check scala spec for more details or look at this stackoverflow question
Martin's answer is great:
It basically generates a private val, so
class A(a:Int) {
def func = a
}
and
class A(private[this] val a:Int) {
def func = a
}
are equivalent and you can access a from inside your class.
But, note that class A(a: Int) means that the field a is instance private. Meaning that you cannot write something like this:
class A(a: Int){
def sum(other: A): Int = {
this.a + other.a
}
}
other.a is not allowed even though both instances are of the same type. You can only use this.a.

Scala Numeric init with constant 0

Lets I have a utility class called MathUtil.
and it looks like this .
abstract class MathUtil(T:Numeric){
def nextNumber(value:T)
def result():T
}
Lets I subclass it this way
class SumUtil[T:Numeric] extends MathUtil[T]{
private var sum:T = 0
override def nextNumber(value:T){
sum = sum + value
}
override def result():T = sum
}
I have a problem with the statement
private var sum:T = 0
Now , I have to initialize to sum to 0. I would guess any numeric to have a way to represent 0. Im pretty new to scala. How do I solve this issue ?
The Numeric type class instance has a zero method that does what you want:
class SumUtil[T: Numeric] extends MathUtil[T] {
private var sum: T = implicitly[Numeric[T]].zero
override def nextNumber(value: T) {
sum = implicitly[Numeric[T]].plus(sum, value)
}
override def result(): T = sum
}
Note that you also need the instance for the plus method, unless you import Numeric.Implicits._, in which case you can use +. You can also clean the code up a bit by not using the context bound syntax in this case:
class SumUtil[T](implicit ev: Numeric[T]) extends MathUtil[T] {
import Numeric.Implicits._
private var sum: T = ev.zero
override def nextNumber(value: T) {
sum = sum + value
}
override def result(): T = sum
}
This is exactly equivalent: the context bound version is just syntactic sugar for this implicit argument, but if you need to use that argument explicitly (as you do here, for its zero), I find it cleaner to write the desugared version.
I think that there needs to be a little clarification of exactly what you're trying to accomplish. From the Scala docs, the Numeric type itself is generic. My feeling here is what you actually want is to describe a MathUtil abstraction that handles any Numeric[T] rather than subclasses of Numeric[_] which is what your code is currently describing. Here is the correct implementation based on that assumption.
//Define a MathUtil that works on any T
abstract class MathUtil[T] {
def nextNumber(value: T)
def result(): T
}
//Define a SumUtil that works on any T that has an available Numeric
//Will search implicit scope, but also allows you to provide an
//implementation if desired.
class SumUtil[T](implicit n: Numeric[T]) extends MathUtil[T] {
//Use the Numeric to generate the zero correctly.
private var sum: T = n.zero
//Use the Numeric to correctly add the sum and value
override def nextNumber(value: T) = sum = n.plus(sum, value)
override def result(): T = sum
}
//Test that it works.
val a = new SumUtil[Int]
val b = List(1,2,3)
b map a.nextNumber //Quick and dirty test... returns a meaningless list
println(a.result) //Does indeed print 6
If the above doesn't do what you want, please clarify your question.