Discuss Scratch

badatprogrammingibe
Scratcher
500+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

Oh, wow. This is really surprising. I'd call it a bug, or an incompatibility, but… I think its potential uses outweigh breaking any hypothetical project which relies on the value of a nonexistant input that shares the name with one of a custom block calling that one to be 0.

Edit: I haven't read far through it yet, but this paper on dynamic scoping (I think it even introduced/formalized the concept?) is interesting: http://galois.com/wp-content/uploads/2014/08/pub_JL_ImplicitParameters.pdf

Last edited by _nix (Nov. 6, 2018 12:16:04)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
TheAspiringHacker
Scratcher
100+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

_nix wrote:

Oh, wow. This is really surprising. I'd call it a bug, or an incompatibility, but… I think its potential uses outweigh breaking any hypothetical project which relies on the value of a nonexistant input that shares the name with one of a custom block calling that one to be 0.

Edit: I haven't read far through it yet, but this paper on dynamic scoping (I think it even introduced/formalized the concept?) is interesting: http://galois.com/wp-content/uploads/2014/08/pub_JL_ImplicitParameters.pdf
That paper doesn't invent dynamic scoping. It merely implements dynamic scoping in Haskell's type system. Dynamic scoping has been around long before Haskell; it's a feature of many Lisps.

Last edited by TheAspiringHacker (Nov. 6, 2018 15:49:53)


Long live Kyoto Animation!
MegaApuTurkUltra
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

badatprogrammingibe wrote:

Example:
https://scratch.mit.edu/projects/259998618/
https://beta.scratch.mit.edu/#259998618
Interesting….

Have you tested this over multiple threads / clones?

$(".box-head")[0].textContent = "committing AT crimes since $whenever"
jokebookservice1
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

My understanding is that dynamic scoping was recently removed, 13 days ago. I can't see this, though, in the latest published previews (e.g. llk.github.io/scratch-gui/develop, llk.github.io/scratch-vm). I'm not sure if the former has pulled in the latest VM changes yet, or if the latter even is updated ever.

Basically, the old (pre-13 day) algorithm was:
  • Go through all stack frames in reverse order of insertion (almost like a… stack!)
  • If this is not a script with a custom block hat, keep traversing (i.e., skip next few steps)
  • If this custom block has the relevant parameter, immediately report its value
  • Else, continue traversing
  • Once we've finished traversing, return 0

But my understanding of the new algorithm was:
  • (Still) go through all stack frames in reverse order
  • (Still) If this is not a script with a custom block hat, keep traversing (i.e, skip next few steps)
  • (Diff) Immediately report either 0 or the value, depending on whether the custom block has the value
  • (Still) If no custom hats were found, report 0

So that change should change it from dynamic scoping to static scoping (if you want to call it that, you can't define a function inside another function so there really isn't any scoping at all).

If a custom block broadcasts to another script, that script can use the parameters of the custom block (i.e. dynamic scoping) – I'm not sure if this is different to 2.0 behaviour, that's something for someone to research.

I'm of the opinion that initially introducing dynamic scoping was not intentional, because the change was described as optimisation, or at least the issue of scoping wasn't mentioned:

kchadha wrote:

This was answered in a discussion offline:
getParams searches for a params object in the stack. When it encounters a params object, it can check it for the parameter being searched for. After the defaults branch being merged, if its not there that implies the param is not from the current running procedure.
Since the parameter is not in the current procedure we can shortcut out of any more searching.

Cross-linking with discussion on GitHub: LLK/scratch-vm#1729 “On matter of scoping and tail call optimisation.” by badatprogrammingibe

Last edited by jokebookservice1 (Nov. 6, 2018 19:45:13)

imfh
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

If you add any parameters to y it outputs 0 though… That is very interesting.

Scratch to Pygame converter: https://scratch.mit.edu/discuss/topic/600562/
_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

jokebookservice1 wrote:

My understanding is that dynamic scoping was recently removed, 13 days ago. I can't see this, though, in the latest published previews (e.g. llk.github.io/scratch-gui/develop, llk.github.io/scratch-vm). I'm not sure if the former has pulled in the latest VM changes yet, or if the latter even is updated ever.
I would think scratch-gui has pretty much the latest scratch-vm changes (e.g. https://github.com/LLK/scratch-gui/pull/3604 was merged 5 days ago), but you're right, it doesn't seem like the changes the PR made are there. It does seem like it was made to deal with nearly this specific situation, per kchadha's comment you quoted.

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

imfh wrote:

If you add any parameters to y it outputs 0 though… That is very interesting.
Oh! Good catch! This is of big significance, I'm sure. See, if a stackFrame doesn't have any parameters, it's skipped:
for (let i = this.stackFrames.length - 1; i >= 0; i--) {
    ...
    const frame = this.stackFrames[i];
    if (frame.params === null) {
        continue;
    }
    if (frame.params.hasOwnProperty(paramName)) { ... }
    return null;
}
So I guess the solution here is to remove those three lines I linked – but of course, I wonder why they were put there to begin with.

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
jokebookservice1
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

imfh wrote:

If you add any parameters to y it outputs 0 though… That is very interesting.
Thanks! I think this is what's causing the issue

EDIT: ninja'd with a more detailed post above

Last edited by jokebookservice1 (Nov. 6, 2018 20:24:19)

_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

_nix wrote:

So I guess the solution here is to remove those three lines I linked – but of course, I wonder why they were put there to begin with.
They were added as part of the original stack frames PR, so I guess this was just overlooked in the recent PR we've been talking about (the one that removes dynamic scoping), maybe?

══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
jokebookservice1
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

_nix wrote:

So I guess the solution here is to remove those three lines I linked – but of course, I wonder why they were put there to begin with.

They are skipped in case the hat block isn't a custom block. As an example:

define proc (arg)
broadcast [do something v] and wait

when I receive [do something v]
say (arg ::custom-arg)

I just don't know if this is 2.0 behaviour?
jokebookservice1
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

No, this isn't 2.0 behaviour. I'm also not sure if that would even trigger a stack frame (it probably wouldn't, idk).

Let's petition the ST to remove those three lines, I guess

Last edited by jokebookservice1 (Nov. 6, 2018 20:58:08)

jokebookservice1
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

Okay, so scratch-flash (the 2.0 source code) also has the null check, but in it, we don't “continue”, instead we return “0”

Last edited by jokebookservice1 (Nov. 6, 2018 20:43:48)

Jonathan50
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

Wow, that is odd. But it shouldn't be a problem (unless you rely on the value of custom block parameters being zero) since Scratch never had block structure/nested procedures in the first place. So why does getParam walk the stack at all?

Last edited by Jonathan50 (Nov. 6, 2018 22:36:20)


Not yet a Knight of the Mu Calculus.
CatIsFluffy
Scratcher
100+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

Someone trying to sneak in something useful for ATers?
_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

CatIsFluffy wrote:

Someone trying to sneak in something useful for ATers?
Nope. It's a bug. They actually meant to (effectively) remove it; they just missed a particular part in their recent change to remove it, so it wasn't quite removed properly

Edit: Well, I can't say for sure. I suppose the original PR adding stack frames may have intentionally had dynamic scoping (I just can't see why the code would be the way it is otherwise), but it's weird that they're removing it now then.

Last edited by _nix (Nov. 8, 2018 00:17:01)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
imfh
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

I hope they keep it. It shouldn't cause any problems especially if it only works when there are no parameters. The most confusing part would be if two custom blocks had similar parameters and that isn't a problem when one doesn't have parameters.

Scratch to Pygame converter: https://scratch.mit.edu/discuss/topic/600562/
JGames101
Scratcher
100+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

Three Days to go until Scratch 3 and it hasn't been removed yet
_nix
Scratcher
1000+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

JGames101 wrote:

Three Days to go until Scratch 3 and it hasn't been removed yet
You're right that it'll still be around for the release of 3.0 – but do not rely on this bug sticking around: there is a WIP pull request (made by a Scratch Team member) to fix/remove it!

Last edited by _nix (Dec. 31, 2018 19:11:14)


══ trans autistic lesbian enbydoggirls // 16 17 18 19 20, she/they
sparrows one word to the paragraph // <3 // ~(quasar) nebula
Andreto
Scratcher
100+ posts

Scratch 3.0 has dynamic scoping, while scratch 2.0 doesn't.

badatprogrammingibe wrote:

Example:
https://scratch.mit.edu/projects/259998618/
https://beta.scratch.mit.edu/#259998618

I just want to know what you were doing when u found this out.

Powered by DjangoBB