Strong? encryption by just multiplying text (viewed as an integer in base 2^32) by an integer

Ring parameters

IIRC you don't have to check the sort order of X and Y. If they're backward, the first iteration of Euclid will swap them.

Sorry I should have looked closer. So your program defines euclid as a local function And this is to avoid the check for valid inputs on each recursion. Makes sense. I hadn't really thought about this problem - it is very common for recursive functions to need input tests only on the first call. I like the beauty of recursion and it is sad that efficiency concerns encourages these blemishes.

Note that a clever compiler could unroll the recursion once and infer the types enabling simpler prettier programs.

Not mine; it belongs to @qwertyperson.

Agreed. This pattern was used in some of the official tool blocks for defining a recursive step. I kind of wish there was a cleaner-looking way to define and call inline functions, but what Snap! has is miles better than a lot of other languages.

On the "We are definitely going to do this As Soon As Things Slow Down™" list is to allow internal definitions, so when you right click on the background of a Block Editor and choose Make a block, it makes a block that's lexically within the scope of the Block Editor and can use its local variables.


This is not a promise about the exact notation! The slightly darker hat block on HELPER shows that there has to be some notation for which is the main definition and which is/are internal. Probably this way to denote it is too subtle and if we did anything like this, the hat block would be deep brown. (Although if we ever adopt the Scratch brown event block category, it'll have to look different from that.) But the point of the picture is its semantics, namely, that HELPER can use the variables A and B from FOO.

But a notation such as this only solves part of the lexical scope problem; it doesn't allow for a group of toplevel procedures all sharing a collection of local state variables. This notation has just one toplevel procedure, which is a very common case, worth solving, but not the whole story. To solve the whole problem we need, I think, the Logo DEFINE command, which lets you define a block programmatically.

(The reason this is more of a problem for us than for Scheme is that we are a Lisp-2, so a procedure is a syntactically different thing from a variable. We can set a global variable to (the value of) a lambda expression, and semantically that's a toplevel procedure, but you have to use a CALL or RUN block to use it.)

Okay on second thought I should have made it a gray hat block.

Another approach to this problem is for me to hold my breath until Jens gets around to min/default/max arity for variadic inputs, and then use 0/0/1 for inputs that don't appear in the block in the palette, and are never (by convention) provided in a toplevel call, but can be used in a recursive call. (The input dialog would specify a default value, just as normal inputs can have default values.) This is the Object Logo/Berkeley Logo solution to the problem of recursive helper functions.

I'm guessing you edited the image to get the hat block in the block definition dialog?

Photoshop is your friend. Except when it refuses to do what you want.

yeah, I use paint.net

Thinking about why I asked about where a and b were defined it occured to me that when I scan for the introduction of local variables I don't look after the body of the code. Snap! may be unique in that instead of lambda variables body we have ring body variables,

Perhaps a mistake?

Well, the reason it's that way is that we expect the ordinary use case to be rings without explicit formal parameters, instead substituting into empty input slots. And our notation for adding something to a block extends to the right. Our target audience doesn't speak Lisp and so doesn't have expectations about the syntax of lambda. :~)

Makes sense. But I think there is still a good argument for a syntax that introduces variables before using them. I think it is easier to read and not because I'm used to this convention.

Yeah, if we'd designed around the case of explicit formal parameters we would have put them first. What we have is the endpoint of a series of design decisions not explicitly about that case.

PS In math other than lambda calculus it's also parameters first: f(x)=... or x ↦ ... But there are cases in which they come late, e.g., the result of a definite integral is sometimes shown as the result of the indefinite integral, then a vertical bar with x=a at the bottom right and b at the top.