Por que expressões compostas?

10

Este é um exemplo de um livro que estou lendo:

volume = begin
    len = 10
    breadth = 20
    height = 30
    len * breadth * height
end

Por que preciso de expressões compostas ?? Eu poderia apenas escrever volume = 10 * 20 * 30ou volume = len * breadth * heightescrever uma função para essa ou uma função anônima ...

Por que eu uso begine end? Ou a pergunta provavelmente melhor: quando eu os uso, como acho que o exemplo acima do livro provavelmente não é muito bom.

Georgery
fonte
11
Que livro é esse? como você também não é um exemplo particularmente bom
Michael K. Borregaard
"Aprendendo Julia", como disponível aqui: epdf.pub/learning-julia.html (página 127)
Georgery

Respostas:

4

Eu acho que existem muitas situações em que os begin ... endblocos são úteis, mas como você observou, muitas vezes também é possível obter um efeito semelhante com outras construções, como funções, etc.

Para que begin ... endblocos podem ser usados?

  • Para simplesmente "conter" variáveis e seus nomes: len, breadthe heightsó existirá dentro do bloco e não poluir o namespace circundante.
  • Para aplicar macros a um bloco de código, em vez de instruções individuais. Por exemplo, @inbounds begin <all my code without bounds checking goes here> endou envolvendo @time begin ... endum pedaço de código.
  • Criar um escopo local em um escopo global circundante (para evitar confusões de escopo global, por exemplo). (Observe que, conforme indicado nos comentários begin ... end, não introduz um escopo local, mas o argumento é válido para o let ... endbloco semelhante .)

Em particular, o segundo ponto é para o que eu os uso nos meus códigos.

crstnbr
fonte
Eu também tive que me tranquilizar, mas beginblocos que não introduzir escopo . Por outro lado, eles convertem uma sequência de instruções em uma expressão, o que pode ser útil se você gerar código com / de uma macro.
phipsgabler 7/03
11
Ah, obrigado, a esse respeito eu confundi com o let ... endque introduz um escopo local. Corrigirá minha resposta.
crstnbr 7/03
Faço a mesma suposição errada o tempo todo :) É exatamente o que se espera.
phipsgabler
11
@crstnbr Sua primeira bala ainda é enganosa. Ainda parece dizer que os beginblocos introduzem um escopo local.
Cameron Bieganek
7

Para generalizar o que todo mundo já disse: os blocos permitem converter uma lista de declarações ("frases" sintáticas que não possuem valores, ou seja, não podem ser atribuídas) em uma expressão (uma "frase" que representa valores e pode ser atribuída )

Por exemplo, embora não deva, você pode escrever

x = begin
    s = 0
    for i = 1:10
        s += i^2
    end
    s
end

para atribuir xao resultado de uma operação de loop. (Com a restrição de que a última instrução na sequência deve realmente ser uma expressão - caso contrário, você não teria valor para a expressão.)

Um caso de uso legítimo disso é o código gerado. Por exemplo, você pode ativar

x = @somthing bla blub

para dentro

x = begin
   (stuff involving bla and blub)
end

transparente para o usuário, enquanto ele @somethingpode gerar livremente qualquer construção de linguagem.

Ou se você deseja escrever uma função anônima com um corpo mais longo (e não usar o functionformulário):

f = x -> begin
   ...
end
phipsgabler
fonte
11
Um pequeno esclarecimento: em Julia, as declarações têm valores e podem ser atribuídas. Então você pode fazer x = y = 1,, a = if false ende b = for i in 1:2 end, depois do qual xtem o valor 1, aeeb ambos têm o valor nothing.
Cameron Bieganek
Oh, aqui está um exemplo mais útil de atribuir o valor de uma if-elsedeclaração: a = if false; 1 else 2 end. Nesse caso, aé igual a 2.
Cameron Bieganek
11
Certo, eles têm valores e são expressões tecnicamente também. A atribuição é uma expressão, pois é basicamente setproperty!/setindex! , e é "tradicionalmente" uma coisa para ter um valor (em linguagens C). O mesmo para if-else, que é uma expressão em alguns idiomas. Mas fore ifsem elseter um valor "padrão" de nothing, vejo isso apenas como um artefato.
phipsgabler 9/03
6

Um uso para esses blocos está nas compreensões:

A = [ begin
           x = y^2
           x - x^2 + 2
         end
         for y = 1:5 ]

Você pode criar uma função e usá-la dentro da compreensão, mas às vezes isso é conveniente. É usado sempre que você deseja usar um bloco de código com várias linhas em algum lugar, por exemplo, para passar como argumento para uma macro (que é muito comumente usada @testsetna biblioteca padrão de teste).

Eric
fonte
Para não se opor ao seu argumento, pode-se escrever apenas y^2 - y^4 + 2neste caso. Talvez seja melhor mostrar um exemplo onde duas (ou mais) etapas são realmente necessárias.
crstnbr 7/03
@crstnbr você está certo, mas eu apenas usei o exemplo do livro inicialmente e estava simplesmente interessado no que seria um uso sensato.
Georgery 7/03
11
Como, para economizar o cálculo de algum valor intermediário caro duas vezes.
phipsgabler 7/03
5

Simplificando: "begin" apenas indica um bloco de código (consulte os documentos sobre isso: https://docs.julialang.org/en/v1/base/base/#begin ).

No exemplo acima, não está claro se existe algum valor em usar um bloco de início versus declarar uma função.

Não vejo essa palavra-chave sendo muito usada no código e pessoalmente nunca a usei na prática. Minha sugestão é usar apenas uma função, pois ela fará a mesma coisa.

logankilpatrick
fonte
Ainda não usei Julia, mas é exatamente isso que estou pensando. No entanto, quando a linguagem foi projetada (presumivelmente muito inteligente), as pessoas devem ter uma ideia em mente, certo?
Georgery 7/03
Concordo com o @logankilpatrick que, em muitos casos, você deseja usar funções. Mas acho que existem razões para a existência desses blocos (veja minha resposta).
crstnbr 7/03
@ Georgery Transformar uma sequência de declarações em uma expressão às vezes é algo útil (cf. prognno LISP).
phipsgabler 7/03
11
como você nota corretamente, parece absurdo no contexto
Michael K. Borregaard