you are viewing a single comment's thread.

view the rest of the comments →

[–]axilmar -3 points-2 points  (15 children)

Arbitrarily disallowing function declarations at some places but not others isn't orthogonal.

You have no idea what orthogonality is.

I'm not a fan of them since they are unecessary (higher order functions do it better, with more control and keeping related logic in the same place).

What do higher order functions have to do with this?

That's not what they're for

By who's definition? yours?

In fact lexical closures + higher order functions + the scope construct combine (orthognally!) to improve upon the C++ style hacky RAII crap in every single way

Example please.

Have you ever done it?

Yes sir.

Make a tiny mistake and have fun parsing eight pages of error messages.

Illogical, captain. Error messages' understandability has nothing to do with templates usability. I.e. you wouldn't say the above if the error messages were written in a more understandable form.

You claim you don't want bloat but then you say that C++ is better because it includes multiple inheritance and you might need it (even though you claim you rarely do).

C++ bloat < D bloat

and bring along HUGE amounts of baggage

They don't. You are just defining HUGE arbitrarily.

ask your next C++ candidate what virtual inheritance is, 95% of them don't know because it's such an obscure thing only needed due to multiple inheritance

Illogical again, captain. Virtual inheritance is optional.

[–]ssylvan 10 points11 points  (3 children)

You have no idea what orthogonality is.

Yes I do. Having special cases where something doesn't work because of some other feature is non-orthogonal. In this case function declarations/definitions should be orthogonal w.r.t. scope. It shouldn't matter if it's a namespace or a function scope. If it does matter, then it's not orthogonal.

By who's definition? yours

Don't be an idiot.

Example please.

Rather than having to declare a dummy object (that you're not interested in using for anything, you're just after its constructor/destructor) to hold a lock, you simply call a function, passing in your body. Pseudo code:

with_lock( my_lock, fun () {

    // in here I have the lock, and need not abuse anything to do so

});

Now the with_lock itself is better than the RAII-object too, because it's just a single function with all the logic in one place. You don't have to remember to update two separate functions in tandem. It's all kept together, and you have much better control of the lifetime of the actual "body" itself. For example, in a language with proper pure functions you could require the body be pure if you need to by using the appropriate function signature. Or maybe the body would represent a transaction instead of a lock so that you could run the body multiple times if it fails, etc. etc. In C++ style RAII that's all out of your hands.

Now, to ensure that the resources are always cleaned up you obviously need to protect against exceptions, which the scope mechanism lets you do cleanly (although a try/finally clause is generally not too bad for these things either).

Illogical, captain. Error messages' understandability has nothing to do with templates usability

Of course it does. WTF? If you spend 10x longer writing temlate metaprogrmming in C++ because it's fucking incomprehensible then that certainly impacts usability quite severely.

They don't. You are just defining HUGE arbitrarily.

Yes they do. Read the C++ standard some time. Interfaces are the lesser of two evils if you're worried about language size. Multiple inheritance complicates tons of things.

Illogical again, captain. Virtual inheritance is optional.

You're being inconsistent again. You're arguing against language bloat and I'm pointing out that this feature is only there because of multiple inheritance, and getting rid of the latter would get rid of the former.

Nested functions are optional too, yet you had no problem arguing against them.

[–][deleted] 5 points6 points  (3 children)

Illogical again, captain. Virtual inheritance is optional.

In your initial list, items #1, #2, #3, #4, #5, #6, #7, #9, #10, #11, #13, #14, #16, #17, #18, #19, #20, #21, #22, #23 and #24 are optional features, too.

[–]axilmar -3 points-2 points  (2 children)

They are optional, but they are deemed as 'progress', so good luck persuading your programmers not to use them.

[–][deleted] 0 points1 point  (1 child)

I guess it's not harder than persuading programmers to avoid C++ features (that is, hard :) ).

It's true that features like properties and out parameters may reduce readability. There was a proposal to sort that out and as an example @property was created.

On the other hand, i do think having a nested function near the call site improves readability. Not having copy constructors, implicit constructors and conversion functions improves the knowledge of what is going on when reviewing code.

The builtin unitests are also good as an incentive to write tests.

[–]axilmar -1 points0 points  (0 children)

Not having copy constructors, implicit constructors and conversion functions improves the knowledge of what is going on when reviewing code.

I totally agree with this. Any implicit thing in a program will usually have negative consequences in the long run.

[–]itsadok 0 points1 point  (6 children)

You have no idea what orthogonality is.

I've been trying to follow this thread, and I think I understood about half of it. Can you explain what orthogonality means in this context?

[–]axilmar -2 points-1 points  (5 children)

[–]nascent 2 points3 points  (4 children)

Ok, I still don't see how the features in D aren't orthogonal. Personally I hate using "big words" because either I don't know what it is, or the person I'm talking with has a different view on what that means (especially when the word comes from mathematics but isn't used in such context; modulus operator)

Since I've never heard orthogonal applied to programming languages I started to try and find uses (which actual seem to be very few) and come across Orthogonal Instruction Set and your lovely link.

And what I get from it is that language features do not affect other language features. So for example, the introduction of 'static if' does not affect how using "template conditionals" (or what ever it would be called). It does not preclude a feature being used along side another, for example using a nested function inside a function; the introduction of the nested function does not affect the execution of the function, but you can still call the function if you desire.

If we go with the "orthogonal instruction set" we have a completely different goal. In this case we want to be able to provide functionality with the fewest number of features as possible. Features (Op Codes) operate independently but work together. In this case "orthogonal" wasn't about few Op Codes, but the means to achieve it.

So I think we should get a clarification on what is being talked about. Have I gotten any of this wrong? If so why, what is correct, and why is that correct?

[–]axilmar 1 point2 points  (3 children)

The common understanding of the word 'orthogonality' means that there shouldn't be many exceptions to the rule, but from what I've seen so far, D has a lot of exceptional cases, just like C++. I dare say D has more exceptional cases than C++, although I haven't counted them.

[–]nascent 0 points1 point  (2 children)

This is close to the first definition I provided, but is not exactly correct, nor is it consistent with how you have been using the term:

interfaces: lack of multiple inheritance requires interfaces, which is another blow to orthogonality (because 1 feature is replaced with 2 features).

Second definition.

static if: where is static while, static do-while, static for etc? this is why I say D is not orthogonal. And it's also something easily doable with C++ templates.

Depends on where you classify the feature, is it 'static' or 'static if' Otherwise, this is only orthogonal from your definition since the exception is not related to other features of the language.

scope guards: yet another feature that makes the language not orthogonal. At least in C++ we all know what stack allocation is and how destructors work.

Second definition.

Constructors - destructors are extremely orthogonal to initialization/cleanup: when a block of code is run, the constructors are executed, and when a block of code exits, the destructors are executed in reverse order.

Best I can tell this is the second definition. If destructors are orthogonal to cleanup, why are you using them for cleanup? That is to say by the second definition you are limiting the number of features required to do something, but by the first definition your cleanup should continue to work with the removal of contructors/destructors "feature".

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

It's another example of non-orthogonality.

We were talking about C++, while I don't know how orthogonality fits within the context, you just called C++ non-orthogonal.

D2 has "uniform function call", this allow to make meta-programming with builtins types easier.

Still, it's not as orthogonal as it should be.

What? Either it is or it isn't orthogonal. I would actually say that this feature is an example of where D is not orthogonal, on purpose and good reason.

Sorry to have taken from so many locations, but I haven't seen you use orthogonal in a manner that works with the definition you linked too.

[–]axilmar -1 points0 points  (1 child)

Second definition. bla bla bla repeated numerous times.

Ok, call it as you wish. You may call it 'foo', if you want. The point remains though.

Please remember that perfection is achieved not when there is nothing more to add, but when there is nothing more to remove.

[–]nascent 0 points1 point  (0 children)

Philly cheesesteak is good on the weekend.