Scribble at 2022-05-27 19:18:40 Last modified: 2022-05-29 23:16:31

Turns out that combining all those simple features in a way to do something useful can be tricky. How do you remove an item from an array in Ruby? list.delete_at(i). And remove entries by value? list.delete(value). Pretty easy, yeah?

Go is not an easy language

まだテキストを読み始めて1週間くらいしか経っていない人間が言うのも変な話だと思うが、僕は Go の配列について解説を初めて読んだときに、この融通の利かなさはどう考えてもわざとやっているようにしか思えなかった。つまり、Go の配列が要素を削ったり足したりできないのは、データを保護するためだろうと思う。そして、この理屈をアルゴリズムなりシステムの設計として徹底すれば、スライスやマップ(他の言語では "dictionary" とか "hash" とか言われる collection type のこと)ですら、杜撰に要素を増やしたり削ったりするべきではないのだろう。そもそも、配列を定義するときに要素の数を含めた特別な型として導入するという仕様をまじめに受け止めたら、Go のコア開発者の意図は明らかだろうと思う。

そもそも、配列だろうとスライスだろうと馬鹿みたいに大量のデータを格納したり、そこから要素を取り出したりセットするならまだしも、要素そのものを PHP で言えば array_pop() だの array_push() だのと増やしたり削ったりするという操作をしなくてはいけない正当な理由があるのかと思う。確かに、ディレクトリを走査してファイルのパスを配列へ次々と追加するときに、$array[] = PATH_TO_FILE として要素を後から増やすという操作はする。しかし、もちろんファイルがいくらでもあって良いなんて走査は馬鹿げているから、一定の制限は設けるのが当然だ。

これも、あくまでも僕が広告代理店の案件で携わってきたサイトやページで使うプログラムの設計という、かなり特殊な状況での経験で言っているにすぎない。それでも、その限りで言えば、配列のボリューム自体、つまり要素の総数を増やしたり減らしたりする必要なんてなかった。というより、配列として一つのデータのまとまりを扱うというのであれば、その要素の数を固定しておくことこそ、安全なプログラムを設計して運用するアイデアの一つであるように思う。正直、ウェブ・アプリケーションの開発という仕事に携わって20年くらいのあいだに、array_pop() とか array_push() なんて使ったことは1度か2度しか記憶にないし、おそらくだが現在の僕なら後ろから当時の自分の頭を張り倒しているような、「クズ」としか言いようがないコードを書いていたがゆえに使ったのだろうと思う。つまり、配列の要素の数を変えるようなコードを書く奴は、僕の感覚で言えば「クズ」なのだ。

基本に戻って話をすると、ここに処理するべきデータがあるとして(データベースにストアしてあるログとか、或るディレクトリに保存されたファイルとか)、その数が1,000個だとしよう。それら全てのデータについて何らかの処理が必要だとする。ここで考えるべきなのは、その処理が1回だけなのか、それとも何度か実行するのかという点だろう。データベースからデータを取り出す場合は、もちろん一時的に作業用に配列として作成したデータ・セットへデータを SQL で取得するというのがスタンダードな手続きとなっている。あるいは特定のディレクトリに保存されたファイルのパスを一時的に配列へ格納するという手続きも一般的だ。そして、配列へ格納するという手法を使うことで、格納するべき条件でデータを無暗に大量に扱うリスクを低減できるという考え方もあろう。もちろん、データベースから取り出す場合は最新の1,000件だけという条件を指定した上で配列に格納するし、ディレクトリからファイルのパスを取り出すときは、たとえば PHP では scandir() 関数の第二引数で並び替えの条件を指定して配列に格納することが多い。どちらにしても、無条件でデータを DBMS から取り出したり、あるいはディレクトリの中身を無制限に取り出すなんてことは、どう考えても危険なコーディングだからだ(ディレクトリの中に、何らかの事情で馬鹿みたいに大量にファイルが吐き出されていたり、何かの原因で破壊されたファイルが大量に入っていないという保証はない)。なんにしても、上記のような事情で配列を使うときは一定の条件、つまり配列として扱うデータの量を一定の数に制限するという条件のもとで配列を作成するに決まっているし、そうしないのはプロのエンジニアとはとても言えない。マシンに幾らでもメモリが積まれていて、配列として確保した膨大なデータを自由に扱える計算資源があるとしても、そのコストを考えないエンジニアというのは、単にプログラミング言語の書き方を覚えただけのペンギンや水牛でしかない。人間のやる「システム開発」ではない。

では、そうして作成した配列の要素数を後から増やしたり減らしたりする操作、それから既存の配列から要素を削除したり、逆に配列へ要素を追加する操作が、いったいどういう事情で正当化されるのだろう。僕には、もちろん僕はそんなコードを書く必要があるとは思えないので、想像するのは難しい。しかし、一つだけ想像できるとすれば、配列というものを、プログラムのプロセスが実行されている状況で暫定的に利用するデータベースのようなものだと考えているプログラマがいるということなのだろう。

しかし、たとえそういう理由で配列のインデックスそのものを削除したり増やすことがあるとしても、そんなことが果たして有益だろうか。既存の配列は、もちろん既存のリソースから取得したデータのひとまとまりである。そして、そこにプログラムを実行しているプロセスで新しく追加されたデータや、あるいは新しく削除されるべきデータがあるとして、それを最初に作成した配列に対して要素を追加したり削除したところで、そのあと最後の処理として何をすればよいだろうか。元のデータベースに、増やしたデータを反映させたいのであれば、どう考えても新しく増やしたデータを別の配列に格納しておき、そこに格納されたデータだけを INSERT した方が合理的だろう。あるいはデータベースから特定のデータを削除したいなら、それはデータベースに対して、どのデータを削除するべきかを指示する SQL を書くべきであって、〈配列からデータを削除することで、削除したデータがなんであるかをデータベースに教える〉なんて発想は、正直なところ少しプログラミングの勉強なり訓練をどこかでやった方がいいと思う。

  1. もっと新しいノート <<
  2. >> もっと古いノート

冒頭に戻る


※ 以下の SNS 共有ボタンは JavaScript を使っておらず、ボタンを押すまでは SNS サイトと全く通信しません。

Twitter Facebook