Ez a bejegyzés eredetileg David weboldalán jelent meg, és itt engedéllyel újraközöljük
Tavaly januárban az Exercism bejelentette a 12in23 nevű új programot, amelyben arra biztatta a résztvevőket, hogy 2023-ban próbáljanak ki 12 új programozási nyelvet. Minden hónapnak volt egy témája (például „Analitikus április" vagy „Objektumorientált október"), és kiemelt bizonyos nyelveket, amelyeket érdemes kipróbálni. Szeretek új dolgokat tanulni, és kicsit nyelvmániás lettem, úgyhogy úgy döntöttem, belevágok. 12 nyelv, 12 hónap!
Most, hogy az év majdnem véget ért, hihetetlenül örülök, hogyan sikerült a projekt. Sikeresen kipróbáltam 12 új nyelvet, remek emberekkel találkoztam az Exercism közösségében, és útközben néhány menő nyílt forráskódú hozzájárulást is sikerült leadnom! Ebben a bejegyzésben végigmegyek mindegyiken, és elmondom, mit kaptam tőlük.
Nyelvek kiválasztása
Kijelöltem néhány irányelvet az évre, hogy a legtöbbet hozzam ki az élményből:
- A nyelvek vagy teljesen újak legyenek számomra, vagy legalább annyira ismeretlenek, hogy érezzem, sokat tanulok.
- A kiválasztott nyelvek (potenciálisan) hasznosak legyenek, hogy a jövőben többet tanulhassak belőlük. Ez a projekt csak szórakozásból indult, de szeretném (legalább részben) hasznos dolgokra fordítani az időmet.
- Minden használt nyelvhez telepítettem az összes helyi toolingot és a VSCode-bővítményt. Körülbelül egyenlő feltételekkel akartam összehasonlítani a nyelveket, a lehető legtöbb típusjelzéssel és intellisense-szel. Az egyetemen minden programozási házimat Sublime Textben írtam meg, mindenféle lintelés és automatikus kiegészítés nélkül. Féltem, hogy ha az összes ilyen eszköz használata mellett tanulok meg programozni, túlságosan rájuk támaszkodom majd, és nem leszek jó programozó. Végül pont az ellenkezője történt. Minél több gondolkodást tudok az eszközeimre bízni, annál inkább a tényleges problémára tudok összpontosítani. Ne jegyezz meg dolgokat, jegyezd meg, hogyan találhatod meg őket.
Kezdjük is!

Január (téma nélkül)
Amikor január elkezdődött, az Exercism csapata még épp a havi témákat választotta, így abban a hónapban mindenki szabadon dönthetett a nyelvről. Mivel nem volt irány, a Go nyelvvel indítottam az évet. 2022 közepén elvégeztem egy gyorstalpalót a nyelvből, de azóta nem sokat használtam, és egyáltalán nem éreztem magam jártasnak benne.
A Go érdekes nyelv. A szigorú fordítója miatt a programod biztos, hogy helyes lesz, és egy tapodtat sem mozdulsz, amíg a fordító úgy nem gondolja, hogy biztonságban vagy.1 A hibakezelés bőbeszédű megközelítése miatt soha nem ér meglepetés (azon az áron, hogy if err != nil { return err }-t írsz le olyan sokszor). Jól csinálja, hogy a nehéz dolgokat könnyűvé teszi (például a csatornákon keresztüli párhuzamosságot), de néhány könnyű dolgot is megnehezít (a stringek kezelését). Robusztus szabványos könyvtára van, így a legtöbb feladatot harmadik féltől származó modulok nélkül is meg tudod oldani. Tetszik, hogy az ökoszisztéma nagy része (formázás, telepítés, buildelés stb.) első kézből származik, és be van építve a go parancsba. A nyelvnek megvannak a bírálói, de szerintem nagyrészt eléri a céljait: a helyességet és a karbantarthatóságot.
Nem élveztem annyira a használatát, hogy első választásként nyúljak hozzá, de nagyszerű eszköz a tarsolyomban a teljesítményérzékeny programokhoz, például ahhoz, hogy a beágyazott útvonalat mutassam a shellpromptomban.
Funkcionális február

A február rögtön a mélyvízbe ugrott a funkcionális nyelvekkel, amelyek a gyakoribb imperatív programozási nyelvek matematikásabb mellékágai. A funkcionális nyelveket a „tiszta" függvényeikről ismerik (amelyeknek nincs mellékhatásuk). Az Elixir mellett döntöttem, főleg azért, mert a barátom, Caleb használta az Advent of Code-hoz, és áradozik róla.
Egészen élveztem az Elixirrel töltött időt. A Ruby ihlette (ami érthető; a megalkotója, José Valim a Rails egyik fő közreműködője volt). Egyszerűnek találtam funkcionális fogalmak, például a metódusláncolás kifejezését. Imádtam az összes szintaktikai cukorkát, ami ezt könnyűvé tette, például a pipe operátort (|>):
foo(bar(baz(new_function(other_function()))))
# becomes
other_function() |> new_function() |> baz() |> bar() |> foo()
Ez volt az első alkalmam makrókkal, azaz kódot író kóddal dolgozni. Mivel az Elixir-programok olyan AST-ként fejezhetők ki, amely maga is érvényes Elixir-kód, könnyű olyan kódot írni, amely más érvényes kódot állít elő. Ez egy igazán menő fogalom, amit az Elixir könnyűvé tett. Az is tetszett, ahogy a függvények mintaillesztést végezhettek az argumentumaik alakjára, így a függvényhívások a megfelelő implementációhoz irányíthatók:
defmodule TuplePrinter do
def print({a}) do
IO.puts("single")
IO.puts(a)
end
def print({a, b}) do
IO.puts("double")
IO.puts(a)
IO.puts(b)
end
end
TuplePrinter.print({1})
TuplePrinter.print({2, 2})
# single
# 1
# double
# 2
# 2
Ez olyan funkciónak tűnik, ami vagy nagyszerű, vagy totális spagettivé teszi a kódodat. Mindegy, menő fogalom volt!
Az Elixirnek az is előnye, hogy az Erlang BEAM virtuális gépében fut, ami nagy ökoszisztémát ad neki, amivel kommunikálhat. Nagyszerű a párhuzamosságban, és a szeretett Phoenix keretrendszer magja.
Bár nincs azonnali szükségem az Elixirre, nagyon szórakoztatónak találtam vele dolgozni, és mindenképp szívesen visszatérnék hozzá. Ráadásul érdekes kihívás volt az ismerős problémákat ismeretlen módon megoldani (nevezetesen rekurzívan).
Mechanikus március
A március a „rendszer" nyelvekre összpontosított, amelyek gépi kódra fordulnak le.
A lehetőségek közül a Go volt az egyetlen nyelv, ami érdekelt.2 A figyelmes olvasók most észrevehetik, hogy már letudtam egy hónapot a Góval, így az ismétlés nem számítana bele a 12-be. Nos, amikor januárra választottam, még nem jelentették be a témákat, így nem vettem észre, hogy saját magamnak ások gödröt.
Ha tudtam volna, hogy jön a Bun, valószínűleg a Zig-et próbáltam volna ki, de sajnos (még) nem láttam a jövőbe. Így, mivel nem volt meggyőzőbb választás, egy plusz hónap Go mellett döntöttem, azzal a tudattal, hogy az év későbbi szakaszában pótolnom kell egy nyelvet.
Analitikus április
Az április teljes egészében az adattudományban népszerű nyelvekről szólt. A Pythont túl jól ismertem, az R-rel pedig az egyetemen találkoztam egy statisztikaórán (és nem jött be), így a Julia mellett döntöttem!
Élveztem vele az időt, de főleg azért, mert annyira hasonlónak éreztem a Pythonhoz. Kicsit nyugtalanító volt, mint amerikainak lenni Kanadában. Minden nagyon ismerősnek tűnik, de csak kicsit más, olyan módon, amit nehéz megfogni. Aztán hirtelen felajánlanak egy kétdolláros érmét (vagy egy függvényt, ami tényleg nagyon jól áll a mátrixmatematikához), és rájössz, hogy már nem Kansasban vagy.
Ami a legjobban megragadta a figyelmemet, az a Julia típusrendszere volt. (Opcionálisan) annotálható volt, mint a Python típusrendszere, de futásidejű ellenőrzésekkel biztosította, hogy az argumentumok megfeleljenek a deklarált típusaiknak. Szerintem a Python rendszere megtalálja a helyes egyensúlyt aközött, hogy illeszkedik az eszközökhöz, és hogy nem áll az utadba, de elismerem, hogy a Julia futásidejű hibái a rosszul típusozott függvényekhez szintén hasznosak voltak.
Végül is a Julia remek volt, de nem számítok rá, hogy a jövőben szükségem lesz rá.
Gondolkodásváltó május
A május még inkább ráerősített a „próbálj ki valami újat" jelszóra azzal, hogy nagyon szokatlan dolgokat művelő nyelveket emelt ki. Kihasználtam az alkalmat, hogy kipróbáljam a rendkívül népszerű Rust-ot. Meg kell mondjam, értem, miért van ekkora felhajtás körülötte.
Bár a hírhedt borrow checker bizony megkívánja, hogy megszokd, tetszett, ahogy arra késztetett, hogy alaposabban gondolkodjak a programjaimról. A fordító bizony szigorú volt, de a hibaüzenetek minden várakozást felülmúltak abban, hogy segítettek kijavítani a problémákat. Nem mondom, hogy különösebben produktív voltam az első héten, de úgy érzem, legalább a tanulási görbe tetejét látom.
A cargo, a Rust csomagkezelője, szintén külön említést érdemel. Bár semmilyen harmadik féltől származó csomagot nem telepítettem, a build-, a teszt- és a formázásfunkciói nagyszerűek voltak. Ugyanez igaz a VSCode-bővítményére, amely mindazt a kényelmet nyújtotta, amit egy Rusthoz hasonló statikusan típusos nyelvtől elvárnék. A jó fejlesztői élmény tényleg mindent megváltoztat.
Bár implementációs szinten nagyon különböznek, a Rust hasonlónak tűnt a Go-hoz abban, amire használnám őket: hogy a programok nagyon gyorsan fussanak. Az általam rendszeresen használt nyelvek számos eszköze kezd a Rust felé fordulni a teljesítményjellemzői miatt, így arra számítok, hogy a jövőben többet látok majd belőle (még ha nem is én írom a Rust-ot).
Az S-kifejezések nyara (június)
A június az S-kifejezések hónapja volt, ami a lisp nyelvek gyakori szintaktikai formája. A Clojure mellett döntöttem, ami egy funkcionális nyelv, amely a JVM-ben fut.
Sok évvel ezelőtt írtam egy kis Clojure-kódot. Frissen végeztem az iskolával, és az első munkahelyemen egy üzletileg kritikus napi szkript egyedüli karbantartója lettem. Mondanom sem kell, trükkös időszak volt. Kíváncsi voltam, hogy most, hogy idősebb és bölcsebb lettem, barátságosabb-e.
Örömmel jelentem, hogy igen! A februári funkcionális tapasztalat segített rekurzívan gondolkodni, és a szintaxis sem volt olyan rossz, ha beleástad magad. A JVM-mel való együttműködése is hasznos lenne, ha egy nagyobb projektben használnám.
Nem látom magam előtt, hogy bármikor Clojure-t használnék, ha vannak alternatívák, de nem is volt teljesen kellemetlen élmény.
Mellékküldetés: az Universal Test Runner!
Évek óta egy kis bash-függvényt használok az aktuális könyvtáramban lévő egységtesztek futtatására. Ahogy ezekben az új nyelvekben dolgoztam, azon kaptam magam, hogy kényelemből sorokat adok hozzá; könnyebb volt megjegyezni, hogy t-t futtassak, mint újra és újra megtanulni a nyelvspecifikus tesztparancsot.
Ahogy a szükséges logika kinőtte a bash-hez fűződő komfortérzetemet, szakítottam rá időt júniusban, és önálló projektté alakítottam: a Universal Test Runner.
Megosztottam az Exercism fórumán, és szép fogadtatást kapott. Annyira megtetszett nekik, hogy úgy döntöttünk, hasonló funkciót építünk magába az Exercism CLI-be (ami Go-ban íródott, pont abban a témában, amit szerencsés módon épp felfrissítettem). Így az év második felében exercism test-et futtathattam, hogy lefuttassam az adott havi nyelv tesztegyüttesét (egy parancs, amit a Universal Test Runner natívan támogat).
Ha szeretnél többet megtudni a folyamatról, sokkal részletesebben írtam róla a megjelenésekor.
Na de haladjunk tovább!
Jura július
A július a régi nyelveket mutatta be. Gyakorlati szempontból elég szűk volt a választék ebben a hónapban. A tiszteletreméltó COBOL-lal kezdtem, mivel hallottam, hogy még mindig sok kritikus infrastruktúrát működtet. De mivel augusztus elején esküvő közeledett, nem volt kapacitásom leülni és megtanulni egy számomra ennyire más nyelvet. Így inkább a Visual Basic-re váltottam, mint a legkevésbé rossznak tűnő lehetőségre.
Nincs sok mondanivaló erről. A nyelv kicsit bőbeszédűnek tűnt, de elég könnyen használhatónak. Úgy tudom, valójában Windowsos felhasználóifelület-fejlesztéshez tervezték, így a kis feladatok miatt nehéz átfogó képet kapni róla.
Appos augusztus
Az augusztus tele volt az appokat építő nyelvekkel. Nem meglepő módon sok választási lehetőség volt ebben a hónapban. A Swift mellett döntöttem. Mivel sok Apple-terméket használok, a saját fejlesztésű nyelvük meglehetősen releváns számomra. Nem volt teljesen új számomra: 2016-ban kiadtam egyetlen iOS-appot, amely teljesen Swiftben íródott. De azóta nem nyúltam a nyelvhez, és sokat fejlődött, így úgy gondoltam, még mindig számít.
Kellemesen meglepett, milyen könnyű volt vele dolgozni. Ellentétben sok más, itt szereplő nyelvvel, a Swift meglehetősen új. 2014-ben jelent meg először, és láthatóan sokat profitált a modern nyelvtervezés tanulságaiból. Van első kézből származó csomagkezelője, opcionális láncolása, első osztályú függvényei és józan string-interpolációja. Ergonómikusnak érződött olvasni és írni benne, még Xcode nélkül is.
Mindezek ellenére a Swift leginkább az Apple-platformokra írt appok kontextusában hasznos, amilyeneket jelenleg nem írok. Bár jól működött a feladatokhoz, nem számítok rá, hogy a közeljövőben visszatérek hozzá. Viszont imádom, hogy az iPademen is írhatom!
Karcsú szeptember
A szeptember a nagyon tömör vagy kicsi nyelveket járta körül. A jq mellett döntöttem, egy eszköz, amit évek óta használok és szeretek.
Mindig is csak egy JSON-nal való munkához használatos eszköznek tartottam, nem általános célú programozási nyelvnek. Kellemesen meglepett, hogy megvannak benne a szokásos kellékek (függvények, változók, ciklusok stb.), így elég összetett programokat is írhattam:
# input: { "series": "1", "sliceLength": 1 }
. as {series: $series, sliceLength: $sliceLength} |
if
$series == "" then
"series cannot be empty" | halt_error
elif $sliceLength > ($series | length) then
"slice length cannot be greater than series length" | halt_error
elif $sliceLength == 0 then
"slice length cannot be zero" | halt_error
elif $sliceLength < 0 then
"slice length cannot be negative" | halt_error
else
.
end
| [range(0; $series | length)]
| map($series[. : . + $sliceLength])
| map(select(. | length == $sliceLength))
Jó móka volt kipróbálni a jq összes olyan funkcióját, amire egyszerű adatátalakításokhoz soha nem volt szükségem. Bár a tooling itt némileg hiányos volt (nincs szerkesztőintegráció stb.), értékes volt mélyebben megérteni a jq funkcionalitásának szélességét.
szerkesztés: DJ Adams a Mastodonon felhívta a figyelmemet a jq-lsp projektre és a hozzá tartozó VSCode-bővítményre. Ezúttal lecsúsztam róla, de a jövőben megnézem.
Objektumorientált október
Az október az objektumorientált nyelvekbe mélyedt el. Gyengéje vagyok az objektumorientált terveknek, amelyek szorosan tükrözik, ahogy a programokat a fejemben elképzelem. A Ruby mellett döntöttem, ami furcsa választásnak tűnhet.
A Stripe-nál dolgozom, ami a világ legnagyobb Ruby-kódbázisának ad otthont. Biztosan nem számítana „ismeretlen" nyelvnek? Bár mindez igaz, a Ruby-monolitunk nagyon távol áll a „standard" Ruby-tól: mindent a Sorbet-tel típusellenőrzünk, rengeteg a kódgenerálás, és sok varázslatot vetünk be, hogy minden együtt működjön és skálázódjon. Bár a Ruby a Stripe-on belül és kívül végső soron ugyanaz a nyelv, az ilyen különböző léptékben való munka egészen más tapasztalatokat nyújt; kíváncsi voltam, milyen az élet odakint (azóta, hogy intenzíven használtam a Rubyt).
Nagyrészt jó volt! Maga a Ruby nagyszerű, és a „programozói boldogságot" jelöli meg fő céljaként, ami együtt rezonált velem. Tetszik, hogy milyen gyakran kitalálom a soha nem használt stdlib-függvények nevét. Tetszik, milyen könnyű funkcionális kódot építeni, és mennyire ergonomikus és kifejező a szintaxis.
Mindezek ellenére meglepett, mennyire le van maradva a fejlesztői tooling a Python mögött. Lehet, hogy el vagyok kényeztetve, de a szerkesztőn belüli típusjelzések, valamint a rendkívül gyors lintelés és formázás fontosabb számomra, mint gondoltam. Egy olyan népszerű nyelv esetében, mint amilyen a Ruby volt a csúcsán, meglepett, mennyire le volt maradva ezen a téren.3 Sosem szoktam meg igazán a függvényhívások opcionális zárójelét, ami miatt a függvények argumentumként való átadása kevésbé volt egyszerű.
A Ruby még mindig nagyszerű nyelv, és a munkámban továbbra is használni fogom, de semmit sem tesz értem, amit a Python ne tenne, legalábbis most.
Nibble november
A november volt eddig a legnehezebb hónap: az assembly-nyelvek. Bár ma már nem gyakori, hogy kézzel írjunk ilyet, hasznos és érdekes téma, amivel érdemes tisztában lenni. A WebAssembly-t választottam, mert fontos a modern és a jövőbeli web számára. Bár jellemzően fordítési célként használják (és nem olyasmi, amit kézzel írnak), létezik tooling a megszállottak számára is.
Váratlanul jól felkészültnek éreztem magam erre a hónapra. A szintaxis a Clojure-ra hasonlított, a nyelv szerkezete pedig a Zachtronics TIS-100-ra. Furcsán élveztem, hogy minden művelethez a nulláról kellett kezdenem; bájosnak éreztem. Utálnám, ha ténylegesen így kellene bármit is elvégeznem, de addig is szórakoztató kuriózum volt. Bőkezű kommentekkel majdnem olvasható kódot sikerült írnom:
(module
(func (export "eggCount") (param $number i32) (result i32)
(local $res i32) ;; result
(local $remainder i32) ;; loop counter
(loop $loop
;; $res =
(local.set $res
;; $res +
(i32.add
(local.get $res)
;; $number % 2
(i32.rem_u
(local.get $number)
(i32.const 2)
)
)
)
;; $number //= 2
;; (keep on stack)
(local.tee $number
(i32.div_u
(local.get $number)
(i32.const 2)
)
)
;; this will keep looping until remainder is 0
br_if $loop
)
local.get $res
)
)
A legnagyobb akadály a dokumentáció és az erőforrások hiánya volt. Még azt is nehéz volt megállapítani, milyen globális függvények érhetők el. De mivel valójában nem fogom használni, amint beindult, ez már nem zavart túlságosan.
A december zárta az évet azokkal a nyelvekkel, amelyek nem fértek bele más kategóriákba. Mivel márciusban duplán kellett nyelvet választanom, ebben a hónapban két nyelvet kellett teljesítenem.
A Wren-nel kezdtem. A szerzője Bob Nystrom, aki többek között a Crafting Interpreters hírnevét szerezte. Elbűvölt a részletekre való figyelme, a kis lábnyoma és a felülről lefelé tervezés; minden nagyon átgondoltnak tűnik. Ez a gondosság a változók scope-jának és a láthatósági szabályoknak a részleteiben is megmutatkozik. A fordítója kicsi és alaposan tele van kommentelve, így remek tanulási forrás, ha érdekelnek a nyelvi implementációk.
A Wren kicsit nyers a szélein, és úgy tűnik, nagyrészt elhagyták, de szerintem ez rendben van egy játéknyelvnél. Senki sem azzal a várakozással áll neki, hogy éles használatra kész. Biztosan van hely a világban a nem éles használatra szánt nyelveknek is.
És még: Lua
A második választásom ebben a hónapban a Lua volt. A Wrennel ellentétben hihetetlenül praktikus. Könnyű beágyazhatósága miatt sok helyen felbukkan, például a Redis-szkriptelésben és a Factorio-modokban. Az objektummodell megszokása kicsit igénybe vett, de látom, hogyan lennék gyorsan produktív. Gyorsan megbarátkoztam a táblákkal mint mindent vivő szerkezettel. A tooling jó volt: a csomagkezelő azonnal működött, a VSCode-bővítmény pedig gond nélkül támogatta a kommentalapú típusannotációkat.
Bár nincs semmi, amihez azonnal szükségem lenne a Luára, széles körű használata miatt egy újabb nagyszerű eszköz a tarsolyban.
Összegzés

Jobban élveztem ezt a nyelvi körutazást, mint vártam. Nemcsak néhány új gyakorlati készséget sajátítottam el, de a látóköröm is alaposan kitágult.
Ami a következőket illeti, azt hiszem, sokkal több Rust lesz. Fontossága a fejlesztői tooling világában mára nyilvánvaló, és szeretnék biztos lenni benne, hogy el tudom olvasni és tudok hozzájárulni azokhoz a dolgokhoz, amelyekre támaszkodom.
Nincs konkrét leszállítandó eredmény a fejemben, de ott van a teljes Rust-könyv, amit el kell olvasnom, egy Rust JS-fejlesztőknek szóló kurzus, amit egy évvel ezelőtt elszámoltattam, és egy teljes Exercism-kurzus, amit be kell fejeznem. Szeretnék legalább egy nyílt forráskódú projekthez hozzájárulni (valószínűleg a Just-hoz, az egyik új kedvenc programomhoz), de majd meglátjuk, hova visz az év.
Addig is boldog ünnepeket, és kívánom, hogy szép legyen a 2023-as év hátralévő része!
-
A nem használt változók fordítói hiba?? Na, azért mégis ↩
-
Valójában először a C++-szal próbálkoztam (amit az egyetem óta nem írtam). Egyszerűen nem volt szórakoztató, úgyhogy elhagytam ↩
-
Ez egy másik módja annak, ahogy a „valódi" Ruby eltér a Stripe-on belüli tapasztalataimtól, így örülök, hogy mindkét módon kipróbálhattam ↩