10

The following example is supposed to make a table, that can convert between a number and a string and back again, but fails to run.

Is it because I'm using a numeric key in a dictionary type way? Or is it because lua starts table indices from 1?

Is there a better way to accomplish this?

dyeColor = {
    0="black"    ,  black     = 0,
    1="red"      ,  red       = 1, 
    2="green"    ,  green     = 2,
    3="brown"    ,  brown     = 3,
    4="blue"     ,  blue      = 4,
    5="purple"   ,  purple    = 5,
    6="cyan"     ,  cyan      = 6,
    7="lightGray",  lightGray = 7,
    8="gray"     ,  gray      = 8,
    9="pink"     ,  pink      = 9,
    10="lime"     ,  lime      =10,
    11="yellow"   ,  yellow    =11,
    12="lightBlue",  lightBlue =12,
    13="magenta"  ,  magenta   =13,
    14="orange"   ,  orange    =14,
    15="white"    ,  white     =15}

using this online interpreter (http://repl.it/languages/Lua) it gives the error

[string "stdin"]:2: '}' expected (to close '{' at line 1) near '='attempt to call a nil value

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Ryan Leach
  • 4,262
  • 5
  • 34
  • 71

3 Answers3

22

You need to put the numeric indices in brackets:

dyeColor = {
    [0]="black"     ,  black     = 0,
    [1]="red"       ,  red       = 1, 
    [2]="green"     ,  green     = 2,
    [3]="brown"     ,  brown     = 3,
    [4]="blue"      ,  blue      = 4,
    [5]="purple"    ,  purple    = 5,
    [6]="cyan"      ,  cyan      = 6,
    [7]="lightGray" ,  lightGray = 7,
    [8]="gray"      ,  gray      = 8,
    [9]="pink"      ,  pink      = 9,
    [10]="lime"     ,  lime      =10,
    [11]="yellow"   ,  yellow    =11,
    [12]="lightBlue",  lightBlue =12,
    [13]="magenta"  ,  magenta   =13,
    [14]="orange"   ,  orange    =14,
    [15]="white"    ,  white     =15}

You can save yourself some typing with:

dyeColor = {
    [0]="black"     ,
    [1]="red"       ,
    [2]="green"     ,
    [3]="brown"     ,
    [4]="blue"      ,
    [5]="purple"    ,
    [6]="cyan"      ,
    [7]="lightGray" ,
    [8]="gray"      ,
    [9]="pink"      ,
    [10]="lime"     ,
    [11]="yellow"   ,
    [12]="lightBlue",
    [13]="magenta"  ,
    [14]="orange"   ,
    [15]="white"    }

for i = 0, #dyeColor do dyeColor[dyeColor[i]] = i end

Lua permits Names as fieldspecs in the form Name = exp but not numbers. Numbers must be in brackets. The same is true of field references. You may say

dyeColor.black

but not

dyeColor.0 -- you may say dyeColor[0] of course
Doug Currie
  • 40,708
  • 1
  • 95
  • 119
  • I'll accept your answer, if you can offer an explanation as to how your answer is different to the code given in the question (from the interpreters point of view) – Ryan Leach Apr 29 '13 at 21:27
  • You can even save some more typing by not defining index except for `[0]`. – hjpotter92 Apr 29 '13 at 22:49
  • 1
    Yes; in this case I view the numbers as documentation of the fact that the mapping is significant, i.e., this is not just an array, so it's nice to see the association. This is a matter of taste, of course. – Doug Currie Apr 30 '13 at 16:53
0

#dyeColor is undefined if it contain [0] so you can

dyeColor = {} do
  local tmp= {
    "black"     ,
    "red"       ,
    "green"     ,
    "brown"     ,
    "blue"      ,
    "purple"    ,
    "cyan"      ,
    "lightGray" ,
    "gray"      ,
    "pink"      ,
    "lime"      ,
    "yellow"    ,
    "lightBlue" ,
    "magenta"   ,
    "orange"    ,
    "white"    
  }
  for i, v in ipairs(tmp) do
    local j = i - 1
    dyeColor[v], dyeColor[j] = j, v
  end
end
moteus
  • 2,187
  • 1
  • 13
  • 16
  • Is length undefined for tables with an item [0]? My reading of both the 5.1 and 5.2 definition leads me to conclude that it is defined, e.g., 5.2: the set of its positive numeric keys is equal to {1..n} for some integer n. I guess it depends on whether you consider 0 positive in this context. In 5.1, it is certainly defined: any integer index n such that t[n] is not nil and t[n+1] is nil -- there is only one such value even when [0] is used. – Doug Currie Apr 30 '13 at 17:01
  • I'm guessing in this solution that the mapping starts at 1? if so, this answer is useless, as the 0 was needed to represent data that I don't have control over. – Ryan Leach May 01 '13 at 05:34
  • Oh. Really. #dyeColor is defined if it contain [0]. – moteus May 07 '13 at 11:44
0

Improving Doug Curie's solution:

local dyeColor = {
    [0] = "black", -- You must set 0 explicitly
    "red"        , -- Unnamed items get their numeric index 
    "green"      , -- automatically, starting at 1.
    "brown"      ,
    "blue"       ,
    "purple"     ,
    "cyan"       ,
    "lightGray"  ,
    "gray"       ,
    "pink"       ,
    "lime"       ,
    "yellow"     ,
    "lightBlue"  ,
    "magenta"    ,
    "orange"     ,
    "white"
}
for i = 0, #dyeColor do dyeColor[dyeColor[i]] = i end

Even though the length of a table with [0] is undefined in Lua 5.2, it actually returns the index of the last element. The code above also works in Lua 5.1 and LuaJIT.

Ray Osgod
  • 56
  • 3