bijington/expressive

Behaviour of `Count()` with string vs. number parameters

Closed this issue · 2 comments

Behaviour of Count() with string vs. number parameters

Again, this comment just captures a behavioural quirk which people should know about. However, unlike with Random() above, this one may warrant some discussion about what would be the most desirable behaviour.

When all of the parameters are numbers, Count() returns the number of parameters.

When all of the parameters are strings, Count() returns the total number of characters across all the strings, i.e. Length(parameter1) + Length(parameter2) +. ....

When the parameters are mixed, Count() returns the number of numeric parameters plus the total number of characters across all the string parameters:

  • Count(123) = 1
  • Count('123') = 3
  • Count(123, 4) = 2
  • Count('123', 4) = 4
  • Count(123, '4') = 2
  • Count('foo', 123) = 4
  • Count('foo', '123') = 6

In all cases, the Count() function does not do the same thing as:

  • .NET's various Count properties and Count() methods return the number of elements in the collection, or equivalently, the number of parameters in the parameter list.
  • Excel's COUNT() function returns a count of the numbers in the parameter list.

I'm not sure if the current behaviour is all that useful. I can't think of a decent use case - maybe other folks can?

The current behaviour with all string parameters is kind of like Length() if you were able to supply an aggregate as a parameter value like you can now do with operators. (by the way, upvote +100 for aggregates in functions, please!!!) Once that's possible, then this behaviour for string parameters would be redundant.

The current behaviour with all numeric parameters is just a count of the number of parameters, basically the same as Count in .NET, for example. The Count() function could be modified so this is the behaviour for mixed parameter types too - at least it would be consistent across types. But right now you already know how many parameters you are supplying (unless the expressions are generated, I suppose). This behaviour won't be all that powerful until you can supply an aggregate as a parameter value. (another upvote +100 for that, please!!!)

Originally posted by @graniero in #86 (comment)

To be clear this is definitely an issue.

The expressions from above should evaluate as follows:

  • Count(123) = 1
  • Count('123') = 1
  • Count(123, 4) = 2
  • Count('123', 4) = 2
  • Count(123, '4') = 2
  • Count('foo', 123) = 2
  • Count('foo', '123') = 2

I suspect the count code is checking for IEnumerable which string implements so we may just need to go a little higher up in the inheritance hierarchy.

Fixed by #102