>@string_array = <STDIN>;
>
>@string_array = reverse(@string_array);
>print("\n@string_array\n");
>print("\n" . reverse(@string_array) . "\n");
>
>
>If this is run, the first print statement prints out the lines in the
>opposite order they were entered, however the second print statement
>reverses the entire line one at a time. I do not understand what is
>going on.
That is a very good question, and it goes right to the heart of a very important and unusual feature of the Perl language, so it'll take a little while to explain. Please bear with me through this explanation of one of Perl's central concepts.
Every Perl expression is in one of two `contexts', either `list context' or `scalar context', depending on whether it is expected to produce a list or a scalar. Many expressions have quite different behaviors in list context than they do in scalar context.
Here is a typical expression:
EXPRESSION
Here it is again, in a list context:
@array = EXPRESSION; # Expression is expected to produce a list
Here is how it looks in a scalar context:
$scalar = EXPRESSION; # Expression is expected to produce a scalar
The values that a particular expression has in these two contexts might be quite different. For example, consider this simple expression:
@q
In list context, this produces a list of the items in the array @q, but in scalar context it produces the number of items in the array @q.
@a = @q; # @q in list context produces a list of items from @q
$s = @q; # but in scalar context, it produces the number of items.
Similarly,
# Note two very different behaviors of // depending on context
# Put ('123.45', 'immediately') into @a
@a = /The amount was \$(\d+\.\d\d)\. You must pay ([\w\s]+)\./
# Put 1 into $s, put '123.45' into $1, put 'immediately' into $2
$s = /The amount was \$(\d+\.\d\d)\. You must pay ([\w\s]+)\./
The main point here: An expression's behavior can be drastically different in list context than it is in scalar context.
Now we'll return to your example.
> @string_array = reverse(@string_array);
Here, reverse is in list context, because it's being asked to produce a list to assign to @string_array. In list context, reverse reverses the order of its arguments, so that the lines come out in the reverse order.
Then you did
> print("\n" . reverse(@string_array) . "\n");
Now, here reverse is in scalar context, because it is being asked to produce a scalar value, a string, which will be concatenated with \n on the front and back. In a scalar context, reverse first concatenates all its arguments, to get a single string, and then reverses that string. As you know by now.
How can you get the behavior you really want? The reverse here needs to be in a list context. The argument list of a function like `print' is always a list context, so if you get rid of the concatenation operators that are providing scalar context to `reverse', your problem will go away:
print "\n", reverse(@string_array), "\n";
reverse is now expected to return a list, which will be inserted into the list which is passed to print. This is probably more efficient than what you were trying to do anyway, since print can print out the many strings without bothering to concatenate them first, as you were doing.
Again, the general rule is:
There is no general rule for deducing a function's behavior in scalar context from its behavior in list context.
This is the cause of a lot of common errors. One mistake you didn't make, but which we see a lot is something like this:
@a = (reverse("part"));
The programmer was expecting @a to get a list containing "trap", but instead they got a list containing "part" again. Because reverse was in a list context, it reversed the order of its arguments, instead of reversing the arguments themselves, and since it only had one argument, it ended up doing nothing.
Perl has a special operator for just such circumstances. It's called scalar, and it forces its argument to be evaluated in scalar context. The last example should have been written as:
@a = (scalar(reverse("part")));
# @a now contains ("trap")
I hope this clears things up for you.
原帖由 penny_kan 于 2007-3-10 22:51 发表
明白了表达的意思,只是不明白为什么会这样
print("\n" . reverse(@string_array) . "\n");
这一句居然reverse 了list本身顺序,因为分格符reverse 了 list中的元素倒是可以理解,
难道这 ...
原帖由 兰花仙子 于 2007-3-10 23:57 发表
没听明白,想要表达what?
@string_array = qw#how are you#;
@string_array = reverse(@string_array);
print("\n@string_array\n");
print("\n" . reverse(@string_array) . "\n");
原帖由 penny_kan 于 2007-3-11 12:45 发表
print("\n" . reverse(@string_array) . "\n");
没明白这句为什么会把list与scalar都reverse一遍。
举例,如果代码是这样
事实第二句的输出内容是
woherauoy
而我的理解是第二 ...
reverse LIST
In list context, returns a list value consisting of the elements of LIST in the opposite order. In scalar
context, concatenates the elements of LIST and returns a string value with all characters in the opposite
order.
print reverse <>; # line tac, last line first
undef $/; # for efficiency of <>
print scalar reverse <>; # character tac, last line tsrif
print("\n" . reverse(@string_array) . "\n"
print("\n" . reverse(@string_array) . "\n"
print("\n" , (@string_array) , "\n"
有许多表达式通常都是产生列表的。当其在标量context 中使用时,会得到什么结果呢?让我们看看这个操作的创始人怎么
解释的。通常,这个人是Larry,其文档展现了整个 ...
原帖由 兰花仙子 于 2008-1-24 23:30 发表
习惯就好了.什么语言都有易混淆之处的.
经常有人批评perl的上下文,其实python不也同样有这个概念...
def test(a,b,c):
return a,b,c
到底是return一个tuple还是三个object呢?
x=test(1,2,3) ...
原帖由 兰花仙子 于 2008-1-24 23:30 发表
习惯就好了.什么语言都有易混淆之处的.
经常有人批评perl的上下文,其实python不也同样有这个概念...
def test(a,b,c):
return a,b,c
到底是return一个tuple还是三个object呢?
x=test(1,2,3) ...
更准确的说,Larry 创建Perl 时,是按照你希望它怎样操作来设
原帖由 orangetouch 于 2008-1-28 13:36 发表
这个问题说是上下文的问题,不如说是reverse的问题。reverse确实是设计得不好的一个函数。
反转一个字符串和反转一个LIST本身就是两种不同的操作,非要用一个函数来示。
这也罢了,而且更怪的是做哪种操作 ...
原帖由 shhgs 于 2008-1-29 13:28 发表
能讲这话的Perler不多。人品没问题。
不过你还是没搞懂上下文。根据返回值决定函数的实现,也是上下文的一种形式。
至于上下文到底是什么。Sorry,真是讲不清楚。连Randy Shawtz在Learning Perl里面 ...
原帖由 nm_0011 于 2008-5-8 16:02 发表
这不是很简单么?
@stray=qw(thank you);
@stray=reverse(@stray); // reverse 处于list上下文下,是将列表中的各项的顺序倒置,得到 you thank
printf("@stray"); // 输出you thank
printf("\n".reverse(@stray)."\n"); reverse 处于scalar上下文下,是将you thank 先转换为字符串再将字符串倒置,得到knahtuoy。
这不是很简单么?
@stray=qw(thank you);
@stray=reverse(@stray); // reverse 处于list上下文下,是将列 ...
nm_0011 发表于 2008-05-08 16:02
欢迎光临 Chinaunix (http://bbs.chinaunix.net/) | Powered by Discuz! X3.2 |