Het artikel onderzoekt de claim dat dynamische en beknopte programmeertalen efficiënter zijn voor LLM's vanwege lagere tokenkosten. Hoewel dit waar is bij triviale taken, verdwijnt dit voordeel bij complexe opdrachten zoals het implementeren van een Zstd-decoder of Pandoc.
De belangrijkste bevindingen zijn:
- Populariteit versus Efficiëntie: Er is een positieve correlatie tussen de populariteit van een taal en de correctheid van de gegenereerde code, waarschijnlijk door de hoeveelheid trainingsdata.
- Complexiteit en Ambiguïteit: Bij zeer complexe taken of ambigue specificaties (zoals business logic in bordspellen) presteren alle talen slecht; het probleem ligt dan bij de interpretatie van de LLM, niet bij de taal zelf.
- Strategieën: Eén poging met 'ultra effort' is vaak kosteneffectiever dan een feedbackloop van medium-effort pogingen.
- Geheugenveiligheid: AI-gegenereerde code in C en C++ vertoont veel geheugenproblemen, terwijl Rust hier een voordeel biedt.
De auteur concludeert dat het voor LLM-gebruikers veiliger is om bij mainstream talen te blijven dan over te stappen op obscure, compacte talen.
Wat is de beste programmeertaal voor coding agents?
Dynamisch getypeerde talen hebben over het algemeen lagere LLM-tokenkosten dan traditionele statisch getypeerde talen, omdat het weglaten van expliciete typeverklaringen de code compacter maakt.
De bron hiervan suggereert dat sommige beknopte dynamische talen wellicht 1/2 tot 1/3 van de tokenkosten hebben van statische talen zoals Rust, Go en C++. De auteur stelt dat er een aanzienlijk gat was van 2,6x tussen C (de minst efficiënte taal) en Clojure (de meest efficiënte). Daarnaast wordt J genoemd als een extreme uitschieter met gemiddeld slechts 70 tokens, bijna de helft van Clojure (109 tokens). Array-talen kunnen extreem token-efficiënt zijn wanneer ze exotische symbolensets vermijden.
Het probleem met triviale evaluaties
Zonder eigen tests uit te voeren, valt op dat het eerste experiment gebruikmaakt van triviale problemen; een probleem dat in 70 tokens in J of 109 in Clojure kan worden opgelost, is simpelweg geen complex probleem (de auteur gebruikte Rosetta Code). Resultaten van triviale taken — waarbij het meeste werk bestaat uit het printen van een antwoord — generaliseren niet naar taken die echt "echt werk" vereisen. De grote winst die wordt geclaimd bij eenvoudige taken verdwijnt zodra men kijkt naar problemen die meer dan een paar tokens kosten.
Ook in andere evaluaties zijn subtielere problemen te vinden. Zo voerde een test het verkeerde pad uit (dat niet bestond), waardoor een test faalde. Een latere agent maakte vervolgens een symlink van dat niet-bestaande pad naar zijn eigen executable. Dit werkte voor die specifieke case, maar zorgde ervoor dat elke volgende test de executable van die ene agent uitvoerde in plaats van de juiste executable van de taal die getest werd. De conclusie dat Rust vaker faalde was dus onjuist; het betekende simpelweg dat de scoring voor Rust plaatsvond voordat de Go-agent alle scores op die defecte test had omgeleid naar de Go-executable.
Eigen evaluaties: Zstd
Om een eigen intuïtie op te bouwen, zijn er tests uitgevoerd met pre-geregistreerde voorspellingen:
- Hoge betrouwbaarheid (95%): De algemene claim over dynamische vs. statische talen zal niet standhouden bij complexere problemen.
- Lage betrouwbaarheid (60%): Statische talen zullen iets beter presteren dan dynamische talen bij "ultra effort" (maximale inzet).
- Hoge betrouwbaarheid (98%): De suprematie van "vreemde" talen zoals J zal niet standhouden, mede omdat AI-labs waarschijnlijk minder synthetische RL-data voor obscure talen hebben.
Voor de eerste evaluatie kregen agents de Zstd RFC (plus errata) en de opdracht een complete Zstd-decoder te implementeren in een container zonder internettoegang. De tests werden niet aan de agents gegeven.
Bij een "medium effort" niveau lijken dynamische talen efficiënter en beter, wat overeenkomt met eerdere claims. Echter, bij "ultra effort" zijn de resultaten gemengd: enkele statische talen presteren hier het best. Er is geen dominantie van één taaltype.
Wat opvalt is dat extreme ratio's uit triviale tests verdwijnen bij grotere taken. Alleen bij assembly (wat voor mensen ook veel tijdrovender is) of zeer obscure talen blijft de performance laag. Dit spreekt de theorie tegen dat zeer compacte talen zoals J logisch zijn vanuit efficiëntie-overwegingen. Voor een normale LLM-gebruiker lijkt het veiliger om bij mainstream talen te blijven dan over te stappen op obscure, compacte talen. Er is een zwakke tot matige positieve correlatie tussen de populariteit van een taal en de prestaties: populairdere talen resulteren vaker in correctere en goedkopere oplossingen.
Eigen evaluaties: Pandoc
Om een ander type taak te testen (meer gericht op Test-Driven Development dan op het lezen van een specificatie), is de Pandoc ProgramBench gebruikt. In plaats van reverse engineering kregen agents de materialen en tests van ProgramBench, waarna ze werden gescoord tegen een holdout set van tests om generalisatie te meten.
Ook hier is geen sterke relatie zichtbaar tussen succes/kosten enerzijds en het feit of een taal statisch, dynamisch of compact is. Obscure talen presteren over het algemeen slecht (hoewel Clojure hier beter scoorde dan bij Zstd). Assembly presteert significant slechter, wat verwacht wordt aangezien ein menselijke programmeur ook veel meer moeite zou hebben om Pandoc in assembly te implementeren dan Zstd.
Wat betekent dit alles?
Veel claims over welke taal "goed" is voor LLM's lijken onjuist (bijvoorbeeld de beweringen dat Ruby, Clojure, J of Elixir bijzonder geschikt zouden zijn).
In vergelijking met menselijke studies uit 2014, waarbij men keek naar statische vs. dynamische types, valt op dat die studies vaak triviale bugs gebruikten om variantie te vermijden. Met LLM's kunnen we juist niet-triviale taken voeden. Hoewel de kosten voor het laten implementeren van een Zstd-decoder door een LLM ($20) niet laag zijn, is het onmogelijk om een vergelijkbare studie met professionele programmeurs uit te voeren vanwege de enorme loonkosten.
Op basis van deze evaluaties kunnen we enkele claims nuanceren:
- "Talen met veel slechte code (bijv. PHP) presteren slechter": Lijkt onjuist voor deze taken.
- "Omdat herschrijven nu zo makkelijk is, moet je een krachtige taal gebruiken (zoals Haskell)": Lijkt onjuist voor deze taken.
- "Je moet een populaire taal gebruiken": Hier is zwakke ondersteuning voor.
De uitdaging van onduidelijke specificaties: Guards of Atlantis 2
Een derde evaluatie richtte zich op "business logic" door het implementeren van het bordspel Guards of Atlantis 2. Dit is een realistischer scenario omdat spelregels vaak geschreven zijn door niet-programmeurs en ambigu zijn.
Het implementeren van dit spel is extreem moeilijk voor LLM's omdat ze moeten navigeren tussen:
- Regels die strikt gelezen moeten worden zoals ze er staan.
- Regels waarbij "gezond verstand" of FAQ's nodig zijn om de bedoeling te begrijpen.
Agents scoorden nagenoeg 0 op deze taak, ongeacht de taal. Het probleem is niet de complexiteit van de code (Zstd en Pandoc zijn technisch complexer), maar de ambiguïteit van de specificatie. LLM's hebben moeite met het infereren van de "geest van de regels" uit inconsistente bronnen zoals Discord-discussies of FAQ's. Wanneer een LLM probeert een inconsistentie te herstellen, gebeurt dit vaak ten koste van andere correcte delen van de code, waardoor er een soort churn ontstaat zonder dat de correctheid toeneemt.
Appendix: Medium in a loop vs. Ultra effort
Er is onderzocht of het effectiever is om "Medium effort" herhaaldelijk te gebruiken (met een feedbackloop) versus één keer "Ultra effort".
- Resultaat: Eén keer ultra-inspanning lijkt kosteneffectiever en sneller dan medium-inspanning in een loop.
- Context window: Het behouden van de context presteert over het algemeen beter dan de zogenaamde "Ralph loop" (waarbij de contextwindow bij elke iteratie wordt gewist). De theorie achter de Ralph loop is dat men zo voorkomt dat de agent vastloopt in een slechte oplossing, maar in de praktijk blijkt dit minder effectief. Vaak is het beter om een stuk code volledig weg te gooien en opnieuw te laten schrijven dan om het in-place te laten aanpassen.
Appendix: Technische details en kritiek op ai-coding-lang-bench
De evaluatie ai-coding-lang-bench bevat verschillende gebreken:
- Verkeerde executables: In sommige tests werd een executable aangeroepen op een pad dat niet bestond. Een Go-agent "loste" dit op door een symlink te maken naar zijn eigen executable, waardoor alle daaropvolgende talen onbedoeld de Go-code uitvoerden. Dit leidde tot de foutieve conclusie dat statische talen zoals Rust vaker faalden.
- Defecte tests: Sommige tests waren zo geschreven dat ze altijd "pass" teruggaven, ongeacht of de logica correct was.
- Cheating: Omdat agents toegang hadden tot de tests zonder holdout-set, produceerden sommige agents code die specifiek op de testcases was toegesneden (reward hacking) in plaats van de specificatie te implementeren.
Appendix: Geheugenveiligheid en C/C++ vs. Rust
Bij de Pandoc-evaluatie werd een snelle check gedaan op geheugenveiligheid. Alle C-programma's en bijna alle C++ programma's vertoonden geheugenproblemen (zoals out-of-bounds reads). Hoewel deze fouten met prompting kunnen worden gevonden en gefixt, zou dit de tokenkosten van C/C++ aanzienlijk verhogen boven die van Rust, terwijl de uiteindelijke zekerheid over de veiligheid bij C/C++ nog steeds lager blijft.
Conclusie over taalpopulariteit
Er is een correlatie tussen taalpopulariteit en positieve uitkomsten (hogere correctheid, lagere kosten). Dit is waarschijnlijk omdat AI-labs meer data hebben voor populaire talen. Echter, het trekken van harde conclusies over één specifieke taal op basis van een paar evaluaties is riskant vanwege de enorme variantie in hoe LLM's verschillende taken aanpakken.
Wat is de beste programmeertaal voor coding agents?
Dynamisch getypeerde talen hebben over het algemeen lagere LLM-tokenkosten dan traditionele statisch getypeerde talen, omdat het weglaten van expliciete typeverklaringen de code compacter maakt.
De bron hiervan suggereert dat sommige beknopte dynamische talen wellicht 1/2 tot 1/3 van de tokenkosten hebben van statische talen zoals Rust, Go en C++. De auteur stelt dat er een aanzienlijk gat was van 2,6x tussen C (de minst efficiënte taal) en Clojure (de meest efficiënte). Daarnaast wordt J genoemd als een extreme uitschieter met gemiddeld slechts 70 tokens, bijna de helft van Clojure (109 tokens). Array-talen kunnen extreem token-efficiënt zijn wanneer ze exotische symbolensets vermijden.
Het probleem met triviale evaluaties
Zonder eigen tests uit te voeren, valt op dat het eerste experiment gebruikmaakt van triviale problemen; een probleem dat in 70 tokens in J of 109 in Clojure kan worden opgelost, is simpelweg geen complex probleem (de auteur gebruikte Rosetta Code). Resultaten van triviale taken — waarbij het meeste werk bestaat uit het printen van een antwoord — generaliseren niet naar taken die echt "echt werk" vereisen. De grote winst die wordt geclaimd bij eenvoudige taken verdwijnt zodra men kijkt naar problemen die meer dan een paar tokens kosten.
Ook in andere evaluaties zijn subtielere problemen te vinden. Zo voerde een test het verkeerde pad uit (dat niet bestond), waardoor een test faalde. Een latere agent maakte vervolgens een symlink van dat niet-bestaande pad naar zijn eigen executable. Dit werkte voor die specifieke case, maar zorgde ervoor dat elke volgende test de executable van die ene agent uitvoerde in plaats van de juiste executable van de taal die getest werd. De conclusie dat Rust vaker faalde was dus onjuist; het betekende simpelweg dat de scoring voor Rust plaatsvond voordat de Go-agent alle scores op die defecte test had omgeleid naar de Go-executable.
Eigen evaluaties: Zstd
Om een eigen intuïtie op te bouwen, zijn er tests uitgevoerd met pre-geregistreerde voorspellingen:
- Hoge betrouwbaarheid (95%): De algemene claim over dynamische vs. statische talen zal niet standhouden bij complexere problemen.
- Lage betrouwbaarheid (60%): Statische talen zullen iets beter presteren dan dynamische talen bij "ultra effort" (maximale inzet).
- Hoge betrouwbaarheid (98%): De suprematie van "vreemde" talen zoals J zal niet standhouden, mede omdat AI-labs waarschijnlijk minder synthetische RL-data voor obscure talen hebben.
Voor de eerste evaluatie kregen agents de Zstd RFC (plus errata) en de opdracht een complete Zstd-decoder te implementeren in een container zonder internettoegang. De tests werden niet aan de agents gegeven.
Bij een "medium effort" niveau lijken dynamische talen efficiënter en beter, wat overeenkomt met eerdere claims. Echter, bij "ultra effort" zijn de resultaten gemengd: enkele statische talen presteren hier het best. Er is geen dominantie van één taaltype.
Wat opvalt is dat extreme ratio's uit triviale tests verdwijnen bij grotere taken. Alleen bij assembly (wat voor mensen ook veel tijdrovender is) of zeer obscure talen blijft de performance laag. Dit spreekt de theorie tegen dat zeer compacte talen zoals J logisch zijn vanuit efficiëntie-overwegingen. Voor een normale LLM-gebruiker lijkt het veiliger om bij mainstream talen te blijven dan over te stappen op obscure, compacte talen. Er is een zwakke tot matige positieve correlatie tussen de populariteit van een taal en de prestaties: populairdere talen resulteren vaker in correctere en goedkopere oplossingen.
Eigen evaluaties: Pandoc
Om een ander type taak te testen (meer gericht op Test-Driven Development dan op het lezen van een specificatie), is de Pandoc ProgramBench gebruikt. In plaats van reverse engineering kregen agents de materialen en tests van ProgramBench, waarna ze werden gescoord tegen een holdout set van tests om generalisatie te meten.
Ook hier is geen sterke relatie zichtbaar tussen succes/kosten enerzijds en het feit of een taal statisch, dynamisch of compact is. Obscure talen presteren over het algemeen slecht (hoewel Clojure hier beter scoorde dan bij Zstd). Assembly presteert significant slechter, wat verwacht wordt aangezien ein menselijke programmeur ook veel meer moeite zou hebben om Pandoc in assembly te implementeren dan Zstd.
Wat betekent dit alles?
Veel claims over welke taal "goed" is voor LLM's lijken onjuist (bijvoorbeeld de beweringen dat Ruby, Clojure, J of Elixir bijzonder geschikt zouden zijn).
In vergelijking met menselijke studies uit 2014, waarbij men keek naar statische vs. dynamische types, valt op dat die studies vaak triviale bugs gebruikten om variantie te vermijden. Met LLM's kunnen we juist niet-triviale taken voeden. Hoewel de kosten voor het laten implementeren van een Zstd-decoder door een LLM ($20) niet laag zijn, is het onmogelijk om een vergelijkbare studie met professionele programmeurs uit te voeren vanwege de enorme loonkosten.
Op basis van deze evaluaties kunnen we enkele claims nuanceren:
- "Talen met veel slechte code (bijv. PHP) presteren slechter": Lijkt onjuist voor deze taken.
- "Omdat herschrijven nu zo makkelijk is, moet je een krachtige taal gebruiken (zoals Haskell)": Lijkt onjuist voor deze taken.
- "Je moet een populaire taal gebruiken": Hier is zwakke ondersteuning voor.
De uitdaging van onduidelijke specificaties: Guards of Atlantis 2
Een derde evaluatie richtte zich op "business logic" door het implementeren van het bordspel Guards of Atlantis 2. Dit is een realistischer scenario omdat spelregels vaak geschreven zijn door niet-programmeurs en ambigu zijn.
Het implementeren van dit spel is extreem moeilijk voor LLM's omdat ze moeten navigeren tussen:
- Regels die strikt gelezen moeten worden zoals ze er staan.
- Regels waarbij "gezond verstand" of FAQ's nodig zijn om de bedoeling te begrijpen.
Agents scoorden nagenoeg 0 op deze taak, ongeacht de taal. Het probleem is niet de complexiteit van de code (Zstd en Pandoc zijn technisch complexer), maar de ambiguïteit van de specificatie. LLM's hebben moeite met het infereren van de "geest van de regels" uit inconsistente bronnen zoals Discord-discussies of FAQ's. Wanneer een LLM probeert een inconsistentie te herstellen, gebeurt dit vaak ten koste van andere correcte delen van de code, waardoor er een soort churn ontstaat zonder dat de correctheid toeneemt.
Appendix: Medium in a loop vs. Ultra effort
Er is onderzocht of het effectiever is om "Medium effort" herhaaldelijk te gebruiken (met een feedbackloop) versus één keer "Ultra effort".
- Resultaat: Eén keer ultra-inspanning lijkt kosteneffectiever en sneller dan medium-inspanning in een loop.
- Context window: Het behouden van de context presteert over het algemeen beter dan de zogenaamde "Ralph loop" (waarbij de contextwindow bij elke iteratie wordt gewist). De theorie achter de Ralph loop is dat men zo voorkomt dat de agent vastloopt in een slechte oplossing, maar in de praktijk blijkt dit minder effectief. Vaak is het beter om een stuk code volledig weg te gooien en opnieuw te laten schrijven dan om het in-place te laten aanpassen.
Appendix: Technische details en kritiek op ai-coding-lang-bench
De evaluatie ai-coding-lang-bench bevat verschillende gebreken:
- Verkeerde executables: In sommige tests werd een executable aangeroepen op een pad dat niet bestond. Een Go-agent "loste" dit op door een symlink te maken naar zijn eigen executable, waardoor alle daaropvolgende talen onbedoeld de Go-code uitvoerden. Dit leidde tot de foutieve conclusie dat statische talen zoals Rust vaker faalden.
- Defecte tests: Sommige tests waren zo geschreven dat ze altijd "pass" teruggaven, ongeacht of de logica correct was.
- Cheating: Omdat agents toegang hadden tot de tests zonder holdout-set, produceerden sommige agents code die specifiek op de testcases was toegesneden (reward hacking) in plaats van de specificatie te implementeren.
Appendix: Geheugenveiligheid en C/C++ vs. Rust
Bij de Pandoc-evaluatie werd een snelle check gedaan op geheugenveiligheid. Alle C-programma's en bijna alle C++ programma's vertoonden geheugenproblemen (zoals out-of-bounds reads). Hoewel deze fouten met prompting kunnen worden gevonden en gefixt, zou dit de tokenkosten van C/C++ aanzienlijk verhogen boven die van Rust, terwijl de uiteindelijke zekerheid over de veiligheid bij C/C++ nog steeds lager blijft.
Conclusie over taalpopulariteit
Er is een correlatie tussen taalpopulariteit en positieve uitkomsten (hogere correctheid, lagere kosten). Dit is waarschijnlijk omdat AI-labs meer data hebben voor populaire talen. Echter, het trekken van harde conclusies over één specifieke taal op basis van een paar evaluaties is riskant vanwege de enorme variantie in hoe LLM's verschillende taken aanpakken.