Implicits-параметры функций как-то сильно настораживают.
За счёт него можно парой строк включить/выключить многопоточность - у конструктора класса Future есть неявный параметр ExecutorContext, и если его опустить, то что именно передастся в конструктор будет зависеть от того, какой именно неявный объект будет находится в области видимости:
importExecutionContext.Implicits.global //так импортируется объект implicit lazy val global: ExecutionContextExecutor implicitval threadPool = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(4)) //так создаётся свой пул потоков Future { println(i + " " + url); saveToFile(url, f"test/$i%03d.jpg") } //эти объявления повлияют на эту строку (в которой нет никакого упоминания ExecutionContext вообще!) //лучше всё время указывать неявный параметр явно: Future { println(i + " " + url); saveToFile(url, f"test/$i%03d.jpg") }(threadPool) //теперь видно, что между создаваемым объектов и местом его выполнения есть связь
Скала не перестаёт удивлять своей идиоматичностью - для каждой подзадачи находится несколько вариантов решения, часто однострочных.