ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

Perlには無いRubyのyield文に少し嫉妬を覚えた

最近Rubyを勉強していて、今日yield文というのに出会った。
忘れないようにメモ

yield文はこんな感じで書く

def foo ( name )
  yield('おはよう' + name)
  yield('おやすみ' + name)
end

foo( 'sasakure' ) do | message |
  puts message
end

結果はこのように表示される

おはようsasakure
おやすみsasakure

fooというメソッドの中でyieldが実行されるたびに、
呼び出し元の後ろに書かれたdoブロックが実行される。


最初にこれ見た時は、
yieldが呼ばれる度に、doブロックを実行する処理が溜まっていって、
fooメソッドが終わった後で順番に実行されるのか、、、とか思ってたけど違った。


fooメソッドの中から、doブロックに飛び出してきて、
またfooメソッドの中に戻って、またdoブロックに飛び出してくる。


なにこれ新しい!!!(すくなくとも僕にとっては)


Perlで書くとこんな感じの動きですね

sub foo {
    my ($name, $cb, ) = @_;
    $cb->('おはよう' . $name);
    $cb->('おやすみ' . $name);
}

foo( 'sasakure', sub{ print shift . "\n"; } );

渡した無名関数がyieldした時に呼ばれるみたいな



それと!
yield文を調べる事で、初めてdoブロックについてもちゃんと理解できた。


Perlでブロックっていうと{}この範囲を指すけど、
Rubyでは do 〜 endを指す
※ただしdo endは {}に置き換えられるよ


んで、このdoブロックはperlと違って、単体では書けない。
必ずメソッドの後ろにくっついて宣言される。

そして、ブロック内が実行されるのは、その前のメソッド内でyieldが呼ばれた時になる。


配列のeacheメソッドも中でyield呼んでるって理解してもいいのかな?

list = [0,1,2,3]
list.each do | num |
  puts num
end

このyield文、覚えてしまうとなかなか便利かもしれない。
ちょっとPerlでも書きたくなるなぁ

Bundlerを使ってRailsをいれてみた

前回のエントリーrubyをインストールしたので、
次はBundlerを使ってRailsを入れてみたいと思います。


やることは大きく3つ
ruby本体にgemでBundlerを入れる
• 一時的なgemでRailsを入れる
Railsアプリケーションを作成したら一時的なgemを消す
(その他のgemはRailsの中で管理する)

これでBundler意外のgemはアプリケーション単位でしか依存しなくなります。
※注 Ruby超初心者なので大きな誤解をしている場合がございます。


まずはgemをアップデート

$ gem update --system


そしてbundlerのインストール

$ gem install bundler
Fetching: bundler-1.3.5.gem (100%)
Successfully installed bundler-1.3.5
Parsing documentation for bundler-1.3.5
Installing ri documentation for bundler-1.3.5
1 gem installed
$ rbenv rehash

rehashするのを忘れずに

僕はrbenvでRuby2.0.0を選択していたので、ちゃんと意図したとこに入ってるか確認

$ gem which bundler
/Users/sasakure/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler.rb

うん大丈夫


それではRailsを入れます。



Gemfileというファイルを「Railsをインストールするためだけに」作る必要があります。
このGemfileというのはBundlerがインストールするためのgemファイルを指定するもので、
これからRailsをインストールしたい場所に作成する必要があります。

$ cd
$ mkdir RailsApps
$ cd RailsApps
$ vi Gemfile

Gemfileの中身はこんな感じ

source 'http://rubygems.org'
gem 'rails', '3.2.13'

んで、この例でいうとRailsAppsディレクトリにいる状態で
bundle install コマンドでインストールするんですが、
オプションで--path vendor/bundleを指定するのを忘れずに!

$ bundle install --path vendor/bundle
Fetching gem metadata from http://rubygems.org/...........
Fetching gem metadata from http://rubygems.org/..
Resolving dependencies...
Installing rake (10.0.4) 
Installing i18n (0.6.1) 
Installing multi_json (1.7.2) 
Installing activesupport (3.2.13) 
Installing builder (3.0.4) 
Installing activemodel (3.2.13) 
Installing erubis (2.7.0) 
Installing journey (1.0.4) 
Installing rack (1.4.5) 
Installing rack-cache (1.2) 
Installing rack-test (0.6.2) 
Installing hike (1.2.2) 
Installing tilt (1.3.7) 
Installing sprockets (2.2.2) 
Installing actionpack (3.2.13) 
Installing mime-types (1.23) 
Installing polyglot (0.3.3) 
Installing treetop (1.4.12) 
Installing mail (2.5.3) 
Installing actionmailer (3.2.13) 
Installing arel (3.0.2) 
Installing tzinfo (0.3.37) 
Installing activerecord (3.2.13) 
Installing activeresource (3.2.13) 
Using bundler (1.3.5) 
Using json (1.7.7) 
Installing rack-ssl (1.3.3) 
Installing rdoc (3.12.2) 
Installing thor (0.18.1) 
Installing railties (3.2.13) 
Installing rails (3.2.13) 
Your bundle is complete!
It was installed into ./vendor/bundle
Post-install message from rdoc:
Depending on your version of ruby, you may need to install ruby rdoc/ri data:

<= 1.8.6 : unsupported
 = 1.8.7 : gem install rdoc-data; rdoc-data --install
 = 1.9.1 : gem install rdoc-data; rdoc-data --install
>= 1.9.2 : nothing to do! Yay!

ここまで良い感じ。
最後に出て来たメッセージは何だろう。
Rubyのバージョンによってはrdocをインストールする必要があるけど、1.9.2以上なら関係ないよヒャッホー!」 ってとこかな。


あとはRailsでアプリケーションを作成したらGemfileを消せばいいんですって。

「demo」という名のアプリを作る場合は下記のようなコマンドを叩く。
※ --skip-bundleオプションでbundel installが走らないようにしておくことが重要

$ bundle exec rails new demo --skip-bundle
      create  
      create  README.rdoc
      create  Rakefile
      create  config.ru
      create  .gitignore
      create  Gemfile
      create  app
      create  app/assets/images/rails.png
      create  app/assets/javascripts/application.js
      create  app/assets/stylesheets/application.css
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  app/views/layouts/application.html.erb
      create  app/mailers/.gitkeep
      create  app/models/.gitkeep
      create  config
      create  config/routes.rb
      create  config/application.rb
      create  config/environment.rb
      create  config/environments
      create  config/environments/development.rb
      create  config/environments/production.rb
      create  config/environments/test.rb
      create  config/initializers
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/secret_token.rb
      create  config/initializers/session_store.rb
      create  config/initializers/wrap_parameters.rb
      create  config/locales
      create  config/locales/en.yml
      create  config/boot.rb
      create  config/database.yml
      create  db
      create  db/seeds.rb
      create  doc
      create  doc/README_FOR_APP
      create  lib
      create  lib/tasks
      create  lib/tasks/.gitkeep
      create  lib/assets
      create  lib/assets/.gitkeep
      create  log
      create  log/.gitkeep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  script
      create  script/rails
      create  test/fixtures
      create  test/fixtures/.gitkeep
      create  test/functional
      create  test/functional/.gitkeep
      create  test/integration
      create  test/integration/.gitkeep
      create  test/unit
      create  test/unit/.gitkeep
      create  public
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/favicon.ico
      create  public/index.html
      create  public/robots.txt
      create  script
      create  script/rails
      create  test/fixtures
      create  test/fixtures/.gitkeep
      create  test/functional
      create  test/functional/.gitkeep
      create  test/integration
      create  test/integration/.gitkeep
      create  test/unit
      create  test/unit/.gitkeep
      create  test/performance/browsing_test.rb
      create  test/test_helper.rb
      create  tmp/cache
      create  tmp/cache/assets
      create  vendor/assets/javascripts
      create  vendor/assets/javascripts/.gitkeep
      create  vendor/assets/stylesheets
      create  vendor/assets/stylesheets/.gitkeep
      create  vendor/plugins
      create  vendor/plugins/.gitkeep

できたー!!
んでGemfile関連を削除(あくまでRailsを入れるためだけで、あとはRailsの中でgemファイルを管理するから洋梨)
この例だとRailsAppsディレクトリにはdemoディレクトリだけ残せばオーケーですね。


##### 追記
この後、demoディレクトリに移動して、bundle installを再び実行する事で、
bundle exec rails serverなど raisコマンドなどが実行出来るようになります。

$ cd demo
$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Installing rake (10.0.4) 
Installing i18n (0.6.1) 
<< 省略 >>

$ bundle exec rails server
=> Booting WEBrick
=> Rails 3.2.13 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2013-04-23 01:02:23] INFO  WEBrick 1.3.1
[2013-04-23 01:02:23] INFO  ruby 2.0.0 (2013-02-24) [x86_64-darwin10.8.0]
[2013-04-23 01:02:23] INFO  WEBrick::HTTPServer#start: pid=18508 port=3000

rbenvを使ってみたよ

Perlのplenvを導入してみて大変便利だったので、
Rubyのrbenvを使ってRubyのバージョン切り替えとか簡単にやりたい!っと思い使ってみました。
※元々plenvはrbenvを参考に作られたそうです。

まずはgithubから持ってきます。

$ git clone git://github.com/sstephenson/rbenv.git ~/.rbenv
Cloning into '/Users/sasakure/.rbenv'...
remote: Counting objects: 1618, done.
remote: Compressing objects: 100% (643/643), done.
remote: Total 1618 (delta 1044), reused 1459 (delta 943)
Receiving objects: 100% (1618/1618), 232.38 KiB | 171 KiB/s, done.
Resolving deltas: 100% (1044/1044), done.

そしたらPATHを通します。
僕はzshを使っているので.zshrcに2行加えます。

export PATH="$HOME/.rbenv/bin:$PATH"
PATH=~/.rbenv/shims:$PATH

zshの設定を反映して、ちゃんとrbenvコマンドが叩けるか確認します。

$ source ~/.zshrc
$ which rbenv
/Users/sasakure/.rbenv/bin/rbenv

次にRubyをビルドするためのruby-buildってプラグインを入れる必要があるそうです。
配置先はrbenvのpluginsディレクトリです。

$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Cloning into '/Users/sasakure/.rbenv/plugins/ruby-build'...
remote: Counting objects: 1848, done.
remote: Compressing objects: 100% (1124/1124), done.
remote: Total 1848 (delta 761), reused 1610 (delta 548)
Receiving objects: 100% (1848/1848), 250.77 KiB | 104 KiB/s, done.
Resolving deltas: 100% (761/761), done.

さぁではRubyをインストールしてみますか。
とりあえず、インストール可能なバージョンを調べます。

$ rbenv install -l
Available versions:
  1.8.6-p383
  1.8.6-p420
  1.8.7-p249
  1.8.7-p302
  1.8.7-p334
  1.8.7-p352
  1.8.7-p357
  1.8.7-p358
  1.8.7-p370
  1.8.7-p371
  1.9.1-p378
  1.9.2-p180
  1.9.2-p290
  1.9.2-p318
  1.9.2-p320
  1.9.3-dev
<< 長いので省略 >>
  jruby-1.7.3
  jruby-1.7.4-dev
  maglev-1.0.0
  maglev-1.1.0-dev
  mruby-dev
  rbx-1.2.4
  rbx-2.0.0-dev
  rbx-2.0.0-rc1
  ree-1.8.6-2009.06
  ree-1.8.7-2009.09
  ree-1.8.7-2009.10
  ree-1.8.7-2010.01
  ree-1.8.7-2010.02
  ree-1.8.7-2011.03
  ree-1.8.7-2011.12
  ree-1.8.7-2012.01
  ree-1.8.7-2012.02
  topaz-dev

いっぱいありますな〜

最新の2.0.0にしようかな

$ rbenv install 2.0.0-p0
Downloading ruby-2.0.0-p0.tar.gz...
-> http://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p0.tar.gz
Installing ruby-2.0.0-p0...
Installed ruby-2.0.0-p0 to /Users/sasakure/.rbenv/versions/2.0.0-p0
$ rbenv rehash

さすがにRubyのインストールは結構時間かかりました。
インストール終わったら rbenv rehashコマンドしておきます。


どれどれ

$ rbenv versions
* system (set by /Users/sasakure/.rbenv/version)
  2.0.0-p0

このsystemというのは元々入ってるバージョンを指します。
これを2.0.0-p0にするにはrbenv globalコマンドを使用します。

$ rbenv global 2.0.0-p0
$ rbenv versions
  system
* 2.0.0-p0 (set by /Users/sasakure/.rbenv/version)
$ ruby -v
ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-darwin10.8.0]

ちゃんと切り替わりました。

rbenv globalコマンドではマシン全体のバージョンを切り替えますが、
ディレクトリ単位に指定したり出来るみたいです。
そこまで使う予定が無いので、それはまたそのうち!

Perl入学式in東京 #1 へ遅刻しました

以前から気になっていた「Perl入学式」というperl未経験/初心者向けのイベントが
ついに東京でも行われるという事で早速参加してみました。

[Zussar] http://www.zusaar.com/event/583008
[Perl入学式 公式ページ] http://www.perl-entrance.org/

仮にもPerlを2〜3年使っている僕が参加していいもんか迷ったけど、plenvやAMON2を使ったこと無いし、既に補欠だったしまぁいいかという事でエントリー!
そしたら繰り上がって参加する事ができました。


それなのに!! 昨晩に飲み過ぎて寝坊して遅刻しました orz

多くの技術者の方々が時間を割いて、しかも無料で開いてくれる勉強会で
遅刻とかホッント申し訳ありません。クズです僕は


第一回目の本日は「Perlを書くための環境構築」のような感じで、
私が到着した頃にはplenvによるPerlのインストールが行われておりました。


とりあえず、出遅れたので皆さんの進行を横目に
主催者papixさんのブログを参考にしてplenvのインストール!


手順はこんな感じ


まずはtokuhiromさんのgithubより持ってきます。

$ git clone git://github.com/tokuhirom/plenv.git ~/.plenv

僕はzshを使っているので.zshrcへ下記の2行を追記して反映

export PATH="$HOME/.plenv/bin:$PATH"
PATH=~/.plenv/shims:$PATH
$ source ~/.zshrc

するとplenvコマンドが使えるようになるので、
「plenv available」でインストール可能なPerlを一覧表示できます。

$ plenv available
perl-5.17.10
perl-5.16.3
perl-5.14.4
perl-5.12.5
perl-5.10.1
perl-5.8.9
perl-5.6.2
perl5.005_04
perl5.004_05
perl5.003_07

Perl入学式では5.16.3を使うという事で下記のようにインストール。

$ plenv install 5.16.3

Perlのインストールには結構時間が必要です。


んでもって終わったら確認してみましょう。ということで
「plenv list」コマンドを叩くと、インストールされているPerlのバージョンが確認出来ます。

$ plenv list
  5.16.3
* system

アスタリスクが付いてるほうが現在有効になっているバージョンで、
元々入ってるPerlは「system」と表示されるようです。

ということで5.16.3に切り替えます。

$ plenv global 5.16.3
$ plenv list
* 5.16.3
  system

perl -v」で5.16.3になっていればOK。
僕の場合どっちに切り替えても元々インストールされていた5.12.3から変わらなくて
「source ~/.zshrc」したらちゃんと切り替わるようになりました。


お次はcpanmのインストール

$ plenv install-cpanm

簡単!


僕は慌ててこれらのインストールと動作確認して、やっと追いついたー
ってとこでPerl入学式第一回目は終わってしまったけど、
実際は超ゆっくり細かく説明していて
Hello world表示したり、Acmeモジュールで易しくCPANモジュールの使い方を教えてくれたり、エディタとかも一人一人面倒見てくれる
そらもう大変素晴らしい勉強会でした。[http://perl-entrance-org.github.io/presentation/2013/perlentrance01-2/index.html#/title:title=
このスライドをベースに進めていました。]


はじめてplenvを使ってみたけど、これ超便利!
自分の作業PCやテストサーバーなんかには必ず入れたいですね。
バージョン毎の動作テストとか捗りますな。


参加者25人くらいに対して
サポートメンバーが10人くらい? とても手厚い!!
なんか補講(同じ内容で別の日にやる)があるらしいので、これからPerl始めてみたい人は是非参加すると良いと思いますよ!


主催のpapixさん。サポートメンバーの皆さん。会場を提供して頂いたSeesaa株式会社様
ありがとうございましたー!

宇宙ステーション演算子について解説してみた

Perlの食えない事情-演算子編を読んで、とても面白く演算子を学ぶ事が出来ました。

なかでも「宇宙ステーション演算子:-+-」はなかなか理解出来なかったので、僕なりに解説したいと思います。


その前に「ビーナス演算子:0+,+0」について触れておきます。

print '100MB' +0;     # 100
print 0+ '5GB';       # 5
print 0+ 'TB';        # 0
print 'route3390' +0; # 0

上記ブログでも簡単な説明がありますが、Perlは文字列と数値などの型を区別して持つ事は出来ません。
StringとかIntとかがないんです。

計算しようとすれば数値として扱うし、文字列操作しようとすれば文字列として扱います。
そのため、'100MB'というような値は
数値として扱えば、「100」として、
文字列として扱えば「100MB」として評価されます。

ビーナス演算子という大した名前がありますが、ただ 0を足しているだけですね。
0を足すのは先でも後でも構いません。
♀という記号を横にしたように見えることから名付けられたのでしょうw

文字列の先頭が「数値」または「-」「+」の符号でない場合は0として評価されます。


さて、宇宙ステーション演算子の解説に入ります。
上記ブログでは優先順位の高いビーナス演算子という説明がありますが、
それは使い方についての話で、演算子は別の動作をしています。

print 0+  '100MB' x 3; # 100
print -+- '100MB' x 3; # 100100100

※「x」はカケルではなく繰り返し演算子です。

まず、ビーナス演算子のほうは優先順位が+より、xのほうが高いので下記のような評価になっています。

print 0+ '100MB' x 3;
print 0 + '100MB' x 3;
print 0 + '100MB100MB100MB';
print 100;

次に宇宙ステーション演算子です。
ビーナス演算子二項演算子の「+」が使われているのに対し、
こちらは単項演算子の「+」と「-」が使われています。
perldocに説明があります。

print -+- '100MB' x 3;
print -+ '-100' x 3;
print - '-100' x 3;
print '100' x 3;
print '100100100';

単項演算子の「-」は文字列を数値として評価した後、+/-の符号を反転します。
単項演算子の「+」は何もしません。

これ例えば下記のようにするとエラーになります。

print -- '100MB';

「--」とするとデクリメント演算子になってしまうため、引数に直接値を渡すんじゃねーってエラーになってしまうんです。
それを防ぐために「-+-」としてるんですね。

いまさら素数戦争のdankogai.plを読んでみた

2012年のYAPC::Asiaで紹介されていた素数戦争

「10000番目までの素数の和を求める」
というお題をいかに早く算出するか!というものでした。

私も参加ダメダメながら参加して楽しんでいました。私の記録はこちら

そこで気になっていたのが「殿堂」となっていたdankogai.pl

length q cmp lc and print chr oct oct ord qw q do q and print chr oct oct ord q mkdir m and print chr oct oct ord qw q for q and print chr oct oct oct ord q eq le and print chr oct ord uc qw q bind q and print chr oct ord uc q each ne and print chr oct oct ord qw q dump q and print chr oct oct oct ord q eq ne and print chr oct oct oct ord q eq ne

なんじゃこりゃ?本当にPerl? って感じですよね。
でも実行すると確かに10000番目までの素数の和である496165411が表示されます!!

当時は感心だけして、どうなっているのかまで関心は沸いていませんでした。
(漠然とすごいなー danさんってすごいんだなーって)


あれから半年、、
いまさらちゃんと読んでみたいと思います。


一番左からじっくり見ていってもいいですが、パッと目につくのはprintでしょうか。
そして、printに注目すると、必ずその前にandがあることが分かります。

length q cmp lc and print chr oct oct ord qw q do q and print chr oct oct ord q mkdir m and print chr oct oct ord qw q for q and print chr oct oct oct ord q eq le and print chr oct ord uc qw q bind q and print chr oct ord uc q each ne and print chr oct oct ord qw q dump q and print chr oct oct oct ord q eq ne and print chr oct oct oct ord q eq ne


andというのは&&と同じです。
&&は下記のようにifとかで使うやつです。

my $sasa = 1;
my $kure = 1;
if ($sasa && $kure ) {
    print 'sasaとkureがどちらもtrueと評価されるから表示される';
}
#こんな使い方も出来る
$kure && print '&&の左辺がtrueならこのprint文も評価される';
$kure || print '&&の左辺がtrueならこのprint文は評価されない';

dankogai.plではandを使う事で、本来なら;(セミコロン)で区切るような
処理を1行でやってしまっているんですね。


ちょっと読み易いようにandを削除して、分けてみましょ

length q cmp lc;
print chr oct oct ord qw q do q; # 4
print chr oct oct ord q mkdir m; # 9
print chr oct oct ord qw q for q; # 6
print chr oct oct oct ord q eq le; # 1
print chr oct ord uc qw q bind q; # 6
print chr oct ord uc q each ne; # 5
print chr oct oct ord qw q dump q; # 4
print chr oct oct oct ord q eq ne; # 1
print chr oct oct oct ord q eq ne; # 1

こうしてみると、驚愕の事実が分かります。

「これ、、計算してない、、」


この時点ではどうして数字が表示されるのか、分かりませんが
素数戦争の答えである496165411をそのまま表示している事実が分かりました。
すげーマジカルな事やって計算してるのかなー って思ってたのに悔しい、、笑


ま、気を取り直して理解を進めます。
次に注目すべきはordという演算子と、その後ろの固まりです。

length q cmp lc;
print chr oct oct ord qw q do q; # 4
print chr oct oct ord q mkdir m; # 9
print chr oct oct ord qw q for q; # 6
print chr oct oct oct ord q eq le; # 1
print chr oct ord uc qw q bind q; # 6
print chr oct ord uc q each ne; # 5
print chr oct oct ord qw q dump q; # 4
print chr oct oct oct ord q eq ne; # 1
print chr oct oct oct ord q eq ne; # 1


その部分だけ実行してみましょう。

print ord qw q do q; # 100
print ord q mkdir m; # 107

これは下記のように評価されています。

print ord 'do';   #100
print ord 'kdir'; #107

これは私もよく分かっていないのですが、
qw q 文字列 q で '文字列' と評価されるようです。

または、
qwを書かない場合は q の次に来る文字から、またその文字までをシングルクォートで囲っていると評価するようです。
(perldocとかに書いてあるんでしょうか。探せなかったので誰かおしえてー(>_<) )

追記:
perldocに書いてありました。
「クォートとクォート風の演算子」のところですね。
Perlではqw{}の括弧は別に何でも代用が出来て、よく使うのだとqw//というのがありますね。
区切り文字が括弧ではない場合は前後で同じ文字があれば、それを区切り文字と評価するようです。
@tsucchiさんありがとうございます!


ordという演算子は引数の「一番先頭の文字」のASCIIコードを返します。

print ord 'A'; # 65
print ord 'Aiueo'; # 65 <-先頭のAしか評価されていない

なのでさっきのも

print ord 'd';    #100
print ord 'k';    #107

こうやってるのと一緒。
わざとPerl予約語のようにみせてただけなんですねー。


それらを踏まえると下記のようになります。

length q cmp lc;
print chr oct oct ord 'do'; # 4
print chr oct oct ord 'kdir'; # 9
print chr oct oct ord 'for'; # 6
print chr oct oct oct ord 'q l'; # 1
print chr oct ord uc 'bind'; # 6
print chr oct ord uc 'ach n'; # 5
print chr oct oct ord 'dump'; # 4
print chr oct oct oct ord 'q n'; # 1
print chr oct oct oct ord 'q n'; # 1

 

length q cmp lc;
print chr oct oct 100; # 4
print chr oct oct 107; # 9
print chr oct oct 102; # 6
print chr oct oct oct 113; # 1
print chr oct 66; # 6
print chr oct 65; # 5
print chr oct oct 100; # 4
print chr oct oct oct 81; # 1
print chr oct oct oct 81; # 1

oct演算子についてはこちらで詳しく説明されていました。
今回のケースでいえば引数を8進数とみなして、10進数への変換を行います。


chr演算子についてもこちら
ord演算子の反対ですね。ASCIIコードから文字に変換します。


oct演算子を2回、3回と使う事で、
目当ての数字にするためのASCIIコードにしているんですね。


最後に先頭にあった行について

length q cmp lc;

こちらは下記のように評価されます。

length 'mp l';

そして、lengthですから4という数値が返ります。
しかしprintしているわけではないので、そのまま何も表示されません。
dankogai.plはこの部分が無くても同じ結果になります。
きっと最初にprintが来てしまうと不思議さが半減してしまうからではないでしょうかw


今回ブログにまとめるにあたり、詳しく調べていたら
こういったコードがppencodeといわれる物だという事が分かりました。

とても参考になったページ
■TAKESAKOさんの ppencode が何で動くのか分かった。

2006年にTAKESAKOさんという方がYAPCで発表していたそうで、当時はだいぶ話題になっていたんですねー!


私はこのコードを会社の同僚と楽しみながら読む事が出来ましたし、
Perlへの理解が進んだように思います。
たくさんの人に感謝☆

AcmeモジュールをCPANにあげてみた

先日Perl Beginnersに参加したときにLTで話した
Acme::ReplicaというモジュールをCPANにアップしました。

コードはCPANgithubをご参照ください。

Acme::Replicaについて

精巧に作られた食品サンプルのように、見た目は本物そっくりですが
実際には食べれない値を返すモジュールです。


暇なときにでも使ってみてください。

use 5.010;
use Acme::Replica;

my $rep = replica_of( 'sasakure' );
if ( $rep eq 'sasakure' ) {
    say 'ここは表示されない';
} else {
    say 'ここは表示される';
    say $rep; # sasakure
}

ifの評価ではfalseになるのに、sasakureってちゃんと表示される。
どういう事かというと
表示しても字としては出てこないけど、実際はバイト単位では余計なデータが付けているから。


ハッシュを渡すとキーに余計なゴミバイトが付くようになってます。

use 5.010;
use Acme::Replica;
use Data::Dumper;

my %rep = replica_of( {
    japanese => 'sushi',
    amelican => 'hotdog',
} );

say Dumper ¥%rep;
# $var1 = {
#     japanese => 'sushi',
#     american => 'hotdog',
# };
say $replica{japanese}; # エラーになる

$replica{japanese} = 'sukiyaki';
say Dumper ¥%rep;
# $var1 = {
#     japanese => 'sushi',
#     japanese => 'sukiyaki',
#     american => 'hotdog',
# };

say $replica{japanese}; # sukiyaki

あくまでReplica(模造品)なので同じようで、違うハッシュが返ってきています。
食品サンプルが並んだハッシュに自分でスキヤキを入れたら、
スキヤキだけはちゃんと(食べれ|取れ)ます。


記念すべき僕の初Acmeモジュール :-P
Ver0.02ではMakefile.pmに初めてinc::Module::Installを使ってみました。


配列やハッシュを引数で渡すとき、使い易さでいったら、そのままブッコむ!
って思ったんですが、
後で引数を増やしたい時とか困るな〜って思ってリファレンス渡しにしました。


こういうAcmeモジュールほど、気軽にアドバイスいただけちゃったり
Pull Reqもらえるんじゃないかとwktkしてます。