-
Notifications
You must be signed in to change notification settings - Fork 745
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cannot pass function as input via call block using implicit arguments #2836
Comments
Doesn't the ring need to go around the |
The reason the 2nd one doesn't work is that you can't "remove" the ring input to map, so you need to use the
My own thoughts are that:
|
Hmm... I was hoping there was a way to avoid that... :) I posted a simple example so I didn't get caught up in a bunch of irrelevant details but basically I am actually using this in the autograder where the assignment creator is defining a function which accepts the custom block as an input so they are unable to add formal parameters (ie, the inputs need to be automatically detected). As an example: I am sure I can detect them automatically but it seemed like this falls under the umbrella of improving the automatic argument input detection (assuming this isn't the expected behavior!). However, my specific use case is a little bit of an exception since I know that all the inputs are empty so they don't really need to be detected in any clever way... |
I guess my question could be more specifically asked as "should ring inputs be considered empty (ie, |
I see. Yeah, the PR makes sense. I think we've gone back and forth about what's "right", if I am remembering previous discussions. However, I do think empty rings should be considered empty slots. IMO, that makes sense, but I may be forgetting something. |
A while ago we decided that an empty reporter ring should mean the identity function. That decision might have broken this, although we could consider them empty for purposes of substitution, and then if they're /still/ empty, treat them as the identity function. |
Ah, I vaguely remember this. What was the reason for that? identity functions are useful, but it seems a little odd. |
Well, it had to mean /something/, even if only an error message. And, if you think of the inside of the ring as a slot into which something can be substituted (rather than including the ring as part of the emptiness) then it's kind of like the block-with-no-name sort of identity function. |
I'm not completely opposed to this suggestion, in fact, we've been discussing it on and off for a long time. Three points are important for me:
ad 1) ad 2) Even though @brianharvey is working on changing that as we speak, and we agreed - in principle - to support dropping reporters that return costumes and lists in those slots. But that still won't make them support implicit parameters, and I'm not even sure whether and how those could / should be supported at all. Other examples of inputs that can't (as of now) be blank are upvars and "static" lists. ad 3) For the future I really want to extend Snap! with first-class expressions ("blocks") and also with first-class variables (which can then also be formal parameters for functions). This will let us programmatically create scripts as well as functions, even custom blocks. There are, of course, lots of design issues around this, starting with how to visually represent and "quote" an expression. We've been discussing this on and off, I'm currently leaning towards @bromagosa's suggestion to simply visualize expressions as plain blocks, but @brianharvey's proposal to overload rings with the semantics of quoting expressions (as we've also done with continuations) is also possible, interesting and attractive. We'll also need the reverse operations that will make functions truly first-class: Querying a function for its body (an expression), its name (we're currently abusing block-specs for this, and this might be right, except in the case of translations, which is, of course, the normal case we tend to forget and ignore outside the U.S.), and its inputs (which might just be text, a list of names, or something more block-ish). While this is exciting to think about it also uncovers some more or less serious design flaws of present Snap, especially those concerning implicit inputs. For example, just looking at a Snap function that uses implicit inputs makes it impossible to tell how many implicit inputs it has or expects. In Snap's current practice this doesn't matter much, and is even kinda "beautiful", but when we're going to make functions fist-class, it's a cardinal sin. We might even end up treating implicit-input functions differently than formal-input ones. The latter can be reasoned about, the former only "used". Also, this kind of going meta on functions and expressions might not be the lowest hanging fruit pedagogically. I'm personally excited about it, but I'm also excited about spreading messages that aren't so super meta in the first place, like recursion, hofs and linear algebra. And in the nearer term making the IDE more customizable to support actual curriculum ideas might be more worth the effort than adding yet more esoteric features which only a handful of savants are going to appreciate and criticize. Anyway, great discussion! |
Thanks for all the info! I suspected it might be a part of a much bigger discussion and it is nice to be brought up to speed! :) @jmoenig - I updated the issue title to better reflect the actual issue! |
@cycomachead I absolutely agree about the ordering of inputs and function body in rings, it's a conceptual problem that the formal parameters come after the body expression. Of course that's also something that makes it easier for users to get started with implicit parameters, which is why I said it's kind of "beautiful". Another similarly "beautiful" hack is automatically unringifying nested lambdas, e.g. when dropping a variable into a ring. It lowers the entry bar for using functions but makes understanding them much, much harder in the longer run. In many ways I feel we've made Snap! the perfect entry language for functions, kinda like a guitar lets you quickly advance to playing 2- and 3-chord songs, and we've successfully shifted the learning curve further away in time, but it's still there to come back with a vengeance, and it gets even harder in some cases, because of all those design kludges and little inconsistencies we put in (e.g. placing formal parameters after the function body in rings, allowing totally different semantics for handling multiple empty input slots inside a lambda at call time). I'm not saying these decisions are bad, in fact they are beautiful in some ways. But they also lower the expressive ceiling. @brianharvey your color slot designs are a great example of that lower ceiling. They don't address the issue I've raised about determining the number of inputs for a function with implicit parameters, because by design we cannot tell before call-time. And even then those colors aren't helpful because now we're talking about doing to programmatically inside what you call macros, i.e. programmatically generated expressions. We don't need a kiddie library to play with blocks as data! This is what our code is doing precisely, this is what we do as Snap developers, it's what blocks.js is all about. It really boils down to what we think a ring is. I've stated my opinion: A ring is function literal, an expression that takes another expression and a set of variable names and returns a function. Another opinion could be: A ring is a shape for an input slot indicating that its expected data type is a function. I'm sure we all agree on the first definition, but some of us also agree on the second one :-D |
P.S. If you think of arity not as a number but rather as three numbers, min/default/max, then you can tell users that the arity of + is 0/2/2. |
Umm, okay... That's an interesting tool but I'm not sure what it's the answer to. |
oh yeah, haha, pressed okay too quickly ;-) that's an expression. It goes into an empty ring, eventually. |
btw, I don't understand your remark about sprites without a costume, a.k.a. the "Turtle costume", or how that compares to a function with ambiguous parameters. I think this issue might be veering off topic. |
Oh, you said that not knowing the arity of a procedure is as bad as it would be not to know the dimensions of a costume, so I pointed out that you don't know the dimensions of a costume, if it's the Turtle costume. We don't have to resolve that longstanding disagreement (you should've called it "None" if you didn't want users to think of it as a costume!); I just wanted to point out that you're not consistent in thinking that it's terrible if you can't see inside some data structure. |
I have been encountering an error when trying to pass a function to a higher order function block as below. I suspect that perhaps the ring in the
map
block is causing the first input not to be detected as an empty input.I ran into this in NetsBlox and was going to dig into it but wanted to first make sure this wasn't by design (and avoiding some bigger issue if the behavior is changed!). Is this the expected behavior?
The text was updated successfully, but these errors were encountered: