Функціональне програмування — з чого почати
Доброго дня і з Новим Роком, шановна спільнота!
Після останніх статтей Dmitry Astapov у мене з’явилося трохи більше мотивації взятися за ще одну мову, і спробувати таки писати у функціональній парадигмі. Всі питання мені хотілось задати тут, реальним фахівцям. Але вирішив спочатку пошукати самостійно.
Якщо у вас виникне питання «Щоб що?» — то just for fun! Ну і мізки розім’яти...
Заодно вирішив ще раз потестити ШІ, задовбавши його запитаннями — тож майже вся інформація надана Google Gemini 2.0 Flash Experimental та Copilot. Саме так і треба сприймати цю статтю — одночасно огляд мов програмування та порівняння ШІ.
В принципі, зі вступом закінчено, але ще один момент хочу зауважити. Я був трохи здивований тим, що Copilot впорався, як на мене, значно гірше, хоча запитання були одні і ті ж. Запитань було багато, і наводити повний лог запитань та відповідей не буду щоб не гаяти ваш час. В принципі, можете повторити мій досвід самостійно. А здивований я був тому, що я вже порівнював ці дві моделі в робочих питаннях — terraform/python і зазвичай Copilot давав кращі відповіді (Gemini навіть якось відмовляв мене від використання одного провайдера terraform на користь іншого, мовляв другий стабільніший і поширеніший :D). До речі, Gemini дає приблизно однакові відповіді на запитання англійською та українською, а ось Copilot краще розуміє англійську (навіть мою, хе-хе)
Я впевнений, що вчити щось краще на реальних задачах. І якщо вже щось вчити — то вчити щось корисне, що можна використовувати в своїй кожнодневній роботи, чи, хоча-б, у пет-проекті. Це було основне припущення.
Перше питання було — надати перелік функціональних мов програмування:
— Gemini: Haskell, Scala, Erlang/Elixir, F#, Clojure, OCaml, Lisp
— Copilot: Python, JavaScript, Scala, F#, Haskell, Erlang, Clojure
тут судіть самі. Як на мене, відповідь Gemini коректніша.
Наступне питання — охарактеризувати ці мови з точки зору складності вивчення, галузей застосування і чи можна створити бінарник, щоб просто використовувати його не маючи всієї інфраструктури для копміляції коду на цільовій машині.
Відповідь Gemini:
Мова Компіляція Сфери застосування Поріг входу Haskell Так Фінанси, аерокосмічна галузь, верифікація, компілятори Високий Scala Так (JVM) Веб-розробка, великі дані, фінанси Середній-високий Erlang/Elixir Так (BEAM) Телеком, месенджери, системи з високою паралельністю та відмовостійкістю Середній F# Так (.NET) Фінанси, веб-розробка, аналіз даних Середній Clojure Так (JVM) Веб-розробка, фінанси, обробка даних Середній OCaml Так Розробка компіляторів, системи верифікації, фінанси, академічні дослідження Середній-високий Lisp Так Штучний інтелект, автоматизація, аерокосмічна галузь, графіка, макроси та метапрограмування Середній
Щось мені підказує, що питання про компіляцію не зрозуміла жодна з моделей, хоча я перепитував кілька разів українською та англійською — обидві моделі надали відповідь, що «Так». Схоже що обидві моделі розуміють це питання як «чи принципово можливо отримати бінарнік». І зовсім не розуміють контексту — наскільки це вживано, просто і стабільно працює для будь-якого коду не відповідній мові.
В принципі, для перерахованих мов відповідь Copilot дуже схожа, додам тільки про Python та JavaScript (хоча далі їх розглядати не буду)
Мова Компіляція Сфери застосування Поріг входу Python Так Data science, web development, automation, finance. Низький JavaScript Так Web development, mobile app development, server-side scripting. Низький-середній
Наступне запитання було про те, з якої мови краще почати, якщо я хочу поглибити свої навички програмування саму у функціональному стилі.
Gemini рекомендує F# | Clojure
Copilot — Haskell | Clojure
Але-ж мене цікавлять суто практичні питання застосування, тому далі я питав про пошук роботи програмістом на ціх мовах. З розділенням по регіонах:
Всі моделі стверджують, що в Європі більш поширені Scala та Haskell, а в США — Clojure та Haskell. Copilot ще додав, що в Азії поширений F# - цікаво, чому?
А ось google trends показує, що найпоширеніші — Scala, Haskell, Elixir, F# (Саме в такому порядку)
Особисто для мене було найцікавіше наступне питання — про використання в тих задачах, з якими я більше всього працюю:
«Я працюю зазвичай з Linux та MacOS. Мої повсякденні задачі — це автоматизація системного адміністрування, DevOps та обробка даних, наприклад парсінг xml/json/yaml/csv або виводу консольних програм чи веб сторінок і видача оброблених даних в якомусь з перелічених форматів або запуск сторонніх програм за результатами отриманих даних»
Звісно, що обидві моделі написали мені, що Python — найкращій вибір для мене. Але ж то не цікаво, бо я і так його використовую, давайте щось нове :D
Gemini — Elixir | Haskell
Copilot — Clojure (і тут Остапа понесло — хоча я просив рекомендувати щось з вищеперерахованих, модель почала рекомендувати та описувати переваги Bash/Go/JavaScript)
Доречі, видавати щось, про що я не питав — прям фішка Copilot, інколи це гарно, а інколи — навпаки. В загальному випадку, краще-б не надавала зайвого шуму.
Ну і порівняння синтаксису, куди ж без цього:
Python:
def factorial(n): if n == 0: return 1 else: return n * factorial(n-1) print(factorial(5)) # Виведе 120
Haskell:
factorial :: Integer -> Integer factorial 0 = 1 factorial n = n * factorial (n - 1) main :: IO () main = print (factorial 5) -- Виведе 120
Scala:
object Factorial { def factorial(n: Int): Int = { if (n == 0) 1 else n * factorial(n - 1) } def main(args: Array[String]): Unit = { println(factorial(5)) // Виведе 120 } }
Erlang:
-module(factorial). -export([factorial/1, main/0]). factorial(0) -> 1; factorial(N) when N > 0 -> N * factorial(N - 1). main() -> io:format("~w~n", [factorial(5)]). % Виведе 120
Elixir:
defmodule Factorial do def factorial(0), do: 1 def factorial(n), do: n * factorial(n - 1) end IO.puts(Factorial.factorial(5)) # Виведе 120
F#:
let rec factorial n = match n with | 0 -> 1 | n -> n * factorial (n - 1) printfn "%i" (factorial 5) // Виведе 120
Clojure:
(defn factorial [n] (if (zero? n) 1 (* n (factorial (dec n))))) (println (factorial 5)) ; Виведе 120
OCaml:
let rec factorial n = if n = 0 then 1 else n * factorial (n - 1);; print_int (factorial 5);; (* Виведе 120 *) print_newline ();;
Lisp (Common Lisp):
(defun factorial (n) (if (zerop n) 1 (* n (factorial (- n 1))))) (print (factorial 5)) ; Виведе 120
Але подивившись на документацію всіх цих мов глибше, у мене склалося враження, що почати, якщо важливіше саме практика, краще зі Scala — а якщо на перше місце поставити теоретичні/академічні питання то Elixir | Haskell
Цікаво було-б почути рекомендації від людей з досвідом. Можливо вся ця інформація і ваші коментарі допоможуть комусь зробити вибір — з чого почати.
64 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів