Я пытаюсь написать библиотеку измерений производительности для 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)
Как ни странно,у этого шаблона есть ряд недостатков:
- заставляет пользователя повторно использовать один и тот же символ при каждом вызове
- затрудняет выполнение более сложных операций, таких как предопределенные таймеры уровня проекта
- не позволяет библиотеке один раз инициализировать структуру данных для 'timerBigString
Так что здесь идет 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) (_: String)
, но это не то, что я хочу.Я хотел бы отложить ввод частично примененной функции до применения.
Я пришел к выводу, что компилятор решает тип возвращаемого значения частичной функции при первом ее создании, выбирая «Nothing», потому что он не можетсделайте более осознанный выбор.
Так что я думаю, что я ищу что-то вроде позднего связывания частично примененной функции.Есть какой-либо способ сделать это?Или, может быть, есть совершенно другой путь, по которому я мог бы пойти?
Ну, спасибо, что прочитали это далеко
-teo