Creating Scala 3 Functions

reviewing the Function docs: Function

it lists various members of Function types, however, i’m incapable of using any of them

val imNotaFunction: () => String = () => "wtf"
def imNotaFunctionEither = () => "wtf"
val amIaFunction: Function[String, String] = (x) => "wtf"

amIaFunction.chain(Seq(amIaFunction)) // value chain not a member
imNotaFunction.chain // value chain not a member
imNotaFunctionEither.chain // value chain not a member

using the syntax listed here (Basics | Tour of Scala | Scala Documentation) doenst work, so i’m sure i’m missing something

The functions are fine, see in Scastie:

wtf
wtf
wtf

What you probably are seeking is this:

val fun: Function[String, String] = (x) => s"$x? wtf!"
val combined = Function.chain(Seq(fun,fun))

println(combined("what"))

to get:

what? wtf!? wtf!

The point is, the method chain is defined on the object Function (to be used as Function.chain) and not on an instance with type Function to be used as you did above.

2 Likes

Hello @noahehall
There is a basic misunderstanding. Those members like chain etc. belong to the singleton object Function, not members of “Function types” as you interpreted.
Screenshot from 2022-07-05 10-19-34

In the REPL you would use them as:

 ➜ scala
Welcome to Scala 3.1.2 (11.0.15, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                                                                       
scala> val f: (Int => Int) = x => x * 2
val f: Int => Int = Lambda$1295/0x0000000840689040@70c56434
                                                                                                                                       
scala> val g: (Int => Int) = x => x * x
val g: Int => Int = Lambda$1313/0x00000008406b3840@269c7104
                                                                                                                                       
scala> val h = Function.chain(Seq(f,g))
val h: Int => Int = scala.Function$$$Lambda$1426/0x0000000840740040@73aae7a
                                                                                                                                       
scala> h(2)
val res0: Int = 16

As far as I can tell, the syntax in the “Tour of Scala” works, so I’m guessing you were mixing Function into it somehow.

I don’t think anyone would define functions by directly using types like Function[...], or Function1[...] or Function2[...]. At least I’ve never seen it outside of some academic explanations. These are all underlying implementation details of how Scala desugars our “normal” definitions. If I understand correctly (someone can correct me if I’m wrong), whenever we define a function value, Scala compiler creates an anonymous class instance that extends the appropriate trait FunctionN depending on the number of arguments… but nobody should bother to know that! It’s all hidden from us for good reason.

You seem to be making a very common mistake that so many others are making: trying to learn the language from documentation (not blaming you!). Please don’t do that! It’s like trying to learn a foreign language purely from a dictionary. It naturally leads to these misconceptions and makes you lose a ton of time. Documentation should be used for reference purposes only (just like a dictionary).

Instead take an online course or pick up a book. I recommend either “Get Programming with Scala” by Daniela Sfregola, or “Programming in Scala 5th Edition” by Odersky (which explains what a singleton object is in one of the earlier chapters on OOP).

2 Likes

I second that, the book is great, you will learn a lot from it! Available at Artima.

1 Like

Hilarious, fatigue is real. Not sure how I missed that :wink:

old habits die hard; the 5th edition looks sweet will put in an order

2 Likes

hello, do you mean that “chain” is only the public method of Function Object, not the member of class Function? and the method “chain” can be called from within the class Function, but can not be called from outside an instance of the class Function ?

There are many methods in the Function object including chain and many others:


There is no class named “Function”. There are a lot of traits Function0, Function1, …

1 Like

And there is the type alias Function, defined here.


(but indeed, no class with that name)

So, to answer your question @flysky8864 , indeed, you cannot call chain on instances of the type Function, for that method is lacking on the trait Function1. This has nothing to do with inside or outside any scope.

1 Like

If I understand correctly Function is a type alias for Function1 (which has its own separate companion object), but at the same time Function is the name of an object, that seems to be the source of the confusion? The Function object does not seem to be the companion object of any trait.

thanks.
I am not familiar with the companion class/object syntax. so want to check whether I understand rightly.
I mean: if a public method called foo is implement in the companion object named Bar but not implemented in the class Bar, an instance of class Bar called bar can not call the method foo, like bar.foo()? and vice versa?
and a method called foo2 implemented in the class Bar can directly call the method foo of object Bar?

This example tells it all:

class Bar :
  import Bar._
  def foo2: Int = foo

object Bar :
  def foo: Int = 42

val bar = new Bar
println(Bar.foo)
println(bar.foo2)

so your first assumption is correct, the second only after an import of Bar.foo

1 Like

No.

It appears you are still learning the basic infrastructure of Scala itself. And that you have not read the book “Programming in Scala” (5th Edition, but it is the same in all editions).

If you come from Java, think of the Companion Object as a Java class’s static methods.

Scala decided to formalize the notion of Java’s static methods into a Singleton called the Companion object. This means that any class/trait instance (i.e. non-static) method can call the (object) static methods. But, object static methods cannot call class/trait instances methods without a reference to a specific instance.

Again, if you are learning Scala, you really need to understand this basic infrastructure. Literally everything about Scala, both OOP and FP, is anchored around this self-referential bottom-up pattern.

1 Like

can you give me an example that object call the metod of instance method? in fact i have read the programming in scala 4th

Okay, let me see if i correctly understand your confusion. The analogy of static Java methods is only partial. The methods in the companion object are not literally static methods of the instances of the accompanied class. In Java you can do:

class Foo {
    public static int sBar() { return 42; }
    public int dBar() { return 21; } 
}

public class Main {
    
    public static void main(String[ ] args) {
        Foo foo = new Foo();
        System.out.println("sBar =" + foo.sBar());
        System.out.println("dBar =" + foo.dBar());
    }
}

But the analogous code in Scala would be:

class Foo :
  def dBar = 42

object Foo :
  def sBar = 21

val foo = new Foo
println("sBar = " + Foo.sBar)
println("dBar = " + foo.dBar)

and you cannot call foo.sBar in this situation.

So, how can you miminc this behaviour in Scala? The easiest way is declare them in the class definition via an export (Scala 3 feature), so that:

class Foo :
  export Foo.sBar
  def dBar = 42

object Foo :
  def sBar = 21

val foo = new Foo
println("sBar = " + foo.sBar)
println("dBar = " + foo.dBar)

will run.

But i think that, if you regularly find your self in this situation, you might be approaching the problem too much in a ‘Java’ way. Normally, you just directly call the method on the object.

2 Likes