مسیرها
/
Julia
Julia
/
تمرین‌ها
/
عشق دبیرستانی
عشق دبیرستانی

عشق دبیرستانی

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

مقدمه

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

نتیجه‌ی این کار معمولاً انبوهی از توابع کوچک و ساده است که برای انجام کارهای غیرساده باید با هم ترکیب شوند.

یک راه واضح این است که فراخوانی توابع را تودرتو کنیم. مثال زیر خیلی ساختگی است، اما نکته را نشان می‌دهد.

julia> first.(titlecase.(reverse.(["my", "test", "strings"])))
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)

این روش یک اشکال دارد: هرچه تودرتویی عمیق‌تر شود، خوانایی به‌سرعت افت می‌کند.

به روشی ساده‌تر و انعطاف‌پذیرتر نیاز داریم.

ترکیب

این همان تکنیکی است که ریاضی‌دانان دوستش دارند و Julia شکل نوشتار ریاضی آن را کپی کرده است.

می‌توان هر تعداد دلخواهی از توابع را با عملگرهای ∘ composed کرد (برای وارد کردن این عملگر، \circ را تایپ کنید و بعد کلید تب را بزنید). نتیجه را می‌توان به‌عنوان یک تابع واحد به کار برد.

julia> compfunc = first ∘ titlecase ∘ reverse
first ∘ titlecase ∘ reverse
julia> compfunc.(["my", "test", "strings"])
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)
# alternative syntax, giving the same result
julia> (first ∘ titlecase ∘ reverse).(["my", "test", "strings"])

چند نکته که بهتر است به آن‌ها توجه کنید:

  • توابعی که کار را شروع می‌کنند به همان ترتیبی ظاهر می‌شوند که در تودرتو کردن داشتیم، و از راست به چپ اجرا می‌شوند.
  • استفاده از پخش در هنگام ترکیب ساده نیست، اما هنگام فراخوانی تابع ترکیب‌شده می‌توان آن را به کار برد.

پایپ‌لاین

راه جایگزین را می‌توان رویکرد برنامه‌نویسان دانست، نه ریاضی‌دانان.

Pipelines از دیرباز در اسکریپت‌های شل یونیکس به کار می‌رفته‌اند و به‌تازگی در زبان‌های برنامه‌نویسی جریان اصلی محبوب شده‌اند (گاهی پیشگامی در رواج آن‌ها را به F# نسبت می‌دهند).

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

عملگر پایپ |> است (همان‌طور که در F# و نسخه‌های اخیر R هست)، هرچند Julia نسخه‌ی پخشی .|> را هم دارد.

julia> ["my", "test", "strings"] .|> reverse .|> titlecase .|> first
3-element Vector{Char}:
 'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
 'T': ASCII/Unicode U+0054 (category Lu: Letter, uppercase)
 'S': ASCII/Unicode U+0053 (category Lu: Letter, uppercase)

اجرا حالا دقیقاً از چپ به راست است و خروجی هر تابع در جهت فلش پیش می‌رود تا ورودی تابع بعدی شود.

محدودیت‌ها، راه‌حل‌های موقت و گزینه‌های دیگر

تصادفی نیست که همه‌ی توابعی که برای نشان دادن ترکیب و پایپ‌لاین به کار رفتند، تنها یک آرگومان می‌گیرند.

برخی زبان‌های کاملاً تابعی، آرگومان اول را به تابع می‌فرستند اما اجازه می‌دهند آرگومان‌های دیگری هم همراه باشند.

در مقابل، Julia در یک پایپ‌لاین تنها اسم توابع (یا چیزی معادل آن) را انتظار دارد، بدون هیچ آرگومان اضافه‌ای.

دلایل فنی مهمی برای این کار وجود دارد (مربوط به این واقعیت که currying بخشی استاندارد از طراحی زبان نیست). بسیاری از کسانی که هیچ درکی از currying ندارند، فقط باید بپذیرند که این محدودیت یک سهو و بی‌دقتی نیست و احتمالاً در نسخه‌های آینده‌ی Julia تغییر نخواهد کرد.

راه‌حل‌های موقت

به توابعی نیاز داریم که تنها یک آرگومان بگیرند و هر کاری که لازم است انجام دهند. خوشبختانه، تعریف توابع تازه در Julia آسان است.

ساده‌ترین راه این است که از یک anonymous function استفاده کنیم. برای مثال، اگر یک رشته‌ی ورودی داشته باشیم و بخواهیم آن را بر اساس زیرخط‌ها تقسیم کنیم:

julia> "my_test_strings" |> (s -> split(s, '_'))
3-element Vector{SubString{String}}:
 "my"
 "test"
 "strings"

آن بردار را می‌توان بعداً مثل قبل به توابع دیگر پایپ کرد.

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

به همین ترتیب، می‌توانیم یک تابع با‌نام را زودتر در برنامه بسازیم و هر وقت لازم شد دوباره از آن استفاده کنیم.

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

در این تمرین، قرار است به عاشق‌های دوران دبیرستان کمک کنید تا عشق‌شان را در شبکه‌های اجتماعی با ساختن یک قلب یونی‌کد از حروف اول اسم‌شان اعلام کنند:

❤ J.  +  M. ❤

1. اسم را پاک‌سازی کنید

متد cleanupname را پیاده‌سازی کنید. این متد یک اسم می‌گیرد و همه‌ی کاراکترهای - را از آن حذف می‌کند و با یک فاصله جای‌گزین می‌کند. همچنین باید فاصله‌های اضافی را از ابتدا و انتهای اسم حذف کند.

julia> cleanupname("Jane-Ann")
"Jane Ann"

2. حرف اول اسم را به دست آورید

متد firstletter را پیاده‌سازی کنید. این متد یک اسم می‌گیرد و حرف اول آن را به‌صورت یک رشته برمی‌گرداند. حتماً از cleanupname که در گام قبلی تعریف کردید دوباره استفاده کنید و آن را با توابع دیگر ترکیب کنید.

julia> firstletter("Jane")
"J"

3. حرف اول را به‌صورت یک حرف اختصاری درآورید

متد initial را پیاده‌سازی کنید. این متد یک اسم می‌گیرد و حرف اول آن را با حروف بزرگ، به‌همراه یک نقطه برمی‌گرداند. حتماً از firstletter که در گام قبلی تعریف کردید دوباره استفاده کنید.

initial("Robert")
"R."

4. حروف اختصاری را داخل قلب بگذارید

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

couple("Blake Miller", "Riley Lewis")
"❤ B.  +  R. ❤"
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Julia Exercism

آماده‌اید عشق دبیرستانی را شروع کنید؟

در Exercism ثبت‌نام کنید تا Julia را همراه با 35 مفهوم128 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.