Сопоставление с шаблоном параметров функции OCaml для строк - PullRequest
10 голосов
/ 25 марта 2012

Я пытался передать строку, чтобы получить обратную строку.Почему я не могу сделать это:

let rec reverse x = 
  match x with
  | "" -> ""
  | e ^ s -> (reverse s) ^ e;;

Компилятор говорит, что это синтаксическая ошибка.Не могу ли я использовать ^ для деструктурирования параметров?

Ответы [ 3 ]

18 голосов
/ 25 марта 2012

Причина этого в том, что строки не представлены в виде данных так же, как списки.Следовательно, в то время как cons (: :) - конструктор, ^ - , а не .Вместо этого строки представляются как тип более низкого уровня без рекурсивного определения (как и списки).Существует способ сопоставления строк в виде списка символов, используя функцию из SML (которую вы можете написать в OCaml), называемую «взорвать» и «взорвать», которая - соответственно - переносит строку в список символов и наоборот, Вот пример их реализации.

2 голосов
/ 25 сентября 2017

Как объяснил Кристофер Мичински , вы не можете разложить строки, используя сопоставление с образцом, как вы делаете со списками.

Но вы можете преобразовать их в списки, используя explode. Вот ваша reverse функция с сопоставлением с шаблоном с использованием explode и ее аналога implode:

let rec reverse str =
  match explode str with
    [] -> ""
    | h::t -> reverse (implode t) ^ string_of_char h

Используйте это так:

let () =
  let text = "Stack Overflow ♥ OCaml" in
  Printf.printf "Regular: %s\n" text;
  Printf.printf "Reversed: %s\n" (reverse text)

Что показывает, что он работает для однобайтовых символов, но не для многобайтовых.

А вот explode и implode вместе с вспомогательным методом:

let string_of_char c = String.make 1 c

(* Converts a string to a list of chars *)
let explode str =
  let rec explode_inner cur_index chars = 
    if cur_index < String.length str then
      let new_char = str.[cur_index] in
      explode_inner (cur_index + 1) (chars @ [new_char])
    else chars in
  explode_inner 0 []

(* Converts a list of chars to a string *)
let rec implode chars =
  match chars with
    [] -> ""
    | h::t ->  string_of_char h ^ (implode t)
2 голосов
/ 27 марта 2012

Когда вы пишете выражение соответствия шаблону, вы не можете использовать произвольные функции в своих шаблонах.Вы можете использовать только конструкторы , которые выглядят как неоцененные функции.Например, функция «+» определена на целых числах.Таким образом, выражение 1+2 оценивается и дает 3;функция "+" оценивается, поэтому вы не можете найти совпадения на x+y.Вот попытка определить функцию для натуральных чисел, которая проверяет, является ли число нулевым:

 let f x =  match x with
  | 0 -> false
  | a+1 -> true
 ;;

Это не может работать!По той же причине ваш пример со строками не может работать.Функция "^" вычисляется на строках, она не является конструктором.

Соответствие на x+1 будет работать только в том случае, если числа были бы неоцененными символьными выражениями, сделанными из неоцененного оператора + и символической константы1.Это не так в OCAML.Целые числа реализуются непосредственно через машинные номера.

Когда вы сопоставляете тип варианта, вы сопоставляете конструкторы, которые являются оцененными выражениями.Например:

 # let f x = match x with
    | Some x -> x+1
    | None -> 0
 ;;
 val f : int option -> int = <fun>

Это работает, потому что тип 'a option состоит из символического выражения, такого как Some x.Здесь Some - это не функция, которая оценивается и дает какое-то другое значение, а скорее «конструктор», который можно рассматривать как функцию, которая никогда не оценивается.Выражение Some 3 больше не оценивается;осталось как есть.Только для таких функций вы можете сопоставлять с образцом.

Списки также являются символическими, неоцененными выражениями, построенными из конструкторов;Конструктор ::.Результат x :: y :: [] является неоцененным выражением, которое представлено списком [x;y] только для косметического удобства.По этой причине вы можете сопоставлять шаблоны в списках.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...