The abstract part of the code takes some initial list, say of strings. It parses this list, then based on the parsing rules, it puts different parts of the list into two similar datatypes.
The actual, working code is for these two datatypes and the main loop (which contains the abstract code) to populate these.
As an extremely rough estimate of verbosity, you can see that both the number of lines and the number of characters is far smaller for the python code.
Getting more specific, there are 2 reasons that python's type system allows just less code: there is no need to declare variables and type them, and there is no need to cast variables. Casting is required heavily in the java example as you need to use more general datatypes (eg an array of the super type Object, or an ArrayList) to hold more specific ones. Creating custom superclasses to defeat this purpose leads to less readable code; nonetheless, this technique is used once in the java sample.
So with this approach in java, the 2 datatypes: countable_d and excrement, with their common method "add", are required to have the exact same number and type of arguments for this method, whereas each "add" method in the python code version is infinitely flexible. To make the java version as flexible would require use of more general holders which leads to more type casting...
The java was written below to minimize the amount of code used. As you see, practically every trick in the book had to be used in this attempt, which leads to less readable and harder to understand code.
The maintainability benefits of python for rapid prototyping should be clear from this example. This *MAY* not imply that python helps you code better when the project gets very large.
A simple counterargument to the code below is that python is getting away with one character symbols for lists and dictionaries whereas java is using normal class names. A more even comparions might be in order in the future of this article.
""" This is basically a dictionary that expects to receive multiple keys with different values attached to them. It maintains counts for each of these and stores the attached values """ class countable_d: def __init__(self): self.h = {} def add(self,SOME_KEY, txt): if not SOME_KEY in self.h: self.h[SOME_KEY] = { 0:0, 1:[txt] } else: self.h[SOME_KEY][0] +=1 self.h[SOME_KEY][1].append(txt)
#has the same method names as the above class, #but different internal functionality class excrement: def __init__(self): self.counter = 0 self.txtHolder = [] def add(self,inp,txt): self.counter +=inp self.txtHolder.append(txt)
holder = { 0:countable_d() , 1:excrement() } somelist = [ SOME LIST TO BE PARSED by SOME_RULE ] #this isn't executable for i in somelist: if SOME_RULE: #neither is this. eg it's an abstraction holder[0].add(SOME_KEY,i) #remember holder[0] is a countable_d else: holder[1].add(SOME_KEY,i) #and this is adding to an excrement.
/*the following superclass avoids some extra casting in the main loop *as we can create and array of only_in_java's instead of using a *more general holder like an ArrayList */
abstract class only_in_java { abstract void add(Object,String); }
class countable_d extends only_in_java { private HashMap dict; public countable_d() { dict = new HashMap(); } public void add(Object SOME_KEY,String txt) { if ( !dict.containsKey(SOME_KEY) ) { ArrayList AL = new ArrayList(); a.add(txt); dict.put(SOME_KEY,new Object[]{new Integer(0),AL}); } else { Object[] h = (Object[])dict.get(SOME_KEY); h[0] = new Integer( ((Integer)h[0]).intValue() + 1); ((ArrayList)h[1]).add(txt); } } }
class excrement extends only_in_java { private int counter; private ArrayList txtHolder; public excrement() { counter=0; txtHolder = new ArrayList(); } public void add(Object SOME_KEY, String txt) { counter += 1; //this is more limited than the python part for this txtHolder.add(txt); } }
public class letsRunThis { public static void main(String args[]) { only_in_java[] holder = {new countable_d(), new excrement()}; String[] list = { SOME LIST TO BE PARSED by SOME_RULE }
for(i=0;i<list.length;i++){ if SOME_RULE: #remember this is just an abstraction holder[0].add(SOME_KEY,list[i]) //no need to remember much here else: holder[1].add(SOME_KEY,list[i]) //since the compiler will help you out } }
With a little work, you can get this code running if you wanted to. But you are going to have to do plenty more type conversions when expanding the parsing part in java. The list to be parsed can also be far more general in python without much more work.
Search Encyclopedia
|