Thread overview
İşleç Önceliği
Feb 02, 2022
Salih Dincer
Feb 02, 2022
Ali Çehreli
Feb 03, 2022
Salih Dincer
February 02, 2022

Merhaba Hocam,

Mümkünse bu dersi biraz çeşitlendirelim derim. En azından sol/sağ birleşim olayının örneklerini arttıralım. İstemediğiniz kadar örnek yazabilirim 😉

Bunlardan biri:

void main()
{
  alias TYPE = int;
  enum :TYPE { E = 1, M = 8} // M = max.

  TYPE a = M;
  writefln!"%,?3d"(' ', 10^^++a);

  TYPE b = M + 1;
  writefln!"%,?3d"(' ', 10^^b++);
  // ÇIKTISI: Alt alt 2 adet 1 miyar yazar
  // ve iddia ediyorum:
  assert(a != b);
}

Örneğin pow(base, power) işlevi olarak kullanılan işleç, yani base^^power yanlış anlaşılmalara müsait. Bu örnekte alıştığımız gibi ve her iki şekilde de (++öncesinde, sonrasında++) değişkenleri arttırdım. Derste daha düşük işlem önceliği olduğu için üst alma işleçi(^^) sonraki aşamada işletiliyor. Ama örneğin 2. bölümündeki b değişkeni solda yapışandan bağımsız işliyor tam karşılığı şu olabilir:

auto pow(T)(T a, ref T b) {
  scope(exit) b++;
  return a^^b;
}

Sevgiler, saygılar...

February 02, 2022
On 2/2/22 04:11, Salih Dincer wrote:

> ```d
> void main()
> {
>    alias TYPE = int;
>    enum :TYPE { E = 1, M = 8} // M = max.
>
>    TYPE a = M;
>    writefln!"%,?3d"(' ', 10^^++a);
>
>    TYPE b = M + 1;
>    writefln!"%,?3d"(' ', 10^^b++);
>    // ÇIKTISI: Alt alt 2 adet 1 miyar yazar
>    // ve iddia ediyorum:
>    assert(a != b);
> }
> ```

Daha kısa olarak şöyle de oluyor:

  int a = 8;
  int b = 9;
  writeln(10^^++a);
  writeln(10^^b++);
  assert(a != b);

Tek tek bakalım:

10^^++a yapıldığında bence işleç önceliği konusuna bakılmıyor bile çünkü ^^ işlecinin işletilebilmesi için sağ tarafındaki ifadeye ihtiyaç var. O da ++a. Yani, ++ tek başına ifade değil. Yani o konu basit: "10 üzeri (a'nın bir arttırılmasının sonucu)".

10^^b++ durumunda ise işleç önceliği devreye giriyor çünkü 10^^b yapıp sonra onun sonucuna mı ++ deneyelim yoksa önce b++ yapıp onu mu 10 üzeri yapalım? Tablo bize sonek (postfix) ++ işlecinin öncelikli olduğunu söylüyor. Demek mi şunun eşdeğeri: 10^^(b++). b++ işlecinin kendine özgü bir davranışı var: Arttırmak, ama önceki değerini üretmek.

O yüzden yazdırılanlar aynı ama b a'dan bir fazla.

Belki önek (prefix) ++ ile ^^ işleçlerinin sırasını değiştirince de ilginç olabilir:

++a^^10

İşleç önceliğine göre ++(a^^10) oluyormuş ama o da derleme hatasına neden olur çünkü parantezli ifade bir sağ-değerdir (rvalue) ve arttırılamaz.

> auto pow(T)(T a, ref T b) {
>    scope(exit) b++;

Ama o postfix ++ işlecinin özelliğinden geliyor. Hatta şöyle olursa bence daha basit:

  scope(exit) ++b;

>    return a^^b;
> }

Yani burada ^^ işleciyle ilgili özel bir karışıklık yok.

Ve bence amacını parantezle göstermekten üşenen programcı hatasını bulup bir şekilde düzeltmek zorundadır. :) Önek ve sonek arttırma işleçlerinin anlatıldığı bölümden bir alıntı:

  http://ddili.org/ders/d/aritmetik_islemler.html

<alıntı>
O yüzden, parantezler kullanarak hem işlemleri doğru sırada uygulatmış olursunuz, hem de kodu okuyan kişilere kodu anlamalarında yardımcı olmuş olursunuz.

İşleç öncelikleri tablosunu ilerideki bir bölümde göreceğiz.
</alıntı>

Ali

February 03, 2022

Bir başka örnek de şu olabilir:

import std.stdio;

void main()
{
  auto birinciBit(T)(T data)
  {
    auto result = cast(bool)(1 & data);
    writeln("\n ", __FUNCTION__,
          " <= ", result);
    return result;
  }

  auto ikinciBit(T)(T data)
  {
    auto result = cast(bool)(2 & data);
    writeln(" ", __FUNCTION__,
           " <= ", result);
    return result;
  }

  foreach(i; 0..4)
  {
    write(i + 1, " numaralı deneme:");
    if(birinciBit(i) && ikinciBit(i))/*
    if(birinciBit(i) || ikinciBit(i))//*/
    {
      writeln;
    }
  }
  /* ÇIKARILAN SONUÇ:
   * İster Mantık Ve, isterse Mantık Veya olsun,
   * soldaki false/true olma durumunda diğerine
   * bakılmaz. Bu durumlar: Ve için false,
   * Veya için true olduğunda gerçekleşir.
   */
}