2

私は Scala を初めて使用し、問題に遭遇しました。

関数のキューを保持するクラスを作成しようとしています。関数をキューに追加できるようにしたいのですが、すべての関数が追加されたら、これらを実行します。基本的に、返されて評価される "function1(function2(function3()))" のような式を作成します。これは私がこれまでに得たコードです:

  class Pipeline() {

    // Queue of functions to run
    private var queue: Queue[ _ => _] = new LinkedList();

    // Add functions to the queue 
    def addFunction(func:_ => _ ): Unit ={
      queue.add(func)
    }

    // Run all the functions in the queue
    def run(): Unit = {
      val function = runHelper(queue.poll(), queue)
      function
    }

    def runHelper(func: _ => _, queue: Queue[_ => _]): _  = {
      // Recursion base case
      if(queue.isEmpty)
        return func
      // Keep building the function recursively
      else
        func(runHelper(queue.poll(), queue))        
    }    
  }

ここには複数のエラーがあると確信しています。しかし今、私が立ち往生しているのは、runHelper 関数の戻り値の型です。ご覧のとおり、_ ワイルドカードを使用しようとしていますが、コンパイル エラーが発生します。関数が関数を返すことをどのように定義しますか? そして、私はこれについて良い方法で進んでいますか?そうでない場合は、問題のより適切な解決策の方向に私を向けてください.

edit1: 明確化 関数の入力と戻り値の型は事前に知られていないため、それらのシーケンスを動的に割り当てることができる必要があります。

Edit2: Edmondo1984 が提案したコードを希望どおりに動作させようとしてきたが、それを取得できないようだ。

私がする必要があるのは、次のようなものです。

val func1: String => File = function1
val func2: File => File = function2

var queue = func1

if(runFunc2)
    queue = queue :: func2

queue("exampleString")

特に知っておく必要があるのは、「queue = queue :: func2」を実行できるようにする方法です。:: は FunctionQueue を返すので、それをキュー変数に割り当てることができると想像していたでしょう。しかし、繰り返しになりますが、変数の最初の初期化により、「文字列 => ファイル」という要求が発生することになると思います。私はここで少し頭を悩ませているように感じます。どんな助けも大歓迎です。

4

5 に答える 5

3

私が関数に好む形式は次のとおり(parameter list) => returnTypeです。

これがあなたのコードがどのように見えるべきだと私が思うかです。私のIDEはそれが好きですが、それは保証ではありません。

class Pipeline[T]() {

 // Queue of functions to run
 private var queue: util.Queue[ (T) => T] = new util.LinkedList()

 // Add functions to the queue
 def addFunction(func: (T)=> T ) {
   queue.add(func)
 }

 // Run all the functions in the queue
 def run() {
   val function = runHelper(queue.poll(), queue)
   function
 }

 def runHelper(func: (T) => T, queue: util.Queue[(T)=> T ]): (T)=>T = {
   // Recursion base case
   if(queue.isEmpty)
     func
   // Keep building the function recursively
   else
     func compose runHelper(queue.poll(), queue)
  }
}
于 2012-07-11T13:52:00.130 に答える
3

関数合成を試してみてください。例えばこんな感じ。

val f = (x:Int) => 2 * x
val g = f.compose(f)

入力と出力のタイプが異なる場合は、入力と出力が一致するように注意する必要があります...

于 2012-07-11T13:53:37.887 に答える
1

実装に関しては、単純なList関数T => T(エンド関数と呼ばれます) を使用できます。

さて、scalaz では、そのような関数の ( and から構築された) のインスタンスがありMonoidます。つまり、次のコードを記述できます。SemigroupZero

scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._

scala> val f = ((_:Int) + 6).endo
f: scalaz.Endo[Int] = <function1>

scala> val g = ((_:Int) * 4).endo
g: scalaz.Endo[Int] = <function1>

scala> val h = (-(_:Int)).endo
h: scalaz.Endo[Int] = <function1>

scala> f :: g :: h :: nil
res3: List[scalaz.Endo[Int]] = List(<function1>, <function1>, <function1>)

scala> .asMA.sum
res4: scalaz.Endo[Int] = <function1>

scala> f(g(h(1)))
res5: Int = 2

scala> res4(1)
res6: Int = 2
于 2012-07-11T15:02:51.753 に答える
0

次のように関数のタイプを指定できます。

Function[T, T]

また

T => T

関数の入力と出力の両方が等しいと仮定すると、実際にはそうあるはずです。もちろん、指定または置換する必要がありますT

可変個引数の入出力がある場合、スキーム全体がはるかに複雑になります。

于 2012-07-11T13:35:08.957 に答える