Arc Forumnew | comments | leaders | submitlogin
Improved plural, pluralize
3 points by zck 3845 days ago | 5 comments
In the course of writing my unit testing library, I wanted to pluralize a word. Great! Arc has a method to do that!

    arc> (pluralize 2 "pass")
    "passs"
Hrm, that's not right. Sure, we could write something to detect if we should add an "s" or an "es", but that would definitely be buggy.

But we can explicitly set the plural, if it's different.

    (def pluralize (n str (o plural-form (string str "s")))
      (if (or (is n 1) (single n))
          str
        plural-form))

    (def plural (n str (o plural-form (string str "s")))
      (string n
              #\space
              (pluralize n str plural-form)))
And how is it used? Well, here's some unit tests for it. (Note: I'd still love any feedback you've got on the unit test library (https://bitbucket.org/zck/unit-test.arc/)).

    (suite pluralize
           0-pants (assert-same "pants"
                                (pluralize 0 "pant"))
           1-pant (assert-same "pant"
                               (pluralize 1 "pant"))
           2-pants (assert-same "pants"
                                (pluralize 2 "pant"))
           0-oxen (assert-same "oxen"
                               (pluralize 0 "ox" "oxen"))
           1-explosion (assert-same "explosion"
                                    (pluralize 1 "explosion" "EXPLOSIONS ARE AWESOME!"))
           7-formulae (assert-same "formulae"
                                   (pluralize 7 "formula" "formulae")))


    (suite plural
           0-pants (assert-same "0 pants"
                                (plural 0 "pant"))
           1-pant (assert-same "1 pant"
                               (plural 1 "pant"))
           2-pants (assert-same "2 pants"
                                (plural 2 "pant"))
           0-oxen (assert-same "0 oxen"
                               (plural 0 "ox" "oxen"))
           1-explosion (assert-same "1 explosion"
                                    (plural 1 "explosion" "EXPLOSIONS ARE AWESOME!"))
           7-formulae (assert-same "7 formulae"
                                   (plural 7 "formula" "formulae")))
Sweet! You have to explicitly write out the plural, but that's not so bad. I considered having the optional argument be suffix instead, but that left out plurals like "party" -> "parties", "foot" -> "feet", and "fish" -> "fish". This way is more general, arguably easier to write, is unit tested, fully backwards compatible, and so I think it's better. Also it doesn't use #\ , preferring #\space. So much easier to read.

Of course, after implementing it, I found I didn't actually need to pluralize the word "pass" in the code I was writing. Dang.



2 points by thaddeus 3836 days ago | link

I like it.

It seems to me , however, that a better solution would be to store the exceptions in a table, then for plural to check for an exception value before defaulting to adding an s.

As you have defined it, we would need to be aware of each exception when the function gets called, often having to add hard coded data for each exception condition and possibly many times.

[edit: what would be really nice is to keep your code along with using a lookup table + memoization.]

-----

2 points by zck 3836 days ago | link

A lookup table would be interesting. I considered that, but wavered -- would it be filled at write-time, or by some sort of memoization? Keep in mind that if it's memoized, you have to worry about when you tell the function what the plural should be, or you could get inconsistent data.

Is there a use case where you're not aware of the exception when calling the function?

-----

2 points by thaddeus 3836 days ago | link

I had imagined that the table would just be defined in advance from a src file. That would be consistent with other comparable features arc offers. And the memoization would just be a code efficiency thing.

If we don't care about being consistent, it certainly would be cool to have the table load from a data file, and then to have the first run of an override write to file when it's not present. Memoization to, again, cover code efficiency.

As for use cases I only had a few plural overrides I needed to deal with and I too just hard coded them. At the time I did so I remember thinking I should put it in a table, but never got around to it. Then I saw your post and I thought of it again!

Note that I don't really use arc these days, but I have ported most arc functions over to clojure and I'm always looking to improve my library. In my clojure world I would just store them in datomic as facts. I think I might run along and do this now that I've spent some time thinking about it ... ;)

-----

2 points by akkartik 3836 days ago | link

"Is there a use case where you're not aware of the exception when calling the function?"

Any situation where the string being pluralized is not a literal. This is I suppose why rails pluralization doesn't work like this.

-----

2 points by zck 3836 days ago | link

Oh. Duh.

-----