Nowoczesne języki w erze AI
Języki nowoczesne
Język nowoczesny odnosi się do języka, który oferuje wyższą produktywność, stabilność, bezpieczeństwo i łatwość utrzymania w porównaniu z językami przeszłości. Języki te aktywnie wprowadzają najnowsze techniki i koncepcje, zapewniając programistom bardziej wydajne i bezpieczne narzędzia programistyczne. Reprezentatywne języki nowoczesne obejmują Java, Rust, Python, TypeScript i charakteryzują się następującymi cechami.
1. Projektowanie obiektowe (OOP)
Większość języków nowoczesnych została zaprojektowana w oparciu o koncepcje obiektowe. Programowanie obiektowe wspiera zasady takie jak hermetyzacja, dziedziczenie i polimorfizm, a poprzez podział złożonych systemów na mniejsze, zarządzalne obiekty, sprawia, że struktura programu jest przejrzysta i elastyczna. Jest to szczególnie skuteczne w przypadku tworzenia oprogramowania na dużą skalę, pomagając kontrolować koszty rozwoju i nakład pracy, a także redukować problemy, które mogą wystąpić podczas konserwacji.
2. "Cukier składniowy" i wyrażenia
Języki nowoczesne oferują różnorodne "cukry składniowe" i składnie oparte na wyrażeniach, aby poprawić czytelność kodu i produktywność programowania. Funkcje takie jak operator trójargumentowy, wyrażenia lambda i dopasowywanie wzorców redukują kod boilerplate, sprawiają, że kod jest bardziej przewidywalny i zwiększają produktywność programistów.
3. System modułów
Języki nowoczesne umożliwiają zarządzanie programami poprzez dzielenie ich na wiele jednostek za pomocą systemu modułów. Ułatwia to ponowne wykorzystanie kodu i zarządzanie zależnościami, co ułatwia konserwację nawet w przypadku wzrostu skali projektu. Typowe przykłady to Maven/Gradle dla Javy, Cargo dla Rusta i npm/yarn dla TypeScript.
4. Język pośredni i maszyna wirtualna
Języki nowoczesne wprowadzają języki pośrednie i maszyny wirtualne w celu zapewnienia niezależności od platformy, optymalizacji wydajności i bezpieczeństwa. Reprezentatywne przykłady to JVM, LLVM, WASM i GraalVM.
Rozwój w erze AI i ograniczenia języków nowoczesnych
Języki nowoczesne powstały z założeniem, że większość kodu jest pisana przez ludzi. Naturalnie, celem języków nowoczesnych jest redukcja powtarzalnych zadań, zwiększenie produktywności i efektywne wdrażanie dużego oprogramowania poprzez struktury umożliwiające współpracę programistów. Jednak w erze AI to założenie jest coraz bardziej podważane. Narzędzia oparte na AI, takie jak Copilot i Cody, automatyzują wiele aspektów pisania kodu, a ilość kodu, którą jeden programista może wyprodukować, gwałtownie wzrasta. W rezultacie cechy języków nowoczesnych, które w przeszłości były postrzegane jako zalety, stopniowo stają się przestarzałymi wadami.
Projektowanie obiektowe
AI może szybko i dokładnie analizować struktury, w których wszystkie informacje są jawnie określone w jednej funkcji lub module. Natomiast wraz ze wzrostem kontekstu, zwiększa się zakres wnioskowania, co obniża produktywność i dokładność AI. Kod napisany w OOP rozprasza logikę między wiele obiektów, zamiast zarządzać nią w jednym miejscu, co w konsekwencji wymaga od AI większego kontekstu. Rozważmy poniższy kod.
1public class AnimalHandler {
2 public void handle(Animal animal) {
3 animal.speak();
4 }
5}
6
7public class Main {
8 public static void main(String[] args) {
9 AnimalHandler handler = new AnimalHandler();
10
11 Animal a1 = new Dog();
12 Animal a2 = new Cat();
13 Animal a3 = new Horse();
14
15 handler.handle(a1);
16 handler.handle(a2);
17 handler.handle(a3);
18 }
19}
W powyższym kodzie, aby AI mogła dowiedzieć się, co faktycznie robi metoda speak(), musi powtórzyć następujące wnioskowania:
- Jakiej konkretnej klasy instancją jest animal?
- Gdzie jest zdefiniowana metoda speak() nadpisana w tej klasie?
- Gdzie znajdują się definicje klas Dog i Cat i jakie są ich wewnętrzne działania?
- Czy istnieje możliwość, że klasy Dog i Cat zostaną nadpisane w innych klasach?
Informacje te nie są zgromadzone w jednym pliku ani w jednej funkcji, lecz można je zrozumieć jedynie poprzez śledzenie relacji między plikami klas i struktur dziedziczenia. Co więcej, elementy decydowane w czasie wykonania, takie jak refleksja lub dynamiczne ładowanie, są dla AI niczym czarna skrzynka, co czyni analizę praktycznie niemożliwą.
"Cukier składniowy" i wyrażenia
AI preferuje jawne działania niż niejawne, i zamiast używać złożonych struktur, woli łączyć proste struktury, aby stworzyć jedną poprawną odpowiedź. Natomiast "cukier składniowy" pozwala na różnorodne wyrażenia, podczas gdy ich wewnętrzne działanie jest często takie samo lub podobne. AI musi uczyć się znaczenia tych różnorodnych wyrażeń jeden po drugim i może mieć trudności z oceną priorytetów, aby polecić odpowiednią składnię w określonej sytuacji.
Język pośredni i maszyna wirtualna
AI uczy się głównie na podstawie kodu źródłowego. Natomiast język pośredni (bytecode) usuwa znaczenie, takie jak nazwy zmiennych, podczas procesu kompilacji, a maszyna wirtualna musi go ponownie interpretować w czasie wykonania. Jest to bardzo trudne zadanie do zrozumienia lub przekształcenia przez AI. Na przykład, konwersja z TypeScript do Go jest możliwa dla AI, ale konwersja kodu bajtowego silnika V8 na kod bajtowy JVM lub kod maszynowy jest praktycznie niemożliwa.
Prawdziwy język nowoczesny w erze AI
Z powyższego wynika, że cechy języków nowoczesnych są w rzeczywistości przestarzałymi elementami, które nie są odpowiednie dla ery AI. Jaki więc język mógłby być najbardziej odpowiednim językiem nowoczesnym w erze AI? Wskazówki można znaleźć w elementach, które języki nowoczesne w przeszłości odrzucały. Język nowoczesny w erze AI powinien:
- Posiadać jawną składnię i naturalny przepływ.
- Wyjść poza nadmierne struktury OOP i mieć płaską i prostą strukturę.
- Zamiast zbędnego "cukru składniowego" lub niejawnych wzorców, tworzyć wiele funkcji za pomocą ograniczonej liczby podstawowych słów kluczowych.
- Posiadać prosty i przewidywalny system budowania, a nie złożony.
Językiem, który najlepiej spełnia te kryteria, jest Golang. Język Go został zaprojektowany tak, aby można było zaimplementować większość praktycznych funkcji za pomocą minimalnej liczby kluczowych słów i prostej kombinacji składni, a także konsekwentnie wyklucza niepotrzebne abstrakcje i niejawne działania. Jest to struktura korzystna nie tylko dla programistów, ale także dla AI w interpretowaniu i generowaniu kodu.
W ten sposób, przewidywalna i płaska struktura, jawny przepływ i spójna składnia Go, w przeciwieństwie do istniejących języków nowoczesnych zaprojektowanych z myślą o programistach-ludziach, lepiej pasuje do środowiska programistycznego, w którym AI aktywnie uczestniczy. Konserwatywna filozofia projektowania Go, która kiedyś była uważana za przestarzałą, staje się w erze AI najbardziej zaawansowanym wyborem.