strict

use strictを使うことで、厳密な文法チェックをし、場合によってはエラーを出す。

strict - 文法チェックを厳しくする - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発
厳密な構文チェック - プログラムの基本構成 - Perl入門

たとえば、

#!/usr/bin/perl

# 変数が宣言されていない.
$var1 = 10;
print '$var1 = '."$var1\n";

myやourなどで、変数宣言されてない。

[bg1@dti-vps-srv93 strict]$ vi strict.pl
[bg1@dti-vps-srv93 strict]$ perl strict.pl
$var1 = 10
[bg1@dti-vps-srv93 strict]$

これでも実行はできるが、厳密に文法をチェックして、これをエラーにすることで、コードの質を高めたい。
そういう場合は、

#!/usr/bin/perl

use strict; # 厳密な文法チェック.

# 変数が宣言されていない.
$var1 = 10;
print '$var1 = '."$var1\n";

こうすると、

[bg1@dti-vps-srv93 strict]$ vi strict.pl
[bg1@dti-vps-srv93 strict]$ perl strict.pl
Global symbol "$var1" requires explicit package name at strict.pl line 6.
Global symbol "$var1" requires explicit package name at strict.pl line 7.
Execution of strict.pl aborted due to compilation errors.
[bg1@dti-vps-srv93 strict]$

変数宣言されていないということで、エラーになる。

myで宣言をすれば、

[bg1@dti-vps-srv93 strict]$ vi strict.pl
[bg1@dti-vps-srv93 strict]$ perl strict.pl
$var1 = 10
[bg1@dti-vps-srv93 strict]$

エラーは出ず、実行できる。

ちなみに、warningsやstrictをuseで指定するのは、

[bg1@dti-vps-srv93 strict]$ ls /usr/share/perl5/
AnyDBM_File.pm  DBM_Filter     Getopt      Net             Text           bigint.pm       filetest.pm     sort.pm
App             DBM_Filter.pm  HTTP        Perl            Thread         bignum.pm       if.pm           strict.pm
Archive         Devel          I18N        PerlIO          Thread.pm      bigrat.pm       integer.pm      subs.pm
Attribute       DirHandle.pm   IO          PerlIO.pm       Tie            blib.pm         less.pm         unicore
AutoLoader.pm   Dumpvalue.pm   IPC         Pod             Time           bytes.pm        locale.pm       utf8.pm
AutoSplit.pm    Encode         JSON        Safe.pm         UNIVERSAL.pm   bytes_heavy.pl  open.pm         utf8_heavy.pl
B               English.pm     Locale      Search          Unicode        charnames.pm    overload        vars.pm
Benchmark.pm    ExtUtils       Log         SelectSaver.pm  User           deprecate.pm    overload.pm     vendor_perl
CORE.pod        File           Math        SelfLoader.pm   Version        diagnostics.pm  overloading.pm  vmsish.pm
Class           FileCache.pm   Memoize     Symbol.pm       XSLoader.pm    dumpvar.pl      perl5db.pl      warnings
Compress        FileHandle.pm  Memoize.pm  Term            _charnames.pm  encoding        perlfaq.pm      warnings.pm
Config          Filter         Module      Test            autouse.pm     feature.pm      pod
DB.pm           FindBin.pm     NEXT.pm     Test.pm         base.pm        fields.pm       sigtrap.pm
[bg1@dti-vps-srv93 strict]$

これらが特別な機能ではなく、モジュールだから。

Sample/perl/strict/strict/src/strict at master · bg1bgst333/Sample · GitHub

warnings

use warningsを使うことで、スクリプトをチェックし、警告を出してくれる。

warningsモジュール - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発
厳密な構文チェック - プログラムの基本構成 - Perl入門

たとえば、

#!/usr/bin/perl

# 変数を間違えている.
$var1 = 10;
print '$var1 = '."$var2\n";

$var1に10を入れたのに、$var2を出力しようとしてる。
$var1または$var2を書き間違えている例。
このままだと、

[bg1@dti-vps-srv93 warnings]$ vi warnings.pl
[bg1@dti-vps-srv93 warnings]$ perl warnings.pl
$var1 =
[bg1@dti-vps-srv93 warnings]$

警告を出してくれない。
そこで、

とすると、

[bg1@dti-vps-srv93 warnings]$ vi warnings.pl
[bg1@dti-vps-srv93 warnings]$ perl warnings.pl
Name "main::var2" used only once: possible typo at warnings.pl line 7.
Name "main::var1" used only once: possible typo at warnings.pl line 6.
Use of uninitialized value $var2 in concatenation (.) or string at warnings.pl line 7.
$var1 =
[bg1@dti-vps-srv93 warnings]$

このようにちゃんと警告を出してくれる。

Sample/perl/warnings/warnings/src/warnings at master · bg1bgst333/Sample · GitHub

local

localは、パッケージ変数の値を一時的に退避し、別の値を入れておいて、パッケージスコープを抜けたら、元に戻すことが出来る。

local - パッケージ変数を一時的に退避して復元 - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発

そもそも、これは変数宣言に使うものではないので注意。

$our_var2に2を入れて、PackageAの中では、localを指定しつつ20を入れる。

[bg1@dti-vps-srv93 local]$ vi local.pl
[bg1@dti-vps-srv93 local]$ perl local.pl
$our_var1 = 1
$our_var2 = 2
$our_var1 = 10
$our_var2 = 20
$our_var1 = 10
$our_var2 = 2
[bg1@dti-vps-srv93 local]$

PackageAを抜けた時、$our_var1は10を入れたままになってるのに対し、$our_var2は2に戻っている。
退避したからね。

Sample/perl/local/local/src/local at master · bg1bgst333/Sample · GitHub

our

ourは、パッケージ変数の宣言時に使う。

our - パッケージ変数の宣言 - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発

myで宣言したレキシカル変数は、スコープを抜けると参照できないが、ourで宣言したパッケージ変数は、スコープを抜けても、パッケージ名(完全修飾名)で参照できる。

宣言無し、my、local、でどうなるか検証してみた。
実行すると、

[bg1@dti-vps-srv93 our]$ vi our.pl
[bg1@dti-vps-srv93 our]$ perl our.pl
$unknown_var1 = 1
$my_var1 = 2
$our_var1 = 3
$unknown_var1 =
$my_var1 = 2
$our_var1 = 3
$unknown_var2 = 10
$my_var2 = 20
$our_var2 = 30
$unknown_var1 =
$my_var1 = 2
$our_var1 = 3
$unknown_var2 = 10
$my_var2 =
$PackageA::our_var2 = 30
$our_var2 = 30
$main::our_var2 =
$unknown_var2 =
$PackageA::unknown_var2 = 10
$my_var2 =
$PackageA::my_var2 =
$our_var2 =
$PackageA::our_var2 = 30
[bg1@dti-vps-srv93 our]$

結構ややこしい。

まず、これの値がNULLになる。宣言無しはパッケージブロックに入ると別変数扱いになるようだ。

スコープを抜けても、PackageAの変数で扱われる。(myとourはmainの変数で扱われる。)

ourは完全修飾名で外からもアクセス可能。
しかし、

付けなくてもアクセスできちゃう・・・。
おそらくmainに$our_var2がないので、PackageAのものがあるからそれと認識してるのでは。

mainにはないのを確認。(NULLになったので。)

PackageBからは、$PackageA::unknown_var2と、$PackageA::our_var2が参照でき、それ以外はアクセスできなかった。
ourはどこでも読めるので、完全修飾名であれば読めるのはわかる。
$PackageA::unknown_var2は、our付けてなくてもパッケージ変数として認識されてるのかな。

とにかくややこしい。
そりゃ、my以外使う必要ないって言われるわ・・・。

Sample/perl/our/our/src/our at master · bg1bgst333/Sample · GitHub

my

myは、レキシカル変数の宣言時に使う。

my - レキシカル変数の宣言 - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発

型のある言語でいうところのローカル変数宣言である。
基本的にPerlの場合、変数を宣言しなくても、勝手に変数を生成して値を割り当てるのだが、myを使うのと使わないのではちょっと意味合いが変わってくる。
使わない場合、

$var1 = 1; # $var1を1で初期化.
print '$var1 = '."$var1\n"; # $var1を出力.
{
  print '$var1 = '."$var1\n"; # $var1を出力.
  $var1 = 2; # $var1に2を代入.
  print '$var1 = '."$var1\n"; # $var1を出力.
  {
    $var1 = 3; # $var1に3を代入.
    print '$var1 = '."$var1\n"; # $var1を出力.
    $var1 = 4; # $var1に4を代入.
    print '$var1 = '."$var1\n"; # $var1を出力.
  }
  print '$var1 = '."$var1\n"; # $var1を出力.
}
print '$var1 = '."$var1\n"; # $var1を出力.

こういうコードに対して、

[bg1@dti-vps-srv93 ~]$ vi my.pl
[bg1@dti-vps-srv93 ~]$ perl my.pl
$var1 = 1
$var1 = 1
$var1 = 2
$var1 = 3
$var1 = 4
$var1 = 4
$var1 = 4
[bg1@dti-vps-srv93 ~]$

こういう結果になる。
$var1は一番上の外側の時点で生成される。
ブロックを抜けても中での代入がそのまま外の変数に反映される。
ブロック内で別の変数名とすれば、外から参照できないわけだけど。

myを使って、

一番外と、一番中の下のほうでmyで宣言してる。
こうすると、

[bg1@dti-vps-srv93 my]$ vi my.pl
[bg1@dti-vps-srv93 my]$ perl my.pl
$var1 = 1
$var1 = 1
$var1 = 2
$var1 = 3
$var1 = 4
$var1 = 3
$var1 = 3
[bg1@dti-vps-srv93 my]$

こうなる。
一番中でmy宣言した初期値4の$var1は、ブロックを抜けると参照できなくなる。
その前に一番中で3を代入された$var1は、もともと一番外側で宣言された変数を中で参照しているものなので、以降はその値が出力されている。

Sample/perl/my/my/src/my at master · bg1bgst333/Sample · GitHub

モジュール

もうひととおりモジュールについて説明したけど、改めてモジュールを作ってみる。

Perlモジュール徹底解説 - Perlプログラミング入門ゼミ - Perlでテキスト処理・Linuxサーバー管理・Webシステム開発

今回は、モジュールを置くディレクトリを掘って、その中にモジュールファイルを置く。

[bg1@dti-vps-srv93 module]$ mkdir CustomDirectory
[bg1@dti-vps-srv93 module]$ cd CustomDirectory
[bg1@dti-vps-srv93 CustomDirectory]$ vi CustomModule.pm

で、モジュールを書く。

# Exporter
use Exporter;
@ISA = qw(Exporter);
@EXPORT = qw/func/;

# BEGIN
BEGIN{
  print "This is BEGIN.\n";
}

# END
END{
  print "This is END.\n";
}

# func.
sub func{
  print "func.\n";
}

1; # これがないとエラーメッセージ.

パッケージ名を付けてない。

[bg1@dti-vps-srv93 CustomDirectory]$ cd ..
[bg1@dti-vps-srv93 module]$ vi module.pl

上がってmodule.plを書く。

パッケージ名を付けてなくても、ディレクトリ名::モジュールファイル名(拡張子なしでもいい)で使える。

[bg1@dti-vps-srv93 module]$ perl module.pl
This is BEGIN.
func.
This is END.
[bg1@dti-vps-srv93 module]$

呼べるね。

としても、

[bg1@dti-vps-srv93 module]$ perl module.pl
This is BEGIN.
func.
This is END.
[bg1@dti-vps-srv93 module]$

もちろん呼べる。

Sample/perl/module/module/src/module at master · bg1bgst333/Sample · GitHub

PQgetvalue

PQgetvalueで、指定の位置の値を取得する。

https://www.postgresql.jp/document/8.4/html/libpq-exec.html

j行i列の値を取得することを、すべての行と列で繰り返す。

[bg1@localhost PQgetvalue]$ vi main.c
[bg1@localhost PQgetvalue]$ gcc main.c -o main -lpq
[bg1@localhost PQgetvalue]$ ./main
CONNECTION_OK
PGRES_TUPLES_OK
field_count = 3
tuple_count = 2
name address age
Taro Tokyo 30
Jiro Sendai 28
[bg1@localhost PQgetvalue]$

2行3列の値、すべて取得できた。

Sample/libpq/PQgetvalue/PQgetvalue/src/PQgetvalue at master · bg1bgst333/Sample · GitHub