Since the beginning of time, back with BYOB, there's been a tension between our teaching mission, which is all about letting users build their own tools, and speed, for which we build the tools in Javascript (in Smalltalk, back then). In BYOB, which was never going to be the fastest language on Earth anyway, and also back when we were hoping to convince the Scratch Team to adopt our ideas so we wanted a minimum of necessary primitives, we always chose pedagogy over speed. We were super proud—still are super proud—that we could build a FOR loop in blocks.
Any 12-year-old can read and understand that, and most can then invent modifications such as a step size other than 1. To make that work we had to invent upvars, which took some careful design and a touch of real grownup computer science (namely, understanding that a "variable" is just a box that holds a value, and there's this separate thing called a "binding" that associates a name with the box).
Even in "grownup" text languages, you can't write something like FOR yourself, because it can't just be a procedure call; it has to be a special piece of syntax.
Then Snap! came along and was starting to be fast enough to do real work, and in particular Jens got interested in media computation, which requires handling large lists, and so we regretfully started recoding some of those tools as primitives. But right from the beginning I made up the name "hybrid primitives" meaning blocks that ran as primitives, but you could say Edit in their context menus and get a definition in Snap! code in a Block Editor. At that time I was thinking that doing so would make it stop being a primitive.
Well, it turns out that back in his Smalltalk days Jens had learned to say "Smalltalk all the way down," meaning that Smalltalk was (almost) entirely written in Smalltalk itself, which is how a different design group thought about the same idea, except their goal was that the Smalltalk interpreter would be fast enough that they wouldn't have to choose between speed and pedagogy.
So, the PRIMITIVE block with its Boolean flag is the way we've ended up having our cake and eating it too. You can edit a primitive, modify its code, experiment with the modified version, and flip back to the primitive version when you need it to run fast.