Я пытаюсь написать библиотеку измерения производительности для Scala. Моя идея состоит в том, чтобы прозрачно «отмечать» разделы, чтобы можно было собирать время выполнения. К сожалению, мне не удалось подчинить компилятор своей воле.
По общему признанию, надуманный пример того, что я имел в виду:
// generate a timing function
val myTimer = mkTimer('myTimer)
// see how the timing function returns the right type depending on the
// type of the function it is passed to it
val act = actor {
loop {
receive {
case 'Int =>
val calc = myTimer { (1 to 100000).sum }
val result = calc + 10 // calc must be Int
self reply (result)
case 'String =>
val calc = myTimer { (1 to 100000).mkString }
val result = calc + " String" // calc must be String
self reply (result)
}
Это самое дальнее, что я получил:
trait Timing {
def time[T <: Any](name: Symbol)(op: => T) :T = {
val start = System.nanoTime
val result = op
val elapsed = System.nanoTime - start
println(name + ": " + elapsed)
result
}
def mkTimer[T <: Any](name: Symbol) : (() => T) => () => T = {
type c = () => T
time(name)(_ : c)
}
}
Использование функции time
работает напрямую, и компилятор правильно использует возвращаемый тип анонимной функции для ввода функции 'time':
val bigString = time('timerBigString) {
(1 to 100000).mkString("-")
}
println (bigString)
Каким бы замечательным это ни казалось, этот шаблон имеет ряд недостатков:
Итак, здесь идет mkTimer, который позволит мне частично применить функцию времени и повторно использовать ее. Я использую mkTimer следующим образом:
val myTimer = mkTimer('aTimer)
val myString= myTimer {
(1 to 100000).mkString("-")
}
println (myString)
Но я получаю ошибку компилятора:
error: type mismatch;
found : String
required: () => Nothing
(1 to 100000).mkString("-")
Я получаю ту же ошибку, если встраиваю каррирование:
val timerBigString = time('timerBigString) _
val bigString = timerBigString {
(1 to 100000).mkString("-")
}
println (bigString)
Это работает, если я выполняю val timerBigString = time ('timerBigString) ( _: Строка)
, но я не этого хочу. Я хотел бы отложить ввод частично примененной функции до приложения.
Я пришел к выводу, что компилятор определяет тип возвращаемого значения частичной функции, когда я впервые ее создаю, выбирая «Ничего», потому что это не может улучшить осознанный выбор.
Итак, я предполагаю, что я ищу своего рода позднюю привязку частично примененной функции. Есть какой-либо способ сделать это? Или, может быть, я мог бы пойти по совершенно другому пути?
Что ж, спасибо, что дочитали до этого места
-teo