Что означает "code: => Unit" в scala? - PullRequest
19 голосов
/ 09 июня 2011

Кто-нибудь знает тип единицы измерения в scala?Я не знаю, что означает => Unit и как его использовать.Я определил функцию, как показано ниже:

def test(code: => Unit){
   print("start ...")
   code
   print("end ....")
}

test(print(1))

Означает ли это функцию с аргументами, возвращающими Unit?

Спасибо

Ответы [ 4 ]

23 голосов
/ 09 июня 2011

Этот тип параметра называется по имени параметр

=> B представляет блок кода, который возвращает значение B, их цель состоит в том, чтобы они оценивались только при вызове параметра.

def foo(code: => Int) {
    println("Not yet evaluated")
    val result = code
    println("parameter evaluated %s, is it an int ? %s " format (
           result, result.isInstanceOf[Int]) )
}

И вы можете позвонить foo следующим образом:

foo(1) 

или

val a = 3
val b = 5
foo {
  val c = a * a
  c * b
}

Другой стиль передачи параметра - по значению : параметры оцениваются перед отправкой в ​​метод

def foo(code : Int) {
    println("Parameter already evaluated")
    val result = code
    println("parameter evaluated : " + result)
}

Ссылки

Выписка из книги Функциональное программирование в Scala

Показано больше различий между параметром по имени и параметром по значению

12 голосов
/ 09 июня 2011

В x: => Type x - это вызов по имени . Это отличается от принятия аргумента, который является функцией без аргументов: x: () => Type

8 голосов
/ 10 июня 2011

Это называется параметром по имени , что относится к стратегии оценки параметров по имени.Пожалуйста, смотрите в связанной статье в Википедии похожие, но не идентичные способы передачи параметров.

Чтобы объяснить это лучше, давайте сначала рассмотрим две наиболее распространенные стратегии оценки параметров: вызов по значению и вызов по ссылке.

Call by value - безусловно, самая распространенная стратегия оценки.Это единственная стратегия в Java, например, и стратегия по умолчанию в C. Рассмотрим, например, эту простую Java-программу:

public class ByValue {
    static public void inc(int y) {
        y++;
    }

    static public void main(String... args) {
        int x = 0;
        inc(x);
        System.out.println(x);
    }
}

Она напечатает 0, потому что xзначение копируется в y, поэтому при увеличении y исходное значение в x не изменяется.Сравните это с этой программой на C ++ с помощью вызова по ссылке:

#include <stdio.h>

void inc(int &y) {
    y++;
}

int main() {
    int x = 0;
    inc(x);
    printf("%d\n", x);
}

Это выведет 1, потому что ссылка на x передается inc вместо *Значение 1022 *.

Обратите внимание, что Java передает ссылки на объекты по значению, что заставляет некоторых утверждать, что он вызывает по ссылке.Это не так, если вы назначите объект new параметру функции, это не будет отражено в вызывающей функции.

Итак, что делаетвызов по имени выглядит?При вызове по имени не передается ни значение, ни ссылка.Вместо этого передается весь код , и везде, где используется параметр, выполняется код и используется его результат.Например:

object ByName {
  def incIfZero(y: => Int): Int = if (y == 0) y + 1 else y

  def main(args: Array[String]) {
    var x = 0
    x = incIfZero( { val tmp = x; x += 1; tmp } )
    println(x)
  }
}

В этом примере печатается 2 вместо 1, поскольку блок кода, переданный в качестве параметра, оценивается дважды.При выполнении это выглядит так, как будто вторая строка в main была написана так:

x = if ({ val tmp = x; x += 1; tmp }) { val tmp = x; x += 1; tmp } + 1 else { val tmp = x; x += 1; tmp }

Теперь параметры по имени имеют как минимум три интересных применения:

  1. Этоможет использоваться для задержки выполнения чего-либо до надлежащего времени.
  2. Может использоваться для избегать выполнения в некоторых ситуациях.
  3. Может использоваться для выполнениянесколько блоков кода несколько раз.

Первый и последний случаи, я думаю, довольно очевидны.Вот пример второго случая:

implicit def fromBoolean(b: Boolean) = new { 
  def and(that: => Boolean): Boolean = if (b) that else b }
val x = 0
(x > 0) and (10 / x > 0)

Если бы that не был параметром по имени, в последней строке было бы исключение.Как это, он просто вернет false.

1 голос
/ 09 июня 2011

Это означает вызов по имени, что в основном означает, что значение вычисляется при использовании в вашей функции. В отличие от вызова по значению, который используется по умолчанию в Java (и Scala с синтаксисом обычного типа), где значение вычисляется до вызова метода. Я полагаю, что тип единицы не имеет особого смысла в вызове по значению ..

Это обычно используется для создания функций, которые ведут себя как пользовательские структуры управления или такие вещи, как синхронизация или ведение журнала, как в вашем примере. Вещи, которые вы часто используете AOP для Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...