Почему сложные выражения?

10

Это пример из книги, которую я читаю:

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

Зачем мне составные выражения ?? Я мог бы просто написать volume = 10 * 20 * 30или volume = len * breadth * heightили написать функцию для этой или анонимной функции ...

Почему я использую beginи end? Или, возможно, лучший вопрос: когда я их использую, как я полагаю, приведенный выше пример из книги, вероятно, не очень хорош.

Georgery
источник
1
Что это за книга? как ты тоже не пример не особо хорош
Майкл К. Боррегор
«Изучаем Юлию», как доступно здесь: epdf.pub/learning-julia.html (стр. 127)
Georgery

Ответы:

4

Я предполагаю, что есть много ситуаций, в которых begin ... endблоки удобны, но, как вы заметили, вы часто можете достичь аналогичного эффекта с другими конструкциями, такими как функции и т. Д.

Для чего можно использовать begin ... endблоки?

  • Просто «содержать» переменные и их имена: len,, breadthи heightбудет существовать только внутри блока и не загрязнять окружающее пространство имен.
  • Применять макросы к блоку кода, а не к отдельным операторам. Например @inbounds begin <all my code without bounds checking goes here> endили обернуть @time begin ... endвокруг кусок кода.
  • Создать локальную область в окружающей глобальной области (например, чтобы избежать путаницы в глобальной области ). (Обратите внимание, что, как было указано в комментариях begin ... end, не вводится локальная область, но аргумент сохраняется для аналогичного let ... endблока.)

В частности, второй момент - то, для чего я использую их в своих кодах.

crstnbr
источник
Я также должен был успокоить себя, но beginблоки этого не вводить сферы . С другой стороны, они преобразуют последовательность операторов в выражение, что может быть удобно, если вы генерируете код с / из макроса.
phipsgabler
1
О, спасибо, в связи с этим я перепутал это с тем, let ... endчто вводит локальную сферу. Исправлю мой ответ.
crstnbr
Я все время делаю одно и то же неправильное предположение :) Это именно то, чего и следовало ожидать.
phipsgabler
1
@crstnbr Ваша первая пуля все еще вводит в заблуждение. Все еще кажется, что beginблоки вводят локальную область видимости.
Кэмерон Биганек
7

Чтобы обобщить то, что сказали все остальные: блоки позволяют преобразовывать список операторов (синтаксические «фразы», ​​которые не имеют значений, т. Е. Не могут быть назначены) в одно выражение («фраза», которая представляет значения и может быть назначена). ).

Например, хотя вы не должны, вы можете написать

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

присваивать xрезультат зацикливания. (С ограничением, что последний оператор в последовательности должен быть на самом деле выражением - иначе у вас не будет значения для выражения.)

Законным вариантом использования этого является сгенерированный код. Например, вы можете включить

x = @somthing bla blub

в

x = begin
   (stuff involving bla and blub)
end

прозрачно для пользователя, а @somethingможет свободно генерировать любые языковые конструкции.

Или, если вы хотите написать анонимную функцию с более длинным телом (и не использовать functionформу):

f = x -> begin
   ...
end
phipsgabler
источник
1
Небольшое уточнение: у Юлии заявления имеют значения и могут быть назначены. Таким образом, вы можете сделать x = y = 1, a = if false endи b = for i in 1:2 end, после которого xимеет значение 1, aи bоба имеют значение nothing.
Кэмерон Биганек
Ах, вот более полезный пример присвоения значения в if-elseотчете: a = if false; 1 else 2 end. В этом случае aравных 2.
Кэмерон Биганек
1
Правильно, они имеют ценности и тоже являются выражениями в техническом отношении. Присвоение - это выражение, так как оно в основном setproperty!/ setindex!, и для него «традиционно» важно иметь значение (в C-подобных языках). То же самое if-else, выражение в нескольких языках. Но forи ifбез elseимея « по умолчанию» значение nothing, я вижу , что просто как артефакт.
phipsgabler
6

Одно использование для этих блоков в понимании:

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

Вы можете создать функцию и использовать ее вместо понимания, но иногда это удобно. Он используется всякий раз, когда вы хотите где-нибудь использовать многострочный блок кода, например, для передачи в качестве аргумента макросу (который очень часто используется @testsetв стандартной библиотеке Test).

Эрик
источник
Не против вашей точки зрения, но можно просто написать y^2 - y^4 + 2в этом случае. Возможно, было бы лучше показать пример, где действительно нужны два (или более) шага.
crstnbr
@crstnbr Вы правы, но я только что использовал пример из книги и просто интересовался, каким будет разумное использование.
Георгий
1
Мол, чтобы сэкономить, вычисляя несколько дорогих промежуточных значений дважды.
phipsgabler
5

Проще говоря: «начало» просто обозначает блок кода (см. Документацию по этому адресу : https://docs.julialang.org/en/v1/base/base/#begin ).

В приведенном выше примере не ясно, есть ли какое-либо значение для использования начального блока по сравнению с объявлением функции.

Я не вижу, чтобы это ключевое слово использовалось в коде, и лично я никогда не использовал его на практике. Мое предложение так просто использовать функцию, так как она будет делать то же самое.

logankilpatrick
источник
Я еще не использовал Джулию, но это именно то, о чем я думаю. Однако, когда язык был разработан (предположительно, очень умный), люди должны были иметь в виду идею, верно?
Георгий
Я согласен с @logankilpatrick, что во многих случаях вы хотите использовать функции вместо этого. Но я думаю, что есть причины для существования этих блоков (см. Мой ответ).
crstnbr
@ Georgery Превращение последовательности операторов в выражение иногда полезно (см. prognВ LISP).
phipsgabler
1
как вы правильно заметили, это кажется бессмысленным в контексте
Майкл К. Боррегор