So I have an array and I can do:
myArr.lift(0)
...and it gives me option of the value at index 0.
So what actually is happening here? When I try to go to lift definition, IDE takes me to PartialFunction, and I see Array doesn't inherit from it.
And whats the usecase for using lift?
CodePudding user response:
It is true that Array
is primitive native to JVM and doesn't have any lift
method.
However in Scala we have implicit conversions and extension methods and this is what we expect to find when we are able to call methods not defined for some type.
If you write the code in IntelliJ and use a magic shortcut for showing implicits (also available in metals)you'll see that your code is turned into e.g (assuming array of ints):
wrapIntArray(myArr).lift(0)
where wrapIntArray
is defined in scala.Predef
(see Array to ArraySeq section) as
implicit def wrapIntArray(xs: Array[Int]): WrappedArray[Int] = if (xs ne null) new WrappedArray.ofInt(xs) else null
(in Scala 2.13 WrappedArray
is deprecated and became aliased to ArraySeq
).
If you are curious why it is in your scope remember that by default Scala compiler imports all definitions from the following paths:
scala
- to import allscala.Int
,scala.Char
and other primitivesscala.Predef
- to aliasMap
toscala.collection.immutable.Map
, add wrappers aroundArray
, let you useprintln
instead of scala.Console.println, etcjava.lang
- to import things likeThrowable
(I wrote "default" because you can change it with -Yimports
but custom predef is something I wouldn't recommend if you don't have experienced devs and good documentation around).
What is the use case of lift
? Basically all Scala collections share some common traits and PartialFunction
is one of them:
- you can use
apply
to get the value but riskingException
if index/key is wrong (e.g.vector(10)
) - you can use
applyOrElse
to get the value or some fallback value - you can check if there is something for key/index with
isDefinedAt
so your collection can be used for anything that expectPartialFunction
e.g.coll1.collect(coll2)
would map all elements ofcoll1
into values ofcoll2
treating values fromcoll1
as keys/indices used for queryingcoll2
Reasoning is pretty simple - if you are accessing values in collection like coll(index)
you are using it like function, but since it is not a total mapping it should be a partial function.
For PartialFunction
s lift
is just a nice utility to return Option[Value]
instead of Value
or Exception
on apply
, that you just got because WrappedArray
like any other collection inherit from it.