2014-12-20 2 views
1

Я недавно начал изучать Erlang и столкнулся с любопытным исключением, которое я не могу объяснить.Соответствие шаблону Erlang string как список в функции

Мой исходный код выглядит следующим образом:

-module(balanced_brackets).                            
-author("Irrelevant"). 
-compile(export_all). 

is_balanced(String) -> is_balanced(String, 0, 0). 

is_balanced([H | T], Opening, Closing) when H =:= "{" -> 
    is_balanced(T, Opening + 1, Closing); 
is_balanced([H | T], Opening, Closing) when H =:= "}" -> 
    is_balanced(T, Opening, Closing + 1); 
is_balanced([], Opening, Closing) -> (Opening - Closing). 

Очень базовый код для подсчета числа открытия и закрытия фигурных скобок в строке.

В оболочке Эрланга, когда я пытаюсь вызвать функцию is_balanced как таковой: balanced_brackets:is_balanced("{}").

Следующая ошибка выводится:

** exception error: no function clause matching balanced_brackets:is_balanced("{}",0,0) (balanced_brackets.erl, line 7)

Однако, если я передать аргумент как явный список, сопоставление образцов работает правильно: balanced_brackets:is_balanced(["{", "}"]).

Не строки Erlang просто перечисляют inte rnally? Почему некорректно сопоставить строку с строкой, используя конструкцию [H | T]?

Выполнение BIF is_list("{}").true.

Я бы искренне оценил чье-то объяснение исключения.

спасибо.

Erlang/OTP 17 [erts-6.2] [source-aaaefb3] [64-bit] [smp:2:2] [async-threads:10] [hipe] [kernel-poll:false]

ответ

1

Проблема в том, ваше определение охранник, вы сравниваете к "{", который [123], то есть список с один элемент, представляющий собой {.

Соответствие вашей модели правильно, но вы должны будете соответствовать 123 вместо "{" (и то же самое для }, конечно).

Самый простой способ исправить код (и сохранить его для чтения), чтобы сравнить с [H] вместо H в гвардии:

is_balanced([H | T], Opening, Closing) when [H] =:= "{" -> 
    is_balanced(T, Opening + 1, Closing); 
+0

Вот и все! Спасибо за краткое объяснение. Маркировка как принято. – user3813812

+0

или вы можете сравнить H с $ {, другим способом представления 123, но показывая его как символ. – Pascal

2

Там нет необходимости использовать числа для представления символов, как предложено в this answer. Скорее, просто используйте символьные константы Эрланга. Например, чтобы представить символ {, вы должны использовать ${.

Хороший способ исправить код, чтобы избежать охранников полностью и просто соответствуют ${ и $} символов в функции головы, как это:

is_balanced([${ | T], Opening, Closing) -> 
    is_balanced(T, Opening + 1, Closing); 
is_balanced([$} | T], Opening, Closing) -> 
    is_balanced(T, Opening, Closing + 1); 

Затем вам нужно другое положение для обработки, кроме ${ символов и $}, который отсутствует в исходном коде:

is_balanced([_ | T], Opening, Closing) -> 
    is_balanced(T, Opening, Closing); 

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

is_balanced([], Opening, Closing) -> (Opening - Closing). 

еще одно: дано имя функции is_balanced, казалось бы, хочет вернуть логическое значение. Если это так, замените верхнюю функцию на это:

is_balanced(String) -> is_balanced(String, 0, 0) == 0. 
Смежные вопросы