एब्स्ट्रैक्ट सिंटैक्स ट्री (AST), जिसे कोटेड एक्सप्रेशन भी कहते हैं, कोड को डेटा के रूप में दर्शाने का एक तरीका है।
AST में हर नोड एक तीन एलिमेंट वाला टपल होता है।
# AST representation of:
# 2 + 3
{:+, [], [2, 3]}
पहला एलिमेंट, जो एक एटम है, ऑपरेशन होता है। दूसरा एलिमेंट, जो एक कीवर्ड ऐरे है, मेटाडेटा होता है। तीसरा एलिमेंट आर्गुमेंट का ऐरे होता है, जिसमें अन्य नोड होते हैं। पूर्णांक, एटम और स्ट्रिंग जैसी लिटरल वैल्यू AST में तीन एलिमेंट वाले टपल के बजाय खुद अपने रूप में दर्शाई जाती हैं।
Elixir कोड को AST में बदलना और AST को वापस कोड में बदलना स्टैंडर्ड लाइब्रेरी का हिस्सा है। AST के साथ काम करने वाले फंक्शन आपको दो मॉड्यूल में मिलेंगे: Code (जैसे कोड वाली स्ट्रिंग को AST में बदलने के लिए) और Macro (जैसे AST के हर नोड पर जाने या उसे स्ट्रिंग में बदलने के लिए)।
ध्यान दीजिए कि स्टैंडर्ड लाइब्रेरी के सभी फंक्शन AST के लिए "quoted" नाम इस्तेमाल करते हैं (जो कोटेड एक्सप्रेशन का छोटा रूप है)।
कोड को AST में बदलने वाला विशेष रूप quote कहलाता है। यह एक कोड ब्लॉक लेता है और उसका AST लौटाता है।
quote do
2 + 3 - 1
end
# => {:-, [], [
# {:+, [], [2, 3]},
# 1
# ]}
कोड को AST के रूप में दर्शाने की क्षमता Elixir में मेटाप्रोग्रामिंग का आधार है। मैक्रो, यानी Elixir कोड लिखने का एक तरीका जो खुद Elixir कोड बनाता है, आउटपुट के रूप में AST लौटाकर काम करते हैं।
AST का एक और उपयोग स्टैटिक कोड विश्लेषण है। इसका उदाहरण Exercism का अपना टूल एनालाइज़र है, जिसे आप शायद उस छोटे बॉट के रूप में पहले से जानते होंगे जो आपके हल पर टिप्पणियाँ छोड़ता है।
आप कॉर्पोरेट जासूसी के खिलाफ लड़ने वाली एक टास्क फोर्स का हिस्सा हैं। Shady Company X में आपका एक गुप्त मुखबिर है, और आपको शक है कि यह कंपनी अपने प्रतिस्पर्धियों से राज़ चुरा रही है।
आपकी मुखबिर Agent Ex एक Elixir डेवलपर हैं। वह अपने कोड में गुप्त संदेश एन्कोड करती हैं।
उसके गुप्त संदेश डिकोड करने के लिए:
n अक्षर लीजिए, जहाँ n उस फंक्शन की आर्टी है।TopSecret.to_ast/1 फंक्शन बनाइए। इसे Elixir कोड वाली एक स्ट्रिंग लेनी चाहिए और उसका AST लौटाना चाहिए।
TopSecret.to_ast("div(4, 3)")
# => {:div, [line: 1], [4, 3]}
TopSecret.decode_secret_message_part/2 फंक्शन बनाइए। इसे एक AST नोड और गुप्त संदेश के लिए एक एक्युमुलेटर (ऐरे) लेना चाहिए। इसे एक टपल लौटाना चाहिए, जिसमें पहला एलिमेंट वही AST नोड हो (बिना बदला हुआ) और दूसरा एलिमेंट एक्युमुलेटर हो।
अगर AST नोड का ऑपरेशन किसी फंक्शन को बनाना है (def या defp), तो फंक्शन के नाम को (स्ट्रिंग में बदलकर) एक्युमुलेटर के आगे जोड़ दीजिए। अगर ऑपरेशन कुछ और है, तो एक्युमुलेटर को बिना बदले लौटा दीजिए।
ast_node = TopSecret.to_ast("defp cat(a, b, c), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["cat", "day"]}
ast_node = TopSecret.to_ast("10 + 3")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["day"]}
इस फंक्शन को पूरे AST की जाँच के लिए कोई रिकर्सिव कॉल करने की ज़रूरत नहीं है, सिर्फ दिए गए नोड की। आखिरी चरण में हम बिल्ट-इन टूल की मदद से पूरे AST को एक-एक करके देखेंगे।
TopSecret.decode_secret_message_part/2 फंक्शन को आगे बढ़ाइए। अगर AST नोड का ऑपरेशन किसी फंक्शन को बनाना है, तो पूरा फंक्शन नाम न लौटाइए। इसके बजाय फंक्शन की आर्टी देखिए। फिर नाम से सिर्फ पहले n अक्षर लौटाइए, जहाँ n आर्टी है।
ast_node = TopSecret.to_ast("defp cat(a, b), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["ca", "day"]}
ast_node = TopSecret.to_ast("defp cat(), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["", "day"]}
TopSecret.decode_secret_message_part/2 फंक्शन को आगे बढ़ाइए। ध्यान रखिए कि जिन फंक्शन परिभाषाओं में गार्ड इस्तेमाल होते हैं, उनका नाम और आर्टी सही-सही पहचाने जाएँ।
ast_node = TopSecret.to_ast("defp cat(a, b) when is_nil(a), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["ca", "day"]}
TopSecret.decode_secret_message/1 फंक्शन बनाइए। इसे Elixir कोड वाली एक स्ट्रिंग लेनी चाहिए और कोड में मिली सभी फंक्शन परिभाषाओं से डिकोड किए गए गुप्त संदेश को एक स्ट्रिंग के रूप में लौटाना चाहिए। पिछले चरणों में बनाए गए फंक्शन दोबारा इस्तेमाल कीजिए।
code = """
defmodule MyCalendar do
def busy?(date, time) do
Date.day_of_week(date) != 7 and
time.hour in 10..16
end
def yesterday?(date) do
Date.diff(Date.utc_today, date)
end
end
"""
TopSecret.decode_secret_message(code)
# => "buy"
Exercism पर साइन अप कीजिए और Elixir को 58 कॉन्सेप्ट168 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।