casiano has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

I can't understand the behavior of mkdir. When called mkdir(@a) it does not work. This seem to be different when using a scalar variable mkdir($a) or a constant argument mkdir('dir'). See the following session with the debugger:

pp2@nereida:~/LGRID_Machine/examples$ perl -wde 0 main::(-e:1): 0 DB<1> @a = ('/tmp/DIRECT', 18) DB<2> x @a 0 '/tmp/DIRECT' 1 18 DB<3> x mkdir(@a) # seems ok 0 1 DB<4> !!ls -ltr /tmp/DIRECT # ... but no: ls: /tmp/DIRECT: No existe el fichero o el directorio (Command exited 2) DB<5> x mkdir('/tmp/DIRECT', 18) # try without a var 0 1 DB<6> !!ls -ltrd /tmp/DIRECT # now it works! d--------- 2 pp2 pp2 4096 2008-03-04 11:43 /tmp/DIRECT DB<7> q

Many thanks

Casiano

Replies are listed 'Best First'.
Re: mkdir with a list variable
by Corion (Patriarch) on Mar 04, 2008 at 12:05 UTC

    mkdir has a prototype of $;$:

    perl -we "print prototype('CORE::mkdir')" $;$

    This means that the first variable in the call to it will be put into scalar context. Most likely, you have now a subdirectory named "2" in ~/LGRID_Machine/examples, because @a evaluated to the number of elements (2).

    To solve your larger problem of calling arbitrary builtins with the appropriate parameters, I think you will have to explicitly pass the parameters:

    mkdir $a[0], $a[1];

    instead of

    mkdir @a;

    Creating the appropriate calls can maybe be done by inspecting prototype("CORE::$function"), but some functions (like print) don't even have a prototype because they are super special.

      Many, many thanks Corion!

      Casiano

      Update:Ah bollocks, that's exactly what the OP wants to do, ignore me please.

      To solve your larger problem of calling arbitrary builtins with the appropriate parameters, I think you will have to explicitly pass the parameters:
      mkdir $a[0], $a[1];

      That won't work, it'll just create the directory $a[0] with the permissions as per filemask $a[1] (at least that's what it does on my 5.8.8 on Linux, is this different on Windows?)

      To the OP: mkdir expects a single directory name. If you want to create multiple directories just do so in a loop, e.g.

      for my $d (@a) { mkdir $d or die "Couldn't create directory $d: $!"; }

      All dogma is stupid.
Re: mkdir with a list variable
by Tanktalus (Canon) on Mar 04, 2008 at 17:10 UTC

    If you have a scenario where you have lots of these arrays floating around and you'd rather not go and change them all to use $array[0], $array[1], you could just put in your code a new function: sub mkdir {CORE::mkdir $_[0],$_[1]} which would then split it up for you.

    I'm pretty sure I've read a few times how prototypes are evil, but I think this is even more evil than normal prototypes: with normal prototypes, I can fake my way around them with the & sigil. Not so with built-ins.

    (...) No, that doesn't work, either. You have to do both: create the function, AND call it with &. Doesn't work:

    $ perl -e '@x=qw(foo 18);sub mkdir{CORE::mkdir($_[0],$_[1])};mkdir(@x) +';ls 2
    Works:
    $ perl -e '@x=qw(foo 18);sub mkdir{CORE::mkdir($_[0],$_[1])};&mkdir(@x +)';ls foo
    Also does not work:
    $ perl -e '@x=qw(foo 18);&mkdir(@x)';ls Undefined subroutine &main::mkdir called at -e line 1.
    *sigh* At that point, you may as well call it "MKdir" so it has a different name, and change all your function calls. That's kind of annoying... it's like super-powered evil prototypes.