[英]How to assign a function as a return type from function in Scala
我對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:澄清函數的輸入和返回類型事先是未知的,它們的序列需要能夠動態分配。
編輯2:更多的問題我一直試圖讓代碼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,我想我可以將它分配給隊列變量。 但話說回來,我想,因為變量的第一次初始化導致它具有“String => File”需求。 我覺得我在這里有點過頭了,任何幫助都會非常感激。
我更喜歡函數的形式是:( (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)
}
}
你可以嘗試一下函數組合。 比如這樣。
val f = (x:Int) => 2 * x
val g = f.compose(f)
如果輸入和輸出類型不同,你必須注意輸入和輸出匹配...
您嘗試做的是不可能的,因為_是存在類型的占位符:存在但當前不相關的類型:例如,當您要打印如下列表時,可以使用它:
scala> def aMethod(a:List[_]) = println(a.size)
aMethod: (a: List[_])Unit
scala> val b = List(2,3,4)
b: List[Int] = List(2, 3, 4)
scala> aMethod(b)
3
這是有效的,因為事實上你不能訪問列表的元素,所以你可以想象你不需要他們的類。
因為Scala是一種強類型語言,即編譯器檢查代碼中是否遵守了簽名。 隊列[_ => _]是從未知類型到未知類型的函數隊列,它沒有用,因為如果您嘗試彈出一個函數並將其應用於輸入參數,您將無法驗證輸入參數是否與簽名匹配。
您要做的事情並非無足輕重,您需要以遞歸方式定義隊列。 您可能希望閱讀Shapeless HLIST實現,但其想法如下:
trait FunctionQueue[A,B]{
def ::[C](newFunction: C => A): FunctionQueue[C,B]
def apply(a:A):B
}
class FunctionQueueImpl[A,B,C](val f:A=>B, val queue:FunctionQueue[B,C]) extends FunctionQueue[A,C]{
def apply(a:A) = queue.apply(f(a))
def ::[D](newFunction: (D) => A):FunctionQueue[D,C] = new FunctionQueueImpl[D,A,C](newFunction,this)
}
object FunctionQueue {
def EmptyQueue[T]:FunctionQueue[T,T] = new FunctionQueue[T,T] {
def ::[C](newFunction: (C) => T):FunctionQueue[C,T] = new FunctionQueueImpl[C,T,T](newFunction,this)
def apply(a: T):T = a
}
implicit def functionToQueue[A,B](function:A => B):FunctionQueue[A,B] = new FunctionQueueImpl(function, EmptyQueue[B])
}
現在你可以在repl中嘗試它:
scala> import FunctionQueue._
import FunctionQueue._
scala> val a: Int => Int = _ * 10
a: Int => Int = <function1>
scala> val b: Double => Int = _.toInt
b: Double => Int = <function1>
scala> val c : String => Double = _.toDouble
c: String => Double = <function1>
scala> val queue = c::b::a
queue: FunctionQueue[String,Int] = FunctionQueueImpl@cccfa5e
scala> queue("1.25")
res1: Int = 10
scala> queue("3.25")
res2: Int = 30
我建議閱讀Miles Sabins的工作以了解更多。
關於實現,您可以使用一個簡單的函數List
T => T
(稱為內部函數)。
現在,在scalaz你有一個實例Monoid
(從建成Semigroup
和Zero
這樣的功能)。 這意味着,您可以編寫以下代碼:
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
您可以指定函數的類型,如下所示:
Function[T, T]
要么
T => T
假設你的函數的輸入和輸出都是相同的,它們應該是真的。 您當然必須指定或替換T
如果你真的有可變輸入輸出,整個方案將變得更加復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.