Треки
/
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 давно використовують у сценаріях оболонки Unix, а останнім часом вони набули популярності в поширених мовах програмування (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 не є стандартною частиною проєктування мови). Ті численні люди, які не розуміють каррінгу, мають просто прийняти, що це обмеження не є недбалою помилкою і навряд чи зміниться в майбутніх версіях Julia.

Обхідні шляхи

Нам потрібні функції з одним аргументом, які роблять усе, що потрібно. На щастя, визначати нові функції в Julia легко.

Найпростіше - скористатися anonymous function. Наприклад, якщо в нас є один вхідний рядок тексту (англ. string) і ми хочемо розділити його за символами підкреслення:

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. Він має приймати імʼя й повертати його першу літеру як рядок тексту (англ. string). Обовʼязково повторно використайте 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 вправ та справжнє наставництво від людей, і все це безкоштовно.