Overview
Currently, the %IF macro only allows one conditional test (i.e. if / then / else). It is proposed to:
- Enhance the %IF macro to allow the ability to build if / elsif / elsif / else statements,
- Enhance the parsing code in Foswiki::Attrs to allow for clean syntax for %IF (probably via creating a subclass).
There is more than one way that Foswiki::Attrs can be modified:
Store Repeated Attributes in an Array (SRA)
If an attribute of the same name is defined more than once, Foswiki::Attrs simply uses the last value to be defined.
SRA would enhance / subclass Foswiki::Attrs so that all of the values for a repeated attribute can be retrieved. This
would be the %IF syntax:
%IF{"condition 1"
then="condition 1 is true."
elsif="condition 2"
then="condition 2 is true and condition 1 is false."
elsif="condition 3"
then="condition 3 is true and conditions 1 and 2 are false."
else="nothing is true. all is permissible."}%
Complex Attribute Types (CAT)
Attribute passing to a macro must be done via a hash map. CAT would enhance / subclass Foswiki::Attrs
so that richer data types can be passed to a macro: ordered lists, ordered lists of hashes, etc.
%IF{tests=[
{if="condition 1"
then="condition 1 is true." },
{if="condition 2"
then="condition 2 is true and condition 1 is false." },
{if="condition 3"
then="condition 3 is true and conditions 1 and 2 are false."}]
else="nothing is true. all is permissible."}%
Nested Ifs
Perhaps if a TML author feels the need to write a nested if, it's a sign that the TML is getting too complicated.
He should break up his logic with %INLCUDE or %TMPL:P. Nevertheless, here is what nested ifs would look like:
SRA
%IF{"condition 1"
then="$percentIF{\"condition 2\"
then=\"c1 and c2. Hello $percentpercentWIKIUSER$percentpercent\"
else=\"c1 but not c2\""
else="nothing is true. all is permissible."}%
CAT
%IF{tests=[
{if="condition 1"
tests=[
{if="condition 2"
then="c1 and c2. Hello $percentWIKIUSER$percent"
else="c1 but not c2" } ] },
else="nothing is true. all is permissible."}%
--
KipLubliner
If we are going to extend the syntax of
Foswiki::Attrs
to support multi-valued attributes (and I support this) then it should not be done as a subclass but be part of the standard implementation. Consistency with the existing usage of Foswiki::Attrs can be achieved through the use of
wantarray
.
I am very concerned about the CAT proposal. Looks like quoting hell to me.
--
CrawfordCurrie - 12 Feb 2012
I'm afraid that I probably pointed Kip down the path of doing a subclass, in a response to
SvenDowdeit's comment on IRC that he didn't want to see
Foswiki::Attrs
become too magical. But now that I recall that conversation, perhaps he was only reacting to the idea of
$params->{foo}
magically becoming arrayrefs (sven?)
--
PaulHarvey - 12 Feb 2012
As Paul said,
Foswiki::Attrs
main interface is a raw hashref lookup. If we simply store an arrayref in there, then we are changing the semantics of repeated attribute keys. This could cause a problem for sites that rely on the current behavior. There could be code out there like:
%MACRO{value="default val" %IF{"condition" then="value=\"other val\""}%}%
This is quite odd, but legal given the currently documented behavior. I just wanted to point out the risks, and also to note that this definitely should not be included in a point release.
Crawford: I'm not clear about your comment about
wantarray
. We would need to use
tie
to get a method behind
$params->{foo}
. That FETCH method could use
wantarray
to decide whether to return a scalar or an array. That would address the issue mentioned above (in the %MACRO example). Is this what you had in mind? One thing to consider - Paul said that attrs parsing came up as a 'hot-spot' in his profiling with nytprof. I'm wary about making any changes that would degrade performance.
For the record, I was leaning towards CAT ... until I actually wrote out examples of what the syntax would look like. Now I am in favor of SRA.
--
KipLubliner - 12 Feb 2012
Perhaps Crawford means passing a
wantarray
option to the constructor, Eg.
my $params = Foswiki::Attrs->new($syntax, wantarrays => 1);
--
PaulHarvey - 12 Feb 2012
Keeping all attributes of the same name instead of throwing away all but the last one is very much in line with
SettingAndGettingVariablesUsingMacros where
%SET{"foo" value="1" value="2" value="3"}%
is used to store a list. So part of that proposal already
is to enhance
Foswiki::Attrs
in that way.
--
MichaelDaum - 13 Feb 2012
Be careful to separate the cost of
parsing attributes and that of
accessing the value of attributes. No, I wasn't thinking of a tie; I was thinking of providing two interfaces -
->{attr}
which always returns the last attribute value and
->get('attr')
which uses a =wantarray.
--
CrawfordCurrie - 13 Feb 2012