Cobra: Üç Motorlu, GIL'siz, Native Derlenen Bir Betik Dili
Go ile yazılmış Cobra dilini baştan sona tanıtan bir yazı: end ile kapanan bloklar, struct ve record, decorator'lar, GIL olmadan gerçek paralellik, kanallar, zengin standart kütüphane, LSP ve hata ayıklayıcı. Ağaç yürüten yorumlayıcı, bytecode VM ve PyPy'yi geçen native derleyici nasıl çalışıyor?

Cobra, Go ile yazdığım genel amaçlı bir betik dili. Blokları girintiyle değil end ile kapatıyor, tek bir statik dosya olarak dağıtılıyor ve aynı programı üç farklı yoldan çalıştırabiliyor: ağaç yürüten bir yorumlayıcı, bir bytecode VM ve doğrudan makine koduna derleyen bir native derleyici. GIL yok; async görevler gerçekten bütün çekirdeklerde aynı anda koşuyor. Yanında bir LSP sunucusu, bir biçimlendirici, bir VS Code eklentisi, bir test çatısı, Django tarzı bir web çatısı ve NumPy benzeri bir sayısal kütüphane de var.
Bu yazıda dili baştan sona dolaşacağım: sözdizimi, veri tipleri, fonksiyonlar, nesneler, hatalar, eşzamanlılık, standart kütüphane, araçlar ve en sonunda iç yapı ile performans. Yazıdaki bütün örnekleri Cobra 0.13.0 ile her iki motorda da çalıştırdım; gösterdiğim çıktılar gerçek çıktılar. Dilin sitesi cobralang.baltavista.com adresinde.
Neden bir dil daha?
Cobra'yı katman katman inşa ettim: önce lexer, sonra Pratt parser, sonra ağaç yürüten değerlendirici, ardından bytecode derleyici ve yığın makinesi, en son da native derleyici. Baştan beri tek bir kural vardı: her özellik iki motora birden girer, ikisinin de aynı davrandığı test edilir. Testler ve benchmark'lar iki motorun bayt bayt aynı çıktıyı üretmesini şart koşuyor; çıktılar farklıysa sonuç raporlanmıyor bile.
Hedeflediğim yer şuydu:
- Kurulumsuz betikler: bir dosyayı kopyala, çalıştır. venv yok, paket yöneticisi yok.
- Gerçek paralellik: CPU'ya yüklenen işi çekirdeklere dağıtınca gerçekten hızlansın.
- Gömülebilirlik ve okunabilirlik: dilin tamamı, baştan sona okunup anlaşılabilecek kadar küçük kalsın.
- Hız gerektiğinde: aynı kaynağı native derleyip sayısal işlerde JIT'li çalışma ortamlarının önüne geçebilsin.
Altmış saniyede Cobra
let name = "Cobra"
let langs = ["go", "rill", "cobra"]
let ages = {"ada": 36, "linus": 28}
def greet(who, times)
let out = []
for i in range(times)
out.push("merhaba ${who} #${i + 1}")
end
return out
end
for line in greet(name, 2)
print(line)
end
let squares = map(def(x) -> x * x, [1, 2, 3, 4])
print(squares, squares[-1], squares[1:3])
print(filter(def(n) -> n % 2 == 0, range(10)))
let a, b = 1, 2
a, b = b, a
print(a, b, 7 / 2, float(7) / 2)
for k in ages
print(k, ages[k])
end
print(" a,b ".strip().split(","))
Çıktı:
merhaba Cobra #1
merhaba Cobra #2
[1, 4, 9, 16] 16 [4, 9]
[0, 2, 4, 6, 8]
2 1 3 3.5
ada 36
linus 28
["a", "b"]
Kurallar az ve net:
- Satır sonu ifadeyi bitirir, noktalı virgül yok.
- Bloklar
def,if,elif,else,while,for,struct,trygibi bir anahtar kelimeyle açılır veendile kapanır. Girinti tamamen kozmetik; yanlış girinti programı bozmaz. #satır sonuna kadar yorumdur.- Mantıksal işleçler kelimedir:
and,or,not. Boş değernull. ( [ {içindeki ifadeler ve çağrı argümanları birden fazla satıra yayılabilir.
Değişkenler ve tipler
let mevcut kapsamda yeni bir isim tanımlar, düz x = ... var olan bir ismi günceller. Tanımlanmamış bir isme atama hatadır; yazım hatası yüzünden sessizce yeni bir değişken doğmaz. const değiştirilemez bir bağ tanımlar; ama değişmezlik bağın kendisinedir, değerin değil: const xs = [1] yazınca xs = ... yasaktır, xs.push(2) serbesttir.
Tipler: tamsayı, ondalıklı sayı, metin, boolean, null, liste, sözlük ve birinci sınıf fonksiyonlar. Birkaç ayrıntı:
- Tamsayı ile ondalıklı karışınca sonuç ondalıklı olur:
1 + 2.5sonucu3.5,1 == 1.0doğru. - İki tamsayı arasında
/tamsayı bölmesidir:7 / 2sonucu3. Ondalık sonuç içinfloat(7) / 2. - Yanlış sayılan değerler:
false,null,0,"",[],{}. andveorkısa devre yapar ve karar veren işleneni döndürür:0 or "x"sonucu"x".- Çoklu atama tek satırda takas yapar:
a, b = b, a. Sağ taraf tamamen hesaplandıktan sonra bağlama yapılır. += -= *= /= %=değişkenlerde, indekslerde (xs[i] += 1) ve alanlarda (self.n += 1) çalışır.
Koleksiyonlar ve metinler
Listeler referans tipidir; let b = a kopyalamaz, aynı listeyi gösterir. Negatif indeks sondan sayar (l[-1]), + birleştirir, == derin karşılaştırır. Metotlar: push, pop, contains, find, count, reverse, sort.
Dilimleme Python'daki gibi seq[low:high:step] biçiminde: xs[:2], xs[1:], xs[::-1]. Sınır dışı değerler kırpılır. Listelerde yeni bir liste, metinlerde rune tabanlı (UTF-8 güvenli) bir metin, range üzerinde ise yine tembel bir aralık döner.
Sözlükler ekleme sırasını korur. Anahtar metin, tamsayı, boolean ya da null olabilir. Olmayan anahtarı d[k] ile okumak hatadır; has ile kontrol edilir ya da get(k, varsayılan) kullanılır. Metotlar: keys, values, items, has, get, del.
Metinler değiştirilemez ve indekslenebilir. upper, lower, strip, split, join, replace, startswith, find, count gibi metotlar zincirlenebilir. Metin içine ifade gömmek için ${...} kullanılır; içine her ifade yazılabilir, iç içe bile olabilir. Çok satırlı metinler için üç tırnaklı dizgiler de var.
Sıralama bir karşılaştırıcı da alabiliyor; sayıları ekranda düzgün göstermek için de fmt modülü var:
import "fmt"
import "json"
let rows = json.parse("[{\"ad\": \"klavye\", \"fiyat\": 1299}, {\"ad\": \"fare\", \"fiyat\": 349.5}]")
rows.sort(def(a, b) -> a["fiyat"] < b["fiyat"])
for r in rows
print(fmt.pad(r["ad"], 8, " "), fmt.group(r["fiyat"], 2))
end
fare 349.50
klavye 1,299.00
sort(less) kararlı bir sıralama kullanıyor; eşit elemanlar giriş sırasını koruduğu için çok anahtarlı sıralamalar art arda yazılarak kurulabiliyor. fmt.group ve math.round yarımları çifte yuvarlıyor (banker's rounding) ve yuvarlamayı ikili kayan nokta yerine ondalık metin üzerinden yapıyor; 0.145 * 100 gibi sinsi hatalar burada yaşanmıyor.
Fonksiyonlar, closure'lar ve decorator'lar
Fonksiyonlar birinci sınıf değerdir ve tanımlandıkları kapsamı yakalarlar. Tek ifadelik anonim fonksiyonlar ok biçimiyle yazılır: def(x) -> x * 2. Çok satırlı gövde için def(x) ... end blok biçimi var. map, filter, reduce, zip, enumerate, any, all yerleşik.
Decorator'lar bir def'in üstüne yazılır ve @d sözdizimi name = d(name) anlamına gelir. Web rotalarını kaydetmenin doğal yolu bu:
let routes = {}
def route(path)
return def(fn)
routes[path] = fn
return fn
end
end
@route("/")
def home(req)
return "ana sayfa"
end
@route("/hello")
def hello(req)
return "merhaba ${req["name"]}"
end
for path in routes
print(path, "->", routes[path]({"name": "ada"}))
end
/ -> ana sayfa
/hello -> merhaba ada
Decorator'lar üst üste binebilir; def'e en yakın olan önce uygulanır. async def üzerinde de çalışırlar.
Nesneler: struct, kalıtım, record, contract
Cobra'da sınıflar struct ile tanımlanıyor (class da eş anlamlı olarak kabul ediliyor). init kurucu, self metot gövdelerinde örtük. Tek kalıtım < ile, üst sınıfın metoduna super ile ulaşılır. Bir struct gövdesinde sınıf sabitleri (const), alan gibi okunan özellikler (get), atama yakalayıcıları (set) ve statik metotlar (static def) olabilir.
record ise değiştirilemez ve değer ile karşılaştırılan bir struct: alanları aynı olan iki record == sayılır, with bir alanı değiştirilmiş yeni bir kopya döndürür.
struct Shape
def init(name)
self.name = name
end
def describe()
return "${self.name}: alan ${self.area()}"
end
end
struct Circle < Shape
const PI = 3.14159
def init(r)
super.init("daire")
self.r = r
end
def area()
return Circle.PI * self.r * self.r
end
end
struct Rect < Shape
def init(w, h)
super.init("dikdörtgen")
self.w = w
self.h = h
end
def area()
return self.w * self.h
end
get square()
return self.w == self.h
end
end
record Point
def init(x, y)
self.x = x
self.y = y
end
end
for s in [Circle(2), Rect(3, 3)]
print(s.describe())
end
print(Rect(2, 5).square)
let p = Point(1, 2)
print(p == Point(1, 2), p.with({"x": 9}))
try
p.x = 5
catch err
print("hata:", err)
end
daire: alan 12.56636
dikdörtgen: alan 9
false
true Point{x: 9, y: 2}
hata: line 49: cannot modify immutable record Point
Shape.describe içinde çağrılan self.area() alt sınıfta tanımlı; metotlar örneğin gerçek tipine göre dinamik olarak seçiliyor. contract ise hafif bir arayüz: gereken metot adlarını listeler, implements(x, Drawable) bir değerin hepsini tanımlayıp tanımlamadığını söyler.
Hatalar: try, catch, finally
throw her değeri fırlatabilir ve değer olduğu gibi yakalanır. Çalışma zamanı hataları satır numaralı mesaj olarak yakalanır. finally her zaman çalışır; return, break ve continue da try bloklarından olduğu gibi geçer.
def divide(a, b)
if b == 0
throw "sıfıra bölme"
end
return a / b
end
try
print(divide(10, 2))
print(divide(1, 0))
catch e
print("yakalandı:", e)
finally
print("finally her zaman çalışır")
end
@memo
def x()
end
Sondaki @memo bilerek tanımsız bırakıldı. İki motorun farkı tam burada görünüyor: ağaç yürüten yorumlayıcı programı o satıra kadar çalıştırıp orada duruyor, VM ise programı derlerken tanımsız ismi yakalıyor ve tek satır bile çalıştırmıyor. Hata mesajı ve satır numarası iki motorda da aynı:

Derleme anında yakalanan hatalar sadece tanımsız değişkenler değil: yerleşik isimlere atama, döngü dışındaki break ve const bir ismi yeniden atamak da çalıştırmadan önce reddediliyor.
Eşzamanlılık: async, await ve GIL olmadan paralellik
async def ile tanımlanan bir fonksiyon çağrıldığında hemen bir görev döndürür ve gövdesi kendi işletim sistemi iş parçacığında çalışır. await gorev sonucu bekler, await [g1, g2, ...] hepsini toplar ve sonuçları sırayla verir. Görevde atılan hata await noktasında yeniden fırlatılır.
GIL olmadığı için CPU'ya yüklenen iş gerçekten hızlanıyor. Aynı hesabı önce sırayla, sonra dört görevle yapalım:
import "time"
import "fmt"
def work(n)
let s = 0
let i = 0
while i < n
s = s + i % 7
i = i + 1
end
return s
end
async def job(n)
return work(n)
end
let t0 = time.clock()
let seq = [work(5000000), work(5000000), work(5000000), work(5000000)]
let t1 = time.clock()
let par = await [job(5000000), job(5000000), job(5000000), job(5000000)]
let t2 = time.clock()
print(seq == par)
print("sıralı ${fmt.decimal(t1 - t0, 3)}s, paralel ${fmt.decimal(t2 - t1, 3)}s")
10 çekirdekli bir Apple M serisi makinede VM ile çıktı sıralı 0.584s, paralel 0.186s oldu: kodda tek bir kilit, havuz ya da ek sözdizimi olmadan yaklaşık 3 kat. pmap(fn, liste) aynı fikrin en kısa hali: map ile aynı çağrı, ama elemanlar çekirdeklere dağıtılıyor ve sonuçlar giriş sırasını koruyor.
Paralellik paylaşılan durumun senkronizasyonunu programcıya bırakıyor. Bunun için yerleşik araçlar var:
Mutex()veRWMutex():lock,unlock,try_lock, okuyucu tarafındarlock,runlock.Channel()veChannel(n): Go'daki gibi tamponsuz ya danelemanlık tamponlu kanallar;send,recv,close,try_send,try_recv.select(ops): birden fazla kanalı aynı anda bekler, hangisi hazırsa onunla devam eder; varsayılan değer verilirse beklemez.
let ch = Channel(4)
let done = Channel()
async def producer()
for i in range(5)
ch.send(i * i)
end
ch.close()
end
async def consumer()
let total = 0
let v = ch.recv()
while v != null
total += v
v = ch.recv()
end
done.send(total)
end
producer()
consumer()
print("toplam:", done.recv())
print(pmap(def(x) -> x * 10, [1, 2, 3]))
toplam: 30
[10, 20, 30]
Global kapsam ve modül önbelleği içeride senkronize; farklı global'lere dokunan görevler her zaman güvende. Yarışan bir görevdeki kurtarılabilir bir panik (paylaşılan listede sınır dışı indeks gibi) programı çökertmek yerine yakalanabilir bir "data race in task" hatasına dönüşüyor. Bu bir güvenlik ağı, kilit yerine geçmiyor: Go'da olduğu gibi paylaşılan bir sözlüğü kilitsiz değiştirmek ölümcül hata.
Modüller ve standart kütüphane
import "lib/utils.cobra" dosyayı bir kez çalıştırır, önbelleğe alır ve bir utils modül nesnesi bağlar; as ile başka ad verilebilir. Döngüsel import hatadır, modüller dışarıdan salt okunurdur.
Yerleşik native modüller Go ile yazıldı ve iki motor tarafından ortak kullanılıyor. Hepsindeki hatalar yakalanabilir:
| modül | içerik |
|---|---|
fs | dosya okuma, yazma, ekleme, satır satır okuma, dizin işlemleri |
math, random | matematik fonksiyonları, tohumlanabilir rastgele sayılar |
fmt | sayıları ondalık, binlik ayraçlı ve dolgulu metne çevirme |
json | anahtar sırasını koruyan parse, girintili stringify |
time | saat, monoton sayaç, strftime biçimli format ve parse |
re | RE2 sözdizimiyle doğrusal zamanlı düzenli ifadeler |
http | istemci (get, post, request) ve sunucu (serve), SSE akışı |
proc, net | alt süreçler, TCP soketleri, TLS |
crypto, encoding | sha256, hmac, PBKDF2 parola özeti, base64, hex |
os, runtime | argümanlar, ortam değişkenleri, GC ve bellek istatistikleri |
test | yerleşik birim test çatısı |
Bir HTTP sunucusu, çatı kullanmadan bile birkaç satır:
import "http"
import "json"
def handler(req)
if req["path"] == "/hello"
let name = req["query"].get("name", "dünya")
return {"headers": {"Content-Type": "application/json"}, "body": json.stringify({"merhaba": name})}
end
return {"status": 404, "body": "bulunamadı"}
end
http.serve(":8099", handler)
curl "localhost:8099/hello?name=ada" isteği {"merhaba":"ada"} döndürüyor. İstek sözlüğünde yöntem, yol, sorgu, başlıklar, gövde, istemci adresi ve multipart/form-data ile gelen dosyalar hazır geliyor. İşleyiciler istek başına bir goroutine ile paralel çalışıyor.
Testler de dilin içinde:
import "test"
@test.it
def toplama()
test.assert_eq(2 + 2, 4)
end
@test.it
def derin_esitlik()
test.assert_eq([1, {"a": [2]}], [1, {"a": [2]}])
end
@test.it
def hata_atar()
test.assert_raises(def() -> 1 / 0)
end
let summary = test.run()
ok toplama
ok derin_esitlik
ok hata_atar
3 passed, 0 failed, 3 total
Araçlar
Tek ikili dosya, bütün modlar:
cobra app.cobra # ağaç yürüten yorumlayıcı
cobra --vm app.cobra # bytecode VM
cobra --native app.cobra # makine koduna derle ve çalıştır (önbellekli)
cobra build app.cobra # app.cobrac bytecode dosyası
cobra build --exe app.cobra # VM gömülü, tek başına çalışan dosya
cobra build --native app.cobra # tek başına native çalıştırılabilir dosya
cobra # REPL (çok satırlı, durumu korur)
cobra fmt -w app.cobra # kaynak biçimlendirici
cobra watch app.cobra # dosya değişince yeniden çalıştır
cobra lsp # dil sunucusu
cobra dap # hata ayıklayıcı (Debug Adapter Protocol)
- REPL iki motorda da var; açık bir
defya daifbloğu yazarken..devam istemiyle girişi tamamlamanızı bekliyor. - LSP sunucusu gerçek parser ve derleyiciden canlı teşhis veriyor: yazarken sözdizimi hataları ve tanımsız değişkenler, tamamlama, üzerine gelince açıklama, sembol listesi, tanıma git.
- VS Code eklentisi sözdizimi renklendirme, bloğa duyarlı girinti, snippet'ler, modül üyelerinde tamamlama ve outline görünümü veriyor;
cobraPATH'teyse LSP'yi kendisi başlatıyor. - Hata ayıklayıcı:
cobra dapeditörlere Debug Adapter Protocol üzerinden kesme noktası, adım adım ilerleme, çağrı yığını ve değişken incelemesi sunuyor. Ayrıca--astve--tokensparser'ın ve lexer'ın ne gördüğünü yazdırıyor, çalışma zamanı hataları yığın iziyle geliyor. - Go eklentileri:
import "ad.so"ile Go ile yazılmış bir eklenti çalışma anında yüklenip modül gibi kullanılabiliyor.
Yayın ikilileri statik ve bağımlılıksız; macOS (arm64, amd64), Linux (amd64, arm64) ve Windows için derleniyor.
İç yapı: bir ön yüz, üç motor

Lexer kaynağı token'lara, Pratt parser token'ları AST'ye çeviriyor. Bundan sonra yol üçe ayrılıyor, ama değerlerin davranışı (object paketi) ve standart kütüphane (eval paketi) hepsinde ortak. Bu yüzden bir liste metodunun ya da bir json.parse çağrısının iki motorda farklı davranması mümkün değil.
Ağaç yürüten yorumlayıcı AST düğümlerini doğrudan değerlendiriyor. Hazırlık maliyeti yok; REPL ve kısa betikler için ideal.
Bytecode VM benchmark paketini yaklaşık 4 kat hızlı çalıştırıyor. Bunu sağlayan şeyler, etkisi büyükten küçüğe:
- Ondalıklı sayılar ve struct örnekleri için VM başına ayırma arenaları. GIL olmadığı ve arenalar VM'e özel olduğu için güvenli.
- Kayıtlara alınmış bir dağıtım döngüsü: komut işaretçisi, yığın işaretçisi ve değer yığını yerel değişkenlerde tutuluyor, sadece çağrılarda ve hata yollarında geri yazılıyor. Bytecode
OpHaltile bittiği için döngüde sınır kontrolü yok. - On bir birleşik süper komut:
while i < ngibi karşılaştır ve atla,i = i + 1gibi hesapla ve yaz,yerel.alanokuma,liste[yerel]indeksleme gibi en sık kalıplar tek dağıtımda. - Tamsayı ve ondalıklı aritmetik için satır içi hızlı yollar ve küçük tamsayıların önbelleklenmesi (-1024 ile 131071 arası).
- Önceden ayrılmış bir dizide yaşayan çağrı çerçeveleri: çağrı başına sıfır ayırma.
- Metin anahtarlı sözlükler için açık adreslemeli özel bir hash tablosu, metin nesnelerinde önbelleklenmiş hash değerleri.
- Satır tablosu aramaları sıcak yoldan tamamen çıkarıldı; hata mesajları satır numarasını ancak gerektiğinde hesaplıyor.
Native derleyici tüm program üzerinde tip çıkarımı yapıyor. Cobra dinamik tipli, ama gerçek programlar çoğunlukla tip olarak kararlı: bir değişken hep tamsayı, bir liste hep ondalıklı tutuyor. Derleyici bunu ispatlayabildiği yerde tamsayıları ve ondalıklıları kutusuz, struct'ları düz, listeleri ve sözlükleri native dilim ve map olarak üretiyor; kod üretici olarak Go araç zincirini kullanıyor. Çıktı, ondalık biçimlendirme ve yuvarlamaya kadar VM'inkiyle bayt bayt aynı olacak şekilde doğrulanıyor.
Native derlemenin kapsamı dilin tip olarak kararlı çekirdeği: fonksiyonlar, init ve metotları olan struct'lar, listeler, sözlükler, metinler, döngüler ve math. Closure, async, try/catch, kalıtım, record ya da başka modüller kullanan bir program "native derlenemez" diye raporlanıyor ve neyin engel olduğu tek tek yazılıyor; o program VM'de değişmeden çalışıyor. Native dosya üretmek için derleme makinesinde Go gerekiyor, üretilen dosyayı çalıştırmak için hiçbir şey gerekmiyor (benim makinemde yaklaşık 2 MB'lık statik bir Mach-O dosyası).
Performans

Üstteki grafik dilin sitesinde yayınlanan ölçümler: n-body, binary-trees, spectral-norm, mandelbrot ve kelime frekansı testleri Cobra'da ve Python'da birebir aynı biçimde yazılmış, bütün çalışma ortamları aynı çıktıyı basıyor. Cobra native toplamda 0.28 saniyeyle PyPy'nin izleyen JIT'inin (0.44 saniye) önünde; CPython 3.14 aynı paketi 5.99 saniyede bitiriyor.
Alttaki grafik altı mikro testte iki motoru karşılaştırıyor: özyinelemeli çağrılarda (fib) VM 10 kattan fazla, toplamda 4.1 kat hızlı.
Dürüst olmak gerekirse VM her işte CPython'u geçmiyor. Bu yazı için 600×600 piksellik, 200 iterasyonluk bir mandelbrot döngüsünü kendim ölçtüm: ağaç yürüten yorumlayıcı 16.5 saniye, VM 2.5 saniye, CPython 3.14 1.7 saniye, native derlenmiş Cobra ise 0.07 saniye (derleme bir kere yapılıp önbelleğe alındıktan sonra). Yoğun ondalıklı aritmetik ve karmaşık döngü koşullarında VM'in kutulama maliyeti hissediliyor; bu tür işler için doğru araç zaten --native. Cobra'nın asıl alanı hızlı ve kurulumsuz betikler, gömülü betik dili kullanımı ve baştan sona anlaşılabilecek kadar küçük bir çalışma ortamı.
Ekosistem: cobranum ve Venom
cobranum Gonum üzerine, macOS'ta cgo ile derlendiğinde Apple Accelerate (BLAS/LAPACK) üzerine kurulmuş, NumPy tarzı bir sayısal dizi kütüphanesi. Bir ve iki boyutlu yoğun diziler, vektörel işlemler, broadcasting, indirgemeler ve lineer cebir sunuyor. Kitapta en küçük kareler, PCA, PageRank, sayısal integral ve diferansiyel denklemler gibi bilimsel örneklerle anlatılıyor:

Venom tamamen Cobra ile yazılmış, Django'dan ilham alan bir web çatısı: decorator ile rotalama, OxiDB üzerinde bir ORM, kalıtımlı şablon motoru, middleware, oturumlar, statik dosyalar ve CSRF koruması. Cobra'da sınıf kalıtımı yerine fabrika fonksiyonları tercih edildiği için model bir fabrikadan üretiliyor:
import "venom/router.cobra"
import "venom/response.cobra"
import "venom/orm.cobra"
let route = router.route
let db = orm.connect("127.0.0.1", 4444)
let User = orm.model(db, "users").ensure()
@route("GET", "/users/<name>")
def show_user(req)
let user = User.get({"name": req["params"]["name"]})
if user == null
return response.not_found("kullanıcı yok")
end
return response.ok(user)
end
router.serve(":8000")
OxiDB'ye bağlantı, Go ile yazılmış oxidb.so eklentisi üzerinden. Aynı ailede OxiDB'nin SQL motoru için Entity Framework tarzı bir ORM (oxisqlorm) de var.
Kitap
Dilin tamamı, Türkçe ve İngilizce iki kitapta anlatılıyor: temellerden kontrol akışına, koleksiyonlardan nesne yönelimine, eşzamanlılıktan iç yapıya ve cobranum'a kadar. İngilizce baskıda bunlara Venom bölümü de ekleniyor. İkisi de PDF olarak ücretsiz:
Denemek için
İkili dosyalar, VS Code eklentisi, cobranum ve kitaplar cobralang.baltavista.com adresinde. macOS'ta (Apple Silicon) en kısa yol:
curl -LO https://cobralang.baltavista.com/releases/cobra-0.13.0-darwin-arm64
chmod +x cobra-0.13.0-darwin-arm64 && mv cobra-0.13.0-darwin-arm64 /usr/local/bin/cobra
cobra --version
Sonra bir dosya açıp print("merhaba") yazmak yeterli.