Monday, June 28, 2004

.NET architecture...

I have reread .NET architecture specification and other related documents on the weekend. The architecture does not provide any means to implement metaclasses. That is why I don’t ask to add this feature to C# further more. The problem is classes in .NET were static and they were not created with a constructor of class Type. Disappointing. Haiku?

Another interesting feature is static members of interfaces. It’s possible to provide implementation for static methods of interfaces, but this will impact CLS-compliance. Do we need this?

I wonder why authors of C# did not include exception filters. Those are supported by the framework. Anonymous delegates will simplify the process.


Friday, June 25, 2004

Tuples

Often they request tuples support in C#. Actually I will remove all the out parameters from my APIs as soon as tuples have been introduced to C#. But what do we really need?

Tuple is an immutable array of objects. "Objects" means instances of type System.Object. Thus method returning tuple has type object[]. This behavior does not require any language change. If someone wishes the method to return something like (int x, int y, Color c) he|she should rethink the model and declare

struct Pixel{ int x, y; Color c }

What tuples actually provide is multiple assignment:

int [] F( string str )
{
string [] ss = str.Split();
int [] result = new int[ ss.Length ];
for( int i = 0; i < ss.Length; i++ )
result[i] = int.Parse(ss[i]);
return result;
}
int a, b;
(a,b) = F( "3 5" ); // assures a=3 and b=5;
(a,b) = (b,a); // swap a and b

That is unrolling of array to a sequence of variables with casting and coercion if needed. Reverse operation is needed to support the last statement of swapping two variables. That is the comma operator which combines objects to an array.

One question is what should happen in the following situation:

(a,b) = F( "3 5 7 9" );

Extra objects could be dropped or an exception could be raised. In the latter case the exception should be thrown after assigning to a and b. Thus there will be a chance to simply ignore the exception:

try { (a,b) = F( "3 5 7 9" ); }
catch(ExtraObectException){};

There could be a way of handling all the extra objects with an array:

int [] others;
(a,b,others) = F( "3 5 7 9" );
// a=3 and b=5 and others = new int[]{7,9}

I have placed parenthesis around tuples a,b after I had written the article. I feel the need of the parenthesis to prevent ambiguity in method calls:

void M( int [] );
void M( int, int, int );
M( 3,4,5 );
M( (3,4,5) );

And one note: IMO tuples are not needful.


Thursday, June 24, 2004

Formatting

The task is to apply colors, fonts, and layout attributes to blocks of text accoring to some patterns. It's common practice to write text patterns in form of regular expressions. Thus we could define style for document as a set of pairs of a regular expression and formatting description.

But C# code is structured text. There is a working solution of structured text formatting, that is XML with style sheets. While C# code is not XML, editor could treat the code as XML internally and apply style sheets, and then render the result on screen. Equivalent XML could look like this

<comment>An example of class</comment>
<class>
<keyword>public</keyword>
<keyword>class</keyword> Class1
{
<method>
<keyword>public</keyword>
<keyword>static</keyword>
<MethodName>Main</MethodName>()
{
<MethodBody>
Console.WriteLine("Hello World");
</MethodBody>
} </method>
} </class>

CSS can use regular expressions as well, thus providing possibility of using regular expressions only to describe formatting rules.

Options dialog present in IDE could provide a limited set of funstionality to simplify the process of formatting. Advanced users can type their own style sheets or create them with third party tools.


Wednesday, June 23, 2004

foreach statement

using <class> is like with <an object> in Pascal. And I think there is a situation where such a feature will be useful.

The foreach statement always involves declaration of a local variable:

foreach( XmlElement element
in doc.SelectNodes(xpath) )
{
Console.WriteLine( "{0} of type {1}",
element.Name,
element.GetAttribute("Type"));
}

How often You name the variable with i? While there is always the variable in the foreach statement it's possible simply omit its name:

foreach( XmlElement in doc.SelectNodes(xpath) )
{
Console.WriteLine( "{0} of type {1}",
Name, GetAttribute("Type") );
}


Enumerators

A little enhancement in Iterators

class DHash : Hashtable
{
public virtual object this[object key,
delegate object def(object)]
{
get
{
object r = base[key];
return r != null ? r : def(key);
}
}
}

An anonymous delegate will provide values for missing items


Language enhancements

What will I code at the moment when I'd obtain my copy of new C#? First I'll try to use templates and anonymous delegates at their full potential. First I'd like to have a class

class Range<Type T>
{
public T Left, Right;
public virtual void Each( T step,
delegate bool body( T ) )
{
for( T t = Left; t < Right; t += step )
if( !body( t ) ) break;
}
}

Please, note that the delegate body has been declared as bool. The purpose is to allow complete mirroring of foreach statement.

Range<double> dr( 0.0, 100.0 );
double max = 66.0;
double min = 33.0;
double sum = 0.0;
dr.Each( 3.14, \(double i)
{
if( i > max ) break;
if( i < min ) continue;
sum += i;
}

break statement is meaningless in this case unless it was equivalent to return false. Reciprocally contiunue would be equivalent to return true. While the example was not very practical, it's illustrative. Certainly the anonymous delegate should return true by default.

Another feature would be a statement for instantiation of a template. Just like in C++

typedef Range<int> Int32Range;

I work on a class library which requires this feature.

Next I'd like to be able to restrict the use the template on ordered and additive types only:

class Range<Type T : IAdditive, IComparable>

Next a variation of Each method

class Range<Type T : IAdditive, IComparable>
{
public virtual void Each(
delegate T step(T),
delegate bool body(T))
{
for( T t = Left; t < Right; t = step(t) )
if( !body(t) ) break;
}
}

Or this could be declared as

public virtual void Each(delegate step(ref T),
delegate bool body(T))

Then DiscontinuousRange<Type T, T step> could be declared to provide Each method with default step etc.

Let's return to IAdditive and IComparable. It would be good if the classification was a little bit complicated. For example, let's declare IOrdered. Then IContinuous:IOrdered, IDiscontinuous:IOrdered, and IAlternative:IOrdered. Finally declare Int32 as IDiscontinuous, Double as IContinuous, Boolean as IAlternative. This will provide an opportunity to define

class DiscontinuousRange<Type T:IDiscontinuous> : Range<T>
{
public void Each( delegate bool body(T) )
{
T t = Left;
while( T.MoveNext(ref t) ) )
if( !body(t) ) ) break;
}
}

The Range class is especially useful in defining ranges of continuous data such as DateTime.

One more piece of sugar:

interface IList<Type ItemType,
Type IndexType : IDiscontinuous>;
class DicontinuousRange<Type T : IDiscontinuous>:Range<T>
{
public template <Type ItemType>
static ItemType [] operator *(
IList<ItemType,T> list,
DicontinuousRange<T>)
{
ArrayList<ItemType> result = new ArrayList<ItemType>();
Each( \(t)
{
Result.Add( list[t] );
});
retun result.ToArray();
}
}


This page is powered by Blogger. Isn't yours?