Help us understand the problem. What is going on with this article?

D言語で書く "イケメンなコード" ~ 階乗をイケメンに書く ~

More than 3 years have passed since last update.

概要

D言語でイケメンに書く書くシリーズをやろうかなぁと思ったのでなんとなく投稿することにしました。

言うまでもないですが、コードに対する感覚は僕の個人的なものなので万人がこのコードをイケメンであると評価するとは思いません。

本題

さて、階乗のコードを書け!と言われると、どのように書きますか?

以下のようにいくつかの例が考えられますね。

1 ループ

T f(T)(T n){
  T s = 1;

  foreach(i; 1..1+n)
    s *= i;

  return s;
}

一番単純ですが、僕はこの実装は嫌いです。

2 再帰

T factorial(T)(T n){
  return n == 0 ? 1 : n * factorial(n - 1);
}

まぁ、普通の実装と言ったところでしょうか。

でも、再帰というと末尾再帰の方がいい気がしますよね?

3 末尾再帰

T factorial(T)(T n, T s = 1){
  return n == 0 ? s : factorial (n - 1, s * n);
}

これが末尾再帰です。

しかし、D言語だと次のようにもっとカッコよく記述できます。

rangeをmapしてreduceする

import std.range,
       std.algorithm;

T factorial(T)(T n){
  return n == 0 ? 1 : n.iota.map!"a+1".reduce!"a*b";
}

何をしているのか

iotaは0から第一引数にnが与えられた時に、0からn-1までのn個のrangeを返します。

つまり、こうなります

assert([0, 1, 2] == 3.iota.array);

それで、mapはrangeの各要素aに対して操作Fを行います。
ここではFはa+1となります、よってiotaで生成されたrangeの各要素aに対してそれぞれ1を加えた値を要素として持つ新しいrangeがmapにより作られます。
つまり、

assert([1, 2, 3] == 3.iota.map!"a+1".array);

その後、reduceですべての要素の積を求めます。
何故こうなるか、というとreduceはrangeと操作を受け取ります。
ざっくり説明すると、
aに与えられたrangeの各要素が順に入り、bにはそれまでの結果が入ります。
そしてそのa,bによる計算結果がbに代入されていく みたいなイメージです。
つまり、

  assert(6 == [1,2,3].reduce!"a+b");
  /*
    int b;
    foreach(a; [1,2,3]){
      b += a;
    }
    return b;
    みたいなイメージ
  */

よってこれらを組み合わせることで階乗が実装できます。

次回予告

次回は気が向いたらきますね

alpha_kai_NET
D/C/Ruby/Haskell/TypeScript GitHub: https://github.com/alphaKAI Twitter: https://twitter.com/alpha_kai_NET
http://alpha-kai-net.info
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした