Pergunta

Eu tenho tentado explicar a diferença entre as declarações de switch e casamento de padrões (F #) para um par de pessoas, mas eu realmente não tenho sido capaz de explicá-lo well..most das vezes eles só olhar para mim e dizer: "então por que você não apenas usar if..then..else".

Como você explicaria a eles?

EDIT! Obrigado a todos para os grandes respostas, eu realmente gostaria de poder marcar várias respostas certas.

Foi útil?

Solução

Tendo sido anteriormente uma "daquelas pessoas", eu não sei que há uma maneira sucinta de resumir porque pattern-matching é tal bondade saborosa. É experimental.

De volta quando eu tinha apenas olhou para pattern-matching e pensei que era uma instrução switch glorificado, eu acho que eu não tinha experiência de programação com tipos de dados algébricos (linhas e discriminados sindicatos) e não chegou a ver esse padrão correspondência era tanto uma construção controle e uma construção de ligação. Agora que eu tenho programado com F #, eu finalmente "pegar". frescor do pattern-matching é devido a uma confluência de características encontradas em linguagens de programação funcional, e por isso é não-trivial para o estranho olhando-se para apreciar.

Tentei resumir um aspecto da razão pela qual pattern-matching é útil no segundo de uma série curta do blog de duas partes sobre design de linguagem e API; confira primeira parte e parte dois .

Outras dicas

Patterns dar-lhe uma pequena linguagem para descrever a estrutura dos valores que deseja corresponder. A estrutura pode ser arbitrariamente profunda e você pode vincular variáveis ??a partes do valor estruturado.

Isso permite que você escreva coisas extremamente sucinta. Você pode ilustrar isto com um pequeno exemplo, como uma função derivada de um tipo simples de expressões matemáticas:

type expr =
    | Int of int
    | Var of string
    | Add of expr * expr
    | Mul of expr * expr;;

let rec d(f, x) =
    match f with
    | Var y when x=y -> Int 1
    | Int _ | Var _ -> Int 0
    | Add(f, g) -> Add(d(f, x), d(g, x))
    | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));;

Além disso, porque a correspondência de padrão é uma construção estática para tipos estáticos, o compilador pode (i) verificar se você cobriu todos os casos (ii) detectar ramos redundantes que nunca pode corresponder a qualquer valor (iii) fornecem uma implementação muito eficiente (com salta etc.).

este artigo do blog :

A correspondência de padrões tem várias vantagens sobre declarações switch e método de envio:

    partidas
  • Padrão pode agir sobre ints, flutuadores, cordas e outros tipos como bem como objetos.
  • Corresponde ao padrão pode agir sobre vários diferentes valores simultaneamente: paralelo correspondência de padrões. Método expedição e switch estão limitados a um único valor, por exemplo "Isto".
  • Patterns podem ser aninhados, permitindo despachar sobre árvores de arbitrária profundidade. Método expedição e switch estão limitados ao caso não-aninhada.
  • Ou-padrões permitem subpadrões ser compartilhado. Método expedição só permite compartilhando quando os métodos são de aulas que acontecem para compartilhar uma base classe. Caso contrário, você deve manualmente fator fora do comum para um função separada (dando-lhe um nome) e chamadas em seguida, insira manualmente de todos os lugares apropriados para o seu função desnecessária.
  • A correspondência de padrões fornece redundância verificação, que pega erros.
  • Nested e / padrão ou paralela jogos são otimizados para você pela F # compilador. O OO obrigação equivalente ser escrito à mão e constantemente reotimizada à mão durante desenvolvimento, que é proibitivamente tedioso e erro tão propenso OO código de qualidade de produção tende a ser extremamente lento em comparação.
  • padrões ativos permitem injetar semântica expedição personalizado.

Em cima da minha cabeça:

  1. O compilador pode dizer se você não ter coberto todas as possibilidades em suas partidas
  2. Você pode usar um jogo como uma atribuição
  3. Se você tem uma união discriminada, cada jogo pode ter um 'tipo' diferente

Switch é as duas rodas dianteiras.

Padrão de correspondência é o carro inteiro.

Tuples ter "" e variantes têm args ctor .. estes são construtores, eles criam coisas.

Os padrões são destruidores, eles rasgar-los.

Eles são conceitos duais.

Para colocar isso com mais força: a noção de uma tupla ou variante não pode ser descrito apenas por seu construtor: o destruidor é necessário ou o valor que você fez é inútil. São essas descrições duais que definem um valor.

Geralmente pensamos em construtores como dados, e destruidores como fluxo de controle. destruidores variantes são ramos alternados (um dos muitos), destruidores tupla são threads paralelas (todos de muitos).

O paralelismo é evidente em operações como

(f * g) . (h * k) = (f . h * g . k) 

Se você acha do controle flui através de uma função, tuplas fornecer uma maneira de dividir um cálculo em linhas paralelas de controle.

Visto dessa forma, as expressões são maneiras de tuplas compor e variantes para fazer estruturas de dados complicadas (pense em um AST).

E coincide com modelo são formas de compor os destruidores (mais uma vez, pense em um AST).

Corresponde ao padrão em OCaml, além de ser mais expressivo, como mencionado em vários aspectos que foram descritos acima, também dar algumas garantias estáticos muito importantes. O compilador irá provar para você que o caso-análise encarnado por sua declaração padrão de jogo é:

  • exaustiva (há casos são perdidas)
  • não redundante (há casos que não podem ser atingidas, porque eles são antecipadas por um caso anterior)
  • som (sem padrões que são impossíveis dado o tipo de dados em questão)

Este é realmente um grande negócio. É útil quando você está escrevendo o programa pela primeira vez, e extremamente útil quando o programa está evoluindo. Usado corretamente, match-declarações torná-lo mais fácil de alterar os tipos em seu código de forma confiável, porque o sistema de tipo pontos você no declarações jogo quebradas, que são um indicador razoável de onde você tem código que precisa ser corrigido.

If-Else (ou switch) declarações são sobre a escolha de diferentes maneiras de processar um valor (de entrada), dependendo do Propriedades do valor em questão.

A correspondência de padrões é sobre a definição de como processar um valor dada a sua Estrutura , (note também que partidas único caso padrão faz sentido).

Assim padrão de correspondência é mais sobre desconstruir valores que fazer escolhas, isso os torna um mecanismo muito conveniente para a definição de funções (recursivo) em estruturas indutivas (tipos de união recursiva), o que explica por que eles são tão abundantemente utilizada em linguagens como Ocaml etc .

PS: Você pode saber o padrão de resultados e "padrões" If-Else de seu uso ad-hoc em matemática;

"se x tem a propriedade A então y outra z" (If-Else)

"algum termo em p1..pn onde .... é a decomposição principal de x .." ((caso único) jogo padrão)

Talvez você poderia fazer uma analogia com cordas e expressões regulares? Você descreve o que você está procurando, e deixe a figura compilador a como por si. Não faz o seu código muito mais simples e mais clara.

Como um aparte: Eu acho que a coisa mais útil sobre a correspondência de padrões é que incentiva bons hábitos. Eu lidar com os casos de canto primeiros , e é fácil verificar que eu cobri todos os casos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top