In the current dev version I'm playing with a bunch of custom hat blocks, feel free to also play with them (but remember it's all experimental and might not make it into Snap!):
Suggestion: make this the default
because if you use volume, then it wants access to microphone which in my case is in the webcam so the webcam light comes on
And no-one likes sitting at a computer with a webcam light on
Will those new events work at every frame, i.e., 60 times a second?
And execution order and reentrance policy will be specified?
If a part ot the program logic is expresed as constraints, it would be nice if state mutators ran first and then checks.
It may be a great step towards declarative programming and the new area to conquer.
Of course, something like a mutation observer may be required to get some performance.
Okay, so, there's this branch of mathematics called "abstract algebra," in which they take some of the properties of regular arithmetic and say "what if we look for other operations over other sets that have the same properties?"
So, for example, addition (+) over the integers has these properties (among others, but these are the ones we're looking at right now):
Closure. If x and y are integers, then x+y is an integer.
Associativity. For all integers x, y, and z, (x+y)+z = x+(y+z).
Identity. There is a particular integer, namely zero, such that for all x, x+0=0+x=x.
Inverse. Every integer x has another integer, -x, such that x+(-x)=0.
Any other operation, over any other set, that has these four properties is called a group. One of the standard examples is to take a square, label its corners, then form the set of all the different ways you can move the square around so that it ends up looking the same, e.g., rotate the square 90° clockwise, flip the square over around its horizontal axis (so what used to be the back is now in front), etc. There are, I think, eight such transformations: three rotations (90° CW, 90° CCW, 180°), four flipping over axes (horizontal, vertical, and two diagonals), and the identity transformation, which is to do nothing to the square. So, that's our set. The operation ∘ is composition, which means "first do this, then do that." So for example, if you label the corners ABCD starting at the top left and going clockwise, the result of rotating 90° clockwise is DABC. The result of flipping ABCD over its horizontal axis is DCBA. But the result of starting with ABCD, rotating 90° CW (to get DABC) and then flipping over the horizontal axis is CBAD, which is also what you get flipping over the positive-slope (slash-shaped, as opposed to backslash-shaped) diagonal. (Try it out!) So
(90° CW) ∘ (flip H) = (flip /)
So, is this a group?
Is it closed? Yes, since every possible repositioning of the four corners is part of the set, the result of composing two transformations has to be in the set also.
Is it associative? Yes, it is, proof left as exercise for the reader. (Since there are only a finite number of transformations, you could just check all of the 8³ groupings of three transformations. But I'm sure there's a more elegant way to prove it.)
Is there an identity element? Yes, the "do nothing" transformation.
Does every element of the set have an inverse? Yes, (90° CW) is the inverse of (90° CCW), and the others are their own inverse--doing the same thing twice gets you back to the original ABCD.
By contrast, the natural numbers (nonnegative integers) aren't a group under addition, because the elements of the set don't have inverse elements. And the integers under multiplication, ditto.
So, now that you know what a group is, you can forget about everything except the first group property, closure. The integers aren't closed under the division (/) operation, for example. Even the real numbers aren't closed under division, because of dividing by zero.
So, what I was trying to say to Jens, but obviously failing, is that my instinct is that composition of language features should be closed. (I did say "Not in the lambda sense, but in the group axioms sense," Jens, but I guess that wasn't clear enough.) This is something my SICP students didn't always believe; they would ask questions of the form "Can you put X in a call of Y?" For example, "Can you put a number in LETTER 1 OF?" And I'd say, the answer to those questions is always yes; sometimes the answer won't make sense, but syntactically, you can put any expression in any context.
An example that came up recently on the forum was "can you put a block in a menu?" My instinct is that you should be able to put anything in a menu, but that isn't Jens's instinct. This difference is because he thinks about how to implement something, whereas I don't. I just expect menus to be implemented such that anything you can put in a speech balloon, say, should go in a menu for free, with no extra implementation effort. But for reasons that go over my head, that's not how Snap! works.
Jens, sorry to get your blood boiling. I didn't mean to say that you did anything wrong in Snap!, just that my instinctive expectation is that composition of features will be closed. I was trying not to say that I'm right and you're wrong about this; on the contrary, I was trying to say that I now understand your point of view better than I did before.
yes, in order to facilitate constraint systems we might wish to expose some of the internal Morphic optimizations for observing complex data structures, such as the timestamps we keep on lists, sprites and other mutables, so we're not clogging up the evaluator with constantly iterating over deeply nested pairs. Exposing them would be trivial, we can simply add a single reporter to the extension blocks, because everything needed is already there...
yes, all generic and custom hat blocks run at the beginning of every frame before the other scripts. They are not reentrant, however, which makes them thread safe but also prone to missing frames in case either their predicate definitions or their triggered scripts span over several frames, e.g. when having loops or interpolated ("timed") blocks.
of course we can put blocks into menus, we're doing it constantly, e.g. in the "relabel* menu, or in the block context menu when we're indicating which part of a script to duplicate. Implementation is seldom an issue. Do I want to let users put blocks into drop-down menus of input slots in their custom blocks? Hell no! What would they do with these? replace the input slot with an expression in the menu? Sure, no problem to implement that, it's dirt easy. But there's no point in doing that, because we have a perfectly valid and consistent method to drop reporters into input slots: Drag & drop! Just because we can do something doesn't mean it's a good idea to encourage folks to actually do it all the time.
That said, I now "get" what you were trying to say, thank you for the explanation, Brian! And sorry for reacting sourly.
It took me a while to think of this, but those bugs (unlike, for example, the also-common bug of FOR and NUMBERS FROM counting backward when you don't want them to, which we should fix by adding the TO/UP TO menu input) are great learning experiences. The distinction between an event and a rule comes up in many different contexts, and struggling with a bug is how you really learn it. If we think of our user as a computer science student, which for the most part we do, it's an interesting and important pedagogic question whether we do them a favor by preventing those bugs. I mean, yes, it took me a little while to debug the second one, but now I never make that mistake again.
Of course really it's the same pedagogic question we keep bumping into. Making MAP a primitive took away a CS learning experience, and, by the way, I don't think we've yet perfected the Snap!-all-the-way-down way to have our cake and eat it too, because in that context we kinda have to show an exact implementation in Snap! blocks of all the bells and whistles of the primitive, whereas for pedagogic purposes I would argue that it'd be better if editing the MAP primitive gave you
I still think we should try to find some time with no crises going on to talk through a revisiting of what we're all about from first principles. Maybe at Olot?
This sort of question is easier for the Scratch Team because they adamantly aren't about teaching computer science, but rather about enabling creative authorship of stories. So, for them, avoiding common pitfalls is an unalloyed good thing. This is one of the reasons it makes me a little unhappy when you get excited about duplicating each new Scratch feature. :~/