Vara trecută, în timp ce mă relaxam pe plajele din Berck, un oraș francez cunoscut pentru tratarea tuberculozei la copii prin expunerea lor la aerul maritim proaspăt (în secolul al XIX-lea, au antibiotice în zilele noastre), m-am trezit visând cu ochii deschiși să-mi construiesc propriul limbaj de programare.
Alertă spoiler: nu știu cum să construiesc limbaje de programare, dar am dezvoltat opinii extrem de puternice de-a lungul anilor despre caracteristicile unui limbaj modern de știință a datelor ar trebui au. Deci, aș putea să le folosesc LLM-uri de lux pentru a construi unul?
De asemenea, să primim răspuns imediat la o întrebare: de ce să creăm o nouă limbă în loc să contribui la cele existente? Cu siguranță contribuiesc, mențin mai multe pachete R, cum ar fi {rix}, {rixpress}și {chronicler}și chiar au două pachete Python (cronista şi ryxpress), dar mi-am dorit un sistem curat pentru a construi un sistem centrat pe câteva principii și caracteristici nenegociabile pe care le-am implementat de-a lungul anilor în R:
- Reproductibilitatea-în primul rând: Un limbaj în care reproductibilitatea nu este o idee ulterioară gestionată de instrumente externe, ci chiar fundamentul timpului de execuție.
- Reutilizare agresivă: În loc să reinventeze roata, acest limbaj ar sta pe umerii giganților. Ar folosi Nix pentru managementul pachetelor și izolarea mediului și Apache Arrow ca coloană vertebrală de înaltă performanță pentru cadre de date. R, Python, Julia și alte limbi ar oferi algoritmii și modelele.
- Conducte de primă clasă: Scripturile nu ar trebui să fie o secvență de efecte secundare. În această limbă, conductele ar fi cetățeni obligatorii și de primă clasă.
- Eșuează devreme și tare: Fără conversii de tip silențios sau NA ascunse. Dacă ceva nu este în regulă, limbajul se întrerupe imediat, astfel încât să puteți repara.
- Erori ca obiecte: Inspirate de programarea funcțională, erorile sunt valori de primă clasă care pot fi inspectate și gestionate cu grație.
- Două țevi: Vreau două conducte, una pentru transformări liniare,
|>și o țeavă poate,?|>pentru recuperarea erorilor. Spre deosebire de conducta standard,?|>transmite întotdeauna valoarea acesteia, inclusiv Erori, la următoarea funcție, permițându-vă să scrieți handler-uri care le inspectează și pot recupera de la acestea. Deoarece Erorile sunt doar valori, aceasta se compune în mod natural cu restul limbajului. - Poliglot prin design: În loc să reimplementeze fiecare algoritm statistic, acest limbaj ar fi proiectat să orchestreze și să pună legătura între R, Python și Julia fără probleme.
De asemenea, suntem într-o lume post LLM și le place sau nu, sunt aici pentru a rămâne. Sunt destul de utile pentru a scrie cod standard și, prin urmare, orice limbă nouă ar fi moartă la sosire dacă nu s-ar juca bine cu LLM-urile. Așa că o astfel de limbă nouă ar trebui să fie scrisă în primul rând pentru LLM, pentru că nu mă aștept ca cineva să învețe vreo limbă nouă. Aici natura declarativă a lui Nix este un mare avantaj. Deoarece mediile sunt descrise cu precizie, este mult mai ușor pentru LLM să se concentreze pe generarea de cod și să nu fie nevoiți să lupte cu configurarea mediului. Acesta este și motivul pentru care am luat o altă decizie radicală: din moment ce Nix ar fi obligatoriu pentru configurarea mediului, de ce să vă deranjați să construim binare specifice sistemului de operare? Aș construi doar un pachet Nix pentru acest limbaj și l-aș lăsa pe Nix să se ocupe de restul.
Această arhitectură are ca rezultat un DSL pentru orchestrare, ceea ce face trivial transferul de obiecte de date între diferite ecosisteme fără frecarea obișnuită FFI (Foreign Function Interface).
Am început să cred cu adevărat că am ceva interesant, așa că am încercat și l-am sunat T. Glumisem de mult timp că succesorul natural al lui R ar trebui să fie numit T (pentru că R este succesorul lui S… și nu, nu o să-i spun Q pentru că sună ca cuvântul pentru fund în franceză).
Altceva care m-a făcut încrezător că aș putea reuși, pe lângă propria mea stăpânire, a fost că sunt destul de familiarizat cu testarea unitară, dezvoltarea bazată pe teste, dezvoltarea bazată pe trunk și Nix. Când combinați toate aceste elemente, dezvoltarea cu LLM-uri este destul de sigură.
Așa că tocmai am început să solicit. Și acum mă bucur să anunț că există o versiune beta a lui T pe care o puteți folosi astăzi!
Folosind Nix ca motor de compilare, T poate trata fluxurile de lucru complexe ale științei datelor ca derivări care se pot construi. O conductă T tipică arată astfel:
p = pipeline {
-- 1. Python node: read data with pandas
mtcars_pl = pyn(
command = <{
import pandas as pd
pd.read_csv("data/mtcars.csv", sep="|")
}>,
include = ("data/mtcars.csv"),
serializer = ^csv
)
-- 2. Python node: filter and serialize as CSV
mtcars_pl_am = pyn(
command = <{
mtcars_pl(mtcars_pl('am') == 1)
}>,
deserializer = ^csv,
serializer = ^csv
)
-- 3. R node: read CSV and take head using functions.R
mtcars_head = rn(
command = <{
my_head(mtcars_pl_am)
}>,
functions = ("src/functions.R"),
deserializer = ^csv,
serializer = ^csv
)
-- 4. R node: select column with dplyr
mtcars_mpg = rn(
command = <{
library(dplyr)
mtcars_head %>% select(mpg)
}>,
deserializer = ^csv,
serializer = ^csv
)
-- Render Quarto report
report = node(script = "src/report.qmd", runtime = Quarto)
}
-- Materialize the pipeline
populate_pipeline(p, build = true)
pipeline_copy() -- Copy the outputs from the Nix store to your working directory
După cum puteți vedea, fiecare nod are un command argument în care puteți scrie cod literal R sau Python. De asemenea, este posibil să furnizați calea către un script. Dacă pachetele trebuie încărcate pentru ca codul să funcționeze, puteți doar să scrieți apelurile pentru a încărca pachetele necesare în command argument la fel.
În timp ce T este puternic inspirat de {targets} pachet în R, duce conceptul cu un pas mai departe făcând conducte obiecte de primă clasă în cadrul limbii în sine. Aceasta înseamnă că puteți:
- Compuneți conducte: Puteți defini conducte mici, modulare și apoi le puteți îmbina în altele mai mari folosind operatori standard.
- Analiza Statica: Deoarece DAG (Graficul aciclic direcționat) este definit în limbaj, T vă poate valida întregul flux de lucru (verificarea dependențelor circulare sau datele lipsă) înainte ca o singură linie de cod să fie rulată.
- Execuție eterogenă: O singură conductă poate amesteca fără efort codul R, Python și T nativ. Datele sunt transmise între aceste noduri folosind serializatoare încorporate, cum ar fi
^csv,^arrowsau chiar formate specializate precum^pmmlpentru modele tradiţionale şi^onnxpentru arhitecturi de deep learning. De asemenea, este posibil să vă definiți propriile serializatoare. - Stare imuabilă: Fiecare ieșire de nod este gestionată de Nix, adică dacă nu ați modificat codul sau datele pentru un anumit nod, T (prin Nix) va extrage pur și simplu rezultatul stocat în cache de la rulările anterioare.
Dar nu lăsați eticheta „orchestrator” să vă păcălească; T este, de asemenea, o limbă capabilă în sine. Dispune de o selecție de pachete încorporate inspirate de tidyverse pentru manipularea datelor. Datorită backend-ului său Arrow, este surprinzător de rapid. Mențin chiar și un benchmark CI care rulează pe datele NYC Taxi pentru a mă asigura că performanța rămâne competitivă.
intent {
description: "Customer churn prediction",
assumptions: ("Age > 18", "NA imputed with multiple imputation"),
requires: ("dataset.csv")
}
Aceasta este panta?
Din experiență personală, când generez cod R sau Python, rezultatul seamănă foarte mult cu ceea ce aș fi scris eu. Principalul mod de defecțiune pe care l-am observat este lipsa de context: cu cât dați mai mult modelul, cu atât rezultatul este mai bun. Permiterea unor LLM-uri separate să examineze PR-urile și iterarea prin mai multe bucle vă ajută să înțelegeți ceea ce ratează orice model.
De asemenea, sunt încrezător în siguranța lui T dintr-un unghi diferit: în cele din urmă este orchestrarea codului Python și R pe care îl scrii singur și pe care îl poți testa independent.
Interesat?
Dacă sunteți interesat să îl încercați sau să contribuiți, consultați depozitul oficial sau site-ul web și nu ezitați să deschideți o problemă sau un PR sau contactați-mă pe canalul dedicat Matrix (https://matrix.to/#/#tproject:matrix.org).
Pentru cititorul interesat, iată cum să începeți cu T.
Cum să începeți
Dacă aveți Nix instalat, începerea cu un nou proiect este la o singură comandă distanță:
# 1. Initialize a new project nix run github:b-rodrigues/tlang -- init --project my_t_project cd my_t_project
Nu va exista altă modalitate de a începe un proiect T. După cum am explicat mai sus, nu vreau să am de-a face cu furnizarea de binare specifice sistemului de operare și, deoarece Nix este folosit de T ca motor de compilare, va trebui să aveți oricum Nix instalat pe sistem. Ar putea la fel de bine să-l reutilizați pentru a gestiona instalarea T în sine!
În folderul proiectului, veți găsi un tproject.toml fişier. Aici enumerați pachetele R și Python de care veți avea nevoie. De exemplu:
(project)
name = "r_py_xgboost_t"
description = "A T data analysis project"
(dependencies)
# T packages this project depends on
# Format: package = { git = "repository-url", tag = "version" }
# Example:
# stats = { git = "https://github.com/t-lang/stats", tag = "v0.5.0" }
(r-dependencies)
packages = ("dplyr", "yardstick")
(py-dependencies)
version = "python313"
packages = ("numpy", "pandas", "scikit-learn", "xgboost")
(additional-tools)
packages = ("quarto")
# Minimum T language version required
min_version = "0.51.2"
Sub „instrumente suplimentare” puteți adăuga orice pachet disponibil în nixpkgs. Dacă aveți nevoie de LaTeX, puteți adăuga și această secțiune dedicată:
\(\)
packages = ("amsmath", "geometry", "hyperref", "biblatex")
Poate ați observat că există și o secțiune pentru pachetele T; așa este, T acceptă pachete definite de utilizator. În loc să porniți un proiect, ați începe un pachet:
nix run github:b-rodrigues/tlang -- init --package my_package cd my_package
În loc de a tproject.toml fișier, va trebui să completați un DESCRIPTION.toml fişier:
(package)
name = "my_package"
version = "0.1.0"
description = "A brief description of what my_package does"
authors = ("brodriguesco")
license = "EUPL-1.2"
homepage = ""
repository = ""
(dependencies)
# T packages this package depends on
# Format: package = { git = "repository-url", tag = "version" }
# Minimum T language version required
min_version = "0.5.0"
Un alt fișier important este flake.nix care va fi generat automat. Nu ar trebui să-l atingi, dar asta flake.nix este ceea ce oferă mediul de dezvoltare reproductibil pentru rularea proiectului dumneavoastră. Pentru a face acest lucru, pur și simplu utilizați:
nix develop
Acest lucru va instala T și va activa mediul. Dacă ați adăugat lucruri la tproject.toml va trebui să fugi t update pentru a sincroniza pachetele cu flake și apoi reconstruiți mediul (va trebui să părăsiți mediul de dezvoltare cu exit și reconstruiește-l folosind nix develop din nou). A, și apropo, T necesită un mediu asemănător Linux, așa că dacă ești pe Windows, va trebui să rulezi T în WSL2 (Subsistem Windows pentru Linux).
Odată intrat în nix develop shell, tot ce aveți nevoie, interpretul T, versiunile dvs. specifice de R/Python și toate instrumentele de proiect sunt gata de utilizare. Nu trebuie să gestionați manual mediile virtuale sau containerele Docker; T se ocupă de ridicarea greutății prin Nix sub capotă.
Puteți căuta exemple în acest depozit.
Suport pentru instrumente și editor
O limbă este la fel de bună ca și experiența sa de dezvoltator. Am cerut politicos LLM-urilor să implementeze un server de limbă complet (LSP) pentru T, care oferă completare automată, diagnosticare în timp real și suport „Mergeți la definiție”.
- Pentru Cod VS / Pozitron: O extensie dedicată care oferă evidențierea sintaxei și integrarea LSP.
- Pentru Vim / Emacs: Sunt disponibile ghiduri de configurare detaliate și fișiere de sintaxă.
- Pentru Quarto: T este pe deplin compatibil cu Quarto pentru programare alfabetizată, permițându-vă să rulați executabil
{t}bucăți direct în documentele dvs.
Pentru instrucțiuni detaliate de configurare, consultați ghidul de asistență pentru editor din documentația oficială.
Sunt multe altele pe care nu le-am acoperit aici, așa că consultați depozitul oficial sau site-ul web.

