Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^2: Function Prototypes and Array vs. List (Pt. 2)

by tadman (Prior)
on Jun 13, 2002 at 14:28 UTC ( [id://174215]=note: print w/replies, xml ) Need Help??


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.

Replies are listed 'Best First'.
•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.
      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

        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.
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!''

      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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://174215]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (5)
As of 2024-03-28 08:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found