From: schneik@... Date: 2000-05-12T14:43:51-05:00 Subject: [ruby-talk:02799] Re: Array.pop and documentation [was:Append alias for Array.append?] Hi, Albert Wagner writes: # I hope it's OK for a newbie to comment here. Why complicate things with # three signatures? Why not just: # slice(n,m) # where n=pos & m=length # so that: # slice(0,1) # slice_low 1st # slice(0,3) # slice_low(3) 1st 3 # slice(-1,1) # slice_high last # slice(-3,3) # slice_high(3) last 3 One reason is that we were trying to come up with a uniform set of functions, not a single function. A more important reason is that we were looking at this from what could be called the "human user's natural associative pattern memory context", not the Ruby parser's perspective. This is tricky to discuss because it involves variations in past programming experience, variations in the sorts of things that people prefer to remember, and so on. One general (but hard to quantify) idea here is that there is a trade off between symbol coding density and easily accessible meaningfulness. In Aristotelian terms, you would like find some reasonably virtuous mean between the undesirable extremes of too terse and too verbose--e.g. as exemplified by APL and COBOL, respectively. In other words, you would like a reasonably mnemonic system. Another general (but also hard to quantify) idea is that you would like to make similar things look similar and important distinctions look different (with respect to how you naturally think about them) in a harmonious and "intuitively obvious" sort of way without having to think about it (leaving your attention free to be more fully concentrated on other things). In this context, the very clever, very useful, but nevertheless still kludgy and unnatural system of negative first indices for slice are a big problem. First of all, you normally think of negative numbers in the sense of "before" positive numbers, but here there is a strange sort of nonlinear wrap in the meaning of numbers regarded as indices. The meaning has also changed from naming an index to denoting an offset from the highest index, and moreover does so in a way that for most people almost always seems at first (and often thereafter) non-symmetric: slice(-1,1) # slice_end slice(-3,3) # slice_end(3) The key mental focus on operating on the "_end" of the object in these cases is differently denoted by slice(n,m) in a context-dependent way by -1 and -3, unlike the corresponding cases for slice_start, where both uses of slice use the same context-independent 0 as the first parameter: slice(0,1) # slice_start slice(0,3) # slice_start(3) With slice_start and slice_end, your intent is somewhat more obvious and clear cut than in the case of slice(0,1) and slice (-1,1), and moreover, this better matches the way you naturally talk about such things. With slice (n,m), you always have to do some more extra thinking--it's not as "perceptually obvious/natural/intuitive", and you have one parameter that is zero-origin and another parameter that is one-origin. Using the 2-parameter slice for everything seems (to me) somewhat like reverting a little bit too much back to the style of FORTRAN programming. The virtue and vice of {push, pop, unshift, shift} is that they pretty directly reflect the major distinctions that we normally make in thinking and talking about such operations on one hand (albeit in an unfortunately past-language/experience-dependent sort of way with respect to this particular choice of names), but they don't indicate their common functional ground on the other. In some sense you might regard all this as a free form "textual GUI" human interface issue. Anyway, these are the sorts of considerations that led to the proposal of slice_* as a useful and systematic tradeoff/alternative to the present scheme of things. Conrad Schneiker (This note is unofficial and subject to improvement without notice.)