jq में आप अपने कस्टम फंक्शन बना सकते हैं, ताकि जो भी लॉजिक आपको चाहिए उसे एक जगह समेट सकें।
फंक्शन बिल्टइन की तरह ही काम करते हैं: वे एक इनपुट लेते हैं और शून्य, एक या अधिक आउटपुट देते हैं।
आप नीचे दिए गए सिंटैक्स से jq में एक फंक्शन बना सकते हैं:
# no arguments
def funcname: expression;
# or with arguments
def funcname(args): expression;
def कीवर्ड से होता है,jq के बाकी सिंटैक्स की तरह, पढ़ने में आसानी के लिए आप मनमानी खाली जगह छोड़ सकते हैं।फंक्शन को इस्तेमाल करने से पहले बनाना ज़रूरी है: यह एक एरर है:
def A: B(10);
def B(n): n + 1;
A
# => error: B/1 is not defined
इसका मतलब है कि आपको फंक्शन अपने jq कोड में सबसे ऊपर रखने होंगे, "मुख्य" एक्सप्रेशन से पहले।
फंक्शन नेस्टेड हो सकते हैं:
def A:
def B(n): n + 1;
B(10)
;
A
# => 11
यहाँ B फंक्शन सिर्फ A की बॉडी में ही दिखता है।
एक फंक्शन वेरिएबलो और नेस्टेड फंक्शन के लिए एक नया स्कोप बनाता है।
फंक्शन के आर्गुमेंट सेमीकोलन से अलग किए जाते हैं, कॉमा से नहीं। उदाहरण के लिए, एक फंक्शन जो एक संख्या लेता है, फिर एक संख्या जोड़ता है और एक संख्या से गुणा करता है:
def add_mul(adder; multiplier): (. + adder) * multiplier;
10 | add_mul(5; 4) # => 60
सेमीकोलन इसलिए ज़रूरी है क्योंकि jq में कॉमा का पहले से एक काम है: स्ट्रीम जोड़ने वाला ऑपरेटर।
सेमीकोलन की जगह कॉमा इस्तेमाल करने पर एक आर्गुमेंट वाले add_mul फंक्शन को दो बार कॉल करने की कोशिश होगी, जो मौजूद ही नहीं है, इसलिए पहली कॉल पर ही वह फेल हो जाएगी:
10 | add_mul(5, 4)
# error: add_mul/1 is not defined
फंक्शन के आर्गुमेंट फ़िल्टर होते हैं, वैल्यू नहीं। इस मायने में वे वैसा ही काम करते हैं जिसे दूसरी भाषाएँ कॉलबैक कहती हैं:
add_mul फंक्शन को उदाहरण के तौर पर लेते हैं:
10 | add_mul(. + 5; . - 2) # => 200
यहाँ हो क्या रहा है?
adder आर्गुमेंट को एक्सप्रेशन . + 5 मिलता है
. + adder चलाता है, तो यह . + . + 5 बन जाता है. == 10 है, इसका मान 25 निकलता हैmultiplier आर्गुमेंट एक्सप्रेशन . - 2 है
25 * 8 == 200 होता हैकभी-कभी आप किसी आर्गुमेंट को वेरिएबल में डालना चाहेंगे:
def my_func(arg):
arg as $arg
| other stuff ...
;
इसका एक शॉर्टहैंड भी है:
def my_func($arg):
other stuff ...
;
ध्यान दीजिए कि यह सिर्फ "सिंटैक्टिक शुगर" है: बिना $ वाला नाम arg भी फंक्शन के स्कोप में बना रहता है।
फंक्शन की एक आरिटी होती है, यानी वे जितने आर्गुमेंट लेते हैं उनकी संख्या।
फंक्शन एक ही नाम को अलग-अलग आरिटी के साथ इस्तेमाल कर सकते हैं।
बिल्टइन range फंक्शन इसका उदाहरण है: range/1, range/2 और range/3 तीनों एक साथ रह सकते हैं।
यह उन रिकर्सिव फंक्शन को बनाने में काम आ सकता है जो आर्गुमेंट के ज़रिए स्थिति साथ ले चलते हैं।
उदाहरण के लिए map को इस तरह बनाया जा सकता है:
def my_map($accumulator; func):
if length == 0
then $accumulator
else first as $elem | .[1:] | my_map($accumulator + [$elem | func]; func)
end
;
def my_map(func):
my_map([]; func)
;
[1, 2, 3, 4] | my_map(. * 10) # => [10, 20, 30, 40]
jq टेलकॉल ऑप्टिमाइज़ेशन करता है, लेकिन सिर्फ 0-आरिटी फंक्शन के लिए।
jq मॉड्यूल एक ऐसी फाइल होती है जिसमें सिर्फ फंक्शन होते हैं।
मॉड्यूल को include या import कमांड से किसी jq प्रोग्राम में शामिल किया जाता है।
इस अभ्यास में आप एक रिमोट कंट्रोल कार के साथ खेलेंगे, जिसे खरीदने के लिए आपने अब जाकर पूरा पैसा जोड़ लिया है।
कारें पूरी (100%) बैटरी के साथ शुरू होती हैं। हर बार जब आप रिमोट कंट्रोल से कार चलाते हैं, तो वह 20 मीटर चलती है और बैटरी का एक प्रतिशत खर्च कर देती है। कार बनने तक उसका उपनाम पता नहीं होता।
रिमोट कंट्रोल कार में एक शानदार LED डिस्प्ले है, जो दो तरह की जानकारी दिखाता है:
"<METERS> meters"।"Battery at <PERCENTAGE>%"।अगर बैटरी 0% पर है, तो आप कार को और नहीं चला सकते, और बैटरी डिस्प्ले "Battery empty" दिखाएगा।
new_remote_control_car/0 फंक्शन बनाइए, जो एक बिल्कुल नई रिमोट कंट्रोल कार ऑब्जेक्ट लौटाए:
new_remote_control_car
# => {
# "battery_percentage": 100,
# "distance_driven_in_meters": 0,
# "nickname": null
# }
new_remote_control_car/1 फंक्शन बनाइए, जो दिए गए उपनाम के साथ एक बिल्कुल नई रिमोट कंट्रोल कार ऑब्जेक्ट लौटाए:
new_remote_control_car("Blue")
# => {
# "battery_percentage": 100,
# "distance_driven_in_meters": 0,
# "nickname": "Blue"
# }
display_distance/0 फंक्शन बनाइए, जो इनपुट में एक कार ऑब्जेक्ट लेता है और LED डिस्प्ले पर दिखाई जाने वाली दूरी की स्ट्रिंग देता है:
new_remote_control_car | display_distance
# => "0 meters"
display_battery/0 फंक्शन बनाइए, जो इनपुट में एक कार ऑब्जेक्ट लेता है और LED डिस्प्ले पर दिखाई जाने वाली बैटरी प्रतिशत स्ट्रिंग देता है:
new_remote_control_car | display_battery
# => "Battery at 100%"
अगर बैटरी 0% पर है, तो बैटरी डिस्प्ले "Battery empty" दिखाएगा।
drive/0 फंक्शन बनाइए, जो:
new_remote_control_car("Red") | drive
# => {
# "battery_percentage": 99,
# "distance_driven_in_meters": 20,
# "nickname": "Red"
# }
drive/0 फंक्शन को ऐसे बदलिए कि जब बैटरी खत्म (0%) हो, तो न तय की गई दूरी बढ़े और न बैटरी का प्रतिशत घटे:
{
battery_percentage: 0,
distance_driven_in_meters: 2000,
nickname: "Red"
} | drive
# => {
# "battery_percentage": 0,
# "distance_driven_in_meters": 2000,
# "nickname": "Red"
# }
Exercism पर साइन अप कीजिए और jq को 12 कॉन्सेप्ट75 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।