Make an member function

scala> def test(s:String)(f:String=>String) = f(s)
def test(s: String)(f: String => String): String

scala> test("hello") { x=>x.reverse }
val res0: String = olleh

scala> "hello".test { x=>x.reverse }
               ^
       error: value test is not a member of String

I want to make above test() to become a member of String class. what’s the easiest way? Thank you.

If you’re on Scala 3, you can do:

scala> extension (x: String) def test(f: String => String) = f(x)
def test(x: String)(f: String => String): String

scala> "hello".test(_.reverse)
val res3: String = olleh

It won’t technically “become a member of the String class”, but it will behave as if it is.

2 Likes

thanks for reply. but I am using 2.13 version.

Scala code runner version 2.13.7 -- Copyright 2002-2021, LAMP/EPFL and Lightbend, Inc.

and, may I know this is a singleton defined by extension?

Easiest way - scala3 extension method
2.13 way - implicit should be in scope and only one should be in scope

implicit class Something(s:String){
    def test(f:String=>String) = f(s)
}

"hello".test { x=>x.reverse }
1 Like

Just to complement @ndas1971 post, if you want the extension to don’t have additional cost in runtime you need to make it like this:

implicit class Something(private val s:String) extends AnyVal {
    def test(f:String=>String) = f(s)
}

BTW, this particular method is already provided by the stdlib is called pipe

import scala.util.chaining._

"hello".pipe(x => x.reverse)
2 Likes

Thanks. Pipe looks really interesting.

Hello

can pipe accept a if…else statement?

scala> "world".pipe {if (_.size > 4) true else false }
                         ^
       error: missing parameter type for expanded function ((<x$1: error>) => x$1.size.$greater(4))
                                     ^
       error: type mismatch;
        found   : Boolean(true)
        required: String => ?
                                               ^
       error: type mismatch;
        found   : Boolean(false)
        required: String => ?

This doesn’t work for me. please help take a look. thank you.

It does accept if, you just need to use proper lambda syntax instead of the _ one.

"world".pipe { w => if (w.size > 4) true else false }

This is because the _ syntax expanded like:

"world".pipe { if (x => x.size > 4) true else false }

Which is not what you want and doesn’t typechecks.
This is one of the reasons why I suggest not using _

BTW, your ìf is redundant, you can just do:

"world".pipe { w => w.size > 4 }

To get the same result.
At which point, you may use _ again if you really want to (again I would advise not)

"world".pipe(_.size > 4)

Since now the expansion works as expected.

2 Likes