3 puan yazan GN⁺ 2025-11-01 | 1 yorum | WhatsApp'ta paylaş
  • John Carmack, değiştirilebilir değişkenlerin (mutable variable) kullanımına dair kişisel görüşünü paylaştı
  • Python kullanırken ‘tek atama (single assignment)’ ilkesini ihmal eder hale geldiğini, bu konuda kişinin kendini uyarması gerektiğini belirtti
  • Döngülerdeki yinelemeli hesaplamalar dışında değişkenlerin yeniden atanmasından veya güncellenmesinden kaçınılması gerektiğini vurguladı
  • Tüm ara hesaplama adımları elde tutulduğunda bunun debugging sırasında yardımcı olduğunu ve kod blokları taşınırken önceki değerlerin istemeden kullanılmasının önüne geçtiğini söyledi
  • C/C++’ta neredeyse tüm değişkenleri ilk tanımlandıkları anda const olarak bildirmeyi iyi bir alışkanlık olarak tanımladı
  • Son olarak, “keşke mutable bir anahtar kelime olsaydı” diyerek, değişmezliğin varsayılan olmasını istediğini vurguladı

1 yorum

 
GN⁺ 2025-11-01
Hacker News görüşleri
  • Clojure kullandığım 2 yılın ardından, değişmezliğin sağladığı açıklığı başka geliştiricilere anlatmanın gerçekten zor olduğunu fark ettim
    Durum değişikliği üzerinden etki yaratmaya alışmış kişiler, bunu bizzat deneyimlemeden anlamakta zorlanıyor

    • Değişken değiştirme, örtük bir sıra bağımlılığı yaratır
      Örneğin x = 7; x = x + 3; x = x / 2 şeklinde yazarsanız sırayı değiştirince hata oluşmayabilir ama sonuç değişir
      Buna karşılık x1, x2 gibi yeni değişkenler kullanırsanız, yanlış sırada hata oluşur ve sorun açıkça görünür
      Sonuç olarak tek atama (single assignment), bu tür bağımlılıkları açıkça ifade etmenin bir yoludur
    • Ben de Scheme ile benzer bir deneyim yaşadım
      Fonksiyonel dil kullanmamış iş arkadaşlarıma, fonksiyon merkezli düşünmenin ne kadar test edilmesi kolay ve temiz olduğunu anlatsam da pek karşılık bulmadı
      Python'da fonksiyonel stili okunaklı biçimde yazmak zor, JS ise bu konuda bana daha iyi geliyor
      Sonuçta yalnızca meraklı geliştiriciler Clojure gibi dilleri denemeye yöneliyor
    • Değişmez veri ve saf fonksiyonlar varsayılan olduğunda, fonksiyonlara tamamen birer kara kutu gibi yaklaşabilirsiniz
      Fonksiyonun dış durumu bilmesi gerekmez, dışarıdakilerin de fonksiyonun içini bilmesi gerekmez
      Programın tüm durumunu bilmeden de belirli bir fonksiyonu bağımsız olarak test edebilir veya hata ayıklayabilirsiniz
    • Değişmezlik ile değişebilirliği basitçe karşı karşıya koymak, karmaşıklıktan kaçmaktır
      Haskell topluluğunun sonunda tür sistemi içinde değişebilirliği yeniden icat etmeye çalışması ilginç
      Asıl mesele, yan etkileri en düşük maliyetle kontrol etmektir
    • Clojure, öğrendiğim diller arasında en etkili dil oldu
      Haskell, tür sistemi nedeniyle giriş eşiği yüksekti; F# ise fazla uzlaşmacı kaldığından C# sözdizimiyle kod yazmaya dönüyordum
      Clojure'un homoiconicity özelliği ve güçlü veri yapıları sayesinde, “değerlerle çalışmak” fikri ilk kez gerçekten netleşti
      Profesyonel olarak kullanmayacak olsam da, fonksiyonel dil ya da Lisp deneyimi olmayan herkese kesinlikle tavsiye ederim
  • Değişkenlerin varsayılan olarak değişmez olmasını ve her şeyin bir ifade (expression) olmasını isterdim
    Ama gerçek hayatta bir Clojure geliştiricisi olarak Python istilasıyla uğraşıyorum

    • Ben de Python geliştiricisiyim ama Clojure'u yalnızca kişisel projelerde kullanıyorum
      Artık ben de TypeScript istilasıyla uğraşıyorum, o yüzden empati kurabiliyorum
    • Rust öğrendikten sonra, bir dil saf fonksiyonel olmasa bile her şeyin ifade olabileceğini fark ettim
      Bu yaklaşım, değişiklik kapsamını sınırlamak için gerçekten çok faydalı
    • Clojure her zaman Python'dan daha hızlıdır, bu da teselli sayılır
    • Sen sadece Clojure kullanan birisin; kendini “Clojure programcısı” olarak tanımlamak zorunda değilsin
      Diller arası kabile savaşlarına kapılmana gerek yok
      Verimlilik artışı çağında bu sınırların pek anlamı kalmadı
      Don’t Call Yourself a Programmer yazısını tavsiye ederim
  • Değişken yeniden atamasını en aza indirmeye çalışıyorum ama sık sık değişken gölgeleme kullanıyorum
    result = result.process() gibi kalıpları kısa olduğu için seviyorum

    • Örnek soyut olduğu için böyle olabilir ama çoğu durumda her adım için açık bir ad verilebilir
    • Bu tür kalıplar güvenlik hatalarına yol açabilir
      Örneğin process() bir doğrulama fonksiyonuysa, hangi anda işlenmiş değerden söz edildiği belirsizleşebilir
      Bu yüzden durumu isimlerle net biçimde ayırmak daha iyidir
    • Fonksiyonel stilde bunu ara değişkenler olmadan fonksiyon zincirleme ile çözebilirsiniz
      Örnek: result = x |> foo |> bar |> baz veya (-> x foo bar baz)
    • result.process() ne demek, hangi result ve hangi process?”
      Kodu sonra okuyacak kişi için kafa karıştırıcı olabilir
    • Zaten sonuç (result) olan bir şeyi tekrar işlemek (process) mantıksal olarak tuhaf duruyor
  • “Değişken (variable)” teriminin kendisi hep aklıma takılır
    Değişmezse neden variable deniyor?

    • Değişkenler tek bir çalıştırma sırasında değişmeyebilir ama her çağrıda farklı bir değere sahip olabilir
      Rust'ta ancak mut ile açıkça belirtilirse değiştirilebilir
      Buna karşılık C'de sabit oluşturmak için önişlemciye başvurmak gerekebildiğinden kafa karıştırıcıdır
    • Bir fonksiyonun x parametresi, her çağrıda farklı bir değer alabildiği için kendi başına değişen bir değerdir
      Yeniden atama olmasa bile ona değişken denebilir
    • Matematikte de değişken, belirli bir nesneyi değil keyfi bir değeri gösteren simgedir
      Programlama bu kavramı doğrudan devralmıştır
    • Sonuçta değişken, çalıştırmadan çalıştırmaya değeri değişebildiği için variable'dır
      Sabit (constant) ise tüm çalıştırmalarda aynı değeri taşır
      Variable (mathematics) bağlantısına bakılabilir
    • “Değişken” sözcüğü, zaman içinde değişmekten çok bağlama göre farklılaşmak anlamında kullanılıyor
  • IDE'nin bir değişkenin değiştirilip değiştirilmediğini görsel olarak göstermesi güzel olurdu
    Mesela değiştirilmiş değişkenler hafifçe işaretlenebilir

    • IntelliJ'de yeniden atanan değişkenlerin altı çiziliyor ve üzerine gelince “Reassigned local variable” ipucu gösteriliyor
      Mümkün olduğunca çok final kullanmak, kodu daha okunabilir ve bakımı daha kolay hale getiriyor
    • Ama otomatik çıkarım yerine açık opt-in daha iyi diye düşünüyorum
      IDE uyarı vermeli ve yalnızca gerçekten gerektiğinde değişikliğe izin verilmeli
      Rich Hickey'nin set vs list anlatısında olduğu gibi, anlamı açıkça ifade eden yapılar seçilmeli
    • Swift'te derleyici, bir değişkenin gerçekten değiştirilip değiştirilmediğini algılıyor ve gereksizse sabite çevirmeyi öneriyor
    • JetBrains IDE'lerinde değişkenin okuma/yazma konumlarını bulma özelliği zaten var
    • Böyle bir iş yapan linter yazılsa, adı “mutalator” olabilir
  • Geçmişte thread safety için değişmezliğin katı biçimde uygulandığı bir projede çalıştım
    Bu sayede kod daha okunabilir hale geldi ve neyin değişebileceğini takip etmek kolaylaştı
    O günden beri değişmezliğin ateşli bir hayranıyım

    • O zaman sana mutlaka Rust denemeni öneririm
  • Büyük bir Haskell kod tabanında çalıştıktan sonra yeniden C'ye dönünce, değişmezliğin varsayılan olmasını istemeye başladım
    const yeterli gelmiyor

    • C'de aslında doğrudan değiştirme değil, yalnızca değer yeniden ataması mümkündür
      Gerçekten değiştirmek için pointer kullanmanız gerekir; C++ ise yalnızca bir fonksiyon çağrısıyla bile argümanları değiştirebildiğinden daha opaktır
    • Rust'ın varsayılan ayarlarının yeterince güvenli bir değişmezlik sağlayıp sağlamadığını merak ediyorum
  • “Neredeyse tüm değişkenleri const olarak tanımlamak iyidir” sözüne katılıyorum
    Burada Rust'ın anılması yerinde olur

  • Varsayılanın değişmez olduğu ve yalnızca belirli bir blok içinde mutable'a izin veren bir sözdizimi hayal ediyorum
    Mesela Python'daki with bloğu gibi

    with mutable(x, items):
        x = 3
        items.append(4)
    

    Blok dışına çıkınca tekrar değişmez hale gelmesi gibi

    • Bu aslında mutable borrow kavramının kendisi
      Rust'ın borrow checker mekanizmasına bakınca bu fikrin ne kadar karmaşık olduğu görülebilir
    • Borrow kontrolü olmazsa, blok dışındayken bile referanslar elde kalıp değişiklik yapılabilir
  • State is the enemy” diye bir söz vardır
    Durum arttıkça test edilmesi gereken koşullar katlanarak büyür
    Değişmezlik, bu tür durum patlamasını önlemenin bir yoludur