1
0
mirror of https://github.com/golang/go synced 2024-11-19 12:04:43 -07:00

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
This commit is contained in:
Rob Pike 2011-07-14 07:59:04 +10:00
parent c3344d61bd
commit 469e333106
4 changed files with 45 additions and 18 deletions

View File

@ -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

View File

@ -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")
}

View File

@ -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},

View File

@ -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]))
}
return
func truth(a interface{}) bool {
t, _ := isTrue(reflect.ValueOf(a))
return t
}
// 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]))
// 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
}
return
for i := range args {
arg0 = args[i]
if !truth(arg0) {
break
}
}
return arg0
}
// 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 arg0
}
// not returns the Boolean negation of its argument.