Swiftの文法を普段書いてる言語に置き換えてみた

## SwiftのコードをDartとTSに書き直してみた
普段は仕事で使っている言語は、DartとTypeScriptなのですが、最近SwiftとKotlinを覚えなくてはいけなくなったので、勉強してます。


`nil`を許容する`Optional`型のBool型の変数
```swift
import UIKit

var val: Optional<Bool>
val = true
val = nil

if let valCheck = val {
    print("実行\(val)")
} else if val == nil {
    print("val is nil")
} else {
    print("val has a value")
}
```

実行結果:
```bash
val is nil
```

これがDartだとnull許容のbool型の変数になる。!=だからelseの処理が実行される。

```dart
void main() {
  bool? val;
  val = true;
  val = null;

  if (val != null) {
    print("実行$val");
  } else {
    print("val is null");
  }
}
```

実行結果:
```bash
val is null
```

`guard let`を使った例。nilだとreturnする。

```swift
import UIKit

func say(value: String?) {
    // nilだとreturnする
    guard let value = value else {
        print("nilだよ!")
        return
    }
    print(value)
}

let arg: String? = nil
say(value: arg)
```

実行結果:
```bash
nilだよ!
```

Dartの場合だと`guard let`はないので、nullだったらreturnする処理を書くことになる。

```dart
void say(String? value) {
  // If null, return
  if (value == null) {
    print("nullだよ!");
    return;
  }
  print(value);
}

void main() {
  String? arg = null;
  say(arg);
}
```

実行結果:
```bash
nullだよ!
```

## functionを使う
関数を書く場合は->をつけたりと見慣れな記号が多い?

```swift
import UIKit

func say(a: String) -> String {
    return a
}

print(say(a: "こんにちは😄"))
```

Dartに書き直すとこうなります。JavaScriptやJavaの方が私はわかりやすいですね。

```dart
String say(String a) {
  return a;
}

void main() {
  print(say("こんにちは😄"));
}
```

TypeScriptの方がSwiftには似ているかもしれないです?
型をつける位置がそもそも変だ...

```ts
function say(a: string): string {
  return a;
}

console.log(say("こんにちは😄"));
```

## 配列を使う
関数に配列を引数として渡して、for文でループさせてみた。

```swift
import UIKit

func result(number: Array<Int>) -> Array<Int> {
    var resultArray = Array<Int>()
    for num in number {
        resultArray.append(num)
    }
    return resultArray
}

let number: Array<Int> = [1, 2, 3, 4, 5]
print(result(number: number))
```

実行結果:
```bash
[1, 2, 3, 4, 5]
```

DartでList<int>を使って同じように表現することができる。

```dart
List<int> result(List<int> numbers) {
  var resultArray = <int>[];
  for (var num in numbers) {
    resultArray.add(num);
  }
  return resultArray;
}

void main() {
  var numbers = [1, 2, 3, 4, 5];
  print(result(numbers));
}
```

実行結果:
```bash
[1, 2, 3, 4 5]
```

型を()の隣に書くのTypeScriptの方が比較対象としてはいいかもしれない?
実は私、普段はここまで型定義してないです笑

```ts
function result(numbers: number[]): number[] {
  let resultArray: number[] = [];
  for (let num of numbers) {
    resultArray.push(num);
  }
  return resultArray;
}

let numbers: number[] = [1, 2, 3, 4, 5];
console.log(result(numbers));
```

実行結果:
```bash
[1, 2, 3, 4, …]
0: 1
1: 2
2: 3
3: 4
4: 5
```

## 最後に
Swiftは書きやすくて良い言語だと聞きます。enumはDartより良いらしい?

例を出すとこんな感じですね。Github Copilotに聞いてみました。

Swiftのenumは非常に強力で、関連値やメソッドを持つことができます。これはDartのenumでは表現できません。以下に、関連値を持つenumを使用したSwiftのコード例を示します。
```swift
import UIKit

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

func printBarcode(_ barcode: Barcode) {
    switch barcode {
    case .upc(let numberSystem, let manufacturer, let product, let check):
        print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
    case .qrCode(let productCode):
        print("QR code: \(productCode)")
    }
}

let upcBarcode = Barcode.upc(8, 85909, 51226, 3)
let qrBarcode = Barcode.qrCode("ABCDEFGHIJKLMNOP")

printBarcode(upcBarcode)
printBarcode(qrBarcode)
```

実行結果:
```bash
UPC: 8, 85909, 51226, 3
QR code: ABCDEFGHIJKLMNOP
```

このコードでは、Barcodeというenumを定義し、その中に2つのケース（upcとqrCode）を定義しています。それぞれのケースは関連値を持っており、それぞれ異なる型の値を持つことができます。そして、printBarcode関数では、引数として受け取ったBarcodeの値に応じて異なる処理を行っています。

TSでも同じ処理をかけるらしい?
しかし、全然別物ですね。

```ts
abstract class Barcode {
  abstract print(): void;
}

class Upc extends Barcode {
  constructor(private numberSystem: number, private manufacturer: number, private product: number, private check: number) {
      super();
  }

  print() {
      console.log(`UPC: ${this.numberSystem}, ${this.manufacturer}, ${this.product}, ${this.check}`);
  }
}

class QrCode extends Barcode {
  constructor(private productCode: string) {
      super();
  }

  print() {
      console.log(`QR code: ${this.productCode}`);
  }
}

function printBarcode(barcode: Barcode) {
  barcode.print();
}

let upcBarcode = new Upc(8, 85909, 51226, 3);
let qrBarcode = new QrCode("ABCDEFGHIJKLMNOP");

printBarcode(upcBarcode);
printBarcode(qrBarcode);
```

コピーできなかったので、ブラウザで実行できるstackblitzのスクリーンショットを貼っておきます。
![スクリーンショット 2024-01-04 21.49.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/fbe0e459-9b35-892a-b4d7-327bcedb846f.png)