Discuss Scratch

_nix
Scratcher
500+ posts

Snap! user discussion

Gabriel2900 wrote:

MichaelOlifant wrote:

bharvey wrote:

MichaelOlifant wrote:

Try it here
I'm confused; that page is a (presumably modified) Snap!, so I was expecting to see a TUPLE block, like LIST but etc., but instead I'm supposed to use JSFunction?
What? There's a
(tuple [] @delInput @addInput:: list)
block!
Effects: same as this block:
(list @addInput :: list)
Actually, there's just one important difference – the tuple's item list can't be changed:



Note that you can still reassign the “my tuple” variable; you just can't add to or replace items of the tuple.

blog (it has art, code, and stuff)
MichaelOlifant
Scratcher
30 posts

Snap! user discussion

Gabriel2900 wrote:

MichaelOlifant wrote:

bharvey wrote:

MichaelOlifant wrote:

Try it here
I'm confused; that page is a (presumably modified) Snap!, so I was expecting to see a TUPLE block, like LIST but etc., but instead I'm supposed to use JSFunction?
What? There's a
(tuple [] @delInput @addInput:: list)
block!
Effects: same as this block:
(list @addInput :: list)
Wrong! The list is immutable.

The CAPITALBOYS will protect me from kumquats.
~smile~ Y combinator:
define Y(fn)
report ((call (fn) with inputs (fn) [] @delInput @addInput::control)@addInput::grey ring)::control cap

say(call(Y((if <(num) = [0]> then [1] else ((num) x (call (fact) with inputs (fact) ((num)-(1))@delInput @addInput::control)::operators)::control) input names: ((fact)::grey) ((num)::grey) @delInput @addInput :: grey ring)) with inputs [5] @delInput @addInput::control
MichaelOlifant
Scratcher
30 posts

Snap! user discussion

sorry it's unfinished.

The CAPITALBOYS will protect me from kumquats.
~smile~ Y combinator:
define Y(fn)
report ((call (fn) with inputs (fn) [] @delInput @addInput::control)@addInput::grey ring)::control cap

say(call(Y((if <(num) = [0]> then [1] else ((num) x (call (fact) with inputs (fact) ((num)-(1))@delInput @addInput::control)::operators)::control) input names: ((fact)::grey) ((num)::grey) @delInput @addInput :: grey ring)) with inputs [5] @delInput @addInput::control
bharvey
Scratcher
1000+ posts

Snap! user discussion

Now it won't load for me at all – I just see a blank screen. It hates me.

jokebookservice1
Scratcher
1000+ posts

Snap! user discussion

bharvey wrote:

Now it won't load for me at all – I just see a blank screen. It hates me.
Is it your white on black browser-injected CSS? Perhaps you have a special case for Snap! that doesn't work here?

Hi I'm human and I think you are a nice person hello how are you because I'm good thank you
bharvey
Scratcher
1000+ posts

Snap! user discussion

jokebookservice1 wrote:

Is it your white on black browser-injected CSS? Perhaps you have a special case for Snap! that doesn't work here?
No, I tried it on Chrome, which I use only for Snap! so it's set up “normally.” I'll try again when I have more time, which probably means next week.

BookOwl
Scratcher
1000+ posts

Snap! user discussion

bharvey wrote:

jokebookservice1 wrote:

Is it your white on black browser-injected CSS? Perhaps you have a special case for Snap! that doesn't work here?
No, I tried it on Chrome, which I use only for Snap! so it's set up “normally.” I'll try again when I have more time, which probably means next week.
This is why you can't load it:

THINK LIKE A RESCUE HERO
THINK SAFE

Check out my blog!
doloop
New to Scratch
15 posts

Snap! user discussion

_nix wrote:

ironmannn wrote:

Speaking of which, how come I cant write something like this within the block?

function ExampleFunc ()
{
this.gotoXY(0,0);
};

ExampleFunc();

it just errors out and returns “this.gotoXY is not a function”
That's because of JavaScript's annoying scoping issues – basically “this” will become undefined in ExampleFunc. (PS, you should probably be starting your function names with lower case letters, likeThis! That's just the global JS convention.)

var myself = this;
function exampleFunc ()
{
  myself.gotoXY(0, 0);
}
exampleFunc();

That should work. In that case, you're storing the this-object (the sprite) in a variable called “myself”, which you can access from exampleFunc.

You can also use “bind” to change the value of “this” within that function:

function exampleFunc() { /* ... */ }
exampleFunc = exampleFunc.bind(this);
exampleFunc();

Or you could use the “new” ES6 arrow functions, which keep the value of the this-object from the this-object that created it:

var exampleFunc = () => {
  this.gotoXY(0, 0);
};
exampleFunc();

I'm experimenting with the javascript block. I don't know javascript but I want to learn it to expand my options with Snap! As an experiment, I inserted all of the example code above into the second slot (between the braces). Much to my surprise it worked. I was surprised because the block nested the example function inside of an anonymous function. I thought it would do that, but I also thought that would return an error (as I said, I don't know javascript). It is good that this works, but it seems “ugly.” Is there a way to create a named (non-anonymous) function with the javascript block?
doloop
New to Scratch
15 posts

Snap! user discussion

_nix wrote:

ironmannn wrote:

Speaking of which, how come I cant write something like this within the block?

function ExampleFunc ()
{
this.gotoXY(0,0);
};

ExampleFunc();

it just errors out and returns “this.gotoXY is not a function”
That's because of JavaScript's annoying scoping issues – basically “this” will become undefined in ExampleFunc. (PS, you should probably be starting your function names with lower case letters, likeThis! That's just the global JS convention.)

var myself = this;
function exampleFunc ()
{
  myself.gotoXY(0, 0);
}
exampleFunc();

That should work. In that case, you're storing the this-object (the sprite) in a variable called “myself”, which you can access from exampleFunc.

You can also use “bind” to change the value of “this” within that function:

function exampleFunc() { /* ... */ }
exampleFunc = exampleFunc.bind(this);
exampleFunc();

Or you could use the “new” ES6 arrow functions, which keep the value of the this-object from the this-object that created it:

var exampleFunc = () => {
  this.gotoXY(0, 0);
};
exampleFunc();

I'm experimenting with the javascript block. I don't know javascript but I want to learn it to expand my options with Snap! As an experiment, I inserted all of the example code above into the second slot (between the braces). Much to my surprise it worked. I was surprised because the block nested the example function inside of an anonymous function. I thought it would do that, but I also thought that would return an error (as I said, I don't know javascript). It is good that this works, but it seems “ugly.” Is there a way to create a named (non-anonymous) function with the javascript block?
Chibi-Matoran
Scratcher
1000+ posts

Snap! user discussion

I made a hash set class: https://snap.berkeley.edu/snapsource/snap.html#present:Username=chibi-matoran&ProjectName=hashset

If you see this signature while scrolling, you have been visited by ʎ++ haskal. Lazy evaluation, monads, function purity, lambdas, currying, partial application, algebraic data types, pattern matching, and typeclasses will come to you, but only if you comment, “Thanks, ʎ++ haskal” on my profile.

Cassian && ||
bharvey
Scratcher
1000+ posts

Snap! user discussion

doloop wrote:

Is there a way to create a named (non-anonymous) function with the javascript block?
Sure, although this probably isn't what you mean, but it's the usual thing we do: Make a Snap! custom block that calls the JS function:


P.S. When quoting a super long post, editing it (as I did with yours) makes it easier to read!

bharvey
Scratcher
1000+ posts

Snap! user discussion

Chibi-Matoran wrote:

I made a hash set class: https://snap.berkeley.edu/snapsource/snap.html#present:Username=chibi-matoran&ProjectName=hashset
Nice. One slight problem I had reading your code is that you have a variable named “method” whose value is not a method (i.e. a procedure) but rather a message.

Oh, not in the code but in your example, maybe you already know this, but generally when you make a hash table you want to pick a prime number of buckets, rather than a power of two, so that regularities in the data (e.g., suppose all your numbers were even) get spread out among the buckets. (Sorry, as I said in another context, I can't help it, I'm a teacher.)

_nix
Scratcher
500+ posts

Snap! user discussion

doloop wrote:

I'm experimenting with the javascript block. I don't know javascript but I want to learn it to expand my options with Snap! As an experiment, I inserted all of the example code above into the second slot (between the braces). Much to my surprise it worked. I was surprised because the block nested the example function inside of an anonymous function. I thought it would do that, but I also thought that would return an error (as I said, I don't know javascript). It is good that this works, but it seems “ugly.” Is there a way to create a named (non-anonymous) function with the javascript block?
I'm.. not sure exactly what you're saying is “ugly”. I think that's probably because I'm simply used to using JavaScript in all the ways I listed above; so I just don't know what code you're finding ugly.

I'm also not sure exactly what code you put into the JS Function block, since you said "I inserted all of the example code" (emphasis mine). Only any one of them is necessary; these all work:







Also, note what these blocks do – they use JavaScript's setTimeout function to move the sprite to (100, 100) later. The “run” block also doesn't wait for that setTimeout to be finished; it just lets the script continue after “setTimeout” is called. That's basically the same as this, in Snap! blocks:



Since setTimeout takes a function as its callback (i.e. a function that will be called later), we have to figure out how to keep access to “this”, since we'll use it later. I just want to make sure you're only using functions when you need to; we don't want an unnecessary monstrosity like this!

––––

But.. while writing this post I think I figured out where you're finding it ugly, possibly. Correct me if I'm wrong, obviously, but is the issue that you're ending up putting requestAnimationFrames inside of requestAnimationFrames inside of requestAnimationFrames, and so on, making your code look somewhat like this?

// Do step 1, then..
requestAnimationFrame(function() {
  // Do step 2, then..
  requestAnimationFrame(function() {
    // Do step 3, then..
    requestAnimationFrame(function() {
      // Do step 4, then..
    });
  });
});

..ending up with continuously indented code, or worse, if you can't be bothered to indent your code at all?

That issue is, for lack of a better word, what the JavaScript world calls “callback hell”. It happens when you have a bunch of steps to your piece of code – callbacks you're passing to functions like requestAnimationFrame or setTimeout – and they pile up, like that, resulting in really indented, hard to read, ugly code.

Thankfully, it's not without its solutions. The latest and popular one would be to use promises, but that's a whole other topic, so I think we can probably just simplify that code by using separate named functions:

function step2() {
// Do step 2, then..
requestAnimationFrame(step3);
}

function step3() {
// Do step 3, then..
requestAnimationFrame(step4);
}

function step4() {
// Do step 4, then..
requestAnimationFrame(step5); // And so on.
}

(Note – you should name your functions better than step1, step2, etc; try something more descriptive, like “countRedPixels” if you're going through a list of data to find the number of solid red pixels there are!)

This will get rid of the “callback hell” you might be experiencing. JavaScript is still doing the same thing – calling functions, one after another, each after requestAnimationFrame is ready to continue – but the code looks a lot easier to read.

(One quick note – variables you make in step2 won't be able to be accessed in step3 or step4, since those are separate functions. Instead put variables at the very top, like this.)

(edit: grammar)

Last edited by _nix (March 23, 2017 10:33:19)


blog (it has art, code, and stuff)
Chibi-Matoran
Scratcher
1000+ posts

Snap! user discussion

bharvey wrote:

Chibi-Matoran wrote:

I made a hash set class: https://snap.berkeley.edu/snapsource/snap.html#present:Username=chibi-matoran&ProjectName=hashset
Nice. One slight problem I had reading your code is that you have a variable named “method” whose value is not a method (i.e. a procedure) but rather a message.

Oh, not in the code but in your example, maybe you already know this, but generally when you make a hash table you want to pick a prime number of buckets, rather than a power of two, so that regularities in the data (e.g., suppose all your numbers were even) get spread out among the buckets. (Sorry, as I said in another context, I can't help it, I'm a teacher.)
Oh, thank you. I wanted to try and implement OOP (with better key lookups than linear naive if-then return checks). However, I realized that I should use the JavaScript function block because I assume that key lookups done by the browser's JS interpreter would be faster than an implementation in Snap!. However, how do I interact with Snap! lists? I tried using arrays but they didn't work. Where may I find documentation for the JS interface to the Snap! data?

If you see this signature while scrolling, you have been visited by ʎ++ haskal. Lazy evaluation, monads, function purity, lambdas, currying, partial application, algebraic data types, pattern matching, and typeclasses will come to you, but only if you comment, “Thanks, ʎ++ haskal” on my profile.

Cassian && ||
joefarebrother
Scratcher
500+ posts

Snap! user discussion

This is why I think JS could have CallCC as a primitive. Since “callback hell” is essentially continuation passing style, which CallCC would allow you to avoid and allow you to put a sleep function or a web request in some place without having to completely restructure the program. Doesn't even need to be fully general continuations like Scheme or Snap!, non-reenterant continuations would probably be good enough for most real world cases.


And it was delicious! Play TBGs! Check out my Scheme Interpreter!
;
_nix
Scratcher
500+ posts

Snap! user discussion

joefarebrother wrote:

This is why I think JS could have CallCC as a primitive. Since “callback hell” is essentially continuation passing style, which CallCC would allow you to avoid and allow you to put a sleep function or a web request in some place without having to completely restructure the program.
I'm just curious, then – and excuse me for never properly understanding CallCC – how do I do something like this?



That runs the “play note” block later, but also now. I kind of always thought passing a continuation would delay it until I choose to call it; how would one do that using continuation-passing, and what's the reason for it not being that way?

blog (it has art, code, and stuff)
bharvey
Scratcher
1000+ posts

Snap! user discussion

Chibi-Matoran wrote:

Where may I find documentation for the JS interface to the Snap! data?
*snicker* Documentation?

You might want to read the comments in the sample JSFunction project in Examples. But if you want to return a list just say new List(your array). And to process a list as input, say yourList.asArray().

joefarebrother
Scratcher
500+ posts

Snap! user discussion

_nix wrote:

joefarebrother wrote:

This is why I think JS could have CallCC as a primitive. Since “callback hell” is essentially continuation passing style, which CallCC would allow you to avoid and allow you to put a sleep function or a web request in some place without having to completely restructure the program.
I'm just curious, then – and excuse me for never properly understanding CallCC – how do I do something like this?



That runs the “play note” block later, but also now. I kind of always thought passing a continuation would delay it until I choose to call it; how would one do that using continuation-passing, and what's the reason for it not being that way?

Yes, passing the continuation does delay it until you choose to call it, BUT you also let the function you pass the continuation into run - which calls the continuation implicitly. So the continuation ends up being called twice.

In CPS, that's like this: http://imgur.com/a/kff2A, wheras you probably wanted this: http://imgur.com/a/nkIIj, which I guess could be done by putting a “stop script” block in the argument to runCC.

This is the was Scheme does it too, and the reason for that is that in Scheme, everything either returns a value, or it escapes by calling a continuation. (or it goes into an infnite loop). if the argument to callCC returns a value, what should happen to it? The least surprising thing is that this is also the value that callCC itself returns, so that's what it does.

Last edited by joefarebrother (March 23, 2017 23:04:06)



And it was delicious! Play TBGs! Check out my Scheme Interpreter!
;
bharvey
Scratcher
1000+ posts

Snap! user discussion

_nix wrote:

I kind of always thought passing a continuation would delay it until I choose to call it; how would one do that using continuation-passing, and what's the reason for it not being that way?
The continuation of an expression is whatever remains to be done after the expression is evaluated. So in particular the continuation captured by call/cc is whatever remains to be done after the call/cc itself; in your example that includes the play note.

You could of course do this:


But it's the way it is because of the intended use cases, e.g., THROW for early exit from a computation to the same place it'd normally reach after the computation. So running the continuation will happen inside an IF.

_nix
Scratcher
500+ posts

Snap! user discussion

Okay, thanks for the explanations.

To joefarebrother – yeah, I've used “stop this script” with CallCC in the past, but it doesn't feel quite clean, since it makes Snap! forget that it's even running that script. (Because, you know, we stopped it )

Generally my solution for a case like that is this:

set [done v] to <(false :: #B80000) :: operators>
launch ({
wait (2) secs
set [done v] to <(true :: #00B800) :: operators>
} @addInput :: grey ring) @addInput :: control
wait until (done)

It's “not hard” to do with JavaScript, either:



(Link to that project.)

blog (it has art, code, and stuff)

Powered by DjangoBB

Standard | Mobile