Let* and letrec for App Inventor

Hi folks,

It’s David here from MIT App Inventor. I have been working on implementing let* and letrec for App Inventor and I would like some feedback from our community.

First of all, Do you think these new blocks would be appreciated?
Next, I’m having a hard time how to name the blocks. Basically, the first two are let* and the bottom two are letrec. Any great ideas how what would be the best way to name these blocks for the users?

Btw, if these blocks do get released, I’m thinking of nesting them under the Variable category as More

Any feedback would be greatly appreciated:-)

1 Like

How about a use case for those?

What languages have such a construct?

The biggest usage would be that these blocks would allow to reference local variables defined on the same let block. So the need for nested let blocks will be unnecessary

Maybe these names are better?

Is there any point in having the "one above" block, when you have an "any" block ? Should this "any" block become the default for local variables ?

1 Like

I spend most of my time on this board reading other peoples' code.

The nested local inits are a reading aid as far as I'm concerned.

When I see your use case, I see a nightmare knot to be untangled.

So would you suggest that the only let block we have upgraded to the recursive let block would be the right direction?

Sorry if I’m misunderstanding, so you think just leaving the let block as it is better? and none of these let variances?

@TimAI2's idea of allowing upward references in the local init covers your use case, and conforms with the idea in block languages of supporting dependencies by spatial reasoning.

Data flows from right to left, control flows from top to bottom with occasional branching to the right, and initialization flows from top to bottom, even within the same init block.

Did I get that right?

As a further note, this is the first time I have seen an AI2 construct that was W-T-F worthy.

C has books devoted to its W-T-Fs.

(Apparently this board regards the W... acronym as rude. I regard the coding practice as rude.)

I guess us "old timers" are used to the behaviour of the local variable blocks as they are.Newer users will find out by trial and error that variables cannot be set and available at the top.

let me show a few more examples of how those blocks can be used.

The third variation, would be mostly used in the above case, where variable can be recursively used.

As another side point, I have encountered limits to AI2's recursion ability in the past.

I vaguely remember being warned about the limits of Ai2 tail recursion, possibly by @ewpatton.

I have a block based matrix multiplication routine that attempts to recurse by dimension. It fails on cubes.

The syntax should not make promises that the compiler can't keep.

This would be a use case for the second variation.
Using the regular let block, one would have to nest four let blocks to make the above work.

One can do the above using the third let variation

2 Likes

That's pretty readable.

There's no back and forth to determine dependencies and order of operation.

Dependency flows in only one direction, upwards.

Given the points raised, I also am not sure we really need letrec. It's effectively syntactic sugar for the regular let block where all of the variables can first be initialized with some trivial value (false) and then within the scope of the block set the variables to the desired values. I agree with ABG that generally for beginners it's good to have the flow be treelike to make it easier to reason about whereas letrec opens up the opportunity to make graphs with cycles that are harder to reason about. I recall a thread with Lyn years ago where we explored this idea. I will try to dig it up.

It seems not very dissimilar from this:

There's no need for an extra block type for this.

Just smarten up the existing init blocks with multiple sockets, behind the scenes.

Counter-argument:

On further thought, the current limitations may be wiser, albeit not more clever.

Nested init block clusters read like topographical maps, where the density of the inclination lines (isoclines) tell you in advance that you are headed for a cliff.

That's a good thing for a code reader.

The difference is you cannot use those variables inside it’s definition. (i.e., ‘x’ cannot use ‘name’, ‘x3’ cannot use ‘x2’ when initializing stuff)

Great these are feedback that I wanted.