|
#!/usr/bin/perl -00
|
|
my $RANDOMIZE = 1;
|
|
my @questions;
|
|
|
|
while (<DATA>) {
|
|
next if /===/;
|
|
my %record;
|
|
(undef, %record) = split /^([^:\s]+):\s*/m;
|
|
for (@record{keys %record}) { s/\s+/ /g }
|
|
if ($record{Question}) { push @questions, \%record}
|
|
elsif($record{Answer} ) { push @{ $questions[-1]{Answers} }, \%re\
|
|
cord}
|
|
else { die "unknown record $_" }
|
|
}
|
|
|
|
my $qnum = '01';
|
|
for $q (scramble(@questions)) {
|
|
fwrite ($qnum++, $q->{Question});
|
|
my $anum = 'a';
|
|
for $a ( scramble(@{$q->{Answers}}) ) {
|
|
fwrite($anum++, $a->{Answer});
|
|
}
|
|
print "\n";
|
|
}
|
|
|
|
sub scramble {
|
|
return @_ unless $RANDOMIZE;
|
|
my @list;
|
|
srand(time() ^ ($$ + ($$ << 15)));
|
|
push(@list, splice (@_, rand @_, 1)) while @_;
|
|
return @list;
|
|
}
|
|
|
|
sub fwrite {
|
|
($num, $text) = @_;
|
|
format =
|
|
@>. ^<<<<<<<<<<<<<<<&\
|
|
lt;<<<<<<<<<<<<<<<<<\
|
|
;<<<<<<<<<<<<<<<<<&\
|
|
lt;<<<<<<<<<<<<<<
|
|
$num, $text
|
|
~~ ^<<<<<<<<<<<<<<<<\
|
|
<<<<<<<<<<<<<<<<<&l\
|
|
t;<<<<<<<<<<<<<<<<<\
|
|
<<<<<<<<<<<<<<
|
|
$text
|
|
.
|
|
|
|
write;
|
|
|
|
}
|
|
__DATA__
|
|
Question: How do you produce a reference to a list?
|
|
Type: References
|
|
Difficulty: 6/7 (Hard)
|
|
Answer: \@array
|
|
Correct: No.
|
|
Why: @array is not a list, but an array.
|
|
Answer: [ @array ]
|
|
Correct: No.
|
|
Why: That makes a reference to a newly allocated anonymous
|
|
array, and populates it with a copy of the contents
|
|
of @array.
|
|
Answer: \($s, @a, %h, &c)
|
|
Correct: No.
|
|
Why: The backslash operator is distributive across a list, and
|
|
produces a list in return, this being (\$s, \@a, \%h, \&c)\
|
|
.
|
|
Well. In list context. In scalar context, it's a strange
|
|
way to get a reference to the function &c.
|
|
|
|
Answer: You can't take a reference to a list.
|
|
Correct: Yes.
|
|
Why: A list is not an array, although is many places one may be
|
|
used for the other. An array has an AV allocated, whereas\
|
|
a
|
|
list is just some values on a stack somewhere. You cannot
|
|
alter the length of a list, for example, any more than
|
|
you could alter a number by saying something like 23++.
|
|
While an array contains a list, it is not a list itself.
|
|
======================================================================\
|
|
==
|
|
Question: What happens when you return a reference to a private vari\
|
|
able?
|
|
Type: References
|
|
Difficulty: 4/7 (Medium)
|
|
Answer: You get a core dump later when you use it.
|
|
Correct: No.
|
|
Why: Perl is not C or C++.
|
|
Answer: The underlying object is silently copied.
|
|
Correct: No.
|
|
Why: Even though the reference returned is for all intents
|
|
and purposes a copy of the original (Perl uses return
|
|
by reference), the underlying referent has not changed.
|
|
Answer: Nothing bad -- it just works.
|
|
Correct: Yes.
|
|
Why: Perl keeps track of your variables, whether dynamic or
|
|
otherwise, and doesn't free things before you're done usin\
|
|
g
|
|
them.
|
|
Answer: The compiler doesn't let you.
|
|
Correct: No.
|
|
Why: Perl seldom stops you from doing what you want to do,
|
|
and tries very hard to do what you mean to do. This
|
|
is one of those cases.
|
|
======================================================================\
|
|
==
|
|
Question: Why aren't Perl's patterns regular expressions?
|
|
Type: Regular expressions
|
|
Difficulty: 3/7 (Medium)
|
|
Answer: Because Perl patterns have backreferences.
|
|
Correct: Yes.
|
|
Why: A regular expression by definition must be
|
|
able to determine the next state in the finite
|
|
automaton without requiring any extra memory
|
|
to keep around previous state. A pattern /([ab]+)c\1/
|
|
requires the state machine to remember old
|
|
states, and thus disqualifies such patterns
|
|
as being regular expressions in the classic sense
|
|
of the term.
|
|
|
|
Answer: Because Perl allows both minimal matching and maxim\
|
|
al
|
|
matching in the same pattern.
|
|
Correct: No.
|
|
Why: The mere presence of minimal and maximal repetitions
|
|
does not disqualify a language from being "regular".
|
|
|
|
Answer: Because Perl uses a non-deterministic finite automa\
|
|
ton
|
|
rather than a deterministic finite automaton.
|
|
Correct: No.
|
|
Why: Both NFAs and DFAs can be used to solve regular
|
|
expressions. Given an NFA, a DFA for it can be constructe\
|
|
d,
|
|
and vice versa. For example, classical grep uses an NFA,
|
|
while classical egrep a DFA. Whether a pattern matches
|
|
a particular string doesn't change, but where the match
|
|
occurs may. In any case, they're both regular. However,
|
|
an NFA can also be modified to handle backtracking, while
|
|
a DFA cannot.
|
|
|
|
Answer: Because Perl patterns can have look-aheads assertio\
|
|
ns
|
|
and negations.
|
|
Correct: No.
|
|
Why: The `(?=foo)' and `(?!foo)' constructs no more violate
|
|
whether the language is regular than do `^' and `$',
|
|
which are also zero-width statements.
|
|
======================================================================\
|
|
==
|
|
Question: What happens to objects lost in "unreachable" memory,
|
|
such as the object returned by Ob->new() in
|
|
`{ my $ap; $ap = [ Ob->new(), \$ap ]; }' ?
|
|
Type: Objects
|
|
Difficulty: 4/7 (Medium)
|
|
Answer: Their destructors are called when that interpreter \
|
|
thread
|
|
shuts down.
|
|
Correct: Yes.
|
|
Why: When the interpreter exits, it first does an exhaustiv\
|
|
e
|
|
search looking for anything that it allocated. This allow\
|
|
s
|
|
Perl to be used in embedded and multithreaded applications
|
|
safely, and furthermore guarantees correctness of object
|
|
code.
|
|
|
|
Answer: Their destructors are called when the memory become\
|
|
s unreachable.
|
|
Correct: No.
|
|
Why: Under the current implementation, the reference-counte\
|
|
d
|
|
garbage collection system will not notice that the object
|
|
in $ap's array cannot be reached, because the array refere\
|
|
nce
|
|
itself never has its reference count go to zero.
|
|
Answer: Their destructors are never called.
|
|
Correct: No.
|
|
Why: That would be very bad, because then you could have ob\
|
|
jects
|
|
whose class-specific cleanup code didn't get called ever.
|
|
|
|
Answer: Perl doesn't support destructors.
|
|
Correct: No.
|
|
Why: A class's DESTROY function, or that of its base classe\
|
|
s,
|
|
is called for any cleanup. It is not expected to dealloca\
|
|
te
|
|
memory, however.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: How do you give functions private variables that
|
|
retain their values between calls?
|
|
Type: Subroutines, Scoping
|
|
Difficulty: 5/7 (Medium)
|
|
Answer: Perl doesn't support that.
|
|
Correct: No.
|
|
Why: It would be difficult to keep private state in a
|
|
function otherwise.
|
|
|
|
Answer: Include them as extra parameters in the prototype l\
|
|
ist,
|
|
but don't pass anything in at that slot.
|
|
Correct: No.
|
|
Why: Perl is not the Korn shell, nor anything like that.
|
|
If you tried this, your program probably wouldn't
|
|
even compile.
|
|
Answer: Use localized globals.
|
|
Correct: No.
|
|
Why: The local() operator merely saves the old value of a g\
|
|
lobal
|
|
variable, restoring that value when the block in which the
|
|
local occurred exits. Once the subroutine exits, the
|
|
temporary value is lost. Before then, other functions
|
|
can access the temporary value of that global variable.
|
|
Answer: Create a scope surrounding that sub that contains l\
|
|
exicals.
|
|
Correct: Yes.
|
|
Why: Only lexical variables are truly private, and they wil\
|
|
l
|
|
persist even when their block exits if something still
|
|
cares about them. Thus:
|
|
{ my $i = 0; sub next_i { $i++ } sub last_i { --$i } }
|
|
creates two functions that share a private variable. The
|
|
$i variable will not be deallocated when its block goes
|
|
away because next_i and last_i need to be able to access i\
|
|
t.
|
|
======================================================================\
|
|
==
|
|
Question: What value is returned by a lone `return;' statement?
|
|
Type: Subroutines, Syntax
|
|
Difficulty: 3/7 (Medium)
|
|
Answer: The undefined value.
|
|
Correct: No.
|
|
Why: That would only be true in scalar context.
|
|
Answer: The empty list value ().
|
|
Correct: No.
|
|
Why: That would only be true in list context.
|
|
Answer: The undefined value in scalar context, and
|
|
the empty list value () in list context.
|
|
Correct: Yes.
|
|
Why: This way functions that wish to return failure
|
|
can just use a simple return without worrying about
|
|
the context in which they were called.
|
|
|
|
Answer: The result of the last evaluated expression in that
|
|
subroutine's block.
|
|
Correct: No.
|
|
Why: That's what happens when the function ends without
|
|
return being used at all.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: Assuming $_ contains HTML, which of
|
|
the following substitutions will remove all tags in it?
|
|
Type: Regular Expressions, WWW
|
|
Difficulty: 6/7 (Hard)
|
|
Answer: You can't do that.
|
|
Correct: Yes.
|
|
Why: If it weren't for HTML comments, improperly formatted
|
|
HTML, and tags with interesting data like <SCRIPT>, \
|
|
you
|
|
could do this. Alas, you cannot. It takes a lot
|
|
more smarts, and quite frankly, a real parser.
|
|
|
|
Answer: s/<.*>//g;
|
|
Correct: No.
|
|
Why: As written, the dot will not cross newline boundaries,\
|
|
and the
|
|
star is being too greedy. If you add a /s, then yes,
|
|
it will remove all tags -- and a great deal else besides.
|
|
Answer: s/<.*?>//gs;
|
|
Correct: No.
|
|
Why: It is easy to construct a tag that will cause this to \
|
|
fail,
|
|
such as the common `<IMG SRC='foo.gif' ALT="> ">'\
|
|
tag.
|
|
|
|
Answer: s/<\/?[A-Z]\w*(?:\s+[A-Z]\w*(?:\s*=\s*(?:(["']).\
|
|
*?\1|[\w-.]+))?)*\s*>//gsix;
|
|
Correct: No.
|
|
Why: For a good deal of HTML, this will actually work, but
|
|
it will fail on cases with annoying comments, poorly forma\
|
|
tted
|
|
HTML, and tags like <SCRIPT> and <STYLE>, whic\
|
|
h can contain
|
|
things like `while (<FH>) {}' without those being co\
|
|
unted
|
|
as tags. Comments that will annoy you include
|
|
<!-- <foo bar = "-->">
|
|
which will remove characters when it shouldn't; it's just
|
|
a comment followed by `">'. And even something like th\
|
|
is:
|
|
<!-- <foo bar = "-->
|
|
Most browsers will get right, but the substitution will no\
|
|
t.
|
|
And if you have improper HTML, you get into even more
|
|
trouble, like this:
|
|
<foo bar = "bleh" @>
|
|
text text text
|
|
<foo bar = "bleh">
|
|
in which case the .*? will gobble up way more than you
|
|
thought it would.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: Assuming both a local($var) and a my($var) exist,
|
|
what's the difference between ${var} and ${"var"}?
|
|
Type: Scope
|
|
Difficulty: 5/7 (Medium)
|
|
Answer: ${var} is the lexical variable $var, and
|
|
${"var"} is the dynamic variable $var.
|
|
Correct: Yes.
|
|
Why: Odd though it appears, this is how it works. Note tha\
|
|
t
|
|
because the second is a symbol table lookup, it is
|
|
disallowed under `use strict "refs"'. The words
|
|
global, local, package, symbol table, and dynamic
|
|
all refer to the kind of variables that local()
|
|
affects, whereas the other sort, those governed by
|
|
my(), are variously knows as private, lexical, or scoped
|
|
variable.
|
|
Answer: ${var} is the package variable $var, and
|
|
${"var"} is the scoped variable $var.
|
|
Correct: No.
|
|
Why: Try again. You're close.
|
|
|
|
Answer: There is no difference.
|
|
Correct: No.
|
|
Why: One is the scoped
|
|
variable, the other the package variable. Which is
|
|
which though?
|
|
|
|
Answer: ${var} is a package variable $var, and ${"var"}
|
|
a global variable $var.
|
|
Correct: No.
|
|
Why: There is no difference between a package variable and
|
|
a global variable. All package variables are globals,
|
|
and vice versa.
|
|
======================================================================\
|
|
==
|
|
Question: Which of these is a difference between C++ and Perl?
|
|
Type: Objects, Scope, C++
|
|
Difficulty: 6/7
|
|
Answer: Perl can have objects whose data cannot be accessed
|
|
outside its class, but C++ cannot.
|
|
Correct: Yes.
|
|
Why: Perl can use closures with unreachable private data as
|
|
objects, and C++ doesn't support closures. Furtherm\
|
|
ore, C++
|
|
does support pointer arithmetic via `int *ip = (int*)&obje\
|
|
ct',
|
|
allowing you do look all over the object. Perl doesn't ha\
|
|
ve
|
|
pointer arithmetic. It also doesn't allow `#define privat\
|
|
e
|
|
public' to change access rights to foreign objects. On
|
|
the other hand, once you start poking around in /dev/mem,
|
|
no one is safe.
|
|
Answer: C++ can have objects whose data cannot be accessed
|
|
outside its class, but Perl cannot.
|
|
Correct: No.
|
|
Why: See the correct answer for why.
|
|
|
|
Answer: C++ supports multiple inheritance, but Perl does no\
|
|
t.
|
|
Correct: No.
|
|
Why: Both support multiple inheritance.
|
|
|
|
Answer: C++ will not call destructors on objects that go ou\
|
|
t
|
|
of scope if a reference to that object still exists,
|
|
but Perl will.
|
|
Correct: No.
|
|
Why: Exchange "Perl" and "C++" in that answer, and you woul\
|
|
d
|
|
be telling the truth. C++ is too primitive to know when
|
|
an object is no longer in use, because it has no garbage
|
|
collection system. Perl does.
|
|
======================================================================\
|
|
==
|
|
Question: What does Perl do if you try to exploit the execve(2)
|
|
race involving setuid scripts?
|
|
Type: Security, Folklore
|
|
Difficulty: 2/7 (Easy)
|
|
|
|
Answer: Reboots your machine.
|
|
Correct: No.
|
|
Why: An appealing idea, though, isn't it? After all, Perl \
|
|
does
|
|
possess super(user)powers at this point. You just never k\
|
|
now
|
|
what it might do. In the interests of courtesy, though,
|
|
Perl stays out of your power supply just as it stays
|
|
out of your living room.
|
|
|
|
Answer: Sends mail to root and exits.
|
|
Correct: Yes.
|
|
Why: It has been said that all programs advance to the
|
|
point of being able to automatically read mail. While
|
|
not quite at that point (well, without having a module
|
|
loaded), Perl does at least automatically send it.
|
|
Answer: Runs the fake script with setuid perms.
|
|
Correct: No.
|
|
Why: That would be bad. Very Bad. What do you think we
|
|
are? A shell or something?
|
|
|
|
Answer: Runs the fake script, but without setuid perms.
|
|
Correct: No.
|
|
Why: It would be improper to run anything at all in the
|
|
face of such naughtiness.
|
|
======================================================================\
|
|
==
|
|
Question: How do you print out the next line from a filehandle
|
|
with all its bytes reversed?
|
|
Type: I/O, Built-in Functions, Context
|
|
Difficulty: 5/7
|
|
|
|
Answer: print reverse <FH>
|
|
Correct: No.
|
|
Why: That reads all lines in FH, then reverses that list of\
|
|
|
|
lines and passes the resulting reversed list off to print.
|
|
This is actually a very useful thing, and simulates
|
|
`tail -r' behavior but without the annoying buffer
|
|
limitations of that utility. Nonetheless, it's not
|
|
what we want for an answer to this question.
|
|
Answer: print reverse scalar <FH>
|
|
Correct: No.
|
|
Why: Although `scalar <FH>' did retrieve just the nex\
|
|
t line,
|
|
the reverse is still in the list context imposed on it by
|
|
print, so it takes its list of one element and reverses
|
|
the order of the list, producing exactly the next line.
|
|
An expensive way of writing `print scalar <FH>'.
|
|
Answer: print scalar reverse scalar <FH>
|
|
Correct: Yes.
|
|
Why: Surprisingly enough, you have to put both the reverse \
|
|
and
|
|
the <FH> into scalar context separately for this to \
|
|
work.
|
|
|
|
Answer: print scalar reverse <FH>
|
|
Correct: No.
|
|
Why: Although the first use of scalar inhibits the list con\
|
|
text
|
|
being imposed on reverse by print, it doesn't carry throug\
|
|
h
|
|
to change the list context that reverse is imposing on <\
|
|
;FH>.
|
|
So reverse catenates all its arguments
|
|
and does a byte-for-byte flip on the resulting string.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: Why is it hard to call this function: sub y { "because" }
|
|
Type: User Functions, Operators
|
|
Difficulty: 4/7 (Medium)
|
|
|
|
Answer: Because y is a kind of quoting operator.
|
|
Correct: Yes.
|
|
Why: The y/// operator is the sed-savvy synonym for tr///.
|
|
That means y(3) would be like tr(), which would be looking
|
|
for a second string, as in tr/a-z/A-Z/, tr(a-z)(A-Z),
|
|
or tr[a-z][A-Z].
|
|
Answer: It's not.
|
|
Correct: No.
|
|
Why: Most people don't call functions with ampersands anymo\
|
|
re.
|
|
If they did, as in &y(), it wouldn't be so hard.
|
|
|
|
Answer: Because y is a predefined function.
|
|
Correct: No.
|
|
Why: y isn't really a function, per se. If it were, you
|
|
would never see y!abc!xyz!, since proper functions
|
|
do not like getting banged on that way.
|
|
|
|
Answer: Because it has no prototype.
|
|
Correct: No.
|
|
Why: Functions don't require prototypes in Perl.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: What does `$result = f() .. g()' really return?
|
|
Type: Operators
|
|
Difficulty: 5/7 (Medium)
|
|
|
|
Answer: The last number from the list of numbers
|
|
returned in the the range between f()'s return
|
|
value and g()'s.
|
|
Correct: No.
|
|
Why: That might work in list context, but never in scalar.
|
|
The list `..' operator is a totally different creature
|
|
than the scalar one. They're just spelled the same
|
|
way, kind of like when you can the rusty old can down
|
|
by the guys' can just because you can. Context,
|
|
as always, is critical.
|
|
Answer: Produces a syntax error.
|
|
Correct: No.
|
|
Why: You'd be amazed at how many things in Perl don't
|
|
cause syntax errors.
|
|
|
|
Answer: True if and only if both f() and g() are true,
|
|
or if f() and g() are both false, but returns false
|
|
otherwise.
|
|
Correct: No.
|
|
Why: That sounds more like a negated logical xor. A logical
|
|
xor is `!$a != !$b', so you've just described `!$a == !$b'\
|
|
.
|
|
Interesting, and perhaps even useful, but unrelated to
|
|
`..', our scalar range operator.
|
|
Answer: False so long as f() returns false, after
|
|
which it returns true until g() returns true,
|
|
and then starts the cycle again.
|
|
Correct: Yes.
|
|
Why: This is scalar not list context, so we have the bistab\
|
|
le
|
|
flip-flop range operator famous in parsing of mail message\
|
|
s,
|
|
as in `$in_body = /^$/ .. eof()'. Except for the first
|
|
time f() returns true, g() is entirely ignored, and f()
|
|
will be ignored while g() later when g() is evaluated.
|
|
Double dot is the inclusive range operator, f() and
|
|
g() will both be evaluated on the same record. If you
|
|
don't want that to happen, the exclusive range operator,
|
|
triple dots, can be used instead. For extra credit,
|
|
describe this:
|
|
$bingo = ( a() .. b() ) ... ( c() .. d() );
|
|
======================================================================\
|
|
==
|
|
Question: Why does Perl not have overloaded functions?
|
|
Type: User Functions
|
|
Difficulty: 4/7 (Medium)
|
|
Answer: Because it's too hard.
|
|
Correct: No.
|
|
Why: Just because it's hard isn't likely to rule out
|
|
something from being implemented -- someday.
|
|
|
|
Answer: Because you can inspect the argument count,
|
|
return context, and object types all by yourself.
|
|
Correct: Yes.
|
|
Why: In Perl, the number of arguments is trivially availabl\
|
|
e
|
|
to a function via the scalar sense of @_, the return
|
|
context via wantarray(), and the types of the
|
|
arguments via ref() if they're references and
|
|
simple pattern matching like /^\d+$/ otherwise.
|
|
In languages like C++ where you can't do this, you
|
|
simply must resort to overloading of functions.
|
|
Answer: It does, along with overloaded operators as well
|
|
as overridden functions and methods.
|
|
Correct: No.
|
|
Why: Actually, Perl does support overloaded operators via `\
|
|
use
|
|
overload', overridden functions as in `use Cwd qw!chdir!',
|
|
and overridden methods via inheritance and polyphormism.
|
|
It just doesn't support functions automatically overloaded
|
|
on parameter signature or return type. Not that such
|
|
isn't longed
|
|
Answer: Because Perl doesn't have function prototypes.
|
|
Correct: No.
|
|
Why: Perl actually does have function prototypes, but this
|
|
isn't used for the traditional sort of prototype
|
|
checking, but rather for creating functions that
|
|
exactly emulate Perl's built-ins, which can implicitly
|
|
force context conversion or pass-by-reference without
|
|
the caller being aware of this.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: What does read() return at end of file?
|
|
Type: I/O, Built-in Functions
|
|
Difficulty: 2/7 (Easy)
|
|
|
|
Answer: undef
|
|
Correct: No.
|
|
Why: That would signal an I/O error, not normal end of file\
|
|
.
|
|
The circumfix operator <> returns undef when it reac\
|
|
hes end
|
|
of file, but a normal read does not.
|
|
|
|
Answer: 0
|
|
Correct: Yes.
|
|
Why: A defined (but false) 0 value is the proper indication\
|
|
of the end of
|
|
file for read() and sysread().
|
|
Answer: "0 but true"
|
|
Correct: No.
|
|
Why: You're thinking of the ioctl() and fcntl() functions w\
|
|
hich
|
|
return this when the C version returned 0, reserving
|
|
undef for when the C version returns -1. For example,
|
|
`fcntl(STDIN,F_GETFL,1)' returns "0 but true" depending on
|
|
whether and how standard has been redirected. (The F_GETFL
|
|
flag was loaded from the Fcntl.pm module.)
|
|
|
|
Answer: "\0"
|
|
Correct: No.
|
|
Why: That's a string of length 1 consisting of the ASCII NU\
|
|
L
|
|
character, whose ord() is 0, which is false. The string,
|
|
however, is true. read() doesn't return strings, but
|
|
rather byte-counts.
|
|
======================================================================\
|
|
==
|
|
Question: What does `new $cur->{LINK}' do? (Assume the
|
|
current package has no new() function of its own.)
|
|
Type: Objects
|
|
Difficulty: 6/7 (Hard)
|
|
|
|
Answer: $cur->{LINK}->new()
|
|
Correct: No.
|
|
Why: Just because it looks like a unary function doesn't
|
|
mean a method call parses like one. You just
|
|
want it to work this way. If you want that,
|
|
write that.
|
|
Answer: $cur->new()->{LINK}
|
|
Correct: Yes.
|
|
Why: The indirect object syntax only has a single token
|
|
lookahead. That means if new() is a method, it only
|
|
grabs the very next token, not the entire following
|
|
expression.
|
|
This is why `new $obj[23] arg' does't work, as well as
|
|
why `print $fh[23] "stuff\n"' does't work.
|
|
Mixing notations between the OO and IO notations is perilo\
|
|
us. If you always use
|
|
arrow syntax for method calls, and nothing else, you'll
|
|
not be surprised.
|
|
Answer: new($cur->{LINK})
|
|
Correct: No.
|
|
Why: If the current package did in fact have its own new()
|
|
function, then this would be the right answer, but for the
|
|
wrong reasons. Within a class, it might appear to make no
|
|
difference since the new() subroutine would get its argume\
|
|
nt in $_[0]
|
|
called as a function or a method. However, a method call
|
|
can use inheritance, while a function call never does.
|
|
That means esoteric overridden new() methos would be
|
|
duped out of calling their derived class's constructor fir\
|
|
st,
|
|
and we wouldn't want that to happen, now would we?
|
|
Answer: $cur ? ($cur->{LINK}->new()) : (new()->{LI\
|
|
NK})
|
|
Correct: No.
|
|
Why: Perl may be crazy, but it's not quite that crazy. Yet\
|
|
.
|
|
======================================================================\
|
|
==
|
|
Question: What's the difference between /^Foo/s and /^Foo/?
|
|
Type: Regular Expressions
|
|
Difficulty: 5/7 (Medium)
|
|
Answer: There is no difference because /s only affects whet\
|
|
her dot
|
|
can match newline.
|
|
Correct: No.
|
|
Why: /s does more than that.
|
|
|
|
Answer: The first would allow the match to cross newline bo\
|
|
undaries.
|
|
Correct: No.
|
|
Why: /s only makes a dot able to cross a newline, and then \
|
|
|
|
only if the string actually has a newline in it.
|
|
Answer: The first would match Foo other than at the start
|
|
of the record if the previous match were /^Foo/gcm,
|
|
new in the 5.004 release.
|
|
Correct: No.
|
|
Why: Although the /c modifier is indeed new as of 5.004 (an\
|
|
d
|
|
is used with /g), this has no particular interaction with \
|
|
/s.
|
|
|
|
Answer: The second would match Foo other than at the start
|
|
of the record if $* were set.
|
|
Correct: Yes.
|
|
Why: The deprecated $* flag does double duty, filling the
|
|
roles of both /s and /m. By using /s, you suppress
|
|
any settings of that spooky variable, and force your
|
|
carets and dollars to match only at the ends of the
|
|
string and not at ends of line as well -- just as
|
|
they would if $* weren't set at all.
|
|
|
|
======================================================================\
|
|
==
|
|
|
|
Question: What does length(%HASH) produce if you have thirty-seven
|
|
random keys in a newly created hash?
|
|
Type: Hashes, Built-in Functions, Context
|
|
Difficulty: 5/7 (Medium)
|
|
Answer: 2
|
|
Correct: No.
|
|
Why: You probably think it decided there were 37 keys, and
|
|
that length(37) is 2. Close, but not quite.
|
|
|
|
Answer: 5
|
|
Correct: Yes.
|
|
Why: length() is a built-in prototyped as sub length($),
|
|
and a scalar prototype silently changes aggregates into
|
|
radically different forms. The scalar sense of a ha\
|
|
sh is
|
|
false (0) if it's empty, otherwise it's a string represent\
|
|
ing
|
|
the fullness of the buckets, like "18/32" or "39/64".
|
|
The length of that string&nb |