++ed by:

3 PAUSE users
2 non-PAUSE users.

Author image Christian Jaeger
and 1 contributors


FP::Show - give (nice) code representation for debugging purposes


    use FP::Show; # exports 'show'
    use FP::List;

    is show(list(3, 4)->map(sub{$_[0]*10})), "list(30, 40)";


The 'show' function takes a value and returns a string of Perl code which when evaluated should produce an equivalent clone of that value (assuming that the Perl functions used in the string are imported into the namespace where the code is evaluated).

It is somewhat like Data::Dumper, but enables classes to determine the formatting of their instances by implementing the FP::Abstract::Show protocol (for details, see there). This allows for concise, more highlevel output than just showing the bare internals. It's, for example, normally not useful when inspecting data for debugging to know that an instance of FP::List consists of a chain of FP::List::Pair objects which in turn are made of blessed arrays or what not; just showing a call to the same convenience constructor function that can be used normally to create such a value is a better choice (see the example in the SYNOPSIS, and for more examples the `intro` document of the Functional Perl distribution or website).

`show` always works, regardless of whether a value implements the protocol--it falls back to Data::Dumper.


Data::Dumper *does* have a similar feature, $Data::Dumper::Freezer, but it needs the object to be mutated, which is not what one will want.

Why not use string overloading instead? Because '""' overloading is returning 'plain' strings, not perl code (or so it seems, is there any spec that defines exactly what it means?) Code couldn't know whether to quote the result:

    sub foo2 {
        my ($l) = @_;
        # this is quoting safe:
        die "not what we wanted: ".show($l)
        # this would not be:
        #die "not what we wanted: $l"

    eval { foo2 list 100-1, "bottles"; };
    like $@, qr/^\Qnot what we wanted: list(99, 'bottles')/;
    eval { foo2 "list(99, 'bottles')"; };
    like $@, qr/^\Qnot what we wanted: 'list(99, \'bottles\')'/;
    # so how would you tell which value foo2 really got in each case,
    # just from looking at the message?

    # also:
    eval { foo2 +{a => 1, b => 10}; };
    like $@, qr/^\Qnot what we wanted: +{a => 1, b => 10}/;
      # would die with something like:
      #   not what we wanted: HASH(0xEADBEEF)
      # which isn't very informative

Embedding pointer values in the output also means that it can't be used for automatic testing. (Even with a future implementation of cut-offs, values returned by `show` will be good enough when what one needs to do is compare against a short representation. Also, likely we would implement the cut-off value as an optional parameter.)


Show can't currently handle circular data structures (it will run out of stack space), and it will not detect sharing.

Show does not use code formatting, which can make complex output difficult to read.

Both of these are planned to be fixed by using FP::AST::Perl and changing the protocol.


FP::Abstract::Show for the protocol definition. Note that FP::Show also works on values which don't implement the protocol (fall back to Data::Dumper).

http://www.functional-perl.org/docs/intro.xhtml for the mentioned intro.



This is alpha software! Read the status section in the package README or on the website.