Windows10でPerl+VSCodeな開発環境を整える

※このエントリはPerl入学式 Advent Calendarの13日目のエントリとして、滑り込むように執筆したものです。

私とPerl入学式の関わり

わいとんです。

実は私、第1回東京開催のころから散発的にPerl入学式のサポーターをやってきました。もう3年以上の関わりになるので、サポーターの中では最古参の部類に入るでしょう。

さて、今回はWindows10でPerlの開発環境を整える話をしたいと思います。

WindowsはPerlの開発に向いていないのではないかという話

Perl入学式の講義では、Windows向けの開発環境としてVirtualBoxUbuntu Linuxをインストールする方法をレクチャーしています。

というのも、基本的にはWindowsでPerlのプログラミングを行うことはやや困難であるとか、あるいはWindowsでPerlを書いている人がサポーターを始め、さほど見受けられないので、サポートを受けにくい状況にある、などという理由が横たわっているためです。

当たり前を疑ってみる

では、本当にWindowsでPerlアプリケーションの開発を行うことは困難なのでしょうか?

あるコンテキストにおいてはこれはYesなのかもしれません。

例えば(Perl入学式の講義レベルから見ると相当高度な話となるのですが)MySQLを使った開発をすべてWindows上で行う場合は、もしかするとLinuxでは考えられない苦労が待っているのかもしれません(ただし、私は試したことがないので、これは間違いかもしれません)。

しかし、Perl入学式のカリキュラムの範囲であれば、私見ですがWindowsでも困ることはないだろうと思います。

WindowsでPerlの開発環境を構築したい向きには、もしかすると役に立つかもしれないので、私なりの環境構築法を紹介します。

Windowsにもパッケージマネージャがある!

個人的に、もっと有効活用されてもよいのにと思うプロダクトに、chocolateyというパッケージマネージャがあります。そう、yumやaptのように、ほしいプログラムパッケージ名を教えると、あとは全自動でインストールまでやってくれる便利なやつです。

chocolateyのインストール

まず、Windowsのスタートボタンを右クリックし、 Windows PowerShell(管理者)を選択します(この時、管理者権限を求められますので、「はい」を選びます)。

すると、PowerShellターミナルが開きますので、chocolateyのインストールガイダンスに従って、以下のコマンドをPowerShellターミナルに貼り付けて実行します(長いので折り返して見えるかもしれませんが、一行です)。

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

これでchocolateyのインストールが完了しました。

chocolateyは、Windows管理者にchocoコマンドを提供してくれます。うまくインストールできているか、試しにchocoコマンドを使って、以下のようにパッケージを検索してみましょう。

choco search perl

chocoateyのインストールに成功している場合、以下のようにパッケージがズラッと表示されます。

Perlを使えるようにする

さて、無事にchocolateyのインストールができたら、今度はPerlを使えるようにしたいところです。

Windows向けのPerlにはいくつか種類がありますが、比較的はまりどころが少ないと感じているStrawberry Perlを、chocolateyを使ってインストールしていきます。

先ほどの choco search の結果を見ると、パッケージ一覧の最初に

StrawberryPerl 5.26.1.1 [Approved] 

と書いてあります。もう見たままなのですが、一番左側にはパッケージ名が、その次にはそのバージョンが表示されていまして、つまり以下のようにchocoを実行してやるだけで、Strawberry Perlの5.26.1.1がインストールされるというわけです。

choco install StrawberryPerl

非常に簡単ですね。途中でインストールの可否を問われますので、「Y」を選択してあげればOKです。

VSCodeをインストールする

VSCodeとはVisual Studio Codeの略称です。エディタですので、宗教上の理由によりほかのエディタでなければいけない、という方はここはスキップしてかまいません。

VSCodeは、MicrosoftがOSSとして開発しているエディタです。atomなどにも似ていると思います。

そんなVSCodeもchocolateyで検索・インストールすることができます。

choco install VisualStudioCode

たったこれだけです。

第2回の課題を一つ、Windowsで実際にやってみる

chocolateyを使って、いとも簡単にPerlの開発環境を整えることができました。

では、実際にこの開発環境をつかって課題をこなしてみます。

via GIPHY

まとめ

  • WindowsでもStrawberry Perlを使うと、Perl入学式のカリキュラムを乗り切ることができるかもしれません。
  • Windowsのパッケージマネージャchocolateyを使うと、開発環境の構築が意外と簡単でした。

Perlコアモジュールに寄せてみる

※このエントリはPerl Advent Calendar 2017の9日目のエントリとなります。

8日目は@mackee_wさんの担当でマスタデータを宣言的かつ高速にテストするTest::MasterData::DeclareとTest2の構造についてというエントリでした。Test2を使ったモックデータを伴うテストの記述に、大変強力そうなモジュールでしたね。

さて、本エントリではPerl5におけるコアモジュールについてのさわりと、その中でも鉄板とも呼べる非常に有用なものをいくつか紹介していきます。

コアモジュールとは?

Perl5におけるコアモジュールとは、Perl5と抱き合わせでインストールされるモジュール群のことを指します。

コアモジュールとして収録されるモジュール群は、Perl5のバージョンごとに差がありますが、個人的な肌感としては、本当に鉄板とも呼べるような物は大抵5.14以降であればそろっていると考えても差し支えないと思います。

コアモジュールをちゃんと調べたい

私のようなテキトーな人間の肌感なんかは余り当てにならないでしょうから、確実性のあるソースを当たるのであればperldoc.perl.orgのコアモジュール一覧がありますので、そちらを参照するのが間違いないでしょう。

上記ページの左上には、Perlバージョンを指定するドロップダウンメニューがありますので、お使いのPerlバージョンを選ぶとよいでしょう。

もしくは、ターミナルで corelist モジュール名 と打ち込んでやると、そのモジュールがコアモジュールかどうかと、(もしコアモジュールの場合は)どのperlバージョンからコアモジュールに収録されたのかを返してくれます。

例えば私の使っているRazer Blade Stealth(Windows10 + Strawberry Perl 5.26.1)で Module::Load について corelist を使って調べてみると、以下のような結果が得られました。

C:Usersytnob>corelist Module::Load

Data for 2017-09-22
Module::Load was first released with perl v5.9.4

なお、 corelist コマンドは Module::CoreListというモジュールによって提供されておりますが、当然これもコアモジュールです。

C:Usersytnob>corelist Module::CoreList

Data for 2017-09-22
Module::CoreList was first released with perl v5.8.9

なぜコアモジュールを使うのか

Perlをはじめとしたモジュール管理のエコシステムが整ったプログラミング言語を各種開発に利用するにあたって、大抵はそのモジュラリティをフル活用した開発スタイルを取ることになると思います。つまり、インターネットなどを通じて外部からモジュールを取り入れて利用することがほとんどでしょう。

CPANなどで公開されている便利な外部モジュールを利用することで、本質的なロジックの開発に集中しようということがその狙いだったりするのですが、つぶさにコアモジュールを調べてみると、外部モジュールに頼るまでもなく、案外とコアモジュールで済ませられる事も多かったりします。

コアモジュールに寄せておくことで、以下のようなメリットに与ることができます。

  • スクリプトの利用環境制限を緩めることができる(Windowsでも動く、とか)
  • 外部モジュールのインストールの手間を省くことができる

私が選んだお気に入りコアモジュール5選

さて、ごちゃごちゃと説明してきましたが、私がよく使うコアモジュールを5つだけピックアップしてみました。本当はもっとお世話になっているコアモジュールはいっぱいあるのですが、執筆に必要な集中力の都合上、このくらいに留めさせておいてください。

HTTP::Tiny (from v5.13.9)

LWP::UserAgentFurlよりもプリミティブな感じのあるHTTPクライアントモジュール。レスポンスがオブジェクトではなくハッシュリファレンスで帰ってくる点が前述のモジュール達よりもシンプルです。

HTTP::Tinyについては、shohexさんが6年前に書いたエントリが非常にわかりやすいですので、そちらもご覧ください。

Module::Load (from v5.9.4)

モジュールの動的ローディングを実現するモジュール。状況によって読み込むモジュールを差し替える(Strategyパターン)ようなケースに使ったりします。

似たようなものにはClass::Loadとかがあるんですが、Module::Loadだとちょっと足りない、というケースで使うかもしれません。私は使わないけど。

Encode (from 5.7.3)

日本人に生まれ日本語とPerlを操っている以上、マルチバイト文字と仲良くすることが求められるのですが、Encodeはそのためのツールを提供してくれるモジュールです。もはや説明の余地もないですね。

JSON::PP (from v5.13.9)

PerlでJSONを扱うためのモジュール。これとHTTP::Tinyをつかうことで、コアモジュールだけでちょっとしたAPIクライアントを作ったりすることができます。

とにかく速度を求められるケースであればJSON::XSを使ったりするのですが、速度よりも簡便性を求める場合にはJSON::PPを使うことが多いです。Windowsでもつるしで使えますし。

List::Util (from v5.7.3)

配列操作に関する追加の関数を提供してくれるモジュール。プログラムを書く仕事をして15年以上経過していますが、配列を処理するプログラムは頻出パターンの一つで、必然的にこのモジュールに助けられる事が多いです。

君もコアモジュールを探検してみよう

時折思い出したようにコアモジュールを探検してみると、「こんな便利なのがコアにあったんだ!」という発見があったり、「このモジュールはこういう使い方もできるな」という発想ができたりと、なかなか飽きないものです。

そもそもコアモジュール自体は結構種類があるので、全部を覚えるのはまぁ無理なんじゃないかとも思われますが、普段なかなか見かけないコアモジュールの使い道を考えたりするのも面白いものですよ。

さて、明日は@tsucchiさんの番で、なにやらMinionの話かなにかをしてくれるようですよ。楽しみですね。

Kichijoji.pm #11 でLTしました

Kichijoji.pm #11 に参加し、「あれっもしかしてPHPっていいんじゃないの?」というタイトルでLTしてきました。

This is an embedded Microsoft Office presentation, powered by Office Online.

内容としてはYAPC::Fukuoka 2017で話した内容の超絶短縮版なのですが、若干の内容追加も行なっております。

個人的に興味あった話

Songmuさんのbusyboxを参考にしたバイナリサイズダイエットの話ってのがなかなか面白くて、go generateからのperlってのがとにかく格好良さありましたね。一つの言語に縛られずに手間を無くしていく様子はさすがというところです。

macopyさんkuiperbeltの話なんかは、だいぶ前に構想を聞いた時と比較してどんどんdocs周りが洗練されてきていると感じました。リアルタイムなやり取りが必要なケースではちょっと試してみたいかも。

sakuraさんの検索の話、独特のリズム感と検索エンジンに出てくる広告の話への転換があり、トークの間「次は何がくる?」という期待の連続で非常に楽しませていただきました。

YAPC::Fukuoka 2017 HAKATAでトークしました

YAPC::Fukuoka 2017 HAKATAにてトークしてきました。

PaaSをつかって怠惰・短気・傲慢にシステムを作るためのマインドセットについての話です。当日は徳丸さんの裏番組ということもあり、人が来てくれるのかと心配しておりましたが、思いの外結構人がいらっしゃったので、話した甲斐があったと思っております。

これを機に「Azureってすごいじゃん!」とか「Azure PaaSで作ってみようかな」と思ってもらえれば本望です。

スタッフの皆様、会場提供してくださったLINE様、その他YAPC::Fukuoka成功に向けて尽力された皆様に、改めて御礼申し上げます。ありがとうございました。

YAPC::Fukuoka 2017 Hakataにて登壇することが決まりました

7/1(土)に開催されるYAPC::Fukuoka 2017 Hakataへの登壇が決まりました。

発表タイトルはBe PaaS Monger – クラウドエンジニアの三大美徳、またはIaaSを使わない3つの理由となります。

上記のセッションでは、PaaSを使ったシステム設計・構築におけるマインドセットを、プログラマの三大美徳になぞらえて解説します。

クラウドの運用に人手がかかっていてお悩みの方、PaaSという物がよくわからないという方などに向けた内容となる予定です。

Otogiri-0.18 – A lightweight medicine for using database – metacpan.org

Otogiri-0.18 – A lightweight medicine for using database – metacpan.org

Azure Functionsのパフォーマンスに関する実験

昨日、ほんの出来心でMojoアプリをAzure Functionsで動かせたらどうだろうなどと考えてしまい、2時間弱くらいでMojo::Server::AzureFunctionsというものを作りました。

Mojo::Server::AzureFunctionsを作って使うまで

もともとAzure FunctionsのHTTP TriggerとHTTP output bindingをハンドリングするためのアダプタとして作ろうとあらかじめ決めており、Functions自体はリクエストごとにプロセスを起動する動作モデルであるため、これはCGIと同様であるとみなすことができました。

従って、既存のMojo::Server::CGIを参考に、環境変数の解析と入出力の調整だけでどうにかMojoアプリをAzure Functionsで動作させることに成功しました。

動作確認したソースコードはこちらのレポジトリに上げてあります。

苦しかった点

Mojoでは $c->render(json => {...}); とすることでJSONによるレスポンスを行うことができます。

ところが、Mojo::ServerMojo::Messageではrenderメソッドの第1引数に渡された値を一切検出できません。

そのため、レスポンスのContent-TypeやContentそのものを検証して、ContentがJSON Stringであるかどうかを検証する必要があり、そうしなければAzure FunctionsのHTTP output bindingでは単なる文字列として判別されてしまい、<string>{"message": "hello"}</string> という感じの残念なレスポンスを返してしまうことになるのです。

これを回避するコードがココでして、Contentが{で始まっていれば多分JSONだろうとみなし、evalで囲った中でdecode_jsonをかけるという非常に野蛮な方法で対応したことがお分かり頂けると思います。

実際に動作させてみた

さて、Azure Functionsにデプロイして実際に動作させてみた結果をお見せします。

Azure Functionsの大変便利な機能の一つとして、関数ごとにレスポンスにかかった時間のモニターをすることができる、その名もずばり「モニター」という機能があります。今回はそこで記録された動作速度を見ていただきたいと思います。

一番右側の丸括弧で囲われた値がレスポンスまでにかかった時間です。平均およそ23秒ほどでしょうか。これは遅いですね!

なぜ遅いか?

実は遅い理由は非常に単純でして、Mojoliciousをuseするコストがあまりにも高いことが挙げられます。これはMojoliciousが悪いわけでもありませんし、もちろんAzure Functionsが悪いわけでもありません。

どういうことかというと、そもそもAzure Functionsには非常にシンプルなものがデプロイされることが期待されています。Webアプリケーションフレームワークのような複雑なコードは毎回ロードするだけでもコストがかかりますので、当然のようにレスポンスまで時間がかかるのです。

証拠

例えば関数内のrun.shの内容が以下のように非常に単純なものだったとします。

perl -MJSON::PP -le 'print encode_json({message => "Hello, World!"})' > $res

その場合は、以下のようなレスポンス速度を実現することができるのです。

概ね0.5〜2秒程度でレスポンスを返すことができています。必要十分な速度と言えますね。

まとめ

Azure FunctionsでMojoアプリを動作可能にするMojo::Server::AzureFunctionsを作って、レスポンス速度を確かめてみました。

その結果わかったのは、Azure Functionsには複雑なコードをデプロイすべきではなく、徹底的にシンプルなコードをデプロイすることでその真価を発揮することができる、ということです。その先にはほぼ無限のスケーラビリティとメンテナンスフリーにほど近いシステムの実現があると私は思います。

Reactive Programmingの波がPerlにもやってきた?

どーも、わいとんです。

遅まきながら、新年おめでとうございます。

さて。近頃、個人的に気になっているCPANモジュールの一つにMoobXというものがあります。

今回は実際にMoobXを使って、PerlでのReactive Programmingを試してみましたので、ご紹介したいと思います。

MoobXについて

MoobXはReactive programming frameworkを標榜しており、JavascriptのMobXにインスパイアされたものであるようです。

本エントリ執筆時点での最新バージョンは0.1.0ですが、作者のYanick Champoux氏によって精力的に開発が継続されており、現在も3つのissueがopenとなっています。

なお、最初のリリースである0.0.1が今年の1/13にリリースされたばかりであり、0.1.0のリリース日も1/14であることから、今後まだまだ仕様が変わる可能性があると思われます。

Reactive Programmingとは

そもそもReactive Programmingとは何なのか、という疑問を持っている方もいらっしゃるかもしれません。

もっともわかりやすいReactive Programmingの例としては、Excelの数式が挙げられます。例えばセルA1に=A2+A3という定義がある場合、A2とA3の値を加算した結果がA1に反映されます。この時、A2の値を修正すると、即座にA1に結果が反映されます。

Excelの場合は、A1に値の関係性を記述することで、A2及びA3の値の変更を伝播させるデータフローが生じます。

このような値の関係性を記述して、値の変更を伝播させる、データの流れに着眼したプログラミングパラダイムのことをReactive Programmingと言うようです。

MoobXを使ってみる

では早速MoobXを使ってReactive Programmingをやってみます。

MoobXはcpanmcpmなどを使ってインストールできます。

cpanm MoobX

実際にMoobXを使った簡単なコードを書いてみました。

use strict;
use warnings;
use MoobX;

observable my $x;
observable my $y;

my $z = observer {$x + ($y * 2)};

$x = 3; $y = 5;
print "$zn";

$y = 2;
print "$zn";

この結果は以下のようになります。

$ perl ./observer.pl
13
7

$yの変化に応じて$zも変化していますね。

もしこれがReactive Programmingでなければ、おそらく以下のような結果になっていたことでしょう。

$ perl ./observer.pl
13
13

MoobXの基礎

MoobXを利用する上で覚えなくてはならないことは2つだけです。

observer

observerには、値の関係性をコードブロック(無名関数)として記述します。

my $z = observer {$x + ($y * 2)};

observable

observableには、observerで言及される対象となる変数定義を記述します。

observable my $x;
observable my $y;

まとめ

PerlにおけるReactive ProgrammingをMoobXで実現できる、ということを紹介しました。

応用することで、様々な有益モジュールの開発に貢献しそうな予感がしますね。

Perlで替え歌エンジンをつくる

※当エントリはPerl入学式 Advent Calendar 2016の第23日目のエントリです。

どーも、わいとんです。

皆さん、明日はクリスマスイブですね。ところで皆さんはカラオケは好きですか?そうでもない?では替え歌ならどうでしょうか?愉快な替え歌なら、ワクワクすると思います。

今日はそんな替え歌を、自動で作ってくれるスクリプトをPerlでつくってみました。

すでに上の画像の時点でネタばれなのですが、クリスマスソングとしておなじみの「赤鼻のトナカイ」の歌いだしの部分を、いい感じに悲壮感漂う風味に仕上がるようにちょっとだけ頑張りました。

と言っても、そんなに難しいことはしておらず、Perl入学式の卒業生であれば、比較的かんたんにつくれる程度のものです。

ソースコードをgistに公開していますので、何をやっているのか見てみると、参考になるかもしれません。

さすがに何の解説もないと理解に苦しむ個所もあろうかと思いますので、少しだけ解説。

動作概説

やってることをかいつまんでしまうと、以下のような手順になります。

  1. 替え歌のもとになる歌詞を形態素解析APIに投げ込み、結果をうけとる。
  2. 受け取った結果データをJSONからハッシュリファレンスに変換する。
  3. 2のデータから一般名詞だけを一定確率で別の単語にランダムで置き換える。
  4. 3のデータをぜんぶjoinしてprintfで出力する。

なお1のAPIは、わいとんお手製のAPIとなっています。いつまでも残しておく保証はないですが、ちょっと遊ぶくらいには使っていただいて構いません。

課題

Perl入学式の受講生ならびに卒業生の皆さんには、思い思いの改造を施して、あなたのオリジナルの替え歌エンジンを作ってみてください。

File::Spec/File::Basenameを使ったライブラリパス指定

※このエントリは Perl Advent Calendar 2016 の15日目のエントリです。

どーも、わいとんです。

早速ですが、みなさんはPerlのライブラリパスをどんな風に指定していますか?

そもそもスクリプト内で指定してない?絶対パスで直接指定?それともFindBinを使ってる?

今回はわいとんがよくやっているFile::SpecFile::Basenameを使ったライブラリパス指定の方法を紹介します。

以下のようなプロジェクトがあったとします。

./
|
+---cpanfile
|
+---bin/
|    |
|    +---run.pl
|
+---lib/
     |
     +---MyProj.pm
     |
     +---MyProj/
          |
          +---Client.pm

cpanfileは以下のような内容です。

requires 'perl', '5.008001';
requires 'LWP::UserAgent';
requires 'LWP::Protocol::https';
on 'test' => sub {
    requires 'Test::More', '0.98';
};

これをcpm installなんてやった場合、local/lib/perl5配下に依存ライブラリがどんどん入ってきます。(cpmについてはskajiさんのエントリを参照してください。)

で、bin/run.plからMyProj::Client->new(...);なんてやりたいなぁって思った時に、以下のように書くと思います。

use strict;
use warnings;
use MyProj::Client;
my $client = MyProj::Client->new(...);
...

でもって、実行時に

perl -Ilib -Ilocal/lib/perl5 ./bin/run.pl

なぁんて書くと思います。別に悪くないけど、面倒ですよね。

ちょっと賢くFindBinを使う

で、use libFindBinを組み合わせて、以下のようにしたりしますよね。(しますよね?したことありません?)

use strict;
use warnings;
use FindBin;
use lib (
    "$FindBin::Bin/../lib",
    "$FindBin::Bin/../local/lib/perl5",
);
use MyProj::Client;
my $client = MyProj::Client->new(...);
...

実行時にはこんな感じで。

perl ./bin/run.pl

楽になりましたね!でもでもでもでもチョッッット待ってwww それってカレントディレクトリがプロジェクトフォルダの直下にないと動かなくないっすか?(動かないですよね?)あとそれWindowsじゃ動かなくないですか?(Windowsなんか使わない?あ、すみませんww)

File::SpecとFile::BasenameとFILEを使う

まあそこで出てくるのがFile::SpecFile::Basenameなんですね。

超雑に解説すると、File::SpecってのはOS間で異なるパス表現(¥とか/とかそういうやつ)を吸収してくれるライブラリで、File::Basenameてのは、食わせた文字列をパス表現文字列とみなしてざっくりパーズし、フォルダまでのパスとかファイル名とかをよしなに引っ張ってきてくれるライブラリです。

あと__FILE__っていうのは実は組みこみ関数でして、__FILE__が記述されているファイルのパス(つまり実行されるスクリプトのパスそのもの)を返してくれます。

んで、こいつらを使ってさっきのbin/run.plを書き換えると、こんな感じになります。

use strict;
use warnings;
use File::Spec;
use File::Basename 'dirname';
use lib (
    File::Spec->catdir(dirname(__FILE__), qw/.. lib/),
    File::Spec->catdir(dirname(__FILE__), qw/.. local lib perl5/),
);
use MyProj::Client;
my $client = MyProj::Client->new(...);
...

若干冗長ですが、実行時は常にスクリプトを正しく指定するだけでOK。

perl ./bin/run.pl

例えばlib/MyProj/からでも

perl ../../bin/run.pl

と実行できます。

少し補足。 File::Spec->catdir(...)は、引数にリストを食わせることで、実行環境に応じたパス文字列を仕立て上げてくれます。dirname(...)は与えられたパス文字列のディレクトリパスを返してくれます。

これらを組み合わせて、どの環境でどのパスから実行されても、読み取りたいライブラリパスがずれずに利用可能となる、と。こういうわけです。

何より、File::SpecFile::Basenameもコアモジュールなので、Perl5が入っていればまず使えないってことはないんじゃないでしょうか。→ツッコミ参照ください

まとめ

  • ライブラリパスをがっちりつかんで離さないスクリプトを書くための方法を紹介しました。
  • File::SpecFile::Basenameを使うぞって言いながら__FILE__も使いました。
  • きっとWindowsの人もニッコリ。
  • cpmかわいいよcpm

ツッコミもらいました

だそうです。。。skajiさん、ありがとうございますm(_ _)m