حل

حلقه در Julia

2 تمرین

درباره‌ی حلقه

اساساً دو نوع حلقه وجود دارد:

  1. حلقه زدن تا زمانی که یک شرط برآورده شود.
  2. حلقه زدن روی عنصرهای یک مجموعه.

هر دو در Julia ممکن‌اند، هرچند ممکن است دومی رایج‌تر باشد.

حلقه‌ی while

برای مسئله‌های بازی که تعداد دفعات گردش در حلقه از پیش معلوم نیست، Julia حلقه‌ی while را دارد.

شکل پایه‌اش نسبتاً ساده است:

while condition
    do_something()
end

در این حالت، برنامه آن‌قدر دور حلقه می‌چرخد تا condition دیگر true نباشد.

دو راه برای خروج زودهنگام از حلقه وجود دارد:

  • یک break باعث خروج از حلقه می‌شود و اجرا از خط بعد از end حلقه ادامه می‌یابد.
  • یک return x اجرای تابع جاری را متوقف می‌کند و مقدار بازگشتی x را به فراخوانی‌کننده برمی‌گرداند.

با وجود این گزینه‌ها، گاهی راحت است که یک حلقه‌ی «بی‌نهایت» با while true ... end بسازید و بعد با یافتن یک شرط توقف در بدنه‌ی حلقه، یک break یا return را فعال کنید.

حلقه زدن روی یک مجموعه

ساده‌ترین نمونه، حلقه زدن روی یک بازه است.

اگر بخواهیم کاری را ۱۰ بار انجام دهیم:

for n in 1:10
    do_something(n)
end

اگر تکرار جاری شرطی را برآورده نکند، می‌توان با یک continue بی‌درنگ به تکرار بعدی پرید:

for n in 1:10
    if is_useless(n)
        continue
    end
    
    # we decided this iteration could be useful
    do_something_slow(n)
end

در شکلی کوتاه‌تر، می‌توان بلوک if را با is_useless(n) && continue جایگزین کرد.

می‌توان روی انواع دیگری از مجموعه‌ها هم حلقه زد: عنصرهای یک آرایه، نویسه‌های یک رشته، کلیدهای یک دیکشنری...

شرط این است که مجموعه باید iterable باشد. این موضوع در یک مفهوم بعدی با جزئیات بیشتری توضیح داده خواهد شد، اما در اصل مجموعه باید راهی داشته باشد که وقتی از آن خواسته شد، عنصر بعدی را بدهد و همچنین راهی برای نشان دادن این که به پایان رسیده و عنصر بیشتری وجود ندارد.

مثال‌های تا اینجا روی بازه‌ی 1:10 حلقه می‌زنند، جایی که مقدار همان اندیس حلقه هم هست.

به‌طور کلی‌تر، ممکن است به اندیس نیاز باشد و نه فقط به مقدار. برای این کار از تابع eachindex() استفاده می‌شود، مثلاً for i in eachindex(my_array) ... end.

کامپرهنشن‌ها

نوشتن حلقه‌های صریح در Julia کمتر از بسیاری از زبان‌های سنتی رایج است، چون گزینه‌های مختصرتر گوناگونی وجود دارد.

یک موقعیت به‌ویژه رایج زمانی است که می‌خواهیم یک بردار جدید از عنصرهای مجموعه‌ی دیگری بسازیم (بردار، رشته، مجموعه ... امکان‌های زیادی وجود دارد).

هر کسی که کامپرهنشن‌های فهرستی در Python را دوست دارد، خوشحال می‌شود بداند که Julia می‌تواند از نحوه‌ی نگارش مشابهی استفاده کند.

جان مطلب این است که یک حلقه‌ی بسیار فشرده را درون یک بردار بسازیم.

ساده‌ترین نحوه‌ی نگارش به شکل result = [f(x) for x in some_collection] است.

با یک حلقه‌ی سنتی، این را می‌توان چنین نوشت:

result = []
for x in some_collection
    push!(result, f(x))
end

به‌صورت اختیاری، می‌توان در پایان یک شرط اضافه کرد تا فقط عنصرهای منطبق در مجموعه انتخاب شوند:

# multiples of 3
julia> [n^2 for n in 1:10 if n%3 == 0]
3-element Vector{Int64}:
  9
 36
 81

# letters beyond 'h' in the alphabet
julia> [uppercase(c) for c in "Julia" if c > 'h']
3-element Vector{Char}:
 'U': ASCII/Unicode U+0055 (category Lu: Letter, uppercase)
 'L': ASCII/Unicode U+004C (category Lu: Letter, uppercase)
 'I': ASCII/Unicode U+0049 (category Lu: Letter, uppercase)

نحوه‌ی نگارش شبیه Python است، اما یکسان نیست. برای چند متغیر و/یا آرایه‌های چندبعدی تفاوت‌هایی وجود دارد، بنابراین این موضوع در یک مفهوم بعدی با جزئیات بیشتری بررسی خواهد شد.

گزینه‌های دیگر

Julia به‌عنوان زبانی مدرن و عمدتاً تابعی، طبیعتاً راه‌های گوناگونی برای کار روی مجموعه‌ها دارد، نه فقط یک حلقه‌ی صریح یا یک حلقه‌ی فشرده در یک کامپرهنشن.

مفهوم‌های بعدی به جایگزین‌هایی مانند پخش و توابع مرتبه‌بالا خواهند پرداخت.

ویرایش از طریق GitHub این پیوند در پنجره یا زبانه‌ی جدیدی باز می‌شود

حلقه را یاد بگیرید