2015-10-29 4 views
0

Я ищу что-то в Скале, чтобы написать следующий код в более компактном виде:Scala обертка для беглых побочных эффектов

def getSomething():X = { 
    val result = compute(...) 
    println(result) 
    result 
} 

Я имею в виду что-то вроде этого:

def getSomething():X = { 
    MagicWrapper(compute(...)).do(println) 
} 

так, что do выполняется, но возвращается исходное значение. похоже, что такая вещь должна существовать где-то, но я ничего не мог найти.

+1

Похоже [Kestrel комбинатора] (http://combinators.info/#kestrels) –

+0

@ PatrykĆwiek но ... но это * рубин *: O –

+0

@ Золтан Ну, это достаточно читаемый и [есть и другие вопросы и ответы, адресованные ему в Scala] (http://stackoverflow.com/a/9673294/1180426) :) –

ответ

3

Используйте расширения-мою библиотеку схему:

implicit class SideEffectPassthrough[A](val a: A) extends AnyVal { 
    def se(sideEffectFunction: A => Unit): A = { 
    sideEffectFunction(a) 
    a 
    } 
} 

def compute(a: Int) = a + 2 + 3 
val x = compute(1).se(println) 
// x: Int = 6 

компилятор сделает упаковку для вас, делая уборщик синтаксиса. Обратите внимание, что когда мы добавляем extends AnyVal, мы фактически гарантируем, что компилятор перепишет этот код так, чтобы он буквально не делал никаких оберток, вместо этого он создаст статическую функцию для обработки поведения, что означает меньшую накладную часть времени выполнения, поскольку ни один объект обертка не нужно будет создавать экземпляры)

sideEffectFunction аргумент se может быть любой произвольной функции, до тех пор, как он принимает, как это аргумент, результат предыдущего выражения:.

val y = compute(1).se { r => 
    println("Performing a side effect now!") 
    println(r) 
} 
// y: Int = 6 

Просто для полноты, вот иная w ау для достижения тех же целей:

def printAndReturn[A](block: => A): A = { 
    val result = block 
    println(result) 
    result 
} 

val x = printAndReturn(1+2+3) 
// x: Int = 6 

val y = printAndReturn { 
    val a = 1 + 2 
    a + 3 
} 
// y: Int = 6 

Аргумента block может быть любым произвольным выражением, в том числе любого произвольного блока кода. Обратите внимание, что он передается по имени, поэтому он оценивается внутри se.

Смежные вопросы