Varsayılan bağımsız değişken - Default argument

Gelen bilgisayar programlama , bir varsayılan argüman bir olan argüman a fonksiyonu bir programcı belirtmek için gerekli olmadığını. Çoğu programlama dilinde, işlevler bir veya daha fazla argüman alabilir. Genellikle, her bağımsız değişken tam olarak belirtilmelidir ( C programlama dilinde durum budur ). Daha sonraki diller (örneğin, C ++ 'da ), programcının, işlevi çağırırken bir değer belirtilmemiş olsa bile, her zaman bir değeri olan varsayılan argümanları belirtmesine izin verir.

C ++ 'da varsayılan bağımsız değişkenler

Aşağıdaki işlev bildirimini göz önünde bulundurun:

int MyFunc(int a, int b, int c = 12);

Bu işlev, sonuncusunun varsayılanı on iki olan üç bağımsız değişken alır. Programcı bu işlevi iki şekilde çağırabilir:

int result = MyFunc(1, 2, 3);
result = MyFunc(1, 2);

İlk durumda c adı verilen bağımsız değişkenin değeri normal olarak belirtilir. İkinci durumda, bağımsız değişken atlanır ve bunun yerine varsayılan değer olan 12 kullanılır.

Bağımsız değişkenin arayan tarafından belirtilip belirtilmediğini veya varsayılan değerin kullanılıp kullanılmadığını bilmenin bir yolu yoktur.

Yukarıda bahsedilen yöntem, işlevin parametrelerle veya parametreler olmadan çağrılabilmesi için varsayılan ölçütlerin belirlenmesi istendiğinde özellikle yararlıdır. Aşağıdakileri göz önünde bulundur:

void PrintGreeting(std::ostream& stream = std::cout) {
  // This outputs a message to the given stream.
  stream << "hello world!";
}

İşlev çağrısı:

PrintGreeting();

varsayılan olarak " merhaba dünya !" için standart çıkış std::cout (tipik ekranı). Öte yandan, türdeki herhangi bir nesne std::ostreamartık aynı işleve geçirilebilir ve işlev, standart çıktı yerine verilen akışa yazdırır.

PrintGreeting(std::cerr);

Varsayılan argümanların değerleri çağrılan fonksiyonun gövdesi yerine çağrı sitesinde "doldurulduğundan", sanal fonksiyonlar varsayılan argüman değerlerini çağrının yapıldığı statik tipten veya çağrının yapıldığı referanstan alır. sanal işlevin gövdesini sağlayan nesnenin dinamik türünden.

struct Base {
  virtual std::pair<int, int> Foo(int x = 1) {
    return {x, 1};
  }
};

struct Derived : public Base {
  std::pair<int, int> Foo(int x = 2) override {
    return {x, 2};
  }
};

int main() {
  Derived d;
  Base& b = d;
  assert(d.Foo() == std::make_pair(2, 2));
  assert(b.Foo() == std::make_pair(1, 2));
}

Aşırı yüklenmiş yöntemler

Java gibi bazı dillerin varsayılan bağımsız değişkenleri yoktur. Ancak aynı davranış, farklı sayıda bağımsız değişken alan aynı ada sahip aşırı yüklenmiş yöntemler oluşturmak için yöntem aşırı yüklemesi kullanılarak simüle edilebilir ; ve daha az argümana sahip sürümler, eksik argümanlar olarak varsayılan argümanlar ile daha fazla argümana sahip sürümleri çağırır:

int MyFunc(int a, int b) { return MyFunc(a, b, 12); }
int MyFunc(int a, int b, int c) { /* main implementation here */ }

Bununla birlikte, diğer birkaç dezavantaja ek olarak , varsayılan bağımsız değişkenler tür sisteminde modellenmediğinden, geri aramanın türü (diğer bir deyişle daha yüksek sıralı işlev), aşırı yüklemelerden birini kabul ettiğini veya varsayılan bağımsız değişkenleri simüle ettiğini ifade edemez. aşırı yüklenmiş fonksiyonlar. Oysa JavaScript'te aşırı yüklenmemiş işlev tanımı, girdi değeri olduğunda varsayılanın yerini alabilir undefined(bağımsız undefineddeğişkenin çağrı sitesinde yokluğu veya açıkça iletilen bir undefineddeğer aracılığıyla dolaylı olarak olmasından bağımsız olarak ); ?: TypeScript'te isteğe bağlı bir argüman parametre türü olarak modellenmiştir . JavaScript'in çözümü statik olarak çözülmez (yani derleme zamanında değil, bu nedenle TypeScript yalnızca isteğe bağlılığı modelliyor ve işlevin tür imzasındaki varsayılan değerleri değil) bu nedenle, geri aramaların bağımsız olarak yapabilmesi için daha fazla esneklik sağlasa da, ek çalışma zamanı ek yüküne neden oluyor. geri aramayı giren işlevin (geri aramanın tür imzası) tarafından merkezi olarak dikte edilmesi yerine varsayılanlarını kontrol edin. Typescript çözüm olabilir Java simüle ile Optionalörtük bir benzeşik hariç türü undefinedher devamsızlık argüman için açık olan Optional.<Integer>absent()çağrı sitesinde.

Değerlendirme

Her işlev çağrısı için varsayılan argüman değerleri çağrılan işleve aktarılmalıdır.

Varsayılan bir bağımsız değişken değeri yan etkiler içeriyorsa, bu yan etkiler değerlendirildiğinde önemlidir - tüm program için bir kez (ayrıştırma zamanında, derleme zamanında veya yükleme zamanında) veya çağrı sırasında işlev çağrısı başına bir kez.

Python, işlev bildirimi değerlendirildiğinde, varsayılan argümanlardaki ifadeleri bir kez değerlendiren dikkate değer bir dildir. İşlev çağrısı başına değerlendirilmesi isteniyorsa, varsayılan argümanı olarak sahip olması ile çoğaltılabilen sentinel değer gibi, NoneSentinel değeri geçirildi sadece varsayılan değerin yan etkiler ve bundan sonra fonksiyon gövdesi olan değerlendirir.

Örneğin:

import random

def eager(a=random.random()):
    return a

x = eager()
y = eager()
assert x == y

def lazy(a=None):
    if a is None:
        a = random.random()
    return a

x = lazy()
y = lazy()
assert x != y

Kapsam

Genel olarak, varsayılan bir bağımsız değişken, parametre tarafından iletilen bir bağımsız değişkenle veya işlevin başlangıcında bildirilen yerel bir değişkenle aynı şekilde davranır ve bir parametre veya başka bir yerel değişkenle, yani ayrılmamış otomatik bir değişkenle aynı kapsam ve boyuta (yaşam süresi) sahip olur. işlev sonlandırması hakkında.

Diğer durumlarda, bunun yerine bir varsayılan bağımsız değişken statik olarak tahsis edilebilir. Değişken değiştirilebilirse, statik bir değişkende olduğu gibi işlev çağrılarında değerini korur .

Bu davranış, Python'da listeler gibi değiştirilebilir türler için bulunur. Değerlendirmede olduğu gibi, yerel bir değişkenle aynı kapsamı sağlamak için, bir gözlemci değer kullanılabilir:

def eager(a=[]):
    return a

x = eager()
x += [1]
assert eager() == [1]

def lazy(a=None):
    if a is None:
        a = []
    return a

x = lazy()
x += [1]
assert lazy() == []

Referanslar