You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current Pyret blocks are mostly expression-oriented, while Pyret has for loops and multi-line statement contexts that don't seem to be supported yet in blocks. I assume there's some work on our side to tell Snap which holes support that and to add more block types?
Hiding Pyret syntax: the blocks environment ends up not looking a lot like Pyret syntax (there's no end, quotation around strings is omitted, etc.). So it seems like there are a few options:
accept such differences and have teachers learn full Pyret so they can help students?
keep the blocks syntax as-is, and migrate anything that shows "normal" Pyret to instead show the blocks syntax (docs, instructional material and error messages)
try to make the blocks syntax more like Pyret (with explicit quotes, "end", etc.).
Of course, and thank you for the callout as I was being very imprecise with my language.
What I mean to say is not about semantics but instead:
lexical syntax: what are we going to do about line breaks and indentation?
syntax: will we allow multiple statements inside a single hole?
Lexical syntax
As expressions get longer, Blocks world shows them on a single line until it runs out of space, at which point it breaks the line and indents just enough to leave the expression inside the circle of its parent:
The question here is whether this automatic line breaking is sufficient and understandable to the intended audience as you make more and more complex nested expressions for things like the flag assignment.
Syntax:
But more importantly, each of the "holes" today only accepts a single expression, and there is no equivalent of Scheme's begin (which is implicit in many contexts in Pyret), so making local definitions and then using them is impossible, whereas it is frequently used in Pyret:
This problem maybe does not arise: is blocks for a subset of Pyret that doesn't need nested definitions or the other cases where you want implicit begin?
--
PS: incidentally, two other things that may need adding: today in blocks world, functions can only take a single argument and there is no support for infix operators like is.
Adam, I so appreciate your thoughtful approach to design. A few responses:
Yes, I do think that blocks are for a subset of Pyret that doesn't need nested definitions. Bootstrap doesn't nest definitions at all, and that's our primary use-case for blocks.
Bootstrap uses only fixed-arity functions, so when Dorai and I designed the block language it was also fixed-arity. But that's definitely not a limitation of Snap! Snap blocks can be defined such that they contain an arbitrary number of holes.
The question of how much "real Pyret syntax" we allow to leak through to blocks is a good one. Snap is shockingly flexible, but it wasn't hard to arrive at Pyret syntax that we couldn't reproduce. The best we could do was create blocks that have all the right syntax, but not in the right place. When I was spec'ing this out, I got stuck on which is worse: blocks looking nothing like Pyret syntax, or blocks looking like badly-indented Pyret syntax.
(3a - keep in mind that it's always easier to add a feature than remove or change it, so I decided to punt on adding Pyret syntax for the first release.)
Emmanuel sent over this file as a benchmark for all the bits of Pyret that need to work in blocks world for it to be demoable.
I spent some time tonight auditing everything in that file and figuring out which bits of it do and don't work in blocks today, so we have a checklist on what is left to figure out.
Things that definitely work
image-url
scale(n, img)
if and nested elses (but note that these continue nesting visually, instead of staying at a single level like the else if, and don't allow alignment, so they're not quite as easy to understand as the text)
Things I couldn't test
use context shared-gdrive: this seems to work, but locally I can't access files on real gdrive.
we could test this for real if the latest version were deployed to the live site, with the new version of Snap that allows shared-drive to work even when its arguments start with digits
load-spreadsheet (it relies on that file)
Things that need some work
Definitions: there's no block for setting the value of a variable, which the sample file does a lot of (e.g. cat_row = row-n(...)). I think this might be straightforward to add to the language definition.
Map lookup: there's no block for var["key"], which the sample file does a lot (e.g. r["species"] == "dog")
load-table: all args are treated as strings, which is not what we need.
The "from" and "of" are treated as literal strings when we need them to refer to variables sometimes.
And the "naming columns" argument is interpreted as one big string ("a, b, c"), whereas we actually want a list of symbols (a, b, c). (I think this is fixable in the language definitions.)
This block is translated into the below code:
load-table: "a, b, c"
source: "b".sheet-by-name("a", true)
end
image-scatter-plot and other of the image functions have a similar issue where arguments are interpreted as strings rather than values, so you can't refer to variables. (I think this is fixable in the language definition.) This block is translated into the below code: image-scatter-plot("a","b","d",animal-img)
Not used in this file, but possibly a problem: there's no way to make functions that have any number of arguments other than 1. You can't remove (only rename) the initial argument, and you can't add others. (Forget the "new math", maybe we should teach currying to 5th graders)
Questions
How do we want the blocks in the sidebar to interact with their dependence on the loaded context? In this example, row-n and many other functions are available in the sidebar globally, even though they aren't defined unless you use the right context file. In a perfect world, perhaps we would detect the context file and its exports and only show the blocks for functions that are actually available. For now, do we want any kind of handling, like nicer error messages, if you pull out one of the sidebar blocks but it isn't defined in the context you loaded?
Next steps
It would be great if we could launch the latest snap upgrade in to production so we can try out gdrive contexts.
@schanzer: can you teach me how you generated the language definitions in transpile.xml? I'm not sure if I should edit those directly or if they're auto-generated and I should edit them from elsewhere.
@asolove from inside the snap submodule, you should be able to run a (full-featured) snap instance without Pyret at all. Dragging transpile.xml into the block palette will load the transpiler, and you can edit, add, or remove features as you see fit. Once you're done, you'll want to export the blocks back to XML.
I found it most useful to keep the original file open in one window, then compare it to the exported transpiler and manually copy over what I wanted. There are some subtleties to the machine-generated XML that will bite you if you replace the file whole-cloth. ;)
Activity
[-]Snap Blocks (tracking issue)[/-][+]Pyret Blocks (tracking issue)[/+]asolove commentedon Jan 21, 2024
For item 3, highlighting error locations, see: #502
asolove commentedon Jan 21, 2024
A couple other topics:
The current Pyret blocks are mostly expression-oriented, while Pyret has for loops and multi-line statement contexts that don't seem to be supported yet in blocks. I assume there's some work on our side to tell Snap which holes support that and to add more block types?
Hiding Pyret syntax: the blocks environment ends up not looking a lot like Pyret syntax (there's no
end, quotation around strings is omitted, etc.). So it seems like there are a few options:shriram commentedon Jan 21, 2024
As an aside, note that Pyret
forloops are not actually statements! They're genuine expressions. E.g.:In Pyret,
foris just a very fancy and roundabout way of writinglambda, sorry-not-sorry. (-:asolove commentedon Jan 21, 2024
Of course, and thank you for the callout as I was being very imprecise with my language.
What I mean to say is not about semantics but instead:
Lexical syntax

As expressions get longer, Blocks world shows them on a single line until it runs out of space, at which point it breaks the line and indents just enough to leave the expression inside the circle of its parent:
The question here is whether this automatic line breaking is sufficient and understandable to the intended audience as you make more and more complex nested expressions for things like the flag assignment.
Syntax:
But more importantly, each of the "holes" today only accepts a single expression, and there is no equivalent of Scheme's

begin(which is implicit in many contexts in Pyret), so making local definitions and then using them is impossible, whereas it is frequently used in Pyret:This problem maybe does not arise: is blocks for a subset of Pyret that doesn't need nested definitions or the other cases where you want implicit
begin?--
PS: incidentally, two other things that may need adding: today in blocks world, functions can only take a single argument and there is no support for infix operators like
is.schanzer commentedon Jan 23, 2024
Adam, I so appreciate your thoughtful approach to design. A few responses:
(3a - keep in mind that it's always easier to add a feature than remove or change it, so I decided to punt on adding Pyret syntax for the first release.)
asolove commentedon Feb 29, 2024
Emmanuel sent over this file as a benchmark for all the bits of Pyret that need to work in blocks world for it to be demoable.
I spent some time tonight auditing everything in that file and figuring out which bits of it do and don't work in blocks today, so we have a checklist on what is left to figure out.
Things that definitely work
image-urlscale(n, img)else if, and don't allow alignment, so they're not quite as easy to understand as the text)Things I couldn't test
use context shared-gdrive: this seems to work, but locally I can't access files on real gdrive.shared-driveto work even when its arguments start with digitsload-spreadsheet(it relies on that file)Things that need some work
cat_row = row-n(...)). I think this might be straightforward to add to the language definition.var["key"], which the sample file does a lot (e.g.r["species"] == "dog")load-table: all args are treated as strings, which is not what we need."a, b, c"), whereas we actually want a list of symbols (a, b, c). (I think this is fixable in the language definitions.)This block is translated into the below code:
image-scatter-plotand other of the image functions have a similar issue where arguments are interpreted as strings rather than values, so you can't refer to variables. (I think this is fixable in the language definition.) This block is translated into the below code:image-scatter-plot("a","b","d",animal-img)Questions
row-nand many other functions are available in the sidebar globally, even though they aren't defined unless you use the right context file. In a perfect world, perhaps we would detect the context file and its exports and only show the blocks for functions that are actually available. For now, do we want any kind of handling, like nicer error messages, if you pull out one of the sidebar blocks but it isn't defined in the context you loaded?Next steps
transpile.xml? I'm not sure if I should edit those directly or if they're auto-generated and I should edit them from elsewhere.jpolitz commentedon Feb 29, 2024
If you want to deploy I'm happy to merge to
horizonand you can test with the Google keys + setup at https://pyret-horizon.herokuapp.comschanzer commentedon Feb 29, 2024
@asolove from inside the snap submodule, you should be able to run a (full-featured) snap instance without Pyret at all. Dragging
transpile.xmlinto the block palette will load the transpiler, and you can edit, add, or remove features as you see fit. Once you're done, you'll want to export the blocks back to XML.I found it most useful to keep the original file open in one window, then compare it to the exported transpiler and manually copy over what I wanted. There are some subtleties to the machine-generated XML that will bite you if you replace the file whole-cloth. ;)
Happy to sit down on Zoom with you, if you like!