Julia 1.0

Modules




julia

Modules

जूलिया में मॉड्यूल अलग-अलग चर कार्यक्षेत्र हैं, यानी वे एक नया वैश्विक दायरा पेश करते हैं। वे सिंटैक्टिक रूप से सीमांकित हैं, module Name ... end अंदर module Name ... end । मॉड्यूल आपके नाम को किसी अन्य व्यक्ति के साथ मिलकर उपयोग किए जाने पर नाम के टकराव की चिंता किए बिना शीर्ष-स्तरीय परिभाषा (उर्फ वैश्विक चर) बनाने की अनुमति देता है। एक मॉड्यूल के भीतर, आप नियंत्रित कर सकते हैं कि कौन से अन्य मॉड्यूल से नाम दिखाई दे रहे हैं (आयात के माध्यम से), और निर्दिष्ट करें कि आपके कौन से नाम सार्वजनिक हैं (निर्यात के माध्यम से)।

निम्न उदाहरण मॉड्यूल की प्रमुख विशेषताओं को प्रदर्शित करता है। इसे चलाने के लिए नहीं है, लेकिन इसे उदाहरण के लिए दिखाया गया है:

module MyModule
using Lib

using BigLib: thing1, thing2

import Base.show

export MyType, foo

struct MyType
    x
end

bar(x) = 2x
foo(a::MyType) = bar(a.x) + 1

show(io::IO, a::MyType) = print(io, "MyType $(a.x)")
end

ध्यान दें कि स्टाइल मॉड्यूल के शरीर को इंडेंट करने के लिए नहीं है, क्योंकि यह आमतौर पर पूरी फाइलों को इंडेंट होने के लिए प्रेरित करेगा।

यह मॉड्यूल एक प्रकार MyType , और दो फ़ंक्शन को परिभाषित करता है। समारोह foo और टाइप MyType निर्यात किया जाता है, और इसलिए अन्य मॉड्यूल में आयात करने के लिए उपलब्ध होगा। फ़ंक्शन bar MyModule लिए निजी है।

using Lib का using Lib बयान using Lib अर्थ है कि Lib नामक एक मॉड्यूल आवश्यकतानुसार नामों को हल करने के लिए उपलब्ध होगा। जब एक वैश्विक चर का सामना किया जाता है जिसकी वर्तमान मॉड्यूल में कोई परिभाषा नहीं है, तो सिस्टम इसे Lib द्वारा निर्यात किए गए चर के बीच Lib और अगर यह वहां पाया जाता है तो इसे आयात करेगा। इसका मतलब यह है कि वर्तमान मॉड्यूल के भीतर उस वैश्विक के सभी उपयोग, उस चर की परिभाषा को Lib में हल करेंगे।

using BigLib: thing1, thing2 बयान मॉड्यूल BigLib से सिर्फ पहचानकर्ता thing1 और thing2 को दायरे में BigLib । यदि ये नाम फ़ंक्शंस का उल्लेख करते हैं, तो उनके लिए तरीकों को जोड़ने की अनुमति नहीं दी जाएगी (आप उन्हें केवल "उपयोग" कर सकते हैं, उनका विस्तार नहीं कर सकते)।

import कीवर्ड using रूप में एक ही वाक्यविन्यास का समर्थन करता है, लेकिन एक समय में केवल एक ही नाम पर संचालित होता है। यह मॉड्यूल का using करने के तरीके को खोजने के लिए नहीं जोड़ता है। import using से भी भिन्न होता है आयात का उपयोग करके import किए गए कार्यों को नए तरीकों से बढ़ाया जा सकता है।

ऊपर MyModule हम मानक show फ़ंक्शन के लिए एक विधि जोड़ना चाहते थे, इसलिए हमें import Base.show लिखना था। ऐसे कार्य जिनके नाम केवल using माध्यम से दिखाई देते हैं, उन्हें बढ़ाया नहीं जा सकता।

एक बार एक चर का using या import माध्यम से दिखाई देने के बाद, एक मॉड्यूल समान नाम के साथ अपना स्वयं का चर नहीं बना सकता है। आयातित चर केवल-पढ़ने के लिए हैं; एक वैश्विक चर को असाइन करना हमेशा वर्तमान मॉड्यूल के स्वामित्व वाले चर को प्रभावित करता है, या अन्यथा एक त्रुटि उठाता है।

मॉड्यूल उपयोग का सारांश

मॉड्यूल लोड करने के लिए, दो मुख्य कीवर्ड using किया जा सकता है: using और import । उनके अंतर को समझने के लिए, निम्नलिखित उदाहरण पर विचार करें:

module MyModule

export x, y

x() = "x"
y() = "y"
p() = "p"

end

इस मॉड्यूल में हम x और y फ़ंक्शंस (कीवर्ड export ) export , और इसमें नॉन-एक्सपोर्टेड फंक्शन p । वर्तमान कार्यक्षेत्र में मॉड्यूल और उसके आंतरिक कार्यों को लोड करने के कई अलग-अलग तरीके हैं:

आयात आदेश क्या दायरे में लाया जाता है विधि विस्तार के लिए उपलब्ध है
using MyModule सभी export एड नाम ( x और y ), MyModule.x , MyModule.y और MyModule.p MyModule.x , MyModule.y और MyModule.p
using MyModule: x, p x और p
import MyModule MyModule.x , MyModule.y और MyModule.p MyModule.x , MyModule.y और MyModule.p
import MyModule.x, MyModule.p x और p x और p
import MyModule: x, p x और p x और p

मॉड्यूल और फ़ाइलें

फ़ाइलें और फ़ाइल नाम ज्यादातर मॉड्यूल से असंबंधित हैं; मॉड्यूल केवल मॉड्यूल अभिव्यक्तियों से जुड़े होते हैं। प्रति मॉड्यूल कई फाइलें हो सकती हैं, और प्रति फ़ाइल कई मॉड्यूल हो सकते हैं:

module Foo

include("file1.jl")
include("file2.jl")

end

अलग-अलग मॉड्यूल में समान कोड शामिल करना मिश्रण-जैसा व्यवहार प्रदान करता है। एक ही कोड को विभिन्न आधार परिभाषाओं के साथ चलाने के लिए इसका उपयोग किया जा सकता है, उदाहरण के लिए कुछ ऑपरेटरों के "सुरक्षित" संस्करणों के साथ इसे चलाकर कोड का परीक्षण:

module Normal
include("mycode.jl")
end

module Testing
include("safe_operators.jl")
include("mycode.jl")
end

मानक मॉड्यूल

तीन महत्वपूर्ण मानक मॉड्यूल हैं: मुख्य, कोर और बेस।

मुख्य शीर्ष-स्तरीय मॉड्यूल है, और जूलिया वर्तमान मॉड्यूल के रूप में मुख्य सेट के साथ शुरू होता है। प्रॉम्प्ट पर परिभाषित वेरिएबल्स मेन में जाते हैं, और varinfo() मेन में वेरिएबल्स को सूचीबद्ध करता है।

कोर में सभी पहचानकर्ता शामिल होते हैं जिन्हें भाषा में "अंतर्निहित" माना जाता है, अर्थात मुख्य भाषा का हिस्सा और पुस्तकालय नहीं। प्रत्येक मॉड्यूल स्पष्ट रूप से using Core , क्योंकि आप उन परिभाषाओं के बिना कुछ भी नहीं कर सकते हैं।

आधार एक मॉड्यूल है जिसमें आधारभूत कार्यक्षमता (आधार / की सामग्री) है। सभी मॉड्यूल अंतर्निहित रूप से using Base , क्योंकि यह अधिकांश मामलों में आवश्यक है।

डिफ़ॉल्ट शीर्ष स्तर की परिभाषाएं और नंगे मॉड्यूल

using Base का using Base करने के अलावा, मॉड्यूल में स्वचालित रूप से eval की परिभाषाएं भी होती हैं और include फ़ंक्शन include हैं, जो उस मॉड्यूल के वैश्विक दायरे में अभिव्यक्तियों / फाइलों का मूल्यांकन करते हैं।

अगर इन डिफ़ॉल्ट परिभाषाओं को नहीं चाहते हैं, तो मॉड्यूल को इसके स्थान पर कीवर्ड baremodule का उपयोग करके परिभाषित किया जा सकता है (ध्यान दें: Core अभी भी आयात किया गया है, जैसा कि ऊपर)। baremodule संदर्भ में, एक मानक module इस तरह दिखता है:

baremodule Mod

using Base

eval(x) = Core.eval(Mod, x)
include(p) = Base.include(Mod, p)

...

end

सापेक्ष और पूर्ण मॉड्यूल पथ

using Foo हुए बयान को देखते हुए, सिस्टम using Foo -नाम के लिए शीर्ष-स्तरीय मॉड्यूल की आंतरिक तालिका को Foo । यदि मॉड्यूल मौजूद नहीं है, तो सिस्टम को require(:Foo) , जिसके परिणामस्वरूप आमतौर पर स्थापित पैकेज से कोड लोड होता है।

हालांकि, कुछ मॉड्यूल में सबमॉड्यूल होते हैं, जिसका अर्थ है कि आपको कभी-कभी एक गैर-शीर्ष-स्तरीय मॉड्यूल तक पहुंचने की आवश्यकता होती है। इसे करने के दो तरीके हैं। पहला एक निरपेक्ष पथ का उपयोग करना है, उदाहरण के लिए using Base.Sort । दूसरा एक सापेक्ष पथ का उपयोग करना है, जो वर्तमान मॉड्यूल या इसके किसी भी संलग्न मॉड्यूल के सबमॉड्यूल्स को आयात करना आसान बनाता है:

module Parent

module Utils
...
end

using .Utils

...
end

यहाँ मॉड्यूल Parent में एक सबमॉड्यूल Utils , और Parent में कोड चाहता है कि Utils की सामग्री दिखाई दे। यह एक अवधि के साथ using पथ शुरू using किया जाता है। अधिक अग्रणी अवधियों को जोड़ने से मॉड्यूल पदानुक्रम में अतिरिक्त स्तर बढ़ जाता है। उदाहरण के लिए using ..Utils Parent के बजाय Parent using ..Utils मॉड्यूल में Utils using ..Utils करेंगे।

ध्यान दें कि स्टेटमेंट-इंपोर्ट क्वालिफायर केवल स्टेटमेंट्स के using और import में ही मान्य हैं।

मॉड्यूल फ़ाइल पथ

वैश्विक चर LOAD_PATH में जूलिया को LOAD_PATH लिए निर्देशिकाओं की require । इसे push! का उपयोग करके बढ़ाया जा सकता है push! :

push!(LOAD_PATH, "/Path/To/My/Module/")

इस स्टेटमेंट को फाइल में डाल देना ~/.julia/config/startup.jl हर LOAD_PATH स्टार्टअप पर LOAD_PATH का विस्तार करेगा। वैकल्पिक रूप से, मॉड्यूल लोड पथ को पर्यावरण चर JULIA_LOAD_PATH को परिभाषित करके बढ़ाया जा सकता है।

नेमस्पेस मेस्केलानिया

यदि कोई नाम योग्य है (उदाहरण के लिए Base.sin ), तो इसे निर्यात नहीं होने पर भी एक्सेस किया जा सकता है। डिबगिंग के समय यह अक्सर उपयोगी होता है। इसमें फ़ंक्शन नाम के रूप में योग्य नाम का उपयोग करके इसमें जोड़े गए तरीके भी हो सकते हैं। हालाँकि, उत्पन्न होने वाली सिंथैटिक अस्पष्टताओं के कारण, यदि आप किसी भिन्न मॉड्यूल में किसी फ़ंक्शन के तरीकों को जोड़ना चाहते हैं, जिसके नाम में केवल चिह्न होते हैं, जैसे कि ऑपरेटर, Base.+ उदाहरण के लिए, आपको इसका उल्लेख करने के लिए Base.:+ का उपयोग करना होगा। । यदि ऑपरेटर लंबाई में एक से अधिक वर्ण का है, तो आपको उसे कोष्ठक में घेरना चाहिए, जैसे: Base.:(==)

मैक्रो नाम @ में आयात और निर्यात कथनों के साथ लिखे गए हैं, जैसे import [email protected] । अन्य मॉड्यूल में मैक्रोज़ को [email protected] या @Mod.mac रूप में लागू किया जा सकता है।

वाक्यविन्यास Mx = y किसी अन्य मॉड्यूल में वैश्विक असाइन करने के लिए काम नहीं करता है; वैश्विक असाइनमेंट हमेशा मॉड्यूल-स्थानीय होता है।

एक चर नाम "आरक्षित" हो सकता है, इसे global x रूप में घोषित किए बिना। यह लोड समय के बाद शुरू किए गए ग्लोबल्स के लिए नाम संघर्ष को रोकता है।

मॉड्यूल आरंभीकरण और precompilation

बड़े मॉड्यूल को लोड करने में कई सेकंड लग सकते हैं क्योंकि मॉड्यूल में सभी कथनों को निष्पादित करने में अक्सर बड़ी मात्रा में कोड संकलित करना शामिल होता है। जूलिया इस समय को कम करने के लिए मॉड्यूल के पूर्व-निर्मित कैश बनाता है।

वृद्धिशील precompiled मॉड्यूल फ़ाइल बनाई जाती है और import का उपयोग करते समय या मॉड्यूल लोड करने के लिए using करते समय स्वचालित रूप से उपयोग किया जाता है। यह पहली बार आयात होने के कारण इसे स्वचालित रूप से संकलित करने का कारण बनेगा। वैकल्पिक रूप से, आप मैन्युअल रूप से Base.compilecache(modulename) कॉल कर सकते हैं। परिणामी कैश फ़ाइलों को DEPOT_PATH[1]/compiled/ में संग्रहित किया जाएगा। इसके बाद, जब भी इसकी कोई निर्भरता बदलती है, तो मॉड्यूल का using या import पर स्वचालित रूप से पुनर्नवीनीकरण किया using ; निर्भरता मॉड्यूल इसे आयात करते हैं, जूलिया निर्माण, इसमें शामिल फाइलें, या मॉड्यूल फ़ाइल (नों) में include_dependency(path) द्वारा घोषित स्पष्ट निर्भरताएं हैं।

फ़ाइल निर्भरता के लिए, एक परिवर्तन जाँच द्वारा निर्धारित किया जाता है कि क्या प्रत्येक फ़ाइल का संशोधन समय (mtime) include या स्पष्ट रूप से include द्वारा जोड़ा गया है। निर्भरता अपरिवर्तित है, या संशोधन के समय के बराबर निकटतम दूसरी (सिस्टम को समायोजित नहीं कर सकते हैं) प्रतिलिपि उप-दूसरी सटीकता के साथ माइम)। यह इस बात को भी ध्यान में रखता है कि क्या खोज लॉजिक द्वारा चुनी गई फ़ाइल का पथ उस पथ से मेल खाता है जिसने precompile फ़ाइल बनाई थी। यह भी निर्भर करता है कि वर्तमान प्रक्रिया में पहले से लोड की गई निर्भरता का सेट और उन मॉड्यूल को फिर से जोड़ नहीं सकता है, भले ही उनकी फाइलें बदल जाएं या गायब हो जाएं, ताकि रनिंग सिस्टम और प्रीकॉपील कैश के बीच असंगति पैदा करने से बचें।

यदि आप जानते हैं कि एक मॉड्यूल आपके मॉड्यूल को precompile करने के लिए सुरक्षित नहीं है (उदाहरण के लिए, नीचे वर्णित कारणों में से एक के लिए), तो आपको मॉड्यूल फ़ाइल (आमतौर पर शीर्ष पर रखा गया __precompile__(false) में __precompile__(false) डालना चाहिए। यह Base.compilecache को एक त्रुटि फेंकने का कारण Base.compilecache , और इसे वर्तमान प्रक्रिया में सीधे लोड करने और प्रीकंपाइल और कैशिंग को छोड़ने के लिए using / import करने using कारण होगा। यह भी मॉड्यूल को किसी भी अन्य पूर्वनिर्मित मॉड्यूल द्वारा आयात किए जाने से रोकता है।

वृद्धिशील साझा पुस्तकालयों के निर्माण में निहित कुछ व्यवहारों से आपको अवगत होना पड़ सकता है, जिन्हें आपके मॉड्यूल को लिखते समय देखभाल की आवश्यकता हो सकती है। उदाहरण के लिए, बाहरी राज्य संरक्षित नहीं है। इसे समायोजित करने के लिए, संकलित समय पर हो सकने वाले चरणों से रनटाइम पर होने वाले किसी भी प्रारंभ चरणों को स्पष्ट रूप से अलग करें। इस प्रयोजन के लिए, जूलिया आपको अपने मॉड्यूल में एक __init__() फ़ंक्शन को परिभाषित करने की अनुमति देता है जो रनटाइम पर होने वाले किसी भी आरंभिक चरणों को निष्पादित करता है। इस फ़ंक्शन को संकलन ( --output-* ) के दौरान नहीं बुलाया जाएगा। प्रभावी रूप से, आप मान सकते हैं कि यह कोड के जीवनकाल में एक बार ठीक से चलाया जाएगा। आप निश्चित रूप से, यदि आवश्यक हो तो इसे मैन्युअल रूप से कॉल कर सकते हैं, लेकिन डिफ़ॉल्ट इस फ़ंक्शन को स्थानीय मशीन के लिए कंप्यूटिंग स्थिति से संबंधित मान लेता है, जिसे संकलित छवि में कैप्चर करने - या होने की भी आवश्यकता नहीं है। मॉड्यूल को एक प्रक्रिया में लोड किए जाने के बाद इसे बुलाया जाएगा, जिसमें यह शामिल है कि क्या इसे वृद्धिशील संकलन ( --output-incremental=yes ) में लोड किया जा रहा है, लेकिन यह नहीं कि इसे पूर्ण-संकलन प्रक्रिया में लोड किया जा रहा है।

विशेष रूप से, यदि आप किसी मॉड्यूल में एक function __init__() को परिभाषित करते हैं, तो जूलिया पहली बार रनटाइम के दौरान मॉड्यूल लोड होने (जैसे, import , using , या require ) के तुरंत बाद __init__() कॉल करेगा (यानी, __init__ ) केवल एक बार बुलाया गया है, और केवल मॉड्यूल में सभी बयानों को निष्पादित किया गया है)। क्योंकि यह मॉड्यूल पूरी तरह से आयातित होने के बाद कहा जाता है, किसी भी सबमॉड्यूल्स या अन्य आयातित मॉड्यूल के पास अपने __init__ फ़ंक्शंस हैं, जो कि संलग्न मॉड्यूल के __init__ से पहले कॉल किए जाते हैं।

__init__ दो विशिष्ट उपयोग बाहरी सी पुस्तकालयों के रनटाइम इनिशियलाइज़ेशन कार्यों को कहते हैं और वैश्विक स्थिरांक को आरम्भ करते हैं, जिसमें बाहरी पुस्तकालयों द्वारा दिए गए संकेत शामिल होते हैं। उदाहरण के लिए, मान लें कि हम एक C लाइब्रेरी libfoo कह रहे हैं जिसके लिए हमें रन-टाइम पर foo_init() इनिशियलाइज़ेशन फंक्शन कॉल करना होगा। मान लें कि हम एक वैश्विक निरंतर foo_data_ptr को परिभाषित करना चाहते हैं जो कि void *foo_data() द्वारा परिभाषित एक void *foo_data() फ़ंक्शन का रिटर्न मान libfoo - इस स्थिरांक को रनटाइम पर शुरू किया जाना चाहिए (समय पर नहीं) क्योंकि सूचक पता रन से बदल जाएगा चलाते हैं। आप अपने मॉड्यूल में निम्नलिखित __init__ फ़ंक्शन को परिभाषित करके इसे पूरा कर सकते हैं:

const foo_data_ptr = Ref{Ptr{Cvoid}}(0)
function __init__()
    ccall((:foo_init, :libfoo), Cvoid, ())
    foo_data_ptr[] = ccall((:foo_data, :libfoo), Ptr{Cvoid}, ())
    nothing
end

ध्यान दें कि __init__ जैसे फ़ंक्शन के अंदर एक वैश्विक को परिभाषित करना पूरी तरह से संभव है; यह एक गतिशील भाषा का उपयोग करने के लाभों में से एक है। लेकिन इसे वैश्विक दायरे में एक स्थिर बनाकर, हम यह सुनिश्चित कर सकते हैं कि प्रकार संकलक के लिए जाना जाता है और इसे बेहतर अनुकूलित कोड उत्पन्न करने की अनुमति देता है। जाहिर है, आपके मॉड्यूल में कोई भी अन्य foo_data_ptr जो foo_data_ptr पर निर्भर करता है, को भी foo_data_ptr करना होगा।

अधिकांश जूलिया ऑब्जेक्ट्स जो कि ccall द्वारा निर्मित नहीं होते हैं, उन्हें ccall आवश्यकता नहीं होती है: उनकी परिभाषाओं को कैश्ड मॉड्यूल छवि से precompiled और लोड किया जा सकता है। इसमें जटिल ढेर-आवंटित वस्तुएं जैसे सरणियाँ शामिल हैं। हालांकि, किसी भी रूटीन पॉइंटर वैल्यू को वापस करने वाले किसी भी रूटीन को काम के लिए प्रीकंप्लीमेंटेशन के लिए रनटाइम पर कॉल किया जाना चाहिए (पंरट ऑब्जेक्ट्स नल पॉइंटर्स में बदल जाएंगे, जब तक कि वे एक इबिट्स ऑब्जेक्ट के अंदर छिपे हों)। इसमें जूलिया फ़ंक्शंस cfunction और pointer के रिटर्न मान शामिल हैं।

शब्दकोश और सेट प्रकार, या सामान्य रूप से कुछ भी जो hash(key) विधि के आउटपुट पर निर्भर करता है, एक पेचीदा मामला है। सामान्य स्थिति में जहाँ कुंजियाँ संख्याएँ, तार, प्रतीक, पर्वतमाला, Expr , या इन प्रकार की रचनाएँ (सरणियों, टुपल्स, सेट, जोड़े, आदि के माध्यम से) होती हैं, वे precompile के लिए सुरक्षित होती हैं। हालाँकि, कुछ अन्य प्रमुख प्रकारों के लिए, जैसे Function या DataType और जेनेरिक उपयोगकर्ता-परिभाषित प्रकार जहाँ आपने hash विधि निर्धारित नहीं की है, फ़ॉलबैक hash विधि ऑब्जेक्ट के मेमोरी एड्रेस (इसके ऑब्जेक्ट के माध्यम से) पर निर्भर करती है और इसलिए रन से रन में बदलाव। यदि आपके पास इन प्रमुख प्रकारों में से एक है, या यदि आप निश्चित नहीं हैं, तो सुरक्षित रहने के लिए आप इस डिक्शनरी को अपने __init__ फंक्शन के भीतर से इनिशियलाइज़ कर सकते हैं। वैकल्पिक रूप से, आप IdDict डिक्शनरी प्रकार का उपयोग कर सकते हैं, जो विशेष रूप से precompilation द्वारा संभाला जाता है ताकि संकलन-समय पर आरंभ करना सुरक्षित हो।

Precompilation का उपयोग करते समय, संकलन चरण और निष्पादन चरण के बीच अंतर की स्पष्ट भावना रखना महत्वपूर्ण है। इस मोड में, यह अक्सर अधिक स्पष्ट रूप से स्पष्ट होगा कि जूलिया एक संकलक है जो मनमाने ढंग से जूलिया कोड के निष्पादन की अनुमति देता है, न कि एक स्टैंडअलोन दुभाषिया जो संकलित कोड भी उत्पन्न करता है।

अन्य ज्ञात संभावित विफलता परिदृश्यों में शामिल हैं:

  1. वैश्विक काउंटर (उदाहरण के लिए, वस्तुओं की विशिष्ट पहचान के प्रयास के लिए) निम्नलिखित कोड स्निपेट पर विचार करें:

    mutable struct UniquedById
        myid::Int
        let counter = 0
            UniquedById() = new(counter += 1)
        end
    end

    जबकि इस कोड का आशय प्रत्येक उदाहरण को एक अद्वितीय आईडी देना था, संकलन के अंत में काउंटर मूल्य दर्ज किया गया है। इस क्रमिक रूप से संकलित मॉड्यूल के सभी बाद के उपयोग उसी काउंटर मूल्य से शुरू होंगे।

    ध्यान दें कि objectid (जो मेमोरी पॉइंटर को हैशिंग द्वारा काम करता है) में समान मुद्दे हैं (नीचे दी गई उपयोग पर नोट देखें)।

    एक विकल्प @__MODULE__ पर कब्जा करने के लिए एक मैक्रो का उपयोग @__MODULE__ और इसे वर्तमान counter मूल्य के साथ अकेले स्टोर करना है, हालांकि, इस वैश्विक स्थिति पर निर्भर नहीं करने के लिए कोड को फिर से डिज़ाइन करना बेहतर हो सकता है।

  2. साहचर्य संग्रह (जैसे कि Dict और Set ) को __in__ में फिर से __init__ । (भविष्य में, एक आरंभिक कार्य को पंजीकृत करने के लिए एक तंत्र प्रदान किया जा सकता है।)

  3. लोड-टाइम के माध्यम से बने संकलन-समय के दुष्प्रभावों पर निर्भर करता है। उदाहरण में शामिल हैं: अन्य जूलिया मॉड्यूल में सरणियों या अन्य चर को संशोधित करना; फ़ाइलों या उपकरणों को खोलने के लिए हैंडल बनाए रखना; अन्य सिस्टम संसाधनों (मेमोरी सहित) के लिए स्टोरिंग पॉइंटर्स;

  4. किसी अन्य मॉड्यूल से वैश्विक राज्य की आकस्मिक "प्रतियां" बनाना, इसके लुकअप पथ के बजाय सीधे इसे संदर्भित करके। उदाहरण के लिए, (वैश्विक दायरे में):

    #mystdout = Base.stdout #= will not work correctly, since this will copy Base.stdout into this module =#
    # instead use accessor functions:
    getstdout() = Base.stdout #= best option =#
    # or move the assignment into the runtime:
    __init__() = global mystdout = Base.stdout #= also works =#

संचालन पर कई अतिरिक्त प्रतिबंध लगाए गए हैं जो उपयोगकर्ता को अन्य गलत व्यवहार स्थितियों से बचने में मदद करने के लिए कोड को precompiling करते समय किया जा सकता है:

  1. दूसरे मॉड्यूल में साइड-इफ़ेक्ट पैदा करने के लिए eval का आह्वान। यह वृद्धिशील precompile ध्वज सेट होने पर उत्सर्जित होने की चेतावनी भी देगा।
  2. __init__() बाद स्थानीय दायरे से global const स्टेटमेंट शुरू किए गए हैं (देखें कि समस्या के लिए एक त्रुटि जोड़ने की योजना के लिए # 12010 जारी करें)
  3. एक मॉड्यूल को बदलना एक वृद्धिशील त्रुटि है जबकि एक वृद्धिशील precompile है।

कुछ अन्य बिंदुओं से अवगत होना:

  1. कोई कोड पुनः लोड / कैश अमान्य नहीं किया जाता है जब परिवर्तन स्वयं स्रोत फ़ाइलों में किए जाते हैं, ([ Pkg.update सहित), और [ Pkg.rm ] के बाद कोई सफाई नहीं की जाती है
  2. एक पुनर्व्यवस्थित सरणी का मेमोरी साझा व्यवहार प्रीकंप्लिमेशन द्वारा अस्वीकृत है (प्रत्येक दृश्य की अपनी प्रतिलिपि मिलती है)
  3. कम्पाइल-टाइम और रनटाइम के बीच फ़ाइल सिस्टम के अपरिवर्तित होने की उम्मीद करना, जैसे @__FILE__ / source_path() रनटाइम पर संसाधन खोजने के लिए, या BinDeps @checked_lib मैक्रो। कभी-कभी यह अपरिहार्य है। हालाँकि, जब संभव हो, संकलित समय में संसाधनों को कॉपी करने के लिए अच्छा अभ्यास हो सकता है, इसलिए उन्हें रनटाइम पर ढूंढने की आवश्यकता नहीं होगी।
  4. WeakRef ऑब्जेक्ट और WeakRef वर्तमान में serializer द्वारा ठीक से नहीं संभाला जाता है (यह आगामी रिलीज़ में ठीक किया जाएगा)।
  5. आमतौर पर आंतरिक मेटाडेटा ऑब्जेक्ट्स जैसे कि Method , MethodInstance , MethodTable , TypeMapLevel , TypeMapEntry और उन ऑब्जेक्ट्स के फ़ील्ड्स के संदर्भों को कैप्चर करने से बचने के लिए सबसे अच्छा है, क्योंकि यह serializer को भ्रमित कर सकता है और आपके TypeMapEntry परिणाम का नेतृत्व नहीं कर सकता है। ऐसा करने के लिए जरूरी नहीं कि यह त्रुटि हो, लेकिन आपको बस तैयार रहने की जरूरत है कि सिस्टम इनमें से कुछ को कॉपी करने और दूसरों के एक एकल उदाहरण को बनाने की कोशिश करेगा।

यह कभी-कभी वृद्धिशील precompilation को बंद करने के लिए मॉड्यूल विकास के दौरान सहायक होता है। कमांड लाइन फ्लैग --compiled-modules={yes|no} आपको चालू और बंद मॉड्यूल को टॉगल करने में सक्षम बनाता है। जब जूलिया को शुरू किया --compiled-modules=no संकलित मॉड्यूल में --compiled-modules=no लोड किए गए मॉड्यूल और मॉड्यूल निर्भरता को अनदेखा नहीं किया जाता है। Base.compilecache को अभी भी मैन्युअल रूप से कहा जा सकता है। इस कमांड लाइन फ्लैग की स्थिति को स्थापित करने, अपडेट करने और स्पष्ट निर्माण पैकेजों के दौरान स्वचालित Pkg.build ट्रिगर को अक्षम करने के लिए Pkg.build को पास किया Pkg.build है।