My First Perl #1

人生初 perl を書いていこうと思います。
頑張るぞ

教材は サンプルコードによるPerl入門 より

perl 自体は lion に入ってたものをそのまま

> perl -v

This is perl 5, version 12, subversion 3 (v5.12.3) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)

Copyright 1987-2010, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

control flow

Perl基礎文法最速マスター を参考にするのでスキップ

fizzbuzz

まずは、やっぱりこれで。
文法を読んだだけなので、エレガントさには欠ける予定

ルール

http://d.hatena.ne.jp/keyword/FizzBuzz より

3と5の公倍数の時は、FizzBuzzとだけ回答するべき。最初の定義では、たとえば15がやってきた時「3の倍数なのでFizzと言う、5の倍数なのでBuzzと言う、3と5の公倍数なのでFizzBuzzと言う、結果、15の時はFizzBuzzFizzBuzzになる」と解釈することも可能である。

定義

  • カウンターを設定、0とする。
  • カウンターに1を加える。
  • カウンターが100(の他、設定した値)を超えたなら、終了する。
  • カウンターが3と5の公倍数であるならば、「FizzBuzz」を出力し、2に戻る。
  • カウンターが3の倍数であるならば、「Fizz」を出力し、2に戻る。
  • カウンターが5の倍数であるならば、「Buzz」を出力し、2に戻る。
  • カウンターの数字を出力し、2に戻る。

実装

こんな感じ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use strict;
use warnings;

for(my $i = 0; $i < 100; ++$i){
  if((0 == ($i % 3)) && (0 == ($i % 5))){
    print "FizzBuzz\n";
  } elsif(0 == $i % 3){
    print "Fizz\n";
  } elsif(0 == $i % 5){
    print "Buzz\n";
  } else {
    print $i . "\n";
  }
}

うむ。正解かどうかわからん。
phpの文法は perl からパクったらしいので、古く慣れ親しんだ php でも描いてみた。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

for($i = 0; $i < 100; ++$i){
  if((0 == ($i % 3)) && (0 == ($i % 5))){
    print "FizzBuzz\n";
    continue;
  }
  if(0 == $i % 3){
    print "Fizz\n";
    continue;
  }
  if(0 == $i % 5){
    print "Buzz\n";
    continue;
  }
  print $i . "\n";
}

うむ。 else区を書きたくない派(あるのか?)の一員としては、単純なループならcontinue使いたくなります。

もう少し凝ってみよう

やっぱり for 文はダサさが目立つので map 文(?) とか 後置文(?) を使ってみたい

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use strict;
use warnings;

my @list = ();
for(my $i = 0; $i < 100; ++$i){
  push @list, $i;
}

my @fizzbuzz = map {
  if(0 == ($_ % 3) && 0 == ($_ % 5)){
    "FizzBuzz"
  } elsif (0 == ($_ % 3)){
    "Fizz"
  } elsif (0 == ($_ % 5)){
    "Buzz"
  } else {
    $_
  }
} @list;

print $_ . "\n" for @fizzbuzz;

配列アクセスは変数として $ を使うけど、配列としてのアクセスは @ を使うのね。
変数が配列なのかどうかが分かりやすいね。この言語。

ただ、 map の戻りを指定するのは、評価された値になるってとこがなんとも。他の式と違うんだね
あとは、map の結果は必ず配列になるハズなのに my @fizzbuzz って宣言するのはなんとも。。。

おわり

次行ってみよう