مسیرها
/
jq
jq
/
تمرین‌ها
/
ماشین کنترل از راه دور
ماشین کنترل از راه دور

ماشین کنترل از راه دور

تمرین یادگیری

مقدمه

توابع

می‌توانید توابع سفارشی خودتان را در 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
Note

نقطه‌ویرگول‌ها لازم هستند چون ویرگول در 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 است، حاصل ۲۵ می‌شود
  • به همین ترتیب، آرگومان 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 بهینه‌سازی فراخوانی انتهایی را انجام می‌دهد، اما فقط برای توابع با تعداد آرگومان صفر.

ماژول‌ها

ماژول jq فایلی است که فقط شامل توابع می‌شود. ماژول‌ها با فرمان‌های include یا import به یک برنامه‌ی jq وارد می‌شوند.

دستورالعمل‌ها

در این تمرین با یک ماشین کنترلی سر و کار دارید؛ ماشینی که بالاخره پول کافی برای خریدنش را پس‌انداز کرده‌اید.

ماشین‌ها با باتری کاملاً پر (۱۰۰٪) شروع می‌کنند. هر بار که ماشین را با کنترل از راه دور می‌رانید، ۲۰ متر جلو می‌رود و یک درصد از باتری را مصرف می‌کند. اسم مستعار ماشین تا زمانی که ساخته نشود، معلوم نیست.

ماشین کنترلی یک نمایشگر LED شیک دارد که دو بخش اطلاعات را نشان می‌دهد:

  • مسافت کل طی‌شده که به این شکل نمایش داده می‌شود: "<METERS> meters".
  • شارژ باقی‌مانده‌ی باتری که به این شکل نمایش داده می‌شود: "Battery at <PERCENTAGE>%".

اگر باتری به ۰٪ برسد، دیگر نمی‌توانید ماشین را برانید و نمایشگر باتری "Battery empty" را نشان می‌دهد.

1. ساخت یک ماشین کنترلی کاملاً نو

تابع new_remote_control_car/0 را پیاده‌سازی کنید تا یک شیء ماشین کنترلی کاملاً نو برگرداند:

new_remote_control_car
# => {
#      "battery_percentage": 100,
#      "distance_driven_in_meters": 0,
#      "nickname": null
#    }

2. ساخت یک ماشین کنترلی کاملاً نو با اسم مستعار

تابع new_remote_control_car/1 را پیاده‌سازی کنید تا یک شیء ماشین کنترلی کاملاً نو با اسم مستعار داده‌شده برگرداند:

new_remote_control_car("Blue")
# => {
#      "battery_percentage": 100,
#      "distance_driven_in_meters": 0,
#      "nickname": "Blue"
#    }

3. نمایش مسافت

تابع display_distance/0 را پیاده‌سازی کنید که یک شیء ماشین را به عنوان ورودی می‌گیرد و رشته‌ی مسافت را همان‌طور که روی نمایشگر LED نشان داده می‌شود، خروجی می‌دهد:

new_remote_control_car | display_distance
# => "0 meters"

4. نمایش درصد باتری

تابع display_battery/0 را پیاده‌سازی کنید که یک شیء ماشین را به عنوان ورودی می‌گیرد و رشته‌ی درصد باتری را همان‌طور که روی نمایشگر LED نشان داده می‌شود، خروجی می‌دهد:

new_remote_control_car | display_battery
# => "Battery at 100%"

اگر باتری به ۰٪ برسد، نمایشگر باتری «Battery empty» را نشان می‌دهد.

5. رانندگی باتری و مسافت طی‌شده را تغییر می‌دهد

تابع drive/0 را پیاده‌سازی کنید که:

  • یک شیء ماشین را به عنوان ورودی می‌گیرد
  • تعداد مترهای طی‌شده را ۲۰ واحد افزایش می‌دهد
  • یک درصد از باتری را مصرف می‌کند
  • شیء ماشین تغییر‌یافته را خروجی می‌دهد
new_remote_control_car("Red") | drive
# => {
#      "battery_percentage": 99,
#      "distance_driven_in_meters": 20,
#      "nickname": "Red"
#    }

6. در نظر گرفتن رانندگی با باتری خالی

تابع drive/0 را طوری به‌روزرسانی کنید که وقتی باتری خالی است (۰٪)، نه مسافت طی‌شده افزایش یابد و نه درصد باتری کاهش پیدا کند:

{
  battery_percentage: 0,
  distance_driven_in_meters: 2000,
  nickname: "Red"
} | drive
# => {
#      "battery_percentage": 0,
#      "distance_driven_in_meters": 2000,
#      "nickname": "Red"
#    }
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
jq Exercism

آماده‌اید ماشین کنترل از راه دور را شروع کنید؟

در Exercism ثبت‌نام کنید تا jq را همراه با 12 مفهوم75 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.