パスワードを忘れた? アカウント作成
1281591 journal
日記

okkyの日記: perl の配列 5

日記 by okky

@array = (); と
@array = undef; は、そのあとで要素を突っ込めばきっと同じだ…と思っていたが違うらしい。

#! /usr/bin/perl
 
use strict;
 
our @array;
 
print "test1\n";
@array    = ();
do_same();
print "test1 end\n";
 
print "test2\n";
@array    = undef;
do_same();
print "test2 end\n";
 
sub do_same {
    push @array, ( 1 .. 3 );
    foreach my $i ( @array ) {
    print "$i\n";
    }
}

結果:

$ ./test.pl
test1
1
2
3
test1 end
test2
 
1
2
3
test2 end

みての通り、test2 の場合 1 の前に空行がある。

@array = ( "",  1,  2,  3 )

のようになっているんだろう。どうりで関数へのリファレンスを呼んでるはずが

Use of uninitialized value in subroutine entry at ./code.pl line 93, <STDIN> line 9.
Can't use string ("") as a subroutine ref while "strict refs" in use at ./code.pl line 93, <STDIN> line 9.

のようなエラーが出るはずだ。そりゃ "" は関数へのリファレンスじゃないよね。

ちなみに、これが実装として正しいのか間違っているのかは知らない。個人的には「undefな配列」を強引に参照したら、( "" ) じゃなく () になってほしい、とは思う。もちろん、undefなハッシュでも同じ。

ちなみに、環境は cygwin。

$ perl -V
Summary of my perl5 (revision 5 version 10 subversion 1) configuration:
 
  Platform:
    osname=cygwin, osvers=1.7.5(0.22553), archname=i686-cygwin-thread-multi-64int
    uname='cygwin_nt-5.1 reini 1.7.5(0.22553) 2010-04-12 19:07 i686 cygwin '
    config_args='-de -Dlibperl=cygperl5_10.dll -Dcc=gcc-4 -Dld=g++-4 -Dmksymlinks -Dusethreads -Dmad=y -Doptimize=-O3 -Accflags=-g3'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=define, usemultiplicity=define
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=y, bincompat5005=undef
  Compiler:
    cc='gcc-4', ccflags ='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g3 -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include',
    optimize='-O3',
    cppflags='-DPERL_USE_SAFE_PUTENV -U__STRICT_ANSI__ -g3 -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
    ccversion='', gccversion='4.3.4 20090804 (release) 1', gccosandvers=''
    intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='g++-4', ldflags =' -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--stack,8388608 -Wl,--enable-auto-image-base -fstack-protector -L/usr/local/lib'
    libpth=/usr/local/lib /usr/lib /lib
    libs=-lgdbm -ldb -ldl -lcrypt -lgdbm_compat
    perllibs=-ldl -lcrypt
    libc=/usr/lib/libc.a, so=dll, useshrplib=true, libperl=cygperl5_10.dll
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=dll, d_dlsymun=undef, ccdlflags=' '
    cccdlflags=' ', lddlflags=' --shared  -Wl,--enable-auto-import -Wl,--export-all-symbols -Wl,--stack,8388608 -Wl,--enable-auto-image-base -L/usr/local/lib -fstack-protector'
 
Characteristics of this binary (from libperl):
  Compile-time options: MULTIPLICITY MYMALLOC PERL_DONT_CREATE_GVSV
                        PERL_IMPLICIT_CONTEXT PERL_MAD PERL_USE_SAFE_PUTENV
                        USE_64_BIT_INT USE_ITHREADS USE_LARGE_FILES
                        USE_PERLIO USE_REENTRANT_API
  Locally applied patches:
    CYG11 no-bs
    CYG12 no archlib in otherlibdirs
    CYG14 Dynaloader
    CYG15 static-Win32CORE
    CYG17 utf8-paths
    CYG21 LibList-Kid.patch
    CYG22 cygwin-1.7 hints
    CYG23 544-stat
    CYG24 build man pages
    CYG25 rebase_privlib
    Module-Build-0.36_13
    Bug#55162 CYG18 File::Spec::case_tolerant performance
    disable ExtUtils::MakeMaker::Coverage in Sys-Syslog
  Built under cygwin
  Compiled at Aug 28 2010 20:17:29
  %ENV:
    CYGWIN=""
  @INC:
    /usr/lib/perl5/5.10/i686-cygwin
    /usr/lib/perl5/5.10
    /usr/lib/perl5/site_perl/5.10/i686-cygwin
    /usr/lib/perl5/site_perl/5.10
    /usr/lib/perl5/vendor_perl/5.10/i686-cygwin
    /usr/lib/perl5/vendor_perl/5.10
    /usr/lib/perl5/vendor_perl/5.10
    /usr/lib/perl5/site_perl/5.8
    /usr/lib/perl5/vendor_perl/5.8

この議論は、okky (2487)によって ログインユーザだけとして作成されたが、今となっては 新たにコメントを付けることはできません。
  • by Tsann (15931) on 2012年01月10日 16時20分 (#2078453)

    LISTコンテキストだから
    @array = ( undef );
    になってるだけでは?

    • 「何が起こっているのか」は多分そうなんでしょう。

      「何が起こって欲しいのか」とはかなり違うっていうだけの話で…。

      --
      fjの教祖様
      親コメント
      • 古い格言に曰く、プログラムは思った通りではなく、書いた通りに動く。

        @arrayを未定義値にしたいなら、

        @array = undef;

        ではなく

        undef @array;

        と書くべきだったという話ですかね。

        undefの返値がLISTコンテキストで()と解釈されて欲しいと思うこともあるかもしれませんが、
        それはそれで、

        select undef, undef, undef, 0.1;

        とか書けなくて不便という。

        ある種のLISPにおけるnilの扱いと混同しがちですが、
        結局のところ、Perlにおける()とundefを理解して適切に使い分けるのが吉かと思います。

        混乱したらperldata(1)やperldoc -f undefを読み返しましょう。

        親コメント
        • 「問題が配列の初期化にあるのであって、push の段階にあるのではない」
          (関数へのリファレンスを作って、push している段階は正しい)
          という所に行きつくまでが大変でした。

          そもそもは、ナンプレを解くプログラムのフレームワークの部分を作ってたんですけどね。
          候補を絞り込むための関数を一杯作って、処理の軽い奴から順に配列に push して、[0]から順に適用していく。
          で、[$i] を実行したら「どこかに答の絞り込みが行われた(たとえば、あるマスは今まで「3,5,7」があり得たが、「5」は候補じゃないと判った、とか)場合、その結果に対して[0]から再び適用していく事を繰り返したい。というものを作ろうとして…ここではまったもんで。

          はて、pushの段階ではエラーは出ていないし、「"" が関数じゃない」ってそんなものを押し込んだ覚えはないし…、関数のリファレンスってこうやって作るんじゃなかったのか…あるいは関数のリファレンスをコールする方法が間違ってるのか…と、いろいろ悩んでしまいました。

          一旦原因が判ってしまえば、直すのも、「ん?本当にそういう事??」というのを確認するためのテストコードを書くのも一瞬なんですが…。
          とにかく、「何を与えられようとも、可能な限り実行を続けようといろいろ型変換してくれる」というのは、ありがたくもあり、想定外の動きをした時に何が悪かったのか判らなくなる元でもあり…

          ----

          ちなみにやりたい事は、「仮置き無しで、すべてのナンプレを解くことは可能か?!」知りたい、というものです。

          すべてのマスに対して仮置きを繰り返せばナンプレは必ず解けますから。余りにも必殺すぎてつまらないので、『封じ手』にしたらどうなるのか知りたいのです。
          # 仮置きするとその結果が伝搬して「どこかのマスで矛盾が生じる」から、その仮置きが否定される。
          # ならば矛盾の伝搬を先に追いかける方法があるんじゃないかと…それを使えば「仮置きするはずだったマス」の候補を絞れるのではないかと。

          --
          fjの教祖様
          親コメント
          • 面白そうなので、自分も(好みにより言語はHaskellで)書いてみようと思ったら、
            すでに沢山あって [haskell.org]ちょっとクラクラしました……。

            No guessing [haskell.org]ってのがokkyさんと似た動機で書かれた版かな。
            リスト中のアルゴリズムを順に試して、
            うまく行ったらまたリストの最初から繰り返す、
            という造りも同じようです。

            Sudoku Solver [kyoto-u.ac.jp]等、
            似たようなプログラムが見付かるところを見ると、
            やはり誰しも書きたくなる題材なのですかね。

            時間ができたら自分でも遊んでみたいと思います。
            面白いネタに気付かせて戴いて有難うございました。

            親コメント
typodupeerror

犯人は巨人ファンでA型で眼鏡をかけている -- あるハッカー

読み込み中...