Call block from Javascript?

@Jens Bill Ferster is part of the team at the University of Virginia (UVA) that is exploring ways to introduce SNAP! to K-12 teachers. We're also the team that developed SoundScope.

Bill's status as a novice on the SNAP! forum will not allow him to post another message for 19 hours; he asked me to send you a follow-up note saying "Thanks!"

hi, @bferster and @glenbull. I'm not sure about the karma levels on this forum software but I've tried to lift the limitations on your accounts...

hi @bferster, I'm adding the beginnings of a "Snap! API" to the next minor release (v5.4) coming up in a few days. This will include the above functionality as a method for IDE_Morph:

IDE_Morph >> broadcast(message, [callback])

you can use it pretty much exactly like the function above, except that it's a method of IDE_Morph:

ide.broadcast('frob');

but you can also use it so that it waits until all processes have completed, and then continue with a callback (same as broadcast and wait):

ide.broadcast('frob', function () {ide.broadcast('quux'); });

in which case "quux" scripts will only get launched once all "frob" scripts are done.

I hope that'll help you for your project. Just to be clear: This does not yet work, but will be in the upcoming release sometime this week.

Wow. The api sounds like it’s worth waiting for. How can I learn more about it? It would be great is it exposed things like dragging a block out, connecting blocks, etc , spa we could walk kids through sequences.

You guys have an amazing product!

While broadcasting from JavaScript is cool and useful I wonder if it is too limiting. I can imagine that the messages from Scales may have parameters beyond just the string to broadcast. I had a similar problem years ago. Instead of using broadcast I would define a new command something like this:

image

Then one can have as many listeners as one wants and they can receive parameters. E.g.

image

Not sure. We'll see what Glen and Rich want to control, but it sounds like Snap is very extensible, so I'm sure we'll get something happening.

Can moderators assign this topic to "Mods & Extensions" category, as it seems it belongs to it.

Sure

Wow @jens, this is very interesting!

We use this feature to call messages from Snap4Arduino web server (this code), but I will replace it with this new API, and I will also use it to implement WebThings server side. Calbacks will be useful to define WebThings Action object responses (to inform about "complete" status), and also for Events objects

Joan

I think the idea is to also add

  • read and write access to global variables (excluding the ability to create new ones), that way we can pass values into Snap and also query them from the "outside"
  • callbacks / "event listeners" to broadcasts (so the "outside" can also get notified and react to them)

These few features should already give us much to play with, and then we can take it from there.

[edit] I've just now added all these features, so we now have an easy way to

  • trigger scripts (programmatically broadcast messages, and optionally wait) from the outside
  • attach listeners (callbacks) to broadcast messages, so we can react to them from the outside
  • access global variables from the outside

That should go a long way to making Snap! somewhat of a team player in platform like "Scale".

I see how useful this is but am worried that this is terrible computer science. Instead of full-message sending (e.g. actors) one sends a string and then uses global variables for message parameters. NetsBlox has messages with parameters why can't Snap!?

Yes, Ken. I agree. Sorta.

Because this is a start. NetsBlox "messages" are nice, but super complicated to set up, especially programmatically (not even sure if that can be done at all). When I look at what people in these forums - even in this thread - fabricate to accomplish what should be the simplest things my impression is that "good computer science" often stands very much in the way. Just look at the title of this thread and the very first question about "continuations". And Bill didn't even need continuations at all, he just didn't know how to trigger a simple Snap! script. So I'm solving this issue for him and for everybody in an easy and straightforward way that doesn't require anybody to even use a JS-function block (let me remind everyone that those JS-function blocks will be deprecated by browsers in the future, and there is nothing we can do about it, they've already stopped working in Chrome apps). By adding the capability to attach callbacks to Snap's events and by accessing global vars we get a very versatile and yet encapsulated interface to a Snap project.

That's the whole idea: Now we're at a level of scale, where I only want to expose a subset of global properties and protocol to the public. The use cases I'm envisioning for this API is being able to embed Snap!-made animations and interactive quizzes into online learning platforms such as Scale, openHPI/openSAP, edX etc. For this purpose I want "regular" Snap! users (not the kind of JavaScript-under-the-hood dudes this forum attracts the most who don't seem to get much done except scare off novices by flaunting half-knowledge) to make these animations and quizzes in vanilla Snap!, and to offer platform integrators an easy way to embed these media projects into their courses. The beauty of this old "Scratch-Protocol" approach is that we don't have to introduce new concepts. Yes, I encourage using broadcast over things like tell / ask, and that's okay (I think) for projects that need to interact with other apps, because that's a level of granularity that makes sense to publish.

So, parameters. The mechanism encouraged in this API is to conscientiously publish state via global variables. If you think about a Snap! project as just an object - again - at this level of scale, that may just be the right way, don't you think? Now we're in a world where a project is just one among potentially many ones, and the internals shouldn't really be exposed, same as we don't want to establish close ties between individual parts across projects or projects and platforms.

For the future I'm considering adding GP's way of optionally sending along "data" with messages. But, again, I'm not sure whether that is the right way to think about inter-project communication at all.

I failed to find anything about this. I see that Snap! implements them by creating functions on the fly with

Function.apply(null, ...)

Is that being deprecated?

There are 3 things being discussed here:

  1. broadcasting
  2. sprite-to-sprite message passing (ask and tell)
  3. event listening

Ask and tell in programming languages for learning goes back to my work in the 70s in Director, in the 80s on Object Logo, and the 90s with Imagine Logo, StarLogo, and NetLogo. Why discourage it? It is a nice fit with "little person" metaphor of computation (but not the same idea).

To my mind event listening is superior to broadcasting though they are similar. I see the difference in that any program can add and remove event listeners dynamically while broadcasting is sending messages to those sprites that have statically declared they are interested in particular messages.

Global variables only work well in very simple cases. Imagine some program is informing a Snap! program of some updates. The program might emit "update x 1", "update x 3", and "update x 5", in very quick succession. As I understand the proposed Snap! scheme would be received as "update" broadcasts and some global variable for "x" would hold "1" and then "3" and then "5". But then synchronisation becomes a real pain. And if the global variable instead holds ["1", "3", "5"] then whose responsibility is it to reset it to [] when everyone has responded?

Ken, I understand your concerns, and it's certainly a no-brainer that parametrization is at the very core of abstraction. And again, I'm not saying we're not going to add it. But as a first measure, without introducing any new concepts or new blocks to Snap!, we have two (well, there's always more, but for argument's sake let's reduce them to two) ways to let other programs interact with Snap! projects:

  1. encourage other programs to inject JavaScript code, and force Snap! project writers to include lots of JavaScript function blocks in their code. This is the current state of affairs, and obviously it's not working very well even for professional programmers and research professors :wink: This also has the downside of not being future-stable, because we never know what people end up writing in their JS functions, so who knows what might break in the next release?

  2. add hooks for outside applications to interact with Snap! projects without requiring Snap! project writers to learn anything new or to include any magic blocks. This way those "hooks" (what I magnanimously call the "Snap! API") are just a few "blessed" functions that I can easily guarantee to keep working whenever we change something, encouraging 3rd-party investments in their platforms.

The way I see it there are questions of granularity. When we wish to pass data into a Snap! project from another program or platform, what is it we're after?

Use Case: Interactive Applet

The use case I'm imagining is not so much peer-to-peer communication between different Snap! instances, although in the long run that's a dream I haven't given up on, the use case is some learning / MOOC platform that does not necessarily teach programming. Such a course, say, on the subject of Climate Change, might wish to embed little interactive simulations, games, quizzes etc. which are really easy and quick to create in Snap!. I'm imagining those projects to be embedded in presentation mode without the ability to see the blocks or edit them, just like an applet. This is what I'm trying to address with the "API" right now.

Of course the MOOC platform would want to get back some result, e.g. the percentage of questions answered correctly, or the time needed to complete a simulation etc. These metrics are often kept in projects' global variables anyway, called "score" or "lives". There might also be a platform which keeps track of a highscore. So that would be something useful to pass into a Snap! project before starting the game. It's those kinds of configurations I have in mind that would open up Snap's usage across the web.

Use Case: Aided Programming

There is, of course, a set of much more demanding use cases, that include going meta on Snap's projects to facilitate learning CS and programming. For those use cases I'm imagining Snap's editor to be the "applet", not so much the stage. Use cases could range from Parson's problems to full-blown BJC programming assignments. This is the realm of forks like Thomas Price's iSnap. Here the granularity of actions to log, parameters to pass, scripts to programmatically create etc. is much, much higher. That's what we want self-reflection, introspection and macros for. And, yes, of course I might want to let an outside "controller" call arbitrary functions passing arbitrary data. This is not what the set of functions I threw in last night and this morning addresses. But I don't think we're making any decisions right now that wouldn't let us add those in the future, do you?

I guess the question I'm interested in right now is, do you think that the proposed set of features will come back to haunt us some day, or are they orthogonal to future features?

Anyway, great discussion!

Programming languages in general find it very difficult to deprecate things and especially to make incompatible changes (e.g. that's why JavaScript can't rename === to ==). (Also I've heard the whole Python problem with moving from version 2 to 3 has to do with incompatible changes.) But maybe the situation is different with programming languages for learning. When something better replaces some old language functionality there is much less of an installed base. Documentation and sample programs can be updated, etc..

Though I also worry about learners acquiring bad habits. A few months before I went before I went to MIT I asked Marvin Minsky if I should learn Lisp on my own over the summer. He said no because of the risk of acquiring bad habits (e.g. creating Fortran-influenced Lisp code). Pat Winston used to boast he could teach anyone Lisp in 3 weeks unless they already knew Fortrain then it would take him 6 weeks.

In this case I worry about relying upon global variables. E.g. Global variable considered harmful (1973).

I agree about global variables being problematic in general. In the case of another program communicating with a Snap! project, however, isn't it more like treating the project's global variables as "project-instance-variables"? Because they're not becoming truly global of being moved to a shared scope of both the project and the ouside program?

So will Snap! handle any possible race conditions? E.g. will there be a phase were global variables are updated from incoming API calls followed by a phase where Snap! programs can read/write the values? And what if there are multiple updates from the API to the same variable since the last phase? If the values are meant to be associated with broadcast strings then you can't just let the second API call clobber the value of the first call.

Wow, the broadcast API will be very useful! This is probably a great way to clean up some autograding and make it more clear what's happening!

Hi @jens and Team,

I read this exchange with great interest. However, since I am not highly skilled in matters JS, I was wondering if there was a way I could read on the proposed API (I am assuming since SNAP! is @ v5.4.5, that it is available) and look at some of the use examples, in order to try to use it to communicate with the Google Web Speech API.

Turgut