A language helps to shape the libraries that are written on it. This can have unexpected side-effects when using these libraries from a different language.
Recently, we were trying to debug a strange issue with one of my coworkers, where we had a list of selectable items with a checkbox to select/unselect all the items. Selecting all the items was working properly, but only the first item got unselected.
After debugging it for a while we reached the conclusion that the iteration was being interrupted. Could
lodash have such a serious bug?
Fortunately, we decided to skip that theory, and instead reached for the documentation, which stated:
Iteratee functions may exit iteration early by explicitly returning false.
Which sounds like a reasonable feature that can help to create more efficient algorithms—though we weren’t returning
But CoffeeScript was. The language draws inspiration from Ruby, and it borrows features like expressions and implicit returns. For functions, this means that the last executed expression becomes the return value of the function. This allows us to write very concise functions:
If we reinterpret our snippet above taking implicit returns into account, it is equivalent to:
When we unselect all the items and
selectAll(false) is called, the first iteration returns the value of
task.selected which is
false, causing lodash to exit the iteration. Mistery solved
We can fix the bug by explicitly returning
true on each loop, which will avoid stopping the iteration, and all the items will be unselected correctly.
These are two useful features on their own, yet extremely inconvenient when combined. The reason is that the library was written for a language with a different mindset. The design of the language and the design of the library are not fully compatible.
Watch out for language differences when using libraries written for another language, they will bite sooner or later.