Подтвердить что ты не робот

Что означает "code: => Unit" в scala?

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

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

test(print(1))

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

Спасибо

4b9b3361

Ответ 1

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

=> B представляет собой блок a кода, который возвращает значение 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

Дополнительные различия между параметром имени и параметром байта значения

Ответ 2

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

Ответ 3

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

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

Вызов по стоимости является, безусловно, самой общей стратегией оценки. Это единственная стратегия в 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. Сравните это с этой программой на С++ с помощью вызова по ссылке:

#include <stdio.h>

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

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

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

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

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

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 }

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

  • Его можно использовать для задержки выполнения чего-либо до нужного времени.
  • Его можно использовать, чтобы избежать выполнения в некоторых ситуациях.
  • Он может использоваться для выполнения нескольких блоков кода несколько раз.

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

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.

Ответ 4

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

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