Safer casts

Yigal Chripun yigal100 at gmail.com
Mon May 12 16:01:57 PDT 2008


Please read my response to Bill.
Dee Girl wrote:
> Yigal Chripun Wrote:
> 
>> my issues with the use of this syntax: a) what if I had a typo?
> 
> algorithm.d(2528): Error: binaryFun(ElementType1,ElementType2) is not
> an lvalue algorithm.d(2528): static assert  "void*"
> 
> Maybe the static assert message should be better. What if it says:
> Your comparison function is invalid?

But it doesn't. also, the file name and line number are wrong. that IS
one of my problems with this.

> 
>> what if i typed n instead of b (they are next to each other on my
>> keyboard)?
> 
> Same message is written.

again, The error I get points me to the wrong place with the wrong error.

> 
>> your solution or any other string solution cannot check this, since
>> it is syntactically valid D code inside the string. b) if I want to
>> compare q{a.member > b.member} there is no check that member
>> exists, or any other type checking. the error would occur in the 
>> template code itself not in the string in both of the above
>> examples.
> 
> Same message is written again.

should I repeat the above, again?
> 
>> c) what if I forgot to type the "q"?
> 
> ../test.d(9): found '}' when expecting ';' following 'statement'
> 
> At least now it is in your file ^_^

oh, god! finally! (that's my inner atheist talking ;) )
and yet, I still need to type that q which is meaningless to me.
> 
>> d) most IDEs mark strings with a different color or something like
>> that so I treat them automatically as data and not code. ( this is
>> a minor issue, since IDEs could be made to work differently. but,
>> my sub-conscience response to strings as "not code" is harder to
>> fix)
> 
> The strings are short otherwise they anyway are better as functions.
> I do not think this could be a problem.
> 
>> the only benefit to this is a slight performance benefit (though a
>> good compiler could provide the same performance by inlining a
>> function call) and a slightly shorter syntax which is a personal
>> preference since you type less but IMHO it becomes less readable
>> and less obvious.
> 
> I think it is very readable and obvious for reasons below.
> 
>> I prefer: sort!((int a, int b) {return a.member >
>> b.member;})(array); this is more typing but provides all the checks
>> and is more readable.
> 
> It is nice you can do both. You can put a string when it is small.
> You double the size of the code to write. When you have long
> comparison, you make it separate function. What I think is best of D
> when coming from other languages is that it gives so much options in
> such small core.

code is read 100 times more then it's written you need to type more
"once" but I get to read it many times.

> 
>> Think of the poor guy that will need to do maintenance on your code
>>  years from now. now the string is a cool quick'n'dirty solution to
>> the problem at hand but in the future that other programmer will
>> have no idea what those "a" and "b" are. especially since you
>> didn't write the types of them.
> 
> Here you may be wrong two times. First I tell from experience. I
> worked internship for a biotech company in Boston. I thought it will
> be research but it was so much work! ^_^ They used Perl and I did not
> know Perl when I began. But then I learned it and it has many nice
> things. One is sort which looks like this
> 
> sort { $a <=> $b } array;
> 
> I remember: first time I saw sort I understood how it works. The only
> odd thing was <=> but that means -1, 0 or 1 if a is less, equal or
> greater than b. I thought Perl has the most elegant definition of
> sort but now I think D has it.

personally, I dislike Perl. You think that the above example is
elegant?! in what way does the above make it obvious that array is
sorted in ascending order?? <=> look to me as the mathematical sign for
"if and only if" (iff, i think is the short form) which doesn't mean
anything regarding sort order. in what way does it make clear that the
sort here is a function call applied to array? this is the opposite of
readable to me.

> 
> Second you may be wrong because you think types help. They do not
> help in fact they may un-help. Write this
> 
> long array[] = ...; sort!((int a, int b) {return a > b;})(array);
> 
> Sadly D lets long -> int conversion go through. Code will compile and
> run! But it gives wrong results for big numbers.
> 
So a bug in DMD makes me wrong? That's a compiler bug that needs to be
fixed. the only thing your example here shows is that DMD has bugs. on
the other hand I can give simple example where types do help:
class A { int member();}
class B { int member(); int value;}
sort!(q{a.member > b.member})(array);
if i change element type from A to B the string will compile. what if
those classes are unrelated and the member functions do completely
different things, that's just a coincidence they have the same name.
when i changed to B i wanted to sort by value instead. but i could miss
one of the calls to sort and the compiler will not yell at me with the
string solution, thus i've introduced a search-and replace bug (i didn't
replace all the instances, by mistake)
a proper function will produce an error since the type of the elements
is not the same at the elements in the array.

> For sort type deduction is best. You should write
> 
> sort!((auto a, auto b) {return a > b;})(array);
> 
> And that works with int, long, float, string and all types that have
> >. It is the best writing of the intent of the sort. But I do not
> know how much type inference the D compiler can do.
That's an interesting idea, I don't know how much work does it take to
implement this, but it worth discussing in a different thread. also, you
can define a templated delegate:
bool comp!(T)(T a, T b) {return a > b;}
sort!(comp)(array);
however, I'd imagine that those either need to be already provided in
the standard library,or there should be a default way for sorting:
so, for regular ascending sort:
array.sort; // no need to provide comperator.
actually, I'd want sort to have another parameter to define
ascending/descending sort (bool or enum or something like that).
the idea is making the common case the simplest so if you just need a
regular sort, just call array.sort and it'll do the right thing. you
only need to actually provide a comperator if you're not doing a regular
 sort. and in that case, I'd prefer a function/delegate so the compiler
could check that my class does have the members I'm comparing and give
me the right error.
> 
>> also the performance could be the same if I used a function instead
>> of a delegate allowing the compiler to inline it (hopefully).
> 
> Good abstraction is the best. Performance is a good bonus ^_^
> 

Agreed.
"first make sure the program is correct, then make sure it's fast"

>> since this is identical to: sort(array, (int a, int b) {return
>> a.member > b.member;}); there is no benefit in making it a
>> template, IMO.
> 
> I hoped I convinced you otherwise. After all effort still no
> understanding? Templates are best. They give you static and dynamic.
> Dynamic only gives dynamic.

take a delegate, and you'll see that both solutions are identical. if
you want static, provide a function instead of a delegate. It's a
standard practice to overload functions and provide a version for both.
(or wrapping it in a new type that handles this internally).
there is a function call here in any case, template or no template. the
compiler can inline a static function call if it's suitable (short).
this is possible in both ways.


> 
>> side note: using a feature of arrays in D this could be also
>> rewritten as: array.sort((int a, int b) {return a.member >
>> b.member;});
> 
> Would be nice to allow array.sort!(cmp).
> 
>> Again, this is only my opinion (and I do prefer higher level
>> solutions and think the compler/linker can do a better job
>> optimizing than I can). you do not have to agree with this view,
>> and there are already people that disagree.
> 
> Different views of same issues is good. But I see there are some
> things about which you are simply wrong because you do not understand
> how they work. Then I waste time explaining ^_^ Thank you, Dee Girl
> 
since there are language issues involved here (both of us are not native
English speakers) I'll ignore the implied insult in that you waste time
on this discussion with me (you choose to answer, you know...). I try
not to insult people, please try and do the same.
besides, had it occurred to you that maybe, you didn't understand what I
was saying, either because of my explanation which is not clear enough,
or cause you didn't understand it?
there are two things we discuss here, one of which is personal
preference regarding syntax. In what way am I wrong that I like typing
one and not the other? it's not a right vs. wrong issue but a Yigal's
preferred style vs Janice's and Dee's preferred style.
I prefer mine because I like to think it's more consistent from an
end-users point of view. even if it is indeed implemented with templates
under the hood.
with my syntax, I just use array, then a dot and than the behavior I
want to get.
i.e. -
array.sort; //same as array.sort(ASC);
array.sort(DESC);
array.sort(someStaticComperator);
array.sort(aDelegateComperator);
array.someOtherfunction(params);
//and also
List.sort;
someOtherCollection.sort;
int.sort; //compile time error, no sort method for int
etc...
I know my examples are lame (Janice is much better than me in explaining
stuff). I hope you see now, what I mean by a consistent API.
this is what I think the end user would prefer.
what is wrong with the above, in your opinion?



More information about the Digitalmars-d mailing list