NetBeans vs UTF-8



  • @Gąska said in NetBeans vs UTF-8:

    I'm pretty sure over 90% of computational power in the world is spent on producing textporn.


  • Discourse touched me in a no-no place

    @Gąska said in NetBeans vs UTF-8:

    @dkf takeaway: computers would work so much better if they didn't have to cater to humans.

    I'm pretty sure over 90% of computational power in the world is spent on producing text.

    Yes, but that could be cut a lot if people used the right string concatenation data structure/algorithm. Schlemiel the Painter has a lot to answer for!


  • Banned

    @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf takeaway: computers would work so much better if they didn't have to cater to humans.

    I'm pretty sure over 90% of computational power in the world is spent on producing text.

    Yes, but that could be cut a lot if people used the right string concatenation data structure/algorithm. Schlemiel the Painter has a lot to answer for!

    If any programming language allowed easy creation of non-Shlemiel strings by lazy-evaluating the billion concatenations across multiple stack frames required to produce a log line, I'd use Shlemiel less.



  • @Gąska StringBuilder is your friend here...


  • Banned

    @Mason_Wheeler StringBuilder only works if you build from the beginning to the end. I'd need something more like a DoubleEndedStringBuilder and a + operator that takes two StringBuilder and produces new StringBuilder without building anything.



  • @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler StringBuilder only works if you build from the beginning to the end. I'd need something more like a DoubleEndedStringBuilder and a + operator that takes two StringBuilder and produces new StringBuilder without building anything.

    Sooo.. linked lists with strings?



  • @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler StringBuilder only works if you build from the beginning to the end. I'd need something more like a DoubleEndedStringBuilder and a + operator that takes two StringBuilder and produces new StringBuilder without building anything.

    :eek: :trwtf: ⬆


  • Banned

    @Mason_Wheeler that, or pass around a single instance of StringBuilder around the entire program top to bottom to be touched by everyone on the way (and hope nobody removes anything from it, only adds). Which sounds less WTF-y?

    Also, it would be very nice if the entire ecosystem stopped forcing me to return intermediate strings. Why bother with StringBuilder when I have to turn them into strings on every step of the way anyway?



  • @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler that, or pass around a single instance of StringBuilder around the entire program top to bottom to be touched by everyone on the way (and hope nobody removes anything from it, only adds). Which sounds less WTF-y?

    :wtf_owl:

    Why do you need that to create a single log entry ⁉


  • Banned

    @Mason_Wheeler There's a thread, there's a handler object, there's one or more data objects, there's one or more operations that were performed, and I want them all nicely described by type and important parameters. How do you do this without making shitton of intermediate strings?

    Edit: oh, and date and time. Forgot about date and time, the most important aspect.

    Though I admit, I was talking more in general about string construction, where you can have really complicated things, like entire documents and such.



  • @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler There's a thread, there's a handler object, there's one or more data objects, there's one or more operations that were performed, and I want them all nicely described by type and important parameters. How do you do this without making shitton of intermediate strings?

    By having each individual component that has something relevant to say write its own log entry.

    Edit: oh, and date and time. Forgot about date and time, the most important aspect.

    You should forget about date and time. Don't put that in the log message; let the logging framework take care of it for you.



  • @Carnage said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler StringBuilder only works if you build from the beginning to the end. I'd need something more like a DoubleEndedStringBuilder and a + operator that takes two StringBuilder and produces new StringBuilder without building anything.

    Sooo.. linked lists with strings?

    Trees with/of strings.

    String1 + String2 ==>    String12
                            /        \
                     String1          String2
    

    Then do a tree traversal at the end to reify it (if that's even necessary: it mostly would be for substring searching, but if you're putting it on an output stream you could just do it leaf by leaf).
    Wait: DAGs with/of strings

    String12 = String1 + String2;
    String31 = String3 + String1;
    String22 = String2 + String2;
    ==>
    
            String31         String12   String22
           /        \       /        \     ||
    String3          String1          String2
    

    Edit: Of course text is harder...


  • BINNED

    @Gąska said in NetBeans vs UTF-8:

    @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf takeaway: computers would work so much better if they didn't have to cater to humans.

    I'm pretty sure over 90% of computational power in the world is spent on producing text.

    Yes, but that could be cut a lot if people used the right string concatenation data structure/algorithm. Schlemiel the Painter has a lot to answer for!

    If any programming language allowed easy creation of non-Shlemiel strings by lazy-evaluating the billion concatenations across multiple stack frames required to produce a log line, I'd use Shlemiel less.

    "A log line" sounds like the kind of length for which O(n^2) isn’t really relevant, unless you really need high performance.

    @Gąska said in NetBeans vs UTF-8:

    more like a DoubleEndedStringBuilder

    Maybe a rope? (Never used it, so idk)

    :hanzo: one minute


  • Banned

    @topspin said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf takeaway: computers would work so much better if they didn't have to cater to humans.

    I'm pretty sure over 90% of computational power in the world is spent on producing text.

    Yes, but that could be cut a lot if people used the right string concatenation data structure/algorithm. Schlemiel the Painter has a lot to answer for!

    If any programming language allowed easy creation of non-Shlemiel strings by lazy-evaluating the billion concatenations across multiple stack frames required to produce a log line, I'd use Shlemiel less.

    "A log line" sounds like the kind of length for which O(n^2) isn’t really relevant, unless you really need high performance.

    The kinds of projects I work on log about 150 lines per second on average.


  • Notification Spam Recipient

    @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler StringBuilder only works if you build from the beginning to the end. I'd need something more like a DoubleEndedStringBuilder and a + operator that takes two StringBuilder and produces new StringBuilder without building anything.

    Are we talking about porn again???

    Edit:

    @Gąska said in NetBeans vs UTF-8:

    @Mason_Wheeler that, or pass around a single instance of StringBuilder around the entire program top to bottom to be touched by everyone on the way (and hope nobody removes anything from it, only adds). Which sounds less WTF-y?

    Yep, definitely talking about porn now.


  • Considered Harmful

    @Mason_Wheeler said in NetBeans vs UTF-8:

    You should forget about date and time. Don't put that in the log message; let the logging framework take care of it for you.

    There is no universal truth. I've torn a fair few beard hairs because logger timestamps were 200 ms after the event I was supposed to match with a cause in another thread. Managed concats are faster for very small strings or under low memory conditions, also thread stalls and possibly I/O congestion.

    I'd argue the hard problem is logging the relevant things while reducing the amount of "success fluff", so instead of logging everything (:phb: more data!) and then wading through millions of logs and entries (or having :asok: do that in a devil may care fashion) you have a concise representation of what was going on.


  • Java Dev

    @topspin said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    @dkf takeaway: computers would work so much better if they didn't have to cater to humans.

    I'm pretty sure over 90% of computational power in the world is spent on producing text.

    Yes, but that could be cut a lot if people used the right string concatenation data structure/algorithm. Schlemiel the Painter has a lot to answer for!

    If any programming language allowed easy creation of non-Shlemiel strings by lazy-evaluating the billion concatenations across multiple stack frames required to produce a log line, I'd use Shlemiel less.

    "A log line" sounds like the kind of length for which O(n^2) isn’t really relevant, unless you really need high performance.

    I have never seen the need on loglines (which typically are only one or two cache lines so everything stays in cache and the cost is negligible) but when writing stuff like large SQL queries I use open_memstream which gives me a file interface which is flushed to a character array when flushing the file:

    char * sqlstring;
    size_t sqlsize;
    FILE * sqlfp = open_memstream( &sqlstring, &sqlsize );
    
    fprintf( sqlfp, "SELECT ..." );
    /* I do generate multi-kilobyte SQL on occasion */
    fputc( sqlfp, '\0' );
    fflush( sqlfp );
    do_sql( sqlstring, ... );
    rewind( sqlfp );
    /* ready for reuse */
    

  • Banned

    @levicki said in NetBeans vs UTF-8:

    @topspin said in NetBeans vs UTF-8:

    it’s based on the async/await model.

    :vomit:

    Care to elaborate?

    @Gąska said in NetBeans vs UTF-8:

    The kinds of projects I work on log about 150 lines per second on average.

    :vomit: :vomit:

    #metoo. Unfortunately, there really is no other way if we want to debug reasonably fast. There's just too many moving parts working in parallel.



  • @dkf said in NetBeans vs UTF-8:

    Greater sins would be possible if you know that char is unsigned. "Fortunately", that's rare.

    Last year I needed to fix a small library to work in a compiler where char was unsigned



  • @topspin said in NetBeans vs UTF-8:

    Compared to a stackfull coroutine which is almost as expensive as an OS thread because, while manually scheduled, it needs a full stack which is typically at least 1MB.
    If I’m not mistaken it’s based on the async/await model.

    I hate it when coroutines are presented as "light-weight threading", or if the term "async" is used in relation with coroutines. That's the usual starting point for the "coroutines are useless, just use threads" bullshit which IMHO completely misses the point. The two have entirely different purposes: if you want asynchronicity, use threads. Use coroutines if you specifically want synchronous operation but more control over execution order than just "execute this from top to bottom".

    Yes you can do pretend multithreading wit coroutines (by essentially writing your own scheduler), and yes you can do pretend coroutines with threads (by completely synchronizing execution between different threads). Both of these are at best implementation details, and at worst poor work-arounds / ugly hacks.


  • Discourse touched me in a no-no place

    @ixvedeusi The key benefit of a coroutine is that it lets you convert a bunch of cooperating functions into one and convert a whole bunch of control variables into your execution position within the coroutine. For some problems, this is a massive simplification and makes the actual algorithm much easier to comprehend. Technically, you never need them; you can always write the code without coroutines. But some problems are just so contorted if you do it that way (and there are standard functions for the cases where you don't need coros, of course).


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    @topspin said in NetBeans vs UTF-8:

    Compared to a stackfull coroutine which is almost as expensive as an OS thread because, while manually scheduled, it needs a full stack which is typically at least 1MB.
    If I’m not mistaken it’s based on the async/await model.

    I hate it when coroutines are presented as "light-weight threading"

    Note that it was quite accurate description back when coroutines were invented. A lot of IT terminology aged poorly.

    or if the term "async" is used in relation with coroutines.

    Coroutines are asychronous. They just don't run in parallel.

    That's the usual starting point for the "coroutines are useless, just use threads" bullshit which IMHO completely misses the point.

    Though not because it's wrong, but because it confuses stackful coroutines with stackless coroutines.

    The two have entirely different purposes: if you want asynchronicity, use threads. Use coroutines if you specifically want synchronous operation but more control over execution order than just "execute this from top to bottom".

    Most of the time, one uses coroutines when they don't want to precisely control the execution order. And rightly so.

    Yes you can do pretend multithreading wit coroutines (by essentially writing your own scheduler), and yes you can do pretend coroutines with threads (by completely synchronizing execution between different threads). Both of these are at best implementation details, and at worst poor work-arounds / ugly hacks.

    Respectfully disagree with this entire section.


  • Banned

    @dkf said in NetBeans vs UTF-8:

    @ixvedeusi The key benefit of a coroutineasync/await is that it lets you convert a bunch of cooperating functions into one and convert a whole bunch of control variables into your execution position within the coroutine.

    FTFY. There are some kinds of coroutines that behave nothing like callback chains (generators come to mind).

    Technically, you never need them; you can always write the code without coroutines.

    Wrong. Unless you consider a manual implementation of a state machine that behaves 100% identical to a coroutine not a coroutine.


  • Discourse touched me in a no-no place

    @Gąska My point was that you can build all the state machine and pass state vectors around and twiddle it around to make it work, but it is a lot of effort to do so and it often makes things more confusing. The effect is particularly acute when you have multiple instances of these things about and they are transferring messages back and forth. (The stuff with the state vectors is particularly tricky when dealing with object lifetimes, as you can no longer use scopes to simplify the problem.)

    That transform to state machine/vector form? That's what the compiler does for you. It is better at such work than you are.


  • Banned

    @dkf I was thinking of coroutines more from a conceptual point of view, as a function/functor object that contains suspension points - not any concrete implementation thereof. While you seem to talk about that state machine transformation thing specifically. In that case, yes, you're absolutely correct in saying it's a much nicer way to express the callback chain pattern.



  • @Gąska said in NetBeans vs UTF-8:

    I hate it when coroutines are presented as "light-weight threading"

    Note that it was quite accurate description back when coroutines were invented.

    No, it never was. Co-operative multitasking was one of the use cases that popularized coroutines, and has nothing to do with threads, which are a means to implement pre-emptive multitasking, a different beast entirely.

    @Gąska said in NetBeans vs UTF-8:

    Coroutines are asychronous. They just don't run in parallel.

    No they are not (at least not according to wiktionary's definition). When you call a coroutine, that call will not return execution to the caller until the coroutine stops executing (by either terminating or suspending itself). By analyzing the program source, without any outside information, you can figure out exactly what will be executed in which order. This is not the case for threads, where execution order depends on the environment or may even not be clearly defined.

    @Gąska said in NetBeans vs UTF-8:

    That's the usual starting point for the "coroutines are useless, just use threads" bullshit which IMHO completely misses the point.

    Though not because it's wrong, but because it confuses stackful coroutines with stackless coroutines.

    On the contrary, because it is utterly wrong and shows that the writer completely misses the point of coroutines. Coroutines are valuable programming constructs of their own which have nothing to do with threads and are very cumbersome to fake by using threads.

    @Gąska said in NetBeans vs UTF-8:

    Most of the time, one uses coroutines when they don't want to precisely control the execution order. And rightly so.

    Then most of the time one uses coroutines as a poor excuse for threads and should instead just go ahead and do full-out multi-threading.

    @Gąska said in NetBeans vs UTF-8:

    @ixvedeusi The key benefit of a coroutineasync/awaitcoroutine is that it lets you convert a bunch of cooperating functions into one and convert a whole bunch of control variables into your execution position within the coroutine.

    FTFTFY. You are wrong and you should feel wrong. Async/await is one syntax construct for the "possibly-asynchronous-or-maybe-faked-using-coroutines" brainworm. Coroutines, by themselves, have no notion of, nor any need for, "await". When execution is returned to the caller, the current part of the processing is done, there is nothing left to "await" on.

    ETA, just to avoid confusion: in the most generic sense of coroutines, execution can also return to somewhere else than the caller. But still, at that point the current step of the coroutine is completed and done with, and there's nothing to "wait" for. Similarly, the caller (or some other code) may decide to resume the coroutine (at the point it last stopped or potentially some other point). Again, the coroutine will do some work and then suspend (or return), and we're back where we started.


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    I hate it when coroutines are presented as "light-weight threading"

    Note that it was quite accurate description back when coroutines were invented.

    No, it never was. Co-operative multitasking was one of the use cases that popularized coroutines, and has nothing to do with threads, which are a means to implement pre-emptive multitasking, a different beast entirely.

    16-bit Windows had cooperative threads. Coroutines are more about using program's own scheduler instead of OS's scheduler.

    @Gąska said in NetBeans vs UTF-8:

    Coroutines are asychronous. They just don't run in parallel.

    No they are not (at least not according to wiktionary's definition).

    Wiktionary is a general dictionary, not a technical dictionary. As many other things in IT, asynchronicity has a slightly different meaning from the general language.

    Asynchronous means not having a specified order of execution. When you create two coroutines and hand them off to an external scheduler, the order in which the two coroutines execute is unspecified (except for synchronization points - awaits, joins, etc.) It can be different on each run, and you can't be sure which one will be resumed after the current one suspends (the scheduler is free to push one of them to completion throughout multiple suspensions before even starting the other, if circumstances allow it). The consequence is that you cannot rely at any point throughout your coroutine that a specific part of another coroutine has or hasn't executed yet, unless there's an explicit synchronization point in place. That's what make them asynchronous. Doesn't need to be actually parallel.

    By analyzing the program source, without any outside information, you can figure out exactly what will be executed in which order.

    Well, by analyzing the source code of the system scheduler and the design of the CPU, you can theoretically figure out exactly in which order and on which cores the individual threads will be executed, too. But the point is that conceptually there is no such guarantee. Much like in C++ there is no guarantee in which order the function arguments will evaluate, even though every compiler evaluates them in fixed order.

    And your statement assumes external events (user input, network traffic, CPU load) doesn't alter the coroutine scheduler's decisions, which is almost always false.

    @Gąska said in NetBeans vs UTF-8:

    That's the usual starting point for the "coroutines are useless, just use threads" bullshit which IMHO completely misses the point.

    Though not because it's wrong, but because it confuses stackful coroutines with stackless coroutines.

    On the contrary, because it is utterly wrong and shows that the writer completely misses the point of coroutines. Coroutines are valuable programming constructs of their own which have nothing to do with threads and are very cumbersome to fake by using threads.

    Nah, not really. Rewriting any given async/await code into threads is trivial (just substitute await with spawn(...).join() and you're done), and the code would read almost the same - it's just that the performance would suck.

    @Gąska said in NetBeans vs UTF-8:

    Most of the time, one uses coroutines when they don't want to precisely control the execution order. And rightly so.

    Then most of the time one uses coroutines as a poor excuse for threads and should instead just go ahead and do full-out multi-threading.

    Bullshit. Why would I ever want to create 12 threads when only one is ever active at the time and the other 11 are sleeping? Because that's what async/await is usually used for.

    @Gąska said in NetBeans vs UTF-8:

    @ixvedeusi The key benefit of a coroutineasync/awaitcoroutines is that it lets you convert a bunch of cooperating functions into one and convert a whole bunch of control variables into your execution position within the coroutine.

    FTFTFY. You are wrong and you should feel wrong. Async/await is one syntax construct for the "possibly-asynchronous-or-maybe-faked-using-coroutines" brainworm. Coroutines, by themselves, have no notion of, nor any need for, "await". When execution is returned to the caller, the current part of the processing is done, there is nothing left to "await" on.

    That's exactly my entire fucking point here. There is only one class of coroutines that is equivalent to a callback chain, and that is what the async/await pattern encodes. The other use cases for coroutines, while they also can be substituted with a mundane synchronous imperative code, that imperative code would certainly not make use of "a bunch of cooperating functions".

    ETA, just to avoid confusion: in the most generic sense of coroutines, execution can also return to somewhere else than the caller.

    That's wrong too. Lazy computations return somewhere else and aren't coroutines.


  • ♿ (Parody)

    @Gąska said in NetBeans vs UTF-8:

    Asynchronous means not having a specified order of execution. When you create two coroutines and hand them off to an external scheduler, the order in which the two coroutines execute is unspecified (except for synchronization points - awaits, joins, etc.)

    That's layering asynchronicity on top of coroutines, not a feature of the coroutines themselves. The same thing happens with passing off any other function to an asynchronous / cooperative multitasking getup.


  • Banned

    @boomzilla fair enough. Coroutines are about suspension first and foremost (and technically only). But they're most commonly used in contexts where asynchronicity is needed, because suspension isn't very useful elsewhere (well, they're useful for generators too, but that's pretty much it).

    The big difference between regular functions and coroutines in asynchronous context is that the state of the program can change between suspension points, and the programmer needs to be aware of that. In a regular function, nothing else can happen (on the same thread) until you return.


  • ♿ (Parody)

    @Gąska I guess you could say that cooperative multitasking turns everything into coroutines.


  • Banned

    @boomzilla well, yes, because you add suspension points.



  • @boomzilla said in NetBeans vs UTF-8:

    @Gąska I guess you could say that cooperative multitasking turns everything into coroutines.

    cooperative multitasking isn't a bad idea for programs that fit that model well. It's even not necessarily a bad thing for operating systems so long as everyone is playing along. It does fall down when one person stops playing the cooperative game, either through mallice, or incopetence. which is why modern operating systems are preemptively multitasked.

    but within one app, cooperative multitasking can still be made to do amazing things. like NodeJS! :-)



  • @Gąska said in NetBeans vs UTF-8:

    When you create two coroutines and hand them off to an external scheduler,

    And this is where you're off path. I've been talking about coroutines, which doesn't involve any such thing as an "external scheduler". You've been talking about fake-threads-maybe-implemented-using-coroutines, which is one application of coroutines among many other. Conceptually these are threads, not coroutines, and should be thought of as such. The fact that coroutines are involved is an implementation detail. This essentially is the primary point I've been trying to make: there are other applications to coroutines than pretending to do multi-threading. A good example is generator functions in python.

    @Gąska said in NetBeans vs UTF-8:

    Nah, not really. Rewriting any given async/await code into threads is trivial (just substitute await with spawn(...).join() and you're done), and the code would read almost the same - it's just that the performance would suck.

    Yes, this is easy because the hard part of faking threading with coroutines (i. e. writing a scheduler) has already been done. On the other hand, faking coroutines with threads is cumbersome because you have to manually synchronize, because coroutines are not asynchronous; you'd need to layer a scheduler on top of them to make them appear so.

    @Gąska said in NetBeans vs UTF-8:

    Bullshit. Why would I ever want to create 12 threads when only one is ever active at the time and the other 11 are sleeping? Because that's what async/await is usually used for.

    That's an implementation detail. In such a case you should use async / await, and not coroutines, because you want threading semantics, not coroutine semantics. The implementation may decide to provide threading semantics using coroutines or os threads. In a way os threads are just coroutines with a "yield" after each instruction, plus a scheduler which makes them behave like threads rather than coroutines.



  • @Vixen said in NetBeans vs UTF-8:

    but within one app, cooperative multitasking can still be made to do amazing things. like NodeJS! :-)

    wtf I hate cooperative multitasking now



  • @hungrier said in NetBeans vs UTF-8:

    @Vixen said in NetBeans vs UTF-8:

    but within one app, cooperative multitasking can still be made to do amazing things. like NodeJS! :-)

    wtf I hate cooperative multitasking now

    come to the dark side of programming.

    c65a4d90-e468-4e32-a5a2-5a8edfa4790a-image.png


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    In a way os threads are just coroutines with a "yield" after each instruction, plus a scheduler which makes them behave like threads rather than coroutines.

    In C# or JS, yes. In Rust or C++, for example, there is no scheduler by default and async functions are just plain old coroutines and you can do with them whatever you would want to do with a coroutine.


  • ♿ (Parody)

    @Gąska said in NetBeans vs UTF-8:

    @ixvedeusi said in NetBeans vs UTF-8:

    In a way os threads are just coroutines with a "yield" after each instruction, plus a scheduler which makes them behave like threads rather than coroutines.

    In C# or JS, yes. In Rust or C++, for example, there is no scheduler by default and async functions are just plain old coroutines and you can do with them whatever you would want to do with a coroutine.

    Huh? Sorry, your response doesn't make any sense to me in the context of @ixvedeusi's post.



  • @Gąska said in NetBeans vs UTF-8:

    because suspension isn't very useful elsewhere

    Apparently this is where we disagree. It's something I've been missing a lot in various situations, there's quite a few situations where I find it really convenient to make code much easier to follow.

    @Gąska said in NetBeans vs UTF-8:

    C++, for example, there is no scheduler by default and async functions are just plain old coroutines and you can do with them whatever you would want to do with a coroutine.

    I don't know about Rust, but in C++ there's no such thing as coroutines to my knowledge, There is std::async which launches asynchronous operations, which is something different as I've repeatedly pointed out. There's no way to return from the middle of a function and then continue execution at that point some time later, which is coroutines. Or have I missed some recent addition to the standard?


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    because suspension isn't very useful elsewhere

    Apparently this is where we disagree. It's something I've been missing a lot in various situations, there's quite a few situations where I find it really convenient to make code much easier to follow.

    Well, I don't claim I've seen every situation ever, so maybe there are other use cases (and I'd absolutely love to hear all about them!) But in my experience, it was just async I/O and generators.

    @Gąska said in NetBeans vs UTF-8:

    C++, for example, there is no scheduler by default and async functions are just plain old coroutines and you can do with them whatever you would want to do with a coroutine.

    I don't know about Rust, but in C++ there's no such thing as coroutines to my knowledge,

    There will be next year.


  • Banned

    @ixvedeusi okay, there was this one time I've experimented with Lua coroutines to implement a battle system in RPG game where the combat scripts could issue commands like "play this animation" which would suspend the script execution until the animation finished. But that's very very similar to async I/O use case.



  • @Gąska said in NetBeans vs UTF-8:

    so maybe there are other use cases (and I'd absolutely love to hear all about them!)

    Mostly I've come to see the interest of coroutines by playing around with Python generators. An example I've recently encountered is handling drag-and-drop. You have to handle that in the GUI thread, which needs to continue running during the various drag-and-drop related events.

    Without coroutines, you'll have to define some structure which holds the state, and several functions to handle the different phases: one for initiating the drag, one for handling the dragging, one for releasing the drag. These function have an implicit dependency on each other: they must be called in the right order, so that the current state matches what's expected by the operation. In C++ I'd define a class with member functions for each state, but this leads to a lot of boiler-plate, requires you to split into several functions what's conceptually a single, continuous operation, and you have to either trust the caller to respect the order or do lots of state validation; plus you have to carry around all that state, which an lead to a messy, relatively long-winded class.

    With coroutines, you can implement the whole shebang in a single coroutine. State is tracked on the coroutine's stack frame, execution order is guaranteed by the coroutine semantics; to follow the evolution of the local state you can simply read the function because everything is local. You initially just handle the initial mouse-down, then yield. The GUI handling code resumes the coroutine for each mouse move that comes in, and once more for the mouse-release.

    Another example is a tokenizer-parser chain: The tokenizer loops through the input stream and yields every time a complete token is recognized. The parser in turn loops through the tokens generated and yields for each AST element constructed. Each of these steps may take one or more input elements and requires state between iterations to track the current progress. With coroutines, you can just write each of the stages like a normal loop and use the local stack frame for keeping track of state. Without, you can only return once, so you have to segment the whole thing into parts in ways that break the logical cohesion.

    @Gąska said in NetBeans vs UTF-8:

    There will be next year.

    Yay! I had heard some early rumors about this but thought it had gotten lost between standards committee bickering and the shouts of the "just use threads" clowns.... didn't think it had made it through to standardization yet. Now I just need to wait for a C++20 compliant compiler...


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    so maybe there are other use cases (and I'd absolutely love to hear all about them!)

    Mostly I've come to see the interest of coroutines by playing around with Python generators. An example I've recently encountered is handling drag-and-drop. You have to handle that in the GUI thread, which needs to continue running during the various drag-and-drop related events.

    Without coroutines, you'll have to define some structure which holds the state, and several functions to handle the different phases: one for initiating the drag, one for handling the dragging, one for releasing the drag. These function have an implicit dependency on each other: they must be called in the right order, so that the current state matches what's expected by the operation. In C++ I'd define a class with member functions for each state, but this leads to a lot of boiler-plate, requires you to split into several functions what's conceptually a single, continuous operation, and you have to either trust the caller to respect the order or do lots of state validation; plus you have to carry around all that state, which an lead to a messy, relatively long-winded class.

    With coroutines, you can implement the whole shebang in a single coroutine. State is tracked on the coroutine's stack frame, execution order is guaranteed by the coroutine semantics; to follow the evolution of the local state you can simply read the function because everything is local. You initially just handle the initial mouse-down, then yield. The GUI handling code resumes the coroutine for each mouse move that comes in, and once more for the mouse-release.

    Well, I wouldn't want to implement drag'n'drop with coroutines. From a high level (looking at user actions, not individual controls), there is really nothing to do in the start or drag phase - the action only happens when you drop the object, so it can be just a single function. From a low level (looking at the individual controls), there is way too much going on. Dropping isn't the only thing that can happen during drag: for example, the user might cancel the drag with Escape, or the user might drag the content outside the current window (which isn't handled with the same pipeline as in-window drag in most frameworks, IIRC), or there can be some other event that alters the layout of the window and invalidates the current drag position without issuing a drag event. Basically, there's more than one entry point for the mid-drag state, and coroutine isn't a good fit for that situation. Not to mention I'm a big fan of functional-reactive UIs, so I'd design it so the fact of dragging is part of the overall state of the application, and each control individually is responsible for updating its own state in reaction to it, without anyone from the above telling it what to do.

    Another example is a tokenizer-parser chain: The tokenizer loops through the input stream and yields every time a complete token is recognized. The parser in turn loops through the tokens generated and yields for each AST element constructed. Each of these steps may take one or more input elements and requires state between iterations to track the current progress. With coroutines, you can just write each of the stages like a normal loop and use the local stack frame for keeping track of state. Without, you can only return once, so you have to segment the whole thing into parts in ways that break the logical cohesion.

    A valid use case, though for me, it falls under generators: the coroutine does nothing until it's called, and when it's called, it yields the next element, then stops.



  • @Gąska said in NetBeans vs UTF-8:

    Well, I wouldn't want to implement drag'n'drop with coroutines.

    To each their own, I guess. For the limited use case I had (dragging something around in a single view) it worked quite nicely.

    @Gąska said in NetBeans vs UTF-8:

    the user might cancel the drag with Escape

    Just needs a way to stop the coroutine prematurely. In Python that would involve an exception. Other things you mention might be a bit more involved though. Still don't seem too difficult if you have a way to pass data into the coroutine when you resume it, but weren't concerns I had to cope with.

    @Gąska said in NetBeans vs UTF-8:

    I'm a big fan of functional-reactive UIs

    Not familiar with that approach, I haven't been doing much UI work recently. I'll admit I've always been somewhat doubtful about the suitability of functional programming for GUIs. Any introductory reading you could point me to?

    @Gąska said in NetBeans vs UTF-8:

    the fact of dragging is part of the overall state of the application

    It is, also in my case, and that part of the state is represented by a suspended coroutine and its associated stack.

    @Gąska said in NetBeans vs UTF-8:

    A valid use case, though for me, it falls under generators:

    Agreed on that; generators are one of the other use cases for coroutines, apart from pseudo-multi-threading, and IMHO one that is most often undeservedly forgotten when people talk about coroutines. If you want asynchronous operation, most environments provide something for that so you can get by without coroutines; but generators kind of require coroutines, there's not much else that cuts it.

    @Gąska said in NetBeans vs UTF-8:

    the coroutine does nothing until it's called, and when it's called, it yields the next element, then stops.

    This is kinda the essence of what coroutines are actually all about, and the coroutines part of async stuff works exactly like that; it's the scheduler which makes them "seem" like separate threads of execution.


  • Banned

    @ixvedeusi said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    I'm a big fan of functional-reactive UIs

    Not familiar with that approach, I haven't been doing much UI work recently. I'll admit I've always been somewhat doubtful about the suitability of functional programming for GUIs. Any introductory reading you could point me to?

    Well, FRP doesn't really have much to do with functional programming per se. It's just a pattern for separating the "business" state, the data you actually care about, from the GUI state, which is derived straight from the "business" data and nothing else - so that identical "business" state always yields identical view. All inputs are translated into events that are handled by the "business" logic, which changes the "business" state and triggers UI refresh, which recalculates all the controls as if it was the first time they're presented (there might be some optimizations in place to only redraw controls that could have changed). The important part is that this event->state change->redraw pipeline is the only way the UI can ever ever ever change in any way.

    If you're familiar with JS, here's a fairly decent FRP tutorial using specifically RxJS and React. It assumes you already have some knowledge of React, but honestly it really shouldn't be that hard to figure out the bits and pieces as you go.


  • Discourse touched me in a no-no place

    @ixvedeusi said in NetBeans vs UTF-8:

    but generators kind of require coroutines, there's not much else that cuts it.

    You can hack it with threads and synchronized comms, but it is ugly. Did that once in Java where it allowed me to greatly simplify a critical bit of processing for the project I was on, but that was dirty hackery and I'm not proud of it aside from it being a bit that then started working reliably (which is nice). Never underestimate the power of modelling state via the traditional structured programming control flow graph!


  • Discourse touched me in a no-no place

    @Gąska said in NetBeans vs UTF-8:

    The important part is that this event->state change->redraw pipeline is the only way the UI can ever ever ever change in any way.

    How is this different from MVC and MVVM?



  • @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    The important part is that this event->state change->redraw pipeline is the only way the UI can ever ever ever change in any way.

    How is this different from MVC and MVVM?

    as i understand it (probably incorrectly) it really isn't from a technical level except in so far as the various libraries have defined how they work with it.... it's more what you would call a philosophy than actual rules


  • Banned

    @dkf said in NetBeans vs UTF-8:

    @Gąska said in NetBeans vs UTF-8:

    The important part is that this event->state change->redraw pipeline is the only way the UI can ever ever ever change in any way.

    How is this different from MVC and MVVM?

    ViewModel has no persistent state of its own - all fields are derived straight from "business state" and nothing else. Of course nothing stops you from doing your WPF ViewModels in such way (and I highly recommend so!)



  • @Vixen said in NetBeans vs UTF-8:

    @hungrier said in NetBeans vs UTF-8:

    @Vixen said in NetBeans vs UTF-8:

    but within one app, cooperative multitasking can still be made to do amazing things. like NodeJS! :-)

    wtf I hate cooperative multitasking now

    come to the dark side of programming.



  • @ixvedeusi said in NetBeans vs UTF-8:

    I'll admit I've always been somewhat doubtful about the suitability of functional programming for GUIs. Any introductory reading you could point me to?

    If you want to try a functional language built around this concept: https://guide.elm-lang.org/


Log in to reply