Inconsistency between calling and running directly

Steps to Reproduce

  1. Do the following script below:
    untitled script pic (31)

  2. :white_check_mark: Notice that the block runs correctly.

  3. Now try running the script below:

  4. :x: Notice that the block does not run correctly, despite being called with the same script.

Cause

List inputs with nothing specified are treated as empty lists. However, if ringified, then placed in a call block, it is treated as a nothing text, therefore breaking it.

But, it says "getting a text", not "getting a nothing".

i guess that nothing is a text by default

The underlying issue is that CALL, RUN, and the blocks that depend on those, namely the higher order functions, substitute actual arguments (provided by CALL etc.) into empty slots in the function being called. If you said


it would be clear that what matters is what's in the "with inputs" slot, rather than the empty IN FRONT OF slot.

And yeah, if you leave that WITH INPUTS slot empty, it's treated as an empty text string.

Let me point out that
untitled script pic (3)
by itself is an error, even though not called out as such by Snap!. Since it's an error, we get to do whatever we want!

i don't think undefined behavior is good for a language designed for learning

It's perfectly well defined; you just have to understand about substitution of actual arguments into empty slots in code being CALLed/RUN.

For what it’s worth: I agree with @sarpnt and @ten_6044: consistent error handling is an asset (especially with an environment that aims ar being child/adolescent-friendly: they tend to value consistent behaviour from actors in their environment).

All right, I was trying avoid having to write a serious reply. But here it is: Our handling of errors is consistent, at least in this regard. What y'all are complaining about has nothing to do with error handling, really; it has to do with the fact that an empty input slot has a special meaning in the context of CALL, RUN, and other blocks, such as HOFs, that have ringed input slots. Outside the context of CALL etc., untitled script pic (2) means the same as untitled script pic (3); the default numeric input value is zero. In a text context, the empty slot in untitled script pic (4) means the empty string.

But in a CALL, etc., empty slots mean to fill the slot with the actual input values provided by CALL. So,

means untitled script pic (6). You all know all this, right?

The same reasoning applies in the OP's example. In
untitled script pic (3)
the empty input slot provides the default list input, namely the empty list. But in


the empty input slot is filled with the list (a b).

So, now the question is, what if you're inside a CALL, but don't provide an actual input value?
untitled script pic (9)
This, I guess, is arguably something you could complain about. According to page 68 of the manual, if the number of actual inputs supplied doesn't match the number of empty input slots (with exactly one actual input matching any number of slots), then we supposedly don't substitute at all, and so that expression should treat the second input slot as meaning an empty list.

But as I recall, we've since changed that, but alas I forget why. Something about zero empty slots accepting any number of actual inputs, putting them in a list, I think. But that isn't what happened in this case, so I'll have to ask Jens. (Good thing he isn't old enough to start forgetting everything!)

So what's problematic is that CALL etc. substitute an empty text string in that situation, rather than substituting the appropriate default for the input type. I suppose you could call that a bug, if you don't mind categorizing it as one of those bugs that'll never be fixed.


The whole idea of using empty input slots as implicit formal parameters, places to put input values into, is controversial, I guess, even among ourselves. Even I have days when I wish I'd invented an unambiguous notation, although most days what I wish is to make it unambiguous the other way, by not using empty slots to denote using default input values. After all, we have a notation for that, the "hello·" and "world" in the JOIN block, for example. We could have put untitled script pic (10) in the palette to make the default inputs clear.

But I claim there's some good research behind using an empty slot to mean a place into which to substitute a value. Namely, if you take an eight-year-old and say "x+3=7, what's x?" you most likely get "huh?" as the answer, but if you take the same kid and say ":white_square_button:+3=7, what number goes in the box?" you reliably get "4." Empty slots are intuitive. If you show someone


they just get MAP, better than five minutes of lecturing about it. Maybe

would do just as well; someone who believes in education research more than I do should try it. But I'm guessing no, not even if you changed the notation to
untitled script pic (13),
because for that to make sense you have to be thinking about functions, an idea you might not even have learned yet. Remember, third graders get :white_square_button:+3.

The background to this was people telling us BYOB (as it was then) would never work, because anonymous functions are such an abstract idea. And yeah, if you call it that, it's scary. But :white_square_button:+3 isn't scary at all. I bet a really good teacher, such as Paul, could teach it to six-year-olds.

The brilliant move (if I do say so myself) we made in 4.0 was to use rings as the "type indicators" (in quotes because they actually do something) for function types, so we can use MAP without talking about functions at all! (Of course eventually we do want to talk about them.)

i never said anything about what is or isn't defined. you're the one that said that because it's an error, it can do anything. that's a description of undefined behaviour. if it were defined, it would either do what the code says, or if that's not possible, give an error message, preferably one that helps the programmer solve the problem.

i originally saw this behaviour as a well defined footgun (still very bad for a language designed for learning), but looking at it again, is it actually defined? it wasn't called with any inputs. have you actually decided that an empty input in a call should be and will always be an empty text? are the various empty inputs on other blocks properly defined? do you test for this? if this code could behave differently in a future version, it's undefined.

actually, are there any proper tests run to make sure code continues to work the same between versions? i don't see any automated tests of any kind in the source code.

EDIT: looks like you've replied before me and already admitted the behaviour has changed randomly and is still undefined. my point stands. as long as there aren't tests, it seems like just about any unusual or complex script might be undefined. could adding tests be considered?

Guys, just use
pic

No, what I said is that there was a change, I'm sure it's documented fully in Jens's HISTORY.md log, which I'll eventually get into the manual, and that it was a well-defined change for a specific reason, one that I don't at the moment remember. Next time I get together with Jens I'll ask.

And, Jens is very good about regression testing. That doesn't mean we won't ever make a backward incompatible change, but it doesn't happen often, and it's always deliberate. (Or if not, it's a bug, and it gets fixed in the x.x.1 release as soon as someone tells us.)

Sure, if you already understand the issue. The original complaint was that something happened that the OP found incomprehensible.

Okay. Sorry.

I was a bit worried by your first statement (and somewhat reassured by the second). It reminded me of the Netherlands’ prime minister, after having been sent away by parliament and having stayed in office awaiting the arrival of a new government*, half-seriously stating, in parliament: “We can do whatever we like, since we don’t have to care any more about you sending us away”. Now you’re in an even more powerful position within the Snap! realm, as there is no (democratically elected) parliament, just a benevolent dictatorship :wink: (BTW I read in the Wikipedia article on BDFL that Guido van Rossum resigned, or at least announced he would resign, in 2018)

*in the Low Countries, we have quite a tradition of caretaker governments (off-topic)

Both the Netherlands and Belgium have been governed by coalitions for as long as anyone can remember. There are no electoral thresholds, so many political parties represented in parliament. Complicating things, both countries have major right-wing political parties that are, or were, excluded by most others.

  • The Netherlands as a state originated from a mostly protestant uprising against a catholic (Spanish) king, and its people have been hair-splitting (religiously, and otherwise) ever since. There are 15 political parties in parliament (more than 20 last year). The current government offered its resignation almost 8 months ago, general elections were in November, and the formation of a new government will probably take some more months.
  • Belgium has two major languages and one minority language. On the federal level, several political movements are represented by a Flemish and an Wallonian political party. Belgium had a caretaker government for two years (2009-2011) awaiting the formation of a new governement (which took a whopping 541 days from the election date, a still-standing world record). A blessing in diguise: with less than 12 million citizens, Belgium has 6 separate governments on a supra-provincial level (not counting the European Commission, in Brussels), so there's always at least someone in charge somewhere.

Is this because of negotiations among the parties over exactly how many seats each party gets?

Much worse ... They will probably have trouble convincing competent administrators to become cabinet members. But for now, it's about policies, and above all: political culture. One of the four negotiating parties focuses on good government, while the leader (and sole member) of the largest (far-right) party has a record of bashing immigrants, reporters, judges and parliament itself.

Ouch, just like here.

Well, yeah, it's harder with >2 parties, but it's worth it, because people like me with minority views get to express them. We wouldn't be stuck with Biden vs. Trump.

What are you getting at?

I've heard from some of my american friends that both candidates aren't the best, so voting is more like choosing the lesser of two evils.