Last year, in July 2011, I wrote a post about How many keywords do you type in your code?.
"Have you ever wondered how many keywords (reserved words) do you type in your programs? Can you type more or type less without changing what your program does? Can you change programming language and save some typing? And if so, to which language?".
Back then, I tried to answer those questions by showing some comparative graphics with the number of keywords needed to build 2 versions (minimal and verbose) of the same little program in 20 different programming languages (C#, VB.NET, C++/CLI, F#, Boo, Phalanger, IronPython, IronRuby, Delphi Prism, Zonnon, Nemerle, Cobra, JScript.NET, Java, JavaFX, Groovy, Jython, JRuby, Fantom, Scala).
The program I chose was an OO version of the famous Hello World (Archive posts June-July 2010) and had the following structure:
// OO Hello World // Import,using,etc. // Class // Field // Constructor // Method // Program // Instantiate Class // Call Method = OUTPUT (Hello, World!)
Finally, I added some comments and thoughts about the results, but... What if we do the same with a bigger example? Will the results be more or less the same if I a more elaborated program is used to do the comparison? Do the most verbose language and the most minimalistic of the previous post will still hold the title?
That's exactly what this new post is all about! :) a new comparison on a more elaborated, still small, program using many more language constructs following the sample rules of the previous comparison:
- 2 Versions Minimal and Verbose.
- 21 Programming Languages (the previous 20 + Gosu).
- Primitive Types such as int, float, double, string not considered as keywords.
- Same OO program and structure (taken from series Language's Basics by Example).
- OO Hello World was small enough to count by hand, but this time I created a little script written in Python 3 that does the automatic counting for me :) (source code to be provided in my next post).
// Language Basics // Greet Class // Fields or Attributes // Properties // Constructor // Overloaded Constructor // Method 1 // "if-then-else" statement // Method 2 // "for" statement // Overloaded Method 2.1 // "while" statement // Overloaded Method 2.2 // use Date Class // "switch/case" statement // Console Program // Define object of type Greet // Instantiate Greet. Call Constructor // Call Set Properties // Call Method 2 // Call Method 2.1 and Get Properties // Call Method 2.2 // Stop and exit - Read Input From Console
Here below th graphs! Click on the images to enlarge.
Total Keywords by Language
|
Version 1 (Minimal)
|
Version 2 (Verbose)
|
Both (Minimal and Verbose)
|
Compare Basics and HelloWorld (Minimal and Verbose)
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CONCLUSIONS
As with the previous post, we can still notice the 3 main groups of languages:
1. Scripting/Dynamic Languages (Python, Ruby, Groovy, etc.) fewer keywords
2. Functional Languages (F#, Scala, Nemerle, etc.) more or less than the previous group
3. Imperative/Static Languages (C#, C++, VB.NET, Java, etc.) more keywords
We can also see that the scripting/dynamic languages are the ones that define the fewer keywords and that's probably the reason why there are few or no difference in the number of keywords typed between the 2 versions of the same program (see latest graph above).
The difference between the number of keywords of the most verbose and the most minimalistic program is of:
Basics Minimal: VB.NET 130 vs Nemerle 33 (97 keys of difference)
Basics Verbose: VB.NET 169 vs Scala 41 (128 keys of difference)
Big differences... and they could be much bigger if we include primitive types as keywords (because they are keywords, but were excluded for this comparison)
When comparing a small program such as the OO Hello World in which didn't use many language constructs we still saw a big difference between the most verbose and the most minimalistic languages. That is still true when many more statements and constructs are added to the code as in the case of: Delphi Prism and VB.NET, however, this time we can clearly see that the most verbose language is not Delphi Prism but VB.NET!!!
So, VB.NET congratulations! You are the most extra-typing language among the .NET and Java languages. I guess that's why Visual Studio 2010 auto-completes all the closing blocks keywords :D so you don't need to type that many... I'm wondering what about those programmers that love to code in raw text using notepad(++?)... I guess those brave of hearth do not program using VB. Am I right?
Nevertheless, I'm very curious about running the keywords counting on a Real Life program (hundreds-thousands lines of code) and see what the result is.
And now, about the most minimalistic language? Well, this time was Nemerle, followed by Scala and F#. The 3 languages are multi-paradigm languages, but are mainly inspired by the Functional ones, so we can probably assume that functional languages use less keywords, less typing even if using their OO syntax features; that's probably why there are lots of blog posts about the difference in amount of code between Scala and Java; of course they always compare Java's Imperative syntax vs Scala's Functional syntax, which is fare enough because Scala is meant to be used as a functional language. Right? So, in summary, using OO or Functional syntax, you will usually have smaller programs. Of course, that depends how you write code and if you use, let's say, match-case instead of if-then-else.
So what happened to the Scripting languages? weren't they the ones with smaller keywords sets? and I'm not talking about Groovy because remember that Groovy needs to be Java syntax compatible, but Python and Ruby?
Let's have a look:
Ruby 48
module 1 class 1 def 11 # this is understandable end 17 # and here is where the most keyword go! if 1 return 2 else 2 for 1 in 1 while 1 do 1 case 1 # using the case construct also requires lots of keys because when 4 # it uses when and then for each case you want to validate against then 4 #
IronPython 50
import 2 from 1 class 1 def 12 # this is understandable return 5 if 2 else 2 for 1 in 1 print 4 # print is a keyword but other languages use # Console.WriteLine | System.out.println while 1 or 16 # and here is where the most keyword go because # python has no switch | case | match syntax elif 2
What else... oh yes. Verbosity of the language has nothing to do with its elegance or expressiveness (for instance Delphi Prism vs Scala|F#).
Finally, counting keywords in your code is probably not relevant, because it will vary a lot between programs, styles, paradigms, if code was automatically generated, manually typed, and so on.
In my case I used the 2 edges to compare the "Minimal" and "Verbose", but in real coding a combination based on the above might be used.
That's pretty much it.
Here below I added the counting results for all the 21 languages in case you wonder which keywords
Basics Minimal | Basics Verbose |
Boo 68 | Boo 114 |
import 1 class 1 as 17 get 3 return 5 set 3 def 6 constructor 2 self 4 private 1 if 2 else 2 for 1 in 1 while 1 or 16 elif 2 | namespace 1 import 1 private 5 class 1 as 24 public 9 get 3 return 5 self 28 set 3 def 7 constructor 2 if 2 else 2 for 1 in 1 while 1 or 16 elif 2 |
Basics Minimal | Basics Verbose |
Cobra 79 | Cobra 109 |
class 2 var 3 pro 3 as 12 get 3 return 5 set 3 cue 2 base 2 def 5 is 1 private 1 if 1 else 2 for 1 in 1 print 4 while 1 branch 1 on 4 or 20 any 1 to 1 | use 1 namespace 1 class 2 is 12 public 10 var 3 as 18 pro 3 get 3 return 5 set 3 cue 2 base 2 def 5 private 1 if 1 else 2 for 1 in 1 print 4 while 1 branch 1 on 4 or 20 shared 1 any 1 to 1 |
Basics Minimal | Basics Verbose |
C++/CLI 59 | C++/CLI 101 |
using 1 namespace 1 class 1 public 2 property 3 return 5 void 6 this 3 private 1 if 1 else 1 for 1 while 1 switch 1 case 24 break 5 default 1 gcnew 1 | using 1 namespace 2 private 5 class 1 public 14 property 3 return 6 this 27 void 6 if 1 else 1 for 1 while 1 switch 1 case 24 break 5 default 1 gcnew 1 |
Basics Minimal | Basics Verbose |
C# 69 | C# 103 |
using 1 class 2 public 8 get 3 return 5 set 3 value 3 this 3 if 1 else 1 void 4 for 1 while 1 switch 1 case 24 break 5 default 1 static 1 new 1 | using 1 namespace 1 internal 2 class 2 private 4 public 9 get 3 return 5 this 29 set 3 value 3 if 1 else 1 void 4 for 1 while 1 switch 1 case 24 break 5 default 1 static 1 new 1 |
Basics Minimal | Basics Verbose |
DelphiPrism 94 | DelphiPrism 134 |
namespace 1 interface 1 uses 1 type 2 class 4 private 1 method 14 public 2 property 3 read 3 write 3 constructor 4 end 17 array 2 of 3 implementation 1 begin 13 if 1 then 1 result 2 else 2 for 1 to 2 step 1 do 2 var 3 while 1 case 1 new 1 exit 1 | namespace 1 interface 1 uses 1 type 2 public 11 class 4 private 6 var 6 method 14 property 3 read 3 write 3 constructor 4 end 17 array 2 of 3 implementation 1 begin 13 self 23 if 1 then 1 result 2 else 2 for 1 to 2 step 1 do 2 while 1 case 1 new 1 exit 1 |
Basics Minimal | Basics Verbose |
Fantom 46 | Fantom 80 |
class 2 private 4 return 5 it 3 new 1 if 1 else 1 for 1 while 1 switch 1 case 24 default 1 static 1 | internal 1 class 2 private 4 public 9 return 5 this 24 it 3 new 1 if 1 else 1 for 1 while 1 switch 1 case 24 default 1 static 1 |
Basics Minimal | Basics Verbose |
F# 42 | F# 54 |
open 1 type 1 let 9 mutable 4 member 7 with 4 and 3 new 2 private 1 if 1 then 1 else 1 for 1 to 2 do 2 while 1 match 1 | namespace 1 open 1 type 1 public 8 class 1 let 9 mutable 4 member 7 with 4 and 3 new 2 private 1 if 1 then 1 else 1 for 1 to 2 do 2 while 1 match 1 end 1 module 1 |
Basics Minimal | Basics Verbose |
Gosu 72 | Gosu 114 |
uses 4 class 1 var 8 property 6 get 4 return 5 set 3 private 1 function 4 else 1 for 1 while 1 new 3 switch 1 case 24 break 4 default 1 | uses 4 public 12 class 1 private 4 var 8 property 6 get 4 return 5 this 27 set 3 function 4 else 1 for 1 while 1 new 3 switch 1 case 24 break 4 default 1 |
Basics Minimal | Basics Verbose |
Groovy 72 | Groovy 101 |
class 1 private 4 def 20 return 5 this 3 if 1 else 1 for 1 in 2 while 1 new 3 switch 1 case 24 break 4 default 1 | package 1 public 12 class 1 private 4 return 5 this 29 void 6 def 3 if 1 else 1 for 1 in 2 while 1 new 3 switch 1 case 24 break 5 default 1 |
Basics Minimal | Basics Verbose |
IronPython 48 | IronPython 50 |
from 1 import 1 class 1 def 11 return 5 if 2 else 2 for 1 in 1 print 4 while 1 or 16 elif 2 | import 2 from 1 class 1 def 12 return 5 if 2 else 2 for 1 in 1 print 4 while 1 or 16 elif 2 |
Basics Minimal | Basics Verbose |
IronRuby 46 | IronRuby 48 |
class 1 def 11 end 16 if 1 return 2 else 2 for 1 in 1 while 1 do 1 case 1 when 4 then 4 | module 1 class 1 def 11 end 17 if 1 return 2 else 2 for 1 in 1 while 1 do 1 case 1 when 4 then 4 |
Basics Minimal | Basics Verbose |
Java 65 | Java 103 |
package 2 import 2 class 2 private 4 return 5 void 7 this 3 if 1 else 1 for 1 while 1 switch 1 case 24 break 5 default 1 public 2 static 1 new 2 | package 2 import 2 public 14 class 2 private 4 return 5 this 29 void 7 if 1 else 1 for 1 while 1 switch 1 case 24 break 5 default 1 static 1 new 2 |
Basics Minimal | Basics Verbose |
JavaFX 64 | JavaFX 105 |
import 4 class 1 var 6 function 11 return 5 init 1 if 5 else 5 for 1 in 2 while 1 def 1 new 1 or 20 | package 1 import 4 public 11 class 1 var 6 function 11 return 5 this 29 init 1 if 5 else 5 for 1 in 2 while 1 def 1 new 1 or 20 |
Basics Minimal | Basics Verbose |
JRuby 46 | JRuby 48 |
class 1 def 11 end 16 if 1 return 2 else 2 for 1 in 1 while 1 do 1 case 1 when 4 then 4 | module 1 class 1 def 11 end 17 if 1 return 2 else 2 for 1 in 1 while 1 do 1 case 1 when 4 then 4 |
Basics Minimal | Basics Verbose |
JScript.NET 72 | JScript.NET 118 |
import 1 class 1 var 7 function 12 get 3 return 5 set 3 this 3 private 1 if 1 else 1 for 1 while 1 switch 1 case 24 break 5 default 1 new 1 | import 1 package 1 public 12 class 1 private 4 var 7 function 13 get 3 return 5 this 29 set 3 if 1 else 1 void 3 for 1 while 1 switch 1 case 24 break 5 default 1 new 1 |
Basics Minimal | Basics Verbose |
Jython 51 | Jython 53 |
from 2 import 2 class 1 def 11 return 5 if 2 else 2 for 1 in 2 print 4 while 1 or 16 elif 2 | import 3 from 2 class 1 def 12 return 5 if 2 else 2 for 1 in 2 print 4 while 1 or 16 elif 2 |
Basics Minimal | Basics Verbose |
Nemerle 33 | Nemerle 67 |
using 1 class 1 mutable 5 public 8 this 5 private 1 if 1 else 1 void 3 for 1 while 1 def 2 match 1 _ 2 | using 1 namespace 1 internal 1 class 1 private 4 mutable 6 public 10 this 29 if 1 else 1 void 4 for 1 while 1 def 1 match 1 _ 2 module 1 static 1 |
Basics Minimal | Basics Verbose |
Phalanger 89 | Phalanger 103 |
namespace 1 class 2 private 4 function 12 return 5 this 24 if 1 else 1 for 1 echo 4 while 1 switch 1 case 24 break 4 default 1 static 1 new 1 exit 1 | namespace 2 class 2 private 4 public 11 function 12 return 6 this 24 if 1 else 1 for 1 echo 4 while 1 switch 1 case 24 break 5 default 1 static 1 new 1 exit 1 |
Basics Minimal | Basics Verbose |
Scala 37 | Scala 41 |
import 1 class 1 private 4 var 4 def 12 this 2 if 1 else 1 for 1 while 1 val 2 match 1 case 5 new 1 | package 1 import 2 class 1 private 4 var 4 def 13 this 2 if 1 else 1 for 1 while 1 val 2 match 1 case 5 object 1 new 1 |
Basics Minimal | Basics Verbose |
VB.NET 130 | VB.NET 169 |
Imports 1 Friend 2 Class 2 Private 4 As 22 Property 6 Get 6 Return 5 End 21 Set 6 ByVal 11 Sub 12 New 3 Function 2 If 2 Then 1 Else 2 For 1 To 5 Next 1 Dim 3 While 2 Select 2 Case 6 Module 2 | Imports 1 Namespace 2 Friend 2 Class 2 Private 4 As 22 Public 9 Property 6 Get 6 Return 5 Me 27 End 22 Set 6 ByVal 11 Sub 12 New 3 Function 2 If 2 Then 1 Else 2 For 1 To 5 Next 1 Dim 3 While 2 Select 2 Case 6 Module 2 |
Basics Minimal | Basics Verbose |
Zonnon 66 | Zonnon 90 |
module 1 import 1 type 1 object 1 var 5 procedure 10 begin 12 return 5 end 16 if 1 then 1 else 2 for 1 to 2 do 2 while 1 case 1 of 1 new 1 exit 1 | module 1 import 1 type 1 object 1 var 5 procedure 10 begin 12 return 5 self 24 end 16 if 1 then 1 else 2 for 1 to 2 do 2 while 1 case 1 of 1 new 1 exit 1 |
Do you mind if I use some of your graphs, with attribution to this blog entry, for a poster at the SIGCSE conference on using Scala in early CS courses?
ReplyDeleteHi Mark,
ReplyDeleteFeel free to do it. You can use any info you find useful from this blog. A link to it would be appreciated :)
Carlos
In Ruby, you can use newlines instead of `then` inside a `case` block.
ReplyDeleteThis would reduce the keyword count and arguably make it more readable too.
Thanks for your feedback. I will have a look and update the code/graphs if needed.
DeleteThis is a greeat post
ReplyDelete