Возможно ли сопоставление с шаблоном в стиле Haskell для Scala Strings? - PullRequest
0 голосов
/ 24 января 2019

Мне просто любопытно.

Я пытаюсь сделать строки сопоставления с образцом в Scala способом Haskell (как список символов)

В качестве примера, эта функция удаляет первый символ "/" в строке:

import scala.language.implicitConversions

implicit def stringToChars(s: String): List[Char] = s.toCharArray.toList

implicit def charsToString(a: List[Char]): String = a.mkString

def filterFirstSlash: Function[List[Char], String] = {
  case Nil => ""
  case '/' :: Nil => ""
  case '/' :: xs => xs
  case xs => xs
}

использование:

println(filterFirstSlash("/test"))

Можно ли удалить косую черту с помощью сопоставления с шаблоном?Это хорошо, чтобы сделать это таким образом?

upd

это удалит все записи в голове и хвосте:

def removeAllSlashes: Function[List[Char], String] = {
    case Nil => ""
    case '/' :: xs => removeAllSlashes(xs)
    case xs :+ '/' => removeAllSlashes(xs)
    case xs => xs
}

это будетудалить только первые записи:

def removeFirstSlash: Function[List[Char], String] = {
    case Nil => ""
    case ('/' :: xs) :+ '/' => xs
    case '/' :: xs => xs
    case xs :+ '/' => xs
    case xs => xs
}

ps Не принимайте это всерьез.Это просто для удовольствия.Спасибо всем, кто участвовал в обсуждении.

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Возможно, технически:

def filterFirstSlash(s: String) = {
  case '/' +: xs => xs
  case xs => xs
}

Конечно, не так эффективно, как тот же код для связанного списка, так как +: копирует всю строку каждый раз, так что вы не захотите использовать это для рекурсивного выделения строк.

0 голосов
/ 24 января 2019

Нет, это не очень хороший способ сделать это. String s не являются списком символов. В JVM строки - это довольно неизменные массивы кодовых блоков UTF-16. Они не имеют ничего общего со связанными списками. Ваш filterFirstSlash всегда будет игнорировать первые три случая и всегда будет возвращать ввод без изменений.

Чтобы сбросить косую черту, вы можете сделать что-то вроде этого:

"////abcd".dropWhile(_ == '/')  // returns `"abcd"`

или

"/abcd".replaceAll("^/", "")

или

((s: String) => if (s startsWith "/") s.tail else s )("/abcd")

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

val Rgx = "^/(.*)$".r
"/abcd" match { case Rgx(s) => s; case s => s }      // evaluates to `"abcd"`
...