Underscore treats val like a def - scala

I think I understand why this happens
def x() = 1
x _ // () => Int
x() _ // error: _ must follow method; cannot follow Int
x _ turns the method into a function, so you get a no-arg function. x() _ makes no sense because calling the method gives you an Int, which can't be turned into a function. But then why does this happen?
val x = 1
x _ // () => Int

There is little difference between a val and a parameterless method, except that the parameterless method doesn't calculate the value until it's called (and will re-calculate the value for each additional call). What really happens to a val underneath is that there is a private field declared along with a public accessor method that returns that value.
object Test {
def method = 1
val value = 1
}
Compiles to:
object Test extends Object {
def method(): Int = 1;
private[this] val value: Int = _;
<stable> <accessor> def value(): Int = Test.this.value;
def <init>(): Test.type = {
Test.super.<init>();
Test.this.value = 1;
()
}
}
Note the line:
<stable> <accessor> def value(): Int = Test.this.value;
This allows you to, for example, override a def in a super-class with a val in a sub-class, since it's actually overriding a method. Since a method is actually generated, you are allowed to eta-expand a val into a function.

Related

Scala 3 : Finding functions with the given annotation

For Scala 3 macros, does anyone know of a way to find all functions with a given annotation?
For instance:
#fruit
def apple(): Int = ???
#fruit
def banana(): Int = ???
#fruit
def coconut(): Int = ???
#fruit
def durian(): Int = ???
def elephant(): Int = ???
#fruit
def fig(): Int = ???
I would want to find a list of apple, banana, coconut, durian, fig. They could be defined anywhere, but in my case they will all be in a single package.
This solution will extract all the definitions with some annotation from a given package. I will leverage also the compile-time reflection.
This solution will extract all the definitions with some annotations from a given package. I will also leverage the compile-time reflection.
So, To solve your problem, we need to divide it in:
methods gathering from a package;
filter only methods with a given annotation;
transform symbols in function application.
I suppose that you can pass the package and the annotation (and also the return type) as a type argument. So the macro signature is something like that:
inline def findAllFunction[P, A <: ConstantAnnotation, R]: List[() => R] =
${Implementation.myMacroImpl[P, A, R]()}
The first point is straightforward. we could extract all the methods defined as:
def methodsFromPackage(packageSymbol: Symbol): List[Symbol] =
packageSymbol.declaredTypes
.filter(_.isClassDef)
.flatMap(_.declaredMethods)
The second point is also quite easy. Symbol class has the method hasAnnotation that could be used in this case:
def methodsAnnotatatedWith(
methods: List[Symbol],
annotation: Symbol
): List[Symbol] =
methods.filter(_.hasAnnotation(annotation))
The last point is a little bit challenging. Here we should construct the method call. So we need to create the AST that correspond to the method call. Inspired by this example, we can call definition using Apply. Select and This serve to select the correct method that will be called:
def transformToFunctionApplication(methods: List[Symbol]): Expr[List[() => R]] =
val appliedDef = methods
.map(definition => Select(This(definition.owner), definition))
.map(select => Apply(select, List.empty))
.map(apply => '{ () => ${ apply.asExprOf[R] } })
Expr.ofList(appliedDef)
Here I used lamba call, if you want to return directly the value you should change the last two instructions:
def transformToFunctionApplication(methods: List[Symbol]): Expr[List[R]] =
val appliedDef = methods
.map(definition => Select(This(definition.owner), definition))
.map(select => Apply(select, List.empty))
.map(apply => apply.asExprOf[R])
Expr.ofList(appliedDef)
To sum up, the all methods could be defined as:
def myMacroImpl[P: Type, A: Type, R: Type]()(using
Quotes
): Expr[List[() => R]] = {
import quotes.reflect.*
val annotation = TypeRepr.of[A].typeSymbol
val moduleTarget = TypeRepr.of[P].typeSymbol
def methodsFromPackage(packageSymbol: Symbol): List[Symbol] =
packageSymbol.declaredTypes
.filter(_.isClassDef)
.flatMap(_.declaredMethods)
def methodsAnnotatatedWith(
methods: List[Symbol],
annotation: Symbol
): List[Symbol] =
methods.filter(_.hasAnnotation(annotation))
def transformToFunctionApplication(
methods: List[Symbol]
): Expr[List[() => R]] =
val appliedDef = methods
.map(definition => Select(This(definition.owner), definition))
.map(select => Apply(select, List.empty))
.map(apply => '{ () => ${ apply.asExprOf[R] } })
Expr.ofList(appliedDef)
val methods = methodsFromPackage(moduleTarget)
val annotatedMethod = methodsAnnotatatedWith(methods, annotation)
transformToFunctionApplication(annotatedMethod)
}
Finally, you can use the macro as:
package org.tests
import org.tests.Macros.fruit
package foo {
#fruit
def check(): Int = 10
#fruit
def other(): Int = 11
}
#main def hello: Unit =
println("Hello world!")
println(Macros.findAllFunction[org.tests.foo, fruit, Int].map(_.apply())) /// List(10, 11)
Scastie

Defining variables in scala using def

In scala def is used to define a method and val, var are used for defining variables.
Consider the following code:
scala> def i = 3
i: Int
scala> i.getClass()
res0: Class[Int] = int
scala> val v = 2
v: Int = 2
scala> v.getClass()
res1: Class[Int] = int
scala> println(v)
2
scala> println(i)
3
scala> i+v
res4: Int = 5
scala> def o = () => 2+3
o: () => Int
scala> o.getClass()
res5: Class[_ <: () => Int] = class $$Lambda$1139/1753607449
Why does variable definition work using def? If it is defining a function that returns an Int then why does getClass show Int instead of a function object?
Unlike val or var declaration, def i = 3 is not variable declaration. You are defining a method/function which returns a constant 3 and i does not take any parameters.
declaration using val and var get evaluated immediately but in case of lazy val and def evaluation happens when called explicitly.
i is a not argument function. In order to get rid of confusion you could declare it using empty parenthesis as well
def i() = 3
Difference between lazy val and def is
lazy val is lazily evaluated and the result is cached. That means further
def declaration is evaluated every time you call method name.
Example using Scala REPL
scala> lazy val a = { println("a evaluated"); 1}
a: Int = <lazy>
scala> def i = { println("i function evaluated"); 2}
i: Int
scala> a
a evaluated
res0: Int = 1
scala> a
res1: Int = 1
scala> a
res2: Int = 1
scala> i
i function evaluated
res3: Int = 2
scala> i
i function evaluated
res4: Int = 2
scala> i
i function evaluated
res5: Int = 2
Notice that a is evaluated only once and further invocations of a return the cached result i.e lazy val is evaluated once when it is called and the result is stored forever. So you see println output once
Notice function is evaluated every time it is invoked. In this case you see println output every time you invoke the function
General Convention
There's a convention of using an empty parameter list when the method has side effects and leaving them off when its pure.
edited
scala> def i = 1
i: Int
scala> :type i
Int
scala> :type i _
() => Int
EDIT: My answer addresses the question of revision #3.
It is quite useful to look on the code in the middle of the compilation process where you can look on what your code is actually translated to. The following simple program:
object TestApp {
def definedVal = 3
val valVal = 3
lazy val lazyValVal = 3
def main(args: Array[String]) {
println(definedVal)
println(valVal)
println(lazyValVal)
}
}
is translated to the following (using -Xprint:mixin compiler option):
[[syntax trees at end of mixin]] // test.scala
package <empty> {
object TestApp extends Object {
#volatile private[this] var bitmap$0: Boolean = false;
private def lazyValVal$lzycompute(): Int = {
{
TestApp.this.synchronized({
if (TestApp.this.bitmap$0.unary_!())
{
TestApp.this.lazyValVal = 3;
TestApp.this.bitmap$0 = true;
()
};
scala.runtime.BoxedUnit.UNIT
});
()
};
TestApp.this.lazyValVal
};
def definedVal(): Int = 3;
private[this] val valVal: Int = _;
<stable> <accessor> def valVal(): Int = TestApp.this.valVal;
lazy private[this] var lazyValVal: Int = _;
<stable> <accessor> lazy def lazyValVal(): Int = if (TestApp.this.bitmap$0.unary_!())
TestApp.this.lazyValVal$lzycompute()
else
TestApp.this.lazyValVal;
def main(args: Array[String]): Unit = {
scala.this.Predef.println(scala.Int.box(TestApp.this.definedVal()));
scala.this.Predef.println(scala.Int.box(TestApp.this.valVal()));
scala.this.Predef.println(scala.Int.box(TestApp.this.lazyValVal()))
};
def <init>(): TestApp.type = {
TestApp.super.<init>();
TestApp.this.valVal = 3;
()
}
}
}
From the output above it is possible to conclude the following:
definedVal is actually a method.
valVal is a field which is initialized in the constructor and has an automatically generated accessor.
For the lazy field lazyValVal compiler generates compute method which is called only once when the field is accessed the first time.
There is few different concept. Call by name, call by value and call by need. All def is essentially calls by name. What do you mean variable definition using def ??
Looks like duplicate to me:
Call by name vs call by value in Scala, clarification needed
More details in wiki: https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name

Scala: function as a parameter to map()

How to use the map method in the Iterable trait in the example below?
As I understand this method will return a function which I have to call to execute internal logic.
trait Container[E] {
def += (e: E): Unit
}
trait Iterable[E, C[X] <: Container[X]]
{
def iterator(): Iterator[E]
def build[F](): C[F]
def map[F](f : (E) => F) : C[F] = {
val res = build[F]()
val iter = iterator()
while (iter.hasNext) res += f(iter.next())
res
}
}
class Buffer[T] extends Container[T]
{
val list = scala.collection.mutable.ListBuffer.empty[T]
def Children = list
def += (e: T): Unit = list += e
}
class Range(val low: Int, val high: Int) extends Iterable[Int, Buffer] {
def iterator() = new Iterator[Int]
{
private var i = low
def hasNext = i <= high
def next() = { i += 1; i - 1 }
}
def build[F]() = new Buffer[F]
}
val range = new Range(1, 3)
var list = range.map[String](_)
The method in question has the following signature:
trait Iterable[E, C[X] <: Container[X]] {
def map[F](f : (E) => F) : C[F]
// ...
}
First, let's look at the type of f argument. The signature (E) => F says that f is a function which takes a single argument of type E and returns a value of type F. Any function (or method) with this signature can be passed to map() as argument. See also Scala documentation.
Another important thing to understand is that the map function is generic with type parameter F. Value for this type parameter can either be specified manually or inferred by the compiler from the argument passed to map:
new Range(1,2).map[String](_.toString) // F is String
// new Range(1,2).map[Int](_.toString) // F is Int, compilation will fail
val mapFunction: Int => String = _.toString
new Range(1,2).map(mapFunction) // mapFunction is a function from Int to String,
// the compiler infers F is String
Basically, e.g. with Range, you can pass to the map() function any function which takes a single Int parameter (because Range binds E to Int) and returns anything (except for Unit). A few more examples:
val r = Range(1,2)
val v1: Buffer[String] = r.map(_.toString)
val v2: Buffer[Int] = r.map(i => i + 1)
val v3: Buffer[Double] = r.map(Int.int2double)
val i: Int = 1
val v4: Buffer[Int] = r.map(i.max)
As you can see, map() returns type Buffer[F] because that's what Range binds to the C[X] type parameter.
As #vitalii noted, the question is not related to higher-kinded types. For more information about those, check out other questions or blogs.
new Range(2,5).map(_.toString)

How to understand this Scala function call

I am Scala beginner. Below Scala code runs well, but I cannot understand it. Log shows, line 19 finally run to line 12. How could it be?
object TestClassDef {
class Person {
private var _age = 0
def age:Int = _age
def age_=(newAge: Int) = {
_age = newAge
println("age changed to " + _age) // line 12
}
}
def main(args: Array[String]) {
var p = new Person()
// p.age_=(25)
p.age = 26 // line 19
}
}
If I get your question correctly, you're surprised that the method is called when you assign the value on line 19. This is because the _= (at the end of the age function with an Int parameter) means that it's an assignment operator (also see What are all the uses of an underscore in Scala?) so it does make sense that it's called when you simply type p.age = 26.
This is mutator
def age_=(newAge: Int) = {
_age = newAge
println("age changed to " + _age)
}
So the call
p.age = 26
is converted by compiler to
p.age_=(26)
which makes call to mutator.
Mutator naming conventions from http://docs.scala-lang.org/style/naming-conventions.html
For mutators, the name of the method should be the name of the property with “_=” appended. As long as a corresponding accessor with that particular property name is defined on the enclosing type, this convention will enable a call-site mutation syntax which mirrors assignment. Note that this is not just a convention but a requirement of the language.
Also to see what compiler is creating pass -Xprint:typer to the Scala compiler. For reference the above code with this parameter generates:
package <empty> {
object TestClassDef extends scala.AnyRef {
def <init>(): TestClassDef.type = {
TestClassDef.super.<init>();
()
};
class Person extends scala.AnyRef {
def <init>(): TestClassDef.Person = {
Person.super.<init>();
()
};
private[this] var _age: Int = 0;
<accessor> private def _age: Int = Person.this._age;
<accessor> private def _age_=(x$1: Int): Unit = Person.this._age = x$1;
def age: Int = Person.this._age;
def age_=(newAge: Int): Unit = {
Person.this._age_=(newAge);
scala.this.Predef.println("age changed to ".+(Person.this._age))
}
};
def main(args: Array[String]): Unit = {
var p: TestClassDef.Person = new TestClassDef.this.Person();
p.age_=(26)
}
}
}
Scala allows non-alphanumerics in identifiers (in two ways):
case 1:
(specialcharacters)*
scala> val ##*# = 1000000
scala> val #Alpha# = 1 // mixing alphanumerics not allowed
case 2:
letter(alphanumerics)* _ (specialcharacters)*
scala> val k12? = 1 // doesn't work, _ is mandatory
scala> val k12_? = 1
scala> val k12_?*&^% = 1
scala> val k12_?Alpha = 1 // doesn't work, can't mix alphanumeric
Special cases:
Some symbols/combination-of-symbols are reserved e.g. = # <%
scala> val # = 1 // doesn't work
scala> val ### = 1 // works fine
scala> val <% = 1 // doesn't work
scala> val <%> = 1 // works fine
Some symbol-combinations are special, _= can be used in method names but not in variable names.
scala> val k_= = 1 // doesn't work
scala> def k_= = 1 // works fine
method names ending in _= are setters.
if a class/object's setter method def x_= is defined along with a parameter-less method of same name def x, then x = e is interpreted as x_=(e)

Initialize class parameter with a function in Scala

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.