http://qs321.pair.com?node_id=302287

As part of our continuing crusade against sanity, we of #perlhelp (EFnet) have created a modest perl quiz to test for all the skills required to make the maintainance programmer voluntarily leap into the gaping chasm of madness. We hope it will reinforce everyone's appreciation of our favorite language, by itself and as a tool towards this noble goal.   ;-)

Only those who know and truly understand the answers to all these questions can call themselves [insert awesome title here].

```For all exercises: no fork/exec/system/qx/open, no cmdline options,
no user input, no modules, no tie, no bless, no %SIG.  Make sure you
don't depend on random factors, such as exact values of addresses.
All solutions should be executable from the cmdline using perl -e

For extra points, try to make them work under strict
(warning: for one exercise no strict solution is known (yet))
UPDATE Thanks to mauke, strict solutions are now known for all exercises! :-)
```Exercise 1:  Create an array @x such that changing \$x[0] also sets
\$x[1] to the same value

Exercise 2:  Given a pre-declared function "foo", write a code snippet
that invokes it in an infinite loop; in 10 chars

Exercise 3a: Create \$foo such that \\$foo->[1] == \\$foo->{1}
Exercise 3b: Create \$foo such that \\$foo->[1] == \\$foo->(1)
You must use different solutions for the two

Exercise 4:  Dump core in 6 chars

Exercise 5:  Create a static variable lexically scoped to a sub, and
no wider than that.  It's ok if it blows up under recursion

Exercise 6:  Create \$x, \$y such that \$x eq \$y && \$\$x ne \$\$y

Exercise 7:  Create \$foo such that fileno(\$foo) && !*\$foo

Exercise 8:  Create \$foo such that (\$foo^=0)++ eq \$foo++

Exercise 9a: Create \$foo such that eval(q[\$\$foo]) != eval(q[0+\$\$foo])
Exercise 9b: Create \$foo such that eval(q[\$\$foo =~ / /]) && !\$\$foo

Exercise 10: Make \$x::y::x::y::y::x::y::x::x::y::y::y::y::x::y::y true
in 26 chars of code

Exercise 11: Make <STDOUT> eq <+STDOUT> in 25 chars

Bonus Exercise:  The code snippet 'sub foo{} goto +foo' produces an
error: "Can't find label SCALAR(0x31c70c)"  (the address may vary)
Where does that ref come from?  What does it point to?

Please black-box solutions/spoilers so people can safely read discussion without seeing all the answers. (for example use: <table bgcolor="#00000000"><tr><td><font color="#00000000">Text goes here</font></table>)

UPDATE: clarification of exercise 5: "static variable" means a variable whose value is retained across multiple invocations of the sub (like static vars in C), and being "scoped to a sub and no wider" means that the standard solution { my \$x; sub { ... } } doesn't qualify, because \$x is one block wider than the sub. (it is static though)
UPDATE: minor reformatting to make everything fit in 70 columns
UPDATE: they're designed for 5.8, though most probably have solutions on older versions too.

UPDATE: Strict solutions are now available for all exercises.

UPDATE: (21-7-2004) How's your Perl? (II)

This waste of time is sponsored by:
#perlhelp - Where people with no life teach people with no clue.

Replies are listed 'Best First'.
by tachyon (Chancellor) on Oct 27, 2003 at 03:08 UTC
```# 1
my @x = ( \\$_, \\$_ );

# 2
sub foo { print "Agree :-)\n" }
{foo;redo}

# 4
dump()

The closure bug/feature Unusual Closure Behaviour

```# 5
sub foo {
my \$x if 0;
++\$x;
}

cheers

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"\$'\$`\$\"\$\&"&ee&&y&srve&&d&&print

Though I'm almost certain that's what the OP had in mind, it relies on a bug rather than a documented feaure. For that reason I happen to like this solution to question #5 of the OP's quiz:

```sub{my\$x=\\$x};

Updated version that creates only one \$x:

```sub { my \$x; \$x = \\$x; }

The anonymous sub is created and immediately falls out of existance because it's not passed to a scalar variable. And yet \$x never disappears because its reference count is always going to be 1; it refers to itself.

It probably doesn't qualify as a static, and is pretty much useless, but it meets the definition of static that the OP gave.

Dave

"If I had my life to live over again, I'd be a plumber." -- Albert Einstein
oops, you're right, my definition of "static" in the clarification was flawed :-)

I do mean function-scoped static like in C/C++ ofcourse

btw tachyon, your #1 solution isn't:
perl -le 'my @x = ( \\$_, \\$_ ); \$x[0]=42; print \$x[1]'

I do not think your code does what you think it does. You have two different \$x variables shown in your anonymous subroutine, not a single one referencing itself.
A static variable in a subroutine context would be created only once and hold its value between invocations. You've created a circular reference in an uninvokable routine. Even if it weren't optimized away, of which I am uncertain, it bears no resemblance to a static variable.

my @x = ( \\$_, \\$_ );

No, that's not good enough :)

```my @x = ( \\$_, \\$_ );
\$x[0] = 5;
\$x[1] == 5 or die;

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

by seattlejohn (Deacon) on Oct 27, 2003 at 07:10 UTC
```# 1:
\$[=1;
@x = (10);

# confirm it:
print \$x[0], ",", \$x[1], "\n";
\$x[1]=20;
print \$x[0], ",", \$x[1], "\n";
\$x[0]=30;
print \$x[0], ",", \$x[1], "\n";

\$perlmonks{seattlejohn} = 'John Clyman';

\$[=1;

Not quite what we had in mind, but a valid and creative solution ;)

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

by BrowserUk (Patriarch) on Oct 27, 2003 at 10:13 UTC
1. perl -e"sub t{ \@_ }; \$s='this'; *x = t \$s, \$s; \$x[0] = 'that'; print join' ',@x;"
2. perl -e"foo while1" or perl -e"{foo;redo}"
1. perl -e"\$foo = [{1=>1}, 'foo']; print \\$foo->{1}, \\$foo->[1]; "
2. ?
3. ?
4. ?
5. ?
6. ?
7. ?
1. perl -e"\$foo = \\1; print eval(q[\$\$foo]), eval(q[\$\$foo + 0])"
2. ?
8. ?
9. ?
10. perl -e"sub STDOUT{\*STDOUT}"
11. Bonus perl -e"print \undef; sub foo{} goto +foo"
I couldn't get :foo while1" to work on my PC (Windows, perl 5.8.0).

I could get to work by rewriting it as "1while foo" or "1until!foo".

My own try involved a for loop--no dice. The best I could do was "for(;;foo){};" which is slightly too long.

I could get to work by rewriting it as "1while foo" or "1until!foo".

That loop will stop as soon as foo() returns false. The quiz didn't specify that foo() will always return a true value, so you can't assume it.

----
I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer

:(){ :|:&};:

Note: All code is untested, unless otherwise stated

1. yes

2. no and yes (perl treats while1 as one identifier)

3a. yes

8a. yes, cool, unexpected solution :-)   our official version uses a much much more obscure trick.. funny we never saw this one
Try this instead: eval(q[\$\$foo]) ne eval(q["\$\$foo"])
•Update: actually, no, the original was fine too.. even though \$\$foo and \$\$foo + 0 print differently, they don't compare numerically unequal, which is what the exercise was

11. doesn't appear to work for me..

```% perl -e 'sub STDOUT{\*STDOUT} <STDOUT> eq <+STDOUT> or die'
Died at -e line 1.

12. yes, but why? :-)

•Update: fixed the "try this".. initially said "!=" instead of "ne"

12. yes, but why? :-)

I missed this before.

For the same reason that these give a similar error

```D:\TEMP>perl -e"sub f{'fred'} goto +f"
Can't find label SCALAR(0x15d7c1c) at -e line 1.

D:\TEMP>perl -e"sub f{'fred'} goto(f)"
Can't find label SCALAR(0x15d7c1c) at -e line 1.

D:\TEMP>perl -e"sub f{'fred'} goto f->()"
Can't find label SCALAR(0x15d7c1c) at -e line 1.

But these do not ;^)

```D:\TEMP>perl -e"sub f{'fred'} goto ~~f"
Can't find label fred at -e line 1.

D:\TEMP>perl -e"sub f{'fred'} goto ''.f"
Can't find label fred at -e line 1.

D:\TEMP>perl -e"sub f{'fred'} goto scalar f"
Can't find label fred at -e line 1.

D:\TEMP>perl -e"sub f{'fred'} goto \${\f}"
Can't find label fred at -e line 1.

Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!

by pg (Canon) on Oct 27, 2003 at 03:29 UTC

What has this to do with a person's Perl ability ;-?

It doesn't. If I saw any of these on a test for a job, I'd probably walk.

I think you should gauge the quiz as a refresher or an exercise in what else you can learn. There are many aspects to learning Perl and after 4 years I haven't even come close to learning half of them. A quiz like this helps to shine a light on other things I didn't know.

--
Barbie | Birmingham Perl Mongers | http://birmingham.pm.org/

by Juerd (Abbot) on Oct 27, 2003 at 08:15 UTC

Bonus Exercise: The code snippet 'sub foo{} goto +foo' produces an error: "Can't find label SCALAR(0x31c70c)" (the address may vary) Where does that ref come from? What does it point to?

Please note that this bug has been fixed in bleedperl.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

by talexb (Chancellor) on Oct 27, 2003 at 16:14 UTC

None of this is useful for someone looking to test Perl skills. But it was properly labelled as a "waste of time" .. I'm just thinking that it may put off anyone not familiar with the weird on-line Perl community.

--t. alex
Life is short: get busy!

Nevertheless this test is a good way to found out if you really know Perl intimately. You don't need to know all Perl to answer these questions in order to be a professional Perl coder that makes mission critical business applications, but that does not mean this test is useless.

None of this is useful for someone looking to test Perl skills. But it was properly labelled as a "waste of time"

Not just waste of time, but waste of time in our effort against sanity. We want you to break your brain cells over this. Your current lazy attitude is not really appreciated and we think you're afraid to admit you are not an [insert awesome title here].

I'm just thinking that it may put off anyone not familiar with the weird on-line Perl community.

Your inability to not understand what this is all about is probably not shared by the people who come here unbiased. They will probably read the introduction, which I quote for you here, with my emphasis added:

As part of our continuing crusade against sanity, we of #perlhelp (EFnet) have created a modest perl quiz to test for all the skills required to make the maintainance programmer voluntarily leap into the gaping chasm of madness. We hope it will reinforce everyone's appreciation of our favorite language, by itself and as a tool towards this noble goal.

# ;-)

I hope you understand now. We do this not for fun, but for a greater good.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

by tilly (Archbishop) on Oct 27, 2003 at 16:26 UTC
My answers without looking at existing ones...  1: I've seen this in chatter mentioned by tye, but the trick slips my memory at the moment. :-( 2: {foo;redo} # See RE: My favorite looping mechanism in Perl is: 3: This is actually two questions My first thought was pseudohashes but pseudohashes are deprecated and IIRC removed in 5.8.0. Then it was \$foo = \*bar; \$\$foo->[1] = \$\$foo->{1} = "hello" Hrm, Pseudohashes are allowed? OK then, \$x = [{1=>1}, "hi"]; Your test will pass, albeit with an ugly scalar for each, but they are not accidentally the same, they are both references to the same string. Trivial with overload, but I am not sure if that is breaking your rules. OK, sub bar {\$bar[\$_[0]]} \$foo = \*bar; \$bar[1]="hi";, that isn't a different idea than what I originally did for 3a, but it works. UPDATE 3 I don't know how to do this after all. 4: dump # So sorry, did you want solutions that aren't supposed to core dump? :-P 5: my \$static if 0; # See Tie::Static for my opinion on this... 6: Is it cheating for me to use a module but not write one? ```# Reformat to one line if you want -e use overload qq("")=>sub{"same"}; \$x = bless \\$foo; \$y = bless \\$bar; \$\$x= "x"; \$\$y= "x"; [download]``` UPDATE You do this like so: \$x = do {local *foo}; \$y = *foo; \$foo = "hello"; 7: UPDATE 2 \$foo = *STDOUT{IO}; 8: *x = \\$| 9: This is actually two questions UPDATE Um, in the questions shouldn't q be qq everywhere? If you don't let \$\$foo interpolate, it shouldn't matter what is in it... UPDATE 3 \$foo = \\$!; \$!=1; UPDATE 5 Oops, this is wrong. I should test these answers a little, ya think? 9b 10 11: UPDATE 4 Put sub CORE'GLOBAL'glob{""} at the END of your code. Location matters, this code has to be seen by the Perl interpreter after Perl has seen some evidence that it needs to load File::Glob (which will overwrite us). Bonus
I, um, would have gotten more if I didn't have to go to work. Yeah, that's the ticket...

UPDATE Minor fixes. BTW I should add that while I am not terribly bad at this kind of trivia, I think that focussing on it is a horrible mistake.

UPDATE 3 Took time out for 9a. I had been thinking about 10, but because nobody else bothers to hide their answers, I saw mtye's version already. 3b has me puzzled again (see Roy Johnson's note).

UPDATE 4 Added a solution to problem 11.

UPDATE 5 Admit my mistake in problem 9a. I think that I'll admit to not knowing stupid Perl trivia that well these days. Particularly since nobody else seems to be trying these too hard. Also note that my solution to problem 11 can't be placed in front with glob-assign without adding a semi-colon, which puts you over the character limit.

3. who cares about deprecated, they still work ;-)

3/6. overload is a module which isn't allowed (though there are ways to circumvent that), but more importantly bless is explicitly forbidden by the rules

the others look good :-)

UPDATE Re 9: it really is q, not qq. (notice the eval? :-)

UPDATE 2 As Roy Johnson pointed out, your 3b currently doesn't work (it's only a small one-char mistake though)

UPDATE 3 Your 9a doesn't work, they print differently but compare numerically equal. make sure to test your answers with perl -e '......; eval(q[\$\$foo]) != eval(q[0+\$\$foo]) or die' rather than using print, to avoid traps like these :-)

UPDATE 4 ex 11 works.. note that you can place it in front by using glob-assign

UPDATE 5 strictly speaking the semi isn't needed to make the condition true (which is the exercise), but even if you do include it it's still possible by dropping the "" from the sub

If by a fix you mean sub bar {\$bar[\$_[0]]} \$foo = *bar; \$bar[1]="hi";, that does not work to the given spec.

Test it with print "yes" if \\$foo->(1) eq \\$foo->[1] and you see that it fails for me on 5.8.1. Get rid of the backslashes and it works, but the problem is that Perl's functions are pass by reference, return by value. Therefore the return of bar(1) is a new string with the same value as \$bar[1], but you get something different by taking a reference to it.

Not an ARRAY reference at testit line 7.
upon trying to
printf "Value: %s\n", \\$foo->[1];
For #4, perl -edump also works... :)

----
Zak
```undef\$/;\$mmm="J\nutsu\nutss\nuts\nutst\nuts A\nutsn\nutso\nutst\nutsh\
+nutse\nutsr\nuts P\nutse\nutsr\nutsl\nuts H\nutsa\nutsc\nutsk\nutse\n
+utsr\nuts";open(\$DOH,"<",\\$mmm);\$_=\$forbbiden=<\$DOH>;s/\nuts//g;print
+;

Note that his version doesn't work under strict, while a strict solution is possible. (the 'official' solution is very different from mtye's), so the exercise isn't spoiled just yet ;-)

How about an answer for #10 at 24 characters that passes strict?  ```use strict; #23456789_123456789_1234 BEGIN{\$'y=*x::=*y::=*::} print "Yes\n" if \$x::y::x::y::y::x::y::x::x::y::y::y::y::x::y::y; [download]```
by mtve (Deacon) on Oct 27, 2003 at 17:56 UTC

Exercise 10 in 24 chars:

```#23456789012345678901234
\$\$_++for glob"'{x,y}"x16

Exercise 6 is easy.

cool! now under strict :-)

shouldn't N8 be:

\$foo++ eq (\$foo^=0)++

?

by jryan (Vicar) on Oct 27, 2003 at 16:44 UTC

Is it just me, or is #8 undefined behaivor?

undefined in what sense? Perl's behavior is defined by its source code, perhaps unless contradicted by docs.

UPDATE ick, I got pulled into a pointless discussion. To short-circuit it: anything that works consistently (that is, not dependent on random or OS/environment-dependent factors) in perl 5.8.* is acceptable for these exercises.

(\$foo^=0)++ eq \$foo++ involves an auto-increment on top of an assignment, which is undefined as far as I know.

For more discussion: Re: Incrementing a Hash Value.

by Anonymous Monk on Oct 27, 2003 at 07:01 UTC
```# 1
{
package MyTie;
require Tie::Array;
@ISA = qw/Tie::StdArray/;
sub STORE {@{\$_[0]}[\$_[1],\$_[1]+1] = (\$_[2]) x 2}
}
tie my @x, 'MyTie';

# 6
\$x = \42;
\$y = "\$x";

tie my @x, 'MyTie';

For all exercises: no fork/exec/system/qx/open, no commandline options, no user input, no modules, no tie, no bless, no %SIG.

I guess the first and most important exercise is reading.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Solutions
by xmath (Hermit) on Oct 28, 2003 at 23:43 UTC
Strict solutions to all exercises, base64-encoded:

 1 b3VyIEB4OyBteSAkeTsgKng9c3Vie1xAX30tPigkeSwkeSk= 2 e2ZvbztyZWRvfQ== 3a bXkgJGZvbyA9IFt7MSwgMX1d 3b c3ViIHogOiBsdmFsdWUgeyAkOjp6WzFdIH0gbXkgJGZvbyA9ICp6 4 ZHVtcDs7 or ZHVtcCgp or fn5kdW1w, etc :-) 5 c3ViIGZvbyB7IG15ICR4IGlmIDA7IC4uLiB9 6 b3VyICgkeCwgJHkpID0gKCp4LCBldmFsICJsb2NhbCAqeCIp 7 bXkgJGZvbyA9ICpTVERPVVR7SU99 8 b3VyICRmb287ICpmb28gPSBcKyskfA== 9a bXkgJGZvbyA9IFwkXlM= 9b cGFja2FnZSBZO291ciRmb289XDA7JFg6OmZvbz1cIiAiOypZOjo9Klg6Og== or JGZvbz0iXzwoZXZhbCAxKSI= (non-strict original) 10 QkVHSU57Knk6Oj0qeDo6PSQ6Onk9Kjo6fQ== 11 KkNPUkU6OkdMT0JBTDo6Z2xvYj1zdWJ7fQ==

For the bonus exercise, see the explanation above

Fun! Now let's see you come up with 10 more for next weeks quiz:)

Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"Think for yourself!" - Abigail
Hooray!

argh :-)
Another (strict) solution for 9b:
```BEGIN {\$^H |= 0x30000}
\$^H{'qr'} = sub {''};
my \$foo = \'';
Another solution for E8:
KmZvbyA9IFxsb2NhbCAkMQ==
This one relies on a bug in perl.
I think the answer to number 2 is unnecessarily obfu. You can actually do it with while too... Perhaps it should ask without using while? UPDATE: I'm pretty sure they shortened the number of characters since I wrote this.

-Paul

In 10 chars?
```while(){foo}   # 12 chars
foo while 1    # 11 chars
by ambrus (Abbot) on Nov 02, 2003 at 16:47 UTC

I could solve 5 of them.

UPDATE: read some solutions. So you accept mine for 3 and 4. Quiestion 10 is really trickey.

UPDATE: please someone explain why my solution to 8 works. I don't understand. Thx.

UPDATE: I still don't know how my solution to 8 works, I've found it accidentally, but I see that there's a similar solution using \$^N. (And one even with \$1, wow!) (The official solution which uses \$| is eaasier to understand.)

by ccn (Vicar) on Mar 27, 2004 at 23:07 UTC
6 of 12  Exercise 1: Create an array @x such that changing \$x[0] also sets \$x[1] to the same value \$[=1;@x=(); Exercise 2: Given a pre-declared function "foo", write a code snippet that invokes it in an infinite loop; in 10 chars {foo;redo} Exercise 4: Dump core in 6 chars dump() Exercise 5: Create a static variable lexically scoped to a sub, and no wider than that. It's ok if it blows up under recursion sub foo{my \$static if 0} Exercise 6: Create \$x, \$y such that \$x eq \$y && \$\$x ne \$\$y \$x=\1;\$y="\$x" Exercise 8: Create \$foo such that (\$foo^=0)++ eq \$foo++ *foo=*|;\$|=1;
by thospel (Hermit) on Jul 02, 2005 at 19:22 UTC
Since it's meant for 5.8.0, I didn't yet see this "real" solution for number 4:
```%::=//
For later perls it's a bit longer (too long):
```%::=0;//
update oops, posted under the wrong node. This is meant for node How's your Perl?

20050703 Edit by ysth: moved from How's your Perl? (II).

by diotalevi (Canon) on Oct 28, 2003 at 18:20 UTC
There's a bunch of spoilers here so click readmore to read them.
re 8: perl has a fixed evaluation order (L->R for most operators, including eq), so you can use that. That it's not officially defined/documented is ofcourse of no concern :-)
I've now see the answer (and its obvious) for #8 and in that rare case the evaluation order doesn't actually matter since it won't affect anything but if it were anything else then I'd have to call shenanigans on you for the trick question since you'd only be testing on the implementation and not the specified language.
by Beechbone (Friar) on Oct 28, 2003 at 18:25 UTC
by ambrus (Abbot) on Jun 08, 2005 at 09:32 UTC

Here's a new solution for question 3a. This is not strict in the sense that you have to turn off strict for the set-up code to work. However, the actual test \\$foo->[1] == \\$foo->{1} runs under strict, unlike in my original symbolic ref solution.

I think that this solution differs from all the solutions given so far, so I submit it even though this puzzle is now quite old.

by Roger (Parson) on Oct 27, 2003 at 03:27 UTC
Exercise 2
```{foo,redo}

Exercise 4
```dump;;
Or
```dump()