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

Hi,

I saw in one of the posting this snippet and got very curious about it...
Basically, I'm not sure why the two 'open' functions inside the for loop are not giving the same output which is to open the heredoc.

I have been reading the open function but couldn't figure it out.
Can anyone explain this?
#!/usr/bin/perl use strict; my $file1 = <<END_FILE2; abc END_FILE2 for my $i (\$file1) { open my $myfile, '<', $i or die "cannot open file"; #open my $myfile, "< $i" or die "cannot open file"; }

Replies are listed 'Best First'.
Re: Open Function Question
by ikegami (Patriarch) on Apr 17, 2009 at 19:36 UTC

    "< $i" results in a string similar to "< SCALAR(0x814f66c)" because references can't exist in a string (by definition). open my $myfile, "< $i" doesn't find a file named SCALAR(0x814f66c), so it returns an error.

    Since 5.8, when you use the three arg form of open and the third arg is a scalar reference, the referenced scalar is used as a virtual file from which data can be read or to which data can be written.

      If it is a scalar, then shouldn't the line below work? I guess in this situation, how do you open the heredoc using the 2 arguments of "open"?
      open my $myfile, "< $$i" or die "cannot open file";
        I think you are getting more confused. You don't "open" a heredoc. $$i will contain the string "abc\n", so open will attempt to open a file with that name. A newline may or may not be a valid character for a file name, so you may or may not be able to even create a file with such a name to read from. Once you put quotes around a variable, it stringifies it, so the value returned from the quote operator is no longer a reference, it's a string, which is why $i didn't work as you expected either.

        Before going on, I'd like to know if you realize that

        my $file1 = <<END_FILE2; abc END_FILE2

        is just another way of writing

        my $file1 = "abc\n";

        how do you open the heredoc using the 2 arguments of "open"?

        Neither know anything about heredocs. Your request to open a heredoc is nonsense.

        As for the ability to create file handles that read from or write to a scalar, the 2-arg version can't do that.

        If $i is some string, like: $i = 'abc/def', then,
        open (my $myfile, "$i") or die... open (my $myfile, "<$i")or die... #no space after < open (my $myfile, '<', "$i") or die... take your pick...
        open (my $myfile, '<', \$i) or die...

        UPDATE:

        open (my $myfile, "$i") or die... open (my $myfile, $i) or die... open (my $myfile, "<$i")or die... #no space after < required open (my $myfile, "< $i")or die... open (my $myfile, '<', "$i") or die... open (my $myfile, '<', $i) or die... \$i is wrong above....
Re: Open Function Question
by kennethk (Abbot) on Apr 17, 2009 at 19:35 UTC

    This is just conjecture, but I think what is happening is that in the second case you are stringifying your reference.

    The terms after the open are just an argument list. By using the 2-argument form of open, you are creating a string that looks like < SCALAR(0x182f4c4). Open then takes that string and looks for a file named SCALAR(0x182f4c4), which presumably does not exist on your system. This is in contrast to three argument form, where you actually pass the reference to the variable.

Re: Open Function Question
by BrowserUk (Patriarch) on Apr 17, 2009 at 19:42 UTC
Re: Open Function Question
by Bloodnok (Vicar) on Apr 17, 2009 at 19:31 UTC
    From the very top of [perlfunc://open], you'll see the following
    • open FILEHANDLE,EXPR
    • open FILEHANDLE,MODE,EXPR
    The first is commonly referred to as the 2 argument open, whereas the 2nd is commonly known as the 3 argument open.

    In your code snippet, the 1st call is an example of the 3 arg open and the 2nd is ...

    The docs couldn't be much clearer.

    A user level that continues to overstate my experience :-))
Re: Open Function Question
by johngg (Canon) on Apr 17, 2009 at 20:24 UTC

    You can, if you wish, open the filehandle against a reference to the HEREDOC.

    $ perl -e ' -> open $fh, q{<}, \ <<EOD or die qq{open: <<HEREDOC: $!\n}; -> abc -> def -> EOD -> print qq{$.: $_} while <$fh>;' 1: abc 2: def $

    I hope this is of interest.

    Cheers,

    JohnGG

Re: Open Function Question
by Marshall (Canon) on Apr 18, 2009 at 06:07 UTC
    I looked again at your question and it looks to me like the problem is more a misuse of the "heredoc" rather than an open() question. A "heredoc" is often used say for a long bunch of text that you want to perhaps print or use in some other way. It is just a shorthand way of making a single string out of multi-line text.
    print <<END; This is some long winded window text that could appear somewhere and using this heredoc allows me to type it in without having to double quote it or put in "." concatenations or "\\n" characters as this will be printed verbatim just like it is except note that I had to double escape the newline! Otherwise it would be a "newline"! END
    So a "heredoc" just makes a string! There is no "open" involved, it is just a string like any other string. If you want to iterate over a number of constant values in your program, there are other ways:
    1. Use @stuff like this: @stuff = qw (thing1 thing2 thing3);foreach (@stuff){..blah..}
    2. For some test data, use a __DATA__ segment placed after your executable code. The DATA file handle doesn't need to opened or closed - you can just read from it.
    I'm saying that putting a list of file names inside of a "heredoc" is a rather weird looking thing to do.
    while (<DATA>) { chomp; #just to show you what the \n is there #just like from a file.. print "$_\n"; } __DATA__ thing1 thing2 thing3
    There are a number of variations on open() which I think have been covered quite well below. I didn't know before that $somevar could be opened as a a RAM file (a memory resident temp file) in Perl 5.8. I've always just generated a "real" temp file in the past.

    You cannot write to a "heredoc", nor to the DATA filehandle.

      I understand what you are saying and when I saw the heredoc with the open function, I found it weird.
      As you pointed out, I love to use __DATA__ to test my data and have always used it.
      I was just curious as to how somehow was able to use heredoc with an open function.