diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-24 14:02:57 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-24 14:02:57 +0300 |
| commit | 7d754768b8d610015cdb016ecda54bbdad54fa6c (patch) | |
| tree | b57bce192aa0ecdac3934b9d636e2b64f32a96de /internal | |
| parent | f3beef8ce2f538783889c55d685fa30a471983b7 (diff) | |
fix(rpn): extract metric inference rules into data-driven maps (task kj)
Replace hardcoded switch statements in resultMetricForMul and
resultMetricForDiv with package-level maps (multiplicationInference,
divisionInference). Adding new category pairs now only requires
appending to the maps instead of editing control flow, satisfying
OCP.
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/rpn/operations_metric.go | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/internal/rpn/operations_metric.go b/internal/rpn/operations_metric.go index decaad8..64cce98 100644 --- a/internal/rpn/operations_metric.go +++ b/internal/rpn/operations_metric.go @@ -106,6 +106,15 @@ func convertFromBase(reg *MetricRegistry, baseVal float64, m *Metric, mode Prefi return baseVal / m.Factor(mode), nil } +// multiplicationInference maps ordered category pairs to the result base-unit name. +// Both orderings are stored so that map lookup replaces the switch for commutative mul. +var multiplicationInference = map[[2]Category]string{ + {DataRate, Time}: "bits", + {Time, DataRate}: "bits", + {Speed, Time}: "m", + {Time, Speed}: "m", +} + // resultMetricForMul computes the resulting metric for multiplication. func resultMetricForMul(reg *MetricRegistry, a, b *Metric) (*Metric, error) { if a == nil || a.Category == Universal { @@ -118,19 +127,17 @@ func resultMetricForMul(reg *MetricRegistry, a, b *Metric) (*Metric, error) { return a, nil } - // Cross-category inference - switch { - case a.Category == DataRate && b.Category == Time: - return baseMetric(reg, "bits") - case a.Category == Time && b.Category == DataRate: - return baseMetric(reg, "bits") - case a.Category == Speed && b.Category == Time: - return baseMetric(reg, "m") - case a.Category == Time && b.Category == Speed: - return baseMetric(reg, "m") - default: - return baseMetric(reg, "Cool") + if name, ok := multiplicationInference[[2]Category{a.Category, b.Category}]; ok { + return baseMetric(reg, name) } + return baseMetric(reg, "Cool") +} + +// divisionInference maps (dividend, divisor) category pairs to the result base-unit name. +// Unlike multiplication, division is not commutative so order matters. +var divisionInference = map[[2]Category]string{ + {DataSize, Time}: "bps", + {Distance, Time}: "mps", } // resultMetricForDiv computes the resulting metric for division. @@ -151,15 +158,10 @@ func resultMetricForDiv(reg *MetricRegistry, a, b *Metric) (*Metric, error) { return baseMetric(reg, "Cool") } - // Cross-category inference - switch { - case a.Category == DataSize && b.Category == Time: - return baseMetric(reg, "bps") - case a.Category == Distance && b.Category == Time: - return baseMetric(reg, "mps") - default: - return baseMetric(reg, "Cool") + if name, ok := divisionInference[[2]Category{a.Category, b.Category}]; ok { + return baseMetric(reg, name) } + return baseMetric(reg, "Cool") } // metricError returns a descriptive error for incompatible metric operations. |
