Unknown Region

プログラムでハマったエラーとその解決方法についての備忘録メモ

【Perl】FindBinを使う

以下はファイルの一覧を出力するプログラムです。

用途としては、このプログラムと同階層にあるファイルの一覧を出力したいとします。

プログラム例1(/tmp/example/hoge.pl) :

#/usr/bin/perl
  
use strict;
use warnings;
use utf8;

my @files = glob("./*");
foreach my $file (@files) {
  print($file);
  print("\n");
}

このプログラムには問題があります。

このプログラム内では相対パスを使用しているので、プログラムをどこから実行したかを考慮しなければいけません。

プログラムと同階層のファイル一覧を取得したいのに、実行した場所にあるファイル一覧が取得されてしまいますね。

 

解決方法としては、相対パスをやめて絶対パスを使うのが一番確実です。

でも配置場所が明確に決まっていないために絶対パスを記載するわけには行かないという場合も存在しますよね?

そういう時に便利なのが「FindBin」というモジュール。

これは、プログラム自体のパスを見つけてくれるものです。

先ほどのプログラムを以下の様に修正します。

プログラム例2(/tmp/example/fuga.pl) :

#/usr/bin/perl
  
use strict;
use warnings;
use utf8;
use FindBin;

my @files = glob($FindBin::Bin."/*");
foreach my $file (@files) {
  print($file);
  print("\n");
}

これでプログラムと同階層にあるファイルとディレクトリの一覧が取得できます。

ただこちらの場合は例1とは違い、出力されるファイル一覧も絶対パスになっているのでそれだけは注意しましょう。

主に設定ファイルやテンプレートファイルなどをプログラムと同階層に置きたい場合などに使えますよ!

 

【Java】Mapへの初期代入について

JavaでMapを作成して最初に何か値を代入したい場合、通常は以下のようにすると思います。

 

Java8でのHashMapの生成と代入例:

Map<String, String> map = new HashMap<>();
map.put("hoge", "fuga");
map.put("foo", "bar");

ただ、他の言語を触っている人だと、Mapの作成と同時に値を設定して置きたいと感じるのではないでしょうか。

例えば下のコードのような形です。

 

PerlでのHash(連想配列)の生成と初期代入例:

my %map = ('hoge' => 'fuga', 'foo' => 'bar');

これをJavaでやろうとすると以下のようにすることで実現できます。

 

Java8でのHashMapの生成と初期代入例:

Map<String, String> map = new HashMap<String, String>() {{
  put("hoge", "fuga");
  put("foo", "bar");
}};

ただしJavaでこの方法を使う場合、一点だけ注意が必要です。

それは、mapのインスタンスの実クラスがHashMapではなくHashMapを継承した匿名クラスになってしまうということ。

どういうことかを説明するために、上記のコードを匿名クラスを使わない書き方に変更すると次のようになります。

 

Java8でのHashMapの生成と初期代入例(匿名クラスを使わない):

class ExtendedHashMap extends HashMap<String, String> {
  {
    put("hoge", "fuga");
    put("foo", "bar");
  }
};
Map<String, String> map = new ExtendedHashMap();

ではこれで何か不都合が起こるかという話なのですが、map.getClass()などでクラスの情報を取るような場合に思った通りのクラス名が取得できないというデメリットがあります。

実際に「Java8でのHashMapの生成と初期代入例」のプログラム実行後に、map.getClass().getName()を取得してみると「プログラム名$1」という結果が返ってくるはずです。

自分の組んだプログラム内では問題がなくても、フレームワークや外部モジュールの作りによっては、もしかしたらここが落とし穴になるかもしれませんね。