Adding HashMaps/Dictionaries/Associative Arrays to Blockly

1,298 views
Skip to first unread message

toe...@extremenetworks.com

unread,
Aug 26, 2015, 4:22:42 PM8/26/15
to Blockly
All of the languages supported by Blockly support the concept of a HashMap (Python Dictionaries, Dart Maps, Javascript associative arrays, PHP Arrays) and it is a very standard programming paradigm.  Is there a reason that they aren't a standard set of blocks in Blockly?

We have been looking at it and believe that it would need the following blocks:
  
  1. Support for Maps in Blockly.Blocks['controls_forEach']
  2. Get the number of entries in a Map similar to Blockly.Blocks['lists_length']
  3. Test for empty on a Map similar to Blockly.Blocks['lists_isEmpty']
  4. Create a single Map entry.  This has two inline input fields, the first being a string corresponding to the element and the second being an arbitrary type to put at that element.  This would be used for initializing multiple entries in a map.
  5. Create an empty Map similar to Blockly.Blocks['lists_create_empty']
  6. Create a Map by combining other Maps similar to Blockly.Blocks['lists_create_with']
  7. Delete all or single element by name from a Map (single block with a dropdown to specify All or Element where Element enables an optional second input field that allows for a string to indicate the element to delete)
  8. Set an element in a map to a value.  This would be similar to Blockly.Blocks['lists_setIndex'] except there would be no drop down and the first field would be a string indicating the element to set
  9. Get an element in a map. This would be similar to Blockly.Blocks['lists_getIndex'] except there would be no second drop down and the second field would be a string indicating the element to get/remove.  Note that this could be used for item #7 above but you would still need the ability to empty the entire map.
  10. Get all of the keys in a Map.  This would return an List of strings of all the keys in the map.

Does this make sense?  Have I missed anything? Has anyone else considered or even started implementing this?  I've tossed in a couple screen shots of what it might look like. 




Screen Shot 2015-08-26 at 4.20.25 PM.png
Screen Shot 2015-08-26 at 4.20.11 PM.png

Austin Bart

unread,
Aug 27, 2015, 2:01:00 PM8/27/15
to Blockly
For reference, our fork of Blockly does have support for creating and accessing dictionaries (python only): https://github.com/RealTimeWeb/blockly/

We went with a model of defining dictionaries where it's all one block, rather than separate blocks for the individual key-value pairs. The idea was, "what python code is generated if you have a `key-value block` outside of a `create dictionary` block? By making it one block, we bypassed that question.

~Cory

toe...@extremenetworks.com

unread,
Aug 28, 2015, 8:14:31 AM8/28/15
to Blockly
Good point.  What we have done is make the code generator for the maps_create_with look to see if any of the elements is a maps_create and optimize out that case.  It makes for some pretty clean code.  I've attached a screen shot of the blocks which generates the Java code below.  Comments/suggestions are welcome.

public void testmaps(){
    HashMap myMap = new HashMap();
    myMap.put("key01", -1);
    myMap.put("key02",
-2);
    HashMap hashMap = new HashMap();
    hashMap.put("key1",
1);
    hashMap.put(
"key2", 2);
    hashMap.put(
"key3", 3);
    hashMap.put(
"key4", 4);
    hashMap.put(
"key5", 5);
    hashMap.put(
"key6", 6);
    hashMap.put(
"key7", 7);
    myMap2 = hashMap;
    for (Iterator it = myMap2.iterator(); it.hasNext();) {
      key = it.next();
        myMap.put(key,
1);
    } // end for
    if (myMap.size() ==
0) {
        var = myMap.get(
"key1");
        myMap.remove(
"key4");
    }
    for (Iterator it2 = myMap2.iterator(); it2.hasNext();) {
      key = it2.next();
        System.out.println(myMap.get(key).toString());
    } // end for
}
Screen Shot 2015-08-28 at 8.07.35 AM.png

Carlos Pereira

unread,
Aug 31, 2015, 4:26:24 PM8/31/15
to Blockly
If the block "map key _block_ as _block_" cannot be attached to any other block other than the "create map with",  and it makes no sense to attach a different block type to "create map with" then why not merge it all into a single block? It would simplify its use, as that way there is no need to explain that the "map key _block_ as _block_" is supposed to be inserted into the other block.

The "get" block seems to have a drop down to select a different option, one would assume a "set" value is in the dropdown, but unless you are mutating the block I am not quite sure that would make sense.

On a personal note, I am not quite I like the use of the word "as" in some of these blocks. It is not very clear that it means "to set a value", and it could be interpreted as a rename of a key name.

Austin Bart

unread,
Aug 31, 2015, 5:44:48 PM8/31/15
to Blockly
One thing I will say that's a disadvantage of making it one block, from my experience: things can get a bit lengthy (or rather, tall).

When only string literals are used as keys, the create dict block is nice and concise:

However, when we a generic block slot for the keys, things looked a lot more complicated. You can't have two block slots on one line in blockly. So you ended up with two lines for every key/value, and I had ugly "key" and "value" labels on them. Currently, our use cases don't demand generic block slots, so I haven't had to think about this. As we move towards a more full version of Python, we may have to go back to that model, unfortunately. Wish I could embed blocks inside of blocks!

toe...@extremenetworks.com

unread,
Aug 31, 2015, 9:10:09 PM8/31/15
to Blockly
Actually Map block as Block is a Map in it's own right - i.e. a Map with a single mapping which does get used on occasion.  The paradigm here was to match what was done with Lists.

Good point on the Get vs Set on that block.  However the same argument would have to apply to Lists and the intention was for Maps to completely mirror the paradigm already set with Lists.  The same is true with the use of 'as" which is also used on Lists.  I don't have a problem with changing, the goal was to be as close as possible to the List implementation.  I would be interested in understanding why Lists evolved to the way it is to ensure that the choices on Maps makes sense.


On Monday, August 31, 2015 at 4:26:24 PM UTC-4, Carlos Pereira wrote:

Jean-François Beauchamp

unread,
Jun 14, 2016, 3:10:57 PM6/14/16
to Blockly
In the mean time, it is always possible to use the block factory (https://blockly-demo.appspot.com/static/demos/blockfactory/index.html) to create 3 blocks that could be used to create JS objects:

 - On block that would return an empty object: {}
 - One block to set the value of a property on an object;
 - And one block to retrieve the value of an object property;

Reply all
Reply to author
Forward
0 new messages