necromanco wrote:Hello Chuck,
I think that, as it is now, Cobra is easier to learn than Python or Ruby(except for
very initial only procedural code lessons).
I don't know how much importance you give about Cobra being friendly to newbies.
A lot of importance. There are many places where the Cobra compiler checks to see if you did something from Python or C# that isn't compatible with Cobra and then gives you a specific error message to help you out.
I also recently added the suggestions to help get the case of the method right.
But I also find it impossible to make a truly perfect syntax. I can only get really close.
necromanco wrote:Anyway, I will share some thoughts, based on my personal experience, about things
that make the language harder for a newbie:
1) Zero based indexing. I know this is the pattern in the info world and that Cobra uses .NET base class library. So this will not change. I wrote it here just to help item 2.
2) The Python style for slicing: excluding the last index element:
- Code: Select all
'012'[0:2] # makes '01'
It is not a pattern in the info world. Even .NET includes the last element - although its slicing uses count from first element index instead of last element index:
- Code: Select all
someList.GetRange(index, count)
This may be tricky even for a skilled programmer from Ruby, for example.
And for a newbie, dealing with item 1 already filled his share of sacrifice.
[/cobra]
In "someList.GetRange(0, 5)" what indexed elements of someList are returned? The answer is someList[0], someList[1], someList[2], someList[3] and someList[4]. You can get this same effect with slicing as in someList[0:5]. Slicing semantics are actually compatible with List<of>.getRange(i,c) and String.substring(i,c). If slices were inclusive then someList[0:5] would return one more element than someList.getRange(0, 5).
I know slices and right-exclusion can take some getting used to, but it actually works out really well. Newbies will have to endure some learning curve on this one.
necromanco wrote:3) The way to call a constructor without arguments:
- Code: Select all
SomeClass()
Cobra sends warning message each time it sees a function call with parentheses but no arguments. I think it is fine - helps to keep the code visually clean. But, when comes the time to call a constructor with no arguments, Cobra
behaves at the opposite, demanding an empty pair of parenthesis(no much coherency). I spent some minutes yesterday because of a missing '()' after a constructor call. I think that
- Code: Select all
SomeClass.new
is less error prone(and, in this case, 'new' instead of 'init' would be welcome).[/cobra]
I played around with this idea before, but the problem I ran into is that "SomeClass.new" implies that there is a "def new is shared" in SomeClass. That doesn't line up with the constructor approach used in C#, VB, Java or Python. Most importantly, it wouldn't line up with C# and VB, whose virtual machine, Cobra lives on.
I agree it's a bit of a clash with avoiding empty parens on dotted access. Note that you also need empty parens for a variable that points to a method (aka, a delegate). So the rule is: Use parens to call on identifiers whether types or variable. Do not use empty parens on dotted members.
I haven't found a better alternative so far.
necromanco wrote:4) Shared X Non Shared. Although I have sympathy for the syntax 'is shared', for a newbie that is writing code, it is important that all the shared stuff of a class be toghether inside the only one shared sector, so keyword 'shared' is used no more than once per class. There is a post in this forum where skilled people stumbled a bit because of spreaded 'shared' declarations.
Yeah, I tend to code this way whenever I have more than one "shared" member. At the very least we can emphasize this approach more in the docs.
I'd also like to kill the requirement that "is shared" be attached to "def main". The compiler should be "smart enough" to make an instance and invoke "main" provided the class doesn't require initialization parameters.
necromanco wrote:5) Liberal naming(this is scary):
- Code: Select all
class NightmareOfANewbie
shared
def main
.pass
def pass
print "'Hail, newbie!' from method 'pass' :P"
The ability to name class members after keywords is motivated by action words like "print" and "throw". It's scariness should be highly mitigated by the fact that dotted access is required. Also, you cannot use keywords for argument or variable names. This is staying.
necromanco wrote:Cobra ROX on many topics, so I feel it could be a pity to keep these small gotchas for newbies.
Thanks. I do appreciate the feedback and hope I don't come across as too stuck in my ways when I don't make most recommended changes. I've thought about most of these issues before and some of them are complex as they intersect with other issues like .NET.
Of course, there have been improvements based on feedback including allowing spaces for indentation (early Cobra versions only recognized tabs), the line continuation character (_) and the ability to declare public vars.
Here are some more things that will be changing based on feedback:
- get count from var as int
- if x < y, print x
- for x in j
- for x in i : j
- for x in i : j : step
The first two are additions to the syntax.
The last three are really the same thing: The numeric for loop will use "in" and a colon-separated specification that matches slicing. The current numeric for loop already matches slicing, but has a funky syntax that doesn't tie in with anything else in the language. However, it will be supported for a long period of time (say a year?) to avoid breaking people's code.
-Chuck