Example of Blockly.procedures

748 views
Skip to first unread message

Bart Butenaers

unread,
Jul 28, 2021, 6:04:41 PM7/28/21
to Blockly
Hi everybody,

I need to generate Javascript code that calls a function:

var result = getResult();

The function body itself needs also be generated:

function getResult() {
      return "Hello World";
}

When N blocks call the same function, then the function body code only needs to be generated once.  When 0 blocks call that function, then the function body code should not be generated.

I think the Blockly.Procedures offers exactly what I want.  So there surely should be somewhere examples available for this, but I could not find one...  Would be nice if somebody could share an example or link that explains how I can use this for my purpose.

Thanks !!!
Bart

Beka Westberg

unread,
Jul 28, 2021, 6:20:45 PM7/28/21
to blo...@googlegroups.com
Hi Bart :D

There are two options, and they depend on one question: Is the getResult() function defined by you, the developer? Or is it defined by the person using Blockly to write code?

If it is defined by you, then you can just define a stringified version of that function and prepend it to your generated code. For example:
```
var prefix = 'function getResult() {\n' +
      '    return "Hello World";\n' +
    '}\n';
var code = Blockly.JavaScript.workspaceToCode(myWorkspace);
code = prefix + code;
eval(code);
```
This makes it so that your function only exists once. It is also basically how the procedure blocks work, except for them the logic exists inside of Blockly, while for you it exists inside your application.

If it is defined by the user, then procedures are exactly what you want =) You can just add the procedure category to your toolbox, and they should work out of the box.

I hope that helps! If you have any further questions please reply!
--Beka



--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/e76f110a-9b8e-461f-9b1f-9264cde5e784n%40googlegroups.com.

Bart Butenaers

unread,
Jul 29, 2021, 1:37:01 AM7/29/21
to Blockly
Hello Beka,
Thanks for joining me again on my trip through Blockly land ;-)

I define the function myself.  But your explanation makes it clear now why I didn't understand how to use the Blockly.procedures.  That was illuminating!!

Sorry but I don't understand how the function will only be generated once, by using your code snippet ...
Suppose I have a block that "might" generate a block if certain conditions are met:

Blockly.JavaScript['block_that_might_generate_a_function'] = function(block) {
     var code = "";

     if (...) {
            // A function need to be declared and called
            code = ....;
     }
     else {
            // No function need to be declared or called
            code = ....;
     }

     return code;
};

Suppose I have 3 of such blocks and the conditions are met, then each block will generate code that contains a function body.  So I end up with 3 identical function bodies in my generated code.

Could you please explain how your code snippet needs to be used inside my code generator snippet to solve my headache?

Thanks!!
Bart

Beka Westberg

unread,
Jul 29, 2021, 10:41:30 AM7/29/21
to blo...@googlegroups.com
> Thanks for joining me again on my trip through Blockly land ;-)
Haha my pleasure! You always ask really great questions :D

> Could you please explain how your code snippet needs to be used inside my code generator snippet to solve my headache?
Yeah definitely! So the thing is you actually *don't* include it in your block-code generator for an individual block. You attach it to the code string generated by the *entire workspace*. That way no matter how many "caller blocks" you have, you only get the one definition.
```
// This is not part of your block-code generator. This deals with generating code for your entire workspace.
var prefix = 'function getResult() {\n' +
      '    return "Hello World";\n' +
    '}\n';
var code = Blockly.JavaScript.workspaceToCode(myWorkspace);
code = prefix + code;
eval(code);

// This doesn't even know about your function definition, it just returns a code string that calls it.
Blockly.JavaScript['my block'] = function(block) {
  return ['getResult()', Blockly.JavaScript.ORDER_NONE];
}
```

This is just a really simple way of getting what you want. It always prepends your function definition, whether you have 0 caller blocks or 1000.

If you want something smarter that only prepends your code if you have 1 or more caller blocks, check out the math_random_int block-code generator. This uses the Blockly.JavaScript.provideFunction_ method, which handles only adding the definition once.

I hope that helps! If you have any further questions please reply!
--Beka
--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Bart Butenaers

unread,
Jul 31, 2021, 6:43:09 PM7/31/21
to Blockly
Hey Beka,

the Blockly.JavaScript.provideFunction_ (used in the math_random_int block) was like hitting the golden buzzer in the Google Got Talent show ;-D
That works perfect: it generates my function only when I call it.  Brilliant!!

Thanks again and have a nice weekend!!!
Bart

Beka Westberg

unread,
Aug 2, 2021, 9:49:30 AM8/2/21
to blo...@googlegroups.com
My pleasure :D I hope you had a nice weekend as well!

--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.

Johnny Oshika

unread,
Apr 28, 2022, 9:12:50 PM4/28/22
to Blockly
It seems that the Blockly.JavaScript.provideFunction_ method that was recommended in this thread became protected properties in the 2021 Q4 release and is no longer available to us (I'm using TypeScript):

Screenshot 2022-04-28 174831.png

The following properties also faced the same fate.:

Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ 
Blockly.JavaScript.BlocklyJS.nameDB_

What is the new and recommended way to generate functions from custom blocks that we only want generated when the block is used in the workspace?

I'm using blockly version 7.20211209.5

Thanks

Johnny Oshika

unread,
Apr 29, 2022, 12:32:50 AM4/29/22
to Blockly
I spoke too soon. It looks like this was fixed in Blockly's March 2022 release. 😀

Johnny Oshika

unread,
May 8, 2022, 12:28:16 PM5/8/22
to Blockly
Just noticed that Blockly.JavaScript.provideFunction_ is documented in the official documentation: https://developers.google.com/blockly/guides/create-custom-blocks/caching-arguments#utility_functions

Really good documentation, BTW

Reply all
Reply to author
Forward
0 new messages