## 10. Tekrardan kesinlikle kaçının

Hazırlıklı olun, bu oldukça uzun bir ders. Yeni komutların nasıl tanımlanacağını öğreneceğiz. Bunun yanında program yazarken uyulması gereken üçüncü kuralıda öğreneceğiz:

Kural # 3
  Bilgisayar programı yazarken aynı kodları tekrar yazmayın.
  Tekrar ediyorum: aynı kodları tekrar yazmayın!

### Üç sol bir sağ yapar

Reeborg'a aynı noktadayken ardı adına üç sol dönüş yaptırırsanız onu sağa döndürmüş olursunuz. Aşağıdaki programın ne yaptığını bilgisayarı kullanmadan bir kağıt üzerinde çizerek bulmaya çalışın.

    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    turn_left()
    turn_left()
    turn_off()

### Sıra sizde

Yukarıdaki programı yazın, kaydedin ve çalıştırın. Reeborg sizin tahmin ettiğiniz gibi bir hareket yaptı mı?

### Yine sıra sizde!

Az önce kaydettiğiniz programı Reeborg'u saatin dönüş yönünde aşağıdaki şekilde olduğu gibi hareket edecek şekilde değiştirin.

### Sağa dönüşü tanımlamak

Reeborg'un sağa dönüşü, ardı ardına üç sol dönüş yaparak yaptığını biliyoruz. Eğer ardı ardına sağa dönüşler yaptırmak istersek gerekli programı yazmanın ne kadar sıkıcı olabileceğini tahmin edebilirsiniz. Bunun nedeni birbiriyle aynı kodların programın farklı yerlerinde tekrar edilmesinden dolayıdır. Reeborg'un Python yardımıyla programlanabilir olması sayesinde bu tekrarlardan kaçınabiliriz.

Python'da bir dizi komuta basit bir ad verilebilir. Örneğin sağa dönüşü aşağıdaki gibi bir komutla tanımlayabiliriz: (define tanımla anlamına gelir, def define'ın kısaltılmışıdır)

Burada beş tane önemli şey vardır:

- Daha önceden anlattığımız gibi `#``` sembolü bu satırın takip eden kısmının Reeborg (veya Python) tarafından okunmayacağını gösterir. Bunlara açıklama denir ve diğer programcılara ya da kendimize onu takip eden satır veya satırların ne iş yaptığını anlatmak için kullanılırlar. Yeşille gösterilmiş olmaları onları komutlardan kolayca ayırt etmemizi sağlarlar. Python ve Reeborg bu açıklamaları dikkate almaz.
- Tanımlama Python komutu olan ve editörün maviyle gösterdiği def ile başlar. Bir Python komutu Python'un kendisi tarafından tanımlanmış özel bir kelimedir. def komutunu, yeni komutun adı, iki parantez ve iki nokta üst üste takip eder.
- Bir komut tanımlamak daha önceden yaptığımız gibi bir komutu bir başkasına eşitlemekten farklıdır. Komutu bir başka kelimeyle kullanırken arada eşittir kullanıp parantezleri kaldırmıştık.
- Yeni tanımlamanın parçası olan tüm komutlar eşit miktarda içe girik yazılmışlardır. Eğer buna uymazsanız Python bir hata mesajı verecek ya da programınızda bir bug olacaktır. İçe girik derken kastettiğim her satırın başında belli miktarda boşluk bırakmaktır, genellikle dört boşluk bırakılır. Editör aşağıdaki şekilde olduğu gibi noktalı çizgileri 4'erli boşlukları gösterecek şekilde otomatik olarak yerleştirmeye ayarlanmıştır.
- def komutunun kullanıldığı satırın sonunda "`:`" vardır, bu bizim Python'a blok halinde kodlar yazacağımızı belirtir, içe girik yazdığımız komutlar bu bloğa aittirler. Bunu diğer bazı komutlarla da kullanırız örneğin daha sonra öğreneceğimiz if de olduğu gibi.

Bir defada oldukça fazla bilgi verdim. Anlayıp anlamadığınızı test etmek için iyi bir zaman.

### Sıra sizde

Aşağıdaki şartları sağlayan bir program yazınız:

1) Sağa dönüş komutunu tanımlayın 2) Bu yeni komutu kullanarak Reeborg'un daha önceden yaptığınız gibi saat yönünde kare şeklinde hareket etmesini sağlayın. Programınızın daha önceden yazdığınız programa göre daha kısa olduğuna ve daha kolay okunduğuna dikkat edin.

### Yine sıra sizde!

`step_back()`(geri adım) adında yeni bir komut tanımlayın.

    # step_back() yukarıda tanımlandı
    move()
    step_back()
    turn_off()

bu komut aşağıda gösterildiği gibi Reeborg'un bir adım ileri atmasını ve başladığı yere geri gelmesini ve yüzünün de başlangıç pozisyonundaki yöne dönük olmasını sağlasın.

İp ucu: Yeni tanımlamanızın parçası olan komutları içe girik yazmayı unutmayın.

### Tekrar sıra sizde!

`turn_around()`(geri dön) adında yeni bir komut tanımlayın. Böylece aşağıdaki tanımlamalar beklediğiniz gibi çalışabilsin.

    def step_back():
        turn_around()
        move()
        turn_around()

    def turn_right():
        turn_around()
        turn_left()

### Gazete dağıtımı tekrar ziyaret ediliyor

Bir önceki derste yaptığınız son alıştırmalardan bir tanesi gazete dağıtımı programıydı. Size hatırlatmak için Reeborg'un ne yaptığını aşağıdaki şekillerde gösteriyorum:

Çözümünüz muhtemelen aşağıdaki gibiydi:

    move()
    # climb step
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    # climb step
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    # climb step
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    # climb step
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    move()
    move()
    # put down newspaper and turn around
    put_beeper()
    turn_left()
    turn_left()
    # step down
    move()
    move()
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    # step down
    move()
    move()
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    # step down
    move()
    move()
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    # step down
    move()
    move()
    turn_left()
    move()
    turn_left()
    turn_left()
    turn_left()
    # move away and stop
    move()
    turn_off()

Bu çok uzun bir program ve pek çok tekrarlama var. Programın sonuna geldiğinizde programın başlangıcını ekranda göremiyorsunuz. Açıklamaların nasıl eklendiğine dikkat etmiş olmalısınız. Bu açıklamalar probleme çözüm getirirken nasıl düşündüğümüzü gösterir diyebiliriz:

- Dört basamak çık. Climb (up) four stairs.
- Gazeteyi bırak. Drop the newspaper.
- Geriye dön. Turn around
- Dört basamak in.Climb (down) four stairs.

Bunu Pythonic bir şekilde yazalım:

    climb_up_four_stairs()
    put_beeper()
    turn_around()
    climb_down_four_stairs()

Bu tam bir çözüm değil [örneğin `turn_off()` kullanılmamış] ancak çözüme oldukça yakın ve öncekilere göre okuması çok daha kolay, eğer yeni komutları tanımlanmış varsayarsak. Aşağıda ihtiyaç duyulan tanımlamaların bir kaçını verdik:

    def turn_around():
        turn_left()
        turn_left()

    def turn_right():
        turn_left()
        turn_left()
        turn_left()

    def climb_up_one_stair():
        turn_left()
        move()
        turn_right()
        move()
        move()

    def climb_up_four_stairs():
        climb_up_one_stair()
        climb_up_one_stair()
        climb_up_one_stair()
        climb_up_one_stair()

### Sıra sizde

Eksik olan tanımlamaları da yapın ve programınız yukarıda Pythonic şekilde verildiği gibi olsun. Bir kaç basit komut daha eklemeniz gerekecek, sonda `turn_off()` gibi. Programınızı farklı bir isimle kaydetmeyi unutmayın.

### Yine sıra sizde!

Yazdığınız programı bundan önce yazdığınız gazete dağıtma programıyla karşılaştırın. Okunması en kolay olan hangisi?

### Program okuma

İyi seçilmiş adlar bir programın ne iş yaptığını anlamakta çok yardımcı olurlar. Kötü seçilmiş adlar ise programın anlaşılmasını zorlaştırırlar. [Kural # 2'ye bakın.] Bilgisayar kullanmadan aşağıdaki programın ne yaptığını anlamaya çalışın.

    def a():
        turn_left()
        turn_left()

    def b():
        turn_left()
        a()

    def c():
        move()
        move()

    def d():
        c()
        b()

    def e():
        d()
        d()
        d()
        d()

    turn_left()
    e()
    b()
    turn_off()

`a(), b(), c(), d(),` ve `e()`yerine daha açıklayıcı adlar kullanmanın daha iyi olacağını anlamışsınızdır.``

Duvarları yapmak - - Tekrardan kaçının, tekrar!