Inconsistency in misuse of "reverse" in list context [closed] - perl

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
print reverse "word"; # prints 'word'
print reverse foreach ("word"); # prints nothing (empty string)
I am using Perl v5.24.
list context is forced by print, and these statements are "bad"
because reverse should be called in scalar contest to be useful.
Nevertheless, why the inconsistency?

print reverse foreach ("word"); # prints nothing (empty string)
What you have written is
for ( 'word' ) {
print reverse();
}
That code clearly executes the loop just once with $_ set to word, and prints a reversed empty list
Perhaps you should avoid statement modifiers until you are more familiar with the language
As tjd comments, reverse will reverse either a list or a string. In list context (as imposed by the call to print) it expects a list of parameters to reverse, and ignores $_. In scalar context it would just concatenate all parameters passed to it and reverse the resulting string; in the absence of any parameters it will reverse the string in $_

The reverse can indeed be used in either scalar context
perl -wE'$w = "hello"; $r = reverse $w; say $r' # olleh
or in list context
perl -wE'say join " ", reverse qw(hello there)' # there hello
Both are useful and there is no "inconsistency" in these behaviors.
One thing to watch out for is that when a list is used in scalar context
perl -wE'say scalar reverse qw(hello there)' # erehtolleh
then the list gets concatenated and reverse returns a string with characters in reverse order.
I am adding another "gotcha" for completeness, even as it has been covered in other answers.
The reverse defaults to $_ in scalar context, as expected. However, in list context it just doesn't take $_, and in for (#ary) { print reverse; }, with list context imposed on it by print, it has no arguments and thus prints nothing.

In scalar context, reverse reverses the characters of a string.
my $s = "abc";
$s = reverse($s);
say $s;
# cba
In list context, reverse reverses the scalars of its argument list.
my #a = qw( abc def ghi );
#a = reverse(#a);
say "#a";
# ghi def abc
Clearly, both uses are very consistent with each other. The only possible lack of consistency between scalar-context reverse and list-context reverse is what happens when you provide no argument expression. Scalar-context reverse defaults to using $_, but doing so would make no sense for list-context reverse, so it doesn't treat that case specially.
That means the reason print reverse for "word"; prints nothing is that the reverse of zero items is zero items.

Related

what is the difference between print #array and print "#array" in perl? [duplicate]

This question already has answers here:
Printing an array within double quotes
(5 answers)
Closed 5 years ago.
Consider the below code for example:
#array=(1..10);
print #array;
print "#array";
The output is as follows:
12345678910
1 2 3 4 5 6 7 8 9 10
This is a question about string conversion and interpolation. In perl, " is treated differently to ', in that perl is asked to interpolate any variables in the string.
That's why:
my $str = "fish";
print "This is a $str\n";
Works. (With single quotes, it wouldn't). But for things that aren't strings, perl applies some conversion rules. Pretty basic for most cases - a numeric value gets turned into the string equivalent (in base 10). So:
my $num = 10;
print "The number is $num\n";
"just works" rather than forcing you to use printf/sprintf to format convert a numeric value to an appropriate representation.
So the reason you get your first result is that print takes a list of arguments.
So print #array is actually print 1,2,3,4,5,6,7,8,9,10;.
That gives you the result, because you haven't specified a separator to your print. (You can do this by setting $, - see below)
However "#array" is using #array in an explicitly stringified context, and so first it unpacks the array and space separates it.
This behaviour is controlled by the special variable $". You can read about this in perlvar
$" = ":";
print "#array";
See also: Interpolating Arrays into Strings
You can also 'tell' print to separate the values it's got, using $,. By default, it's not set (e.g. is undef - see also perlvar) - so you get your first behaviour.
But you could:
$, = ",";
print #array;

In Perl what is the difference between double quotes("), single quotes(') and grave accent(`) [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 6 years ago.
Improve this question
In Perl, what is the difference between quoting with double quotes("), single quotes('), and grave accents(`)?
This code:
#!/bin/env perl
use v5.10;
say "Hello";
say 'Hi';
say `Hola`;
gives the following result:
Hello
Hi
Single quotes ''
Construct strings without interpolation. There is also a q() operator that does the same.
my $foo = 'bar';
print '$foo'; # prints the word $foo
print q($foo); # is equivalent
You would use single quotes when you just have text and there are no variables inside the text.
Double quotes ""
Construct strings with interpolation of variables. There is also a qq() operator that does the same.
my $foo = 'bar';
print "$foo"; # prints the word bar
print qq($foo); # is equivalent
Use these if you want to put variables into your string. A typical example would be in an old-fashioned CGI program, where you see this:
print "<td>$row[0]</td>";
The qq() variant comes in handy if your text contains double-quotes.
print qq{$link_text}; # I prefer qq{} to qq()
This is way easier to read than escape all the quotes.
print "$link_text"; # this is hard to read
Backticks ``
Shell out and execute a command. The return value of the other program is returned. There is also a qx() operator that does the same. This interpolates variables.
print `ls`; # prints a directory listing of the working directory
my $res = qx(./foo --bar);
Use this if you want to write a script that is a bit more powerful than a shell script, where you need to call external programs and capture their output.
All the interpolating ones can only interpolate variables, not commands.
my $foo = 1;
my $bar = 2;
print "$foo + $bar";
This will print 1 + 2. It will not actually calculate and print 3.
All of those (and more) are explain in perlop under Quote and Quotelike operators.

Im using Perl for the first time [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
Im taking a Bioinformatics class and I keep getting an "Undefined subroutine &main::Print called at ReverseComp.txt line 4." error
# ReverseComp.txt => takes DNA sequence from user
# and returns the reverse complement
print ("please input DNA sequence:\n");
$DNA =<STDIN>;
$DNA =~tr/ATGC/TACG/; # Find complement of DNA sequence
$DNA =~reverse ($DNA); # Reverse DNA sequence
print ("Reverse complement of sequence is:\n");
print $DNA."\n";
This is my code and I have tried a few different things with line 4 but with no results. Any suggestions? (I am writing this from a prompt, everything looks right....)
I have some notes related to your code:
Name your scripts with the .pl extension instead of .txt. That is the common accepted extension for Perl scripts (and the .pm for Perl modules, libraries with reusable code)
Always start your scripts with use strict; use warnings;. These sentences helps you to avoid common mistakes.
Declare your variables before you use it (See the my function)
chomp your input from STDIN to remove the newline at the end.
The call to reverse function is odd. I think that $DNA =~ reverse ($DNA); should be $DNA = reverse ($DNA);
The reverse function is more common used with Perl arrays; with a string you get the reversed version of that string, as I guest you expected.
The print function may take a list of parameters, so you can print several things in one sentence
You can omit parentheses in many places, e.g. reverse($a) is the same as reverse $a. Both are valid, but the latter is more suitable to the Perl style of writing code. The Perl style guide is a recommended read
Related to your question, I think your script is right, because the print function exists in Perl, and the error you got says about Print (with uppercase, which is important in Perl). You maybe run a different script that you have posted here.
This is your script with the previous considerations applied (ReverseComp.pl):
use strict;
use warnings;
print "please input DNA sequence:\n";
chomp( my $DNA = <STDIN> );
$DNA =~ tr/ATGC/TACG/; # Find complement of DNA sequence
$DNA = reverse $DNA; # Reverse DNA sequence
print "Reverse complement of sequence is:\n", $DNA, "\n";
In any case, welcome to the fantastic Perl world, and be prepared to enjoy your trip.

Perl operators that modify inputs in-place

I recently took a Perl test and one of the questions was to find all the Perl operations that can be used to modify their inputs in-place. The options were
sort
map
do
grep
eval
I don't think any of these can modify the inputs in-place. Am I missing anything here or is the question wrong?
Try this:
my #array = qw(1 2 3 4);
print "#array\n";
my #new_array = map ++$_, #array;
print "#new_array\n";
print "#array\n"; # oops, we modified this in-place
grep is similar. For sort, the $a and $b variables are aliases back to the original array, so can also be used to modify it. The result is somewhat unpredictable, depending on what sorting algorithm Perl is using (which has historically changed in different versions of Perl, though hasn't changed in a while).
my #arr = qw(1 2 3 4 5);
my #new = sort { ++$a } #arr;
print "#arr\n";
do and eval can take an arbitrary code block, so can obviously modify any non-readonly variable, though it's not clear whether that counts as modifying inputs in place. Slade's example using the stringy form of eval should certainly count though.
I'm assuming the question is testing to see if the student knows to properly use the return values of sort, map, and so on instead of using them in void context and expecting side effects. It's totally possible to modify the parameters given, though.
map and grep alias $_ to each element, so modifying $_ will change the values of the variables in the list passed to it (assuming they're not constants or literals).
eval EXPR and do EXPR can do anything, more or less, so there's nothing stopping you from doing something like:
my $code = q($code = 'modified');
eval $code;
say $code;
The arguments to do BLOCK and eval BLOCK are always a literal block of code, which aren't valid lvalues in any way I know of.
sort has a special optimization when called like #array = sort { $a <=> $b } #array;. If you look at the opcodes generated by this with B::Concise, you'll see something like:
9 <#> sort lK/INPLACE,NUM
But for a question about the language semantics, an implementation detail is irrelevant.

Why does my Perl print show HASH(0x100a2d018)?

Here I am thinking I know how to use lists in Perl, when this happens. If I do this (debugging code, prettiness not included):
#! /usr/bin/perl -w
use strict;
my $temp1 = "FOOBAR";
my $temp2 = "BARFOO!";
my #list = { $temp1, $temp2 };
print $temp1; #this works fine
print $list[0]; #this prints out HASH(0x100a2d018)
It looks like I am printing out the address of the second string. How do I get at the actual string stored inside the list? I assume it has something to do with references, but dunno for sure.
my #list = { $temp1, $temp2 };
should be
my #list = ( $temp1, $temp2 ); # Parentheses instead of curly braces.
What your original code did was store a reference to a hash {$temp1 => $temp2} into #list's first element ($list[0]). This is a perfectly valid thing to do (which is why you didn't get a syntax error), it's just not what you intended to do.
You already got the answer to your question, don't use {}, because that creates an anonymous hash reference.
However, there is still the matter of the question you didn't know you asked.
What is the difference between an array and a list in Perl?
In your question, you use the term 'list' as if it were interchangeable with the term array, but the terms are not interchangeable. It is important to understand the what the difference is.
An array is a type of variable. You can assign values to it. You can take references to it.
A list is an ordered group of zero or more scalars that is created when an expression is evaluated in a list context.
Say what?
Ok, conisder the case of my $foo = (1,2,3). Here $foo is a scalar, and so the expression (1,2,3) is evaluated in a scalar context.
On the surface it is easy to look at (1,2,3) and say that's a literal list. But it is not.
It is a group of literal values strung together using the comma operator. In a scalar context, the comma operator returns the right hand value, so we really have ((1 ,2),3) which becomes ((2),3) and finally 3.
Now my #foo = (1,2,3) is very different. Assignment into an array occurs in a list context, so we evaluate (1,2,3) in list context. Here the comma operator inserts both sides into the list. So we have ((1,2),3) which evaluates to (list_of(1,2),3) and then list_of(list_of(1,2),3), since Perl flattens lists, this becomes list_of(1,2,3). The resulting list is assigned into #foo. Note that there is no list_of operator in Perl, I am trying to differentiate between what is commonly thought of as a literal list and an actual list. Since there is no way to directly express an actual list in Perl, I had to make one up.
So, what does all this mean to someone who is just learning Perl? I'll boil it down to a couple of key points:
Learn about and pay attention to context.
Remember that your array variables are arrays and not lists.
Don't worry too much if this stuff seems confusing.
DWIM does, mostly--most of the time the right things will happen without worrying about the details.
While you are pondering issues of context, you might want to look at these links:
Start with the discussion of context in Programming Perl. Larry et alia explain it all much more clearly than I do.
Perlop means something entirely different when you pay attention to what each operator returns based on context.
A nice discussion of scalar and context on Perlmonks.
An short introductory article about context: Context is Everything.
MJD explains context.
The perldoc for scalar and wantarray