Это довольно читаемо и отлично работает:
var ref = Firebase(url:MY_FIREBASE_URL)
ref.childByAppendingPath("some-child").observeSingleEventOfType(
FEventType.Value, withBlock: { (snapshot) -> Void in
for child in snapshot.children {
let childSnapshot = snapshot.childSnapshotForPath(child.key)
let someValue = childSnapshot.value["key"] as! String
}
})
В двух словах, шаблоны похожи на определение кусочных функций в математике. Вы можете указать разные тела функций для разных аргументов, используя шаблоны. Когда вы вызываете функцию, соответствующий орган выбирается путем сравнения фактических аргументов с различными шаблонами аргументов. Прочтите Нежное введение в Haskell для получения дополнительной информации.
Сравнить:
[/g2]
с эквивалентом Haskell:
fib 0 = 1
fib 1 = 1
fib n | n >= 2
= fib (n-1) + fib (n-2)
Обратите внимание, что « n ≥ 2» в кусочной функции становится защитой в версии Haskell, но два других условия являются просто шаблонами. Шаблоны - это условия, которые проверяют значения и структуру, такие как x:xs
, (x, y, z)
или Just x
. В кусочном определении условия, основанные на =
или ∈
отношениях (в основном, условия, которые говорят что-то », являются« чем-то другим), становятся образцами. Охранники допускают более общие условия. Мы могли бы переписать fib
для использования охранников:
fib n | n == 0 = 1
| n == 1 = 1
| n >= 2 = fib (n-1) + fib (n-2)
Совпадение шаблонов, по крайней мере, в Haskell, глубоко связано с понятием алгебраических типов данных . Когда вы объявляете тип данных следующим образом:
data SomeData = Foo Int Int
| Bar String
| Baz
... он определяет Foo
, Bar
и Baz
как конструкторы - не должен быть путают с «конструкторами» в ООП, которые строят значение SomeData
из других значений.
Совпадение шаблонов не более чем делает это в обратном порядке - шаблон «деконструировать» значение SomeData
в его составные части (на самом деле, я считаю, что сопоставление с образцом является способом only для извлечения значений в Haskell).
Когда есть несколько конструкторы для типа, вы пишете несколько версий функции для каждого шаблона, причем правильный выбирается в зависимости от того, какой конструктор использовался (при условии, что вы написали шаблоны в соответствии со всеми возможными конструкциями, что обычно является хорошей практикой) .
В функциональном языке сопоставление шаблонов включает проверку аргумента в отношении разных форм. Простой пример включает рекурсивно определенные операции над списками. Я буду использовать OCaml для объяснения соответствия шаблонов, так как это мой функциональный язык выбора, но понятия в F # и Haskell, AFAIK. - [1] Вот определение функции для вычисления длины списка lst
. В OCaml «список is defined recursively as the empty list
[] , or the structure
h :: t , where
h is an element of type
a (
a being any type we want, such as an integer or even another list),
t is a list (hence the recursive definition), and
::` - это оператор cons, который создает новый список из элемента и списка.
Таким образом, функция будет выглядеть так:
let rec len lst =
match lst with
[] -> 0
| h :: t -> 1 + len t
rec
является модификатором, который сообщает OCaml, что функция будет называть себя рекурсивно. Не беспокойтесь об этой части. Утверждение match
- это то, на чем мы фокусируемся. OCaml проверит lst
на два шаблона - пустой список или h :: t
- и вернет другое значение, основанное на этом. Поскольку мы знаем, что каждый список будет соответствовать одному из этих шаблонов, мы можем быть уверены, что наша функция вернется безопасно.
Обратите внимание, что хотя эти два шаблона будут заботиться обо всех списках, вы не ограничены их. [31]
Конечно, использование шаблонов не ограничивается рекурсивно определенными структурами данных или рекурсивными функциями. Вот (надуманная) функция, чтобы рассказать вам, является ли число 1 или 2:
let is_one_or_two num =
match num with
1 -> true
| 2 -> true
| _ -> false
. В этом случае формы нашего шаблона являются самими числами. _
является специальным catch-all, используемым как случай по умолчанию, если ни один из указанных выше шаблонов не соответствует.
Совпадение шаблонов - одна из тех болезненных операций, которые трудно обойти, если вы исходите из процедурного программирования. Мне трудно попасть, потому что для сопоставления может использоваться тот же синтаксис, который используется для создания структуры данных.
В F # вы можете использовать оператор cons ::
, чтобы добавить элемент в начало list like so:
let a = 1 :: [2;3]
//val a : int list = [1; 2; 3]
Аналогичным образом вы можете использовать один и тот же оператор, чтобы разбить список так:
let a = [1;2;3];;
match a with
| [a;b] -> printfn "List contains 2 elements" //will match a list with 2 elements
| a::tail -> printfn "Head is %d" a //will match a list with 2 or more elements
| [] -> printfn "List is empty" //will match an empty list
Есть и другие хорошие ответы, поэтому я дам вам очень технический ответ. Соответствие шаблонов - это конструкция исключения для алгебраических типов данных :
Идея алгебраических типов данных заключается в том, что вы определяете тип вещи, и вы говорите все способы, которыми вы можете это сделать. В качестве примера давайте определим «Последовательность String» как тип алгебраических данных с тремя способами:
data StringSeq = Empty -- the empty sequence
| Cat StringSeq StringSeq -- two sequences in succession
| Single String -- a sequence holding a single element
Теперь, с этим определением есть все, что не так, но как Например, это интересно, потому что оно обеспечивает конкатенацию последовательностей произвольной длины в постоянное время. (Есть и другие способы достижения этого.) В декларации представлены Empty
, Cat
и Single
, все из которых существуют , создающие последовательности . (Это делает каждый из них введение construct & mdash; способ сделать вещи.)
Cat
, вам понадобятся две другие последовательности. Single
, вам нужен элемент (в этом случае строка) Здесь идет строка перфорации: конструкция исключения, сопоставление шаблонов, дает вам способ тщательно изучить последовательность и задать вопрос о том, какой конструктор вы создали? Поскольку вы должны быть готовы к любому ответу, вы предоставляете по крайней мере одну альтернативу для каждого конструктора. Вот функция длины:
slen :: StringSeq -> Int
slen s = case s of Empty -> 0
Cat s s' -> slen s + slen s'
Single _ -> 1
В основе языка все шаблонные сопоставления построены на этой конструкции case
. Однако, поскольку алгебраические типы данных и сопоставление образцов настолько важны для идиом языка, существует специальный «синтаксический сахар» для выполнения сопоставления шаблонов в форме объявления определения функции:
slen Empty = 0
slen (Cat s s') = slen s + slen s'
slen (Single _) = 1
С помощью этого синтаксический сахар, вычисление путем сопоставления шаблонов во многом напоминает определение уравнениями. (Комитет Haskell сделал это специально.) И, как вы можете видеть в других ответах, можно выделить либо уравнение, либо альтернативу в выражении case
, похлопывая охрану с ним. Я не могу придумать правдоподобного стража для примера последовательности, и в других ответах есть много примеров, поэтому я оставлю его там.