Разделить список символов на список слов

В настоящее время я изучаю функциональный язык SML, и я пытаюсь создать функцию, которая принимает список символов, а затем ищет любые пробелы в списке, когда находит пробел, он объединяет символы перед пробелом, чтобы создать строку после что он возвращает список строк, состоящих из символов, разделенных пробелами.

Вот мой код, но с ним что-то не так, компилятор говорит, что в eof есть ошибка!

fun sepWords ([]) = []
  | sepWords (x :: xs) =
    let 
      val word = "" 
      val list
      sepWords (xs)
    in 
      if (Char.isSpace (x)) then (word = "")
      else (word ^ x)
      word :: list
    end;

person xx3z    schedule 02.10.2017    source источник


Ответы (1)


  1. У вас есть синтаксическая ошибка вокруг строк val list и sepWords (xs). Возможно, вы хотели написать val list = sepWords (xs)? У вас также есть синтаксическая ошибка вокруг строк if ... и word :: list. Я не уверен, в чем здесь смысл, но, может быть, вы думаете, что word :: list будет иметь побочный эффект добавления «слова» в «список»?

  2. У вас есть ошибка типа в вашем if ..., так как ветвь "тогда" имеет выражение word = "", которое имеет тип bool, а ветвь "else" имеет выражение word ^ x, которое имеет тип string. У оператора if-then-else должен быть один и тот же тип на каждой ветке, чтобы средство проверки типов могло принять программу.

  3. Вместо создания функции типа список символов -> список строк, почему бы не создать функцию типа строка -> список строк? Если вы сделаете это, вы даже сможете избежать промежуточного этапа преобразования вашей строки в список символов, отслеживая индексы символов в исходной строке (например, с помощью < em>подстрока типа).

    Хорошим названием для этой функции могло бы быть «слова».

  4. Вы не определили поведение, когда несколько пробелов встречаются последовательно. Должен ли words "hello world" производить ["hello", "world"] или ["hello", "", "world"]?

  5. На самом деле для этого есть встроенные библиотечные функции:

    - String.tokens Char.isSpace "hello  world";
    > val it = ["hello", "world"] : string list
    
    - String.fields Char.isSpace "hello  world";
    > val it = ["hello", "", "world"] : string list
    
  6. Альтернатива сначала преобразовать вашу строку в список символов — прекрасное упражнение в рекурсии списка, даже если эта стратегия не очень эффективна. Вы можете сделать это, решив проблему извлечения одного слова из вашего ввода вместе с остальной частью строки:

    fun firstWord [] = ([], [])
      | firstWord (c::cs) =
        if Char.isSpace c
        then ([], cs)  (* throw away the space c *)
        else case firstWord cs of
               (fw, remainder) => (c::fw, remainder)
    

    Вы можете назвать это так:

    - firstWord (explode "hello  world");
    > val it =
        ([#"h", #"e", #"l", #"l", #"o"], [#" ", #"w", #"o", #"r", #"l", #"d"])
            : char list * char list
    

    И вы можете вызывать его рекурсивно, пока остаток не пуст:

    fun words [] = []
      | words cs =
        let val (fw, remainder) = firstWord cs
        in implode fw :: words remainder end
    

    И используя это:

    - allWords (explode "hello  world");
    > val it = ["hello", "", "world"] : string list
    
person Simon Shine    schedule 02.10.2017
comment
Спасибо большое. Ваш ответ не только решил мои проблемы, но и научил меня многим вещам, о которых я не знал. Ты самый лучший ! - person xx3z; 03.10.2017