Commit 469e3331 authored by Rob Pike's avatar Rob Pike

exp/template: tweak behavior of booleans.

Russ suggested this technique, making the "and" and "or" functions handier.
But it's hacky, and I can be talked out of it.

R=dsymonds, rsc
CC=golang-dev
https://golang.org/cl/4698044
parent c3344d61
......@@ -199,7 +199,10 @@ the set but the Funcs methods can be used to add them.
Predefined global functions are named as follows.
and
Returns the boolean AND of its arguments.
Returns the boolean AND of its arguments by returning the
first empty argument or the last argument, that is,
"and x y" behaves as "if x then y else x". All the
arguments are evaluated.
html
Returns the escaped HTML equivalent of the textual
representation of its arguments.
......@@ -213,7 +216,10 @@ Predefined global functions are named as follows.
not
Returns the boolean negation of its single argument.
or
Returns the boolean OR of its arguments.
Returns the boolean OR of its arguments by returning the
first non-empty argument or the last argument, that is,
"or x y" behaves as "if x then x else y". All the
arguments are evaluated.
print
An alias for fmt.Sprint
printf
......
......@@ -289,7 +289,7 @@ func (s *state) evalCommand(dot reflect.Value, cmd *commandNode, final reflect.V
case *stringNode:
return reflect.ValueOf(word.text)
}
s.errorf("can't handle command %q", firstWord)
s.errorf("can't evaluate command %q", firstWord)
panic("not reached")
}
......
......@@ -280,8 +280,8 @@ var execTests = []execTest{
// Booleans
{"not", "{{not true}} {{not false}}", "false true", nil, true},
{"and", "{{and 0 0}} {{and 1 0}} {{and 0 1}} {{and 1 1}}", "false false false true", nil, true},
{"or", "{{or 0 0}} {{or 1 0}} {{or 0 1}} {{or 1 1}}", "false true true true", nil, true},
{"and", "{{and false 0}} {{and 1 0}} {{and 0 true}} {{and 1 1}}", "false 0 0 1", nil, true},
{"or", "{{or 0 0}} {{or 1 0}} {{or 0 true}} {{or 1 1}}", "0 1 true 1", nil, true},
{"boolean if", "{{if and true 1 `hi`}}TRUE{{else}}FALSE{{end}}", "TRUE", tVal, true},
{"boolean if not", "{{if and true 1 `hi` | not}}TRUE{{else}}FALSE{{end}}", "FALSE", nil, true},
......@@ -326,6 +326,10 @@ var execTests = []execTest{
{"range empty map else", "{{range .MSIEmpty}}-{{.}}-{{else}}EMPTY{{end}}", "EMPTY", tVal, true},
{"range empty interface", "{{range .Empty3}}-{{.}}-{{else}}EMPTY{{end}}", "-7--8-", tVal, true},
// Cute examples.
{"or as if true", `{{or .SI "slice is empty"}}`, "[3 4 5]", tVal, true},
{"or as if false", `{{or .SIEmpty "slice is empty"}}`, "slice is empty", tVal, true},
// Error handling.
{"error method, error", "{{.EPERM true}}", "", tVal, false},
{"error method, no error", "{{.EPERM false}}", "false", tVal, true},
......
......@@ -122,22 +122,39 @@ func index(item interface{}, indices ...interface{}) (interface{}, os.Error) {
// Boolean logic.
// and returns the Boolean AND of its arguments.
func and(arg0 interface{}, args ...interface{}) (truth bool) {
truth, _ = isTrue(reflect.ValueOf(arg0))
for i := 0; truth && i < len(args); i++ {
truth, _ = isTrue(reflect.ValueOf(args[i]))
func truth(a interface{}) bool {
t, _ := isTrue(reflect.ValueOf(a))
return t
}
// and computes the Boolean AND of its arguments, returning
// the first false argument it encounters, or the last argument.
func and(arg0 interface{}, args ...interface{}) interface{} {
if !truth(arg0) {
return arg0
}
for i := range args {
arg0 = args[i]
if !truth(arg0) {
break
}
}
return
return arg0
}
// or returns the Boolean OR of its arguments.
func or(arg0 interface{}, args ...interface{}) (truth bool) {
truth, _ = isTrue(reflect.ValueOf(arg0))
for i := 0; !truth && i < len(args); i++ {
truth, _ = isTrue(reflect.ValueOf(args[i]))
// or computes the Boolean OR of its arguments, returning
// the first true argument it encounters, or the last argument.
func or(arg0 interface{}, args ...interface{}) interface{} {
if truth(arg0) {
return arg0
}
for i := range args {
arg0 = args[i]
if truth(arg0) {
break
}
}
return
return arg0
}
// not returns the Boolean negation of its argument.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment