http://qs321.pair.com?node_id=264682


in reply to (OT) The Schwartzian Transform in Java

With proper indenting it looks a lot better and doesn't need "end foreach"-like comments (if you ever feel you need comments that say what you're ending, fix your style instead!!).

Rule of thumb: always let the thing that causes the indentation be the last on a line. Another rule of thumb: align closing parens/brackets with the indentation of the line that caused indentation.
So don't use:

somefunction( foo(bar, "Hello World", ) // end of foo ); // end of somefunction
But instead use:
somefunction( foo( bar, "Hello World", ) );
You may or may not like it, but I find it much better readable.

import java.util.ArrayList; import java.util.Comparator; import java.util.List; import perlforjava.control.Looper; import perlforjava.functions.Arrays; import perlforjava.functions.Mapper; import perlforjava.lang.Block; public class TheSchwartz { public static void main(String[] args) { // Create a new List of values to sort ArrayList in = new ArrayList(); in.add("foobarbazquux"); in.add("foo"); in.add("foobarbaz"); in.add("foobar"); /* Sort based upon length of string by mapping each string to a List where the first element is the string and the second + is its length. Sort on the latter and return a new List of str +ings. */ List out = Mapper.map( new Block() { // pull the first element from each List and return it protected Object process(Object elem) { return ((List)elem).get(0); } }, Arrays.sort( // run the comparison of Integer values to determine o +rder new Comparator() { public int compare(Object a, Object b) { return ((Integer)((List)a).get(1)). compareTo(((Integer)((List)b).get(1))); } }, // map each string into an ArrayList of string => leng +th Mapper.map( new Block() { protected Object process(Object elem) { ArrayList temp = new ArrayList(); temp.add(elem); temp.add(new Integer(((String)elem).length +())); return temp; } }, in ) ) ); // Loop over the results to view them Looper.foreach( out, new Block() { protected Object process(Object elem) { System.out.println("ELEM " + elem.toString()); return null; } } ); } }

But indeed, Perl is much nicer towards programmers anyway.

Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Replies are listed 'Best First'.
Re: Re: (OT) The Schwartzian Transform in Java
by ignatz (Vicar) on Jun 10, 2003 at 22:53 UTC
    The problem isn't with the comments, it's with throwing everything into one big main() method. Why throw away code when with a little bit more work you can give it some real power?
    import java.util.ArrayList; import java.util.Comparator; import java.util.List; import perlforjava.control.Looper; import perlforjava.functions.Arrays; import perlforjava.functions.Mapper; import perlforjava.lang.Block; /** * The Schwartzian Transform written in Java. */ public class TheSchwartz { private ArrayList list; /** * Comparator to sort by length. */ public final static Comparator BY_LENGTH; /** * Comparator to sort alphabetically. */ public final static Comparator ALPHABETICALLY; /** * Static initializer */ static { BY_LENGTH = new Comparator() { public int compare(Object a, Object b) { return ((Integer) ((List) a).get(1)).compareTo( ((Integer) ((List) b).get(1))); } }; ALPHABETICALLY = new Comparator() { public int compare(Object a, Object b) { String s1 = a.toString().substring(1); String s2 = b.toString().substring(1); return s1.compareTo(s2); } }; } /** * Simple Constructor. * * @param list */ public TheSchwartz(ArrayList list) { this.list = list; } /** * Workhorse function. Sorting by passed in Comparator * * @return */ public ArrayList sort(Comparator sortBy) { List out = Mapper.map(new Block() { // pull the first element from each List and return it protected Object process(Object elem) { return ((List) elem).get(0); } }, Arrays.sort( // run the comparison of Integer values to determine o +rder sortBy, // map each string into an ArrayList of string => length Mapper.map(new Block() { protected Object process(Object elem) { ArrayList temp = new ArrayList(); temp.add(elem); temp.add(new Integer(((String) elem).length())); return temp; } }, list))); return (ArrayList)out; } public static void main(String[] args) { // Create a new List of values to sort ArrayList in = new ArrayList(); in.add("fu"); in.add("duhh"); in.add("birdy"); in.add("sea"); /* Sort based upon length of string by mapping each string to a List where the first element is the string and the second + is its length. Sort on the latter and return a new List of str +ings. */ TheSchwartz merlyn = new TheSchwartz(in); List outByLength = merlyn.sort(TheSchwartz.BY_LENGTH); System.out.println("By Length:"); // Loop over the results to view them Looper.foreach(outByLength, new Block() { protected Object process(Object elem) { System.out.println("ELEM " + elem.toString()); return null; } }); System.out.println("\nAlphabetically:"); List outAlphabetically = merlyn.sort(TheSchwartz.ALPHABETICALL +Y); // Loop over the results to view them Looper.foreach(outAlphabetically, new Block() { protected Object process(Object elem) { System.out.println("ELEM " + elem.toString()); return null; } }); } }
    Fun post.
    ()-()             
     \"/              
      `              
    

      Nice ignatz! I was merely shooting for a minimalist example in my OP, but this is a great demo of a more realistic application of the idea. I like the encapsulation of the core routine and the use of static Comparators to facilitate ease of use. And of course since public sort method can take any Comparator, using it in custom applications would be a breeze. The one part that concerns me is that the map that does the initial setup isn't always going to be the same (string => length), so there needs to be some way of conveying dynamic behavior for that aspect through the public sort method. Writing a general wrapper in Perl for the ST you'd probably pass a subroutine reference; in Java you'd probably have to pass an object or break the rules and pass a java.lang.reflect.Method. Hmmm, actually, that latter option probably would work:

      sort(Comparator c, Method prepare) .... .... // The second map would then look something like this map(new Block() { protected Object process(Object elem) { ArrayList temp = new ArrayList(); temp.add(elem); try { temp.add(prepare.invoke(elem, null)); // or possibly with ar +gs; } catch (Exception e) { // for real we'd catch finer grained exceptions and // do something smart } }, in);

      This does work, I just passed in the result of String.class.getMethod("length", null) and it ran as expected :^) Of course one limitation is the assumption that the transformation to be run on the element exists as an instance method. Probably this measure could be omitted for the first map as in basically all cases you just want to pull out the first element.


      "The dead do not recognize context" -- Kai, Lexx

      The problem isn't with the comments

      The readability problem wasn't the comments. I rearranged those too, but the real problem was having screwed up indenting (closing paren lined up with opening paren). The comments "end of foreach" and "end of sort" were just signs of bad style, not the bad style itself.

      As for your code: I hate /* */ comments :)

      Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: Re: (OT) The Schwartzian Transform in Java
by djantzen (Priest) on Jun 10, 2003 at 21:01 UTC

    Good points, the original indenting is the result of emacs' java-mode, which obviously is dictated by the syntactical structure of the code. I thought perhaps that it would help others see the implementation, but your version definitely reads better. Thanks juerd.


    "The dead do not recognize context" -- Kai, Lexx