From: Rob Pike Date: Wed, 4 Sep 2013 03:42:22 +0000 (+1000) Subject: text/template: allow eq to take more than two arguments X-Git-Tag: go1.2rc2~354 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0ba7ffe2897cd9771de172362e9edcb5f733cf1f;p=gostls13.git 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 --- diff --git a/src/pkg/text/template/doc.go b/src/pkg/text/template/doc.go index ab18f9ab1a..f622ac7dce 100644 --- a/src/pkg/text/template/doc.go +++ b/src/pkg/text/template/doc.go @@ -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 diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go index bc8aee6f3c..f60702de8f 100644 --- a/src/pkg/text/template/exec_test.go +++ b/src/pkg/text/template/exec_test.go @@ -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 { diff --git a/src/pkg/text/template/funcs.go b/src/pkg/text/template/funcs.go index 63287085aa..e854122624 100644 --- a/src/pkg/text/template/funcs.go +++ b/src/pkg/text/template/funcs.go @@ -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 - } - 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") + 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 + } } - return truth, nil + return false, nil } // ne evaluates the comparison a != b.