¿Por qué expresiones compuestas?

10

Este es un ejemplo de un libro que estoy leyendo:

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

¿Por qué necesito expresiones compuestas? Podría escribir volume = 10 * 20 * 30o volume = len * breadth * heightescribir una función para eso o una función anónima ...

¿Por qué uso beginy end? O la pregunta probablemente mejor: ¿ cuándo los uso, ya que supongo que el ejemplo anterior del libro probablemente no sea muy bueno?

Georgery
fuente
1
¿Qué libro es ese? como tú tampoco, el ejemplo no es particularmente bueno
Michael K. Borregaard
"Aprendiendo Julia", disponible aquí: epdf.pub/learning-julia.html (página 127)
Georgery

Respuestas:

4

Supongo que hay muchas situaciones en las que los begin ... endbloques son útiles, pero como notó, a menudo también puede lograr un efecto similar con otras construcciones, como funciones, etc.

¿Para qué podrían begin ... endusarse los bloques?

  • A simplemente "contener" las variables y sus nombres: len, breadthy heightsólo existirá dentro del bloque y no contamina el espacio de nombres circundante.
  • Para aplicar macros a un bloque de código en lugar de declaraciones individuales. Por ejemplo, @inbounds begin <all my code without bounds checking goes here> endo envolviendo un @time begin ... endcódigo de una pieza.
  • Para crear un alcance local en un alcance global circundante (para evitar confusiones de alcance global, por ejemplo). (Tenga en cuenta que, como se ha señalado en los comentarios begin ... end, no introduce un alcance local, pero el argumento es válido para el let ... endbloque similar ).

En particular, el segundo punto es para qué los uso en mis códigos.

crstnbr
fuente
También tuve que tranquilizar a mí mismo, pero beginlos bloques qué no presento alcance . Por otro lado, convierten una secuencia de declaraciones en una expresión, lo que puede ser útil si genera código con / desde una macro.
phipsgabler
1
Oh, gracias, en ese sentido lo confundí con let ... endlo que introduce un alcance local. Corregirá mi respuesta.
crstnbr
Hago la misma suposición incorrecta todo el tiempo :) Es justo lo que uno esperaría.
phipsgabler
1
@crstnbr Su primera viñeta sigue siendo engañosa. Todavía parece decir que los beginbloques introducen un alcance local.
Cameron Bieganek
7

Para generalizar lo que todos han dicho: los bloques le permiten convertir una lista de declaraciones ("frases" sintácticas que no tienen valores, es decir, no se pueden asignar) a una expresión (una "frase" que representa valores y se puede asignar )

Por ejemplo, aunque no deberías, puedes escribir

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

asignar xal resultado de una operación de bucle. (Con la restricción de que la última instrucción de la secuencia debe ser realmente una expresión; de lo contrario, no tendría ningún valor para la expresión).

Un caso de uso legítimo de esto es el código generado. Por ejemplo, podrías activar

x = @somthing bla blub

dentro

x = begin
   (stuff involving bla and blub)
end

transparente para el usuario, mientras que @somethingpuede generar libremente cualquier construcción de lenguaje.

O si desea escribir una función anónima con un cuerpo más largo (y no usar el functionformulario):

f = x -> begin
   ...
end
phipsgabler
fuente
1
Una ligera aclaración: en Julia, las declaraciones tienen valores y pueden asignarse. Entonces puede hacer x = y = 1,, a = if false endy b = for i in 1:2 enddespués de lo cual xtiene el valor 1, ay bambos tienen el valor nothing.
Cameron Bieganek
Oh, aquí hay un ejemplo más útil de asignar el valor de una if-elsedeclaración: a = if false; 1 else 2 end. En este caso, aes igual 2.
Cameron Bieganek
1
Correcto, tienen valores y también son expresiones técnicas. La asignación es una expresión, ya que es básicamente setproperty!/ setindex!, y es "tradicionalmente" que tenga un valor (en lenguajes tipo C). Lo mismo para if-else, que es una expresión en un par de idiomas. Pero fory ifsin elsetener un valor "predeterminado" de nothing, veo eso como un mero artefacto.
phipsgabler
6

Un uso para estos bloques es en las comprensiones:

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

Podrías hacer una función y usarla dentro de la comprensión, pero a veces esto es conveniente. Se usa siempre que desee usar un bloque de código multilínea en algún lugar, por ejemplo, para pasarlo como argumento a una macro (que se usa muy comúnmente @testsetdesde la biblioteca estándar de Prueba).

Eric
fuente
No para oponerse a su punto, pero uno podría simplemente escribir y^2 - y^4 + 2en este caso. Quizás sería mejor mostrar un ejemplo donde realmente se necesitan dos (o más) pasos.
crstnbr
@crstnbr tiene razón, pero inicialmente solo usé el ejemplo del libro y simplemente me interesó cuál sería un uso razonable.
Georgery
1
Como ahorrar dos veces el cálculo de un valor intermedio costoso.
phipsgabler
5

En pocas palabras: "comenzar" solo denota un bloque de código (vea los documentos sobre esto: https://docs.julialang.org/en/v1/base/base/#begin ).

En el ejemplo anterior, no está claro que haya un valor para usar un bloque de inicio frente a declarar una función.

No veo que esa palabra clave se use mucho en el código y personalmente nunca la he usado en la práctica. Mi sugerencia es que solo use una función, ya que hará lo mismo.

logankilpatrick
fuente
Todavía no he usado a Julia, pero esto es exactamente lo que estoy pensando. Sin embargo, cuando el lenguaje fue diseñado (presumiblemente muy inteligente) la gente debe haber tenido una idea en mente, ¿verdad?
Georgery
Estoy de acuerdo con @logankilpatrick en que, en muchos casos, querrás usar funciones en su lugar. Pero creo que hay razones para la existencia de estos bloques (ver mi respuesta).
crstnbr
@Georgery Convertir una secuencia de declaraciones en una expresión es algo útil a veces (cf. prognen LISP).
phipsgabler
1
como notan correctamente, parece absurdo en el contexto
Michael K. Borregaard