
On Sun, Jun 29, 2008 at 6:41 PM, Andre Roberge <andre.roberge@gmail.com> wrote:
In Python, the humble colon (:) has multiples uses:
1. as a signal to indentation increase, signaling a block of code, such as [snip] However, the colon has also some other uses.
2. in slices [a:b:c]
I agree this isn't the clearest it could be.
3. in dict assignments {a:b}
This mirrors a number of existing languages, including English, and, more or less (depending on your priorities) important, JSON. It's always been comforting that valid Python structures (in fact, simply printed) are instantly valid JSON (for the most part...with ints and strings and such).
4. in lambda assignments (lambda x: x+1)
This (correctly) mirrors a standard function definition. the only way it could be closer is with something like lambda(x): x+1, but then this is not what's up for debate.
I would argue that, in these last three examples, there might be better choices. (some of these choices have been inspired by reading http://www.resolversystems.com/documentation/index.php/Differences_Between_R...)
Are you suggesting this because you work with both languages? This e-mail seems a bit self-serving, because of the inclusion of someone's in-house language spec.
Slices: ---------
I would argue that, the usual slicing notation would be more readable if it were as follows:
[a -> b; c]
Thus [1:10:2] would become [1 -> 10; 2] [1:10] would become [1 -> 10]
The "shorter" combinations would not gain in terms of readability; they would be as follows:
[ :10 : 2] would become [10; 2] [ :10] would become [10;] [:: -1] would become [; -1] [:] would become [;]
If such a change were to be made, an second slicing notation, *with a different meaning*, could be introduced:
[a => b; c]
This would be an inclusive range, i.e.
[a => b] is equivalent to [a -> b+1]
I am always very wary of multiple-character symbols. They are harder to type, harder to read, harder to parse (in a compiler or an editor), and open the language up to an unbounded number of (dare I say it?) Perlisms. That said, I'm not sure 'arrows' are even the right approach for slices. Slices should be thought of as ranges, which usually lend themselves to ellipses. I remember (loosely, from a long time ago) Ruby having '..' and '...' as exclusive and inclusive ranges, and I really liked that. With regard to the third item in a slice, the increment value, I almost never use it, because it seems to make code a lot harder to read clearly. If I feel the need to use it, it's usually a good indicator that I need to restructure my code, and if it's absolutely necessary, I'll typically just iterate over the list with a for loop so that I can understand what I was doing when I come back. If my half-suggestion of ellipses were taken up, I'd say that the colon could stay as the separator between the second and third arguments (and, as someone said already, the semi-colon introduces some weird parsing problems and possible ambiguities).
dict assignments ------------------------
Here again, I would argue that using "->" instead of ":" would make the code more readable - at least for beginners.
numbers = {'one' -> 1, 'two' -> 2} instead of numbers = {'one': 1, 'two': 2}
Like I said before, the colon is a widely-accepted way to separate keys and values in a dict. The only strange case I can see with this is something like: functions = {'plus': lambda x, y: x+y, 'minus': lambda x, y: x-y} In fact, I'm not sure if this _is_ legal python, so before running it, I'd just parenthesize out the lambda expressions to be sure anyway, and this clears everything up nicely: functions = {'plus': (lambda x, y: x+y), 'minus': (lambda x, y: x-y)}
lambda assignments ---------------------------
Once again, same choice.
lambda x -> x+1 is, I think, more readable than lambda x: x+1
(but perhaps the last two [dicts and lambda] largely depends on the font choice...)
As a pseudo-mathematician (and a recent student of Erlang), this is quite appealing, for a few reasons. First, let me say that the obvious "f(x) -> x**2 shows up all over math" is not the correct reason to say this is correct notation for functions. Python functions are procedures, not expressions (as they are in Erlang and Haskell, where the arrow-notation is commonplace). As such, a colon separating the function's name from its definition makes perfect sense, as this is the way we write English all the time, and I've seen more than one professor write pseudocode just like this. However, lambda functions _are_ single-expressions, not blocks. This leads me to believe that the arrow could be a good delimiter (except for my above statement that multiple-character symbols suck). Unfortunately for the arrow, it seems that priority in Python syntax is given to consistency within itself, rather than consistency with the outside world, so the fact that "lambda x: x**2" is consistent with "def sq(x): x**2" probably pulls more weight. Let me just say that putting something like the arrow (especially if we ever allow non-ASCII characters into the syntax) in lambda expressions would not be totally distasteful to me.
====== Other considerations:
If "->" were to be adopted for dict or lambda assignments, then the "naturalness" of their choice for slices would be reduced. An alternative might be inspired from the mathematical notation
[a, ..., b; c]
I realize that this is "much" longer than [a: b: c].
Final comment:
I have seen other alternatives for simple slices suggested in the past such as [a..b] and [a...b] which would be the equivalent of [a->b] and [a=>b]; however, the extra "." might sometimes be difficult to read, whereas the difference between "->" and "=>" is much easier to see.
You're right. This is one of the reasons I hate Ruby. Yet another reason to ignore your suggestion for slices :-). -- Cheers, Leif