Procedure predefined block: Input arguments not updating value

255 views
Skip to first unread message

pfei...@unbosque.edu.co

unread,
Mar 8, 2019, 1:01:06 AM3/8/19
to Blockly
Hi everyone,

For some reason, when using predefined procedures blocks, the input arguments are not getting the value selected on the Canvas, but the "name" of the arguments instead.

The XML code I used for the predefined procedure block is:

                                 <category name="Functions on Items">
<block editable="false" type="procedures_defnoreturn">
<field name="NAME">insertElementToItem</field>
<mutation>
  <arg name="item" varid="currentItem"></arg>
      <arg name="element" varid="newElement"></arg>
    </mutation>
    <comment pinned="false" h="80" w="160">Describe this function...</comment>
</block>
</category>

The code used to get both input arguments is:
                  var value_item = Blockly.JavaScript.valueToCode(block, 'item', Blockly.JavaScript.ORDER_ATOMIC);
  var value_element = Blockly.JavaScript.valueToCode(block, 'element', Blockly.JavaScript.ORDER_ATOMIC);

So, what is happening is that in both, value_item and value_element, when I alert the received input it is "item" for value_item and "element" for value_element. 
I simply don't know why and how to fix this. Could you please help me?

Thank you and I will be waiting for your response.

Best regards,

Coda Highland

unread,
Mar 8, 2019, 9:37:57 AM3/8/19
to blo...@googlegroups.com
There's nothing to fix because this is working as intended.

Remember that the code generator functions are, in effect, a compiler. The valueToCode function does not return the current value of the variable, because there is no current value, because the program isn't running -- it's compiling. It returns code for an expression in the target language (in this case, JavaScript) that -- when evaluated -- will itself return the current value of the variable.

Consider the code that would be generated for the insertElementToItem function. It would look something like this:

function insertElementToItem(item, element) {
  /* ... */
}

If valueToCode were to return values instead of the names "item" and "element", that code wouldn't be syntactically valid JavaScript. Even if it were valid, the values would end up being hard-coded constants instead of picking up the value passed to the function at run time.

/s/ Adam

--
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.
For more options, visit https://groups.google.com/d/optout.

pfei...@unbosque.edu.co

unread,
Mar 8, 2019, 10:23:54 AM3/8/19
to Blockly
Hi, thank you for your answer.

I really don't get it. I just included in the statement a print block, and the input argument is printed as I am expecting. However, when passing that input argument to my block, it appears as "element".
Why the value appears when I use the "print" block, but not in the other one?

Thank you,

Coda Highland

unread,
Mar 8, 2019, 2:15:10 PM3/8/19
to blo...@googlegroups.com
Again, it's a run-time versus compile-time thing. Try looking at the code generated for the print block. It'll contain the name, too, not the value. But when you execute the code, it evaluates the variable.

That is to say: It's print(item), not print("item").

/s/ Adam

pfei...@unbosque.edu.co

unread,
Mar 8, 2019, 4:33:38 PM3/8/19
to Blockly
Hi Adam,

Thank you for your response.

I get what you mean, but my problem is at execution. How do I get the value of the element that is passed to the procedure?

Coda Highland

unread,
Mar 8, 2019, 4:58:24 PM3/8/19
to blo...@googlegroups.com
I'm afraid I must be confused about what your problem is. The question doesn't make sense to me. You shouldn't have to get the value, because it's passed to the procedure. Blockly isn't involved in the execution of the program once you've generated the code, so it's all contained within the Python code.

How are you using Blockly? How are you generating and executing the Python code?

/s/ Adam

pfei...@unbosque.edu.co

unread,
Mar 8, 2019, 5:59:32 PM3/8/19
to Blockly
Hi Adam,

What is happening in my code is that, whenever I call the function and try to work with the value I intend to input, I keep getting as an input the variable name and not the value that I am passing when calling the procedure. This is why I was telling you that it was weird, because when using the print block, the value is printed, but when trying to get it inside my block, what appears is the variable name.

That's why I am asking how to get the variable's value.

Thank you again. 

Coda Highland

unread,
Mar 8, 2019, 6:18:12 PM3/8/19
to blo...@googlegroups.com
Can you show some of your code? I'm not having a lot of luck figuring out what you're actually doing based on the description.

/s/ Adam

pfei...@unbosque.edu.co

unread,
Mar 9, 2019, 11:41:51 AM3/9/19
to Blockly
Hi Adam, sure!

The procedure block I defined is the following:
<variables>
     <variable type="" id="newElement">element</variable>
</variables>

<block editable="false" type="procedures_defnoreturn">
     <field name="NAME">INSERT</field>
     <mutation>
        <arg name="element" varid="newElement"></arg>
     </mutation>
     <comment pinned="false" h="80" w="160">This procedure inserts an element to an item</comment>
</block>

I am intending to use this procedure to call the following block:

               Blockly.Blocks['new_item'] = {
  init: function() {
    this.appendValueInput("pElement")
        .setCheck("Number")
        .appendField("Create Item");
    this.setInputsInline(false);
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(345);
    this.setTooltip('');
  }
};

Blockly.JavaScript['new_item'] = function(block) {
  var value_element = Blockly.JavaScript.valueToCode(block, 'pElement', Blockly.JavaScript.ORDER_ATOMIC);
                  element = parseInt(value_element, 10);
  // TODO: Assemble JavaScript into code variable.
  var code = 'Store.lastItem = new Item('+element+');\n'+ 
  return code;
};

When I receive value_element, the value I am receiving is "element", despite passing a value with Blockly Canvas.  What I want is to be able to retrieve the value passed as argument, and use it in my code.

Thank you again,

Coda Highland

unread,
Mar 9, 2019, 12:58:07 PM3/9/19
to blo...@googlegroups.com
A Blockly "value" isn't a value in the same sense as a Python value. It's better described as an expression to be used as a parameter to a function. As such, I'll be calling it an expression from here on to try to avoid confusion.

The expression you passed in the Blockly canvas is a variable. That variable is named "element", and it represents a Python variable. The Python value of that expression will change at runtime; it doesn't have a Python value at compile-time. If you were to generate all of the code for the Blockly script, the "element" Python variable will be populated at runtime before the Item() constructor is called, and it'll all just work. Unless there's something that I really understand, the only problem is that you as the developer are misunderstanding how this all is meant to work together. I bet if you try it, it'll work.

If you want a compile-time constant instead of a runtime Python variable, don't use a Blockly variable. Make a separate custom block whose code generator returns the code you care about.

/s/ Adam

pfei...@unbosque.edu.co

unread,
Mar 9, 2019, 2:15:29 PM3/9/19
to Blockly
Hi Adam,

I get what you are telling me, but it is confusing why when I "get element" and pass it to a print block, it shows the value that I need to operate with; and right after, when passing it to my defined block, it indicates to receive "element".

Blockly.png



How can I access the value of the "element" variable, such as the print block does, without receiving the variable's name?

Thank you again for your help.

Beka Westberg

unread,
Mar 9, 2019, 5:33:05 PM3/9/19
to Blockly
Hello,

Have you tried looking at how the print block works? It makes me think that if you skip your parseInt step it might work better for you. Looking at the source can be a great tool for sorting out all kinds of issues.

Another good debugging tool to keep in mind (if you haven't tried it already :P) is to log your generated code to the console before running it. This can help you see how the generators are working (or not).

I hope that helps! Please reply if you have any further questions.
Beka

pfei...@unbosque.edu.co

unread,
Mar 9, 2019, 6:39:08 PM3/9/19
to Blockly
Beka and Adam, thank you so much!

I figured it out!
It happened that I had not defined the type of input in one of my blocks, and it was the reason why it was not getting the value. I fixed it changing the setCheck("Null") to setCheck("Number")

Thank you again for your help, and sorry for bothering you.

Have a great rest of the weekend!

Coda Highland

unread,
Mar 9, 2019, 7:34:01 PM3/9/19
to blo...@googlegroups.com
Happy to help. I'm a little surprised by that result; I didn't realize the checks would have an impact on code generation -- I thought it only affected what you were allowed to connect in the UI.

/s/ Adam
Reply all
Reply to author
Forward
0 new messages