May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | BCS Wrote: > Reply to Dee, > > > Yigal Chripun Wrote: > > > >> Dee Girl wrote: > >> > >>> I agree! Strings and aliases are much less powerful than delegates > >>> and closures because they are static and can not have state. > >>> But I am confused about something. I compiled this with phobos: > >>> sort!(function bool(int a, int b) { return a > b; })(array); > >>> > >>> There is clear difference in syntax from your examples. But my question is: what are the differences in semantics? Thank you, Dee Girl > >>> > >> I'm not sure what exactly are you asking. are you asking what's the difference between a delegate and a function? > >> > > Please let me rephrase. What is the difference between a function passed as an alias, and a delegate? You hate one and you like the other so the difference must be big. But I do not find it. Thank you, Dee Girl > > > > a function is just a free function or a static class function or the like. A delegate is both a function and a context. Generally the context is another function's scope or an object or struct. Sorry I do not know how to express myself. It is frustrating ^_^. I understand what a function is. But it looks to me as when a function is passed to a template weird things happen. I have compiled and run successfully this program: #!/home/yasuko/bin/compile-launch -w import std.stdio; import std.algorithm; void main() { int[] array = [ 1, 2, 3, 4 ]; int x = 5; bool comp(int a, int b) { return a + x > b + x; } sort!(comp)(array); writeln(array); sort(array); writeln(array); test(&comp); writeln(array); } void test(bool delegate(int, int) dg) { int[] array = [ 1, 2, 3, 4 ]; sort!(dg)(array); } There are many interesting things about above program. Function comp accesses a variable in its enclosing scope therefore it can not be a "simple" function. However sort works with it. Then even more interesting. I pass the function as a delegate to another function. Here sort works again even when passed the delegate! So I see no difference between passing the delegate as a template alias or as a normal parameter. But I do not understand how the compiler can generate the code for the dynamic case. Dee Girl |
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dee Girl | Your example does use delegates. the difference is this: say you have two delegates you pass to sort, for example you sort one array in ascending order, and another in descending order. the template solution will generate two almost identical sort functions with the only difference that one sort instance calls internally the first delegate, and the second instance calls the second. you get 4 functions. without the template, you get one sort function and two delegates, so only 3 functions. Now, when you use a string with the template, the sort will contain the code itself inline to the sort instance so it "saves" you a function call. IMO, the string solution is not clean ( C MACROs? )and while for simple cases it could save you a function call it's premature optimization IMO. Also, if I use delegates, I can't see how a template can save that function call. so it just bloats my executable with unneeded copies of sort. I hate when library code forces me to this. I think the programmer knows his code better than the library writer and should be able to choose himself whether he needs to use a compile time solution to save function calls or a run-time solution to prevent unnecessary executable bloat. this optimization should be made by the programmer and _not_ the library writer. This solution does not give me that freedom. this solution is a classic STL piece of code, BUT, the main difference is that for C++ this is probably the only reasonable solution as C++ doesn't have delegates. this is why when coding for D I urge people to rethink their solution instead of just doing what is best in C++ (or any other preferred language of the library writer). This is a prime example why the C++ solution is wrong for D. --Yigal |
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | On 11/05/2008, Yigal Chripun <yigal100@gmail.com> wrote:
> BUT, the main difference
> is that for C++ this is probably the only reasonable solution as C++
> doesn't have delegates.
C++ has functors (classes which overload operator ()), and they're a
bit like delgates. What C++ doesn't have is alias template parameters,
nor string template parameters.
sort!("a.member > b.member")(array)
simply couldn't be done in C++. This is /not/ a C++ solution. It's a D solution, and a fantastically brilliant one.
Perhaps what you mean when you say "C++ solution", is, "it uses templates"?
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | On Sun, 11 May 2008 13:18:33 +0400, Janice Caron <caron800@googlemail.com> wrote:
> sort!("a.member > b.member")(array)
I like this one, too. It's very simple, efficent and clean.
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron wrote:
> On 11/05/2008, Yigal Chripun <yigal100@gmail.com> wrote:
>> BUT, the main difference
>> is that for C++ this is probably the only reasonable solution as C++
>> doesn't have delegates.
>
> C++ has functors (classes which overload operator ()), and they're a
> bit like delgates. What C++ doesn't have is alias template parameters,
> nor string template parameters.
>
> sort!("a.member > b.member")(array)
>
> simply couldn't be done in C++. This is /not/ a C++ solution. It's a D solution, and a fantastically brilliant one.
>
> Perhaps what you mean when you say "C++ solution", is, "it uses templates"?
it mis-uses templates, as I said in my previous post. it's the same C++ mind set. the only difference is that it utilizes more D++ features to accomplish the same thing.
Personally, I prefer a smalltalk like collections framework over the c++ generic templates solution. it makes so much more sense to me to have a orderedCollection interface which defines a sort method, than a c++ generic sort template.
It makes more sense to me to write:
array.sort(); or array.sort(aDelegate);
instead of using:
sort(array); or sort(array, aDelegate); or even worse:
sort!(aDelegate)(array);
C++ avoids using real OOP encapsulation since it perceives it as adding unnecessary overhead. this is plain wrong since the overhead is orthogonal to the design principles. This is why C++ is adding the notion of concepts (which facilitate compile time OOP) to the next standard.
--Yigal
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Koroskin Denis | Koroskin Denis wrote:
> On Sun, 11 May 2008 13:18:33 +0400, Janice Caron <caron800@googlemail.com> wrote:
>
>> sort!("a.member > b.member")(array)
>
> I like this one, too. It's very simple, efficent and clean.
In what way is that clean? How is that different from a C macro?
if you have a typo: "a.member > b.membr" the compiler won't check it at
the place you wrote it, since it's just a string. the compiler will
probably complain about the library code instead. (I haven't tried that
on actual code, though).
Now there is a way to tell the compiler to validate the content of
strings with q"here goes a valid D code snippet" (if i remember
correctly), but that requires me to not forget that q.
all in all, all those string manipulations, although powerful, are quite
dangerous, IMO.
also, what if a doesn't actually have a "member" member? this is still
syntactically valid D code, but again I think the error would be
reported elsewhere.
--Yigal
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | Janice Caron Wrote:
> sort!("a.member > b.member")(array)
>
> simply couldn't be done in C++. This is /not/ a C++ solution. It's a D solution, and a fantastically brilliant one.
does it have any use?
Maybe implementing LINQ will be much more powerful and readable?
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | On 11/05/2008, Yigal Chripun <yigal100@gmail.com> wrote: > Personally, I prefer <snip> By your own words, that's just a personal preference. > It makes more sense to me to write: > array.sort(); or array.sort(aDelegate); > instead of using: > sort(array); or sort(array, aDelegate); or even worse: > sort!(aDelegate)(array); But now you're just saying "my syntax is better than your syntax", when both do the same thing. In addition, the D version is more powerful, as it allows you to say: sort!(f)(array) where f is a function (not a delegate). It also allows you to write sort!(dg, SwapStrategy.stable)(array) to get a stable sort instead of a non-stable (but faster) sort. This kind of flexibility offers way more power than delegates alone. Besides which, arrays cannot implement an orderedCollection interface, because arrays cannot implement interfaces, so you'd be limited only to sorting custom collection classes. > This is why C++ is adding the > notion of concepts (which facilitate compile time OOP) So is D. Shall we take bets on which language gets them first, or in which language they will be most powerful? |
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Yigal Chripun | On 11/05/2008, Yigal Chripun <yigal100@gmail.com> wrote:
> also, what if a doesn't actually have a "member" member? this is still
> syntactically valid D code, but again I think the error would be
> reported elsewhere.
On that point, I concede. The reporting of template errors could certainly be improved. More than once I have wanted to see the "stack trace" of errors, working back from the innermost, to the line of code that ultimately triggered it.
However, that it not an argument against templates, it is an argument for improved error reporting. And hopefully, one day we'll get that.
This is not the first time that you've argued that some feature or strategy is bad because today's D compiler isn't good enough, but you need to remember that tomorrow's D compiler will be better. That's life on the cutting edge.
|
May 11, 2008 Re: Safer casts | ||||
---|---|---|---|---|
| ||||
Posted in reply to Janice Caron | On Sat, 10 May 2008 07:59:23 +0200, Janice Caron <caron800@googlemail.com> wrote: > 1) convert or downcast: cast(Foo)bar > 2) reinterpret: cast!(Foo)bar > 3) constancy: cast(invariant)bar, cast(!const)bar For 3), what if I want to cast const(int*) to const(int)*? cast(const(int)*)cast(!const)foo? -- Simen |
Copyright © 1999-2021 by the D Language Foundation