Apply several transformation functions to string

Refresh

December 2018

Views

227 time

2

Suppose I have 2 methods:

def a(s: String) = s + "..."

def b(s: String) = s + ",,," 

And I want to create 3rd method which will call both methods:

def c (s: String) = a(b(s))

How I can do it in idiomatic Scala way?

I think it's better to aggregate this functions into some List and then sequentially apply them:

List(a_, b_)

5 answers

0

Если вы действительно думаете , что вам нужно сделать это:

val c = a _ andThen b

// (The signature is:)
val c:(String)=>String = a _ andThen b

или, что более очевидно:

def d(s:String) = a _ andThen b
3

Я думаю, что лучше агрегировать эти функции в какой-то список, а затем последовательно применять их.

Вы получаете некоторую помощь, указав ожидаемый тип:

scala> val fs: List[String => String] = List(a,b)
fs: List[String => String] = List(<function1>, <function1>)

scala> fs.foldLeft("something")((s,f) => f(s))
res0: String = something...,,,
1

Многие ответы используют andThen, но это будет дать вам

b(a(s))

Учитывая то, что вы хотите

a(b(s))

compose это путь (ну, или реверсивный список, но какой смысл?)

def c(s: String) = List[String => String](a, b).reduce(_ compose _)(s)
// or alternatively
def c(s: String) = List(a _, b _).reduce(_ compose _)(s)

В следствии

c("foo") // foo,,,...

Теперь, говоря о том, что это идиоматическое, я считаю, что

a(b(s))

более идиоматические и читаемый, чем

List(a _, b _).reduce(_ compose _)(s)

Это, безусловно, зависит от количества функций, которые вы пишете. Если вы должны были иметь

a(b(c(d(e(f(g(h(s))))))))

затем

List[String => String](a, b, c, d, e, f, g, h).reduce(_ compose _)(s)

Вероятно, аккуратнее и более идиоматических, а также.

0

Если приковано приложение является предпочтительным, то ниже работой. Предостережения - неявный синтаксис немного некрасиво; Это является структурным тип использует отражение.

object string {
  implicit def aPimp(s: String) = new {
    def a = "(a- " + s + " -a)"
  }
  implicit def bPimp(s: String) = new {
    def b = "(b- " + s + " -b)"
  }
}

scala> import string._
scala> "xyz".a.b
res0: String = (b- (a- xyz -a) -b)
scala> "xyz".b.a
res1: String = (a- (b- xyz -b) -a)

На моем взгляде, если бы не уродливый синтаксис, это было бы идиоматическое Scala.

2

Вот как вы можете объединить множество функций в одном:

// a() and b() are as defined in the question 
// the following is equivalent to newfunc(x) = b(a(x))   
val newFunc: String => String = List( a _, b _).reduce( _ andThen _ )

Вы даже можете создать обобщенную функцию, чтобы объединить их:

def functionChaining[A]( functions: A => A *): A => A = functions.reduce( _ andThen _ )

или с помощью foldLeft:

def functionChaining[A]( functions: A => A *): A => A  = functions.foldLeft( (x:A) => x )( _ andThen _ )

Вот пример того, как использовать это на РЕПЛ:

scala> val newFunc: String => String = functionChaining( (x:String) => x + "---", (x:String) => x * 4)
scala> newFunc("|")
res12: String = |---|---|---|---