How can we increase adoption of c/c++ alternatives?



  • How much faster would those parts of the runtime be if they were written in c?



  • Probably not faster at all, but much harder to maintain.

    http://benchmarksgame.alioth.debian.org/u64q/performance.php?test=fasta#about



  • Thats the same bench a second time. I noticed that go used more cycles but achieved shorter execution time by better utilizing all four cores. Are there many programs or algorithms for which that would be doable?


  • Banned

    @dkf said:

    JIT

    Is JIT still relevant in the world of JOP, where there's no further compile step than Java bytecode?

    @ben_lubar said:

    The original statement was "A good language provides enough tools so that that runtime can be a library written in the language itself."

    which I simplified to "A good language is Turing-complete."


    Wrong. The point is that a good language is such that can have runtime written exclusively in itself - which is equivalent to being able to run with no runtime at all (because runtime can't require runtime). Can Go do that? With channels and GC and all that fuzz?

    Also, fucking nested quotes how do they work?



  • ... Can a C runtime be written exclusively in C? I'm pretty sure glibc has some inline ASM, or at least some ASM source files.


  • kills Dumbledore

    Have you just proved that C isn't a good language?


  • Banned

    @riking said:

    ... Can a C runtime be written exclusively in C? I'm pretty sure glibc has some inline ASM, or at least some ASM source files.

    I'm pretty sure these are just hardcore optimizations written by early 70's hackers that didn't trust gcc to produce code good enough, and could be easily rewritten in C.



  • @Gaska said:

    hardcore optimizations

    @Gaska said:

    easily rewritten in C

    I don't know of any valid, portable, plain C source code that compiles to the x86_64 SYSCALL instruction.



  • @riking said:

    ... Can a C runtime be written exclusively in C? I'm pretty sure glibc has some inline ASM, or at least some ASM source files.

    With exception of platform-specific bits (that any other language needs assembly, or existing standard C library, for too) it can. The only assembly needed in standard C library is the system call mechanism and the only assembly needed in kernel is syscall and interrupt entry trampolines, bus I/O, before C11 thread synchronization and on platforms with segmented memory segment register manipulation. There are some other bits written in assembly as hand-optimization, but they are not needed.


  • BINNED

    @ben_lubar said:

    Any questions?

    [-]>[-]<
    >++++++++[<++++++++>-]<++.
    >+++++++[<+++++++>-]<-.
    >++++[<---->-]<-.
    >+++[<+++>-]<-.
    >++[<++>-]<+.
    >++++++[<------>-]<----.
    >+++++++[<+++++++>-]<--.
    >++++[<---->-]<--.
    >+++[<+++>-]<-.
    >+++++++++[<--------->-]<++++++.
    >+++++++++[<+++++++++>-]<--------.
    >+++[<+++>-]<+.
    >+++++++++[<--------->-]<--.
    >+++++++[<+++++++>-]<+++.
    >++++++[<++++++>-]<---.
    ---.
    >+++[<--->-]<.
    >++[<++>-]<+.
    >+++[<--->-]<++.
    >++++++++[<-------->-]<-------.
    >++++++++[<++++++++>-]<+++.
    >+++[<+++>-]<+++.
    --.
    +++.
    ----.
    >+++[<--->-]<++.
    >++++[<++++>-]<-.
    >++++[<---->-]<+.
    >+++++++[<------->-]<------.
    >++++[<---->-]<++.
    >+++++++[<+++++++>-]<++++++.
    >+++++[<+++++>-]<-.
    >++[<++>-]<++.
    >+++[<--->-]<.
    >+++[<--->-]<+.
    >++++++++[<-------->-]<----.
    >+++++++++[<+++++++++>-]<++++++++.
    >+++[<--->-]<-.
    >++[<++>-]<++.
    >+++++++++[<--------->-]<----.
    >++++++++[<++++++++>-]<+++.
    --.
    >+++[<+++>-]<++.
    .
    >+++++++++[<--------->-]<+++++.
    >+++++++++[<+++++++++>-]<--------.
    >+++[<+++>-]<++.
    >+++++++++[<--------->-]<---.
    >++++++++[<++++++++>-]<+.
    >++++++++[<-------->-]<-.
    >++++++++[<++++++++>-]<+++++++.
    >+++[<+++>-]<-.
    .
    >+++[<--->-]<--.
    >++++++++[<-------->-]<----.
    >+++++++++[<+++++++++>-]<-----.
    >+++[<--->-]<--.
    >++++[<++++>-]<---.
    >+++[<--->-]<++.
    >++++[<++++>-]<--.
    >++++[<---->-]<----.
    >++[<++>-]<++.
    --.
    >++++++[<------>-]<--.
    
    


  • <Riking> ?web>bf http://pastebin.com/raw.php?i=SBmqHkpR
    <Shocky> BrainFuck is Turing complete. Would you call it a good language?
    

    No less than 5 fully-featured computers were involved in bringing you this message, running software in at least 45 different programming languages. (It depends on what the IRCd(s) is(are) written in.)

    Bumped from 4 to 5 because I forgot to count Brainfuck. Also, PHP got ran twicethree times.


  • BINNED

    @riking said:

    No less than 5 fully-featured computers were involved in bringing you this message, running software in at least 4 different programming languages.

    Efficient.

    Also, while your public service is appreciated, you just robbed me of some joy involved in making others translate it by themselves.


    Filed under: @ben_lubar would probably write his own interpreter in Go



    1. Machine D runs Ruby to show the webpage
    2. Machine R runs C++ to have a browser
    3. Machine R runs Javascript to display Discourse
    4. Machine P runs PHP to display pastebin.com to me, involving L the load balancer
    5. Machine R runs C to have an IRC client
    6. Machine I runs ? to act as an IRC daemon
    7. Machine I2 runs ? to act as a peering IRC daemon
    8. Machine S runs Java to serve an IRC bot
    9. Machine C runs PHP to download the pastebin and report its contents to S
    10. Machine P2 runs PHP to display the pastebin raw to C (Episode VI: L the load balancer strikes back)
    11. Machine S runs Brainfuck to interpret the BF code
    12. The result bounces back from S → I2 → I → R, where I submit it as a new post to D.

    Key:

    Discourse at what.thedailywtf.com, Riking's computer, Pastebin.com php server, pastebin.com Load balancer, Irc server, Shocky the irc bot, Clone1018's php server which shocky uses as a php runner.

    What a wonderful world.


  • Banned

    @riking said:

    Also, PHP got ran twicethree times.

    Word Of The Day: thrice.



  • @Gaska said:

    Is JIT still relevant in the world of JOP, where there's no further compile step than Java bytecode?

    No but an optimizing compiler could do many of the things yall were talking about.

    @ben_lubar said:
    The original statement was "A good language provides enough tools so that that runtime can be a library written in the language itself."

    which I simplified to "A good language is Turing-complete."


    Wrong. The point is that a good language is such that can have runtime written exclusively in itself - which is equivalent to being able to run with no runtime at all (because runtime can't require runtime). Can Go do that? With channels and GC and all that fuzz?

    Just because the language semantics allow gc doesn't mean that every single allocation will have to go through the garbage collector. Future Ben's gonna be able to say that the c parts of the go runtime were just hardcore optimizations by early hackers who didn't trust the go compiler.

    Also, fucking nested quotes how do they work?
    Use email-style >s.

  • Banned

    @Buddy said:

    No but an optimizing compiler could do many of the things yall were talking about.

    To date, no non-JIT Java optimizing compiler exists.

    @Buddy said:

    Just because the language semantics allow gc doesn't mean that every single allocation will have to go through the garbage collector.

    But can I use GC in runtime-less app? Because I totally can use shared_ptr in runtime-less C++ (assuming I have an implementation that doesn't depend on runtime itself - which I can wind up myself because shared_ptr is just a library). Same question for channels - because while GC is optional(?) and you can live without it, channels are the killer feature which make it better than plain C and working without them would be very unidiomatic Go.

    @Buddy said:

    Use email-style >s.

    I tried

    and

    I failed


  • Discourse touched me in a no-no place

    @Bulb said:

    I don't think it's doable with Java

    If I was making a super-snazzy JIT for Java, I'd be very interested in looking at whether I can prove I can inline POJOs in what contains them. Proving it is tricky, but might be possible. (It depends on being able to prove that the POJO isn't ever handled as an independent entity except by things that we're planning to inline.)

    I suspect that most code won't ever be able to establish that proof, not unless there's a mechanism for undoing the data-inlining optimisation too, which I think would be necessary if anything obtains a Field instance for the POJO. (That in turn is rather common, at least in the frameworks that my code uses. Ho hum…)


  • Discourse touched me in a no-no place

    @Gaska said:

    To date, no non-JIT Java optimizing compiler exists.

    gcj was a thing, and might still be. Nobody sane uses it.



  • @Gaska said:

    To date, no non-JIT Java optimizing compiler exists.

    I know. It's disappointing. But the nice thing about jop is that code could be optimized for a specific version of the architecture but still be compatible with any jvm.

    But *can* I use GC in runtime-less app? Because I totally can use shared_ptr in runtime-less C++ (assuming I have an implementation that doesn't depend on runtime itself - which I can wind up myself because shared_ptr is just a library). Same question for channels - because while GC is optional(?) and you can live without it, channels are the killer feature which make it better than plain C and working without them would be very unidiomatic Go.
    Which is why it makes sense to bake those things into the language. Because for what go is trying to accomplish, it is much better to be able to use multiple cores well than to conserve cycles, and it is much more useful to have guaranteed memory safety than to allow low level access to allocation and deallocation. And the gap between fully optimized go and c is just going to shrink as each compiler matures, but programmer productivity will only increase.
    @Buddy said:
    Use email-style >s. >I tried

    and

    I failed


    That's messed up, I don't know what to tell you :<frowning>(


  • kills Dumbledore

    Discourse and empty lines have a love/hate relationship


  • Banned

    @Buddy said:

    Which is why it makes sense to bake those things into the language.

    No, it means the exact opposite - it's BAD DESIGN DECISION for systems language. If your language has hard-coded feature that heavily depends on runtime implementation, you can't do runtimeless build anymore no matter what. It becomes impossible. Your language becomes useless everywhere where you can't run your runtime. For example, barebone PC without an operating system in place.

    @Buddy said:

    Because for what go is trying to accomplish, it is much better to be able to use multiple cores well than to conserve cycles, and it is much more useful to have guaranteed memory safety than to allow low level access to allocation and deallocation.

    When did I say anything about performance? But answering to your non sequitur, Rust has both memory safety and low-level access. And doesn't depend on its runtime.



  • @Gaska said:

    To date, no non-JIT Java optimizing compiler exists.


  • Banned

    @ben_lubar said:

    http://proguard.sourceforge.net/

    I don't see "removing excess variables" or "inlining" in feature list...




  • Banned

    Ok, point taken. Now, what is the performance of optimized bytecode running on JOP vs. JIT-ed bytecode running on x86/ARM of comparable power?



  • @Gaska said:

    If your language has hard-coded feature that heavily depends on runtime implementation, you can't do runtimeless build anymore no matter what. It becomes impossible. Your language becomes useless everywhere where you can't run your runtime. For example, barebone PC without an operating system in place.
    There's no fundamental reason that you couldn't GC inside an OS.

    There are small (and I emphasize small) portions where you couldn't, but there are small portions of OSs now where you can't dynamically/deallocate memory at all, and that covers most of the not-GC-able parts.

    I'm not necessarily saying it's a good idea, because of performance, but it would work. (I generally think that virtually everything should be in a GC'd language for memory-safety reasons, but the OS is one of the few exceptions I'm willing to grant.)


  • Banned

    @EvanED said:

    There's no fundamental reason that you couldn't GC inside an OS.

    There is - garbage collecting must be done by runtime, and you don't have runtime if you write OS.

    @EvanED said:

    I generally think that virtually everything should be in a GC'd language for memory-safety reasons

    There are other ways to achieve memory safety.

    @EvanED said:

    but the OS is one of the few exceptions I'm willing to grant

    Which is, ironically, the single thing that absolutely must be perfectly stable.


  • Discourse touched me in a no-no place

    @Gaska said:

    There is - garbage collecting must be done by runtime, and you don't have runtime if you write OS.

    Operating systems contain their own runtime (if they need it). The GC engine itself is one of the parts that can't be garbage collected.


  • Banned

    @dkf said:

    The GC engine itself is one of the parts that can't be garbage collected.

    As well as anything that GC uses to do its work, which is, frankly, many of the basic OS functions.



  • @Gaska said:

    There is - garbage collecting must be done by runtime, and you don't have runtime if you write OS.

    Bull. Shit. A runtime is just a library, usually with the implication that it's doing something fancy. But plain C has a runtime; it provides things like malloc/free. Does that mean that malloc/free can't exist in the kernel? No, of course not, as evidenced by every OS kernel ever. (Statement may be an exaggeration.)

    There's nothing magical about runtimes or what runtimes do. The only thing that a GC needs to be able to do is interrupt other parts of the same "process" to do GC, to muck about with memory, and to find the root set to use. The latter two things don't change when running in the kernel; as for the first, almost all of the kernel is interruptable already, and the exceptions are what I said before where you can't do memory alloc/dealloc anyway. (I could be wrong about that last part, but I don't think so.)

    If you want concrete evidence that you can write an OS kernel in a GC'd language, you need look no further than Singularity, which is written in C#:

    The Singularity kernel is a privileged system component that controls access to hardware resources, allocates and reclaims memory, creates and schedules threads, provides intraprocess thread synchronization, and manages I/O. It is written in a mixture of safe and unsafe C# code and runs in its own garbage collected object space.

    (As another example of this reasoning, consider exceptions. You often see people asserting you can't use (software) exceptions in a kernel because it requires a runtime. But this too is patently false, as evidenced by, oh, Windows.)

    @Gaska said:

    There are other ways to achieve memory safety.
    That's true, but I don't know of another way that still looks like "common" programming today.

    @Gaska said:

    Which is, ironically, the single thing that absolutely must be perfectly stable.
    It's also the thing that must be performant, and the stability issues are countered somewhat by the fact that it's always running under everything (and is thus unusually well-tested), gets an unusual amount of attention to correctness, etc.


  • Banned

    @EvanED said:

    Bull. Shit. A runtime is just a library, usually with the implication that it's doing something fancy.

    It's pretty low-level, that's all. More low-level than anything else except kernel, and probably few other things.

    @EvanED said:

    But plain C has a runtime; it provides things like malloc/free.

    I'm pretty sure you could compile C program without providing malloc/free anywhere.

    @EvanED said:

    If you want concrete evidence that you can write an OS kernel in a GC'd language, you need look no further than Singularity, which is written in C#:

    Oh, cool. I'll look into it later. Thanks alot!

    @EvanED said:

    As another example of this reasoning, consider exceptions. You often see people asserting you can't use (software) exceptions in a kernel because it requires a runtime. But this too is patently false, as evidenced by, oh, Windows.

    AFAIK runtime is only needed to catch uncaught exceptions. I see no reason why it would be impossible to throw in kernel code.

    @EvanED said:

    That's true, but I don't know of another way that still looks like "common" programming today.

    An intuitive definition of word "common" excludes all non-GC languages.


  • Discourse touched me in a no-no place

    @Gaska said:

    AFAIK runtime is only needed to catch uncaught exceptions.

    That's also something that both Java and C# make pretty easy. ;)


  • Banned

    @dkf said:

    That's also something that both Java and C# make pretty easy.

    C++ makes it easy too - just int main() { try { return real_main(); } catch(...){} }.



  • @Gaska said:

    An intuitive definition of word "common" excludes all non-GC languages.
    I'm also including C, C++, etc. in here, as well as refcounted languages if you count that as not GC.

    @Gaska said:

    I'm pretty sure you could compile C program without providing malloc/free anywhere.
    You could write a C program without a runtime, yes, I will agree with that. But that's not my point: my point is that kernels have a support library that could be reasonably called a runtime.



  • @Gaska said:

    C++ makes it easy too - just int main() { try { return real_main(); } catch(...){} }.

    Small note: there's no need for the extra function, e.g.:

    int main() try 
    { /* whatever */ return 0; } 
    catch( ... ) 
    { /* whatever */ return 1; }
    

  • Banned

    @EvanED said:

    I'm also including C, C++, etc. in here, as well as refcounted languages if you count that as not GC.

    If you put it that way, then the alternative is RAII.

    @EvanED said:

    You could write a C program without a runtime, yes, I will agree with that. But that's not my point: my point is that kernels have a support library that could be reasonably called a runtime.

    And you must write that runtime without using runtime.



  • @EvanED said:

    You could write a C program without a runtime, yes, I will agree with that. But that's not my point: my point is that kernels have a support library that could be reasonably called a runtime.

    Yes, they certainly do. And yes, they could have garbage collector in it. After all it's just a bunch of functions that the compiler inserts calls to at appropriate places. And kernels have to handle interrupts anyway, so there's nothing simpler than hook up the collector into schedule().

    The thing with non-hosted (= without the usual runtime) implementations is more like this: in languages like C, C++ or Rust you only have to do features you want to use and only those features cost you memory, code size and CPU cycles, so you can choose whether in your particular situation it is easier to implement the support, do without the feature or implement lighter-weight version of the feature or version tuned to the purpose (Linux kernel has very sophisticated allocator, but it's interface is quite different from malloc and free). On the other hand languages that have runtime-dependent features built into the language usually force you to implement the feature and don't let you implement modified version.

    The later ability is probably useful in more circumstances. It can be demonstrated on Go like this: Consider some functionality that uses associative container. Fine, Go has it built in. So you go with that. But then you find you would need the container to be sorted, or to maintain order of insertion or something. You are suddenly left with polymorphic solution using empty interface and the associated allocation overhead and casts all over the place. On the other hand in C++ or Rust you just replace the standard unordered map with ordered map or multi-index container from suitable library and it is almost direct replacement and you get to keep the same efficiency and features.



  • @riking said:

    ... Can a C runtime be written exclusively in C? I'm pretty sure glibc has some inline ASM, or at least some ASM source files.

    In an OS environment: the likely hangups would be the system call stub(s) and perhaps some of the pre-startup initialization code, although the latter probably can be written in C.

    Ironically enough, it's easier to do this on some microcontrollers (the ARM Cortex-Ms were designed for an assembler-free bootstrap) -- the NVIC in the Cortex-M family is smart enough to invoke a C function directly (no more trampolines!).

    @Bulb said:

    The only assembly needed in standard C library is the system call mechanism and the only assembly needed in kernel is syscall and interrupt entry trampolines, bus I/O, before C11 thread synchronization and on platforms with segmented memory segment register manipulation. There are some other bits written in assembly as hand-optimization, but they are not needed.

    I'd say that you could write a kernel completely in C given a suitably smart interrupt controller in your hardware and a platform that uses memory-mapped I/O. (Why more interrupt controllers lack the ARM NVIC's brains beats me...)

    @dkf said:

    gcj was a thing, and might still be. Nobody sane uses it.

    GCJ is still a thing, but yes, it is insane.

    @Gaska said:

    No, it means the exact opposite - it's BAD DESIGN DECISION for systems language. If your language has hard-coded feature that heavily depends on runtime implementation, you can't do runtimeless build anymore no matter what. It becomes impossible. Your language becomes useless everywhere where you can't run your runtime. For example, barebone PC without an operating system in place.

    Exactly -- the Cortex-M family can run compiled C code from the very first instruction after reset!

    @dkf said:

    Operating systems contain their own runtime (if they need it). The GC engine itself is one of the parts that can't be garbage collected.

    Pretty much this -- klibc is a thing.

    @Bulb said:

    The thing with non-hosted (= without the usual runtime) implementations is more like this: in languages like C, C++ or Rust you only have to do features you want to use and only those features cost you memory, code size and CPU cycles, so you can choose whether in your particular situation it is easier to implement the support, do without the feature or implement lighter-weight version of the feature or version tuned to the purpose (Linux kernel has very sophisticated allocator, but it's interface is quite different from malloc and free). On the other hand languages that have runtime-dependent features built into the language usually force you to implement the feature and don't let you implement modified version.

    This, even more so when you're writing embedded code -- embedded hardware often demands a drastically different and lower-level interface than what a "normal" set of syscalls provide; in some cases, you may not even be able to use "normal" calls to talk to a device due to needing to use a different mode of the hardware or somesuch.



  • @Gaska said:

    If you put it that way, then the alternative is RAII.
    I count reference counting as (poor1) GC. RAII also doesn't give you memory safety; you'd need a language that enforced it (as well as removing the other things that makes C++ memory-unsafe).

    1Overall. There are some advantages compared to a tracing GC like usually more amortized & predictable performance.

    @Gaska said:

    And you must write that runtime without using runtime.
    And? How do you think a user-space GC is written? Does it use OS capabilities to do GC? (No.) Is it GCs all the way down?

    Just like a user-land GC can be written without an underlying GC, so could a kernel-land one.

    @Bulb said:

    in languages like C, C++ or Rust you only have to do features you want to use and only those features cost you memory, code size and CPU cycles, so you can choose whether in your particular situation it is easier to implement the support, do without the feature or implement lighter-weight version of the feature or version tuned to the purpose
    I agree with out this, with a couple caveats. First, the problem with that applied to GC is that while using GC costs you memory and CPU cycles, not using it can cost you security, and that's sort of my focus. (That being said, I think that GC is less important than other memory-safety guarantees that come with languages that are, somewhat orthogonality, attached to GCs, like bounds checking.) Second, you can say "oh I'll just write a GC for C", and while technically true2... that's really really difficult. The only one I know of is Boehm, and you wouldn't want to use that in the kernel.

    2 Technically technically false except I think C++11.

    @Bulb said:

    On the other hand languages that have runtime-dependent features built into the language usually force you to implement the feature and don't let you implement modified version.
    So I'm not saying a kernel would want to use sort of an off-the-shelf GC; they could customize it. The kernel is probably a good candidate for a more real-time one.



  • @tarunik said:

    This, even more so when you're writing embedded code -- embedded hardware often demands a drastically different and lower-level interface than what a "normal" set of syscalls provide
    Yeah. I mentioned above that I'm begrudgingly willing to budge on my GC ideology for the kernel; I definitely (and not-begrudgingly) wouldn't apply to most embedded stuff.


  • I survived the hour long Uno hand

    @Gaska said:

    If your language has hard-coded feature that heavily depends on runtime implementation, you can't do runtimeless build anymore no matter what

    Maybe I'm old fashioned, but what happened to the idea that languages are designed to do different things, and in theory, you'd want a different language for something like embedded systems or barebones no-OS PCs than you'd want for, say, a typical desktop environment with memory to spare? I mean, otherwise.... why have many languages at all? If all hammers are meant to be multi-tools capable of handling every possible home construction project start to finish, why would you ever want more than one? And how can it be as good at everything all at once?


  • Banned

    @EvanED said:

    And? How do you think a user-space GC is written? Does it use OS capabilities to do GC?

    Yes. malloc() for instance. And many other memory-related syscalls.

    @Yamikuronue said:

    Maybe I'm old fashioned, but what happened to the idea that languages are designed to do different things, and in theory, you'd want a different language for something like embedded systems or barebones no-OS PCs than you'd want for, say, a typical desktop environment with memory to spare?

    Marketing happened. Go is presented as a language that can fully replace C and C++ in every field.

    @Yamikuronue said:

    And how can it [language] be as good at everything all at once?

    By keeping the core functionality as small as possible and stuffing everything into libraries, making these libraries feel like the core language but still making them more or less optional :)



  • @Yamikuronue said:

    Maybe I'm old fashioned, but what happened to the idea that languages are designed to do different things, and in theory, you'd want a different language for something like embedded systems or barebones no-OS PCs than you'd want for, say, a typical desktop environment with memory to spare? I mean, otherwise.... why have many languages at all? If all hammers are meant to be multi-tools capable of handling every possible home construction project start to finish, why would you ever want more than one? And how can it be as good at everything all at once?

    Once you get high enough up on the language power web -- you start seeing programming languages that are good metalanguages -- i.e. they not only provide you with tools to write code for a given task, but allow you to build and customize those tools to make the language better at a given task.


  • kills Dumbledore

    And then you are doomed to never again STFU about Lisp


  • Banned

    Someone post this xkcd about the universe and God, please.



  • If only for blakeyrat's benefit 😈



  • @Gaska said:

    Someone post this xkcd about the universe and God, please.

    I have been summoned!



  • @Yamikuronue said:

    Maybe I'm old fashioned, but what happened to the idea that languages are designed to do different things…

    Oh, that's totally a thing. C/C++ mostly was already replaced in areas where the other languages provide benefits and don't show any significant disadvantages. Even the C zealots from GNOME have switched to Python or C# for most of their applications. But we are talking about what features that would be needed to replace it in places where it stubbornly sticks (not possible completel; backward compatibility is a thing too; but at least for new stuff).

    @Gaska said:

    By keeping the core functionality as small as possible and stuffing everything into libraries, making these libraries feel like the core language but still making them more or less optional

    QFT


  • I survived the hour long Uno hand

    @Bulb said:

    . But we are talking about

    Nah, I was just replying to the increasing amount of "Your language doesn't do X so it is terrible" stuff going on as this thread develops, the original topic was fine.



  • It's more “your language doesn't do X so it is not adequate replacement of C++”. Which, well, it usually isn't, if C++ does X and the language does not and does not have any adequate replacement for it.


Log in to reply