Recapitulando: a linha que você já viu
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
nilposto em cada profundidade,obj&.a&.b&.cdevolvenilpara a expressão inteira assim que qualquer elo énil, o primeiro ou o último, sem levantar exceção.
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.