Blocks
When a script grows, you’ll find yourself writing the same few lines more than once. A block gives those lines a name so you can use them again.
Your first block
Section titled “Your first block”block sayHello printline "Hello from a block"end
sayHellosayHelloHello from a blockHello from a blockblock sayHello() { printline("Hello from a block")}
sayHello()sayHello()Hello from a blockHello from a blockblock name starts the block and end finishes it. Writing the name calls it. You can also write sayHello() with brackets. They mean the same.
Inputs
Section titled “Inputs”List the inputs after the block’s name. They’re called parameters:
block greet name printline "Hello, {{name}}"end
greet "Ada"greet("Bo")Hello, AdaHello, Boblock greet(name) { printline("Hello, {{name}}")}
greet("Ada")greet("Bo")Hello, AdaHello, BoUse brackets and commas when there’s more than one parameter:
block describe name age printline "{{name}} is {{age}}"end
describe("Ada", 36)Ada is 36block describe(name, age) { printline("{{name}} is {{age}}")}
describe("Ada", 36)Ada is 36Giving a value back
Section titled “Giving a value back”return ends the block and hands a value back to whoever called it:
block area width height return width * heightend
set a to area(3, 4)printline "The area is {{a}}"The area is 12block area(width, height) { return width * height}
a = area(3, 4)printline("The area is {{a}}")The area is 12A block can return from several places. This one sorts a number into a word:
block describe n if n is less than 0 return "negative" end if n is 0 return "zero" end return "positive"end
printline describe(-2)printline describe(0)printline describe(9)negativezeropositiveblock describe(n) { if (n < 0) { return "negative" } if (n == 0) { return "zero" } return "positive"}
printline(describe(-2))printline(describe(0))printline(describe(9))negativezeropositiveA block that never reaches a return gives back null.
You can call a block with or without brackets:
printline describe(9)andprintline describe 9both print the answer. A bracket-less call takes everything to the end of the line, so use brackets when something follows the call:printline describe(9) ~ "!".
Blocks can call each other, and themselves:
block factorial n if n is less than or equal to 1 return 1 end return n * factorial(n - 1)end
printline factorial(5)120block factorial(n) { if (n <= 1) { return 1 } return n * factorial(n - 1)}
printline(factorial(5))120Blocks and the collection methods
Section titled “Blocks and the collection methods”Remember the blocks you copied in the last chapter? They were the same thing, written inline with no name. You can also pass a named block to map:
block cube n return n * n * nend
printline mash.collect([1, 2, 3]).map(cube).join(", ")1, 8, 27block cube(n) { return n * n * n}
printline(mash.collect([1, 2, 3]).map(cube).join(", "))1, 8, 27What a block can see
Section titled “What a block can see”A block can read and change the variables of the script around it. Its own parameters are private to it:
set name to "outer"
block hi name printline "inside: {{name}}"end
hi("param")printline "outside: {{name}}"inside: paramoutside: outername = "outer"
block hi(name) { printline("inside: {{name}}")}
hi("param")printline("outside: {{name}}")inside: paramoutside: outerBut a plain set inside a block changes the script’s variable, and a variable made inside a block is still there afterwards:
set total to 0
block bump set total to 100 set leftover to 5end
bumpprintline totalprintline leftover1005total = 0
block bump() { total = 100 leftover = 5}
bump()printline(total)printline(leftover)1005To keep a variable inside the block, start the line with here:
set x to 1
block tryIt here x = 50 printline "inside: {{x}}"end
tryItprintline "outside: {{x}}"inside: 50outside: 1x = 1
block tryIt() { here x = 50 printline("inside: {{x}}")}
tryIt()printline("outside: {{x}}")inside: 50outside: 1Use here for scratch variables in a block that others might call, so you don’t overwrite something in the script by accident.
Name your blocks differently from your variables
Section titled “Name your blocks differently from your variables”Don’t give a block and a variable the same name. MaSH won’t stop you, but one will hide the other. Pick clear names: total for a number, calculateTotal for the block.
Try it
Section titled “Try it”Write a block called clean that takes some text and returns it trimmed and in lower case. Hint: mash.str(text).trim().lower().toString(). Call it on " Invoice 2041 ".
Next, you’ll make your scripts cope when something goes wrong.