Mojoliciousで表示前の共通処理(bridge)
bridge
Mojoliciousで各ページを表示する前にhtmlのタイトルなどの共通設定を各ページで定義するのが無駄な感じがする場合に処理をするところ。これを使用することで認証チェックなども実施可能
構成
[vagrant@localhost sample_web]$ tree . ├── lib │ └── Sample │ ├── Web │ │ ├── Example.pm │ │ ├── Root.pm │ │ ├── Test1.pm │ │ └── User.pm │ └── Web.pm ├── log │ └── development.log ├── public │ ├── css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ └── user.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── index.html │ └── js │ ├── bootstrap.js │ ├── bootstrap.min.js │ └── jquery-2.1.1.min.js ├── script │ └── sample_web ├── t │ └── basic.t └── templates ├── example │ └── welcome.html.ep ├── layouts │ └── default.html.ep ├── test1 │ ├── conf.html.ep │ ├── index.html.ep │ └── post.html.ep └── user └── index.html.ep 15 directories, 29 files [vagrant@localhost sample_web]$
routerで事前にbridgeを指定
lib/Sample/Web.pm
package Sample::Web; use Mojo::Base 'Mojolicious'; # This method will run once at server start sub startup { my $self = shift; # Documentation browser under "/perldoc" $self->plugin('PODRenderer'); # Router my $r = $self->routes; # 共通処理 my $init = $r->bridge->to('root#init'); # ログイン制御ページ my $login = $init->bridge->to('user#init'); $login->get('/login')->to('user#index'); $login->post('/login')->to('user#login'); $login->get('/logout')->to('user#logout'); # 認証チェック my $auth = $init->bridge->to('root#auth'); # 認証後アクセスできる処理 $auth->get('/')->to('example#welcome'); $auth->get('/test1')->to('test1#index'); $auth->get('/test1/new')->to('test1#post'); $auth->post('/test1/conf')->to('test1#conf'); $auth->post('/test1/create')->to('test1#create'); } 1;
lib/Sample/Web/Root.pm
package Sample::Web::Root; use Mojo::Base 'Mojolicious::Controller'; # 初期処理 sub init { my $self = shift; # 共通で使用する変数を設定する $self->stash->{title} = "aaaa"; } # 認証チェック処理 sub auth { my $self = shift; # セッションのauthが設定されているかチェックする if($self->session->{auth}){ return 1; }else{ $self->redirect_to('/login'); } return undef; } 1;
※共通処理として初期処理や認証チェックなどを定義し、bridgeで指定する
一応、超適当な認証
lib/Sample/Web/User.pm
package Sample::Web::User; use Mojo::Base 'Mojolicious::Controller'; # ログイン共通 sub init { my $self = shift; # ログイン処理独自のcssを設定 $self->stash->{cssfiles} = ["user"]; } # ログインページ sub index { my $self = shift; # セッションをすべて破棄 $self->session(expires => 1); # view適用 $self->render(); } # ログイン処理 sub login { my $self = shift; my $login = $self->param('login'); my $password = $self->param('password'); # きちんとした認証処理はそのうち実装 if($login eq "root" && $password eq "password"){ # session $self->session->{auth} = { user => 'root' }; # ログイン成功後はTOPへ遷移 $self->redirect_to('/'); }else{ # ログイン画面へ戻る $self->redirect_to('/login'); } } # ログアウト処理 sub logout { my $self = shift; # セッションをすべて破棄 $self->session(expires => 1); # ログイン成功後はTOPへ遷移 $self->redirect_to('/login'); } 1;
※認証して成功した場合にトップへ遷移可能
※そのうちきちんとした認証を実装しよう…(´・ω・`)
確認
認証していない場合は自動的にログインページへ遷移
ログイン後はトップページヘ遷移
参考
http://d.hatena.ne.jp/perlcodesample/20101112/1278596435
http://qiita.com/yusukebe/items/9f755d17a3a1b657a8b6
まとめ
bridgeを使用することで全体の共通処理、部分的な共通処理を実装できるよう。
毎回記載するけどなんかいい方法がないかな?と思っていたのでこれは便利と思う。
適当にアプリの雛形を作成だけの場合では深く考えないので気づかないことがあるのでいろいろ探してみることは重要かと思われる
perlモジュール確認(Digest::SHAとかText::Markdown::Discount)
Digest::SHA
暗号化を行うモジュール認証の処理を使用する際はお世話になるかも…
インストール
cpanm Digest::SHA
サンプルソース
#!/usr/bin/env perl use strict; use warnings; use Digest::SHA qw(sha1_hex sha256_hex sha384_hex sha512_hex); my $password = "1"; my $crypt; $crypt = sha1_hex($password); print $crypt . "\n"; $crypt = sha256_hex($password); print $crypt . "\n"; $crypt = sha384_hex($password); print $crypt . "\n"; $crypt = sha512_hex($password); print $crypt . "\n";
↓
[vagrant@localhost sha]$ perl sample1.pl 356a192b7913b04c54574d18c28d46e6395428ab 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b 47f05d367b0c32e438fb63e6cf4a5f35c2aa2f90dc7543f8a41a0f95ce8a40a313ab5cf36134a2068c4c969cb50db776 4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a [vagrant@localhost sha]$
※簡単なパスワードの場合はこんな感じみたい。
※さすがに平文の1文字をパスワードとして有効にしていないとおもうので"a"でのサンプルにしている。
※これになんらかの文字列を付与して暗号化をして対応するかな?
Text::Markdown::Discount
markdownをテキストに変換する?
なんか他にもあったような?
インストール
cpanm Text::Markdown::Discount
サンプル
#!/usr/bin/env perl use strict; use warnings; use Text::Markdown::Discount qw(markdown); my $text = <<'EOT'; # aaa ## bbb ### ccc ``` <?php echo "hello world."; ?> ``` EOT my $html = markdown($text); print $html . "\n";
↓
[vagrant@localhost markdown]$ perl sample1.pl <h1>aaa</h1> <h2>bbb</h2> <h3>ccc</h3> <p><code> <?php echo "hello world."; ?> </code></p> [vagrant@localhost markdown]$
※ソースコードも変換する
※なんか意外と便利みたいな感じ。
参考
http://www.kent-web.com/perl/crypt/step05.html
http://search.cpan.org/~sekimura/Text-Markdown-Discount-0.02/lib/Text/Markdown/Discount.pm
まとめ
モジュールっていろいろ多すぎて何をどうすればいいのかがわからないことがある。ある程度自分でなんとかできそうな場合は作成するけどやっぱり既存のものを使用したほうが楽な感じもするし…
https://github.com/hachiojipm/awesome-perl
なんかいろいろ参考になりそうなんで利用するかも…まだ、よく、みてないけど
PerlでTengを使用したDB操作2
MVCのモデルみたいな感じにしようと画策中
データベースを接続する際は毎回接続するのはちょっと面倒臭いのでなんか1つの場所で接続して使用した方がいいはず。
構成
. ├── config.pl ├── lib │ ├── Config │ │ └── App.pm │ ├── DB │ │ └── Schema.pm │ ├── DB.pm │ ├── Model │ │ ├── App.pm │ │ └── Posts.pm │ └── Model.pm └── sample.pl
設定
config.pl
{ connect_info => [ 'dbi:mysql:sample_db1:localhost', 'root', undef ] }
Config
Config::App.pm
package Config::App{ use Mouse; use Config::PL; sub config{ return config_do "config.pl"; } __PACKAGE__->meta->make_immutable(); } 1;
※Config::PLでconfig.plを読み込む
DB
DB.pm
package DB; use parent 'Teng'; 1;
DB::Schema.pm
package DB::Schema; use strict; use warnings; use Teng::Schema::Declare; table{ name 'posts'; pk 'id'; columns qw/id title body/; }; 1;
Model
Model.pm
package Model{ use Mouse; use DB; use Config::App; has 'db' => ( is => 'ro', isa => 'DB', lazy_build => 1 ); has 'connect_info' => ( is => 'ro', isa => 'ArrayRef', lazy_build => 1 ); sub _build_connect_info{ my $self = shift; Config::App::config->{connect_info}; } sub _build_db{ my $self = shift; DB->new( connect_info => $self->connect_info ); } __PACKAGE__->meta->make_immutable(); } 1;
Model::App.pm
package Model::App{ use Mouse; use Model; extends Model; has 'table' => ( is => 'ro', isa => 'Str', ); sub find{ my ($self) = @_; my $data; $data = $self->db->single($self->table, {}); return $data; } __PACKAGE__->meta->make_immutable(); }
※Model.pmを継承して
Model::Posts
package Model::Posts{ use Mouse; use Model::App; extends Model::App; has 'table' => ( is => 'ro', isa => 'Str', default => 'posts' ); __PACKAGE__->meta->make_immutable(); }
※Model::Postsでテーブルを指定
実行ソース
#!/usr/bin/env perl use strict; use warnings; use FindBin; use lib "$FindBin::Bin/lib"; use Data::Dumper; use Model::Posts; my $model = new Model::Posts(); my $data = $model->find(); print Dumper($data->id, $data->title, $data->body);
↓
[vagrant@localhost teng2]$ perl sample.pl $VAR1 = '2'; $VAR2 = 'test2'; $VAR3 = 'body2'; [vagrant@localhost teng2]$
こんな感じかな?
機能やテーブルなどをうまく調整してメソッドを別途実装して個別対応していくことになるかも…
基本、phpやjavaしか知らないからそれぞれの言語に合わせた実装を理解する必要があります。
まとめ
perlを使用したModuleの使用にはまだ慣れていないけどなんとか形になってきた感じ。
何度も書いて検証を続けていかないと
ちょっとMojoliciousのサンプルで動かせるかなども検証する必要がある
MojoliciousでCSRFを実施
Mojoliciousでは内部実装可能
なんかtokenが同じ値なのでなんかおかしいかも…
サンプル
コントローラーのモジュール
package Sample::Web::Test1; use Mojo::Base 'Mojolicious::Controller'; use Mojolicious::Validator; use Mojolicious::Validator::Validation; # This action will render a template sub index { my $self = shift; # template変数を設定 #$self->stash->{msg} = "index"; $self->app->log->debug("index"); # template配下のtest1.aaa.html.ep $self->render(); } sub post { my $self = shift; # template変数を設定 #$self->stash->{msg} = "index"; # undefを設定してクリア $self->session->{csrf_token} = undef; $self->app->log->debug("new"); #$self->app->log->debug($self->session->{csrf_token}); if($self->session->{errors}){ $self->app->log->debug("error !!!"); $self->stash->{errors} = $self->session->{errors}; }else{ $self->stash->{errors} = undef; } $self->session->{errors} = undef; # template配下のtest1.aaa.html.ep $self->render('test1/post'); } sub conf { my $self = shift; my $validation = $self->validation; my $messages; if ($validation->csrf_protect->has_error('csrf_token') ) { return $self->render_not_found(); } if ($validation->required('title')->has_error('title') ) { push @$messages, 'title error !'; } if ($validation->required('body')->has_error('body') ) { push @$messages, 'body error !'; } my $cnt = scalar(@$messages); if($cnt > 0){ $self->session->{errors} = $messages; $self->redirect_to('/test1/new'); } # template変数を設定 #$self->stash->{msg} = "index"; $self->app->log->debug("conf"); $self->app->log->debug($self->param('title')); $self->app->log->debug($self->param('body')); $self->stash->{title} = $self->param('title'); $self->stash->{body} = $self->param('body'); # template配下のtest1.aaa.html.ep $self->render(); } sub create { my $self = shift; $self->redirect_to('/test1'); } 1;
※「$self->session->{csrf_token} = undef;」を設定することで毎回tokenの値を振り直し
※バリデータのモジュールでチェックなどを行う
CSRFは失敗時はエラー処理を実施するけど、入力データ不備の場合は前の画面へ戻す
テンプレート
% layout 'default'; % title 'Welcome'; % if ($errors) { <b>Error!</b> <ul> % for my $error (@$errors) { <li><%= $error %></li> % } </ul> % } <h1>入力してpostする画面</h1> <form action="./conf" method="post"> <input type="hidden" name="csrf_token" value="<%= csrf_token %>" /> <form role="form"> <div class="form-group"> <label for="title">タイトル</label> <input type="text" class="form-control" id="title" name="title" placeholder="タイトル"> </div> <div class="form-group"> <label for="body">Password</label> <input type="text" class="form-control" id="body" name="body" placeholder="本文"> </div> <button type="submit" class="btn btn-default">確認する</button> </form> </form>
※csrf_tokenというヘルパーが存在するのでそれを使用してtokenを設定する
所感
チェックするのをコントローラーでやらずにモデルとかでやったりといろいろ工夫することを追加して対応してみる必要があります。基本的な部分を少しずつうめていって対応して行くようにする
PerlでTengを使用したDB操作
準備
データベース作成
create database sample_db1;
テーブルを作成
create table posts( id int auto_increment NOT NULL, title varchar(50), body varchar(256), created DATETIME, modified DATETIME, primary key(id) );
適当にデータを突っ込んでおく
insert into posts(title, body) values('test1', 'body1'); insert into posts(title, body) values('test2', 'body2'); insert into posts(title, body) values('test3', 'body3');
cpanmでTengを入れる
cpanm Teng
モジュールを作成
lib/DB.pm
package DB; use parent 'Teng'; 1;
※Tengを継承したものを用意
lib/DB/Schema.pm
package DB::Schema; use strict; use warnings; use Teng::Schema::Declare; table{ name 'posts'; pk 'id'; columns qw/id title body/; }; 1;
※テーブルスキーマ?の情報を定義したモジュールを用意。使用するテーブルの名前やキーなどの情報を定義するよう
モジュールを使用して実行
sample1.pl
#/usr/bin/env perl use strict; use warnings; use FindBin; use lib "$FindBin::Bin/lib"; use DB; use Data::Dumper; my $obj; $obj = DB->new( connect_info => ['dbi:mysql:sample_db1:localhost', 'root', undef ] ); # 1件参照 my $data; $data = $obj->single('posts', {}); print "single---->\n"; print $data->title . "," . $data->body . "\n"; # 3件参照 $data = $obj->search('posts', {}); print "search---->\n"; while(my $row = $data->next()){ print $row->title . "," . $row->body . "\n"; } # 追加 my $data2; $data2 = $obj->insert('posts' => { 'title' => 'sample1', 'body' => "zzzzzzzz1111" }); print "insert row---->\n"; print $data2->id . "," . $data2->title . "," . $data2->body . "\n"; # 更新 my $data3; $data3 = $obj->update('posts' => { 'body' => 'xxxxxxxxxxxxx' }, { 'title' => 'sample1' }); print "update count---->\n"; print $data3 . "\n"; # 削除 $data3 = $obj->delete('posts' => { 'title' => 'test1' }); print "delete count---->\n"; print $data3 . "\n"; # SQL my $sql = "select * from posts order by id desc "; my $res; $res = $obj->do($sql); print Dumper($res);
※doを使用してもデータ自体は取得してくれないのかな???
結果
[vagrant@localhost teng1]$ perl sample1.pl single----> test1,body1 search----> test1,body1 test2,body2 test3,body3 insert row----> 4,sample1,zzzzzzzz1111 update count----> 1 delete count----> 1 $VAR1 = 3; [vagrant@localhost teng1]$
table内
mysql> select * from posts; +----+---------+---------------+---------+----------+ | id | title | body | created | modified | +----+---------+---------------+---------+----------+ | 2 | test2 | body2 | NULL | NULL | | 3 | test3 | body3 | NULL | NULL | | 4 | sample1 | xxxxxxxxxxxxx | NULL | NULL | +----+---------+---------------+---------+----------+ 3 rows in set (0.00 sec) mysql>
DB::Schema…
なんかこれがどこでuseされているかわからないけどおそらくDB.pmを使用する際に参照している感じかな?
sample1.plをモデル化する?
ある程度機能をまとめたモジュールとして用意して、いくことでモデル化して対応出来る感じかな?
トランザクション
sample2.pl
#/usr/bin/env perl use strict; use warnings; use FindBin; use lib "$FindBin::Bin/lib"; use DB; use Data::Dumper; my $obj; $obj = DB->new( connect_info => ['dbi:mysql:sample_db1:localhost', 'root', undef ] ); # トランザクション $obj->txn_begin(); # 1件参照 my $data; $data = $obj->single('posts', {}); print "single---->\n"; print $data->title . "," . $data->body . "\n"; # 3件参照 $data = $obj->search('posts', {}); print "search---->\n"; while(my $row = $data->next()){ print $row->title . "," . $row->body . "\n"; } # 追加 my $data2; $data2 = $obj->insert('posts' => { 'title' => 'sample1', 'body' => "zzzzzzzz1111" }); print "insert row---->\n"; print $data2->id . "," . $data2->title . "," . $data2->body . "\n"; # ロールバック $obj->txn_rollback();
↓
[vagrant@localhost teng1]$ perl sample2.pl single----> test2,body2 search----> test2,body2 test3,body3 sample1,xxxxxxxxxxxxx insert row----> 5,sample1,zzzzzzzz1111 [vagrant@localhost teng1]$
table
mysql> select * from posts; +----+---------+---------------+---------+----------+ | id | title | body | created | modified | +----+---------+---------------+---------+----------+ | 2 | test2 | body2 | NULL | NULL | | 3 | test3 | body3 | NULL | NULL | | 4 | sample1 | xxxxxxxxxxxxx | NULL | NULL | +----+---------+---------------+---------+----------+ 3 rows in set (0.00 sec) mysql>
※rollbackしたので戻っている
ディレクトリ構成
[vagrant@localhost teng1]$ tree . ├── lib │ ├── DB │ │ └── Schema.pm │ └── DB.pm ├── sample1.pl ├── sample2.pl └── sql └── create.sql
PerlでWebアプリのモデルなしサンプル
なんか色々と迷走している感じ、調べているけどどんなものを作成するのがいいかで結構悩み中
Mojoliciousで作成する
生成
$ mojo generate app Sample::Web
↓
[vagrant@localhost mojo1]$ mojo generate app Sample::Web [mkdir] /vagrant/perl/mojo1/sample_web/script [write] /vagrant/perl/mojo1/sample_web/script/sample_web [chmod] sample_web/script/sample_web 744 [mkdir] /vagrant/perl/mojo1/sample_web/lib/Sample [write] /vagrant/perl/mojo1/sample_web/lib/Sample/Web.pm [mkdir] /vagrant/perl/mojo1/sample_web/lib/Sample/Web [write] /vagrant/perl/mojo1/sample_web/lib/Sample/Web/Example.pm [mkdir] /vagrant/perl/mojo1/sample_web/t [write] /vagrant/perl/mojo1/sample_web/t/basic.t [mkdir] /vagrant/perl/mojo1/sample_web/log [mkdir] /vagrant/perl/mojo1/sample_web/public [write] /vagrant/perl/mojo1/sample_web/public/index.html [mkdir] /vagrant/perl/mojo1/sample_web/templates/layouts [write] /vagrant/perl/mojo1/sample_web/templates/layouts/default.html.ep [mkdir] /vagrant/perl/mojo1/sample_web/templates/example [write] /vagrant/perl/mojo1/sample_web/templates/example/welcome.html.ep [vagrant@localhost mojo1]$ $
ディレクトリ構成
[vagrant@localhost mojo1]$ tree . └── sample_web ├── lib │ └── Sample │ ├── Web │ │ └── Example.pm │ └── Web.pm ├── log ├── public │ └── index.html ├── script │ └── sample_web ├── t │ └── basic.t └── templates ├── example │ └── welcome.html.ep └── layouts └── default.html.ep 11 directories, 7 files [vagrant@localhost mojo1]$
起動
[vagrant@localhost mojo1]$ morbo sample_web/script/sample_web Server available at http://127.0.0.1:3000.
Web.pm
sample_web/lib/Sample/Web.pm
package Sample::Web; use Mojo::Base 'Mojolicious'; # This method will run once at server start sub startup { my $self = shift; # Documentation browser under "/perldoc" $self->plugin('PODRenderer'); # Router my $r = $self->routes; # Normal route to controller $r->get('/')->to('example#welcome'); $r->get('/test1')->to('test1#index'); $r->get('/test1/new')->to('test1#post'); $r->post('/test1/create')->to('test1#create'); } 1;
※なんか適当に追加
新しくTest1.pm追加
package Sample::Web::Test1; use Mojo::Base 'Mojolicious::Controller'; # This action will render a template sub index { my $self = shift; # template変数を設定 #$self->stash->{msg} = "index"; $self->app->log->debug("index"); # template配下のtest1.aaa.html.ep $self->render(); } sub post { my $self = shift; # template変数を設定 #$self->stash->{msg} = "index"; $self->app->log->debug("new"); # template配下のtest1.aaa.html.ep $self->render('test1/post'); } sub create { my $self = shift; $self->redirect_to('/test1'); } 1;
template
layouts/default.html.ep
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="/css/bootstrap.min.css"> <link rel="stylesheet" href="/css/bootstrap-theme.min.css"> <title><%= title %></title> </head> <body> <div class="header"> </div> <div class="container"> <%= content %> </div> <div class="footer"> </div> <script src="/js/jquery-2.1.1.min.js"></script> <script src="/js/bootstrap.min.js"></script> </body> </html>
test1/index.html.ep
% layout 'default'; % title 'Welcome'; <h1>一覧を表示する画面</h1> <a href="/test1/new" class="btn btn-default">新規</a> <br /> <div class="row"> <br /> <table class="table"> <tr> <td>1</td> <td>タイトル1</td> <td>本文1</td> </tr> <tr> <td>2</td> <td>タイトル2</td> <td>本文2</td> </tr> <tr> <td>3</td> <td>タイトル2</td> <td>本文3</td> </tr> </table> </div>
post.html.cp
% layout 'default'; % title 'Welcome'; <h1>入力してpostする画面</h1> <form action="./create" method="post"> <form role="form"> <div class="form-group"> <label for="title">タイトル</label> <input type="text" class="form-control" id="title" placeholder="タイトル"> </div> <div class="form-group"> <label for="body">Password</label> <input type="text" class="form-control" id="body" placeholder="本文"> </div> <button type="submit" class="btn btn-default">登録する</button> </form> </form>
※デザインはtwitter bootstrapを使用する
確認
↓
モデルはまだ
モデルを介したオブジェクトの操作をperlでうまく再現できていないのでサンプルをそのまま流用しても対応出来ない感じがする。
先にDBIかTengを使用したオブジェクトの制御の学習をしないといけない
所感
Mojolicoousのアプリケーションをliteではないappの方で行った複数のファイルに分割できる分管理はしやすくなった分、データの流れを上手く把握しないと動かせない感じです。
基本的なコントローラーとビューはわかったけどモデルの制御というか他のモジュールとの連携をうまく使えないと失敗するかもモジュールの継承などをうまく使えないときちんと学習する必要があります。
Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)
- 作者: 和田裕介,石田絢一(uzulla),すがわらまさのり,斎藤祐一郎
- 出版社/メーカー: 技術評論社
- 発売日: 2014/03/11
- メディア: 大型本
- この商品を含むブログ (5件) を見る
Webアプリエンジニア養成読本[しくみ、開発、環境構築・運用…全体像を最新知識で最初から! ] (Software Design plus)
- 作者: 和田裕介,石田絢一(uzulla),すがわらまさのり,斎藤祐一郎
- 出版社/メーカー: 技術評論社
- 発売日: 2014/03/11
- メディア: 大型本
- この商品を含むブログ (5件) を見る
perlの学習(再帰方法)
再帰処理?
なんか自身の関数を呼び出す処理。これがあるコードはデータの流れを理解するのに時間がかかる。
実際、苦手。
簡単なやつ
sample1.pl
#/usr/bin/env perl use strict; use warnings; func(10); sub func{ my ($a) = @_; printf("%04d\n", $a); if($a > 1){ func($a -1); } }
↓
[vagrant@localhost perl]$ perl sample1.pl 0010 0009 0008 0007 0006 0005 0004 0003 0002 0001 [vagrant@localhost perl]$
※シンプルな指定値から繰り返して最小値になったら終わるやつ
階乗
sample2.pl
#/usr/bin/env perl use strict; use warnings; my $b = func2(5); print $b . "\n"; sub func2{ my ($a) = @_; if($a > 1){ return $a * func2($a -1); }else{ return 1; } }
↓
[vagrant@localhost perl]$ perl sample2.pl 120 [vagrant@localhost perl]$
累乗?なんか 2 ^ 3 → 2 * 2 * 2みたいなやつ
#/usr/bin/env perl use strict; use warnings; my $b = func3(2, 8); print $b . "\n"; sub func3{ my ($a, $b) = @_; if($b > 1){ return $a * func3($a, $b - 1) }else{ return $a; } }
↓
[vagrant@localhost perl]$ perl sample3.pl 256 [vagrant@localhost perl]$
所感
単純なものはこんな感じ、プログラムとしてアルゴリズムを考えたら結構時間がかかる。
普段使用していることは頭に入っている分、やり方は簡単ですけど
知らないことの場合はまず仕組みを理解することから始まるから結構たいへんな感じです。