Discuss Scratch

Jonathan50
Scratcher
1000+ posts

Snap! user discussion

bharvey wrote:

@Jonathan: Okay, I spent all afternoon trying different slight modifications to your code and stepping through it (with the wonderful PAUSE ALL block). The only place I can see where you might get that particular error message is in calling a block with a variadic input, bringing me back to UPDATE NAMED LET BINDINGS, but I tried rewriting REPLACE without named let and it didn't help. I give up.
I wasn't even setting parent, so replace wouldn't have even been used… Removing the let block makes it work:

…but the let block seems to work fine:


So the only thing I can think of is that it is a bug in Snap!.

EDIT: Let is implemented as:

Last edited by Jonathan50 (June 5, 2016 23:40:08)


Not yet a Knight of the Mu Calculus.
bharvey
Scratcher
1000+ posts

Snap! user discussion

Jonathan50 wrote:

So the only thing I can think of is that it is a bug in Snap!.
I confess I was skeptical the first time you said that, but after banging my head against it all this time I'm more convinced. File a bug report. It would be great to know what the smallest failing example is, but maybe it doesn't matter because Jens will instantly know what the problem is.

Jonathan50
Scratcher
1000+ posts

Snap! user discussion

Ok https://github.com/jmoenig/Snap--Build-Your-Own-Blocks/issues/1245

Last edited by Jonathan50 (June 6, 2016 00:18:21)


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

Snap! user discussion

I've answered that question on Github. Short explanation: Snap treats fully collapsed variadic slots as “empty” implicit formal parameters. Short solution: Either call the “proc” input with an argument (which gets ignored) or expand the call block with an ignorable input so the variadic slot isn't empty anymore.

Last edited by Jens (June 6, 2016 12:35:16)

bharvey
Scratcher
1000+ posts

Snap! user discussion

1. See I knew Jens would see the problem instantly.

2. I was right, it was about variadic inputs!

3. Duh, this is why UPDATE NAMED LET BINDINGS works despite looking like a bug! In that case this feature works to your advantage.

4. If this feature is too confusing for me to be able to catch the bug, maybe we need to rethink it.

joefarebrother
Scratcher
500+ posts

Snap! user discussion

Wait, so why doesn't calling something with no inputs just bind empty varadic inputs to the empty list? That appears to be the intended and most intuitive behaviour, and I can't see any other behaviour would be more usefull


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

Snap! user discussion

joefarebrother wrote:

Wait, so why doesn't calling something with no inputs just bind empty varadic inputs to the empty list? That appears to be the intended and most intuitive behaviour, and I can't see any other behaviour would be more usefull
I agree. This means the named let doesn't work with zero inputs (even though enough inputs have been supplied to LOOP)

Not yet a Knight of the Mu Calculus.
Jonathan50
Scratcher
1000+ posts

Snap! user discussion

What is the “correct” way to construct a linked list from JavaScript? Both List.prototype.cons and new List([]).cons seem to work, and I find it a bit odd that it's List.prototype.cons instead of List.cons.

EDIT: The Snap! source uses new List().cons
EDIT 2: how do I check if a list is empty in JavaScript?
EDIT 3: !list.isLinked && list.contents.length == 0 seems to work

Last edited by Jonathan50 (June 7, 2016 01:37:28)


Not yet a Knight of the Mu Calculus.
liam48D
Scratcher
1000+ posts

Snap! user discussion

Jonathan50 wrote:

EDIT 2: how do I check if a list is empty in JavaScript?

Try this:
const list = [1, 2, 3]
const list2 = []
list.length === 0 // false
list2.length === 0 // true
!list.length // false
!list2.length // true

Here's another note:
// bad:
if (!!aList.length) { // the "!!" is unnecessary because JS will make it a boolean for you
  // not empty, literally the list length when converted to a boolean is true
} else {
  // empty
}
// good:
if (aList.length) {
  // not empty - same reason as above but JS will make it into a boolean for you
} else {
  // empty
}

PS you can also just use the Boolean function/constructor:
Boolean(list.length) // true
Boolean(list2.length) // false

EDIT: Oh, you mean Snap! lists..

Last edited by liam48D (June 7, 2016 01:38:35)


202e-202e-202e-202e-202e UNI-CODE~~~~~
Jonathan50
Scratcher
1000+ posts

Snap! user discussion

liam48D wrote:

EDIT: Oh, you mean Snap! lists..
Yes, and I think I found a solution. (!list.isLinked && list.contents.length == 0) seems to work.

Not yet a Knight of the Mu Calculus.
comp09
Scratcher
1000+ posts

Snap! user discussion

Jonathan50 wrote:

What is the “correct” way to construct a linked list from JavaScript? Both List.prototype.cons and new List([]).cons seem to work, and I find it a bit odd that it's List.prototype.cons instead of List.cons.

EDIT: The Snap! source uses new List().cons
EDIT 2: how do I check if a list is empty in JavaScript?
EDIT 3: !list.isLinked && list.contents.length == 0 seems to work
You can implement linked lists yourself in JS with pointers to objects. https://github.com/benoitvallon/computer-science-in-javascript/blob/master/data-structures-in-javascript/doubly-linked-list.es6.js


Visit the website of Andrew Sun!


bharvey
Scratcher
1000+ posts

Snap! user discussion

Jonathan50 wrote:

What is the “correct” way to construct a linked list from JavaScript? Both List.prototype.cons and new List([]).cons seem to work, and I find it a bit odd that it's List.prototype.cons instead of List.cons.

EDIT: The Snap! source uses new List().cons
EDIT 2: how do I check if a list is empty in JavaScript?
EDIT 3: !list.isLinked && list.contents.length == 0 seems to work
So, the business about “prototype” is a general JS stupidity. I agree that List.cons would make more sense but this is not an issue unique to lists.

What is a special confusion about lists, which I've just noticed, is that this comment in lists.js is wrong:
    cons                - answer a new list with the given item in front
That makes it sound as if cons takes one argument, the car, and the cdr is the list whose cons method you're calling, as in my_list.cons(5). But actually cons takes two arguments, the cons and the cdr of a new pair, so you could just as well say this.wardrobe.cons(5,this.jukebox) or whatever. It doesn't matter whether you get the cons method from a particular list or from List.prototype. Maybe just List.cons would work, too, for all I know.

And, yeah, an empty list is represented as an array of length zero.

Jens
Scratcher
100+ posts

Snap! user discussion

cons answers a new list. Period.
bharvey
Scratcher
1000+ posts

Snap! user discussion

Jens wrote:

cons answers a new list. Period.
It's the “with the given item in front” part that's misleading. Cons takes two explicit arguments, but this makes it sound as if the new car is given explicitly while the new cdr is the JS “this” object.

(Please don't be grumpy, at least not in messages I'm going to see first thing when I wake up. )

PullJosh
Scratcher
1000+ posts

Snap! user discussion

Hey everyone!

I've been thinking about using Snap! to go back and learn to program the “real” way. So far the way I've learned to code has been by finding something I want to make and then figuring out how to make it, as opposed to learning a language and then creating something cool with it. This mentality is what got me excited about code, but it has left me a little bit clueless when it comes to writing elegant code or understanding the more complex aspects of programming.

Today I found the BJC website and thought it might be cool to read through each unit and try to follow along, hopefully learning to code “properly” in the process. Is this a worthwhile use of my time? (And if so, am I looking for help in the right place?)
bharvey
Scratcher
1000+ posts

Snap! user discussion

PullJosh wrote:

Is this a worthwhile use of my time? (And if so, am I looking for help in the right place?)
Yes and yes!

You might find Unit 1 and maybe Unit 2 a little easy, but hang in there for Units 3, 6, and 7. (Use the http://bjc.edc.org version.) Units 4 and 5 are stuff that have to be in the course to make the College Board happy, and aren't yet up to the standard of the rest of the course.

joefarebrother
Scratcher
500+ posts

Snap! user discussion

Any tips for optimising Snap! projects? I've started a couple of projects but they are both really slow even with turbo mode so it's difficult to make much progress on them.


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

Snap! user discussion

joefarebrother wrote:

Any tips for optimising Snap! projects? I've started a couple of projects but they are both really slow even with turbo mode so it's difficult to make much progress on them.
Rewrite some procedures in JavaScript?

Last edited by Jonathan50 (June 8, 2016 04:10:48)


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

Snap! user discussion

How to optimize any program:

Forget about ideology, elegance and code reuse and just solve the problem at hand. Think YAGNI (You Ain't Gonna Need It) again. Avoid abstraction. Don't use things like Objects, Functions or fancy stuff. All you need is a bunch of global variables and a stack. Not kidding! Making the *computer* do something fast is different from writing something for others to read or reuse. This is important. CS is about abstraction, which is for humans. Often there are sweet spots where the penalty of applying abstractions isn't so brutal. But if you're looking for raw computing power remember being fast means you want to be doing less, not writing less. This applies to all programming languages, btw.

How to optimize Snap projects:

1) The closer you stick to primitives, the faster your project will be. This also means the more “elegant” and “functional” your code is, the slower it will get. Don't get me wrong, I *love* elegant FP, it's the reason why Snap exists, but it comes at a cost (even in JavaScript, btw.) Therefore: Instead of using FOR or FOR EACH or MAP etc. using REPEAT and a script variable in an imperative style will be faster, especially if you WARP the REPEAT part.

2) WARP carefully selected parts of your scripts. Don't just “turbo” or “warp” everything, it might not make anything faster at all. WARP is about speeding up one process at the cost of others, so be cautious about it, it might end up making your project slower. In general: Only warp REPEAT stacks, not nested reporters or top-level command stacks.

3) Avoid enumerations where possible. It's faster to imperatively iterate over a list once and do everything in a single pass, than to pipe several functions that each iterate over the result of the previous one. A good example is the BJC Acronym exercise. While it is my favorite ever example of MAP/FILTER/REDUCE it's also dreadfully inefficient. Instead you can do everything in a plain old imperative way in a single pass, and it'll be MUCH, much faster, but - alas! - also much less reusable and abstract.

4) Avoid (zillions of) parallel FOREVER threads, and if you do make extensive use of parallelism use the “prefer smooth animations” setting. Duh, I guess this doesn't apply to you, since you'll be doing things in a functional way :-)

5) Cache and precompute. Don't call the same function with the same argument(s) twice. Use lots of variables and remember results you might need again. Whenever you ask for something, first check whether you've already computed it before. For example, make yourself use (temporary) variables for the “current element” of a list your script iterates over, instead of querying it again and again. Variables are less costly to access than most other functions. Similarly, use “flag” variables to cache the results of a predicate, instead of repeatedly evaluating the same predicate over and over again, as I'm often seeing people do in “functional” code. For some reason unbeknownst to me people (especially teachers) believe that variables are somehow evil or “not elegant”. Forget it! Variables are what makes computing cool. Variables are your friend. Use them!

In case you've forgotten how to program in an imperative style using primitives and variables, here's the “acronym” example in an ugly but efficient edition :-)

http://snap.berkeley.edu/snapsource/snap.html#cloud:Username=jens&ProjectName=Imperative%20Acronym

Come to think of it, it's not so ugly after all, right? There is elegance to solving a problem straightforwardly instead of first boostrapping your own DSL for it.

Last edited by Jens (June 8, 2016 08:29:16)

Jonathan50
Scratcher
1000+ posts

Snap! user discussion

What do you count as a DSL? (Does making one or two macros in Scheme and using them mean you aren't really using Scheme anymore?)

Not yet a Knight of the Mu Calculus.

Powered by DjangoBB