#How do I create a JS DefaultDict?

3 messages · Page 1 of 1 (latest)

torn acorn
#

Hi! My question is going to be a lengthy one, so I'll have to break it into multiple messages, I apologize.

I'm trying to create an Apps Script, and I've been trying to implement a Default Dictionary. So far, I've been able to yoink a couple of things that didn't end up working, the first one was this:

class DefaultDict {
  constructor(defaultInit) {
    return new Proxy({}, {
      get: (target, name) => name in target ?
        target[name] :
        (target[name] = typeof defaultInit === 'function' ?
          new defaultInit().valueOf() :
          defaultInit)
    })
  }
}
#

And while this works well enough for a flat Default Dictionary with say let locationDict = new DefaultDict(Array), or maybe new DefaultDict(Number), it kind of breaks with new DefaultDict(DefaultDict(DefaultDict(Array))).

Specifically, the error I get is TypeError: Class constructor DefaultDict cannot be invoked without 'new'... and I'm not sure what that means... I was hoping that the new keyword that's inside of the class constructor definition would take care of invocations of class constructors...

So I managed to find a workaround to fix it that seemed to make things rosy by turning it into a function instead of a class:

function DefaultDict (defaultInit) {
  const handler = {
    get: (target, name) => name in target ?
      target[name] :
      (target[name] = typeof defaultInit === 'function' ?
        new defaultInit().valueOf() :
        defaultInit)
  }
  return new Proxy({}, handler)
}
#

and I had thought it was working dandy with the new DefaultDict(DefaultDict(DefaultDict(Array))) (because there weren't any errors) until I actually ran it with some data. Without going too nitty gritty, let me see if I can simplify the use case:

   const data = [["Welcome to El Mirage Sign", "El Mirage", "Arizona", "United States"],
                 ["Indian Roller Bird", "Austin", "Texas", "United States"],
                 ["Greenbrier Park Half-Court", "Austin", "Texas", "United States"],
                 ["Pink Dinosaur Playscape", "Austin", "Texas", "United States"]]
  const caption = 0
  const subregion = 1
  const region = 2
  const country = 3
  
  let locationDict = new DefaultDict(DefaultDict(DefaultDict(Array)))
  for (let i = 0; i < data.length; i++)
  {
    const caption = data[i][0]
    const subregion = data[i][1]
    const region = data[i][2]
    const country = data[i][3]
    locationDict[country][region][subregion].push(caption)
  }

  console.log(locationDict)