Recapitulando: a linha que você já viu

Prévia grátis 3 min de leitura

Onde isto começou

A aula "O operador AND", de Lógica: álgebra booleana, ensinou o && e o curto-circuito dele com este exemplo:

current_user && current_user.subscription && current_user.subscription.active?

Logo abaixo, aquela aula mostrou mais uma linha, chamada de "alternativa moderna do Ruby", e seguiu sem explicar:

current_user&.subscription&.active?

Foi só isso que o &. recebeu ali: uma linha, um rótulo, nenhuma mecânica. Este curso abre essa linha.

O que a cadeia de && faz

current_user && current_user.subscription && current_user.subscription.active? avalia current_user três vezes e chama .subscription duas. Uma classe que conta as próprias chamadas mostra isso:

a = Chain.new
a && a.b && a.b.c
a.calls
# 2 — .b rodou duas vezes

Cada cláusula de && recomeça do início da própria expressão. Na terceira cláusula o Ruby não lembra que a.b já foi calculado; ele roda a.b de novo ao avaliar a.b.c.

O que a cadeia de &. faz

a2 = Chain.new
a2&.b&.c
a2.calls
# 1 — .b rodou exatamente uma vez

O &. passa um valor adiante pela cadeia em vez de recomeçar. Ele avalia a2 uma vez, chama .b nele e entrega o resultado ao próximo &., que chama .c nesse resultado. É uma avaliação por elo, e não uma por cláusula.

O comportamento de verdade: a cadeia inteira para

O que "O operador AND" nunca mostrou é o que acontece quando o nil pode estar em qualquer ponto de uma cadeia mais longa. Pegue quatro objetos User, cada um sem alguma coisa numa profundidade diferente:

full.subscription.plan.name       # "Pro"     — usuário tem assinatura com plano
no_plan.subscription.plan&.name   # assinatura existe, plano não
no_sub.subscription               # usuário existe, assinatura não
nothing                           # o próprio usuário é nil

Rodando user&.subscription&.plan&.name nos quatro:

full&.subscription&.plan&.name      # "Pro"
no_plan&.subscription&.plan&.name   # nil
no_sub&.subscription&.plan&.name    # nil
nothing&.subscription&.plan&.name   # nil

Todo ponto de falha dá o mesmo resultado para a expressão inteira: nil, sem exceção. Isso vale para o primeiro elo (nothing) e para o último (no_plan, cujo plan é nil). O mecanismo: cada &. só pergunta "este receiver é nil?" Se for, ele para e devolve nil na hora, sem chamar nada e ignorando o que vem depois. Esse nil vira o receiver do próximo &., que faz a mesma pergunta, recebe "sim" e também para. O nil passa de elo em elo até o fim, então uma cadeia de qualquer tamanho vira nil assim que um elo falha.

Pontos-chave

  • "O operador AND" mostrou current_user&.subscription&.active? como a "alternativa moderna do Ruby" a uma cadeia de &&, sem explicação; este curso começa dali.
  • Uma cadeia de && avalia o receiver de novo a cada cláusula e chama um método compartilhado duas vezes onde a cadeia de &. chama uma.
  • O &. passa um valor avaliado pela cadeia em vez de recomeçar; cada elo chama o método no resultado do elo anterior.
  • Com um nil posto em cada profundidade, obj&.a&.b&.c devolve nil para a expressão inteira assim que qualquer elo é nil, o primeiro ou o último, sem levantar exceção.
Aula 1 de 7 · grátis

Continue com a aula 2

Safe navigation com argumentos e blocos

Mostra que o &. passa argumentos e blocos sem mudança e também funciona antes de métodos de operador como >.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...