Why Does Take work differently than a For Loop

I just discovered this language at Aldi of all places. Got a learn how to code book using Snap for my son because he's 12 and getting curious about what dad does for work (we've sat down to talk through very high level what some of the code I'm working on does)

So in the spirit of trying something new I've been playing around in snap myself so i'm at least mildly competent when he asks me questions or gets stuck. But I've hit a point where things don't make sense

To set the stage I'm drawing a perfect black square of whatever size then saving the PenPaths to a costume, then repeating with a white square. Then i'm cloning that single object to layout a grid of whatever row and column count. finally a little when clicked to toggle white to black to white for its costume

Now to the point where i'm lost. Looking to detect (like in minesweeper) the up to 8 "touching" squares (5 on the edge, 3 in the corner) I found code like this that works

Apparently I cannot use pictures in my post so...

set Close Neighbors to list
for each Cell in my:neighbors
    if touching Cell ?
        add Cell to Close Neighbors

But I noticed there are functional blocks for all your map, filter, reduce needs so read through the docs on them and thought I would recreate the for loop as a single Keep From block

Set Alt Close Neighbors to keep items touching object:myself ? from my:neighbors

To me these should be logically identical

First opens an empty list loops through all the neighbors (I get the idea of neighbors is loosely defined) checks if (I assume the calling clone) is touching that sprite from its neighbors and if it is adds it to the list. Simple makes sense.

However I should ALSO be able to START with the my:neighbors list and then ONLY keep the items actually touching:myself

So why do I get things that are 2 blocks away acting like they touch in this method?

I feel silly coming back literally minutes after posting answering my own question.

I had assumed that each individual call to the predicate was from the perspective OF the individual item. i.e. checking if each item in the filter was touching the object that was initiating the filter

Most of the languages I work with treat lambda's like that. the individual item as each predicate or functor executes scopes to be the one comparisons are made against.

Seems in Snap the calling object retains its role as the object comparisons are done against even in a Lambda

The solution was ridiculously simple

went from

Set Alt Close Neighbors to keep items touching object:myself ? from my:neighbors

to

Set Alt Close Neighbors to keep items touching ? from my:neighbors

I'm assuming by dropping the explicit reference to mouse-pointer, edge, pentrails, it defaults to just say anything is touching. I'm not sure what is actually happening here. I would love to get some insights the insane levels of implicit references in this language is frankly a little nerve wracking to me coming from mostly strongly typed languages

I think what you're missing is that an empty input slot in a lambda expression is filled with the actual argument when the resulting procedure is called:


Similarly, in

the empty input slot in TOUCHING is filled with one item of the input list (MY NEIGHBORS in this case) each time the predicate is called.

(You'll be able to post pictures after you read a bit more. The initial restriction is an anti-porn-spam feature.)

This empty-slot notation is supposed to remind kids of the 3+:white_square_button:=7 notation you see in elementary school arithmetic. The empty slot is the box. (Kids younger than around 12 typically can't answer questions such as "3+x=7; what's x?" but much younger kids can answer "3+:white_square_button:=7; what number goes in the box?")

Ordinarily, all code in a given sprite's scripting area that that sprite as an implicit argument. The exceptions are
untitled script pic (5)
untitled script pic (6)
and, at a lower level of abstraction,
untitled script pic (7)
to access a local procedure of another sprite.

Thanks for the clarification and explanations. It's starting to make a bit more sense. I learn mostly by experimentation and observation all wrapped in iteration so those examples are a huge help to give me something to play with to observe and understand things

I'm genuinely enjoying playing around but coming from C, C++, C#, PowerShell etc is making it harder to think in terms of how Snap operates to me at least there is a lot of implied behavior under the surface you either have to know ahead of time. I'm sure its in the documentation somewhere but I couldn't find an easily searchable reason why dropping a reference in something like the touching predicate would do what I expect. In languages I'm used to you explicitly mark out your predicate something like

this.Neighbors.Where(neighbor => this.touching(neighbor)) or
this.Neighbors.Where(neighbor => neighbor.touching(this))

There's no room for interpretation in the predicate its literally right there. so when its (at least to me) left ambiguous in a Snap predicate I get stuck trying to sort the logic out.

Probably been coding so long in higher level languages playing with these more mechanical style Turing machines makes my brain glitch out for a bit

Try not to use a phrase like that around here :slight_smile:

Not meaning to offend but what exactly would you call it then. I'm not downplaying Snap but to me it does seem more like a graphical representation of a classic state machine than something like C, Java, Pascal, etc.

Mind you i've actually programmed in assembler its many flavors in the past so i'm just used to calling something like C higher level

em - do C, Java or Pascal do co-operative multitasking OOTB?

Different languages have different strengths :slight_smile:

All languages above assembler were considered higher level languages when I started programming :slight_smile:

You're in our house - don't diss the wallpaper :slight_smile:

Fair enough. I'll try and keep my sacrilege to a minimum :stuck_out_tongue: Been in this game long enough to remember a time BEFORE auto complete, and any kind of IDE so I know how religious we can be as programmers

Genuinely ask now that I'm thinking about it Higher level language is a bit off the mark. Would it be less heresy to qualify something like C# as strongly/strictly typed languages vs the variant type(?) style used here?

Also definitely not dissing more trying to understand HOW and WHY the wallpaper.

I'm pretty sure they mean low level programming languages, as snap is a high level programming language, whereas c, c++, c#, etc. are low level programming languages.

Also, I don't see anything wrong with them mentioning they're used to low level programming, because it allows us to know what they're used to. It's also very clear that they are interested in how snap work, and how to code in snap, not saying how it should work. It's also good for them to compare and show what they're used to, and learn about how snap handles this.


In that case, I would think of it kind of like this

this.Neighbors.Where(neighbor => this.touching(neighbor))

this.Neighbors.Where(neighbor => neighbor.touching(this))

or

this.Neighbors.Where(neighbor => (parent => this.touching(parent)).call(neighbor, this))

If it's not explicitly stated, then snap will run it in the context that the lambda was created in. If you create a lambda in a sprite, blocks will execute as if they were in that sprite. If you want to call a function on a different sprite, you need to explicitly state that with an ask or tell block.

Alll your family of languages are minor variants on C, which (ironically) was designed specifically for writing an operating system, i.e., to carry out low level memory manipulation. That's why pointers are such a big deal in C and its children, so you can get at the page table and the I/O device registers given their addresses. (That's also why they have the bizarre idea of zero-origin indexing, so that an item's cardinal position doesn't agree with its ordinal position, i.e., "item 5" is the sixth item, not the fifth. That's why people think programming is hard.)

As for "strong typing," I put the name in scare quotes because it's kind of a misnomer. What I think you mean is that types are associated with variables, rather than with values as in higher level languages. I guess you are, like me, old enough to remember when user interfaces consisted of telling the user "type 9999 when done" because the user was entering values into a numeric variable and therefore couldn't just type DONE when done. Language designers used to attach types to variables so that compilers could issue integer arithmetic instructions or floating point arithmetic instructions at compile time, because runtime type checking was too slow. These days, computers are so incomprehensibly fast that constant factors in timing are essentially irrelevant, just as the CS theory people told us all along they would be. So in newer languages such as JavaScript and Python, all variables are declared as type VAR, meaning that they can hold any value. Newer languages, that is, and also the other genetic kingdom of programming languages, the ones derived from Lisp rather than from Fortran -- that is, the higher level languages. :~)

So, "strong" doesn't really catch the distinction, which is between early typing (the Fortran Kingdom) and late typing (the Lisp Kingdom). Words like "strong" and "strict" are about a related but separate question, namely, to what extent the language allows implicit type conversions. In a truly strictly typed language, you couldn't do 2.5+3; it'd have to be 2.5+3.0, so that the numbers were natively of the same type, or 2.5+(float)3, with an explicit type conversion. AFAIK there actually aren't any fully strict languages. Some newer languages even allow implicit conversion between numeric and string types, so you can say "012345"[3]+7 and get 10 (supposing you index from 0, like the C family, rather than from 1, like Snap!).

We are definitely in the Lisp Kingdom. As such, we strive to allow programmers to think in terms of the problem they're trying to solve, rather than about the idiosyncrasies of computer hardware. This is particularly important if your goal is teaching kids, but we think it helps adult programmers too. High level abstraction includes big ideas such as first class functions, and also a myriad of details such as recognizing that numbers have as many digits as you need, and recognizing that human beings suck at memory management and so denying them access to things like malloc() and free(). Computers are great at knowing when a chunk of memory has become useless, i.e., nothing points to it, and so we just get out of the computer's way and leave it to it. (A very few superpowered human beings can do memory management, and they're allowed to write compilers and operating systems in C and its children.)

I'm not sure what you mean by

Where are you seeing a state machine? Snap! programs are stateful in that you can change the value of a variable, but that's not different from C and friends.

Wow those little black arrows are going to be the death of me in this language!! :stuck_out_tongue:

I didn't even realize keep items HAD overloads (or any of the other reporters or predicates) I had figured it out with the + and * operators already not sure WHY it didn't click I could do that for the other stuff...

I'm normally a be as explicit as possible when I code developer but it is fun to play around with a slightly less explicit language to see what I can figure out.

I'm also trying to avoid any libraries and especially using JavaScript so I'm experiencing the language as plain vanilla as possible as my son has of course a very miniscule programming knowledge and he's the one I'm learning this for. (can't deny I'm not having fun though :wink: )

Thanks a bunch for giving me a quick lesson I'll never forget

Historically, our genetic tree is convoluted, Lisp -> Logo -> Smalltalk -> Scratch -> BYOB -> Snap!. You'll note that from almost the beginning of this history our ancestors have been focused on teaching kids, and many design decisions large and small come from that passion.

(Smalltalk is a special case; its early versions with Alan Kay in charge were all about kids, but later there was a fairly dramatic shift to focusing on adults who'd grown up in the Fortran Kingdom. It's the early Smalltalk that influenced Scratch.)

Since then we've done some genetic engineering. When I joined the team I brought a Scheme world view with me, so there's a Lisp -> Scheme -> Snap! genetic pathway too. And we've introduced some exotic DNA from the functional but array-based APL.

Definitely agree with you on all of that. I'm definitely enjoying playing around with Snap because its giving me something to stretch my thought process outside my normal coding for work. I've always enjoyed dipping my toes or going for a quick swim in other languages or even dabbling in paradigms I don't normally work with because it gives me ideas on how to approach problems i might normally not have if stuck with say just OOP or just Functional

I'm enjoying the feed back too because I'm rethinking a lot of the concepts I've played with over the decades. I guess to me I've always separated the kind of languages I've used over my career into two camps variant (ECMAScript, COM, VBScript, PowerShell) and strongly/strictly typed (like C#) where yes it bends the idea a bit but you're still required to define your types and if the covariance and contravariance are not defined to allow implicit casting you have to cast things explicitly.

I can remember my first experience with VBScript at a job after I had learned C, then C++, and finally C#. Could not for weeks figure out why a particular script was going south. Everything about it looked solid even recreated it in C# and it worked perfectly. Turned out after finding a little VBScript IDE that had a built in debugger and I was actually able to step through the code low and behold one of my variables was a completely different type than I thought it should be at a critical point in the script. Once I saw it, I knew what the problem was immediately but I still had to use a debugger to tell me something in my opinion the code should have told me.

I'll admit I'm probably a bit salty from that kind of an introduction to variant typing ( I did a tiny bit of apple basic but pretty much jumped right to learning Borland C as my first language I did anything serious in, VBScript just happened to be a job specific necessity and I spent half a decade coding in VBScript almost exclusively )

Now When I say state machine I mean in terms of the Turning concept of a state machine like you learn about or at least used to learn about in school

The graphical way Snap lays out your code reminds me of pretty much how I would picture the theoretical state machines we would talk about in class when we were covering Turing and things being Turing complete.

Is it so hard to just subtract one when getting/setting list items?
If I were to make a completely independent* then i would let the user choose between 0- or 1-indexed, even if it is so simple.

Again, if I were to make a completely independent* language I would try to account for everything the user would do, so the string "1.5" + the integer 1 = the floating-point 2.5, except if it can't be converted to a number so instead it would try to concatenate ("a" + 1 = "a1")


*Big asterisk: other than the compiler or interpreter

Yeah, that's what Python does. I think that's asking for bugs in your users' programs. They do that overloading, I think, because (1) back in the ASCII days there were only 128 characters, and only 20 or so were punctuation, and (2) they were worried because "JOIN" is three more keystrokes than "+". But (1) has been solved by Unicode, and (2) has been solved by block languages! You never have to type the word "join"; it's just as easy to drag out of the palette as +.

Sorry, I know what a state machine is; I meant, how does Snap! look like one, and I'm still not sure from your answer. A stack of blocks looks exactly like a sequence of instructions in a text language. There's no "next state" field in an instruction, for example. The repertoire of commands doesn't include anything like "move the head left."

Did you have an automata theory textbook that drew Turing machine programs as stacks of command blocks, or something?

Books? Not any more. had one way back when I was in school. My Assembly professor was big into Turing and general programming history

Sorry if I'm not explaining it clearly its simply that i found it amusing when I first saw Snap it reminded me of how when I was first learning about it I would visualize the idea of pieces of the state machine being big color coded blocks that each maintained its own state but played into the larger state machine.

I work as a kind of automation engineer, primarily building focused, fast, concise tools that I or others use in conjunction with other tools to build out or enhance existing tasks. So I'm constantly working IN the idea of a state machine as every Tool I build HAS to work or fail in a digestible controlled manner regardless of the inputs it is given, and each Tool has to handle JUST what its supposed to do.

I've just been in this space for so long, gotten so used to the languages I use regularly I didn't notice I think primarily in code now. Of course the general problem is thought about visually I really hadn't thought about how the code comes together in a visual way for ages. Playing around with Snap has sparked a bit of that, and I'm enjoying the nostalgia trip if nothing else

No, that's javascript. Python throws an error if you try to concatenate a str and int

>>> 'a' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module> TypeError: can only concatenate str (not "int") to str

Ah, thanks. I knew it was one of them...

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.