
-----------------------------------
Martin
Sun Mar 06, 2005 8:49 pm

Design Patterns
-----------------------------------
An interesting read on writing better code.

 Design patterns are recurring solutions to software design problems you find again and again in real-world application development. Design patterns are about design and interaction of objects, as well as providing a communication platform concerning elegant, reusable solutions to commonly encountered programming challenges.

http://www.dofactory.com/Patterns/Patterns.aspx

The sample code is in C#. It should be fairly easy to read and translate over to other languages though.

-----------------------------------
wtd
Sun Mar 06, 2005 10:53 pm


-----------------------------------
Honestly, I looked at these, and most of them are only really useful if you're using a completely brain-dead language like C# or Java. Sometimes you can't avoid that, but I just want to put this into perspective.

-----------------------------------
rizzix
Sun Mar 06, 2005 11:23 pm


-----------------------------------
wtd: whats with the unnecessary adjectives?  :lol:

so anyways the stuff listed up there are really just conventions. the most important of the lot include: Factories, Iterators, Observers and Delegation  (dunno but did they include that there? *shurgs*). The rest are unnecessary stuff  IMHO.

-----------------------------------
wtd
Mon Mar 07, 2005 4:33 am


-----------------------------------
wtd: whats with the unnecessary adjectives?  :lol:

If you're counting "completely brain-dead" as unnecessary adjectives, then in the case of the languages named (and a good many others), they're quite necessary.  Aside from their large libraries, and the backing of large corporations which have used their influence to quash alternatives (or at least relegate alternatives to academic curiosities), such languages have no redeeming qualities.

Now, that said, that corporate support sometimes makes them useful.  However, useful does not by any means necessarily mean good, and any computer scientist should know the difference.

-----------------------------------
Martin
Mon Mar 07, 2005 8:54 am


-----------------------------------
One of the uses of design patters is that (apparently) they help to write platform independant code.

I have a course on them in my 2A semester (Jan - Apr 2006).

-----------------------------------
rizzix
Mon Mar 07, 2005 3:06 pm


-----------------------------------
wtd: whats with the unnecessary adjectives?  :lol:

If you're counting "completely brain-dead" as unnecessary adjectives, then in the case of the languages named (and a good many others), they're quite necessary.  Aside from their large libraries, and the backing of large corporations which have used their influence to quash alternatives (or at least relegate alternatives to academic curiosities), such languages have no redeeming qualities. welll. thats your opinion...

-----------------------------------
wtd
Mon Mar 07, 2005 3:27 pm


-----------------------------------
Name a single good thing either language contains which is not merely intended to compensate for some other basic deficiency.

-----------------------------------
Martin
Mon Mar 07, 2005 4:04 pm


-----------------------------------
C# is backed by the most profitable company ever.

Wait a second...

-----------------------------------
Tony
Mon Mar 07, 2005 4:24 pm


-----------------------------------
University of Waterloo was paid $12mil to start teaching C#.

Wait a second...

-----------------------------------
wtd
Mon Mar 07, 2005 5:35 pm


-----------------------------------
Heh.  I already mentioned backing by large corporations.  :)

And if we're going to count that, Java's on a pretty solid footing.  IBM, Sun, HP, etc. all throwing their weight behind it.

-----------------------------------
Hikaru79
Mon Mar 07, 2005 8:28 pm


-----------------------------------
If we're going to go with that method of argument, name some things that these languages LACK that others don't ;)

-----------------------------------
wtd
Mon Mar 07, 2005 9:17 pm


-----------------------------------
Decent support for generics.  Not only based on type.  Consider templates in C++ or generics in Ada.  A simple example: a lottery ticket.

template 
class LotteryTicket
{
   private:
      int numbers[N];
   public:
      LotteryTicket();
      int operator[](size_t index) const;
      bool operator==(const LotteryTicket& other_ticket) const;
      int matching_numbers(const LotteryTicket& other_ticket) const;
};

generic
   N : Positive;
package Lottery_Ticket is
   subtype Index_Type is Positive range 1..N;
   type Ticket is limited private;
   
   procedure Make(T : out Ticket); 
   function "()" (T : in Ticket; Index : in Index_Type) return Integer;
   function "=" (T1, T2 : in Ticket) return Boolean;
   function Matching_Numbers(T1, T2 : in Ticket) return Natural;
private
   type Ticket is array (1..N) of Integer;
end Lottery_Ticket;
The ability to deal with functions as first class entities.  Let's say I have a Name class with first and last name properties.

using System;

class Name
{
   private string first, last;

   public this(string f, string l)
   {
      first = f;
      last = l;
   }

   public string First
   {
      get { return first; }
   }

   public string Last
   {
      get { return last; }
   }
}

Now, how do I sort based on last name?  Why shouldn't it be as simple as:

class Name
   attr_reader :first, :last

   def initialize(first, last)
      @first, @last = first, last
   end
end

names = [Name.new("Bob", "Smith"), Name.new("John", "Doe")]
sorted_names = names.sort { |a, b| a.last  b.last }

Or:

data Name = Name {first::String, last::String}

names = [Name "Bob" "Smith", Name "John" "Doe"]
sortedNames = sortBy (\a b -> last a `compare` last b) names
Why should it be difficult to construct lists?  Neither Java nor C# offer sane syntax for expediting the creation of many useful data structures (lists, vectors, hashtables).
No standalone functions.  Heck, Java and C# even acknowledge the need for such by including static members and member functions.  Yet, somehow these got left out.
Multiple inheritance.  MI can greatly reduce the need for standalone functions and data, but it's missing too.  Consider the case of Eiffel vs. Java, for instance.  In Java you use System.out, which is static member of the System class.  In Eiffel, all classes inherit std_output, so they can use such things without having to go into a different class.

Let's see the reaction to those before I go on.  :)

-----------------------------------
rizzix
Mon Mar 07, 2005 9:58 pm


-----------------------------------
Ha! Its all missleading. You see you've just pointed out mostly to syntax sugar that Java and C# dont have. The idea behind Java and C#, is to include the bare minimum in the language and knock out the additional stuff into libraries. This i believe is a plus point on behalf of Java and C#, most other languages are simply bloated, but these two languages have rich and diverse libraries.

- templates
well ur temaplate design is bad. its is not a good idea to pass values as arguments to templates since you'll almost never come across the "need" to do so (unnecessary syntax sugar leads to a TIMTOWTDI effect, which is bad as far as full-fledge programming languages are concerned. scripting languages are an exception). As for types, java has generics, and java does it far better than c++, taking care of the potential flaws with the c++ template design. The only downfall (due to generics in java) is the fact that learning java just got a little harder, with the added complexity. (but java was never intended to be the easiest language to learn)

- functions as first class entities
As i said syntax sugar. It does reduce code but is not required. In java the same thing can be accomplished likewise:public class Name {
   private String first, last;

   public Name(String f, String l)
   {
      first = f;
      last = l;
   }

   public String getFirst {return first;}
   public String getLast {return last;}
}import java.util.*; ...

Name[] names = {new Name("Bob", "Smith"), new Name("John", "Doe")};

Arrays.sort(names, 
    new Comparator() {
        public int compare(Name n1, Name n2) {
            return n1.getLast().compareTo(n2.getLast());
        }
    }
);

- Construction of lists
It would be a good idea to have syntax sugar for hashtables at the least, in Java or C#. But its difficult to change that now.

- No standalone functions
That would go against the consistancy and idealogy of both these languages. These languages depict object interactions, with only one class of the many, being the application class (has the "main" method). I dont see this as a drawback but rather as a plus point. The language is not bloated with features and syntax sugar.

- Multiple inheritance
What happens when two classes define the same symbols? But it is a fact that Single Inheritance has lead to less complexity in object design and modelling (specially in 1000000 lins of code projects) thus further supports extensibility and maintainance once again specially in large projects (hence the awesome support by huge firms). The only drawback is that designing is more difficult as compared to MI design. If ur not a big fan of design before code, then you might as well stay away from these langauges.

-----------------------------------
Hikaru79
Mon Mar 07, 2005 10:02 pm


-----------------------------------
:P Wow. WTD never disappoints! ^__^

I just have a few questions. I'm only just starting C++ so I don't understand what you mean by "templates" but just by looking at it, it looks an awful lot like an interface or abstract class in java. I'm guessing there's a vital difference there... what is it?

Also, Java *does* have Vectors and the other stuff you mention... or did you just mean you don't like the way that they're implemented?

-----------------------------------
rizzix
Mon Mar 07, 2005 10:09 pm


-----------------------------------
wait sorry, my gernerics counter might not have properly countered ur argument: i dont know ada.

-----------------------------------
wtd
Mon Mar 07, 2005 10:26 pm


-----------------------------------
Ha! Its all missleading. You see you've just pointed out mostly to syntax sugar that Java and C# dont have. The idea behind Java and C#, is to include the bare minimum in the language and knock out the additional stuff into libraries. This i believe is a plus point on behalf of Java and C#, most other languages are simply bloated, but these two languages have rich and diverse libraries.

Bloated?  Really.  Have you studied languages like Ruby, Haskell, Eiffel?  Their syntaxes are anything but bloated.  

- templates
well ur temaplate design is bad. its is not a good idea to pass values as arguments to templates since you'll almost never come across the "need" to do so. As for types, java has generics, and java does it far better than c++, taking care of the potential flaws with the c++ template design. The only downfall (due to generics in java) is the fact that learning java just got a little harder, due to the added complexity. (but java was never intended to be the easiest language to learn)

How is my use of templates flawed?  All I've done is provide a compile-time (vs. run-time) assurance that we'll never have something like a 7 number lottery ticket being compared to a 6 number lottery ticket.

Having checks at compile-time is generally preferable to run-time checks where possible.  Of course, I'm also a fan of languages which do most checking at run-time, like Ruby, but in those cases there're typically other benefits.

What are the potential flaws with the C++ template system you refer to, if I may ask?

- functions as first class entities
As i said syntax sugar. It does reduce code but is not required. In java the same thing can be accomplished likewise:public class Name {
   private String first, last;

   public Name(String f, String l)
   {
      first = f;
      last = l;
   }

   public String getFirst {return first;}
   public String getLast {return last;}
}import java.util.*; ...

Name[] names = {new Name("Bob", "Smith"), new Name("John", "Doe")};

Arrays.sort(names, 
    new Comparator() {
        public int compare(Name n1, Name n2) {
            return n1.getLast().compareTo(n2.getLast());
        }
    }
);

Yes, there's that, but that isn't really functions as first class entities, and yes it does go deeper than syntacic sugar, though that should be enough motivation.  Making good methods syntactically easy encourages their use.

- No standalone functions
That would go against the consistancy and idealogy of both these languages. These languages depict object interactions, with only one class of the many, being the application class (has the "main" method). I dont see this as a drawback but rather as a plus point. The language is not bloated.

Ok, let's look at how Ruby manages this.  Everything that goes into what seems like the global space gets added to the Object class.  Since every class inherits from Object, other classes can use that method.

def foo
   "foo"
end

class Bar
   def initialize 
      puts foo
   end
end

It looks like the Bar class is simply using the global foo method.  Instead it looks like this to the compiler:

class Object
   def foo
      "foo"
   end
end

class Bar < Object
   def initialize 
      puts foo
   end
end

- Multiple inheritance
What happens when two classes define the same symbols? But it is a fact that Single Inheritance has lead to less complexity in object design and modelling (specially in 1000000 lins of code projects) thus further supports extensibility and maintainance once again specially in large projects (hence the awesome support by huge firms). The only drawback is that designing is more difficult as compared to MI design. If ur not a big fan of design before code, then you might as well stay away from these langauges.

Single inheritance is easier, but MI is not by any means impossible.  It certainly gets used in C++, Eiffel, and Perl with little trouble.  When name errors do arise these languages have mechanisms for removing ambiguity.

And it's quite useful for modelling some problems.  Let's say I want a class which represents a student.  Clearly handling the student's name and their grades are entirely separate problems, so they should be modelled that way.

#include 
#include 

class Name
{
	private:
		const std::string _first, _last;
	public:
		Name(std::string f, std::string l): _first(f), _last(l) { }
		
		std::string first() const
		{
			return _first;
		}
		
		std::string last() const 
		{
			return _last;
		}
};

class GradesCollection : public std::vector
{
	public:
		GradesCollection() : std::vector() { }

		int sum_grades() const
		{
			int sum = 0;
			for (const_iterator i(begin()); i != end(); ++i)
				sum += *i;
			return sum;
		}
		
		double average_grade() const
		{
			return sum_grades() / size();
		}
};

class Student : public Name, public GradesCollection
{
	public:
		Student(std::string f, std::string l)
		: Name(f, l)
		, GradesCollection()
		{ }
};

-----------------------------------
wtd
Mon Mar 07, 2005 10:35 pm


-----------------------------------
:P Wow. WTD never disappoints! ^__^

I just have a few questions. I'm only just starting C++ so I don't understand what you mean by "templates" but just by looking at it, it looks an awful lot like an interface or abstract class in java. I'm guessing there's a vital difference there... what is it?

A template is a compile-time mechanism.  It doesn't produce executable code, (which is why they go in .h files), but rather a "template" for executable code.

When I declare:

template  LotteryTicket

I simply provide a "template" for LotteryTicket classes.  When I later use:

LotteryTicket

The compiler creates a class for me where N is replaced by 7.  Think of it like macros... only safer, and much more powerful.

Also, Java *does* have Vectors and the other stuff you mention... or did you just mean you don't like the way that they're implemented?

Exactly.  It's inconvenient to use them, so a lot of people don't, and that leads to problems.  Lots of problems.

-----------------------------------
rizzix
Mon Mar 07, 2005 11:35 pm


-----------------------------------
Bloated?  Really.  Have you studied languages like Ruby, Haskell, Eiffel?  Their syntaxes are anything but bloated. No, but the fact that I can do everything those languages can do with the limited syntax of Java and C# does make it seem as though those languages are simply bloated.  

How is my use of templates flawed?  All I've done is provide a compile-time (vs. run-time) assurance that we'll never have something like a 7 number lottery ticket being compared to a 6 number lottery ticket. Yes good argument, it is also preferable to move as far as possible, the error checking to compiler time even in the Java world (hence generics). But that is really not the real reason to the use of value passing in that example. The real reason is that C arrays do not hold length information, hence you are forced to rely on templates to take care of this drawback in C. And templates is simple the only better way to work around this,, originally C programmers would use macros, but macors dont result in compiler errors.

What are the potential flaws with the C++ template system you refer to, if I may ask? The folling link will explain it all (it's kinda complex) and will detail the reasons as to why the modifications were made: http://java.sun.com/docs/books/tutorial/extra/generics/ 


Yes, there's that, but that isn't really functions as first class entities, and yes it does go deeper than syntacic sugar, though that should be enough motivation.  Making good methods syntactically easy encourages their use. Not to mention the Comparator object could be refered to by a reference and reused in various other Arrays.sort calls for various other arrays.

Why?  Look at Groovy for an example of this working just peachy with Java. Groovy does use the Java platform but it is a whole new language. For java to implement this syantax requires the Java Language Specification to be ameded, which is a long process and quite a pain in the neck. Either way i must mention the use of HashTables result in a heavy use of RAM memory. HashTables work on the basis that strings can be represented as a number of a fixed length (like int, short etc). This process is known as hashing. Hash functions vary in that they provide for a disctinct number on either a small range or large range of values (the domain). The larger the domain the more varied a string can be hashed. But behind the scenes all these hashed values are used as the index of a generic array. Thus the array has to be large enough to cover the entire domain of the hash function. Hence the increase in memory use.

Ok, let's look at how Ruby manages this.  Everything that goes into what seems like the global space gets added to the Object class.  Since every class inherits from Object, other classes can use that method.

def foo
   "foo"
end

class Bar
   def initialize 
      puts foo
   end
end

It looks like the Bar class is simply using the global foo method.  Instead it looks like this to the compiler:

class Object
   def foo
      "foo"
   end
end

class Bar < Object
   def initialize 
      puts foo
   end
end No argument.



Single inheritance is easier, but MI is not by any means impossible.  It certainly gets used in C++, Eiffel, and Perl with little trouble.  When name errors do arise these languages have mechanisms for removing ambiguity.

And it's quite useful for modelling some problems.  Let's say I want a class which represents a student.  Clearly handling the student's name and their grades are entirely separate problems, so they should be modelled that way.

#include 
#include 

class Name
{
	private:
		const std::string _first, _last;
	public:
		Name(std::string f, std::string l): _first(f), _last(l) { }
		
		std::string first() const
		{
			return _first;
		}
		
		std::string last() const 
		{
			return _last;
		}
};

class GradesCollection : public std::vector
{
	public:
		GradesCollection() : std::vector() { }

		int sum_grades() const
		{
			int sum = 0;
			for (const_iterator i(begin()); i != end(); ++i)
				sum += *i;
			return sum;
		}
		
		double average_grade() const
		{
			return sum_grades() / size();
		}
};

class Student : public Name, public GradesCollection
{
	public:
		Student(std::string f, std::string l)
		: Name(f, l)
		, GradesCollection()
		{ }
}; The biggest drawback in MI is the overhead complexity that should be excluded in any  project specially those with complex heirarichal structures. Following conventions does not guarantee anything. It is very likely the feature available will be abused in some way or another. Either way in ur example it is best that the Name of the student is used as a property of the Student class, your OOD is flawed.


Also, Java *does* have Vectors and the other stuff you mention... or did you just mean you don't like the way that they're implemented?

Exactly.  It's inconvenient to use them, so a lot of people don't, and that leads to problems.  Lots of problems. Thats a lie. Infact IMO its the other way around. The Java's Vector class is one of the most used classes in any java application. The entire java standard library by far is  quite superior that that of the stl. Not to mention the documentation avaialable for the java API as compared to that for the stl, java's outbeats it anyday. Name something that the the stl library can do better than that of Java's.

-----------------------------------
wtd
Tue Mar 08, 2005 7:15 pm


-----------------------------------
Bloated?  Really.  Have you studied languages like Ruby, Haskell, Eiffel?  Their syntaxes are anything but bloated. No, but the fact that I can do everything those languages can do with the limited syntax of Java and C# does make it seem as though those languages are simply bloated.

Let me assure you, while some are (there are lots of languages and speaking in absolutes is the path to madness), the languages I've mentioned aren't.  They simply provide good syntax and library level support for common data structures and what you might call "design patterns."  Notably things like pre and post condition checks.

Generally the inclusion of such things leads to much more elegant, less bloated code since a single standard (and typically sane) means of accomplishing a task is provided.  Programmers need not find their own ways to solve simple problems (though doing so is not necessarily bad from a learning experience point of view).

Consider the task of taking one array/list and mutating each element, then saving the result in another array/list.

Java 5.0:
int[] foo = new int[10];
int[] bar = new int[10];

for (int i = 0; i < 10; i++)
   foo[i] = i;

for (int i = 0; i < 10; i++)
   bar[i] = foo[i] * 2;

Haskell:
foo = [0..9]
bar = map (* 2) foo

Why shouldn't it be that easy?  Haskell has a simpler syntax, after all.

How is my use of templates flawed?  All I've done is provide a compile-time (vs. run-time) assurance that we'll never have something like a 7 number lottery ticket being compared to a 6 number lottery ticket. 

Yes good argument, it is also preferable to move as far as possible, the error checking to compiler time even in the Java world (hence generics). But that is really not the real reason to the use of value passing in that example. The real reason is that C arrays do not hold length information, hence you are forced to rely on templates to take care of this drawback in C. And templates is simple the only better way to work around this,, originally C programmers would use macros, but macors dont result in compiler errors.

The reasoning behind C++ templates is not what you think it is.  I could easily create a class which emulates an array, stores size, and only stores a single kind of value.

#include 

class MyVector
{
   private:
      int *_data;
      size_t _size;
   public:
      MyVector() : _data(new int[0]), _size(0) { }
      MyVector(size_t size) : _data(new int[size]), _size(size) { }
      ~MyVector() { delete [] _data; _size = 0; }
      /* yada yada */
};

What the template system gives me is type safety.  Yes, Java has generics, but they're really half-assed.  I'll grant you that they're an improvement, but they still leave a lot to be desired.  Out of concern for backwards compatibility (which they later broke anyway) Sun didn't give the Java community real generics.  Instead, what you get is truly syntactic sugar for casts which are still there and still can be troublesome.  The C++ solution eliminates casts.  

What are the potential flaws with the C++ template system you refer to, if I may ask? The folling link will explain it all (it's kinda complex) and will detail the reasons as to why the modifications were made: http://java.sun.com/docs/books/tutorial/extra/generics/ 

I'm actually familiar with generics in Java.  Compared to C++, Ada and Eiffel (not to mention Haskell and O'Caml), they're not impressive.

Yes, there's that, but that isn't really functions as first class entities, and yes it does go deeper than syntacic sugar, though that should be enough motivation.  Making good methods syntactically easy encourages their use. Not to mention the Comparator object could be refered to by a reference and reused in various other Arrays.sort calls for various other arrays.

Ok, here's the same idea.

data Name = Name {first::String, last::String}

names = [Name "Bob" "Smith", Name "John" "Doe"]
sortedNames = sortBy (\a b -> last a `compare` last b) names

Now, if I want my "comparator" function as a function I can use elsewhere:

compareNames a b = last a `compare` last b

Or better yet:

compareNames (Name _ a) (Name _ b) = a `compare` b

Then the sorting looks like:

sortedNames = sortBy compareNames namessortNames = sortBy compareNames

Then:

sortedNames = sortNames names

Can you achieve something sort of similar in Java if you try?  Yes.  Why should it be hard, though?  

Why?  Look at Groovy for an example of this working just peachy with Java. Groovy does use the Java platform but it is a whole new language. For java to implement this syantax requires the Java Language Specification to be ameded, which is a long process and quite a pain in the neck. Either way i must mention the use of HashTables result in a heavy use of RAM memory. HashTables work on the basis that strings can be represented as a number of a fixed length (like int, short etc). This process is known as hashing. Hash functions vary in that they provide for a disctinct number on either a small range or large range of values (the domain). The larger the domain the more varied a string can be hashed. But behind the scenes all these hashed values are used as the index of a generic array. Thus the array has to be large enough to cover the entire domain of the hash function. Hence the increase in memory use.

Hashtables need not be that memory-intensive, though the trade-off can be increased CPU usage.  The general truth is that you can either code fast, or run fast.  Trying to optimize every little thing is not terribly easy.

The truth is, hashtables are often immensely useful.

Ok, let's look at how Ruby manages this.  Everything that goes into what seems like the global space gets added to the Object class.  Since every class inherits from Object, other classes can use that method.

def foo
   "foo"
end

class Bar
   def initialize 
      puts foo
   end
end

It looks like the Bar class is simply using the global foo method.  Instead it looks like this to the compiler:

class Object
   def foo
      "foo"
   end
end

class Bar < Object
   def initialize 
      puts foo
   end
end No argument.



Single inheritance is easier, but MI is not by any means impossible.  It certainly gets used in C++, Eiffel, and Perl with little trouble.  When name errors do arise these languages have mechanisms for removing ambiguity.

And it's quite useful for modelling some problems.  Let's say I want a class which represents a student.  Clearly handling the student's name and their grades are entirely separate problems, so they should be modelled that way.

#include 
#include 

class Name
{
	private:
		const std::string _first, _last;
	public:
		Name(std::string f, std::string l): _first(f), _last(l) { }
		
		std::string first() const
		{
			return _first;
		}
		
		std::string last() const 
		{
			return _last;
		}
};

class GradesCollection : public std::vector
{
	public:
		GradesCollection() : std::vector() { }

		int sum_grades() const
		{
			int sum = 0;
			for (const_iterator i(begin()); i != end(); ++i)
				sum += *i;
			return sum;
		}
		
		double average_grade() const
		{
			return sum_grades() / size();
		}
};

class Student : public Name, public GradesCollection
{
	public:
		Student(std::string f, std::string l)
		: Name(f, l)
		, GradesCollection()
		{ }
}; The biggest drawback in MI is the overhead complexity that should be excluded in any  project specially those with complex heirarichal structures. Following conventions does not guarantee anything. It is very likely the feature available will be abused in some way or another. Either way in ur example it is best that the Name of the student is used as a property of the Student class, your OOD is flawed.

So, because a feature which is potentially incredibly useful may be abused, it should be removed from the language entirely?  Read Bertrand Meyer's Object-Oriented Software Construction.  Multiple inheritance can be done right, and when it is, it's a very good thing for code re-use.


Also, Java *does* have Vectors and the other stuff you mention... or did you just mean you don't like the way that they're implemented?

Exactly.  It's inconvenient to use them, so a lot of people don't, and that leads to problems.  Lots of problems. Thats a lie. Infact IMO its the other way around. The Java's Vector class is one of the most used classes in any java application. The entire java standard library by far is  quite superior that that of the stl. Not to mention the documentation avaialable for the java API as compared to that for the stl, java's outbeats it anyday. Name something that the the stl library can do better than that of Java's.

Show me a function which will swap any two variables of type T where T is any type.  Show me how I'd sort just the first ten items in a vector, list, array, etc.

-----------------------------------
rizzix
Wed Mar 09, 2005 4:07 pm


-----------------------------------
Java 5.0:
int[] foo = new int[10];
int[] bar = new int[10];

for (int i = 0; i < 10; i++)
   foo[i] = i;

for (int i = 0; i < 10; i++)
   bar[i] = foo[i] * 2;

Haskell:
foo = [0..9]
bar = map (* 2) foo

Why shouldn't it be that easy?  Haskell has a simpler syntax, after all.No Argument.


Yes, Java has generics, but they're really half-assed.  I'll grant you that they're an improvement, but they still leave a lot to be desired.  Out of concern for backwards compatibility (which they later broke anyway) Sun didn't give the Java community real generics.  Instead, what you get is truly syntactic sugar for casts which are still there and still can be troublesome.  The C++ solution eliminates casts. I'm actually familiar with generics in Java.  Compared to C++, Ada and Eiffel (not to mention Haskell and O'Caml), they're not impressive. What more do you need besides type-safety, considering that Java is much more dynamic than C++. And elaborate on "half-assed", show me how, and what you mean, exculding examples that include the passing of 'values', since we have established Java does not have that (and as I commented, its unnecessay).


...Can you achieve something sort of similar in Java if you try?  Yes.  Why should it be hard, though? Its not harder just different. But if you mean by harder that it takes a few extra lines of code.. then maybe, but its insignificant comparatively. Java's way of going about it also provides a form of encapsulation over the sorting algorithm. You sorted you object based on a rather simple criteria, but in the real-world the criteria could be much complex. In these cases I see the Java's way as the prefered method. For example the retained Comparator object can be passed to other objects where its state maybe modified. Based on its current state and other factors it would modify its sorting criteria etc. Thus this proves to be a more versatile solution.



So, because a feature which is potentially incredibly useful may be abused, it should be removed from the language entirely?  Read Bertrand Meyer's Object-Oriented Software Construction.  Multiple inheritance can be done right, and when it is, it's a very good thing for code re-use. A good language should aviod abuse as far as possible, cuz just as stated in Murphy's Law: "Anything that can go wrong will go wrong". Now look at a huge firm that has 1000s of programmer under it, the probability of abuse is much higher. Also not to mention opensource projects.



Show me a function which will swap any two variables of type T where T is any type.  Show me how I'd sort just the first ten items in a vector, list, array, etc. Actually for arrays most of this is already possible. But of the rest of the Collection framework, java lacks the functions. To overcome this drawback there's the [url=http://jaxlib.org]jaxlib's jax.col.* classes which cover all these little details and much more. Also: The Java Collection Framework is thread-safe, how about stl?

-----------------------------------
wtd
Wed Mar 09, 2005 7:31 pm


-----------------------------------
What more do you need besides type-safety, considering that Java is much more dynamic than C++. And elaborate on "half-assed", show me how, and what you mean, exculding examples that include the passing of 'values', since we have established Java does not have that (and as I commented, its unnecessay).

class Dog
{
        public Dog() { super(); }

        public void talk()
        {
                System.out.println("Woof!");
        }
}

class Robot
{
        public Robot() { super(); }

        public void talk()
        {
                System.out.println("More oil, please.");
        }
}

class Tree
{
        public Tree() { super(); }

        public void bark()
        {
                System.out.println("Rough");
        }
}

public class Test
{
        public static void main(String[] args)
        {
                speak(new Dog());
                speak(new Robot());
                speak(new Tree());
        }

        private static  void speak(T speaker)
        {
                speaker.talk();
        }
}


This doesn't compile.  It doesn't even compile if we remove:

speak(new Tree());

What's the error?

Test.java:42: cannot find symbol
symbol  : method talk()
location: class java.lang.Object
                speaker.talk();
                       ^
1 error


Basically, T is being really treated like Object, so I can only call Object methods on the speaker object.  To make it work, I have to write this as:

interface Speaks
{
        public void talk();
}

class Dog implements Speaks
{
        public Dog() { super(); }

        public void talk()
        {
                System.out.println("Woof!");
        }
}

class Robot implements Speaks
{
        public Robot() { super(); }

        public void talk()
        {
                System.out.println("More oil, please.");
        }
}

class Tree
{
        public Tree() { super(); }

        public void bark()
        {
                System.out.println("Rough");
        }
}

public class Test
{
        public static void main(String[] args)
        {
                speak(new Dog());
                speak(new Robot());
//              speak(new Tree());
        }

        private static  void speak(T speaker)
        {
                speaker.talk();
        }
}


In which case I might as well have written:

interface Speaks
{
        public void talk();
}

class Dog implements Speaks
{
        public Dog() { super(); }

        public void talk()
        {
                System.out.println("Woof!");
        }
}

class Robot implements Speaks
{
        public Robot() { super(); }

        public void talk()
        {
                System.out.println("More oil, please.");
        }
}

class Tree
{
        public Tree() { super(); }

        public void bark()
        {
                System.out.println("Rough");
        }
}

public class Test
{
        public static void main(String[] args)
        {
                speak(new Dog());
                speak(new Robot());
//              speak(new Tree());
        }

        private static void speak(Speaks speaker)
        {
                speaker.talk();
        }
}


Though the generic way does have merit (within the context of previous limitations placed on the Java language at least) when you require multiple arguments or variables to be of the same type that implements Speaks.

...Can you achieve something sort of similar in Java if you try?  Yes.  Why should it be hard, though? 

Its not harder just different. But if you mean by harder that it takes a few extra lines of code.. then maybe, but its insignificant comparatively. Java's way of going about it also provides a form of encapsulation over the sorting algorithm. You sorted you object based on a rather simple criteria, but in the real-world the criteria could be much complex. In these cases I see the Java's way as the prefered method. For example the retained Comparator object can be passed to other objects where its state maybe modified. Based on its current state and other factors it would modify its sorting criteria etc. Thus this proves to be a more versatile solution.

Provide me with a more complex sorting problem and we'll compare solutions.  :)

-----------------------------------
wtd
Wed Mar 09, 2005 7:33 pm


-----------------------------------
A good language should aviod abuse as far as possible

Java has casts and automatic promotion (int -> float and such).  They're a huge potential problem, and a nuisance at best.  Is it a bad language for having them?

-----------------------------------
Naveg
Wed Mar 09, 2005 9:36 pm


-----------------------------------
wow, i've never seen such a true love of programming before. All i can say is that you guys are truly dedicated to what you do, and you should both be commended.

-----------------------------------
Andy
Wed Mar 09, 2005 9:37 pm


-----------------------------------
errr you do realize both of them have jobs in the tech field rite?

-----------------------------------
Naveg
Wed Mar 09, 2005 11:06 pm


-----------------------------------
yea, and its good to know we have people who care so much and know what theyre doing in those jobs.

-----------------------------------
wtd
Wed Mar 09, 2005 11:11 pm


-----------------------------------
wow, i've never seen such a true love of programming before. All i can say is that you guys are truly dedicated to what you do, and you should both be commended.

Thank you.

-----------------------------------
Martin
Thu Mar 10, 2005 8:37 am


-----------------------------------
Rizzix, how old are you, and where do you work?

-----------------------------------
rizzix
Thu Mar 10, 2005 9:35 am


-----------------------------------
I dont work, 18.

-----------------------------------
Martin
Thu Mar 10, 2005 10:16 am


-----------------------------------
That's what I thought. Alright, gentlemen, carry on.

-----------------------------------
rizzix
Thu Mar 10, 2005 3:33 pm


-----------------------------------
Java has casts and automatic promotion (int -> float and such).  They're a huge potential problem, and a nuisance at best.  Is it a bad language for having them? Automatic type promotion is much better than type casting (like in c/c++). And yes casting can be abused (although its quite restrictive in java, but thats no excuse) hence 1.5 came out with generics to reduce the unnecessay (forced) casts that were required specially when using the Collection Framework. So, all in all, the java language hasn't reached it's final state yet, it is evolving and for the better. I guess we can agree its not simply a brain-dead language now, can we?  :wink:

As for the comparator example i'd rather not, i feel like closing this debate now, i hate arguing anyways, heh. :lol: It maybe true that those other languages u use in ur arguments can accomplish the sorting based on complex criterias but i doubt they can do it through encapsulating the entire criteria, state, etc in some form or the other... similar to java and its OO method. Unless of course you create an object just for that purpose. If thats the case, I see the java way the better way.

-----------------------------------
wtd
Thu Mar 10, 2005 7:08 pm


-----------------------------------
Arguing is good.  It brings stuff to the surface that wouldn't otherwise get discussed.  :)

As for encapsulation, you still have to access the objects being compared from a public viewpoint.  You can't have any special access to their internal state.

The only thing I can think of is adding an instance variable to your Comparator class which compare updates, but I'm not sure where that would be useful or wise.  The only behavior I can see that permitting is for the comparison to change after a certain number of comparisons have been made, which could result in something really bizarre.

Of course, in any such debate confusion is likely to reign, particularly over the issue of mutable state.  Of course, if you're talking about a default sorting algorithm of some complexity, I can do that with Haskell too.  :)

Let's say I create a Name data type like so, with two constructors and for which we have the ability to stringify, test for equality, and compare:

data Name = Name2 {first::String, last::String} | Name3 {first::String , middle::String, last::String} deriving (Eq)

instance Show Name where
   show (Name2 f l) = f ++ " " ++ l
   show (Name3 f m l) = f ++ " " ++ m ++ " " ++ l

instance Ord Name where
   compare (Name2 f1 l1) (Name2 f2 l2) = 
      case compare l1 l2 of
         EQ -> compare f1 f2
         n  -> n
   compare (Name3 f1 m1 l1) (Name3 f2 m2 l2) =
      case compare l1 l2 of
         EQ -> case compare f1 f2 of
            EQ -> compare m1 m2
            n  -> n
         n  -> n
   compare (Name2 f1 l1) (Name3 f2 _ l2) =
      case compare l1 l2 of
         EQ -> compare f1 f2
         n  -> n
   compare (Name3 f1 _ l1) (Name2 f2 l2) =
      case compare l1 l2 of
         EQ -> compare f1 f2
         n  -> n

Roughly equivalent to the following Java:

class Name implements Comparable
{
   private String first, middle, last;

   public Name(String first, String last)
   {
      this.first = first;
      this.last = last;
      this.middle = null;           
   }

   public Name(String first, String middle, String last)
   {
      this.first = first;
      this.last = last;
      this.middle = middle;           
   }

   public String getFirst() { return first; }
   public String getMiddle() { return middle; }
   public String getLast() { return last; }

   public String toString()
   {
      if (hasMiddle())
         return first + " " + middle + " " + last;
      else
         return first + " " + last;
   }

   public boolean hasMiddle() { return middle != null; }

   public boolean equals(Object o)
   {
      Name n = (Name)o;
      return (first == n.getFirst() && middle == n.getMiddle() && last == n.getLast());         
   }

   public int compareTo(Name n)
   {
      int cmp;

      // Compare names with middle names.
      // First sort on last name, then first name, then middle name
      if (this.hasMiddle() && n.hasMiddle())
      {
         switch (cmp = this.last.compareTo(n.getLast()))
         {
            case 0: 
               switch (cmp = this.first.compareTo(n.getFirst()))
               {
                  case 0:
                     return this.middle.compareTo(n.getMiddle());
                  default:
                     return cmp;
               }
            default:
               return cmp;               
         }
      }
      // Compare names on a first and last name basis only
      else
      {
         switch (cmp = this.last.compareTo(n.getLast()))
         {
            case 0:
               return this.first.compareTo(n.getFirst());
            default:
               return cmp;
         }
      }
   }
}

Is it wrong that this is fun? :)

-----------------------------------
Martin
Thu Mar 10, 2005 7:17 pm


-----------------------------------
A three page online debate without anybody saying 'f-a-g'

That's gotta be a first.
Nick-just-couldn't-resis editt: stop being gay, Martin

-----------------------------------
rizzix
Thu Mar 10, 2005 7:53 pm


-----------------------------------
wtd: yea.. and maybe adding there an ascending/decending state as well. (refering to example)

I also see the java approach seemlessly intergrating with MVC architecture: where a controller object is passed the comparator object, changing it's state based on user intereaction. At the same time (upon a risen event) the controller issues change notifications to various observers. The model also having a reference to the comparator and being one of the observers could update itself (thus a sort is in action). But the difference here is that the compartor has its state changed. Hence the sort results are different. The view is then notified and the results are displayed.

-----------------------------------
wtd
Thu Mar 10, 2005 8:05 pm


-----------------------------------
The problem I see with that approach (mutable comparator) is that it could cause a lot of oddities with regards to different sorting strategies (number of passes and such).

-----------------------------------
rizzix
Thu Mar 10, 2005 8:08 pm


-----------------------------------
Hmm, well i can;t see how that could be a problem, so long as the comparator and the sort method calls  are in the same thread.

edit: but even if they arn't, in this case,  i guess you would just have to block futher sort events till the view is updated.

-----------------------------------
wtd
Thu Mar 10, 2005 8:12 pm


-----------------------------------
wtd: yea.. and maybe adding there an ascending/decending state as well. (refering to example)

When you have comparable data (by implementing Comparable in the Java example, and by making Name an instance of the Ord class in Haskell), you have everything there that's necessary.  The sort method/function should then be able to control ascending or descending state (based on the output of compareTo/compare).

Of course, the obvious answer is that you only need to be able to sort in an ascending manner, then reverse the list/array.  :)

-----------------------------------
rizzix
Thu Mar 10, 2005 8:15 pm


-----------------------------------
that may be the case for the ascending/decending state. but lets take a table  component in consideration. now based on the column the user click we want to sort our model to the respective fields. the situation is different now dont you think? encapsulation helps a lot.

edit: nvm. didn;t see ur quotes. heh.

-----------------------------------
wtd
Thu Mar 10, 2005 8:47 pm


-----------------------------------
Something like this, you mean?  :)

import List

data Column = NameCol | AgeCol | WeightCol
data Row = Row {name::Name, age::Int, weight::Int}
type Table = [Row]
 
sortByCol col =
   sortBy (\a b -> case col of 
      NameCol -> compare (name a) (name b)
      AgeCol -> compare (age a) (age b)
      WeightCol -> compare (weight a) (weight b))
