4

In Scala there are high order functions, which from what I understand either function that return function or function that accept function.

this for example is high order function that takes function from Int to Int:

def highOrderFunc(f: Int => Int) = {
   ???
}

why when i call highOrderFunc with List(1,2,3) it compiles? from this signature I though I need to pass a function...im confused here, can someone explain this please?

2 Answers2

3

List[A] extends Seq[A] which also extends PartialFunction[Int, A]:

trait Seq[+A] extends PartialFunction[Int, A]
                      with Iterable[A]
                      with GenSeq[A]
                      with GenericTraversableTemplate[A, Seq]
                      with SeqLike[A, Seq[A]]

And PartialFunction[Int, A] extends Function1[A, B] or (A => B). In your case A is Int, so Int => Int is a parent of PartialFunction[Int, Int] which is a parent of Seq[Int] which is a parent of List[Int].

That's why you can pass List[Int] as Function1[Int, Int] or Int => Int

Duelist
  • 1,562
  • 1
  • 9
  • 24
  • will have to be careful with that one then. Presumably this a conscious design decision on `Seq` rather than an undesired artefact of the collections hierarchy architecture? – joel Jul 02 '18 at 17:03
  • 1
    According to [this answer](https://stackoverflow.com/a/47537784/9128490) it is probably made for convenience because of method `apply` when we get element by index like `someList(1)` or `someSeq(1)` – Duelist Jul 02 '18 at 17:11
  • This is intended, and a useful feature. A list is just a mapping from index to value. Its apply method takes in the index, and returns a value. Syntactically, doThing(1) might be a list index or a function call, and there really shouldn't be any reason to care. In either case, we pass in an int and get something out. – Ethan Jul 02 '18 at 19:39
2

This works because a List(1, 2, 3) extends Int => Int. Somewhere up the class hierarchy, List extends Function1 (the actual trait behind the => syntax, which is just that, syntax). Try it, it'll be a partial function from index to elements.

@ val f : Int => Int = List(1, 2, 3) 
f: Int => Int = List(1, 2, 3)

@ f(2) 
res6: Int = 3

@ f(5) 
java.lang.IndexOutOfBoundsException: 5
  scala.collection.LinearSeqOptimized.apply(LinearSeqOptimized.scala:63)
  scala.collection.LinearSeqOptimized.apply$(LinearSeqOptimized.scala:61)
  scala.collection.immutable.List.apply(List.scala:86)
  scala.collection.immutable.List.apply(List.scala:86)
  scala.Function1.apply$mcII$sp(Function1.scala:36)
  scala.Function1.apply$mcII$sp$(Function1.scala:36)
  scala.collection.AbstractSeq.apply$mcII$sp(Seq.scala:41)
  ammonite.$sess.cmd7$.<init>(cmd7.sc:1)
  ammonite.$sess.cmd7$.<clinit>(cmd7.sc)
Reactormonk
  • 21,472
  • 14
  • 74
  • 123