Which language is the least bad?


  • Notification Spam Recipient

    @gąska said in Which language is the least bad?:

    assumed people

    First mistake yadda yadda....



  • @gąska said in Which language is the least bad?:

    ...or maybe he just doesn't realize that every programmer has stacks of post-it notes everywhere on their desks because they can't write code efficiently without them.

    Maybe; but that doesn't mean you can just dismiss the idea of cognitive load. Small, straightforward languages are easier to keep in your head than large languages with lots of surprising behavior.



  • @blakeyrat said in Which language is the least bad?:

    @gąska said in Which language is the least bad?:

    ...or maybe he just doesn't realize that every programmer has stacks of post-it notes everywhere on their desks because they can't write code efficiently without them.

    Maybe; but that doesn't mean you can just dismiss the idea of cognitive load. Small, straightforward languages are easier to keep in your head than large languages with lots of surprising behavior.

    I see, and when did you plan on switching to Forth, then?

    Filed Under: OK, so that was a cheap shot. Mea Culpa.


  • Considered Harmful

    @gąska said in Which language is the least bad?:

    No I think I've been wrong in at least one case.

    SpectateSwamp?


  • Considered Harmful

    Also, just throwing this out there: I have yet to see a problem or application C++ is better suited to than Rust.


  • Banned

    @blakeyrat said in Which language is the least bad?:

    Small, straightforward languages are easier to keep in your head than large languages with lots of surprising behavior.

    Small, straightforward languages rarely stand up to challenges of modern software development. Of course you should strive for as much ease of use in every product you make, languages included - and C++ is bloated, overcomplicated mess that makes you lose will to live. But it's not impossible to deal with. It's definitely harder than other languages, but not by that much. I used to have a teammate who was a former stage sound technician, and his only programming experience was three-month crash course sponsored by city council and my company, and after a year of working in our team, he's been doing alright. Didn't have enough knowledge to make good designs, but implementation wasn't a problem for him.

    C++ seems extremely hard mostly to people who already know Java/C#/Javascript/Python, and compare learning the language to using what they already know. Likewise, most people who say C++ is better than Java/C#/Javascript/Python are people who try writing in those languages exactly like they would write in C++, because they never bothered to learn how to do things the proper (for a given language) way. I'm sure whatever @Evo was doing with virtual inheritance, he could do with C#'s interfaces just as easy, if not easier.


  • Banned

    @pie_flavor said in Which language is the least bad?:

    Also, just throwing this out there: I have yet to see a problem or application C++ is better suited to than Rust.

    GUI


  • Discourse touched me in a no-no place

    @blakeyrat said in Which language is the least bad?:

    with templates having the added bonus of the error reporting being absolutely shit

    Hey, with clang the error reporting with templates is usually just poor and not absolutely shit.

    Unless you get a language standard library API/ABI version mixup, when the errors make absolutely no sense at all…


  • Banned

    @dkf said in Which language is the least bad?:

    Unless you get a language standard library API/ABI version mixup, when the errors make absolutely no sense at all…

    Linker errors are the most straightforward C++ errors of all.


  • Considered Harmful

    @gąska said in Which language is the least bad?:

    @pie_flavor said in Which language is the least bad?:

    Also, just throwing this out there: I have yet to see a problem or application C++ is better suited to than Rust.

    GUI

    And why's that?


  • Banned

    @pie_flavor all GUI libraries in existence are built entirely around the Javaesque OOP fields-and-implementation inheritance. In Rust, fields-and-implementation inheritance is unavailable, and emulating it using other language features is between impossible and borderline obnoxious. To do GUI right in Rust a brand new GUI library using brand new paradigm must be made - and so far there hasn't been, and I haven't seen any promising projects (the best so far is gtk-rs, which is a more annoying wrapper for already extremely annoying GTK).

    I think the way to go is have GUI written in some other language and only use Rust for backend. When I finally have some free time, I might start a project to get some popular GUI to bind easily to Rust code using MVVM or similar pattern.


  • Considered Harmful

    @gąska Structs may not be able to extend other structs, but traits can extend other traits, and fat pointers let you do dynamic dispatch.
    Also, conrod.


  • Banned

    @pie_flavor traits can't extend traits that already extend traits (if A: B and B: C and C defines foo(), you cannot make A::foo() do B::foo()) - because this requires full-fledged specialization which is still WIP. Also, what good are trait functions if you can't access fields? About conrod, IMGUI doesn't scale well to huge ass corporate behemoths of applications with millions of LOC.


  • Discourse touched me in a no-no place

    @gąska said in Which language is the least bad?:

    C++ seems extremely hard mostly to people who already know Java/C#/Javascript/Python, and compare learning the language to using what they already know.

    C++ has more twiddly features than most other languages (excluding standard libraries from this discussion) and that makes for some serious complexity. It's not too bad to use if you're able to just swim about on the surface, if the libraries you are using are written to be comparatively nice, but the potential for trouble when you go deep is much greater than I like in a language.

    Professionally, the ABI/API thing I talked about earlier is also a killer, and there's bits and pieces of the language runtime library that are quite expensive in terms of code-space. (Fortunately, this is a known issue: compilers for embedded targets allow you to disable exceptions and RTTI.)


  • Discourse touched me in a no-no place

    @gąska said in Which language is the least bad?:

    Linker errors are the most straightforward C++ errors of all.

    Yes. Unfortunately, they didn't manifest that way. I really forget the details now, but the errors were far more gnostic than that.



  • @barbaz said in Which language is the least bad?:

    PHP has two main issues: it lets people who shouldn't touch a keyboard write code, and it was designed by committee who shouldn't touch a keyboard, especially not to write code.

    Answering the question in general, there aren't bad languages other than PHP, only it might not be best suited for the task at hand.

    FTFY

    And JavaScript. Don't forget about JavaScript. A language, where the months and days are 0-based, but years aren't. (Also new Date(1970,0,0) is 31st Dec 1969. WTF?)


  • 🚽 Regular

    @hans_mueller said in Which language is the least bad?:

    A language, where the months and days are 0-based, but years aren't.

    "Days" here being days of the week (starting Sunday). "Dates", or days of the month, start at 1.


  • Discourse touched me in a no-no place

    @hans_mueller said in Which language is the least bad?:

    (Also new Date(1970,0,0) is 31st Dec 1969. WTF?)

    Days (of the month) are not zero based, but rather one-based. They also (after applying a trivial offset) indicate an integer count of days from the start of the given month, which turns out to be quite useful for doing calendrical calculations.

    Dates and times are TRWTF.



  • @blakeyrat said in Which language is the least bad?:

    @masonwheeler Nope. It requires empathy for the user, deep knowledge of the problem space, an eye for UX, a holistic understanding of the business need, data modeling, etc.

    The actual code is the boring bit you only do so you can get to the interesting stuff.

    People who write software because "they like coding" almost invariably produce garbage.

    But that wouldn't sell books and consulting. Let's just run after the newest fad like dependency injecting all the things using XML files or something.



  • @evo said in Which language is the least bad?:

    No, the instant a second programmer who doesn't know what they're doing, but is given too much responsibility in a code base, the codebase will grow terrible. If somebody doesn't know C++ properly, you shouldn't let them anywhere near the design of the software. This is true in all programming, but more in C++, simply because it gives you more tools and variety to do things properly.

    Unfortunately we have no control over that, and it is the most common case.


  • Discourse touched me in a no-no place

    @dkf said in Which language is the least bad?:

    excluding standard libraries from this discussion

    Expanding on that, the reason why it is useful to distinguish between the core language and its standard library for pretty much any language is because the library features are stuff that you can usually get away with not knowing until you need them, whereas core language features typically get used all over and in all sorts of ways. For an experienced programmer, learning a language to the level required to do maintenance programming is a matter of understanding the core language that will be written in plus whatever specific library calls are being used at the moment; for everything else, a swift web search will pull up a bunch of possible ways to do it as and when you need it.

    But C++ has a lot more core language features than most languages, and the interactions between some of them are really subtle.



  • @masonwheeler said in Which language is the least bad?:

    objects-as-value-types

    D does not have objects-as-value-types. It uses the same dichotomy as C#, i.e. struct is a value type and class is a reference type.

    Go and Rust, however, both do have objects-as-value-types just like C++ (with the inconsistent exception of arrays in Go).

    @masonwheeler said in Which language is the least bad?:

    when your biggest headlining feature is OOP,

    OOP definitely is not biggest headline feature of C++. I'm not sure it's even a headline feature.

    C++ was always a multi-paradigmatic language that allows you to mix-and-match various kinds of abstractions. One of them is OOP. If you want to do dynamic polymorphism, you have to use (smart-)pointers and references. But a lot of code either uses static polymorphism, or does not use polymorphism at all. And even when you do use dynamic polymorphism, the owner of the object often knows the exact type anyway, so it makes sense to stack-allocate it or embed it directly somewhere.

    If you want to do OOP, C++ is not for you. That's fine. No tool is everything for everybody. But that applies equally well to OOP.

    @scholrlea said in Which language is the least bad?:

    TBH, I see that as an optimization and performance issue, not a language semantics issue. C++ hasn't stuck around because value semantics are so bitchin' great, but because a naive implementation of reference semantics has terribad performance, and most languages that use them either don't snap pointers often enough, or don't give you the pragmas you want to force them to be snapped when you need them to be.

    Snapping pointers won't really help you. The difference is biggest between array of data and array of pointers and you can't do that transformation without affecting the language semantics.

    @scholrlea said in Which language is the least bad?:

    99.9% of the time, you want reference semantics

    I definitely don't. Most of the time I don't really care whether I have a value or reference to immutable, but references to mutable objects are pain, because then you can't reason about the code locally. That's why I really, really miss const in C# and Java. It can be emulated by creating a read-only interface for each of your types, but it is a lot of typing.

    I also want value semantics in all the cases where it is necessary for RAII and that's a lot of places. And no, java.lang.AutoCloseable and try(declaration) does not come anywhere near the power of RAII, because RAII composes automatically.

    @scholrlea said in Which language is the least bad?:

    If you can tell the compiler what to do out-of-band, you can decouple the two problems, which is why I am playing around with that kind of thing - I have no idea if my ideas on it are any good or not, but I want to find out rather than just assuming otherwise.

    Again, you can switch between by-value and by-reference-to-immutable easily, but reference to mutable is semantically different and you can't really change it without user noticing. In a functional language, which is referentially transparent, it would be a nice feature though. But in a procedural language it is just so much easier to let the programmer tell you what they need—they know.

    Yes, it does make C++ more difficult to learn and wield efficiently. But it also makes it a lot more powerful.


  • Banned

    @dkf said in Which language is the least bad?:

    Expanding on that, the reason why it is useful to distinguish between the core language and its standard library for pretty much any language is because the library features are stuff that you can usually get away with not knowing until you need them, whereas core language features typically get used all over and in all sorts of ways.

    But C++ has long passed the point where it becomes so featureful you don't use many of them anymore. Examples: mutable member fields, private inheritance, reference to fixed-size array, cast operator overloading, variable declaration in condition, , overloading, logical operators overloading which disables short-circuiting, shadowing inherited members. And that's only the ones I know about - I'm sure there's many more.



  • This post is deleted!


  • @gąska said in Which language is the least bad?:

    But C++ has long passed the point where it becomes so featureful you don't use many of them anymore. Examples: mutable member fields, private inheritance, reference to fixed-size array, cast operator overloading, variable declaration in condition, , overloading, logical operators overloading which disables short-circuiting, shadowing inherited members. And that's only the ones I know about - I'm sure there's many more.

    I definitely do use most of them at least occasionally. I don't think I used overloading of the short-circuiting logic operator—the loss of short-circuiting makes it not worth it—, but I did use all the others recently. Yes, including defining operator , (combined with a variadic macro, no less).



  • @bulb said in Which language is the least bad?:

    That's why I really, really miss const in C# and Java. It can be emulated by creating a read-only interface for each of your types, but it is a lot of typing.

    Or CodeGen (which I use quite often!)


  • Discourse touched me in a no-no place

    @gąska said in Which language is the least bad?:

    But C++ has long passed the point where it becomes so featureful you don't use many of them anymore.

    Even more “fun”: different people use different subsets…


  • Discourse touched me in a no-no place

    @bulb said in Which language is the least bad?:

    I also want value semantics in all the cases where it is necessary for RAII and that's a lot of places. And no, java.lang.AutoCloseable and try(declaration) does not come anywhere near the power of RAII, because RAII composes automatically.

    Can you explain what you mean by that? I can think of a few thing it might mean, and they'd get responses that vary from “well duh!” to “do you actually know what you're talking about here?” so in the interests of meaningful discussion, I'd like you to define what you mean by “composes automatically”.


  • Impossible Mission - B

    @bulb said in Which language is the least bad?:

    D does not have objects-as-value-types. It uses the same dichotomy as C#, i.e. struct is a value type and class is a reference type.

    Does it? I must have gotten some bad information. 😐

    Go and Rust, however, both do have objects-as-value-types just like C++ (with the inconsistent exception of arrays in Go).

    I have no experience with Rust, but Go doesn't have objects at all. (It has polymorphism through interfaces, but no inheritance and extremely minimal encapsulation.)

    OOP definitely is not biggest headline feature of C++. I'm not sure it's even a headline feature.

    C++ was always a multi-paradigmatic language that allows you to mix-and-match various kinds of abstractions.

    Always? You must be very young, or have a very short memory. OOP is literally the whole reason C++ exists in the first place. It was originally called "C with classes," because that's what it started out as.

    I definitely don't. Most of the time I don't really care whether I have a value or reference to immutable, but references to mutable objects are pain, because then you can't reason about the code locally.

    Ugh, not this nonsense again! 🤢

    Relevant data changes. Literally the entire point of a computer is to compute how things change. That's a simple fact, and that means your code has to come to terms with data changing in one way or another.

    Broadly speaking, there are two ways to do this. You can either have mutable data structures and update them as needed, or you can have immutable data structures and update them as needed by making copies with updated data in them. Both pose "reasoning about" problems that are essentially equivalent.

    In the case of mutable data, you have to worry about external code changing your data around, and make sure your code is able to handle it. And, frankly speaking, if your code is designed with mutable data in mind, this is simply not a problem unless you're doing multithreading, in which case things can get hairy.

    In the case of immutable data, you also have to worry about external code changing your data around. The model is different, though. Now, instead of modifying the data, what you need to worry about is the case of someone making an updated copy and leaving you with stale data that's no longer up-to-date. This is just as difficult to reason about, if not worse, because the changes that have been made are, by definition, invisible to you. So you need to ensure that there are communications mechanisms in place to keep every relevant piece of code aware of what the most up-to-date data is.

    Both styles have their own problems, and both problems are difficult. Stop pretending like this is only something that happens to mutable data.


  • Discourse touched me in a no-no place

    @masonwheeler said in Which language is the least bad?:

    You can either have mutable data structures and update them as needed, or you can have immutable data structures and update them as needed by making copies with updated data in them.

    You can also use hybrid techniques, such as making a structure mutable when it only has a single reference to it. Doesn't make the multithreading problem any easier though, as you still have to decide when an object is unshared and that's quite hard to do in general. (It's much easier in a lot of practical code though, as you often know that an object is newly-created and not handed off anywhere else.)

    Multithreaded programming is hard, m'kay?


  • Banned

    @bulb said in Which language is the least bad?:

    @gąska said in Which language is the least bad?:

    But C++ has long passed the point where it becomes so featureful you don't use many of them anymore. Examples: mutable member fields, private inheritance, reference to fixed-size array, cast operator overloading, variable declaration in condition, , overloading, logical operators overloading which disables short-circuiting, shadowing inherited members. And that's only the ones I know about - I'm sure there's many more.

    I definitely do use most of them at least occasionally. I don't think I used overloading of the short-circuiting logic operator—the loss of short-circuiting makes it not worth it—, but I did use all the others recently. Yes, including defining operator , (combined with a variadic macro, no less).

    Overloading new for single type. Overloading new globally. Octal numbers. const_cast. Extern templates.



  • @dkf said in Which language is the least bad?:

    @bulb said in Which language is the least bad?:

    I also want value semantics in all the cases where it is necessary for RAII and that's a lot of places. And no, java.lang.AutoCloseable and try(declaration) does not come anywhere near the power of RAII, because RAII composes automatically.

    Can you explain what you mean by that? I can think of a few thing it might mean, and they'd get responses that vary from “well duh!” to “do you actually know what you're talking about here?” so in the interests of meaningful discussion, I'd like you to define what you mean by “composes automatically”.

    I mean that when I have object that has some members with finalizers, it gets appropriate finalizer that finalizes all the subobjects. It can be done without value types, but not without explicit ownership that Java and C# don't have.

    Of course Java and C# do invoke the finalizers finally, when releasing the memory. But RAII does it immediately, which is important when the resources can't be shared.


  • Banned

    @masonwheeler said in Which language is the least bad?:

    @bulb said in Which language is the least bad?:

    Go and Rust, however, both do have objects-as-value-types just like C++ (with the inconsistent exception of arrays in Go).

    I have no experience with Rust, but Go doesn't have objects at all.

    Where did you get this stupid misconception that objects require class keyword?


  • Discourse touched me in a no-no place

    @bulb Ah. In that case the normal C#/Java approach would be to either list the managed resource directly (they can both have multiple managed resources in the same context) or to teach the container object about how to participate in that situation because it makes semantic sense to do so. It tends to not be as big a deal as all that in practice as they use other techniques for things like lock and transaction management; most of the time, we're actually talking about ensuring that it is things like files and database connections that get closed.

    Is the order of destruction of local variables and object fields well defined in C++? (I've never looked…)

    Thanks, Oracle. Thanks for absolutely nothing. Fuckwitted shitstains.


  • Impossible Mission - B

    @gąska said in Which language is the least bad?:

    Where did you get this stupid misconception that objects require class keyword?

    Where did you get the idea that I have such a stupid misconception?

    Objects do, however, require inheritance and virtual dispatch. Without that, you have something else that is not OOP. It might be better to say that OOP requires the base keyword.

    To give a real-world example, Go has interface-based polymorphism, which allows you to create multiple struct types that follow the same interface, and you can build a tree out of them, but you can't implement a proper Visitor Pattern to walk that tree, the way you can in OO languages.



  • @masonwheeler said in Which language is the least bad?:

    @bulb said in Which language is the least bad?:

    D does not have objects-as-value-types. It uses the same dichotomy as C#, i.e. struct is a value type and class is a reference type.

    Does it? I must have gotten some bad information. 😐

    Definitely.

    Go and Rust, however, both do have objects-as-value-types just like C++ (with the inconsistent exception of arrays in Go).

    I have no experience with Rust, but Go doesn't have objects at all. (It has polymorphism through interfaces, but no inheritance and extremely minimal encapsulation.)

    Rust and Go have very similar models in this regard. The only difference is that Go only has dynamic polymorphism and Rust has both static and dynamic one.

    And, well, it actually solves the issues with objects-as-value-types, because the bases—interfaces only—can't ever be by value, only the concrete types can and they are always final.

    OOP definitely is not biggest headline feature of C++. I'm not sure it's even a headline feature.

    C++ was always a multi-paradigmatic language that allows you to mix-and-match various kinds of abstractions.

    Always? You must be very young, or have a very short memory. OOP is literally the whole reason C++ exists in the first place. It was originally called "C with classes," because that's what it started out as.

    I have good memory.The whole reason C++ exists in the first place is zero-cost abstractions. These include OOP abstractions. But not OOP as a whole, just separate bits of your choice, opt-in, mixed-and-matched with whatever you used to use in C.

    I definitely don't. Most of the time I don't really care whether I have a value or reference to immutable, but references to mutable objects are pain, because then you can't reason about the code locally.

    Ugh, not this nonsense again! 🤢

    I am not talking about designing code with one or the other exclusively—I am talking about being able to distinguish the owner of the data, who can change them, and the consumers, who must not. C++ has const for this, in Java and C# it requires verbose interfaces.



  • @dkf said in Which language is the least bad?:

    @bulb Ah. In that case the normal C#/Java approach would be to either list the managed resource directly (they can both have multiple managed resources in the same context) or to teach the container object about how to participate in that situation because it makes semantic sense to do so. It tends to not be as big a deal as all that in practice as they use other techniques for things like lock and transaction management; most of the time, we're actually talking about ensuring that it is things like files and database connections that get closed.

    It's mainly a maintainability issue. As you refactor the code, it's quite easy to miss something. C++ will mind it for you.

    Is the order of destruction of local variables and object fields well defined in C++? (I've never looked…)

    Yes. They are always destroyed in reverse order of construction.

    There is the “static initialization order fiasco” where the ordering of global objects not fully specified (it is specified within compilation unit, but not between them), but it is actually the order of construction that is unspecified—they are always destroyed in reverse order of construction.



  • @dkf said in Which language is the least bad?:

    Dates and times are TRWTF.

    I think somebody posted this recently, but I'll post it again anyway:
    https://www.youtube.com/watch?v=-5wpm-gesOY



  • @masonwheeler said in Which language is the least bad?:

    @gąska said in Which language is the least bad?:

    Where did you get this stupid misconception that objects require class keyword?

    Where did you get the idea that I have such a stupid misconception?

    Objects do, however, require inheritance and virtual dispatch. Without that, you have something else that is not OOP. It might be better to say that OOP requires the base keyword.

    They do have inheritance. Of interfaces only, but that's still inheritance.

    They also do have virtual dispatch.

    To give a real-world example, Go has interface-based polymorphism, which allows you to create multiple struct types that follow the same interface, and you can build a tree out of them, but you can't implement a proper Visitor Pattern to walk that tree, the way you can in OO languages.

    Why couldn't you? The visit methods will have to be suffixed, because neither language has function overloading, but then the visit method needs to be declared for each type to be visited in “OO languages” anyway, so it does not make it improper in any way.


  • Discourse touched me in a no-no place

    @masonwheeler said in Which language is the least bad?:

    Objects do, however, require inheritance and virtual dispatch.

    Technically, no. They require state encapsulation and message dispatch by the object type, but there's no need to support inheritance (that's just very common) or virtual dispatch (it only makes sense with some form of inheritance).



  • @bulb said in Which language is the least bad?:

    But it also makes it a lot more powerful.

    I think a lot of the debate here is whether being "more powerful" (however you define that vagueness) is better necessarily.

    I'd actually disagree in two ways:

    1. C++ is not "more powerful" than C#. C# has all the good features of C++, plus a lot of stuff C++ does not and will never have.
    2. A language being "more powerful" does not (necessarily) make it better for creating quality software.

    Obviously it's going to be a bitch writing quality software in, say, BIT. But that doesn't mean the inverse is true.


  • Impossible Mission - B

    @bulb said in Which language is the least bad?:

    Rust and Go have very similar models in this regard. The only difference is that Go only has dynamic polymorphism and Rust has both static and dynamic one.

    And, well, it actually solves the issues with objects-as-value-types, because the bases—interfaces only—can't ever be by value, only the concrete types can and they are always final.

    So then Rust has the same problem as Go, where there's no inheritance. Which makes it crippled to the point of near-uselessness for modern software development.

    I have good memory.The whole reason C++ exists in the first place is zero-cost abstractions.

    This is simply not true. That's its selling point today. But "zero-cost abstractions" is a code word for "templates", and those weren't even suggested until the language was several years old; they weren't (pseudo-)standardized until 1990, when it had already been around for more than a decade.

    I am not talking about designing code with one or the other exclusively—I am talking about being able to distinguish the owner of the data, who can change them, and the consumers, who must not.

    You're still making a very big assumption here. Why should that necessarily be the case. In many cases, it isn't. In others, it is.

    C++ has const for this, in Java and C# it requires verbose interfaces.

    C++ also has const_cast to work your way around it. Anders Hejlsberg once suggested that that's the only reason const works in C++ at all, because you can cast your way out of it when you need to.



  • @bulb said in Which language is the least bad?:

    I mean that when I have object that has some members with finalizers, it gets appropriate finalizer that finalizes all the subobjects. It can be done without value types, but not without explicit ownership that Java and C# don't have.

    Seems to me that using in C# does exactly that...?

    @bulb said in Which language is the least bad?:

    Of course Java and C# do invoke the finalizers finally, when releasing the memory. But RAII does it immediately, which is important when the resources can't be shared.

    using releases the resources the instant you leave its scope.



  • @blakeyrat said in Which language is the least bad?:

    @bulb said in Which language is the least bad?:

    But it also makes it a lot more powerful.

    I think a lot of the debate here is whether being "more powerful" (however you define that vagueness) is better necessarily.

    I'd actually disagree in two ways:

    1. C++ is not "more powerful" than C#. C# has all the good features of C++, plus a lot of stuff C++ does not and will never have.
    2. A language being "more powerful" does not (necessarily) make it better for creating quality software.

    Obviously it's going to be a bitch writing quality software in, say, BIT. But that doesn't mean the inverse is true.

    I definitely agree on 2. Different languages are better for different kinds of tasks and C# is certainly better than C++ for many.

    I still don't agree on 1. C++ is more "powerful" (with it's vagueness). The power is very useful in building some kinds of abstractions and there are cases where those abstractions are worth the complexity. There are cases where they are not.


  • Impossible Mission - B

    @bulb said in Which language is the least bad?:

    @masonwheeler said in Which language is the least bad?:
    They do have inheritance. Of interfaces only, but that's still inheritance.

    No, that's implementation of an interface.

    They also do have virtual dispatch.

    Of interfaces, not of objects.

    Why couldn't you? The visit methods will have to be suffixed, because neither language has function overloading, but then the visit method needs to be declared for each type to be visited in “OO languages” anyway, so it does not make it improper in any way.

    How do you recurse into subnodes without a base call? The way Go's AST walker does it is by having you pass it a function pointer that takes a node and returns a bool, and if that return value is true you recurse into the subnodes, and if it's false you don't. Which means there's no way to support the (extremely common) Visitor Pattern operation of recursing into the subnodes first and then processing the parent node.


  • Discourse touched me in a no-no place

    @blakeyrat said in Which language is the least bad?:

    @bulb said in Which language is the least bad?:

    I mean that when I have object that has some members with finalizers, it gets appropriate finalizer that finalizes all the subobjects. It can be done without value types, but not without explicit ownership that Java and C# don't have.

    Seems to me that using in C# does exactly that...?

    I think he means that if you glue some objects together in a larger object, that also obeys RAII finalisation rules. Apparently, he thinks this is a big deal.


  • Impossible Mission - B

    @dkf said in Which language is the least bad?:

    Technically, no. They require state encapsulation and message dispatch by the object type, but there's no need to support inheritance (that's just very common) or virtual dispatch (it only makes sense with some form of inheritance).

    Ugh, you just said "message". This means you're already on the wrong track.

    The definition of OOP for decades has been support for the so-called "three pillars:" encapsulation, inheritance, and polymorphism. If you don't have these three pillars, you have something else that is not OOP.



  • @dkf said in Which language is the least bad?:

    I think he means that if you glue some objects together in a larger object, that also obeys RAII finalisation rules.

    But that happens with using too.

    If do you using( var blah = new Blah() ){}, and Blah's constructor does using( var ted = new Ted() ){}, and the outer using scope goes away, all of those dispose calls happen right away in the reverse order of the object initialization.

    It is true that you can't do: using( var foo = new Foo(), var bar = new Bar() ){} in C# if Foo and Bar are different types. I'm not sure why it's not allowed, but I'm sure the C# designers had a good reason for it.

    I'm not sure how RAII differs.


  • Discourse touched me in a no-no place

    @masonwheeler said in Which language is the least bad?:

    The definition of OOP for decades has been support for the so-called "three pillars:" encapsulation, inheritance, and polymorphism. If you don't have these three pillars, you have something else that is not OOP.

    You happen to be wrong, but you're entertaining anyway.



  • @masonwheeler said in Which language is the least bad?:

    I am not talking about designing code with one or the other exclusively—I am talking about being able to distinguish the owner of the data, who can change them, and the consumers, who must not.

    You're still making a very big assumption here. Why should that necessarily be the case. In many cases, it isn't. In others, it is.

    If you are used to Java or C#, you are used to rely on the convention that methods only modify the invocant and hope for the others to follow it and mostly it's good enough. Once you get use to const, you'll find the lack of it a bit, well, lacking.

    C++ has const for this, in Java and C# it requires verbose interfaces.

    C++ also has const_cast to work your way around it. Anders Hejlsberg once suggested that that's the only reason const works in C++ at all, because you can cast your way out of it when you need to.

    const_cast is only needed to work around old code, especially C one, that lacks const in places they should be. I haven't seen it in code written by moderately sane programmers in the last decade.

    @blakeyrat said in Which language is the least bad?:

    @dkf said in Which language is the least bad?:

    I think he means that if you glue some objects together in a larger object, that also obeys RAII finalisation rules.

    But that happens with using too.

    If do you using( var blah = new Blah() ){}, and Blah's constructor does using( var ted = new Ted() ){}, and the outer using scope goes away, all of those dispose calls happen right away in the reverse order of the object initialization.

    So the ted instance leaves the Blah constructor and gets disposed in Blah::Dispose? If so it would achieve the same goal as C++ RAII, but I wouldn't call it exactly readable, because the var ted appears, for all that's written, to be inside the Blah constructor and thus deleted at end of that, not in Blah::Dispose, which is a different function.

    It is true that you can't do: using( var foo = new Foo(), var bar = new Bar() ){} in C# if Foo and Bar are different types. I'm not sure why it's not allowed, but I'm sure the C# designers had a good reason for it.

    using(var foo = new Foo(), var bar = new Bar()) { … } is no different from using(var foo = new Foo()) { using(var bar = new Bar()) { … }} and you can obviously write the later. No reason for that, really.


Log in to reply