Re: list reversal closure
by BrowserUk (Patriarch) on Aug 21, 2006 at 11:18 UTC
|
Two immediate thoughts.
- Very few languages support lexical closures, so your test excludes many of them.
- Your test is a GUOLCAAS. A gratuitous use of lexical closures and anonymous subs--neither is a requirement for performing the function of the code which would be equally achieved by:
#!/usr/bin/perl -l
print for reverse @ARGV;
- It is no more succinct than the simpler version.
- It is no more correct than the much simpler version.
- It is no more understandable than the simpler version.
- It is no more efficient than the simpler version.
- It is no more flexible that the simpler version.
- It is no more reusable than the simpler version.
- It is no more reliable that the simpler version.
It's also rather limiting to write a filter program that only accepts input from the command line and not via redirection.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
While I agree with the thesis that appears to be implicit in your post (that only real-world problem solving can provide a truly comprehensive measure of a language's benefits), that's not terribly useful for discussion with "hard" data on hand. As such, I've gone a little closer to the scientific method approach by trying to work with a series of clearly defined, strictly regulated mini-tests that each focus on specific characteristics of languages while minimizing the problem of additional, unnecessary variables. As such, for this particular test, I'm looking for fewer untargeted variables in the test, not more of them.
This unfortunately tends to result in a test whose conditions appear somewhat arbitrary and extraneous, until one considers the fact that the conditions are sorta the point.
If, however, you think another approach than using @ARGV would be better, I certainly encourage you to modify my code (or write code from scratch) to improve upon my original, and if you have suggestions for addressing the needs of this little test directly as opposed to attempting to turn it into a real-world problem, I'm open to that as well.
| print substr("Just another Perl hacker", 0, -2); |
|
- apotheon
CopyWrite Chad Perrin |
| [reply] |
|
|
Put more simply, most languages assume the existence of command line arguments in an array, which eliminates the overhead of using the language or system libraries to process input for the test.
That does treat some languages more fairly, but it's not really reflective of any real world condition. You might as well begin by having the language explicitly set an array or variable with a specified input.
Side note on the closures bit -- a better, practical closures example is probably some sort of argument currying.
sub first_n_chars {
my $n = shift;
return sub {
return substr( shift, 0, $n )
};
}
my $first_4 = first_n_chars(4);
print $first_4->("hello world");
-xdg
Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
| [reply] [d/l] |
|
|
Re: list reversal closure
by xdg (Monsignor) on Aug 21, 2006 at 11:02 UTC
|
It's an interesting idea. But one that easily can be skewed towards any particular language's strengths (even unconsciously).
I find this particular example fairly uninspiring, as I'm not sure when I would ever use such a thing. It feels like a completely arbitrary use of a closure to make it hard for languages that don't have such a thing. So, in short, I think it's too arbitrary. E.g. it could just as easily be a list object that overloads stringification to reverse the list. So to me, that makes the "list reversal closure" seems like an example with some unconscious bias.
A better "test" is probably one that considers how a language performs (loosely speaking) on average across similar tasks each presented by advocates of a different language. The idea isn't to see how well one language performs on things it does well, but to see how well it performs on things that other languages do well.
Even that is likely to be highly controversial and unsatisfying. But to the OP's point, I don't think any single test will reveal much of anything.
-xdg
Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
| [reply] |
|
|
The closure requirement isn't really all that awful, if you think about it: it translates directly into two other requirements that seem quite reasonable, for most purposes, to impose. The first is lexical scoping (or equivalently protected scope) and the second is the ability to return a function from a function and pass it around in a variable, while still being able to execute it.
I'm generally a little unfairly biased against a language that doesn't support closures, perhaps, but I'm not so sure that a bias against languages that don't support everything needed to construct closures is at all unfair (despite the fineness of that distinction). While I'm keen on closures, that doesn't mean that closures don't provide a simple, clean, succinct, and fair means of demonstrating other positive characteristics of programming languages. In other words, the bias is conscious, but (as far as I can tell) largely irrelevant in this case.
As for the notion of comparing on a series of tasks, that's sorta what's happening that prompted me to come up with this in the first place. There's sort of an ongoing series of task-examples being dreamed up by me and a small number of others who make use of various languages for the enjoyable exercise of comparing implementations across languages. In fact, it was a Pythonista that suggested doing something involving list processing in the first place.
Single tests can demonstrate good points, though. You simply have to ensure that everyone involved in the comparisons is honest in the analysis, including an analysis of the shortcomings of the specific test task in demonstrating much. For instance, a succinctness test on "hello world" programs certainly won't declare a "winner" between Perl and Python, but it does demonstrate to a useful degree the significant and unwieldy scaffolding overhead required by Visual Basic for the simplest of tasks.
| print substr("Just another Perl hacker", 0, -2); |
|
- apotheon
CopyWrite Chad Perrin |
| [reply] |
|
|
| [reply] |
Re: list reversal closure
by imp (Priest) on Aug 21, 2006 at 12:15 UTC
|
I find examples like the following more useful:
sub reverse_iterator {
my @list = @_;
my $i = $#list;
sub {
return if $i < 0;
return $list[$i--];
};
}
my $foo = reverse_iterator(@ARGV);
while (defined ($_ = $foo->())) {
print;
}
| [reply] [d/l] |
|
|
sub reverse_iterator {
my @list = @_;
sub {
return pop @list;
};
}
Update: I prefer to signal the end of the list out of band to allow undefined values in @list. That why I prefer returning the value through an argument.
sub reverse_iterator {
my @list = @_;
sub {
return unless @list;
$_[0] = pop @list;
return 1;
};
}
my $foo = reverse_iterator(@ARGV);
while ($foo->(my $val)) {
print("$val\n");
}
Update: I just noticed that you assigned to $_ without localizing it first. Don't do that!
Update: s/shift/pop/ | [reply] [d/l] [select] |
|
|
#!/usr/bin/perl -l
sub revlist {
my @list = @_;
sub { pop @list };
}
my $foo = revlist(@ARGV);
print while local $_ = $foo->();
Edit: Optionally, closure subroutine might look like this, of course:
sub { return unless @list; pop @list; };
| print substr("Just another Perl hacker", 0, -2); |
|
- apotheon
CopyWrite Chad Perrin |
| [reply] [d/l] [select] |
|
|
Using your iterator, but with a slightly different invocation:
my $foo = reverse_iterator("a",undef,"c");
while (my ($elem) = $foo->()) {
print( defined( $elem ) ? $elem : "undef" );
}
| [reply] [d/l] |
Re: list reversal closure
by wazoox (Prior) on Aug 21, 2006 at 16:26 UTC
|
Joel Spolsky wrote an interesting article on the subject : Can your programming language do this?
He comes to this conclusion:
Ok. I hope you're convinced, by now, that programming languages with first-class functions let you find more opportunities for abstraction, which means your code is smaller, tighter, more reusable, and more scalable.
Is it the "someone else" you mentioned ? :) | [reply] |
|
|
'Fraid not. I've read that particular essay (several times), along with one by Paul Graham that touches on much the same thing, but it was actually list handling that was brought up by the person with whom I was discussing languistic tests and not the use of lexical closures.
I'd certainly be happy to have a conversation like this with Joel Spolsky at some point, though. The guy's full of good ideas.
| print substr("Just another Perl hacker", 0, -2); |
|
- apotheon
CopyWrite Chad Perrin |
| [reply] |
Re: list reversal closure
by chromatic (Archbishop) on Aug 21, 2006 at 20:59 UTC
|
... understandability for someone new to the language with only a brief explanation at most...
I can't see how that's a meaningful measure of anything interesting. Why not "For which any docs fail to contain the first-following non-consonant?"
| [reply] |
|
|
| [reply] |
Re: list reversal closure
by ikegami (Patriarch) on Aug 21, 2006 at 14:47 UTC
|
Nit:
print for reverse @list;
is equivalent to
print reverse @list;
when $, and $\ are equal (as they are by default).
| [reply] [d/l] [select] |
|
|
C:\test>perl -e" print for reverse 1.. 10"
10987654321
C:\test>perl -le" print for reverse 1.. 10"
10
9
8
7
6
5
4
3
2
1
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
Thanks for bringing that up in response. You're right: eliminating the for() changes the intended behavior of the program.
Now, I suppose, a new question has arisen: Should I intend for every list element to be printed on a separate line, or should I intend for the list to have its own line as in ikegami's example? It's not particularly critical either way, but perhaps there's an aesthetic benefit to be had from one or the other approach.
| print substr("Just another Perl hacker", 0, -2); |
|
- apotheon
CopyWrite Chad Perrin |
| [reply] [d/l] |
|
|
You did not contradrict me. I did say as long as $, and $\ are equal. -l changes $\, but not $,. This actually makes the version without for more flexible!
| [reply] [d/l] [select] |
|
|
|
|
|