Vote for Espruino features!

Posted on
of 2
/ 2
  • I've opened an issue on GitHub where you can vote on ES6 features that you'd like me to implement inside Espruino:­ues/1302

    If you're interested, please use the reaction icon just below to each post you're interested in and I'll see what I can do!

  • I miss destructuring and rest + spread in the list. Or are they implemented already and i missed it?

    Thanks for giving the community this much influence it is really appreciated!

  • Just added to the list - they're not in there at the moment :)

  • Great thanks! I am so exited about this.. i am used to ES6 and it allows for so much cleaner and shorter code :)

  • Just for info I am using Typescript (target: es5) along with webpack to transpile and minify code before sending to Espruino, and this gives me most of the features I'm used to. Obviously doesn't work for features that the Typescript folks haven't done es5 polyfills for...

  • ESP-NOW for esp8266 and esp32.
    Touch sensors on esp32.

  • The GitHub link is for more general JavaScript language features.

    ESP32 specific additions are basically not going to happen unless the community is going to do them (they've done a good job so far!). Maybe you could do add the functionality yourself or talk to Espressif and ask them if they would add support to Espruino. I tried to talk to Espressif at embedded world - maybe I talked to the wrong people, but they honestly couldn't care less about Espruino - which obviously doesn't motivate me to spend much time supporting their products :(

  • I tried to talk to Espressif at embedded world - maybe I talked to the wrong people, but they honestly couldn't care less about Espruino

    Shortsighted of them Gordon. They are missing a trick.

  • I tried to talk to Espressif at embedded world - maybe I talked to the wrong people, but they honestly couldn't care less about Espruino

    How did you convice STMicro to support Espruino?

  • How did you convice STMicro to support Espruino?

    I've been talking to ST for a long time - probably 4 years now, and they even originally supported the first batch of Picos with free chips. There are some people there that really like the idea of it, but we started talking when I didn't have a clear 'support package' to offer and we never managed to come to any kind of agreement that would have worked out.

    However having this £150/month option for supporting a board is cheap enough and limited enough in scope that it can be justified pretty easily, and it coincides with them launching a discovery kit for cellular access (­ERY will be filled in with more info as time goes on) - where offering an option to use JavaScript for talking to various IoT services makes a lot of sense.

    Let's just hope they get a lot of good feedback and want to roll it out across more of their discovery/nucleo boards :)

  • These would be nice to have:

    Although I manage just fine without. I think Espruino's ES6 support is actually pretty good :)

  • Actually, Map is something I've missed several times lately when both Object and Array have fallen short. Set would also be useful. Having become used to the two in NodeJS, it's hard to live without them in Espruino :)

    Arguments for adding Map:
    Until Map arrived, JavaScript lacked a "pure" associative array. Instead, Object is often used/misused, leading to complicated code and weird issues, mainly due to its prototype nature and its limitation of only strings as keys.
    With Map, keys can be of any type, they're easily iterated (in insertion order), and it's easy to get a map's size or check if it has a certain key. It performs better, and it just works! After years of trying to make Object behave like an associative array, it's like a breath of fresh air.

    Shouldn't be too hard to implement, should it? :)

  • Shouldn't be too hard to implement, should it? :)

    Here you go :)

    Would it not be possible to write Map and Set as a JavaScript module though? I'm not sure they actually require interpreter support.

  • There should be polyfills for them.. but i guess they are always not optimal memory and/or speed wise

  • @Gordon If considered then I think it would require native support to match the spec behavior

    Proper Map and Set implementation allow the keys be an arbitrary Object for polyfills that requires the lookup be O(n) instead of O(1) as there AFAIK isn't any other way then to approximately this m.get = (key) => m[ Object.keys(m).find(k => m[k] === key) ].

  • Yes - however actually that's what Espruino does internally for maps anyway (an O(n) search) - so if you implemented Map that way it wouldn't be the end of the world. Not great I know but I figured most objects/maps will be <10 items, in which case the overhead of just doing a very fast compare is much lower than that of having something like a red/black tree (especially as built-in object lookups are handled with a binary search).

    If you're wondering it's on the issue tracker as something to look at - obviously it's more of an issue the more RAM you have available :)

  • I guess you are right @Gordon in terms of performance impact. But RAM is still an issue i guess because its very precious :)

    I have a sweet little example for the Map vs. Object point @opichals made before.
    Should be self-explanatory.

    'use strict';
    let sequence = ( => (ok, nok) => {
            map = new Map( => Array.isArray(e) ? e : [e]));
            ok(Array.from(map.keys()).reduce((all, prm) => {
                return all.then(res => prm.then(data => res.set(prm, (map.get(prm) || (() => data))(data))).catch(nok));
            }, Promise.resolve(map)));
    let add = num => num + 1;
    let mul = num => num * 2;
    let addPromise = num => Promise.resolve(num);
    let mulPromise = num => Promise.resolve(num);
    let adding = addPromise(10);
    let multing = mulPromise(20);
    let map = [adding,[multing, mul]];
    new Promise(sequence( => {
        console.log('result', {addResult: result.get(adding), mulResult: result.get(multing)});
    }).catch(console.log.bind(null, 'error'));
  • Should be self-explanatory.

    Honestly, I'm not finding it that easy to see what's going on there :) So you've got promises as map keys?

    Here's a bodged up Map implementation:

    function Map(keyVal) {
      this._keys = [];
      this._values = [];
      if (keyVal) keyVal.forEach(k=>{
      this.size = this._keys.length;
    Map.prototype.has = function(k) {
      return this._keys.indexOf(k)>=0;
    Map.prototype.get = function(k) {
      var i = this._keys.indexOf(k);
      if (i<0) return;
      return this._values[i];
    Map.prototype.set = function(k,v) {
      var i = this._keys.indexOf(k);
      if (i<0) {
        this.size = this._keys.length;
      } else this._values[i] = v;
      return this;
    Map.prototype.delete = function(k) {
      var i = this._keys.indexOf(k);
      if (i<0) return false;
      this.size = this._keys.length;
    Map.prototype.keys = function() { return this._keys; };
    Map.prototype.values = function() { return this._values; };

    It's actually pretty quick because it uses Array.indexOf. It doesn't work for NaN (that could be special-cased) but I think it works for most other stuff.

    I've added it to the ES6 wishlist linked above, but looking at the API I wonder if it makes much sense without Iterator support?

  • sweet little example

    Man I'm struggling to see what's going on here!

  • Well sorry.. its a quick hack. Its a function to run promise chains in sequence with optional mapper functions for the resolves. And the resulting resolve returns the changed map (key: original promise, value: resolve result of that promise) so you can reference results by promises you did feed the function.

    I guess it doesnt help that code with 120 chars per line (pretty common standard) is getting wrapped in posts here.

    --- Little warning ---
    The code has bugs.. it was a first draft of something i needed at work the next day.. so dont use it for production :D

  • Shouldn't be too hard to implement, should it? :)

    Here you go :)

    Now I regret saying that :) It came off wrong, sorry if it sounded like writing features for Espruino is easy! I'm sure it would take many hours to implement this, and I know you're not getting paid by the hour to work on Espruino. Instead I should thank you for making and continuously improving Espruino for free, and for providing such great support!

    I looked around for JS polyfills for Map and Set, and found one that was used by Firefox Nightly and Chrome Dev when the features were under the Enable Experimental JavaScript flag. It's also the smallest that I found (6KB, 2.77KB minified) and claims to have good performance.­lections­lection/es6-collections/master/index.js

    As far as I can tell, it actually does roughly what your bodged up implementation does :)

    I tested it on a Pico (had to move the exported functions to the bottom) and it seems to work fine, except for two issues:

    • Although it shims iterators, Espruino doesn't support iterators or for…of (good point!)
    • The .size property is missing (requires support for getters in Object.defineProperty)­82b3cce32092cccfb99701d

    Despite those issues, I'll give it a try on a project I'm working on later and see how it goes.

  • It came off wrong

    No, not at all - I was only joking :)

    That's great news about the Polyfill.

    for..of and getters/setters are pretty attainable and are definitely on my list - I'm actually surprised at the lack of interest in them on the wishlist - but perhaps for..of was such an obvious one nobody thought to request it.

  • @Gordon, a non-pressing question about line 14 var i = this._keys.indexOf(k); of your Map implementation. I assume it handles the == conforming to the k(ey) type. So behavior is dependent on key nature. I assume any enhancements with, for example, hashing, would become an overkill, since the Maps can anyway not be really big, where it could matter. Furthermore, I like that it is a insert-sequence sorted Map, and so will be an iterator over keys and values (when exposed). A key sorted map would expect all key types - that means - all 'objects' ever to be used as keys would have to 'share' a comparator. For my needs so far, I never had to issue to come up with an id of a String and used the obvious not so 'loved' feature of the Object {} to handle my access (CRU). Since you know the ins and outs of your object property access, how does it compare with this map setup w/ key and value arrays?

    I'm sure it is much more light weight than using the Promise machinery to get to the result... since in the code I see no asynchronous needs...

  • How does {} compare to the map code above?

    The map code will be slower because it's executing more JS, but both will take O(n) time and delegate the search itself to the interpreter so the map implementation isn't going to be that bad. Using indexOf is definitely slower than a map access because Espruino's object access can check the keys quickly at first rather than doing a full equality test, but it'd be interesting to do some benchmarks.

    I'd definitely say use {} if you're at all able to though - it'll use less memory, is faster, and will probably get a lot better in future versions of Espruino too.

  • No, not at all - I was only joking :)

    Even still, I felt like an ungrateful kid begging for icecream after having been served a delicious cake :)

    I actually have checked whether for…of was supported, but never thought of suggesting it here! Maybe it's been overlooked because iterators and loops are not as attractive as arrow keys and async/await..

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Vote for Espruino features!

Posted by Avatar for Gordon @Gordon