проблемы с пониманием с картой и картой в Scala - PullRequest
1 голос
/ 04 ноября 2011

Я попытался создать какой-нибудь удобный класс (ниже) для хранения папки и получения файла, используя имя файла (строку). Эта работа, как и ожидалось, но одна вещь, которую я не понимаю, это часть карты Map(folder.listFiles map {file => file.getName -> file}:_*).

Я помещаю туда :_*, чтобы предотвратить несовместимость какого-либо типа, но я не знаю, что он делает на самом деле. Кроме того, что такое _* и можно ли заменить на что-то более конкретное?

спасибо

class FolderAsMap (val folderName:String){
  val folder = new File(folderName)
  private val filesAsMap: Map[String, File] = Map(folder.listFiles map 
                                          {file => file.getName -> file}:_*)

  def get(fileName:String): Option[File] = {
    filesAsMap.get(fileName)
  }
}

Ответы [ 2 ]

8 голосов
/ 04 ноября 2011

: _ * правильно.Кроме того, вы можете использовать toMap:

folder.listFiles map {file => file.getName -> file}.toMap

Map(...) - это метод apply в объекте Map: def apply [A, B] (elems: (A, B)*): Map[A, B].У него повторный параметр.Ожидается, что он будет вызван с несколькими параметрами.: _ * Используется для указания того, что вы передаете все параметры как один аргумент Seq.

Избегает неясностей.В java (где эквивалентные varargs являются массивами вместо Seqs) возможна неоднозначность, если метод f(Object... args) и вы вызываете его с помощью f(someArray), это может означать, что args имеет только один элемент, с someArray (поэтому fполучает массив только из одного элемента, который someArray), или аргументы someArray и f получает someArray напрямую).Ява выбираю вторую версию.В scala с более богатой системой типов и Seq, а не Array неоднозначность может возникать гораздо чаще, и правило состоит в том, что вы всегда должны писать: _ * при передаче всех аргументов как одного, даже когда нет двусмысленностивозможно, как здесь, а не сложное правило, чтобы сказать, когда есть фактическая неопределенность.

2 голосов
/ 04 ноября 2011

_* заставляет компилятор передавать каждый элемент folder.listFiles map { file => file.getName -> file} в качестве собственного аргумента Map вместо всего его в качестве одного аргумента.


В этом случае mapФункция создает Array (потому что folder.listFiles возвращает этот тип).Поэтому, если вы напишите:

val files = folder.listFiles map { file => file.getName -> file }

... возвращаемый тип будет Array[(String, File)].Чтобы преобразовать это в Map, вам нужно будет передать files один за другим конструктору карт, используя _* (или использовать метод toMap, как писал @didierd):

val filesAsMap = Map(files : _*)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...