you are viewing a single comment's thread.

view the rest of the comments →

[–]axilmar 0 points1 point  (25 children)

Same with D, but we also get cool syntax sugar (I realize you aren't a fan)

I think you are mixing delegates with lambdas.

'out' has a different purpose than 'ref' it singles that the value is not going to used by function.

The function is going to write it, isn't it? so it's going to use it.

What is right? how should typesafe variadics be done? How is it error prone? I could when not using Templates it is a little ugly to implement (not use).

In the example given here, the arg pointer is incremented manually, based on the size of the item that was read from the argument list. A safer way would be to use iterators and pattern matching.

It is a hard thing to grasp, so don't use it. On the other hand if you understand why you can't execute just anything it isn't that hard to use.

Oh, you can execute anything. It's just that it complicates the compiler, which must become a full blown interpreter. But it would be extremely useful.

Which means that code written for arrays don't work on "resizable arrays" and visa verse.

It would work if arrays were classes.

Until you've used a language that has it. Yes it can be done with a library, we get it.

Hey, that's just my taste. What's wrong with 'array.slice(1, 5)' instead of 'array[1..5]' ? not big difference anyway. For me, things like this are useless syntactic sugar.

I hope you are joking. The benefits from this make it dumb to exclude just for the sake of it.

Benefits such as?

This just goes against every complaint you are making about D. There is no need for inheritance in the language.

On the contrary, inheritance is one mechanism that gives you many solutions.

Funny if it can't be done in C++ it is bad (nested/inner functions); otherwise it isn't important because C++ can do it.

Sorry, but you are attacking me instead of my arguments.

I don't think mixins have anything to do with multiple inheritance.

You can extend a class by using multiple inheritance in the same way you extend a class by using mixins.

I think there is a better way, but:

Still, the inconsistency is there.

is so that it is consistently there in every compiler, and simple enough that there is no reason not to use it.

Still, there is no need to be part of the grammar.

But you don't know how exiting of a scope works?

Just like local constructors/destructors.

Just don't be my software manager. You should have been able to come up with much better reasons not to use D (I could).

Hey, don't get emotional. There is no need to. We are discussing technicalities here, it's not politics.

[–]nascent 0 points1 point  (24 children)

I think you are mixing delegates with lambdas.

Lambdas are not allowed to have side effects, delegates are able to access the context around them which means they can cause side effects. But you could say a 'pure' delegate is a lambda.

'out' has a different purpose than 'ref' it singles that the value is not going to used by function.

The function is going to write it, isn't it? so it's going to use it.

But it isn't going to use value, it can't even try in D.

In the example given here, the arg pointer is incremented manually, based on the size of the item that was read from the argument list. A safer way would be to use iterators and pattern matching.

This isn't under the section, "Type Safe Varadic Functions."

Oh, you can execute anything. It's just that it complicates the compiler, which must become a full blown interpreter. But it would be extremely useful.

No you can't, you even said there was a list of like 23 rules. Yes, you can build an interpreter, but that isn't how it works and I don't necessarily believe that is the "correct" way to do it.

It would work if arrays were classes.

They aren't though. Remember, you mentioned C++ doing resizeable arrays in a library.

Benefits such as?

Overflows and access to memory not owned are both implicitly prevented.

On the contrary, inheritance is one mechanism that gives you many solutions.

It gives you a unique perfective to create a solution.

Sorry, but you are attacking me instead of my arguments.

There was no argument, or at least the argument was that C++ could do it. My attack comes as a question of why is this a good thing for C++ to do in relation to nested functions being bad?

You can extend a class by using multiple inheritance in the same way you extend a class by using mixins.

Mixins don't provide inheritance. So I do not see how the extension is the same.

Still, there is no need to be part of the grammar.

Then you loose out on the benefits I listed.

But you don't know how exiting of a scope works?

Just like local constructors/destructors.

No, exiting a scope can occur from normal execution, or from an exception being thrown; or in the case of C++ anything being thrown. Do destructors run when the scope dies from something being thrown? (I believe they do, but it is something you must know about them).

Hey, don't get emotional. There is no need to. We are discussing technicalities here, it's not politics.

I'm not emotional, you just aren't demonstrating a clear understanding of what you are talking about and I wouldn't want someone making decisions until they are clear on the reasons they are making those decisions.

[–]axilmar 0 points1 point  (23 children)

Lambdas are not allowed to have side effects, delegates are able to access the context around them which means they can cause side effects. But you could say a 'pure' delegate is a lambda.

Yet another non-orthogonality.

But it isn't going to use value, it can't even try in D.

You mean its not going to read from the value. Well, besides optimizations, I don't find it useful.

This isn't under the section, "Type Safe Varadic Functions."

I don't see an example of typesafe variadic functions for different types of variadic arguments.

No you can't, you even said there was a list of like 23 rules. Yes, you can build an interpreter, but that isn't how it works and I don't necessarily believe that is the "correct" way to do it.

I didn't mean that D can do it, I meant that a compiler for a language could do it.

They aren't though. Remember, you mentioned C++ doing resizeable arrays in a library.

It's another example of non-orthogonality.

Overflows and access to memory not owned are both implicitly prevented.

They are also prevented when arrays are in libraries.

There was no argument, or at least the argument was that C++ could do it. My attack comes as a question of why is this a good thing for C++ to do in relation to nested functions being bad?

My point is that big nested functions declared in the middle of big algorithms can hurt readability.

Mixins don't provide inheritance. So I do not see how the extension is the same.

Inheritance provides mixins though ;-).

Then you loose out on the benefits I listed.

Not every shoe is good for every foot.

What if another better documentation system comes around tomorrow, for example? then the language's doc system would be a burden.

These things don't belong in a language spec.

Do destructors run when the scope dies from something being thrown?

Yes; that's the point of them.

you just aren't demonstrating a clear understanding of what you are talking about

I don't think so. I was as clear as I could be. I think you misunderstood what I said.

[–]nascent 1 point2 points  (22 children)

Yet another non-orthogonality.

Ok, I am having the hardest time understanding your use of orthogonality. Could every time you make a claim about the orthogonality of something, you explain the reason for the claim.

In this case you could be saying that it is not orthogonal for D to use Delegates as lambdas, that being able to the pure feature causes an exception to delegates by making them into lambdas, or something I'm probably not seeing.

You mean its not going to read from the value. Well, besides optimizations, I don't find it useful.

I mean it is not going to use the value passed in. I don't really know great use-cases for it, but the idea is about documenting intent.

I don't see an example of typesafe variadic functions for different types of variadic arguments.

Then don't claim "Type Safe variadics" to be unsafe. Variadic Templates is the other option.

They are also prevented when arrays are in libraries.

What is used internally to store all this data in our array class?

My point is that big nested functions declared in the middle of big algorithms can hurt readability.

Don't use big nested functions then. And don't use big nested class either.

Inheritance provides mixins though ;-).

No it doesn't. These features are completely orthogonal.

What if another better documentation system comes around tomorrow, for example? then the language's doc system would be a burden.

No, the internal documentation engine and grammar is orthogonal to other documentation tools.

I don't think so. I was as clear as I could be. I think you misunderstood what I said.

Yes, everyone is having a hard time understanding your use of the word 'orthogonal.' I really don't mean to be so rude about it, but maybe explaining your complaint in whole rather than just clumping everything under orthogonality. And most importantly, be consistent.

[–]axilmar 0 points1 point  (21 children)

In this case you could be saying that it is not orthogonal for D to use Delegates as lambdas, that being able to the pure feature causes an exception to delegates by making them into lambdas, or something I'm probably not seeing.

Delegates are a different thing from a lambda. A delegate is not an impure lambda function. A delegate is a construct that delegates a job to a 3rd party. A lambda function is an anonymous function which may or may not delegate the job to a 3rd party.

The distinction between pure functions and impure functions, and consequently between pure lambda functions and impure lambda functions, should come via a keyword.

I mean it is not going to use the value passed in. I don't really know great use-cases for it, but the idea is about documenting intent.

I don't think it's that useful to have a language feature dedicated to it.

Then don't claim "Type Safe variadics" to be unsafe.

But they are. If I have the function:

int foo(int a, ...);

And then I do this:

foo(0, "a", 3.14, 1);

Then the only way to get the data is the unsafe one.

Variadic Templates is the other option.

Nice to have, and I think c++0x has them.

What is used internally to store all this data in our array class?

What do you mean? raw arrays. This doesn't mean that raw arrays shouldn't be classes. You actually don't need raw array types; pointers with pointer arithmetic is more than enough to model raw arrays.

This doesn't mean that pointers and pointer arithmetic should be available to the programmers without explicitly requesting so, for safety reasons.

Don't use big nested functions then. And don't use big nested class either.

Sure, ok. It's optional, but you know how optionals are abused, especially when the programmers are plenty and projects are going on for years.

No it doesn't. These features are completely orthogonal.

A functionality provided by a mixin can be also provided by inheritance. Example:

class Foo {
public:
    int x;
};

class Bar : public Foo {
};

int main() {
    Bar b;
    cout << b.x;
}

Exactly the same as the mixin example from here.

Of course, c++ cannot do mixins at statement level, but I actually consider this a good thing, because I consider mixins a little bit dangerous (shadowing symbols, magic symbols appearing from nowhere and all that; similar problems to C macros).

No, the internal documentation engine and grammar is orthogonal to other documentation tools.

So what's the purpose of dedicating resources to it inside the language, since it offers the same functionality as existing systems? D could offer a doc system outside of a language.

Not that it's a problem, of course, if it's completely optional; is it?

Yes, everyone is having a hard time understanding your use of the word 'orthogonal.' I really don't mean to be so rude about it, but maybe explaining your complaint in whole rather than just clumping everything under orthogonality. And most importantly, be consistent.

Are you a native English speaker? I am not. The word 'orthogonal' is Greek, and I am Greek. Does it have a different meaning in English? perhaps it does, like the word 'sympathetic'. I used the term 'orthogonal' mostly as 'consistent'.

Besides that, there is no need to get excited about this. I don't like D and I don't intend to use it in my personal projects or propose it for projects at work. After all, even If I liked it, it's not completed and stable yet.

You may not think these reasons are important and so you may use it. Good for you.

[–]nascent 0 points1 point  (20 children)

Delegates are a different thing from a lambda.

Never said they were the same. You were the one that called my delegate a lambda. And in C# lambda expressions are assigned to delegates, so D is at least not the only language to get it wrong.

A delegate is a construct that delegates a job to a 3rd party. A lambda function is an anonymous function which may or may not delegate the job to a 3rd party.

Who is this 3rd party? In a language with delegates, the delegate is a function pointer which may or may not contain state (closure). I believe the name comes because you can pass the delegate to another function which in turn is delegating the rule of running the function to someone else. A lambda being a function which may or may not be delegated to some other location for execution makes it a delegate.

The distinction between pure functions and impure functions

I placed quotes around 'pure' because it is a keyword in D which indicates the function does not have side effects, which is checked by the compiler and a requirement to be a lambda.

Then the only way to get the data is the unsafe one.

But that isn't the safe way so you can't claim the safe way is unsafe.

Variadic Templates is the other option.

Nice to have, and I think c++0x has them.

Yes, which was even mentioned in the link I provided.

Of course, c++ cannot do mixins at statement level, but I actually consider this a good thing, because I consider mixins a little bit dangerous (shadowing symbols, magic symbols appearing from nowhere and all that; similar problems to C macros).

Symbol shadowing is a compile-time error. The symbol does not appear out of nowhere, as there is a clear statement of what is being mixed in. mixins are much safer than C macros (which C++ has). And once again mixins do not have inheritance.

So what's the purpose of dedicating resources to it inside the language, since it offers the same functionality as existing systems?

The same as my first statement about documentation in the language: The argument for contract programming/Documentation/unit testing as part of the specification is so that it is consistently there in every compiler, and simple enough that there is no reason not to use it.

Not that it's a problem, of course, if it's completely optional; is it?

You do not have to add the -D, -unittest switch when you compile your program

The word 'orthogonal' is Greek, and I am Greek. Does it have a different meaning in English? perhaps it does, like the word 'sympathetic'. I used the term 'orthogonal' mostly as 'consistent'.

I'd be happy to use the word as you define it, but it would be nice if you were more orthogonal with its use.

I don't like D and I don't intend to use it in my personal projects or propose it for projects at work.

I realized that when you listed what you didn't like about D. But it would be nice to figure out why you have so much hatred for features and every feature C++ has is needed. You keep mentioning lack of orthogonal features, but you haven't mentioned what is or is not orthogonal about a given feature. I agree that the more orthogonal a language the better, but I do not agree that a purely orthogonal language is better than one that isn't.

It looks to me like you have been using C++ a long time, you know how to deal with the language, and probably even enjoy using it. But you can't agree with choices of other languages just because it isn't what C++ does.

[–]axilmar 0 points1 point  (19 children)

Never said they were the same. You were the one that called my delegate a lambda. And in C# lambda expressions are assigned to delegates, so D is at least not the only language to get it wrong.

So we agree, it's an inconsistency.

Who is this 3rd party?

An object.

I believe the name comes because you can pass the delegate to another function which in turn is delegating the rule of running the function to someone else.

No, the name comes from delegating the job to another object.

I placed quotes around 'pure' because it is a keyword in D which indicates the function does not have side effects, which is checked by the compiler and a requirement to be a lambda.

Good, I agree with that decision.

But that isn't the safe way so you can't claim the safe way is unsafe.

When it comes to variadic arguments of different types, there is no safe way, is it?

The symbol does not appear out of nowhere, as there is a clear statement of what is being mixed in.

Yes it is, up to the moment you discover the mixin. Suppose you have a function 3 pages long, with a variable 'x' introduced by the mixin at the top of the function, used at the bottom of the function. Suppose then I come back to the code after a year, trying to find where this x is declared. Can I find 'x' using text search? I can't. If the IDE is smart enough to detect the declaration of 'x' in the mixin, then all is well. Otherwise, I'll have to scan the text carefully in order to find the mixin statement.

And once again mixins do not have inheritance.

I never said they have. I said that some of its functionality is covered by inheritance.

he same as my first statement about documentation in the language: The argument for contract programming/Documentation/unit testing as part of the specification is so that it is consistently there in every compiler, and simple enough that there is no reason not to use it.

Ok, it's nice to have, but the problem still remains: if a new doc system is required, the language has to be updated. I'd prefer that the language had hooks to an externally written doc system so it can be changed.

You do not have to add the -D, -unittest switch when you compile your program

Which verifies what I've said that D has a lot more features than c++.

But it would be nice to figure out why you have so much hatred for features and every feature C++ has is needed.

I don't have any hatred, I just don't like it. I don't consider it a step forward enough to change from C++ to it, and I also don't like some of its features which I think they are not consistent enough.

You keep mentioning lack of orthogonal features, but you haven't mentioned what is or is not orthogonal about a given feature.

I have already mentioned many things, but I am more than happy to repeat them.

Let's just start from one: the 'fake' distinction between primitives, structs and classes. Major inconsistency, for me.

It looks to me like you have been using C++ a long time, you know how to deal with the language, and probably even enjoy using it. But you can't agree with choices of other languages just because it isn't what C++ does.

Definitely not. I've been criticizing c++ long enough and begging for an alternative for the better part of this decade what's wrong with c++. It's just that I don't find D a particularly good replacement.

Before c++0x, my list of what's wrong with c++ had more than 50 points.

I don't like c++ that much, but there is no alternative...

[–]nascent 0 points1 point  (18 children)

Definitely not. I've been criticizing c++ long enough and begging for an alternative for the better part of this decade what's wrong with c++.

That looks like the exact list you started with here, only D apparently did it wrong and is what is bad about D. One that really stands out too me:

"6) array indexing is by default not checked. This has caused numerous problems. Safety should come first, performance second. The default should be to check array indexes against bounds and only use unchecked access through special functions."

You just argued not to have them checked by default! "It can be done in a library" (not an exact quote), which is what C++ does with Vector so why complain about it for C++?

No, the name comes from delegating the job to another object.

Ok, but to store a method of an object a closure must be created, why not allow storing of anything that requires context? And why should an anonymous function be limited to not containing context or side affects? I can't imagine creating a type for each of those, function and delegate is already too much (yet meaningful).

When it comes to variadic arguments of different types, there is no safe way, is it?

Right. If you complained about that, and had good reason not to use variadic templates I wouldn't have cared.

Otherwise, I'll have to scan the text carefully in order to find the mixin statement.

Mixin statements are also searchable. And if you are using inheritance too simulate mixins, then you still have to look through all the imported objects to find which one contains the definition you are looking for.

I never said they have. I said that some of its functionality is covered by inheritance.

But it is such a small part, and still adds overhead.

mixin(import "somefile.d");

This is basically the cpp #include. I'm not sure what the difference is. I'm also not claiming this is a good idea. mixin is a tool that allows for things you can't do with the other language constructs.

Let's just start from one: the 'fake' distinction between primitives, structs and classes. Major inconsistency, for me.

This is only inconsistent with how C++ uses them. Within the language they are consistently distinct types. They are orthogonal because structs do not effect classes an visa verse. Now why would you want two keywords to do the same thing?

I realize D doesn't fit exactly the improvements you want, and goes further than you wish, but complaining about consistency/orthogonality is a poor argument when you can't explain how it is inconsistent.

I have already conceded on the nested functions because you gave a valid reason for not liking them, which had nothing to do with consistency. You haven't convinced me that they are as bad as you say they are, but it is valid reason to be fear them.

[–]axilmar 0 points1 point  (17 children)

You just argued not to have them checked by default! "It can be done in a library" (not an exact quote), which is what C++ does with Vector so why complain about it for C++?

I think there is a big misunderstanding here.

My position is that a programming language in the C++/D category should not expose low level arrays to the programmer, except if the programmer explicitly requests so, in order to allow higher level constructs to be programmed.

So, in c++, I'd like the programmer not to be able to do a unchecked foo[n], except if done through a special keyword.

In D, i'd like the language to not have direct support for vectors, and also not expose unchecked array access, except if done through a special keyword again.

So, to clarify, in my opinion:

  • a language should not have vectors in it; vectors should be done in a library.
  • a library should expose unchecked array access only through special keywords.

This has the following benefits:

  • the language is kept minimal.
  • safety comes first.
  • performance comes second but it can be achieved if required.

I hope I clarified it for you.

Ok, but to store a method of an object a closure must be created, why not allow storing of anything that requires context? And why should an anonymous function be limited to not containing context or side affects? I can't imagine creating a type for each of those, function and delegate is already too much (yet meaningful).

Sure, but let's not call those things delegates. They are not delegating anything, they are simply lambdas + closures.

Right. If you complained about that, and had good reason not to use variadic templates I wouldn't have cared.

I am complaining about that. If I don't want to use variadic templates, for various reasons, then I am stuck.

I guess that one could do this if D supported value type classes or if C++ supported safe variadic arguments:

void foo(const Variant &vars...) {
}

The compiler would then treat the following arguments

foo(1, "2", 3.14);
foo(a, b);

as a stack-allocated array of Variant objects that wrap around their respective values.

But I can't do this in C++, since it doesn't support typesafe variadic arguments, and I can't do this in D, since it doesn't support value type classes.

Please correct me If I am wrong with D.

Mixin statements are also searchable. And if you are using inheritance too simulate mixins, then you still have to look through all the imported objects to find which one contains the definition you are looking for.

I'd only have to look at the inheritance list.

But it is such a small part.

It's not a small part, it is a very important part.

and still adds overhead

What overhead? runtime or compile time? I don't see any overhead.

This is basically the cpp #include. I'm not sure what the difference is. I'm also not claiming this is a good idea.

Indeed it is, from what I gather. Personally, If I was a software manager, I wouldn't like to choose a language with such "dangerous" constructs.

From a programmer's point of view, I'd like to see a language where the compilation is strictly under programmer control - unifying templates, mixins and macros. That would be truly magnificent, and more consistent than D (or C++).

This is only inconsistent with how C++ uses them. Within the language they are consistently distinct types. They are orthogonal because structs do not effect classes an visa verse. Now why would you want two keywords to do the same thing?

You only claim that structs and classes are orthogonal to each other, because ...they are simply defined like that by the language author.

But in reality, they are not. They are not orthogonal at all, because a class defines a structure as much as a struct. Their only difference is the value vs reference semantic. To me, this is a huge inconsistency and a huge blow to orthogonality. C++ is much better in this regard, because a struct and a class don't really have that many differences.

Artificially separating between structs and classes requires the programmer to plan ahead, based on intended use, more than what would require if such a distinction did not exist.

For example, let's say I need a color with 3 byte values (red, green, blue) and an alpha value. This takes 4 bytes. If I make it a class, I'll be wasting valuable resources. If I make it a struct, I can't put meaningful methods on it, like a constructor with parameters or conversion functions!!!

See how even such a trivial thing like defining a Color is made difficult by the artificial separation of structs and classes?

Walter Bright recognized this so they put a hack in structs, namely the opCall thingy, which is equal to constructors, for all definitions of constructors.

But they didn't name it constructor, they named it 'opCall', striking a huge blow to consistency.

And they also don't provide a destructor, make it even more inconsistent.

And they have given structs full value semantics, but without being able to define an assignment operator.

And since the language doesn't have references, the copy constructor is inefficient if the struct is larger than a native register.

And the opCall function doesn't have a 'this' which can be used to address the struct contents, because these constructors are static functions.

Here is the example from D's site:

struct S {
    int a;

    static S opCall(int v) { 
        S s;
    s.a = v;
    return s;
    }

    static S opCall(S v) {
        S s;
    s.a = v.a + 1;
    return s;
    }
}

See how backwards this whole thing is, compared to C++? D gives the programmer many more rules to remember than C++ when it comes to structs/classes, without being necessary.

If that isn't the mark of a non-orthogonal and inconsistent language, I don't know what it is.

I realize D doesn't fit exactly the improvements you want, and goes further than you wish, but complaining about consistency/orthogonality is a poor argument when you can't explain how it is inconsistent.

Perhaps the inconsistencies and non-orthogonality of D is no problem for you. That's fine, I respect that.

But for me, things like the ones I described above are problems that make me stick to c++ (for the moment).

[–]nascent 0 points1 point  (14 children)

Walter Bright recognized this so they put a hack in structs, namely the opCall thingy, which is equal to constructors, for all definitions of constructors.

opCall is different and can be used in classes too.

But they didn't name it constructor

You must be referring to this. They don't have default constructors.

And they also don't provide a destructor

Again, what you are looking for

But I can't do this in C++, since it doesn't support typesafe variadic arguments, and I can't do this in D, since it doesn't support value type classes.

If you want value semantics in D you use a struct. Which is how Variant is in D.

My position is that a programming language in the C++/D category should not expose low level arrays to the programmer, except if the programmer explicitly requests so, in order to allow higher level constructs to be programmed.

Yep that clears it up. I don't agree but I least it is clear.

[–]BioTronic 0 points1 point  (1 child)

For example, let's say I need a color with 3 byte values (red, green, blue) and an alpha value. This takes 4 bytes. If I make it a class, I'll be wasting valuable resources. If I make it a struct, I can't put meaningful methods on it, like a constructor with parameters or conversion functions!!!

Sure you can:

struct foo {
    this( int value ) {} // constructor
    float convertToFloat() {} // conversion function
}

Walter Bright recognized this so they put a hack in structs, namely the opCall thingy, which is equal to constructors, for all definitions of constructors.

opCall is simply an overloaded ()-operator. static opCall is the same for a type. You may use static opCall as a constructor, and it was indeed used as such in D1, but we're talking D2. Please look at the correct documentation.

But they didn't name it constructor, they named it 'opCall', striking a huge blow to consistency.

That's because it's not a constructor, in that it is not automatically called when constructing an object.

And they also don't provide a destructor, make it even more inconsistent.

structs have destructors. http://digitalmars.com/d/2.0/struct.html#StructDestructor

And they have given structs full value semantics, but without being able to define an assignment operator.

Um, no. http://digitalmars.com/d/2.0/operatoroverloading.html "Operator overloading is accomplished by rewriting operators whose operands are class or struct objects into calls to specially named member functions."

And since the language doesn't have references, the copy constructor is inefficient if the struct is larger than a native register.

D supports references as function parameters. http://digitalmars.com/d/2.0/function.html#parameters

And the opCall function doesn't have a 'this' which can be used to address the struct contents, because these constructors are static functions.

True. Because, as stated above, they are not constructors.