Нарушает ли возврат ссылочную прозрачность?

Я читал описание инструмента Scala WartRemover и был сбит с толку одним из их пунктов. В описании сказано следующее:

return нарушает ссылочную прозрачность. Выполните рефакторинг для безопасного завершения вычислений.

// Won't compile: return is disabled
def foo(n:Int): Int = return n + 1
def foo(ns: List[Int]): Any = ns.map(n => return n + 1)

Для меня это не имеет никакого смысла, и оба примера выглядят ссылочно прозрачными. Есть ли способ, которым ключевое слово return повышает вероятность нарушения функцией ссылочной прозрачности? Я просто совершенно не понимаю их точку зрения?


person resueman    schedule 06.01.2015    source источник
comment
Я думаю, что предупреждение return предназначено для предотвращения использования, такого как def f(x : Int):Int = ((w : Nothing) => 3) (return x) (это функция идентификации, а не константа 3). Хотя я могу согласиться с запретом return (есть ли вообще причина для его использования в чистом коде?), Я бы не сказал, что ранний возврат нарушает ссылочную прозрачность, поскольку вы можете достичь того же эффекта, используя преобразование с продолжением передачи.   -  person chi    schedule 06.01.2015
comment
@chi, call / cc или подобные конструкции, которые позволяют вам получить первоклассный дескриптор вашего неявного продолжения, также не являются ссылочно прозрачными. Передача функции продолжения явно - это совсем другая история. То, что глобальное преобразование создает ссылочно прозрачную программу, не означает, что оригинал является ссылочно прозрачным (в противном случае изменяемое состояние также будет RT).   -  person Andreas Rossberg    schedule 06.01.2015
comment
@AndreasRossberg Понятно. Я, вероятно, путал RT return с чистотой foo.   -  person chi    schedule 07.01.2015


Ответы (1)


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

За исключением того, что операторы return вообще ничего не оценивают. Они заставляют текущий вызов включающего метода оценивать что-то. Это никак не укладывается в концепцию ссылочной прозрачности. Оператор throw имеет аналогичную проблему.

Для примеров первый

def foo(n:Int): Int = return n + 1

мягко, но многословно и не идиоматично. Второй

def foo(ns: List[Int]): Any = ns.map(n => return n + 1)

намного более проблематично. Если передан пустой список, он возвращает пустой список. Если передан непустой список, он возвращает значение заголовка списка плюс 1.

person Dave Griffith    schedule 06.01.2015
comment
Почему вторая проблема? = if (ns.isEmpty) () else ns.head + 1 ведет себя так же без return? - person The Archetypal Paul; 06.01.2015
comment
Поскольку наивное чтение (при котором возвращение становится оценкой функции, а не методом) равно ns.map (_ + 1), почти наверняка это то, что задумал программист. Гораздо более вероятно, что возвращение - случайный Java-ism, чем то, что семантика, которую вы описываете, на самом деле является тем, что хотел сказать программист. - person Dave Griffith; 06.01.2015
comment
Я согласен, это могло быть ошибкой. Я думаю, мне не хватает связи с нарушением ссылочной прозрачности - person The Archetypal Paul; 06.01.2015