I versjon 1.0 av Julia er det en særegenhet som man lett kan bli litt forvirret av, om man prøver å bruke løkker i det globale navnerommet (altså ikke inne i en funksjon). Følgende tilsynelatende opplagt korrekte kode fungerer nemlig ikke:

x = 0
for i = 1:10
    x += i
end

For løsninger, se lenger ned.

Det blir ikke nødvendigvis mindre forvirrende av at dette fungerte fint i versjon 0.6. Feilmeldingen man får er:

ERROR: LoadError: UndefVarError: x not defined

Det er mange som synes dette er lite intuitivt, og det er diskusjoner på gang om å endre atferden så den blir mindre overraskende, så innen du leser dette kan ting ha endret seg. Men om man forstår reglene bak navnerom i Julia, så er det hele egentlig ganske logisk og konsekvent.

Saken er at løkker har sitt eget lokale navnerom, akkurat som funksjoner, og man vil stort sett ikke at tilordninger i slike lokale navnerom skal endre globale variable. Det er jo hakket mer opplagt at det følgende ikke fungerer:

x = 0
f(i) = x += i
f(1)

Her får man samme feilmelding, og det er fordi tilordningen til x oppretter den som en lokal variabel i funksjonen f, og man prøver å hente ut verdien fra den før før den er definert. Her kunne man i stedet ha brukt

x = 0
f(i) = global x += i
f(1)

og så ville den globale variabelen x ha blitt endret – men normalt så er variable inne i funksjoner og løkker lokale. Normalt så vil man jo gjerne være i stand til bruke løkker til å endre variable utenfor løkka, uten å måtte gjøre dem globale – og det kan man også:

function g()
    x = 0
    for i = 1:10
        x += i
    end
end
g()

Grunnen til at dette fungerer er at man kan endre variable i omkringliggende lokale navnerom. Det betyr at det følgende også fungerer like fint:

function g()
    x = 0
    f(i) = x += i
    f(1)
end
g()

Løsninger

Noen mulige løsninger er:

  • Marker variabelen du har problemer med som global.
  • Pakk koden din inn i en funksjon.
  • Pakk koden din inn i noe annet med et eget navnerom.

Den første løsningen er nok den dårligste; det er generelt greit å unngå globale variable om man kan. Å bryte koden opp i funksjoner er generelt bra. Om du ser på stilguiden til Julia, så sier den første overskriften i skrivende stund «Write functions, not just scripts».

Om du liker å prototype koden som et enkelt script før du begynner å dele opp i funksjoner, så kan du bruke den tredje løsningen, og for eksempel bruke et let-utsagn. Disse brukes vanligvis eksplisitt til å introdusere nye variable, men om du kun trenger et midlertidig lokalt navnerom kan du bare skrive let før koden din og end etterpå. Med andre ord fungerer dette fint:

let
x = 0
for i = 1:10
    x += i
end
end