in reply to Re: Function Prototypes and Array vs. List (Pt. 2) in thread Function Prototypes and Array vs. List (Pt. 2)
The thing is, the documentation doesn't say. It would be something like this, although with a bit more gritty realism:
create(id)
Creates a Foo object with the id parameter set accordingly. id should be a valid record identifier.
So, I have an array @bob = ('Bob') which I want to use on this function. Eyeballing it, it looks like it would fit, so I go ahead and use it:
Foo::create(@bob);
Do you get a warning? Nope. Yet later, you might notice that for some reason your Foo has an id of 1, which doesn't make any sense. Maybe smoke starts pouring out of your Perl program because of acalar conversion induced program failure. You lose a life and must hit "P1 Start" to continue.
Without checking the source code you're never really going to know for sure.
Conceputally, I was hoping for either a quick idiomatic way to do it, or something like one of these:
Foo::create(listify(@bob)); # List converter?
Foo::create($bob[0..$#bob]); # Array slice as list?
Instead, you're going to have to do some work, which is anti- Lazy. In the general sense:
Foo::bar($baz[0],$baz[1],$baz[2],...,$baz[$#baz]);
Update:
I certainly can't contest merlyn's "random crap" remark, so I'd say this was "premeditated ignorance". I knew the array had a single element and expected a particular behavior. After all, why expand twice (once on call, once on parameter import)? Well, sometimes you've just got to.
•Re: Re^2: Function Prototypes and Array vs. List (Pt. 2)
by merlyn (Sage) on Jun 13, 2002 at 14:38 UTC
|
See, I don't get this:
create(id)
Creates a Foo object with the id parameter set accordingly. id should be a valid record identifier.
when put together with this:
So, I have an array @bob = ('Bob') which I want to use on this function. Eyeballing it, it looks like it would fit
What part of your brain says that when they wanted a "record identifier" (whatever that is, but it looks to be a single value), you can hand it an array?!
That's the part that's off here. It's not Perl's fault
you're trying to jam in something that doesn't make sense. And Perl has every right to given you surprising
(to you) results when you've wandered out into unsuggested territory.
As I saw somewhere in a purl factoid:
You can't just throw random crap together and expect
it to work.
If I knew that the function was looking for a scalar
ID, and I had that ID as the first element of an array
I'd know immediately that I needed to hand it an
element:
create($bob[0])
Case closed.
-- Randal L. Schwartz, Perl hacker
update:
And if you can show me where you "Well, sometimes you've just got to." in actual useful code and not some junky little hypothetical misdesign, I'd be surprised. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
I'd say the specification of create is incomplete.
Prototyping does act surprisingly because it goes against
the list flattening you'd expect from unprototyped functions.
Not specifying that a function is prototyped, or not saying
that the first argument will be evaluated in scalar context
means, IMO, that the description is incomplete (and hence wrong).
I only use prototypes if there are clear benefits (\@
and & prototypes, sometimes a prototype with a
single $ (which changes the way perl compiles your
Perl)). But often it's too much of a nuisance.
I also don't agree with your reasoning that with such a simple
description of create you should use $array[0]
Take a look at the description of POSIX::strftime.
With your reasoning, the proper way of calling it would be:
use POSIX;
my @chunks = localtime;
print strftime "some format", $chunks [0], $chunks [1], $chunks [2
+],
$chunks [3], $chunks [4], $chunks [5
+],
$chunks [6], $chunks [7], $chunks [8
+];
instead of
print strftime "some format", localtime;
strftime could have been prototyped as
$$$$$$$;$$$; the description doesn't say
it's not, and spells out the arguments for strftime.
Abigail
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
The cause of all this fuss was use of a function in an existing library that is mostly, for some reason, prototyped. This is real code, not some "hypothetical misdesign".
I hardly ever prototype, only when I have to, such as those examples you mention. I've used prototypes before, and they caused all sorts of wierdness, so I stopped. This might have been when they were still considered neat and not inherently dangerous.
Because of this, I've come to rely on doing things like chaining functions together, not unlike your example, or saving repeated parameters in arrays. I don't suggest that you should expand your arrays into lists just because. Not at all. What I'm saying is that if the function is prototyped, then you have no choice, which is another way of saying "sometimes you just have to". That's not my reasoning, that's reality! If you don't use prototypes, then this isn't an issue, and that's probably the best course of action. If you do, then you're going to have to be prepared for the consequences, so you'd better have a really good reason.
Although it probably wasn't clear, the whole point of the original post was to validate the theory that, if one can't deprototype the target function, then the consequences are that you really have to do all this extra work to use that function properly. I was hoping for the programmatic equivalent of a rubber glove that could be used to idiomatically insulate code A from prototyped code B, but no such technique seems to be available. Not that I was depending on this, of course.
This is yet another reason why the widespread use of prototypes is not a great idea. In Perl 6, things look like they will be much smoother.
| [reply] [Watch: Dir/Any] |
|
Re: Re^2: Function Prototypes and Array vs. List (Pt. 2)
by ariels (Curate) on Jun 13, 2002 at 14:47 UTC
|
No, your hypothetical create method is simply wrong. It's buggy. It should be (to paraphrase John Cleese) a NON-method. It should be bereft of life and pushing up the daisies.
The only reason to use prototypes is in order to give your functions the same syntax as various Perl builtins. E.g., with prototypes you can write a mymap that will have the same semantics as map. Your ``create'' method isn't doing that; it's using a prototype in order to create a bug.
I could equally well claim that map is broken, because this code
my %hash = map { $_ => X => 1 } qw(a b c d)
does something very strange.
You're right about coding, though: In order to make sure code does not have a bug, it is not enough to check documentation. You must look at the code.
Why are you using a prototype? So far you've shown excellent reasons for you not to use a prototype for this function. ``Doctor, whenever I leave the spoon in the cup and drink my tea, my eye hurts!''
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Eh, no, it's using a prototype to act as Perl buildins....
Remember that by default, subroutine calls gobble up all the
arguments (unless there are parens), except subroutines
that are prototypes to take zero or one argument.
Witness:
#!/usr/bin/perl -w
use strict;
sub all {print "@_\n"};
sub gobble_no_proto {return};
sub gobble_proto ($) {return};
all "foo", "bar", gobble_no_proto "baz", "quux", "fluff";
all "foo", "bar", gobble_proto "baz", "quux", "fluff";
__END__
foo bar
foo bar quux fluff
See the difference?
Abigail
| [reply] [Watch: Dir/Any] [d/l] |
|
|