Почему scala жалуется, когда данный шаблон соответствует интегральному значению? - PullRequest
3 голосов
/ 01 марта 2011

Цель : написать функцию, которая генерирует новую строку, исключая указанный символ (определяемый индексом)

Пример :

  • takeAllExcept(0, "abc") возврат bc
  • takeAllExcept(1, "abc") возврат ac
  • takeAllExcept(2, "abc") возврат ab

Что я сделализначально :

def takeAllExcept( index: Int, s: String ): String = {
  val lastIndex = s.length()-1
  index match {
    case 0 => return s.slice(1, s.length)
    case lastIndex => return s.slice(0, s.length()-1)
    case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
  }
}

Компилятор жалуется, что блок операторов для case _ недоступен.

Как я это исправил

def takeAllExcept( index: Int, s: String ): String = {
  val lastIndex = s.length()-1
  if( index == 0 )
    return s.slice(1, s.length)

  if( index == lastIndex )
    return s.slice(0, s.length()-1)

  s.slice(0, index) + s.slice(index+1, s.length)
}

Я хочу знать, почему моя первоначальная попытка не удалась с недоступным кодом.Это выглядит законным для меня.Кроме того, есть ли в Scala встроенное средство, которое уже делает это?

Ответы [ 3 ]

10 голосов
/ 01 марта 2011

lastIndex в шаблоне является неявным объявлением нового имени, которое связано с любым значением, введенным в совпадение, и скрывает уже определенное lastIndex, как уже указывалось в двух других постах.Есть две другие возможности вместо использования идентификаторов в верхнем регистре (см. Пост Питера):

Использование обратных галочек, чтобы сообщить компилятору, что это не должно быть объявлением нового идентификатора:

case `lastIndex` => ...

Использование шаблонных охранников:

case x if x == lastIndex => ...

Если вы хотите сделать много удаления на основе индекса для строк, то было бы быстрее использовать Buffer, вызвав toBuffer для строки, а затем вы можете использоватьremove(i: Int) метод Буфера.Это медленнее только для одной операции, потому что вам придется преобразовывать Buffer обратно в строку, когда вы закончите, но если вы выполняете много операций произвольного доступа, это намного быстрее.После того, как вы закончите, вы можете позвонить mkString в Buffer, чтобы вернуть вашу String.Для однократного удаления я бы сделал это так, как предложил Питер, или вот альтернатива:

def takeAllExcept(i: Int, s: String) = s.take(i) + s.drop(i+1)
6 голосов
/ 01 марта 2011

Ваш первый вопрос:

def takeAllExcept( index: Int, s: String ): String = {
  val LastIndex = s.length()-1
  index match {
    case 0 => return s.slice(1, s.length)
    case LastIndex => return s.slice(0, s.length()-1)
    case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
  }
}

lastIndex после case вновь связывается при сопоставлении с образцом и скрывает определение val lastIndex = s.length()-1.Как показывает мой пример, вы можете использовать имена в верхнем регистре, тогда scala использует определенную область действия val.

Чтобы ответить на ваш второй вопрос так, как я бы решил:

1 голос
/ 01 марта 2011
val lastIndex = s.length()-1
index match {
  case 0 => return s.slice(1, s.length)
  case lastIndex => return s.slice(0, s.length()-1)
  case _ => { s.slice(0, index) + s.slice(index+1, s.length) }
}

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

...