Why C# doesn't support overloading based on return type - c#-4.0

In C# why can't we have two functions with same signature except return type:
(1) int Function(int a,int b)
{
---}
(2) string Function(int a,int b)
{
---}
Why C# doesn't support overloading based on return type?

object result = Function(a, b);
Which one do you call?

Because you can't specify the return type when you call it.
// int or string?
Function(a, b);
I'm also curious why you would want to do this, naming something the same but returning two different things is probably a bad idea. This code is far more readable and the intent is clearer:
string x = FunctionToString(a, b);
int y = FunctionToInt(a, b);

Related

Is there a name for a trampoline class?

I'm designing a programming language and one feature I'd like to add is a cross between a trampoline function and a class. That is, a class which takes in a literal akin to a generic class taking in a type. I'm stuck on a name for these because I haven't encountered them in a language before, is there something which already means this concept or something close? Using trampoline class is an option, but if there's something that more accurately describes this or is already in use in another language I'd prefer to go with it to cut down on the amount of jargon required in the documentation.
Pseudo-code follows to illustrate this principle in case it is not clear from the above:
class Point<const int n> {
private float[n] _value;
Point() {
for (int i = 0; i < n; i++) {
this._value[i] = 0f;
}
}
Point(Point<o> other) {
for (int i = 0; i < min(n, o); i++) {
this._value[i] = 0f;
}
}
public static float operator [index] (optional float value = null) {
if (value != null) { this._value[index] = value; }
return (this._value[index]);
}
public static Point<max(o, p)> operator + (Point<const int o> p1, Point<const int p> p2) {
Point<min(o, p)> small = (p1.n < p2.n ? p1 : p2);
Point<min(o, p)> large = (p1.n < p2.n ? p2 : p1);
Point<max(o, p)> ret = new Point<max(o, p)>(large);
for (int i = 0; i < min(o, p); i++) { ret[i] += small[i] }
return (ret);
}
}
The term you are looking for is dependent types. It means that a type cannot only have type parameters (like generics), but a type can also be parameterized with arbitrary values (the dependent type parameters). For example, you can define the signature of a function that takes a number n and returns an array of length n.
Sadly, dependent type checking in general is undecidable. This is, because you have to calculate the range of possible values of the dependent type parameters while the type checking itself is executed. To actually type check the program, you have to check whether two pieces of code produce the same range of possible values. This is known as extensional function equality and this is the part that is known to be undecidable in general.
Now, it might be true that dependent type checking becomes decidable if only compile-time constants are used as dependent type parameters. However, I am not sure about that.
In the comments below, we figured out that the part that seems to be the dependent type parameter should actually not be used for the type checking. Instead, it can be seen as an implicit parameter. It is similar to implicit parameter passing in the Scala programming language.

How can I distinguish tail recursive calls/non-tail recursive calls?

int gcd(int a,int b){
if(a == b) return a;
else if (a>b) return gcd(a-b,b);
else return gcd(a,b);
}
For example, i think this is tail-recursive because you don't call another function.
int gcd(int a,int b){
int x;
if(a == b) x=a;
else if (a>b) x= gcd(a-b,b);
else x= gcd(a,b);
return x;
}
And this is non-tail recursive because it calls function gcd.
Am I right? Or is there any easier method to distinguish tail/non-tail recursive call?
First of all, for the purpose of g++ TCO (tail-call optimization) it doesn't matter if you are doing a recursive call or calling a different function altogether - function call will be replaced with unconditional jump.
Second of all, a tail call is happening when there is nothing happening between the call to other function and return. It can be last line before return, not last line before return or return itself.
For example,
} else {
x = gcd(a,b);
return x;
}
is a tail-call, because the value of x is returned unmodified (nothing is happening).
On the other hand,
} else {
x = gcd(a,b);
return x + 1;
}
This is not eligible for TCO, since return value is modified - something is happening.
But the fun just begins! Let's talk C++ and destructors. Consider following code:
int do2();
int do() {
std::string x;
// ...
return do2();
}
Is it a tail-call? First impression - yes, it is. Nothing is happening, right? Second impression - no, it is not! x destructor needs to happen! Third impression - yes, it is - because compiler, seeing as x is not used after the call, can easily destruct x before.
But, look at that:
int do2(const std::string& );
int do() {
std::string x;
// ...
return do2(x);
}
Here it is not a tail-call! x has to outlive do2, so going back to my original (deliberately vague) definition, something is happening.
Tail-calls are funny!

NDepend rule to warn if objects of a given type are compared using ==

as the title says: I need a NDepend rule (CQLinq) for C#/.net code, that fires whenever instances of a given type are compared using == (reference comparison). In other words, I want to force the programmer to use .Equals.
Note that the type in question has no overloaded equality operator.
Is this possible? If so, how? :)
Thanks, cheers,
Tim
With the following code with see that for value type, == translate to the IL instruction: ceq. This kind of usage cannot be detected with NDepend.
int i = 2;
int j = 3;
Debug.Assert(i == j);
var s1 = "2";
var s2 = "3";
Debug.Assert(s1 == s2);
However for reference types we can see that a operator method named op_Equality is called.
L_001d: call bool [mscorlib]System.String::op_Equality(string, string)
Hence we just need a CQLinq query that first match all method named op_Equality, and then list all callers of these methods. This can look like:
let equalityOps = Methods.WithSimpleName("op_Equality")
from m in Application.Methods.UsingAny(equalityOps)
select new { m,
typesWhereEqualityOpCalled = m.MethodsCalled.Intersect(equalityOps).Select(m1 => m1.ParentType) }
This seems to work pretty well :)

How do I use groovy's AS keyword

This may be a duplicate but "as" is an INCREDABLY hard keyword to google, even S.O. ignores "as" as part of query.
So I'm wondering how to implement a class that supports "as" reflexively. For an example class:
class X {
private val
public X(def v) {
val=v
}
public asType(Class c) {
if (c == Integer.class)
return val as Integer
if(c == String.class)
return val as String
}
}
This allows something like:
new X(3) as String
to work, but doesn't help with:
3 as X
I probably have to attach/modify the "asType" on String and Integer somehow, but I feel any changes like this should be confined to the "X" class... Can the X class either implement a method like:
X fromObject(object)
or somehow modify the String/Integer class from within X. This seems tough since it won't execute any code in X until X is actually used... what if my first usage of X is "3 as X", will X get a chance to override Integer's asType before Groovy tries to call is?
As you say, it's not going to be easy to change the asType method for Integer to accept X as a new type of transformation (especially without destroying the existing functionality).
The best I can think of is to do:
Integer.metaClass.toX = { -> new X( delegate ) }
And then you can call:
3.toX()
I can't think how 3 as X could be done -- as you say, the other way; new X('3') as Integer is relatively easy.
Actually, you can do this:
// Get a handle on the old `asType` method for Integer
def oldAsType = Integer.metaClass.getMetaMethod( "asType", [Class] as Class[] )
// Then write our own
Integer.metaClass.asType = { Class c ->
if( c == X ) {
new X( delegate )
}
else {
// if it's not an X, call the original
oldAsType.invoke( delegate, c )
}
}
3 as X
This keeps the functionality out of the Integer type, and minimizes scope of the effect (which is good or bad depending on what you're looking for).
This category will apply asType from the Integer side.
class IntegerCategory {
static Object asType(Integer inty, Class c) {
if(c == X) return new X(inty)
else return inty.asType(c)
}
}
use (IntegerCategory) {
(3 as X) instanceof X
}

How should one best recode this example extension method to be generic for all numeric types?

How should one best recode this example extension method to be generic for all numeric types?
public static float clip(this float v, float lo, float hi)
{ return Math.Max(lo, Math.Min(hi, v)); }
Thanks.
// IComparable constraint for numeric types like int and float that implement IComparable
public static T clip<T>(this T v, T lo, T hi) where T : IComparable<T>
{
// Since T implements IComparable, we can use CompareTo
if(v.CompareTo(lo)<0)
v=lo; // make sure v is not too low
if(v.CompareTo(hi)>0)
v=hi; // make sure v is not too high
return v;
}

Resources