I am having trouble understanding this Scala code involving a lambda expression:
object ScalaList {
case class Student(rollNo : Int, name : String, marks : Int)
val students= List(Student(1,"A",10),Student(2,"B",14))
var toppers = students.filter(s=>s.marks>10) //> toppers : List[ScalaList.Student] = List(Student(2,B,14))
}
It works, but the filter function takes an argument 's' that I didn't define. What is 's'. Also, if this were pandas, I think I would need to supply an axis=1 parameter. Why don't I need it in Scala
Perhaps it would help to compare Python implementation
>>> from pydantic import BaseModel
>>>
>>> class Student(BaseModel):
... rollNo: int
... name: str
... marks: int
...
>>> students = [
... Student(rollNo=1, name="A", marks=10),
... Student(rollNo=2, name="B", marks=14)
... ]
>>>
>>> list(filter(lambda s: s.marks > 10, students))
[Student(rollNo=2, name='B', marks=14)]
with similar Scala implementation
scala> case class Student(
| rollNo: Int,
| name: String,
| marks: Int
| )
| val students = List(
| Student(1, "A", 10),
| Student(2, "B", 14)
| )
| students.filter(s => s.marks > 10)
class Student
val students: List[Student] = List(Student(1,A,10), Student(2,B,14))
val res0: List[Student] = List(Student(2,B,14))
where we see Scala lambda
s => s.marks > 10
is similar to Python lambda
lambda s: s.marks > 10
which should make it clear that declared lambda parameter s
becomes a local variable inside the body of the lambda.
Consider Scala API documentation for List#filter as well as Scala for Python Developers section of Scala 3 Book.
Note that the argument to the filter
method is not s
, but rather the entirety of s => s.marks > 10
: this is the syntax to define an anonymous function that takes some s
and returns the result of the comparison of its marks
field with the literal 10
. In this context, s
is just the made up name of a parameter of the function, just like it would be if it was defined as a method as in the following example:
def marksGreaterThan10(s: Student): Boolean = s.marks > 10
One thing that could make someone a bit confused about the syntax is that the compiler itself is able to infer the types based on your input, making it very compact and readable, but perhaps a bit opaque for newcomers. Note that without the appropriate context (ie a list of Student
s is being filtered, therefore the input type of the function must be a Student
), the compiler would complain about the missing parameter type
and you would need to provide one, as in the following example (where I assign the anonymous function to a variable, so that I can use it in some other part of the program):
val marksGreaterThan10 = (s: Student) => s.marks > 10
Note that both a method and a function can be passed to a higher-order function (a function that can take a function as a parameter or return one as an output) like filter
.
final case class Student(marks: Int)
val marksGreaterThan10Function = (s: Student) => s.marks > 10
def marksGreaterThan10Method(s: Student): Boolean = s.marks > 10
val students = Seq(Student(1), Student(11))
// Both of these returns `Seq(Student(11))`
students.filter(marksGreaterThan10Function)
students.filter(marksGreaterThan10Method)
You can play around with the code above here on Scastie.
If you are familiar with the Java lambda expression syntax, ->
is more or less equivalent to =>
and you would have written something like:
students.stream().filter(s -> s.marks > 10)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.