in reply to Undef value in Template Toolkit

What exactly "way around this" do you want? Perl itself treats undef in a string context as an empty string. What do you expect TT to do instead?

The cake is a lie.
The cake is a lie.
The cake is a lie.

Replies are listed 'Best First'.
Re^2: Undef value in Template Toolkit
by DreamT (Pilgrim) on Aug 20, 2019 at 14:51 UTC
    The goal is to set the mentioned variable to undef, rather than an empty string.

      This sounds like an XY problem(?). I would argue that manipulating data within templates is generally a mistake. Caring about what form unviewable data is within a view also seems like a mismatch to the context.

        I get your point. Indeed at XY problem, given that there probably are better solutions for this
        The goal here was to create a "mapper" from one data source (a data structure from another system) to another (a data structure that "fits" in my system). Something like this:
        [% destination.header.address.surname = source.orderData.custI +nfo.surname %] [% destination.header.timestamps.created = methods.tounixtime(sour +ce.orderData.orderDate) %]

        This results in a hash structure that is converted to the format my system expects. I.e. So yes, I'm using Template Toolkit to manipulate/process data.

        I would agree that TT isn't a good solution for this from a developers point of view. But the end result is _exactly_ what I'm looking for, a simple "configuration file" where the intended user (a system admin that sometimes dynamically needs to change/add fields) can do what he/she needs. If I could find a better solution for it, I would use it ;-)
        I am generally uncomfortable with "program logic in a template," because that's not where I expect to find it.
      This seems to be some intermediate or side effect goal to me. TT's output is a string, so for that purpose undef and the empty string are equivalent. Maybe you have something like [% IF hashref.defined('value1') %]...[% END %] later on, or you want to pass a value back to the Perl code which called TT's process? For these situations you can [% hashref.delete('value1') %] which should do the trick unless you also need to distinguish between keys which exist from keys with an undefined value.
        Yes, I'm basically using TT as a field mapper (se my other reply in this thread), i.e. " pass a value back to the Perl code".
        And I need to distinguish between existing/undefined.

      It is undef. However you're displaying it is stringifying it most likely.

      Update: Oops, I stand corrected. Assigning undef in a template does look like it gets an empty string. Interesting. Amended code sample setting baz directly in the template.

      Another update: Did some poking and I'm most of the way to convincing myself to agreeing that this might be a bug. It's prossibly worth at least pinging the mailing list with a sample script like this and seeing what the maintainers say.

      Update the third: ++ and agreement with those below that relying on results from logic in the display template for anything other than displaying things just raises the hackles.

      #!/usr/bin/env perl use strict; use warnings; use Template (); my $t = Template->new( {} ); my $tmpl_source = <<"EOT"; This is my template. [% timestamp %] [%- IF foo.defined %] foo is defined and is "[% foo %]" [%- ELSE %] foo is undef [%- END %] [%- IF bar.defined %] bar is defined and is "[% bar %]" [%- ELSE %] bar is undef [%- END %] [%- baz = undef -%] [%- IF baz.defined %] baz is defined and is "[% baz %]" [%- ELSE %] baz is undef [%- END %] Done. EOT $t->process( \$tmpl_source, { foo => undef, bar => q{}, timestamp => scalar localtime() } ) or die $t->error, qq{\n}; exit 0; __END__ $ perl tt_test.plx This is my template. Tue Aug 20 11:07:30 2019 foo is undef bar is defined and is "" baz is defined and is "" Done.

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.

        It's intentional, if now regretted.

        From Template-Toolkit/source/lib/Template/Stash.pm

        #--------------------------------------------------------------------- +--- # undefined($ident, $args) # # Method called when a get() returns an undefined value. Can be redef +ined # in a subclass to implement alternate handling. #--------------------------------------------------------------------- +--- sub undefined { my ($self, $ident, $args) = @_; if ($self->{ _STRICT }) { # Sorry, but we can't provide a sensible source file and line +without # re-designing the whole architecture of TT (see TT3) die Template::Exception->new( $UNDEF_TYPE, sprintf( $UNDEF_INFO, $self->_reconstruct_ident($ident) ) ) if $self->{ _STRICT }; } else { # There was a time when I thought this was a good idea. But it +'s not. return ''; } }