जूलिया में एक "प्रतीक" क्या है?


131

विशेष रूप से: मैं जूलिया के डेटाफ्रेम पैकेज का उपयोग करने की कोशिश कर रहा हूं, विशेष रूप से नाम विकल्प के साथ पठनीय () फ़ंक्शन, लेकिन इसके लिए प्रतीकों के वेक्टर की आवश्यकता होती है।

  • प्रतीक क्या है?
  • वे तार के सदिश से अधिक क्यों चुनेंगे?

अब तक मुझे जूलिया भाषा में शब्द प्रतीक के लिए केवल कुछ ही संदर्भ मिले हैं। ऐसा लगता है कि प्रतीकों को ": var" द्वारा दर्शाया गया है, लेकिन यह मेरे लिए स्पष्ट से बहुत दूर है कि वे क्या हैं।

एक तरफ: मैं चला सकता हूँ

df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )

मेरे दो बुलेटेड सवाल अभी भी खड़े हैं।


3
इस विषय पर कुछ बातचीत यहां पाया जा सकता: groups.google.com/d/msg/julia-users/MS7KW8IU-0o/cQ-yDOs_CQEJ
jverzani

जवाबों:


231

जूलिया में प्रतीक लिस्प, स्कीम या रूबी में समान हैं। हालाँकि, उन संबंधित प्रश्नों के उत्तर वास्तव में संतोषजनक नहीं हैं , मेरी राय में। यदि आप उन उत्तरों को पढ़ते हैं, तो ऐसा लगता है कि प्रतीक एक स्ट्रिंग से अलग है कारण यह है कि तार परस्पर भिन्न हैं जबकि प्रतीक अपरिवर्तनीय हैं, और प्रतीक "इंटर्न" भी हैं - जो भी इसका मतलब है। रूबी और लिस्प में स्ट्रैटिबल होने के लिए स्ट्रिंग्स होते हैं, लेकिन वे जूलिया में नहीं हैं, और यह अंतर वास्तव में एक लाल हेरिंग है। तथ्य यह है कि प्रतीकों को नजरअंदाज किया जाता है - यानी तेजी से समानता की तुलना के लिए भाषा कार्यान्वयन द्वारा हैशेड - एक अप्रासंगिक कार्यान्वयन विस्तार भी है। आपके पास एक ऐसा कार्यान्वयन हो सकता है जो प्रतीकों को आंतरिक नहीं करता है और भाषा बिल्कुल समान होगी।

तो क्या एक प्रतीक है, वास्तव में? इसका उत्तर कुछ इस तरह से है कि जूलिया और लिस्प में आम है - भाषा के कोड को भाषा में डेटा संरचना के रूप में दर्शाने की क्षमता। कुछ लोग इसे "समरूपता" ( विकिपीडिया ) कहते हैं, लेकिन दूसरों को यह नहीं लगता है कि अकेले भाषा के लिए पर्याप्त है। लेकिन शब्दावली वास्तव में मायने नहीं रखती है। मुद्दा यह है कि जब कोई भाषा अपने स्वयं के कोड का प्रतिनिधित्व कर सकती है, तो उसे असाइनमेंट, फ़ंक्शन कॉल, ऐसी चीज़ों का प्रतिनिधित्व करने के लिए एक रास्ता चाहिए, जिसे शाब्दिक मूल्यों के रूप में लिखा जा सकता है, आदि। इसके लिए अपने स्वयं के चर का प्रतिनिधित्व करने का एक तरीका भी आवश्यक है। यानी, आपको डेटा के रूप में प्रतिनिधित्व करने के लिए एक तरीका चाहिए - इस fooके बाईं ओर:

foo == "foo"

अब हम इस मामले के दिल में आ रहे हैं: एक प्रतीक और एक स्ट्रिंग के बीच का अंतर fooउस तुलना के बाएं हाथ की तरफ और "foo"दाहिने हाथ की तरफ के बीच का अंतर है । बाईं ओर, fooएक पहचानकर्ता है और यह fooवर्तमान क्षेत्र में चर के लिए बाध्य मूल्य का मूल्यांकन करता है । दाईं ओर, "foo"एक स्ट्रिंग शाब्दिक है और यह स्ट्रिंग मान "फू" का मूल्यांकन करता है। लिस्प और जूलिया दोनों में एक प्रतीक यह है कि आप डेटा के रूप में एक चर का प्रतिनिधित्व कैसे करते हैं। एक तार सिर्फ खुद का प्रतिनिधित्व करता है। आप evalउन्हें लागू करके अंतर देख सकते हैं :

julia> eval(:foo)
ERROR: foo not defined

julia> foo = "hello"
"hello"

julia> eval(:foo)
"hello"

julia> eval("foo")
"foo"

प्रतीक क्या :fooमूल्यांकन करता है, इस पर निर्भर करता है कि क्या - अगर कुछ भी - चर के fooलिए बाध्य है, जबकि "foo"हमेशा "फू" का मूल्यांकन करता है। यदि आप जूलिया में उन अभिव्यक्तियों का निर्माण करना चाहते हैं जो चर का उपयोग करते हैं, तो आप प्रतीकों का उपयोग कर रहे हैं (चाहे आप इसे जानते हैं या नहीं)। उदाहरण के लिए:

julia> ex = :(foo = "bar")
:(foo = "bar")

julia> dump(ex)
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol foo
    2: String "bar"
  typ: Any

अन्य चीजों के अलावा, जो सामान दिखाता है, वह यह है कि :fooकोड को उद्धृत करके आपको प्राप्त होने वाली अभिव्यक्ति ऑब्जेक्ट के अंदर एक प्रतीक वस्तु है foo = "bar"। यहां एक और उदाहरण दिया गया है, :fooजो चर में संग्रहीत प्रतीक के साथ एक अभिव्यक्ति का निर्माण कर रहा है sym:

julia> sym = :foo
:foo

julia> eval(sym)
"hello"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        foo = "bar"
        1 + 2
    end)

julia> eval(ex)
3

julia> foo
"bar"

यदि आप symस्ट्रिंग के लिए बाध्य होने पर ऐसा करने की कोशिश करते हैं "foo", तो यह काम नहीं करेगा:

julia> sym = "foo"
"foo"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        "foo" = "bar"
        1 + 2
    end)

julia> eval(ex)
ERROR: syntax: invalid assignment location ""foo""

यह देखने के लिए बहुत स्पष्ट है कि यह काम क्यों नहीं करेगा - यदि आपने "foo" = "bar"हाथ से असाइन करने की कोशिश की है , तो यह भी काम नहीं करेगा।

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

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

स्ट्रिंग के बजाय डेटा फ़्रेम्स में प्रतीकों का उपयोग क्यों किया जाता है, इसका कारण यह है कि कॉलम-वैल्यूज़ को उपयोगकर्ता-प्रदान की गई अभिव्यक्तियों के अंदर वेरिएबल्स से बाँधने के लिए डेटाफ़्रेम में यह एक सामान्य पैटर्न है। इसलिए कॉलम नामों के लिए प्रतीक होना स्वाभाविक है, क्योंकि प्रतीक वही हैं जो आप डेटा के रूप में चर का प्रतिनिधित्व करने के लिए उपयोग करते हैं। वर्तमान में, आपको कॉलम df[:foo]को एक्सेस करने के लिए लिखना होगा foo, लेकिन भविष्य में, आप df.fooइसके बजाय इसे एक्सेस करने में सक्षम हो सकते हैं । जब यह संभव हो जाता है, केवल कॉलम जिनके नाम मान्य पहचानकर्ता हैं, इस सुविधाजनक वाक्यविन्यास के साथ सुलभ होंगे।

यह सभी देखें:


6
इंटरस्टिंग: कंप्यूटर विज्ञान में, स्ट्रिंग इंटर्निंग प्रत्येक विशिष्ट स्ट्रिंग मान की केवल एक प्रति संग्रहीत करने की एक विधि है, जिसे अपरिवर्तनीय होना चाहिए। इंटरस्टिंग तार कुछ स्ट्रिंग प्रोसेसिंग कार्यों को अधिक समय देता है- या जब स्ट्रिंग बनाया या इंटर्न किया जाता है, तो अधिक समय की आवश्यकता की लागत पर अंतरिक्ष-कुशल। en.wikipedia.org/wiki/String_interning
xiaodai

एक बिंदु पर आप लिखते हैं eval(:foo)और दूसरे पर eval(sym)। क्या eval(:foo)और के बीच एक सार्थक अंतर है eval(foo)?
ग्रेस्केल

बहुत अधिक: eval(:foo)मान देता है कि चर fooबाध्य है, जबकि eval(foo)उस मूल्य पर कॉल कॉल करता है। लेखन eval(:foo)सिर्फ foo(वैश्विक दायरे में) के बराबर eval(foo)है eval(eval(:foo))
स्टेफानकारपिंस्की
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.