instagram

The Bootstrap Blog

You can read our other entries on the subject: Getting Started, and Folding & Errors

Building a Block Language: Functions and Applications

For teachers who are evaluating a block language, it's important to ask "what concepts is this language designed around?" Choose right, and a block language can make certain concepts wonderfully easy to teach. Choose wrong, and they can make it downright painful!

Bootstrap puts mathematical concepts first, since all of our curricular modules are designed around mathematically modeling everything from videogames to physics simulations. So what language concepts matter in mathematics? Math has literals (f, x, 3.14, +) and function applications ( f(3), 2+3 ), so we'll start with those.

Goal 1: Low Floor

Our use of a functional language makes this easy: every expression is either a literal or an application. We of course support Number literals (e.g. - 3, 1.3, 4i), but we also extend this to support Strings (e.g. - "hello, world"), Booleans (true or false), or a symbol that stand for values or functions (e.g. - x, y, +, string-length, etc). Expressions are groups of symbols, contained in a set of matching brackets. As an added bonus, our languages don't have assignment statements, which means the color/shape budget we might have spent on those concepts can be spent somewhere else.

Circle of evaluation for 1 + (2 * 3)
Fortunately, Bootstrap already has a visual paradigm that works perfectly for these goals: Circles of Evaluation! The Circles of Evaluation are a perfect visual metaphor for expressions, and serve essentially as sentence diagramming for arithmetic. Teachers can have students draw these circles to demonstrate their understanding of order-of-operations, with nested expressions becoming nested blocks. Even better, they let us lean on established block-and-slot metaphors that are found in languages like Scratch, Blocky, Snap! and Alice.

User Interface: Just as in other block languages, the user can drag these blocks around, or edit literals by double-clicking or hitting enter when a block is selected. For accessibility, we use the lessons learned from WeScheme to make sure literals describe themselves properly using aria-label.

Goal 1a: Distinguish between a Function and its Application

Functions exist separately from their inputs, and the distinction between a function and a function application is critical in algebra. Math teachers often ask students if "f is linear" or "how many roots f has", without ever referring to f being applied to anything. It is critical that students build a mental model that allows functions to exist on their own, rather than as some kind of incomplete expression. This is a common misconception for a lot of students, which every algebra teacher works hard to avoid! Our block language should support this, not undermine it.

This learning goal immediately shows the limitations of all the aforementioned block languages. Languages like Scratch lack any representation for the function itself (see the thumbnail on the right - f does not exist independently of its input). Block languages like this reinforce a common misconception in mathematics. For us at Bootstrap, this tradeoff is not acceptable for our learning goals. Our experience porting Bootstrap to Code.org's block language in 2015 found their blocks made it harder to teach the difference between a function and its application.

Functions are just literals, and can be edited
This design decision has other benefits: if functions are literals, we move and edit them the same way one would move or edit a input. Suppose you have the expression 2+3 in Snap!, and you realize that you wanted multiplication instead. Instead of dragging a new "multiply" block, moving each of the children, and then deleting the old "addition" block, now you can just change the function from + to -. When changing functions is easier, it means more experimentation and exploration for students - definitely in-line with another one of our learning goals!

User Interface: Now that we have function application, we can create Abstract Syntax Trees by combining functions and literals. For example: (2 + 4) - (6 * 4) contains four literals and three functions, all connected to one another. Navigating this tree can be done in pre-order, in-order or post-order walks. We decided to let the source language make that decision, with the user simply navigating to the "next" and "previous" node by hitting the up and down keys. Starting a new function application (circle) is accomplished by hitting an open-bracket ((, {, or [).

For accessibilty, we describe an expression in terms of its function (e.g. - "An addition expression with two arguments."), again using aria-label. The Quorum programming language improves screenreader descriptions by changing the syntax and grammar of the language to make recited code more understandable. We believe that decoupling the written presentation of code from its description is a unique accessibility win, for both sighted and non-sighted users.

Goal 2: High Ceiling

Blocks-as-Functions!
You can't have much of a lower floor than where we started. Our interaction modality is pretty much on-par with Scratch, which has been widely acknowledged as one of the easiest languages for young people to learn. But we also want to make sure that this model works for more complex expressions, such as conditionals, if-statements, and anonymous functions (lambdas). By extending our parser to include these expressions, and creating custom blocks for them, when can leverage our existing UI to have student navigate, and edit these expressions.
And those lambdas? Why, you already know where functions go...

You can read our other entries on the subject: Getting Started, and Folding & Errors