Чому складені вирази?


10

Це приклад із книги, яку я читаю:

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

Навіщо мені потрібні складені вирази ?? Я міг би просто написати volume = 10 * 20 * 30або volume = len * breadth * heightнаписати функцію для цього або анонімну функцію ...

Для чого я використовую beginі end? Або, мабуть, краще питання: Коли я їх використовую, як я здогадуюсь, наведений вище приклад із книги, мабуть, не дуже хороший.


1
Що це за книга? як ви також не такий приклад не особливо хороший
Майкл К. Боррегаард

"Навчання Джулії", доступне тут: epdf.pub/learning-julia.html (стор. 127)
Джордж

Відповіді:


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блоку.)

Зокрема, другий момент - це те, для чого я їх використовую в своїх кодах.


Я також мав заспокоїти себе, але 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

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!, і це "традиційно" річ для нього має значення (на мовах, подібних С). Те саме if-else, що є виразом на пару мов. Але forі ifне elseмаючи значення "за замовчуванням" nothing, я вважаю це лише артефактом.
phipsgabler

6

Одне використання цих блоків полягає в розуміннях:

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

Ви можете зробити функцію та використати її всередині розуміння, але іноді це зручно. Він використовується, коли ви хочете десь використовувати багаторядковий блок коду, наприклад, для передачі в якості аргументу макросу (що дуже часто використовується @testsetу стандартній бібліотеці тестів).


Не протистояти вашій точці, але можна просто написати y^2 - y^4 + 2в цьому випадку. Можливо, було б краще показати приклад, де дійсно потрібні два (або більше) кроків.
crstnbr

@crstnbr Ви маєте рацію, але я просто спочатку використав приклад із книги і просто зацікавився, що таке розумне використання.
Джорджері

1
Мовляв, щоб заощадити обчислення деякого дорогого проміжного значення в два рази.
phipsgabler

5

Простіше кажучи: "Почати" просто позначає блок коду (див. Документи про це: https://docs.julialang.org/en/v1/base/base/#begin ).

У наведеному вище прикладі незрозуміло, що є якесь значення для використання блоку початку та оголошення функції.

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


Я ще не використовував Джулію, але саме так я і думаю. Однак, коли мова була розроблена (імовірно, дуже розумна), люди, мабуть, мали на увазі, чи не так?
Джорджері

Я погоджуюся з @logankilpatrick, що у багатьох випадках ви хочете використовувати функції замість цього. Але я думаю, що існують причини існування цих блоків (див. Мою відповідь).
crstnbr

@Georgery Перетворення послідовності висловлювань у вираз іноді є корисною справою (пор. prognLISP).
phipsgabler

1
як ви правильно зазначаєте, це здається безглуздим у контексті
Майкл К. Боррегаард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.