antlr / stringtemplate4

StringTemplate 4
http://www.stringtemplate.org
Other
956 stars 231 forks source link

Enhance if-attribute conditional treat number zero and empty containers as false #92

Closed martinda closed 9 years ago

martinda commented 9 years ago

The if-attribute conditional could be enhanced to convert certain data type values to boolean. For example, python and groovy convert empty containers (empty lists, empty hash tables, empty maps) to false, the empty string to false and number zero to false (non-zero would be true, positive or negative). It looks as if nulls are already converted to false. I think this would be useful, as it would reduce the business logic when assigning template values. Right now, zeros, empty strings and empty containers have to be explicitely converted to false or null before being passed to the template.

sharwell commented 9 years ago

StringTemplate 4 defines the result of <if(x)> for all values of x.

x <if(x)>foo<else>bar<endif>
null or not defined bar
true (Boolean in Java) foo
false (Boolean in Java) bar
Instance of Collection<E> or Map<K, V>, where size() > 0 foo
Instance of Collection<E> or Map<K, V>, where size() == 0 bar
Instance of Iterable<T>, where x.iterator().hasNext() foo
Instance of Iterable<T>, where !x.iterator().hasNext() bar
Instance of Iterator<T>, where x.hasNext() foo
Instance of Iterator<T>, where !x.hasNext() bar
Otherwise foo

Since there are no values for which <if(x)> is an error, changing the behavior of this construct runs a very high risk of breaking the behavior of applications that already use it. Can you give a more specific example of the inputs you have and the outputs you want? There may be another way to approach your specific case that fits within the current behavior.

martinda commented 9 years ago

What about the case where x is a number and has a value of zero or x is a string and has a length of zero?

On Sun, Dec 14, 2014 at 10:41 PM, Sam Harwell notifications@github.com wrote:

StringTemplate 4 defines the result of <if(x)> for all values of x. x <if(x)>foobar null or not defined bar true (Boolean in Java) foo false (Boolean in Java) bar Instance of Collection or Map<K, V>, where size() > 0 foo Instance of Collection or Map<K, V>, where size() == 0 bar Instance of Iterable, where x.iterator().hasNext() foo Instance of Iterable, where !x.iterator().hasNext() bar Instance of Iterator, where x.hasNext() foo Instance of Iterator, where !x.hasNext() bar Otherwise foo

Since there are no values for which <if(x)> is an error, changing the behavior of this construct runs a very high risk of breaking the behavior of applications that already use it. Can you give a more specific example of the inputs you have and the outputs you want? There may be another way to approach your specific case that fits within the current behavior.

Reply to this email directly or view it on GitHub https://github.com/antlr/stringtemplate4/issues/92#issuecomment-66946523 .

sharwell commented 9 years ago

Both of those cases fall into the "Otherwise" category at the end of the table.

If you want zero and the empty string to be treated as false for a particular expression, you can use something like this:

zeroOrEmptyAsFalse ::= [
  "": [],
  "0": [],
  default: key
]

example(value) ::= "<if(zeroOrEmptyAsFalse.(value))>foo<else>bar<endif>"

Note that the above is supported starting with StringTemplate 4.0.7 (see #33). Prior to that, you would need to use the following definition for zeroOrEmptyAsFalse:

zeroOrEmptyAsFalse ::= [
  "": false,
  "0": false,
  default: key
]
parrt commented 9 years ago

ah. i wondered if we already handled len(list)==0 etc... Yeah, testing 0 as false would break the semantics.