in reply to Why ref() is bad.
in thread Is "ref $date eq 'ARRAY'" wrong?

All because HTML::Template uses ref.

Actually, no, that's not why. If it was just using ref() it wouldn't see that your object was an arrayref, it would see it as an object of some class. It uses isa(). This is exactly the advice the OP was getting: that he should use UNIVERSAL::isa(). I think that's generally poor advice and HTML::Template is one good example of one place just using ref() would have been an excellent idea.

Here is the relevant crufty code from HTML::Template:

if (defined($value_type) and length($value_type) and ($value_type +eq 'ARRAY' or ((ref($value) !~ /^(CODE)|(HASH)|(SCALAR)$/) and $value->isa('ARRA +Y')))) { (ref($param_map->{$param}) eq 'HTML::Template::LOOP') or croak("HTML::Template::param() : attempt to set parameter '$pa +ram' with an array ref - parameter is not a TMPL_LOOP!");

I think you are really misplacing blame. You are using HTML::Template so, you've contracted to abide by its API. You can't expect HTML::Template to handle everyones quirky data, afterall. And I think that's the fundamental misconception here. It isn't the module author's responsibility to code for every contingency. It's his responsibility to develop an API that makes sense and stick to it. Keeping it simple is a sound approach!

Your simple fix is to call

$template->param( PARAM => "$object");
In other words, stringify your object yourself. You're the one who knows it should be stringified. HTML::Template doesn't.

-sauoq
"My two cents aren't worth a dime.";

Replies are listed 'Best First'.
Re: Re: Why ref() is bad. (It isn't bad, your assumptions are.)
by dragonchild (Archbishop) on Dec 20, 2003 at 16:39 UTC
    Why is HTML::Template checking to see if I'm passing in an arrayref to a non-TMPL_LOOP param? Why should HTML::Template care?!? What if I wanted to see "ARRAY=(0x23453245)" as my value for some parameter. I can see a very good reason to do that - creating an online debugger. But, HTML::Template prevents me from doing that.

    Furthermore, HTML::Template doesn't check to see if the thing is truly a scalar. All it does is make sure the thing isn't an arrayref. The original version of my formatted number class used a hashref as its implementation. No problems. So, I figured that any implementation would work. And, in fact, any implementation would work ... except for arrayref. THAT is my complaint.

    Though, the fact that HTML::Template uses isa() makes sense, cause I "fixed" the problem by blocking isa() from reporting the object is any form of base type. You're right - ref wouldn't've caused the problem. I still stand why my statement - you shouldn't check to see if it is a duck ... you should check to see if it walks, talks, and smells like a duck. Deal with interface, not implementation. And, that can be done pretty simply.

    As for me knowing it should be stringified ... HTML::Template should trust me. If I say I want it to use X as a scalar, it should let me. It smacks too much of B&D, the way it does things now.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Why is HTML::Template checking to see if I'm passing in an arrayref to a non-TMPL_LOOP param? Why should HTML::Template care?!?

      On this point, we agree. I think this was a poor decision on the part of HTML::Template's author. FWIW, I don't care for HTML::Template, I've never recommended it, and this is one of the reasons why. But, the issue you were discussing (note your title) and the conclusion you came to were not in sync with the example you gave.

      What if I wanted to see "ARRAY=(0x23453245)" as my value for some parameter. I can see a very good reason to do that - creating an online debugger. But, HTML::Template prevents me from doing that.

      No, it does not prevent you from doing that. It simply requires that you stringify your arguments yourself. Whether or not that should be required is really a moot point. The module provides a complete interface. If you don't like it, find another module or roll your own. But, TIMTOWTDI and you can't blame the author for picking one you don't like.

      You're right - ref wouldn't've caused the problem. I still stand why my statement - you shouldn't check to see if it is a duck ... you should check to see if it walks, talks, and smells like a duck. Deal with interface, not implementation. And, that can be done pretty simply.

      And using ref() is an effective way to do that. If ref() reports that a scalar is an array reference, then you can use it like one. If it reports that that it is an object of class Foo, then treating it like an array reference is dealing with the Foo-thing's implementation rather than its interface and should be avoided.

      You are complaining because you wrote a Foo class and you tried to make its interface appear to be like a builtin type. That's a questionable design decision. And the way you go about it is questionable too. Presumably, if you wanted it to act like an array, you could have written Tie::FooArray instead of abusing overloading.

      You say "deal with the interface, not the implementation", and I agree. But, that contract must be between programmers. You can't expect one module to discover and deal appropriately with the multitude of interfaces that exist. In Perl especially, enforcing such a contract is not the job of the language. In Perl, it's not even defined by the language, but by the documentation.

      As for me knowing it should be stringified ... HTML::Template should trust me.

      Any module, HTML::Template included, should only have to trust you to abide by its interface. It should not be required to make assumptions about what your data is, and it should be allowed to make decisions based upon what your data appears to be when checked with a builtin function such as ref().

      It smacks too much of B&D, the way it does things now.

      I don't buy that. A module can't be expected to support every overly clever interface that might come its way. It can only be expected to provide its own. The programmer's job is to glue them together.

      -sauoq
      "My two cents aren't worth a dime.";