Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift #593

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

Swift #593

6 changes: 3 additions & 3 deletions java101/içerikler.md
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ public class PatikaDev {
```

1. Yukarıdaki programın çıktısı nedir ?
- Show Metodu... (Doğru)
- Show metodu... (Doğru)
- NULL
- Derleme Hatası Verir
- Hiçbiri olmaz
Expand Down Expand Up @@ -1027,7 +1027,7 @@ public class PatikaDev {
- Math.cos();

2. Java Math sınıfından 0 ile 100 arasında rastgele sayı üretmek için hangi komut kullanılır ?
- (int) (Math.random() * 100) (Doğru)
- (int) (Math.random() * 101) (Doğru)
- Math.random() * 100
- Math.random(100)
- Math.random() / 100
Expand All @@ -1042,4 +1042,4 @@ public class PatikaDev {

2. Java String sınıfına ait equals(); metodu iki string ifadeyi karşılaştırmak için kullanılır. Bu karşılaştırmada küçük büyük harf duyarı yoktur ?
- Doğru
- Yanlış (Doğru)
- Yanlış (Doğru)
21 changes: 7 additions & 14 deletions node-js/içerikler.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,11 @@
artık Javascript kodlarını çalıştırırken tarayıcıya bağımlı olmadığımızı gördük.
### [Node.js REPL Ortamı](NodejsREPL/)
#### Sorular
1. Node.JS çalışma ortamında "process.argv[1]" ifadesine ait konsol çıktısı ne olur?
- Node.js yazılımına ait dosya yolu.
- Çalıştırılan .js dosyasında kullanılacak 3. argüman.
- undefined
- null
- Çalıştırılan .js dosyasına ait dosya yolu. (Doğru)
2. "process" nesnesi için hangisi söylenemez?
- Global bir nesnedir.
- Kullanımı için "require()" zorunludur. (Doğru)
- Üzerinde çalışılan işlem ile ilgili bilgiler taşır.
- Node versiyon bilgisi taşır.
- Dosya yolu bilgisi taşır.
1. Aşağıdakilerden hangisi REPL çalışma ortamı için yanlış bir bilgidir?
- REPL, Read - Eval - Print - Loop birleşiminin kısaltılmış halidir.
- REPL, bize node.js tarafında Javascript kodlarını çalıştırmamıza olanak sağlayan bir komut sistemi sunar.
- Komut sisteminde ctrl+c, çalışan komutu durdurma kombinasyonudur.
- Komut sisteminde ctrl+d, REPL ortamını başlatma kombinasyonudur.
#### Video
1. (Youtube adresi yazılacak)
- Bu videoda; Node.js'in terminal ekranı olan REPL ortamı üzerine konuştuk. Nasıl kullanırız, kullanım avantajları ve dezavantajları nelerdir detaylıca bahsettik.
Expand Down Expand Up @@ -435,7 +428,7 @@ olan Compass kurulumu da yapıldı.
- remove
2. Aşağıdakilerden hangisi MongoDB özelliklerinden değildir?
- deleteOne
- decorator (Doğru)
- deleteMany (Doğru)
- insertOne
- find
- insertMany
Expand Down Expand Up @@ -694,7 +687,7 @@ dosyası oluşturuldu.

- req.body
- req.query
- req.true (Doğru)
- req.params (Doğru)
- req.id
- req.slug

Expand Down
3 changes: 1 addition & 2 deletions php/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@
- [Oturum(Session) İşlemleri](session/)
- [Çerez(Cookie) İşlemleri](cookie/)
- [Pratik - Login Uygulaması](login-pratik/)
- [Oturum Çerez Yönetimi Ödev 1](oturum-cerez-yonetimi-odev-1/)
- [Oturum Çerez Yönetimi Ödev 2](oturum-cerez-yonetimi-odev-2/)


#### Tarih ve Zaman İşlemleri ####
- [Tarih ve Zaman İşlemleri](tarih-ve-zaman-islemleri/)
Expand Down
2 changes: 1 addition & 1 deletion react-native/içerikler.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ State nedir?
State’e neden ihtiyaç duyarız?
- Component’te yenileme işlemi state güncellemesi ile yapılabilir (Doğru)
- Component’te sadece state ile veri tanımlanabilir
- State’ler performans için kullanışsızdır.
- State’ler performans için daha kullanışlıdır
- State tanımlamadan bir component kullanılamaz

Aşağıdakilerden hangisi state tanımlamasıdır?
Expand Down
28 changes: 28 additions & 0 deletions swift/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,32 @@
- [Listeden Eleman Silme ve Düzenleme](list-app-remove-edit)
- [CoreData ile Verilerin Yerel Hafızaya Kayıt Edilmesi](list-app-coredata)

#### 6. Bölüm: Swift İleri Seviye ####
- [Closures](swift-advance-closures)
- [Struct ve Class](swift-advance-struct-class)
- [Erişim Denetimi](swift-advance-access-level)
- [Protokoller](swift-advance-protocol)
- [Extensionlar](swift-advance-extension)
- [Optional Yapısı](swift-advance-optional)
- [ Swift Dil Yazım Standartları](swift-advance-standards)

#### 7. Bölüm: Üçüncü Parti Kütüphaneler ####
- [Cocoapods](third-party-libraries-cocoapods)
- [Alamofire](third-party-libraries-alamofire)
- [SnapKit](third-party-libraries-snapkit)
- [KingFisher](third-party-libraries-kingfisher)
- [Flex](third-party-libraries-flex)
- [IQKeyboardManager](third-party-libraries-iqkeyboardmanager)
- [SwiftGen](third-party-libraries-swiftgen)
- [SwiftLint](third-party-libraries-swiftlint)

#### 8. Bölüm: İkinci Proje - Flickr Uygulaması ####
- [Proje Oluşturma ve Giriş](flickr-app-intro)
- [Uygulama Arayüzünün Oluşturulması](flickr-app-ui)
- [Flickr API Nedir ve Nasıl Kullanılır?](flickr-app-api)
- [Network Request ve Codable Yapısı](flickr-app-request-and-codable)
- [Arayüzün Sunucudan Gelen Data İle Doldurulması](flickr-app-show-data)
- [CocoaPods Kurulumu](flickr-app-cocoapods)
- [SnapKit İle Kodlayarak Arayüz Oluşturma](flickr-app-snapkit)
- [Moya ile Network Katmanının Oluşturulması](flickr-app-moya)
- [Son Ayarlar ve Değerlendirme](flickr-app-final)
1 change: 1 addition & 0 deletions swift/flickr-app-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Flickr API Nedir ve Nasıl Kullanılır?
1 change: 1 addition & 0 deletions swift/flickr-app-cocoapods/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# CocoaPods Kurulumu
1 change: 1 addition & 0 deletions swift/flickr-app-final/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Son Ayarlar ve Değerlendirme
1 change: 1 addition & 0 deletions swift/flickr-app-intro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Proje Oluşturma ve Giriş
1 change: 1 addition & 0 deletions swift/flickr-app-moya/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Moya ile Network Katmanının Oluşturulması
1 change: 1 addition & 0 deletions swift/flickr-app-request-and-codable/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Network Request ve Codable Yapısı
1 change: 1 addition & 0 deletions swift/flickr-app-show-data/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Arayüzün Sunucudan Gelen Data İle Doldurulması
1 change: 1 addition & 0 deletions swift/flickr-app-snapkit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# SnapKit İle Kodlayarak Arayüz Oluşturma
1 change: 1 addition & 0 deletions swift/flickr-app-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Uygulama Arayüzünün Oluşturulması
4 changes: 2 additions & 2 deletions swift/setup-needs-tech-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ Swift tek başına iOS uygulamaları geliştirmemiz için yeterli değil. Bu ned
### 3. Üçüncü Parti Kütüphaneler*
Üçüncü parti kütüphaneler, Apple kütüphanelerinde var olan bir yapıyı daha kolay kullanmamızı ya da Apple kütüphanelerinde yer verilmeyen özellikleri bize sağlıyor. Bu nedenle üçüncü parti kütüphanelere de sıklıkla başvuracağız.

### 4. Paket Yönetim Sistemleri*
### 4. Paket Yönetim Sistemleri*
Projemize eklediğimiz üçüncü parti kütüphanelerin yönetimi, kütüphane sayısı arttıkça zorlaşıyor. Paket yöneticisi bu zorluğu geliştiriciden devralarak kolay şekilde yönetim olanakları sunuyor. Paket yöneticiler de sektörde sıklıkla kullanıldığı için eğitimde çokça yer vereceğiz.

Eğitim süresince, sektörde sıklıkla kullanılan paket yöneticisini Cocoapods'u kullanacağız. Diğer paket yöneticilerine de değineceğiz. Cocoapods içinde yer alan paketleri cocopods.org adresinden inceleyebilirsiniz.

Cocoapods Link: <a href="https://cocoapods.org">Cocoapods</a>

### 5. Versiyon Kontrol Sistemleri*
###  5. Versiyon Kontrol Sistemleri*
Versiyon kontrol adından da anlaşılabileceği gibi projemizi versiyon versiyon kaydetmemizi, bu versiyonlar arasında kolayca geçebilmemizi, birden çok geliştiricinin çalıştığı projelerde sorunsuz bir şekilde versiyonların birleştirilmesini sağlayan araçlardır. En popüler olanı GIT versiyon kontrol sistemidir. Biz de eğitim süresince GIT versiyon kontrolünü kullanacağız.

GIT Link: <a href="https://git-scm.com">GIT</a>
Expand Down
53 changes: 53 additions & 0 deletions swift/swift-advance-access-level/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Erişim Denetimi

Swift beş farklı erişim denetim düzeyi sağlıyor.

* <b>Open ve Public Erişim Denetimi: </b> Proje modülü içinde veya bu modül dışında yer alan herhangi bir kaynak dosya bu varlıklara erişebilir. Bir kütüphane geliştirirken sıklıkla bu erişim denetim metodlarını tercih edersiniz.
* <b>Internal Erişim Denetimi: </b> Proje modülü içinde yer alan kaynak dosyalar bu varlılara erişebilirken, modül dışında kalan kaynak dosyalar erişemez. Bir uygulama geliştirirken dışarıya açık olması gerekmeyen varlıklar bu erişim denetimi ile tanımlanır.
* <b>File-private Erişim Denetimi: </b> Kaynak dosya içinde yer alan varlıklar birbirine erişebilir. Kaynak dosya dışında kalan varlıkların erişimi engellenir. Kaynak dosya için gerekli fakat dışında kalan kısımlar için gereksiz olan yapılar bu erişim denetim metodu ile dış erişime kapatılır.
* <b>Private Erişim Denetimi: </b> Bu erişim denetimine sahip varlıklar, yalnızca bulunduğu blok içinde erişime açıktır. Varlık içinde kalan yapılar bu erişim denetimi ile dışarıdan müdahaleleri engeller.

Open erişime en açık denetimi sağlarken, private erişimi en çok kısıtlayan erişim denetim metodudur.

Open, sadece Class ve Class'a ait öğeler için geçerli bir erişim denetim metodudur. Public erişimden farklı olarak, Subclass'ın miras aldığı öğeleri gerçersiz kılmasına(override) izin verir. Bir Class'ı, Open erişim denetimi ile tanımladıysanız, bu sınıfan türeyecek alt sınıfların koda etkisini düşünerek Class'ın iç yapısını oluşturduğunuz anlamına gelir.

### Erişim Denetiminin Yol Gösterici İlkeleri

Bir varlık, daha kısıtlı bir erişim sağlayan diğer bir varlık tarafından tanımlanamaz. Örneğin;

* Public erişim denetimine sahip bir değişken, Internal, File-private veya Private bir yapı içinde tanımlanamaz. Çünkü bu yapılar değişken için erişilebilir olmayabilir.
* Bir fonksiyon, parametre ve dönüş tipinden daha kısıtlı bir erişim seviyesinde olamaz. Çünkü fonksiyon çağrısında parametre erişim dışı kalabilir ve bu durum fonksiyonun işlevini olumsuz etkileyebilir.

Swift, istisnalar dışında, varsayılan erişim denetimi olarak, Internal erişim denetimini kullanır.

### Erişim Kontrolü Yazım Kuralları

Aşağıda çeşitli erişim denetimine sahip tanımlamaları görebilirsiniz.

```
public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}
```

Eğer tanım öncesinde bir erişim denetimi belirtilmezse, tanımlanan varlık Internal erişim denetimine sahip olarak tanımlanmış olur. Örneğin aşağıdaki tanımlar bir ön ek almasa da Internal erişim denetimine sahiptir.

```
class SomeInternalClass {}
let someInternalConstant = 0
```

Her varlık aksi belirtilmediği sürece içinde bulunduğu kod bloğunun erişim denetimini alır. File-private bir Class içinde yer alan özelliklerde File-private erişim düzeyinde olacaktır.

```
fileprivate class SomeFilePrivateClass {
func someFilePrivateMethod() {} // Bu metod belirtilmesede içinde bulunduğu kod bloğu sebebiyle fileprivate erişim düzeyindedir.
private func somePrivateMethod() {}
}
```
114 changes: 114 additions & 0 deletions swift/swift-advance-closures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Closures

Closure'ı çoğunlukla isimsiz fonksiyonlar olarak tanımlayabiliriz. Bu fonksiyonları bir değişken veya sabit gibi tanımlayıp, kod içerisinde istediğimiz bir noktada çağırabiliriz. C ve Objective-C'de yer alan blocks veya diğer dillerde yer alan lambda fonksiyon yapısına benzer şekilde çalışırlar.

Closure, çoğunlukla bir değişkendeki değer değişikliği veya bir olayın(Örn. bir butona dokunulması durumu vb.) yakalanması için kullanılır. Bir diğer sık kullanım şekli ise, bir kod bloğu çalıştıktan sonra gerçekleştirilmesini istediğimiz işlemleri belirtebileceğimiz bir araya girme olanağı sağlamasıdır. Örneğin bir animasyon son bulduğunda yapılması gereken işlemleri closure içinde tanımlayabiliriz. Teoride karmaşık gelsede kullanım şekilleri oldukça basittir.

Closurelar üç farklı biçimde tanımlanabilir:

- Mevcut kod bloğu içerisinde global olarak tanımladığımız closure yapısı. Çağırabilmemiz için bir isim alırlar. Çeşitli parametreler alabilir ve geri dönüş tipi olabilir.
- Bir fonksiyon parametresi olarak tanımladığımız, belirli bir noktada araya girmek için kulladığımız closure yapısı. İsim ve parametre alabilir, geri dönüş tipi olabilir.
- Bir nesne üstünde işlem yapmamızı sağlayan closure yapısı. İsimsizdirler fakat üstünde işlem yapılan nesneye göre bazı parametreleri ve geri dönüş tipleri olabilir. Parametrelere isim verilebildiği gibi $0, $1 ... $n şeklinde index numarası ile de paramtreye erişim sağlanabilir.

### Global Closure Yapısı

Mevcut kod bloğu içinde bir değişken veya sabit tanımlar gibi closure tanımı yapabiliriz. Aşağıda parametre almayan ve değer döndürmeyen closureExample adında bir closure tanımı yapıldığı görülebilir.
```
var closureExample: () -> Void = {
print("Closure Example")
}
```

Closure çağrıldığında yapılacak işlem, tıpkı bir fonksiyonda olduğu gibi, süslü parantezler ile oluşturulan kod bloğu içinde yapılacaktır. Bu closure tanımını, bir butona dokunulduğunda aşağıdaki gibi çağırabiliriz.

```
@IBAction func didTapButton(_ sender: UIButton) {
print("Button Tapped!")
closureExample()
}
```

Eğer didTapButton metodu, bir butona ait touchUpInside event ile bağlanırsa, butona dokunulduğunda terminal ekranına önce 'Button Tapped!' sonrasında ise alt satıra 'Closure Example' yazdırıldığı görülebilir. Eğer closureExample print öncesinde çağrılsaydı terminal ekranında yazıların yer değiştirdiğini görebilirdik.

Closure çağrıları sırayla işlenen kod bloklarında çok anlam taşımasa da internet çağrıları gibi servisten cevap beklediğimiz durumlarda, 'cevap döndüğünde şu işi yap' gibi komutları kolayca verebilmemizi sağladığında, daha bir anlam kazanır. Bu örnekte closure ile bir butonun touchUpInside durumunu yakaladık.

Bir değişkenin değer değişimini yakalamak için ise aşağıdaki closure kullanımını inceleyebilirsiniz.

```
var counter: Int = 0 {
didSet {
didIncreaseCounter(counter)
}
}

var didIncreaseCounter: (Int) -> Void = { increasedCounter in
print("Counter increased! Last value of counter variable is \(increasedCounter).")
}

@IBAction func didTapIncreaseCounterButton(_ sender: UIButton) {
counter += 1
}
```

Yukarıdaki örnekte counter değişkeninin didSet durumunda didIncreaseCounter closure yapısı çağrıldı. counter değişkenine yapılan her atamada didIncreaseCounter closure yapısı tetiklenir.

### Fonksiyon İçinde Closure Yapısı

Aşağıda bir internet çağırısı içinde closure kullanımına örnek verilmiştir.

```
func fetchData(withURL url: URL, completion: @escaping (Error?) -> Void) {
URLSession.shared.dataTask(with: url) {(data, response, error) in
if let error = error {
completion(error)
}
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
completion(nil)
}.resume()
}
```

Burada daha önce görmediğiniz pek çok yapı olabilir. Bunlara ileriki derslerimizde değineceğiz. Sadece fonksiyonun bir parametresi olan completion isimli closure tanımı ve fonksiyon içinde kullanımını dikkate almanız yeterli olacaktır.

Eğer bir closure yapısını başka bir closure içinde çağıracaksanız, tanımın başına @escaping ön ekini eklemeniz gerekiyor. Bu ön ek, tanımladığımız closure yapısını başka bir closure kapanmadan çağıracağız anlamına geliyor. Swift bu ön eki gördüğünde arka planda gerçekleşen işlemleri performans açısından optimize eder ve olası bellek kaçaklarını önler.

Bu kısım çok karmaşık gelmiş olabilir fakat zaten bu ön ek arkaplanda birtakım işlemlerin optimize edilmesini Swift diline bildirmek amaçlı eklenir. Yani sizi bu ön eki ezbere bir şekilde, başka bir closure içinde, bir fonksiyon parametresi olarak, tanımladığınız closure'ı çağıracaksanız (ki bu Swift içinde gerçekleşen Async işlemlerde sıklıkla kullanılan bir kalıptır. Sıklıkla kullanacaksınız ve yapı o zaman kafanızda daha iyi oturacaktır.) @escaping ön ekini closure tanımına ekliyoruz.

Aşağıda bu fonksiyonun bir viewDidLoad metodu içinde çağrımını görebilirsiniz.

```
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://www.your-url.com")!
fetchData(withURL: url) { error in
if let error = error {
print(error)
return
}
print("Successful response.")
}
}
```

### Nesne Üstüne İşlem Yapan Closure Yapısı

Çoğunlukla dizi ve sözlük gibi birden çok elemana sahip yapılar üstünde işlem yapmak için kullandığımız closure yapısıdır. Bu closurelar üstünde işlem yapılacak nesnenin bir veya birden çok elemanını parametre olarak alır ve eğer gerekiyorsa bir geri dönüş tipi de içerebilir. Örneğin tam sayı bir dizi üstünde map ile dizinin her bir elemanını bir artıralım.

```
var intArray = [0, 3, 1, 5, 103, 7, 7, 8, 1, 11, 4, 24]

var sortedIntArray = intArray.sorted { firstItem, secondItem in
firstItem < secondItem
}

print(sortedIntArray)
```

Yukarıdaki örnekte, elemanları rastgele bir şekilde sıralanmış intArray adındaki dizinin elemanları sorted metodu ile küçükten büyüğe sıralanmıştır. Eğer sorted metodunun tanımını açarsak bir closure olarak tanımlandığını net bir şekilde görebiliriz.

```
@inlinable public func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
```

Bu tarz metodlara önceki derslerimizde değinmiştik. Yeri geldiğinde bu metodların kullanımına değineceğiz.
48 changes: 48 additions & 0 deletions swift/swift-advance-extension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Extension

Extension, var olan Class, Struct, Enum veya Protocol yapısına yeni özellikler veya metodlar eklemek için kullanıyoruz. Bu sayede kaynağına erişimin kısıtlı olduğu varlıklara kolayca yeni özellikler ve metodlar ekleyebilirsiniz. Extension yapısı Objective-C'de yer alan Categories yapısına benziyor. Categories'den farklı olarak Swift Extension yapısı bir isim almıyor.

Extension ile yapabileceğiniz eklemeler aşağıdaki gibidir.

* Özellik eklemek
* Metod eklemek
* Başlatıcı(Initializer) eklemek
* Tanımlı bir protokolü sağlayacak şekilde eklemeler yapmak

### Extension Sözdizimi

Extension ile var olan bir varlığa ekleme yapmak istiyorsak, extension anahtar kelimesinden sonra ekleme yapmak istediğimiz varlığın adını yazmamız ve devamında açtığımız süslü parantezler içine eklemek istediğimiz tanımları yapmamız yeterli olacaktır.

```
extension SomeType {
// Yeni özellik veya metodlar buraya gelecek.
}
```

Hali hazırda var olan bir varlığın, bir protokolü sağlamasını istiyorsak, varlığın adından sonra iki nokta koyup devamında sağlamasını istediğimiz protokol(ler) belirtilmelidir. Protokolün beklediği özellik ve metod tanımları extension bloğu içinde yapılabilir.

```
extension SomeType: SomeProtocol, AnotherProtocol {
// Protokolün beklediği özellik ve metod tanımları buraya eklenebilir.
}
```

### Hesaplanmış Özellikler

Extension bloğu içinde, varlığın kendi bloğunda olduğu gibi özgürce özellik tanımlaması yapamıyoruz. <b>Hesaplanmış Özellikler(Computed Properties)</b> adı verilen, geriye ne döndüreceği önceden bilinen özelliklerdir. Aşağıda Double veri tipi için, uzunluk bilgisi döndüren hesaplanmış özellikler tanımlanmıştır.

```
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
print("Bir inç \(oneInch) metredir.")
// Çıktı: "Bir inç 0.0254 metredir."
let threeFeet = 3.ft
print("Üç feet \(threeFeet) metredir.")
// Çıktı: "Üç feet 0.914399970739201 metredir."
```
Loading