pengyh
January 25, 2022, 10:14am
1
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.
kavedaa
January 25, 2022, 11:35am
2
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
pengyh
January 25, 2022, 12:06pm
3
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.
pengyh
January 25, 2022, 12:09pm
4
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
pengyh
January 25, 2022, 12:55pm
7
Thanks. Pipe looks really interesting.
pengyh
January 26, 2022, 1:16am
8
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