ESM アジャイル事業部 開発者ブログ

永和システムマネジメント アジャイル事業部の開発者ブログです。

いつもと違うプログラミングの風景を見に行く

昨年、「プログラミング多言語主義」という記事を書きました。

それを踏まえて。 ふだんと違うプログラミング言語を使ったとき、実際にどんな風景が見えるのか、それ見に行こう… というのが、今回の記事の表のテーマです。

先に弁明をしておくと。 今回書くコードは「いつもと違う風景を見る」ことに重心を置いていて、効率とかは脇によけてあります。 その点はご容赦を。

どう書く?:すべての順列を生成するプログラム

早速ですが、一連の要素の順番を入れ替えてできる並びをすべて挙げる例を考えてみましょう。

例えば

(1, 2, 3)

という入力に対して、

(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)

という出力をえる、というものです。

Rubyで書いたばあいであれば、このような結果になると想像してください。

perm([1, 2, 3])
# => [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]]

あるいはイテレータで、

perm([1, 2, 3]) do |output|
  p output
end
# [1, 2, 3]
# [1, 3, 2]
# [2, 1, 3]
# [2, 3, 1]
# [3, 1, 2]
# [3, 2, 1]

Thinking Time

お時間のある方はここで立ち止まって、自分ならどんなコードを書くか、想像してみてください…。

順列を定義する

さて、ここではふだん触れられることの少ない言語を使って順列を定義してみたいと思います。

Prologです。

ふだんあまり使われない言語(たぶん)、Prolog

Prologプログラミングは、ふだん手続的なプログラミングをしている人にとっては、視点の転換をしいてくる面白い言語です。 いつもと違う視点のプログラミングをしてみる例として、今回はPrologで実装していきたいと思います。

Prologを紹介した書籍としては「7つの言語 7つの世界」が割と有名です。 わたしもこの本で関心を持った一人です。

気付くと邦訳が出てから十年になるんですね。

Prolog利用者人口をわたしも把握しているわけではありませんが、周囲を見るかぎり使用している人を見かけません。 そこであえて、Prologを使ってコードを書いてみたいと思います。 はい、わたしの趣味です。

なお今回のコードは、2つの処理系 GNU PrologSWI-Prolog で動作を確認しています。

思考の準備運動

まずはじめに、Prologプログラミングの面白いところを append という述語を例に説明してみたいと思います。 この append はとても使い出がある述語で、この後の実装でも利用する予定です。

「述語」という言葉を使いましたが、Prolog は、関数(function)やメソッド(method)でなく、述語(predicate)でプログラムを書きます。 述語とは入力に対して真偽を返すものです。

append は3つの引数を受け取り、第1引数のリストに第2引数のリストを連結したリストが第3引数のリストであるばあいに真を返します。

実際に処理系を起動して動きを見てみましょう。

GNU Prologの例:

$ gprolog # GNU Prolog を起動
| ?- append([1, 2], [3, 4], [1, 2, 3, 4]).
yes

SWI-Prolog の例:

$ swipl # SWI-Prolog を起動
?- append([1, 2], [3, 4], [1, 2, 3, 4]).
true.

GNU Prologでは真偽を yes, no で返し、SWI Prologでは true, false で返すという違いはありますが、どちらも同じように真を返しています(以降はGNU Prologを使います)。

Prologは、ここが面白いところですが、述語の引数の一部を変数にすると、結果が真になるような値をその変数に割り当てて返してくれます。

例えば、第3引数を変数にすると次のようになります。 ちなみに Prolog では変数名は大文字から書き始めるルールになっていて、ここでは L が変数になります。

| ?- append([1, 2], [3, 4], L).
L = [1,2,3,4]

式が真になるために必要な値が、変数 L に割り当てられました。

これは第1引数を変数にしても、第2引数を変数にしても同じです。

| ?- append([1, 2], L, [1, 2, 3, 4]).
L = [3,4]
| ?- append(L, [3, 4], [1, 2, 3, 4]).
L = [1,2]

第1引数と第2引数の両方を変数にすると、他のプログラミング言語ではあまり見かけない結果を返してくれます。

| ?- append(L1, L2, [1, 2, 3, 4]).
L1 = []
L2 = [1,2,3,4] ?

まず、[][1, 2, 3, 4] を追加すると [1, 2, 3, 4] になるので、結果が真になる値の組み合わせです。

結果を表示した後は入力待ちの状態になっているので、ここでセミコロン ( ; ) を入力します。

| ?- append(L1, L2, [1, 2, 3, 4]).
L1 = []
L2 = [1,2,3,4] ? ;

L1 = [1]
L2 = [2,3,4] ?

[1][2, 3, 4] の組み合わせが表示されます。 これも式が真になる値の組み合わせです。

このように真になる値が複数あるばあいに、すべての結果を出力してくれます。 セミコロンは他の値の出力を促す入力になっています。

他にも組み合わせがあるので、何回かセミコロンを入力してましょう。

| ?- append(L1, L2, [1, 2, 3, 4]).
L1 = []
L2 = [1,2,3,4] ? ;

L1 = [1]
L2 = [2,3,4] ? ;

L1 = [1,2]
L2 = [3,4] ? ;

L1 = [1,2,3]
L2 = [4] ? ;

L1 = [1,2,3,4]
L2 = []

とりうる値のすべての組み合わせが出力されると、ようやく通常のプロンプトに戻りました。

Prolog自体の詳細は、先に紹介した「7つの言語 7つの世界」やドキュメントを参照してみてください。

これらを踏まえて。 ようやく順列をえる述語 perm を実装します。

順列の Prolog での実装

% agile-dev-blog.pro

perm([], []).                           % 空のばあい
perm([Head | Tail], Output) :-          % 第1引数を Head と Tail に分割
  perm(Tail, Partial),                  % Partial は Tail の順列であり、
  append(Left, Right, Partial),         % Partial は Left と Right から成り、
  append(Left, [Head | Right], Output). % Output は、その Left と Right の間に Head を置いたもの

このコードは agile-dev-blog.pro というファイル名のファイルに保存しておいてください。

[Head | Tail] という記述は、リストを先頭の要素と後続のリストにわけて表現したものです。

| ?- [1, 2, 3] == [1 | [2, 3]].
yes

先頭の複数の要素については次のように書くこともできます。

| ?- [1, 2, 3, 4] == [1, 2 | [3, 4]].
yes

| ?- [1, 2 | [3, 4]] == [1 | [2 | [3, 4]]].
yes

では実行してみましょう。

GNU Prologでのばあいは次のようにファイルを読み込みます。

$ gprolog --consult-file agile-dev-blog.pro

SWI-Prologのばあいは次のようになります。

$ swipl -f agile-dev-blog.pro

起動してファイルの読み込みが完了するとプロンプトが表示されれますので、次のように入力します。

| ?- perm([1, 2, 3], Output).

今回実装した perm も、先ほどの append のばあいと同じように、変数がとりうる値は複数あるので、セミコロンを入力して残りを表示しましょう。

| ?- perm([1, 2, 3], Output).
Output = [1,2,3] ? ;
Output = [2,1,3] ? ;
Output = [2,3,1] ? ;
Output = [1,3,2] ? ;
Output = [3,1,2] ? ;
Output = [3,2,1]

いかがでしょう?。 コードも動きも見慣れない、不思議な印象を受けたのではないでしょうか。

ふだんプログラミングをするとき、多くのばあいで「問題を『どのように』解くか」と、手順を考えると思います。

一方Prologプログラミングでは「問題に対して解は『どうあるべき』なのか」と考えることが求められれます。 脳のふだん使わない部分を、がんばって稼働させる感覚さえしてきます。

どう書く?:ソートプログラム

これで順列をえる手段を入手することができました。

これを利用して、今度はソートを考えてみたいと思います。

Thinking Time

お時間のある方はここで立ち止まって、自分ならどんなコードを書くか、想像してみてください…。

Prolog でなく、先ほどの Thinking Time で想像したご自身のコードをもとに考えてもらって大丈夫です…。

ソートを定義する

ソートのアルゴリズムは多々ありますが、いざソートを定義しようとすると、その手順が頭に浮かんでしまいます。

その思いをふりはらい、入力と出力に注目してみます。

入力: [5, 1, 4, 2, 3]

出力: [1, 2, 3, 4, 5]

ここまでの話の流れをふまえて。 入力と出力をじっと見てみると。 出力は「入力の要素を並べ替えてできる列のうち、隣り合うどの2つの要素を取り出しても、左の要素が右の要素以下であるもの」という見方も見えてきませんか?

ソートの Prolog での実装

そのような見方をPrologのコードにしてみましょう。

% agiile-dev-blog.pro

perm([], []).
perm([N | Rest], Perm) :-
  perm(Rest, Partial),
  append(Left, Right, Partial),
  append(Left, [N | Right], Perm).

my_sort(Input, Output) :- % ※ 組み込みの述語 sort と名前が衝突しないようにしています
  perm(Input, Output),             % 順列のうち、
  forall(                          % すべての、
    append(_, [N, M | _], Output), % 出力内の、隣接する要素は、
    N =< M                         % 左の要素が右の要素以下である
  ).

起動してファイルを読み込ませて実行してみます。

| ?- my_sort([5, 1, 4, 2, 3], L).
L = [1,2,3,4,5] ?

結果が出力されました。 が、入力待ちになっています。

これは見つけた結果以外で条件に合うものが残りの中にある可能性があるためです。 この入力では1つだけですが、重複した要素があるばあいにそれぞれを別の要素として扱っているので、それぞれの順序が結果として出力されます。

| ?- my_sort([2, 1, 1], L).
L = [1,1,2] ? ;
L = [1,1,2]

このようなばあい、Prolog のプログラミングの手法として、条件に合う結果がえられたら探索の打ち切りを指示することができます。

my_sort(Input, Output) :-
  perm(Input, Output),
  forall(
    append(_, [N, M | _], Output),
    N =< M
  ),
  !. % 条件に合致したら探索を打ち切る
| ?- my_sort([2, 1, 1], L).
L = [1,1,2]

最初に見つかった結果だけが出力されるようになりました。

どこかで見覚えがありません?

プログラミングとしては、見慣れないコードだったかと思いますが、ここ感じどこかで覚えがありませんか?

ある集まりから、条件に合う結果を出力する。

Ruby on Railsプログラマでしたらよくご存知の、SQLがそれですね。 SQLを書くことは、条件を組み合わせてDBに格納されているデータから欲しいデータを取得する、プログラムを書いていることでもあるわけです。

SQLは、実際にデータ検索以外の問題を解くこともできます(これとかこれとかこれとか)。 ですが、あまり無茶をなさらぬよう…。

まとめ:いつもと違う風景を見に行く

ある問題を解くアルゴリズムが複数あることからもわかるように、複数の解法があることが一般的です。

一方で、解法に注目するのでなく、ここでPrologで書いたように、結果に注目して問題に取り組むという方法もあるわけです。

複雑化する問題に頭を抱えたとき、この記事が「そもそも問題はなんだっけ?」「欲しいものはなんだっけ?」という気付きの一助になれば幸いです。


「情報化技術を通じて社会と共生する」株式会社永和システムマネジメント アジャイル事業部では、エンジニアを絶賛募集しています。 応募エントリお待ちしております! 一緒にいつもと違う風景を見に行きませんか? 応募エントリお待ちしております!

agile.esm.co.jp

Rails / OSS パッチ会オンライン 2021年10月のお知らせ

2021年10月の Rails / OSS パッチ会を 10月28日(木)にオンライン開催します。

この会をひとことでいうと、日頃のお仕事で使っている Rails をはじめとする OSS への upstream にパッチを送る会です。

会には Ruby と Rails のコミッターである顧問の a_matsuda もいますので、例えば Rails に送るパッチのネタがあるけれど、パッチを送るに適しているかの判断やパッチを送る流れが悩ましいときなど a_matsuda に相談して足がかりにするなどできます。

開催時間は 17:00-19:00 となりますがご都合のあう方はぜひご参加下さい。Zoom あたりのテレビ会議システムを使います。

当日の招待 URL は Idobata の esminc/rails ルームで共有する予定です。

idobata.io

特に募集ページなど設けませんが、上記理由からすでに Idobata のアカウントを持っている方は、当日の案内を Idobata にてご確認ください。 また Idobata はクローズ化されているため Idobata アカウントを持っていない参加希望の方は、@koic までメンションしてください。

パッチ会では、来月開催の RubyConf 2021 に関する話題などあるかもしれません。

rubyconf.org

Hacktoberfest への活動の場としてもご活用ください。

hacktoberfest.digitalocean.com

その他の開催方針については以下の Gist に記していますので、ご参照ください。

Reboot Rails/OSS meetup online · GitHub

『Kaigi on Rails 2021』に Gold スポンサーとして協賛します

いよいよ今週末の22日(金)、23日(土)の2日間、 Kaigi on Rails 2021 が開催されます。

kaigionrails.org

永和システムマネジメントでは、 Gold スポンサーとして支援させていただいています。 当日は会場内に作られるスポンサーブースエリアにも出展します。 すべての時間というわけではないですが、多くの時間に当社のエンジニアや、事業部長の平田がブースに入って、皆様とお話できることを楽しみにしています。講演の合間などにぜひお気軽にブースにお立ち寄りください。 講演についての感想、当社の事業の紹介、興味のある技術等、話題は何でも歓迎です。

スポンサーブース

また RuboCop コミッターの koic も参加していますので、御用命のときはその時ブースにいる当社メンバーまでお声掛けください。

参加者の皆さんで Kaigi on Rails 2021 を盛り上げましょう!


株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

『中高生国際Rubyプログラミングコンテスト in Mitaka』をシルバースポンサーとして協賛します

これからの社会を担っていくことになる世代に向けての Ruby プログラミングコンテストである『中高生国際Rubyプログラミングコンテスト in Mitaka』をシルバースポンサーとして協賛します。

www.ruby-procon.net

アジャイルと Ruby が実現するソフトウェア開発は、開発者が「楽しさ」を感じられる開発であり、そこにはきっとビジネス価値がある――私たちはそう信じて行動を続けています。同じように、プログラミングを楽しくする Ruby を通じて実現される、中高生の作品を楽しみにしています!

f:id:koic:20211019154845j:plain


株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

スペルチェッカーによる自動化のすすめ

さて、ひとめで以下のおかしな点がわかるでしょうか?

Fix a false positive for Layout/ClosingParenthesisIndentation when using keyword arguemnts.

正解例を少し先送りして、これは typo が含まれているテキストでした。私自身の typo 実例からでしたが、世の中には typo が溢れており、普段開発している膨大な量のテキストからひとつひとつの typo を見つけるのはそれなりに困難です。

それでは、正解例を見てみるのにツールを使ってみましょう。

% misspell a.txt
a.txt:1:83: "arguemnts" is a misspelling of "arguments"

このように typo 検出に役立つツールとしてスペルチェッカーがあります。私がリポジトリに対して度々使うスペルチェッカーはふたつあります。

ひとつめは正解例で使った Go 製の misspell です。Go のインストールが必要です。

github.com

そしてふたつめは Python 製の codespell です。Python のインストールが必要です。

github.com

こちらの codespell を使うと以下のような結果になります。

% codespell a.txt
a.txt:1: arguemnts ==> arguments

詳しくはそれぞれの公式サイトを参照となるのですが、テキスト規模が大きくなると検出できる対象が違ったりするので、重ね掛けをして typo のあぶり出しをすることでより効果的な typo 検出をすることができます。

Rails アプリケーションでの例を挙げると、スペルチェッカーの実行で以下の typo 起因のバグが検出されて、before_action が実行されていないアクションがあったことが判明したケースがあります。

-before_action :do_something, only: %i(edit confirm updae)
+before_action :do_something, only: %i(edit confirm update)

静的解析で見つけられれば良いですが、そのような検出機構がない場合にスペルチェッカーの方で検出できたという興味深い (?) ケースでした。

スペルチェッカーの良いところは、個人の開発環境から導入を開始することができる点にもあります。その先のアドバンスドとしては、Rails が GitHub Actions で行っているように CI での typo 検出をしておくと、リポジトリの master (main) ブランチに含まれる前に typo 検出をすることができるのでチーム開発としても便利です。

github.com

そのほかにも Git Hooks に引っ掛けたりと、コマンドラインツールということで自動化に向けたいろいろな応用が効くでしょう。

今回取り上げたスペルチェッカーは英文に対するチェックになりますが、仮にお仕事の開発が日本語でのコミュニケーションだとしても、プログラムの変数名やメソッド名などは英単語主体になります。実プロジェクトの開発に組み込むことで、きっと typo を減らせるきっかけになるでしょう。

今日はここまでです。では、Happy Hacking!


「情報化技術を通じて社会と共生する」株式会社永和システムマネジメント アジャイル事業部では、エンジニアを絶賛募集しています。応募エントリお待ちしております!

agile.esm.co.jp

『エクストリームプログラミング実践者の集い』イベントをオンライン開催します

XP祭り 2021』に登壇したアジャイル事業部メンバーのリアルタイム再演イベントとして、『エクストリームプログラミング実践者の集い』を開催します。

2021年10月25日(月) から 10月29日(金) までの 5夜連続 19:00-20:00 の時間帯で、メンバーが日替わりで登壇します。各日程の講演終了後には、登壇者に直接質問ができる QA 時間を設ける予定です。 最終日 10月29日(金) は本イベント独自の初演登壇があります。

全日通しでのフル参加、あるいは気になる日程のみの参加でも歓迎です。ふるってご参加ください!

申し込み方法

Doorkeeper から申し込みをお願いします。チケット (無料) は5日間通しになっています (気になる日程のみの参加でも歓迎です) 。

esminc.doorkeeper.jp

スケジュール

  • 第1夜: 10/25(月) 19:00-20:00 @koic 『ソフトウェア見積りの公式』
  • 第2夜: 10/26(火) 19:00-20:00 @color_box 『とあるアジャイルプロジェクト108日の記録』/ @kasumi8pon 『チームによい提案をするには』
  • 第3夜: 10/27(水) 19:00-20:00 @fkino 『チームの劇的瞬間 〜航空、医療、類人猿、そして XP に学ぶ〜』
  • 第4夜: 10/28(木) 19:00-20:00 @junk0612 『ソフトウェア開発におけるコミュニケーション』
  • 第5夜: 10/29(金) 19:00-20:00 @m_pixy 『価値創造契約10周年(とそこから得られるアジャイルな受託開発についての理解)』

f:id:koic:20211005125823j:plain

参加にあたって

Zoom ビデオ会議を使用しますので、Zoom が利用できるようにご準備ください。


株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp

XP祭り 2021 に登壇した弊社メンバーのスライドまとめ

2021年9月18日(土) にオンライン開催した XP祭り 2021 の弊社メンバーのスライドまとめです。

xpjug.connpass.com

@hiranabe 『自分のしたい、から、みんなのしたい、へ。 (Appreciative Inquiry behind Extreme Programming)』

www.slideshare.net

@haru01 『XP祭りの中でドメイン駆動設計の勉強会!!』

ワークショップのためスライドではなくブログとなります。

twop.agile.esm.co.jp

@fkino 『チームの劇的瞬間 〜航空、医療、類人猿、そして XP に学ぶ〜』

@color_box 『とあるアジャイルプロジェクト108日の記録』

@junk0612 『ソフトウェア開発におけるコミュニケーション』

@koic 『ソフトウェア見積りの公式』

@kasumi8pon 『チームによい提案をするには』

@okajima_yukio 『対話と創発 ~ アジャイルなマーケティングチームの1年間』

www2.slideshare.net

さらに、惜しくも聞き逃した人のためのイベントがあるかもしれません。続報にご期待ください。


株式会社永和システムマネジメントでは、Ruby とアジャイルソフトウェア開発を通じてコミュニティと共生しながら成長したいエンジニアを絶賛募集しています。

agile.esm.co.jp