News for hackers. Stuff that matters.
Re:Ruby Methods Are Colorless by vlucas on Tuesday July 23, 2024 @05:43PM (#41051270)
Long-time JS/TS/Node programmer here.

Knowing ahead of time which functions are async is a feature.

It's a big neon sign that says "hey, this function call is expensive". This is a good thing for programmers to easily see and know at the call site.

If you make multiple calls with async/await in a row, the performance issues are plainly obvious at the call site. With "colorless" functions, this information is hidden in a deeper layer. You have to know what the function does on the inside to even know what its performance impacts are.

Also, a nitpick - you can call async functions from sync ones, you just can't access the return value. Sometimes, you don't need to.

Re:Ruby Methods Are Colorless by throw10920 on Tuesday July 23, 2024 @07:57PM (#41052313)
> Knowing ahead of time which functions are async is a feature.

"Expensive" is subjective and should be up to the programmer to decide.

And, it absolutely should not require creating two identical function definitions to get around the function coloring problem - that's completely indefensible.

> This is a good thing for programmers to easily see and know at the call site.

Yes, and the IDE can show you that information, exactly like it does the types of arguments. We don't redundantly write the types of arguments at the call site because it's a good thing for programmers to see (which it is), we let the IDE do that.

Re:Ruby Methods Are Colorless by mattigames on Tuesday July 23, 2024 @09:31PM (#41052823)
Why have Json? We can always use binary to save a lot of space and bandwidth and the IDE will always compile it into plain text for us, why have underscore at the beginning of private variables? We can let the IDE do that, we even have long named functions instead of single letter ones? Most IDEs can read the jsdocs and give us a long description of what every function does, and I could go on and on. At the end it's a balance and subjective preferences of what you want to be immediately visible or something a bit more obscure (e.g. when you move your mouse over a variable)
Re:Ruby Methods Are Colorless by throw10920 on Tuesday July 23, 2024 @10:50PM (#41053204)
> Why have Json? We can always use binary to save a lot of space and bandwidth and the IDE will always compile it into plain text for us

Yes, this is a great idea, and people would do it if there was widespread support for a binary structured format.

The difference between this incredibly ignorant sarcasm and my point is that IDEs already support the thing that I'm suggesting. You can already hover over a method and it'll give you information about the types of the arguments and return values that are specific to the call site.

> At the end it's a balance and subjective preferences

...and you completely missed the main point of my comment, which was not about what information to show, but avoiding duplication due to function coloring:

> And, it absolutely should not require creating two identical function definitions to get around the function coloring problem

Re:Ruby Methods Are Colorless by CGamesPlay on Tuesday July 23, 2024 @10:47PM (#41053190)
> And, it absolutely should not require creating two identical function definitions to get around the function coloring problem - that's completely indefensible.

I'm afraid I don't follow. It's impossible for you to have two identical functions (one sync and one async), since then they would both be sync. What did you mean?

Re:Ruby Methods Are Colorless by throw10920 on Tuesday July 23, 2024 @10:53PM (#41053223)
Two functions that are identical up to one of them being async and using "await" to call another function foo_async, and the other that is sync and calling foo_sync (a synchronous version of foo_async) without await?
Re:Ruby Methods Are Colorless by CGamesPlay on Tuesday July 23, 2024 @11:03PM (#41053269)
I think the only place that happens is in programming languages where you actually can choose to do something using a thread-blocking operation? Specifically, I've only seen it in Python. And yeah, it's not very ideal there. In other languages, it's typically only possible to do the operation in async mode, so you never write a foo_sync function in the first place.
Re:Ruby Methods Are Colorless by throw10920 on Tuesday July 23, 2024 @11:10PM (#41053303)
The "it's typically only possible to do the operation in async mode" is part of the problem. If I'm writing a a batch script that parses a file as part of its operation, I don't want or need the read_file() function to be async! My code should just block until the file opens.

Alternately, I want to be able to designate a computationally-intense function call (just that call, leaving the other calls alone) as async so that control yields to the event loop.

The main problem is that someone got it in their head that the function definition was the right place to designate whether a function was async or not, and it's not. The right place is the call site.

Re:Ruby Methods Are Colorless by spankalee on Wednesday July 24, 2024 @12:53AM (#41053725)
> The main problem is that someone got it in their head

This unnecessarily trivializes the technical problems at hand. This wasn't just something someone got in their head, especially considering...

> that the function definition was the right place to designate whether a function was async or not, and it's not. The right place is the call site.

This is exactly what JavaScript did. The program only yields at `await`ed callsites and doesn't yield at all other callsites.

`async` only tells the VM to create the state machine necessary to resume the function after `awaited` calls return.

Re:Ruby Methods Are Colorless by throw10920 on Wednesday July 24, 2024 @09:57AM (#41057184)
> This unnecessarily trivializes the technical problems at hand.

Making a language that automatically generates two versions of a function, one that is async and returns a Promise-wrapped object, and another that is sync, is not hard.

> This is exactly what JavaScript did.

No, it isn't. JavaScript requires you to declare functions as async at the function definition, and you can't call async functions from sync ones. This is exactly the thing I am arguing against, and is the opposite of "The right place is the call site."

Re:Ruby Methods Are Colorless by spankalee on Wednesday July 24, 2024 @12:33PM (#41058789)
If it wasn't hard, it would have been done. I suppose we should all await your backwards compatible proposal?

> No, it isn't.

Yes, actually, it is. Async functions are a concept that only affects the internal structure of a function - to generate the state machine that allows yielding at `await` keywords and resuming after they resolve. Externally they are no different from "sync" Promise-returning functions.

So they only thing that async functions do is enable yielding at the callsite, the `await` keyword is what actually yields at the callsite and you can await anything, not just async functions.

Again:

> I want to be able to designate a computationally-intense function call (just that call, leaving the other calls alone) as async so that control yields to the event loop.

This is what `await` is - `await` yields. Non-await calls don't yield.

Re:Ruby Methods Are Colorless by throw10920 on Wednesday July 24, 2024 @10:01PM (#41064101)
> If it wasn't hard, it would have been done.

This comment shows a true departure from reality. Computing is filled to the brim with ideas that are easy but are not implemented for reasons other than difficulty.

> I suppose we should all await your backwards compatible proposal?

Your sarcasm merely helps to further demonstrate that you're not interested in a serious discussion.

> Yes, actually, it is.

Then it should be trivial for you to show me an instance of a sync function calling an async one, synchronously waiting for it, then getting back the return value, without clever hacks.

Re:Ruby Methods Are Colorless by zogrodea on Wednesday July 24, 2024 @04:13AM (#41054709)
My experience with this is in .NET, which has methods like readFile (which is async) and readFileSync.

.NET doesn't really need to provide two separate utility methods like this though, because you can use Task.wait to block until the async task is done.

Re:Ruby Methods Are Colorless by neonsunset on Wednesday July 24, 2024 @05:53AM (#41055328)
File.ReadAllBytes/Text/Lines use synchronous underlying file API.

Their async variants call different OS APIs for asynchronous operation where available (Overlapped IO on Windows, on Linux it is specially scheduled (p)read and write calls).

A similar distinction applies to Socket where asynchronous calls use an internal epoll-based engine while synchronous ones are plain send/recv.

Generally speaking, in synchronous code there is no advantage to calling `.Wait()` or `.GetAwaiter().GetResult()` over synchronous APIs when such are offered, and if you can help it, it is best to update the code using them to be async too if your application is multi-threaded. Luckily it's quite easy in most situations unlike what HN public (that hates better languages like C#) would lead you to believe. But ff you do have to do block on waiting for a task, the impact on throughput is usually negligible if you do so within say threadpool worker - the implementation nowadays can cope with this very well and is more resilient to scenarios that used to be problematic.

Re:Ruby Methods Are Colorless by amluto on Wednesday July 24, 2024 @07:01AM (#41055675)
I sometimes wonder whether this is really an optimization problem pretending to be a coloring problem. In some sense, the sync versions of blocking things are generally better in only one way: they can be more performant (run faster, use less memory, generate shorter code, etc). [0]. If a function can be implemented in async/await style, then ISTM the compiler could treat the sync variant as an automatically generated optimization instead of as a totally different (and differently colored) variant.

Of course, in languages like Rust with multiple colors of async code (single-threaded or multithreading-capable), this would get very messy.

[0] As a major caveat, synchronous code also enforces various state transitions much more efficiently. Want to prove that IO is done (in the sense that the user code is done with it) before closing a file? This is pretty easy in single threaded blocking code.

Re:Ruby Methods Are Colorless by lmm on Wednesday July 24, 2024 @12:03AM (#41053507)
> And, it absolutely should not require creating two identical function definitions to get around the function coloring problem - that's completely indefensible.

Oh yes, absolutely. But the solution to that is stop using joke languages that can't do kind polymorphism.

> Yes, and the IDE can show you that information, exactly like it does the types of arguments.

How can it, if the language doesn't give it that information? Either you have a language that can reliably distinguish between sync and async calls in a standard way - which is to say, it has a type system that distinguishes between sync and async, whether it calls it that or not - or your IDE has an ad-hoc informally specified bug-ridden slow implementation of half of one.

Re:Ruby Methods Are Colorless by pjmlp on Wednesday July 24, 2024 @02:13AM (#41054067)
Good luck with that, when we keep using glue languages for full blown applications, and then shelling out to C extensions, instead of ones that could do the job all by themselves.
Re:Ruby Methods Are Colorless by spankalee on Wednesday July 24, 2024 @12:46AM (#41053692)
> And, it absolutely should not require creating two identical function definitions to get around the function coloring problem - that's completely indefensible.

This is very rarely necessary in app code. It's usually only a pattern for higher-level utility functions, and even then if you really wanted to you could unify implementations with generators.

Re:Ruby Methods Are Colorless by wiseowise on Wednesday July 24, 2024 @05:33AM (#41055213)
> And, it absolutely should not require creating two identical function definitions to get around the function coloring problem - that's completely indefensible.

Where do you see insanity like this?

Re:Ruby Methods Are Colorless by vips7L on Wednesday July 24, 2024 @10:00AM (#41057217)
Everywhere in the C# ecosystem. You’ll see things like x.Read() and x.ReadAsync().
Re:Ruby Methods Are Colorless by lolinder on Wednesday July 24, 2024 @10:10AM (#41057306)
That sounds more like a legacy problem than a problem with the async/await model in the abstract.

If you were designing a language from the ground up, why would you implement a synchronous read operation? I would just assume that all code written in the language will treat async the way that Haskell programmers treat IO and make all IO operations async no matter what.

Re:Ruby Methods Are Colorless by vips7L on Wednesday July 24, 2024 @10:43AM (#41057613)
There’s lot of programming models that don’t require async or it’s complexity. Not everything is a web server that needs to serve 100k requests.
Re:Ruby Methods Are Colorless by neonsunset on Wednesday July 24, 2024 @11:37AM (#41058151)
Because Read and ReadAsync are usually meaningfully different. There is nothing wrong with that.

See https://news.ycombinator.com/item?id=41055328

This bifurcation is mostly a concern for the standard library. It’s not something you do this way in your regular application code.

Re:Ruby Methods Are Colorless by dragonwriter on Wednesday July 24, 2024 @11:02AM (#41057809)
Everywhere that hard function coloring exists where the language also supports synchronous calls that do the same thing (JS doesn't support sunchronous calls for lots of things and has only soft function coloring since async is sugar for Promises, so it has two reasons why that doesn't need to happen.)
Re:Ruby Methods Are Colorless by mananaysiempre on Tuesday July 23, 2024 @06:24PM (#41051617)
> It's a big neon sign that says "hey, this function call is expensive".

IMO the more important part is that it can yield control. Half the advantage of cooperative multithreading is knowing where you may yield control makes sharing memory more or less workable.

I also like Trio’s model: if it’s async, it will yield control, even if the result is already available so it doesn’t technically have to. Makes it more difficult to accidentally starve other tasks. (I suppose I also have to mention Curio’s model: if it’s async, it’s a scheduler upcall, whether yielding or not. But for all that Curio deserves credit for freeing Python from asyncio hell, I just don’t find myself caring about things being scheduler upcalls or not.)

Re:Ruby Methods Are Colorless by newZWhoDis on Tuesday July 23, 2024 @06:38PM (#41051736)
Ruby/rails is full of shortsighted crap like this.

I feel stuck, our whole backend is legacy rails and I can’t escape.

Re:Ruby Methods Are Colorless by goatlover on Tuesday July 23, 2024 @07:26PM (#41052087)
Bit of a strong claim when the Erlang/OTP was designed to handle massive concurrency without colorful methods. Given that both Erlang and Ruby are inspired by the message passing semantics of Smalltalk.
Re:Ruby Methods Are Colorless by lmm on Wednesday July 24, 2024 @12:06AM (#41053523)
Unicoloured languages are great as long as your code doesn't have to actually do anything (which is lots of modern code, to be fair). Try writing a physics simulator or 3D renderer in Erlang and see how that goes.
Re:Ruby Methods Are Colorless by pmontra on Wednesday July 24, 2024 @04:15AM (#41054722)
Erlang is not great at math performance, also because it uses arbitrary length integers. There is a nice comparison between several languages, including Erlang at https://stackoverflow.com/questions/6964392/speed-comparison...

It all depends on how the code is written. Eventually somebody managed to make the Erlang code faster than the baseline C, then someone else made the C version 8k % faster, which proves your point. However, how is that related to using sync/async vs message passing?

Re:Ruby Methods Are Colorless by lmm on Wednesday July 24, 2024 @09:17PM (#41063881)
> Eventually somebody managed to make the Erlang code faster than the baseline C, then someone else made the C version 8k % faster, which proves your point. However, how is that related to using sync/async vs message passing?

If you want to write high-performance code then you need to be able to write synchronous code and have control over what your yield points are. If you take the "all calls are potentially async, runtime does what it wants" approach (i.e. "no function colouring") then you just will not be able to do that.

Re:Ruby Methods Are Colorless by igouy on Wednesday July 24, 2024 @01:11PM (#41059286)
> … Erlang … inspired by the message passing semantics of Smalltalk.

What makes you think that?

Re:Ruby Methods Are Colorless by goatlover on Thursday July 25, 2024 @04:18PM (#41072927)
The Wikipedia entry says Smalltalk was one of it's influences and Joe Armstrong, co-developer of Erlang, mentions message passing as the fundamental aspect of OOP that Erlang gets right.
Re:Ruby Methods Are Colorless by igouy on Thursday July 25, 2024 @07:03PM (#41074361)
The Wikipedia "Influenced by Lisp, PLEX,[2] Prolog, Smalltalk" seems to be un-sourced !

> … Joe Armstrong … mentions message passing …

Where?

Re:Ruby Methods Are Colorless by igouy on Friday July 26, 2024 @12:48PM (#41080096)
Here's something Joe Armstrong's PhD thesis does reference in the context of message passing:

"4.5 Programming Notations Based on Message Passing" p33

"Concepts and Notations for Concurrent Programming", Gregory R. Andrews and Fred B. Scheider, Computing Surveys 15(1) March 1983, pp 3 - 43

[pdf] https://www.cs.cornell.edu/fbs/publications/LangSurv.pdf

Re:Ruby Methods Are Colorless by rco8786 on Tuesday July 23, 2024 @09:41PM (#41052871)
Legacy codebases that are a joy to work with are few and far between, in any language.
Re:Ruby Methods Are Colorless by segfaltnh on Tuesday July 23, 2024 @10:03PM (#41052996)
Rails doesn't scale well in my experience. Or maybe rails devs don't scale well.

The language and framework are both centered around developer happiness, which in my experience drops off around 10,000 lines. That's about when projects start getting difficult.

Re:Ruby Methods Are Colorless by pmontra on Wednesday July 24, 2024 @03:34AM (#41054482)
A Rails project I'm working on has this LOC

  Ruby 12169
  ERB   2339
  Vue  24895
  Js    4526
The Vue frontend is indeed more complex than the Rails backend, and in my experience Vue is much simpler than React. My customer organized the Rails app with models, controllers, api/v1/controllers, jobs, services (naming only the most important stuff). It's not bad to work with.
Re:Ruby Methods Are Colorless by norman784 on Wednesday July 24, 2024 @05:29AM (#41055179)
I also work on a legacy Ruby/Rails codebase, what I dislike is Ruby as a dynamic language, I'd prefer typed languages, but overall Rails didn't changed too much in the last 14 years that I know it (I didn't used too much in the past), but the concept is still the same to this day, few changes to the API/syntax, but otherwise if you know Rails, if you know Rails, it is most likely that you find very easy to work on any Rails app.
Re:Ruby Methods Are Colorless by lta on Tuesday July 23, 2024 @08:50PM (#41052604)
> is a feature

I was quite shocked to read this, as in it never brushed my mind that it could be. I personally doesn't feel like it is and is one of the reasons why I try to avoid working with that stack at all cost.

I don't think the neon sign is a good excuse for the mess colored functions are. You easily can create a synchronous O(n^4) function, and there are probably tons of quick async functions. Moreover, your comment might be read as a free pass for using functions and methods that you're not really understanding the behavior off, it obviously doesn't sound like a good thing

The information is only hidden with colorless methods if you consider the documentation to be a place to hide information (o^o).

Re:Ruby Methods Are Colorless by slibhb on Tuesday July 23, 2024 @09:37PM (#41052853)
Async/await is clearly a feature in JS, though not for the reason the previous poster mentions. Async/await wasn't part of the language until 2017. If you don't like it, you can just use Promises. If you do that, there are no "colored function" (functions of color?).

As far as the article goes, I think the pattern in Ruby is great. I prefer it to JS. But the JS approach works fine and the whole controversy about colored functions is a little silly.

I would be interested in understanding why JS can't enable await from inside non-async functions. I (maybe naively) wonder if the compiler couldn't just figure out which functions to treat as async rather than making the programmer do it.

Re:Ruby Methods Are Colorless by spankalee on Wednesday July 24, 2024 @12:41AM (#41053669)
Using promises is basically no different than using async functions, and definitely doesn't "uncolor" your functions.

Any function that calls another that returns a Promise will have to return a Promise to represent completion correctly. That's the color.

Re:Ruby Methods Are Colorless by dragonwriter on Wednesday July 24, 2024 @10:59AM (#41057778)
> Any function that calls another that returns a Promise will have to return a Promise to represent completion correctly

No, it doesn't, closures let you update values in the wcope of the parent in .then() callbacks and then you can loop in the function and wait for completion and return a non-Promise value.

Re:Ruby Methods Are Colorless by modal-soul on Wednesday July 24, 2024 @01:44PM (#41059657)
This is not true. If your sync function loops until the value is set, then the Promise will never resolve, since it never yields to the event loop.
Re:Ruby Methods Are Colorless by dominicrose on Wednesday July 24, 2024 @04:58AM (#41054999)
With a well-configured dev env with typescript, prettier, eslint and the appropriate config, async/await does feel like a feature. The IDE adds the async keyword for you if you forget it. If you enable errors in the whole project, it will tell you of any file/function that has an inconsistency in that regard.

So yes the compiler can figure it out, but only with Typescript. For javascript, a promise it a promise, but it doesn't know that a function will return a promise until it does. You can try compiling some async/await codebase to an old ES5 version and see the mess.

Re:Ruby Methods Are Colorless by lmm on Tuesday July 23, 2024 @11:56PM (#41053483)
> The information is only hidden with colorless methods if you consider the documentation to be a place to hide information (o^o).

No, source code is where you hide the information, documentation is where you hide misinformation (or accurate information about how the function worked 3 versions ago, which is much the same thing).

Re:Ruby Methods Are Colorless by RHSeeger on Wednesday July 24, 2024 @11:52AM (#41058289)
The code tells you what the code _does_. The documentation (which can include comments in the code) tell you what the code is intended to do. Either one of those can be wrong. If the code doesn't match the documentation, then there is a bug in the system.

Not having documentation just removes the ability to determine if what the code _does_ is what the code is _intended to do_.

Re:Ruby Methods Are Colorless by lmm on Thursday July 25, 2024 @12:33AM (#41064732)
> If the code doesn't match the documentation, then there is a bug in the system.

Then I'd say the vast majority of Ruby libraries are buggy.

> Not having documentation just removes the ability to determine if what the code _does_ is what the code is _intended to do_.

But usually there isn't any intent when it comes to async-or-not. Library authors usually just write a method that results in the right value; whether that method can yield or not isn't even something they thought about, much less had a specific design in mind for.

Re:Ruby Methods Are Colorless by unscaled on Wednesday July 24, 2024 @02:41AM (#41054210)
This is not just about performance.

Unlike Go or Ruby, JavaScript is a single-threaded language. Synchronization constructs such as mutexes and semaphores are uncommon and not part of any standard library. When you are calling a synchronous function, you can be completely assured that no race condition can develop while the function is running, but the same guarantee is not true for asynchronous functions.

That's why knowing which function is running asynchronously is even more useful for languages like JavaScript.

Re:Ruby Methods Are Colorless by regularfry on Wednesday July 24, 2024 @04:51AM (#41054954)
"Now you have two problems." Adding async/await was a hack to avoid having to tackle the hard problem of real concurrency, so now you have a) no real concurrency, and b) coloured functions.

There is a parallel universe where JS added almost any other concurrency primitive and got a better trade-off than async/await.

Re:Ruby Methods Are Colorless by lolinder on Wednesday July 24, 2024 @09:52AM (#41057136)
Having interacted with a bunch of other concurrency models in a bunch of other languages, I call. Concurrency is hard, every concurrency model has flaws, and which flaws you want to live with is largely a matter of personal preference and what type of problem you are working on.

For myself, I happen to agree with OP that single threaded plus async/await has honestly been my favorite concurrency model I've ever worked with for the types of programs I tend to write (IO-bound web apps with lots of network requests and no hot loops). The property that they described of having no race conditions of any kind except where you opt into them by calling out to an explicitly tagged async function is an enormous unnecessary mental burden removed.

In other contexts with higher compute demands, a full threading model or something like Go can make a ton of sense. But it's not worth the overhead for your average web app where what you really want is to just resume when that web request finishes.

Use the right tool for the job, don't get dogmatic about programming language features in the abstract.

Re:Ruby Methods Are Colorless by unscaled on Thursday July 25, 2024 @03:24AM (#41065751)
There is a parallel universe in which Brendan Eich was given more than 10 days to hack on JavaScript, and in which he presented the language with full-blown stackful coroutines instead of hacky callbacks for concurrency. There might be even a parallel universe in which '[] + 0' produces an error rather than the string "0".

Unfortunately, we do not live in that parallel universe, and JavaScript had to evolve the way it did. When callbacks have already been established as the standard concurrency mechanism, promises were a big improvement. When promises became standard, async/await was the natural evolution rather than breaking existing programs by introducing stackful coroutines.

Other languages which chose async/await (Rust, C#, Kotlin) had their own reasons. In all of the cases above, the language designers wanted to give the user more control over the scheduler (Colorless Stackful coroutines require a global scheduler).

In Rust's case, it's async/await state machines are just not wasting memory and unnecessarily copying it like stackful coroutines do (not to mention that Rust doesn't have a garbage collector and pointer rewrites, so it cannot just copy stacks around when they grow). In fact, Rust did have garbage collection and green threads, but they were both removed early on, as the language changed its focus to became a language where you can expect performance that are _at least_ on par with C or C++.

In case of Kotlin, this all mostly had to do with finding an abstraction that can run on pre-Loom JVMs, JavaScript targets and native targets. Kotlin does not own the runtime.

Saying everybody should follow Go here is silly. Not all languages share the same background and design constraints. Go-style Stackful coroutines require garbage collection, full control of the runtime and generally a language that is designed from scratch to have them - or a 6-year project to adapt your language and runtime to have them, like Project project Loom did.

Async/await imposes some costs, but the benefits (compatibility, performance, flexibility) often outweigh these. After working with both async functions and stackful coroutines in multiple languages, I cannot say I ever felt concurrency in Go to be more ergonomic than Kotlin. If anything, it was the reverse for me in that particular case (owing to Go's lack of reification for goroutines and verbose syntax). Deciding in advance what color is my function (i.e. whether it needs to deal with I/O), is pretty simple and it rarely changes during the lifetime of a program (and even when it does, refactoring is not hard unless your design is bad).

The only case where I did feel some pain using async/await, was Rust, and this has more to do with Pin, competing async runtimes (for a while), lack of support for async traits (for a while) and other areas where Async Rust still needs some work.

Re:Ruby Methods Are Colorless by Joker_vD on Wednesday July 24, 2024 @07:58AM (#41056050)
> The information is only hidden with colorless methods if you consider the documentation to be a place to hide information (o^o)

That's exactly the mindset of quite a number of programmers nowadays, sadly. Two anecdotes: First, there was a blog post (probably even featured on HN) about problems in the design of the API of... Python's requests library, I think? It was quite a bizarre reading, complaints made almost no sense to me until I got to about the middle of the article when it clicked: the author was trying to figure out how to use the API by just reading the names of the classes, methods, and parameter names and making guesses as how it all would connect together instead of, you know, reading the docs. Which do exist, by the way.

The second example happened just yesterday at my job. In the essence, some fellow programmer added a call to function foo() which he thought would do some particular thing and return a particular answer while in reality it did not quite do that, and the return value is essentially meaningless (the function basically always returns "yep, I've scheduled do_foo() to run asynchronously some time soon"). Now, this foo() dunction is not documented, and if you read it's source (3 lines of code), it's quite obvious that its return value is useless... so why did they think it works the way they wanted it to work? When asked about it, the answer was "Well, it's named foo(), so I just thought that's what it would do". Sadly, calling strange third-party functions and hoping them to work they way you'd like them to work is no basis for writing the working programs.

Re:Ruby Methods Are Colorless by jsight on Wednesday July 24, 2024 @08:10AM (#41056134)
And of course, these developers will also complain that the project lacks documentation. Often this is the case for projects that are actually well documented, its just that the dev didn't read it.
Re:Ruby Methods Are Colorless by resonious on Wednesday July 24, 2024 @09:43AM (#41057057)
Was also going to say this. I've seen so many people fumble around figuring something else, then write a doc for how to do it, just to find that someone else wrote effectively the exact same doc 5 months ago.
Re:Ruby Methods Are Colorless by akoboldfrying on Tuesday July 23, 2024 @09:47PM (#41052899)
It's a big neon sign that says "Either this function is expensive, or it isn't but some framework somewhere that sometimes needs to call expensive functions might also need to call this function using the same syntax".
Re:Ruby Methods Are Colorless by resonious on Wednesday July 24, 2024 @09:47AM (#41057089)
This feels very true in Rust but not sure about JS. In JS you can `await` non-promise values without issue.
Re:Ruby Methods Are Colorless by lolinder on Wednesday July 24, 2024 @10:01AM (#41057228)
No, because in JavaScript/TypeScript you can happily await any function that you'd like on the chance that it sometimes returns a Promise. If a framework demands that you return a Promise unnecessarily, that's on the framework, not the language.
Re:Ruby Methods Are Colorless by zogrodea on Wednesday July 24, 2024 @04:01AM (#41054637)
I had the same opinion with async/await, that it's nice to know a function performs IO and will wait before continuing. Makes it clearer when to use Promise.all to make multiple requests in parallel and wait for all of them to finish before continuing (faster than making calls sequentially).

I kind of wish the languages I use had Haskell's IO monad too, to separate functions in terms of the type system, but that's slightly different.

You might like this article (which is my personal favourite about function colouring). https://www.tedinski.com/2018/11/13/function-coloring.html

Re:Ruby Methods Are Colorless by grumple on Wednesday July 24, 2024 @07:09AM (#41055714)
I hate that async functions are the ones we are forcing to wait and become synchronous. The naming was a failure imo.
Re:Ruby Methods Are Colorless by j-krieger on Wednesday July 24, 2024 @09:44AM (#41057063)
Not really. What it really means is that some function in this callstack is expensive. Async Await bubbles to the top of your program. Eventually, you might just read this as this application as a whole might be expensive.
Re:Ruby Methods Are Colorless by icholy on Wednesday July 24, 2024 @10:01AM (#41057225)
> Also, a nitpick - you can call async functions from sync ones, you just can't access the return value.

Or wait for them to finish.

Re:Ruby Methods Are Colorless by dragonwriter on Wednesday July 24, 2024 @10:53AM (#41057726)
> Knowing ahead of time which functions are async is a feature.

> It's a big neon sign that says "hey, this function call is expensive"

Async and expensive aren't the same thing.

> Also, a nitpick - you can call async functions from sync ones, you just can't access the return value.

That's a quirk of the particular async/await implementation in JS and not generally true of colored-function implementations. (Actually, since async/await is sugar for promises, you can actually, I’m pretty sure, both call and use syntactically async functions from ones which are syntactically not-async if you really want to, the code is just ugly.

Re:Ruby Methods Are Colorless by klysm on Wednesday July 24, 2024 @10:58AM (#41057777)
nit: I don't think _expensive_ is quite the right way to think about it. I view it as "hey, this function does IO". The actual cost of doing that IO varies immensely.
Re:Ruby Methods Are Colorless by munificent on Wednesday July 24, 2024 @11:52AM (#41058296)
> Knowing ahead of time which functions are async is a feature.

It can be, but this fact doesn't always scale well to larger APIs over time.

If you see that a function is async, any of these could be true:

1. The function does some asynchronous work.

2. The function did some asynchronous work at some point in the past, but does no longer, but changing the signature is a breaking API change, so it still looks async.

3. The function does no asynchronous work, but it's a public API and the library maintainer thinks there is a good chance it may need to do async work in the future so made it async today to reserve the right to make that change without breaking the API.

4. The function may or may not do asynchronous work, but it's part of an interface that others are allowed to implement and the designer of the interface wants to give implementers the freedom to make their implementations async if they want.

5. The function is higher-order and wants to be able to accept callbacks that are themselves async.

There are probably others I'm forgetting.

This all sounds hypothetical but it's really not. If you maintain any widely-used long-lived package, you run into design questions like this all the time.

There is always a tension between an API consumer wanting to know what a function "really" does versus the API author wanting some abstraction so that implementation details can be changed over time without breaking users.

Asynchrony is one kind of effect or observable behavior that a user/maintainer of an API may or may not want to encapsulate, but it's not the only one. The C++ standard library documents and commits to the algorithmic complexity of most functions. Haskell function signatures pin down whether or not a function does IO. Statically typed languages pin down the types parameters must be.

Pinning down more of this stuff gives the API consumer some more information, but it's not always a pure win. It calcifies the behavior of the function in ways that can harm its evolution or interact poorly with higher-order code or polymorphism. There's no silver bullet.

Personally, I've never found "does this function suspend" to be a particularly interesting effect for a function to have to commit to and the fact that it poisons the entire callstack makes it very difficult to work with in practice.

Re:Ruby Methods Are Colorless by phplovesong on Wednesday July 24, 2024 @01:17PM (#41059374)
Its a bad feature. The thing is it does not matter if its ”obvious” as anything that touches async needs to be async too. Its a bad paradigm, CSP is obviously a better way to do concurrency. As async is usually only IO bound, but how about CPU bound? In the node ecosystem CPU bound tasks are not something you do with async/await.
Re:Ruby Methods Are Colorless by vlucas on Wednesday July 24, 2024 @01:23PM (#41059436)
In node, you generally don't want to do anything CPU bound.
Re:Ruby Methods Are Colorless by lolinder on Wednesday July 24, 2024 @07:40PM (#41063384)
Yep. If you have CPU-bound work then you should use a different language. If you have IO-bound work then explicitly tagged async functions are actually a really nice concurrency model for the only kind of concurrency you need—it's equivalent to having the Haskell IO monad as a first-class language feature.
Re:Ruby Methods Are Colorless by caditinpiscinam on Wednesday July 24, 2024 @04:42PM (#41061838)
If explicitly marking expensive IO operations using async is a feature, then why don't languages with async make their "print" functions asynchronous?
Re:Ruby Methods Are Colorless by unscaled on Thursday July 25, 2024 @03:31AM (#41065806)
What about a language which has both lightweight threads, but in which every I/O operation (including printing and getting a random number) is colored?

https://www.haskell.org/tutorial/io.html