Як працює "20 секунд" у Scala?


130

Як складається наступне:

import scala.concurrent.duration._

val time = 20 seconds

Що насправді відбувається тут?

Відповіді:


171

Дещо відбувається.

По-перше, Scala дозволяє опускати точки та парени з багатьох викликів методів, тому 20 secondsеквівалентно 20.seconds()*.

По-друге, застосовується "неявна конверсія". Так як 20це Intі Intне має ніякого secondsметоду, компілятор шукає неявне перетворення , який приймає Intі повертає то , що дійсно є в secondsметоді, з пошуком туги рамкою вашого виклику методу.

Ви імпортували DurationInt у свій обсяг. Оскільки DurationIntце неявний клас з Intпараметром, його конструктор визначає неявне Int => DurationIntперетворення. DurationIntмає secondsметод, тому він задовольняє всім критеріям пошуку. Тому компілятор переписує ваш дзвінок як new DurationInt(20).seconds**.

* Я маю на увазі це вільно. 20.seconds()насправді недійсний, оскільки secondsметод не має списку параметрів, і тому паролі повинні бути опущені під час виклику методу.

** Насправді це не зовсім вірно, оскільки DurationIntце клас значень, тому компілятор уникне обгортання цілого числа, якщо це можливо.


83
Будь-яка досить вдосконалена технологія не відрізняється від магії.
ripper234

4
На щастя, більшість ІДЕ здатні розрізнити це! Неявні перетворення звикають досить багато в Scala. Якщо ви просто читаєте текстовий файл, це може бути заплутаним ("звідки цей метод походить"), але при відповідній підтримці інструментів ви зможете знайти свій шлях, і тоді Scala може бути дуже значущим і стислим. (наприклад, 20 секунд набагато читабельніше, ніж new DurationInt(20).seconds()поки ви знаєте, як це робиться)
Вільям

1
Якщо ви все-таки користуєтесь неявними, завжди запитайте себе, чи є спосіб досягти того ж без їхньої допомоги. twitter.github.com/effectivescala/#Types and
Generics-Implicits

4
Насправді secondsметод визначений без паролів, тому викликати його паролями - це помилка.
Френк С. Томас

1
@Frank Це хороший момент. Я не хотіла припускати, що ви можете писати 20.seconds()в Scala, лише що компілятор перекладає виклик саме так. Варто зазначити, що Scala вимагає опустити паролі, якщо відповідний метод не має списку параметрів, як у цьому випадку.
Аарон Новструп

7

"Магія", що там відбувається, називається "неявна конверсія". Ви імпортуєте неявні конверсії, а деякі з них обробляють перетворення між Int (і Double) у Duration. Ось з чим ви маєте справу.


1
Будь-яка ідея, чому імпорт import scala.concurrent.duration._вирішує, 20 secondsа насправді імпорт DurationConversionsриси не робить? EDIT : Щойно зрозумів, що вони насправді імпортують DurationInt. Я здогадуюсь це тому, що ви не можете імпортувати фактичну ознаку? Лише конкретна реалізація риси?
франклін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.