Executing rings with JS

I have been mentioning it in this thread because I was trying to optimize my programs using JS, however, I cannot seem to figure out how to execute a ring properly. I have tried a lot of things but most of them give me very strange outcomes. For example, I cannot even get that task hack I used to return half of the time and I have no idea why. Hopefully I will be able to figure out a cleaner way of doing this so that I can use the snap reporter blocks and get their results in JS.

End effect is for me to be able to get a minimum by calculating the reporters using Snap ! and its result in JavaScript. This is because I create an array of ringed reporters which I will use for calculating the minimum.

This is the current method I use:


But I wanted to instead use JavaScript to do the call part and the entire function as well.

var result;
var lowest = Infinity;
for (item of map.contents) {
    result = execute(item, position);
    if (result < lowest)
        lowest = result;
}
return lowest;

Oh I see. I replied back in the other one. But this should probably be in some AT category. Maybe we need a "Help with JavaScript" one. :~)

Honestly, you shouldn't have to resort to JS; we have effectively done that for you by writing the HOFs as primitives. If something in Snap! is slowing you down, it's likely some graphics thing rather than the control structures.

It is mostly due to the amount of objects I create, the amount of custom blocks, and the amount of loops. Things can get very unoptimized that way and it was clearly and evidently the case in my last attempt. Now that my workflow is almost entirely JS-based, it runs smooth like butter with the blocks only providing an interface.

Okay, looking at your code again, my new guess is that THIS at the time your function is called isn't what you think it is. If it's a sprite you win, if something else you lose, or maybe vice versa.

So, your problem is solved?

Well what was very strange is that you saw that it was working in the image, but I had no idea why because every other time I tried it it either worked or spat out something very, very strange like undefined while still managing to run execute (because it would throw errors when it is getting too many arguments). I was wondering:

  • If there is a more reliable and less convoluted way of executing a ringed reporter
  • How do I make sure it works all the time and gives a proper return value?


Why does this not work yet this does????

It also seems to randomly error at times saying this.context is null

Actually, what seems to be happening is execute is overwriting some context here so that the return is actually of 4 the result of the reporter, not the call. How do I make it so that I can execute the reporter and give its result back to JS without messing up the context? It would be pretty sick if there is some sort of JS API solution where u just execute the context and it returns the results back.

Okay, I'm getting more and more annoyed by threads like this under the "Help with Snap!" headline. Can we move this somewhere hidden from everybody else who might be looking for help?

Should I move it into Advanced Topics or Advanced Topics - Development?

that would be great, thank you! The point is, I'm afraid we're scaring off users with topics that revolve around special hacks around JS in these forums. Compared to what I'm seeing in my Email-inbox we're getting very few actual questions here, and I suspect it might have something to do with the kinds of questions and suggestions that happen here, that it's off-putting novices and my target audience.

I am still trying to look through the source code but I cannot seem to understand how these ring contexts become evaluated and how their return is properly associated with whatever input requires it.

Ok so after a little bit of digging I think I understand how most of it works now. It appears that what map does is it uses a thing called an accumulator to do recursive calls. pushContext appears calls the same selector until it returns a value. So it seems that eventually it satisfies the iteration and returns all the way back to the first push context call. The final evaluate just seems to be a way to push the return value to the whatever called it.
I think this is sort of how it works so does that mean that in order for me to do something like this, I would also have to use accumulators to iterate through it with pushContext and returnValueToParentContext in JS and get the response value? Also, what is the use of the cdr function?
I do not really want to do it like in reportMap though as I would rather just compute the reporter block one time and then do it as many times as I want after because this simplifies the script.

I think the point is that you don't need to follow the evaluator to make Snap projects at all. If you want to understand how programming languages work there are better ways to study them than to sift through the Snap! source code.

I know how to use Javascript but I am trying to do one thing in specific which is computing what is in a reporter ring and using it in Javascript which means I have to figure out how Snap! is doing things, but it is a bit difficult to understand what the interpreter is trying to do in cases like doCall and reportMap.

you can use invoke() on the ring.

invoke requires a lot of parameters apparently and does it have global access? (Is it available in just general global space?)
Also which parameters are necessary and what is the most common way to set up a call with a ring? I know the parameters have comments but I still don't fully understand how the structure of Snap! is layed out in terms of Processes and Context and etc.
Is this sort of how you do it?

return invoke(
    myRing,
    new List(args)
);

Wait is it really just that easy ^ holy crap! Well there is a magical API then! Thanks a bunch! I will test more when I can get on PC
I managed to somehow test it on mobile though which at least means I know it works

You mentioned before that the visuals are what would be slowing Snap! down...


Look how fast it is now! :smiley:
Just from switching minimum distance to have a JS mode already bumped up performance to an insane degree! Thanks to all involved!
This is what it looks like now:
old:

new:

Is there a version of invoke that will allow the process to yield? How do I make it execute command block rings without freezing Snap?

Okay, think about this for a minute. "Yielding" means stopping JS and surrendering control to the browser. After JS has stopped, you can't continue a function call. So, of course there cannot be a version of invoke() that yields. The version that yields is the Snap! programming language :slight_smile:.