Another week of my career makeover at Learners Guild has elapsed. I’m almost disappointed to report that it was free of crises.
My teammate has been at the Guild about 20 weeks, so this week gave me a chance to experience asymmetry in experience. It’s actually a bit complicated, this asymmetry. You might think it means A knows a lot more than B, so the information flow is all from A to B. Or maybe A asks B to perform some easier tasks that are within B’s competence. Or perhaps A does the work, explaining it to B.
It may be like that in some cases, but my experience differed. In fact, there are thousands of factoids and skilloids in our environment, and there is a good deal of choice open to Learners, so it simply isn’t true that A knows everything that B knows and then some. What’s surprising to me (although it happens to my wife and me a few times a week) is that A and B each know things that the other doesn’t know (or has forgotten) and that the knower assumes are utterly basic.
Today, for example, our coach was reviewing our code, and he noticed the line “continue arg0” in my code. The keyword “continue” gets out of the current iteration of a loop; it’s like “Stop checking this one”. That keyword is enough if you want to get out of the immediate loop. But, if your loop is inside another loop, and you want to get out of both at once, “continue” alone won’t do it. (Imagine you are checking every department within every university, and if you find any department headed by a robot then you can classify that university as one that has at least 1 robot-headed department, so you can proceed to the next university [not the next department].) For that, you need to label the outer loop and then specify it by appending the label to “continue”. I knew that convention well and presumed “everybody” did, but my teammate and coach were unaware of it. There are more cases of the opposite, but the fact that the knowledge gap is even slightly bilateral seems to promote an egalitarian style of shared work.
Returns the first element of an array. Passing n will return the first n elements of the array.
OK, so you give
_.first an array (which is a linear list of items), and optionally you may also give it something else. If you give it only the array, it gives you back the first element (item). If you also give it a number, it returns that many elements, starting from the beginning of the array, rather than only 1 element.
Clear? Not at all. A clear specification would need to say what the function does under various conditions, including:
- You give it nothing.
- You give it only 1 thing, but it isn’t an array.
- You give in an empty array, so it has no first element.
- You give it an array and something other than a number.
- You give it an array and a number, but the number is any of these:
- Larger than the count of elements in the array.
- Fractional (such as 4.75).
There’s more. If the array’s first element is a pointer to a complex item (such as another array or an “Object” (something that has properties and routines you can tell it to perform), should the function return a pointer to that same complex item, or to a brand new item identical to the original one? It will make a difference as soon as anything changes that complex item.
This week I mostly exercised discretion to interpret ambiguous specifications as I saw fit. My usual principle was that the function should not guess what its user wants. My teammate, by contrast, tested Underscore itself to determine how it actually behaves, and he wrote his functions to emulate that behavior.
So far it seems that the Guild’s more advanced Learners and its hired professionals are tolerant of stylistic and even definitional divergence between members of a team. They nudge us, but they don’t crack the whip. And they all recognize that not all of the nudging will be consistent. Dealing with ambiguity, and with ambiguity about how to deal with ambiguity, is one of those skills we learn and practice here.