What is the etymology of `GenServer.cast`

I want to be clear:

I am not asking what GenServer.cast/2 or handle_cast/2 does… I already understand this!

I’m purely interested in the choice of words when naming this function (along with its callback, handle_cast).

I do understand the concept of casting in programming languages. You convert from one type to another. Ecto.Changeset.cast also makes sense to me—It’s casting an unknown databag into a known one.

However, cast when referring to “I’m sending out a message yet don’t want a response and don’t even care if it was received”… what is this in reference to? Like, casting a spell? I can maybe sort of relate it to the standard programming term, though it’s more like “casting into an unknown”. That would actually be a good explanation as far as I’m concerned, but what was the actual intent behind the name?

Again, I’m purely interested in the etymology here—this is not a technical question. Whether I should or not, I get very hung on and interested in language. For example, why does the Hidden Fortress tile in Roll for the Galaxy yield just one warrior?—I excepted more from discovering an entire hidden fortress!!

Thank you

7 Likes

I think @rvirding would be the one to answer this but I always personally thought of it as “casting into the unknown”. I smiled when I read thar. Possibly with an etymological relationship to “broadcast”?

5 Likes

How I see it:

To cast something, is to throw it (“let him who is without sin cast the first stone”). So you cast a message, you don’t expect a response. You’re just tossing it over like, “Here, catch this.”

To call, like calling a person, (“Hello, Joe”), you expect a response.

Definition of cast

(Entry 1 of 2)
transitive verb

1a : to cause to move or send forth by throwing

11 Likes

Although cast means “to throw,” the traditional usage of cast implies specifically that you are throwing the item with the mentality that the item will never return. This is why people don’t cast baseballs, but they do cast things into the sea, and they do cast off their chains. This is why we have “outcasts,” “castaways,” and other individuals who are presumably gone forever. It’s an excellent choice for the function in question, I think.

10 Likes

These are all great answers! I was so stuck on the data conversion meaning that I didn’t even think about “throwing”. This gives me much relief, thank you!

Edited to add: re-reading this sentence from my original post
However, cast when referring to “I’m sending out a message yet don’t want a response and don’t even care if it was received”” is now making me all :man_facepalming: :man_facepalming: :man_facepalming:

2 Likes

I honestly wouldn’t read too much into the actual call names. They needed/wanted to label two different interfaces, the completely synchronous and well-checked and the asynchronous unchecked ones.

I am guessing here as I wasn’t on the otp team (I don’t do this high-level stuff but prefer the basics :wink:).

So the basic erlang send is asynchronous and without any guarantees at all: the receiver may or may not be there and the message may or may not arrive. It really is a “send and pray”. There is in fact only guarantee and that is if you send 2 messages and both arrive they will arrive in the same order as you sent them. The gen_server/gen_statem:cast models this exactly, in fact if you look in the code it ends up just doing a raw send. So what do you call this? You could call this send as well but then people could get mixed up between it and underlying message sending. Also some OO system you send for the synchronous object call.

The name call is easier to understand. It has all the guarantees you can get: the receiver is there and alive, you will get a reply within your specified timeout and you will know if the receiver dies before it can reply. This is sort of close to remote function calls so calling it call is pretty good.

In the older now deprecated gen_fsm the calls were called send_event and sync_send_event.

It is interesting to look at the code for the synchronous gen_server:call. Check out the do_call function in the gen.erl module. It shows how easy it actually is to get this reliability. It shows how right we got the primitives :wink:

These are just my thoughts.

12 Likes

Now I wonder, as a non native English speaker, why “cast” has been chosen to mean “type conversion of some data”.

I am not native speaker either, I think typecast has special meaning in performing art. Eg: Clint Eastwood is often typecast as a cowboy.

1 Like

This is a great question with a fun answer! As I’ve heard it, the root of both “to cast” meaning to convert the type, and “to cast” meaning to throw or send is actually from the same context: Pottery. When you form a clay vessel this can be referred to as “throwing” or “casting”. This activity involves both the rapid spinning of the clay which gives us the “throwing” connotation, as well as the idea of giving something a form, which gives us the “typecast” usage.

9 Likes

It’s quite a rabbit hole, actually. Here is a pottery site explaining the use of “throw” in pottery, from the old English “thrawan.” Presumably this led to usage in other contexts, e.g. “cast iron.”

Why is it called Throwing?

Origin of “To throw”: Old Engilish - twist, to turn, to propel.

Some potters describe their work at the potters wheel as turning. The Old English word thrawan from which to throw comes, means to twist or turn. Going back even farther, the Indo-European root *ter- means to rub, rub by twisting, twist, turn. The German word drehen, a direct relative of to throw, means turn and is used in German for throwing. Because the activity of forming pots on the wheel has not changed since Old English times, the word throw has retained its original meaning in the language of pottery but has developed a completely different meaning in everyday usage. Those who say they throw pots are using the historically correct term. Those who say they turn pots are using more current language. Both are saying the same thing.

4 Likes

@rvirding Thanks so much for that detailed explanation! And thank you @benwilson512 and @Dusty for the extra info!

1 Like

Replying to @rvirding here since it’s related to his explanation that has now really sunk in, but open to anyone.

So as I understand it, the only difference between handle_cast and handle_info is that the former is used by clients who know the API of the server in question whereas the latter is used by clients who have no idea who they are sending messages to. Is the sole advantage here having a clean API for clients who know who they are dealing with, or could one theoretically just always use handle_info with send(pid, message)?

One scenario that has just occurred to me as I typed this is when communicating with servers through a module which hides the pid. That alone makes handle_cast necessary. Uhhh, I may have just answered my own question, but is there anything else I’m not thinking of??

No, sorry that’s wrong, well only partially right.

gen_server:cast and its callback handle_cast is used when sending an asynchronous request to a genserver in which there is no reply expected a or sent back to caller. It is just a “do this but don’t tell me about it”. The handle_cast is expected to return a {noreply, State}. Note that doing a gen_server:cast to a server causes the server to the handle_cast callback as they are coupled together.

The handle_info callback is called when an unrecognised message is received by the server. The server, while it may be a gen_server, is just a normal Erlang process so it can receive messages which haven’t been sent by the system or using gen_server:call/cast. For example it could be monitoring processes or nodes, or be linked to processes and trapping exits so it receive exit messages. The top-level server loop handles all messages and anything it doesn’t recognise results in it calling handle_info. This allows the users behaviour module to handle everything.

3 Likes

Hey, that’s cool, I don’t mind being wrong! :smile:

Thanks for the info (har har, get it?). My thinking was just a little off in terms of what is considered “unrecognized” but this makes sense (I was thinking exits and whatnot could be considered “recognized”). Thanks again!

1 Like

As both an Elixir developer and language nerd I can’t resist this.

For me, handle_cast always brought to mind broadcast. The throw without expecting anything back meaning makes sense too. (I guess calling it throw would be confusing because that is used in a lot of languages for exceptions.)

From the Oxford, that sense of cast is this one:

1 [usually with adverbial of direction] mainly literary throw (something) forcefully in a specified direction: he cast the book down on to the chair angrily | the fishermen cast a large net around a school of tuna | figurative : individuals who do not accept the norms are cast out from the group.

For typecasting, I always had the idea of moulding something into the shape that you want; that’s this sense (especially the third one):

4 shape (metal or other material) by pouring it into a mould while molten: when hammered or cast, bronze could be made into tools.
make (a moulded object) by casting metal: a bell was cast for the church.
arrange and present in a specified form or style: he issued statements cast in tones of reason.

Etymology:

Middle English: from Old Norse kasta ‘to cast or throw’.

2 Likes