PythonのコードをC++98に移植して感じたこと。


Pythonでは簡潔に記述できる事でも、C++98では膨大なテンプレコードを書く必要があります。参考に(?)C++とPythonのコードを並べてみました。

一言でいうと「シンタックスシュガーと動的型付けってすばらしい」

（書きかけなので、今後項目が増えるかもしれません）

# その1 静的型付け/動的型付け

```c++
Point get_distance(const Point& point1, const Point& point2) {
  return sqrt( pow(point1.x - point2.x, 2) + pow(point1.y - point2.y, 2);
}
```

```python
def get_distance(point1, point2):
  pt1_x, pt1_y = point1
  pt2_x, pt2_y = point2
  return math.sqrt((pt1_x - pt2_x) ** 2, (pt1_y - pt2_y) ** 2)
```

C++:型に加えconst、*やら&、テンプレートといった修飾子などが煩わしい。（入出力が明示かされたり、コンパイル時の構文チェックは助かるけども・・・）
Python:動的型付けなので、型定義が不要。型は変数ではなく値が持つ.

# その２ リストとディクショナリ

```c++
vector<double> calculate(const vector<Line>& lines) {
  vector<double> result;
  vector<Line>::const_iterator ite = lines.begin();
  while( ite != lines.end() ) {
    double value = 何かする(*ite);
    result.push_back(value);
    ++ite;
  }
  return result;
}
```

```python
def calculate(lines):
  result = [] // []でリスト形式, {}だとディクショナリ.
  for line in lines:
    value = 何かする(line)
    result.append(value)
  return result
```

C++: C++98では、シンタックスシュガーなし（C++11はシンタックスシュガー有り）。

python: オブジェクトの生成、要素へのアクセス、ループにシンタックスシュガー有り。上のケースはリスト内包表記を使うとさらに簡潔に記述できる。

```python
def calculate(lines):
  result = [ 何かする(line) for line in lines]
  return result
```

# その３ タプル

```c++

void foo() {
  Point pt1(0,1);
  Point pt2(0,5);
  Line line(pt1, pt2);

  double score;
  double distance;
  calculate(line, &score, &distance); 
  ...
}

void calculate(const Line& line, double* out_score, double* out_distance) {
  *out_distance = get_distance(line.point1, line.point2);
  *out_score = get_score(line);
}

double get_distance(const Point& pt1, const Point& pt2) {...}

```

```python

def foo():
  pt1 = (0,1)
  pt2 = (0,5)
  line = (pt1, pt2)
  distance, score = caclculate(line)
  ...

def calculate(line):
  distance = get_distance(*line)
  score = get_score(line)
  return distance, score

def get_distance(pt1, pt2):
  ...

```

C++:値をまとめたいときは、汎用のpairを使うか、PointやLineのように構造体/クラスを定義する必要がある。これも構文チェックとのトレードオフ。

Python:タプルを使えば、ちょっとしたペアを引数に渡したいときに重宝します。使いすぎると、可読性が下がる。

# その４ ラムダ式

```c++
void foo(const Line& line, double x) {
  double y1 = func(line, x);
  double y2 = func(line, x+1);
}

// 直線line上のxに対応するy座標を求める.
// ※：y=1やx=0といった線は考慮しない.
double func(const Line& line, double x) {
   // 傾き取得
   double slope = get_slope(line.point1, line.point2);
   double const_value = get_const_value(line.point1, slope);
   double y = x * slope + c;
   return y;
}
```

```python

def foo(line, x):
  func = get_func(line)
  y1 = func(x)
  y2 = func(x + 1)

def get_func(line):
  slope = get_slope(*line)
  const_value = get_const_value(line[0], slope)
  return (lamda x: x * slope + c)

```

pythonではラムダ式が提供されているので、ちょっとした事が簡単に記述できるようになります。
C++ならクラスを書けば、再利用性は上がるけど書くための敷居が高い。


# その５ 関数呼び出し

タプルやリストを自動的に個別の引数に展開してくれたり、名前付き引数できたりと楽ができます。

例: C++の関数のオーバーロードを減らす。


```c++
doule get_distance(const Point& pt1, const Point pt2) {
   return //演算結果
}

double get_distance(const Line& line) {
  return get_distance(line.point1, line.point2);
}
```

```python
def get_distance(point1, point2):
  return ...

def foo(line):
  get_distance(*line) // lineがタプルかシーケンスなら、自動的にpoint1, point2に展開してくれる.
```