Пока без глобального


person Michael Paul    schedule 27.08.2018    source источник
comment
Я думаю, что цикл for больше подходит для этого примера.   -  person Michael Paul    schedule 27.08.2018
comment
Вы пробовали i = i + 1?   -  person Viggo Lundén    schedule 27.08.2018
comment
Да, это также дает мне ту же ошибку: UndefVarError: я не определен Stacktrace: [1] область верхнего уровня в ./In[12]:5 [встроенная] [2] область верхнего уровня в ./none:0   -  person Michael Paul    schedule 27.08.2018
comment
Я только что видел в bogumilkaminski.pl/files/julia_express.pdf упоминается, что глобальный не будет быть необходимым, если цикл был внутри функции   -  person Michael Paul    schedule 27.08.2018
comment
Правила области видимости изменились с версии 0.7+. См. мой ответ здесь: stackoverflow.com/ вопросы/51930537/   -  person crstnbr    schedule 27.08.2018


Ответы (2)


Как @Michael Paul и @crstnbr уже ответили в комментариях, правила области видимости были изменены (Область действия переменных в Julia). Циклы for и while вводят новую область видимости и не имеют доступа к внешним (глобальным) переменным. Вы можете получить доступ к области с помощью ключевого слова global, но рекомендуемый рабочий процесс заключает ваш код в функции.

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

Одним из недостатков является путаница при экспериментировании с REPL и видении таких ошибок.

На мой взгляд, новое поведение является более чистым с точки зрения предсказуемости. Тем не менее, это была очень жесткая и продолжительная дискуссия в рамках всего сообщества Джулии ;)

В настоящее время обсуждается, будет ли REPL изменен, чтобы вести себя как старый, используя let-обертки: https://github.com/JuliaLang/julia/issues/28789 Это то, что нецелесообразно делать вручную (гораздо сложнее, чем использовать ключевое слово global), см. пример Стефана Карпински. : https://github.com/JuliaLang/julia/issues/28789#issuecomment-414666648

В любом случае, для полноты картины (хотя я бы не рекомендовал этого делать) вот версия с использованием global:

myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
i = 1;
N = length(myfriends)    

while i <= N  # you cannot even call a function here
              # with a global, like length(myfriends)
    global i, myfriends
    friend = myfriends[i]
    println("Hi $friend, it's great to see you!")
    i += 1
end

Обратите внимание, однако, что это также полностью справедливо:

myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]

greet(friend) = println("Hi $friend, it's great to see you!")

for friend in myfriends
    greet(friend)
end
person tamasgal    schedule 27.08.2018
comment
Можете ли вы добавить пример без global, используя обертку let? Это сделало бы ответ еще более полным. - person Michael Paul; 27.08.2018
comment
Я добавил комментарий к let-обертке. Я не думаю, что пример будет полезен, так как он, вероятно, вызовет больше путаницы, см. мое объяснение;) - person tamasgal; 28.08.2018
comment
Вы уверены, что не сможете вызвать функцию в состоянии while? Когда я пытаюсь, он работает без проблем, см. Также мой ответ. Очень интересно было прочитать комментарии к выпуску о разрешении, спасибо, что поделились. - person Michael Paul; 28.08.2018
comment
Циклы имеют доступ для чтения к глобальным переменным, поэтому вы можете распечатать или использовать их для определения других переменных. Кроме того, запись в i внутри цикла не вызовет ошибки, поскольку будет создана новая отдельная переменная i. Джулия будет жаловаться, только если вы попытаетесь прочитать и записать i в одном и том же цикле, например i=i+1. Это потому, что Джулия не знает, хотите ли вы глобальную или локальную i, не объявляя ее как таковую. По этой причине println(i) и i=2 можно безошибочно указывать по отдельности в цикле, но не вместе. Эти тонкости сбивали меня с толку, когда я тестировал прицел на себе. - person Nathan Boyer; 13.05.2020
comment
@NathanBoyer на самом деле правила области были изменены, и есть некоторые правила, которые были введены, чтобы сделать это более прозрачным. Это действительно запутанно ;) - person tamasgal; 13.05.2020

Я обнаружил, что это работает в Julia v1.0:

let 
    myfriends = ["Ted", "Robyn", "Barney", "Lily", "Marshall"]
    i = 1;

    while i <= length(myfriends) # this function here seems to work no problem
        friend = myfriends[i]
        println("Hi $friend, it's great to see you!")
        i = i + 1 # gives syntax error when prefixed with global 
    end
end

Фактически, это выдаст мне синтаксическую ошибку, если я попытаюсь сделать i глобальным :) в цикле while.

person Michael Paul    schedule 28.08.2018