mirror of
https://github.com/golang/go
synced 2024-11-21 15:24:45 -07:00
text/template: allow eq to take more than two arguments
Based on an old suggestion by rsc, it compares the second and following arguments to the first. Unfortunately the code cannot be as pretty as rsc's original because it doesn't require identical types. R=golang-dev, dsymonds, adg CC=golang-dev https://golang.org/cl/13509046
This commit is contained in:
parent
54b2a83d9a
commit
0ba7ffe289
@ -326,13 +326,22 @@ functions:
|
||||
ge
|
||||
Returns the boolean truth of arg1 >= arg2
|
||||
|
||||
These functions work on basic types only (or named basic types,
|
||||
such as "type Celsius float32"). They implement the Go rules for
|
||||
comparison of values, except that size and exact type are ignored,
|
||||
so any integer value may be compared with any other integer value,
|
||||
any unsigned integer value may be compared with any other unsigned
|
||||
integer value, and so on. However, as usual, one may not compare
|
||||
an int with a float32 and so on.
|
||||
For simpler multi-way equality tests, eq (only) accepts two or more
|
||||
arguments and compares the second and subsequent to the first,
|
||||
returning in effect
|
||||
|
||||
arg1==arg2 || arg1==arg3 || arg1==arg4 ...
|
||||
|
||||
(Unlike with || in Go, however, eq is a function call and all the
|
||||
arguments will be evaluated.)
|
||||
|
||||
The comparison functions work on basic types only (or named basic
|
||||
types, such as "type Celsius float32"). They implement the Go rules
|
||||
for comparison of values, except that size and exact type are
|
||||
ignored, so any integer value may be compared with any other integer
|
||||
value, any unsigned integer value may be compared with any other
|
||||
unsigned integer value, and so on. However, as usual, one may not
|
||||
compare an int with a float32 and so on.
|
||||
|
||||
Associated templates
|
||||
|
||||
|
@ -891,6 +891,8 @@ var cmpTests = []cmpTest{
|
||||
{"eq `xy` `xyz`", "false", true},
|
||||
{"eq .Xuint .Xuint", "true", true},
|
||||
{"eq .Xuint .Yuint", "false", true},
|
||||
{"eq 3 4 5 6 3", "true", true},
|
||||
{"eq 3 4 5 6 7", "false", true},
|
||||
{"ne true true", "false", true},
|
||||
{"ne true false", "true", true},
|
||||
{"ne 1+2i 1+2i", "false", true},
|
||||
@ -946,7 +948,6 @@ var cmpTests = []cmpTest{
|
||||
{"ge .Xuint .Yuint", "false", true},
|
||||
{"ge .Yuint .Xuint", "true", true},
|
||||
// Errors
|
||||
{"eq 3 4 5", "", false}, // Too many arguments.
|
||||
{"eq `xy` 1", "", false}, // Different types.
|
||||
{"lt true true", "", false}, // Unordered types.
|
||||
{"lt 1+0i 1+0i", "", false}, // Unordered types.
|
||||
@ -970,7 +971,7 @@ func TestComparison(t *testing.T) {
|
||||
continue
|
||||
}
|
||||
if !test.ok && err == nil {
|
||||
t.Errorf("%s did not error")
|
||||
t.Errorf("%s did not error", test.expr)
|
||||
continue
|
||||
}
|
||||
if b.String() != test.truth {
|
||||
|
@ -264,6 +264,7 @@ func not(arg interface{}) (truth bool) {
|
||||
var (
|
||||
errBadComparisonType = errors.New("invalid type for comparison")
|
||||
errBadComparison = errors.New("incompatible types for comparison")
|
||||
errNoComparison = errors.New("missing argument for comparison")
|
||||
)
|
||||
|
||||
type kind int
|
||||
@ -297,39 +298,47 @@ func basicKind(v reflect.Value) (kind, error) {
|
||||
return invalidKind, errBadComparisonType
|
||||
}
|
||||
|
||||
// eq evaluates the comparison a == b.
|
||||
func eq(arg1, arg2 interface{}) (bool, error) {
|
||||
// eq evaluates the comparison a == b || a == c || ...
|
||||
func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
|
||||
v1 := reflect.ValueOf(arg1)
|
||||
k1, err := basicKind(v1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
v2 := reflect.ValueOf(arg2)
|
||||
k2, err := basicKind(v2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
if len(arg2) == 0 {
|
||||
return false, errNoComparison
|
||||
}
|
||||
if k1 != k2 {
|
||||
return false, errBadComparison
|
||||
for _, arg := range arg2 {
|
||||
v2 := reflect.ValueOf(arg)
|
||||
k2, err := basicKind(v2)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if k1 != k2 {
|
||||
return false, errBadComparison
|
||||
}
|
||||
truth := false
|
||||
switch k1 {
|
||||
case boolKind:
|
||||
truth = v1.Bool() == v2.Bool()
|
||||
case complexKind:
|
||||
truth = v1.Complex() == v2.Complex()
|
||||
case floatKind:
|
||||
truth = v1.Float() == v2.Float()
|
||||
case intKind:
|
||||
truth = v1.Int() == v2.Int()
|
||||
case stringKind:
|
||||
truth = v1.String() == v2.String()
|
||||
case uintKind:
|
||||
truth = v1.Uint() == v2.Uint()
|
||||
default:
|
||||
panic("invalid kind")
|
||||
}
|
||||
if truth {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
truth := false
|
||||
switch k1 {
|
||||
case boolKind:
|
||||
truth = v1.Bool() == v2.Bool()
|
||||
case complexKind:
|
||||
truth = v1.Complex() == v2.Complex()
|
||||
case floatKind:
|
||||
truth = v1.Float() == v2.Float()
|
||||
case intKind:
|
||||
truth = v1.Int() == v2.Int()
|
||||
case stringKind:
|
||||
truth = v1.String() == v2.String()
|
||||
case uintKind:
|
||||
truth = v1.Uint() == v2.Uint()
|
||||
default:
|
||||
panic("invalid kind")
|
||||
}
|
||||
return truth, nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ne evaluates the comparison a != b.
|
||||
|
Loading…
Reference in New Issue
Block a user