lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It was thus said that the Great Pierre Chapuis once stated:
> On Wed, Mar 14, 2018, at 15:55, Roberto Ierusalimschy wrote:
> 
> > Every year or so the list has its recurrent discussion about the length
> > operator and holes in sequences. Quite often, this discussion leads some
> > people to propose that Lua needs an array type, different from tables.
> 
> In practice, this is not the reason why people (at least me, but not only)
> wish Lua had an array type.
> 
> The main reason is that Lua is a dynamic language where you can
> inspect the type of values (with type() mostly), but there is no
> standard way to know if a table is supposed to be a sequence
> or not when you get it. But in the outside world, things are not
> tables, they tend to be sequences or map. This causes issues
> when we try to interact with it using Lua.

  I had the same issue when writing my CBOR interface [1].  By default, an
empty table becomes an empty map.  I can get around this a few ways:

	--[[ explicitely call on empty sequence ]]

	a = {}
	x = cbor.TYPE.ARRAY(a)

	--[[ use metatable on sequences ]]

	a = setmetatable( 
		{}, 
		{ 
		  __tocbor = function(...)
		    return cbor.TYPE.ARRAY(...)
		 end
		}
	)

	x = cbor.encode(a)

	--[[ change default behavior of mapping tables ]]

	cbor.__ENCODE_MAP.table = function(value,...)
	  if next(value) == nil then
	    return cbor.TYPE.ARRAY(value,...)
	  elseif #value > 0 then
	    return cbor.TYPE.ARRAY(value,...)
	  else
	    return cbor.TYPE.MAP(value,...)
	  end
	end

	a = {}
	x = cbor.encode(a)

  Each has their tradeoffs.

  An issue with having a separate array type is how do you know when one is
created?  Sure, this:

	{ 1 , 2 , 3 , 4 , 5 }

is an array.  This:

	{ [100] = 1 , [200] = 2 , [300] = 3 , [400] = 4 , [500] = 5 }

results in a map (or associative array).  It's obviously NOT an array.  But
then this:

	{ [1] = 1 , [2] = 2 , [3] = 3 , [4] = 4 , [5] = 5 }

Should that be an array?  Or a map?  And there are times when I've done
this:

	{
	  alpha = 1 , 
	  beta = 2 , 
	  gamma = 3 , 
	  delta = 4 ,
	  [1] = alpha,
	  [2] = beta,
	  [3] = gamma ,
	  [4] = delta
	}

(usually via programming, but not always).  It is useful, and I used such a
construction in my CBOR encoder/decoder:

	TAG = setmetatable(
	  {
	    --[[ encode a tag of __datetime ]]

	    _datetime = function(value)
	      return cbor_c.encode(0xC0,0) .. TYPE.TEXT(value)
	    end,

	    --[[ decode a tag of 0 ]]
	
	    [0] = function(packet,pos,conv,ref)
	      local value,npos,ctype = decode(packet,pos,conv,ref)
	      if ctype == 'TEXT' then
	        return value,npos,'_datetime'
	      else
	        throw(pos,"_datetime: wanted TEXT, got %s",ctype)
	      end
	    end,
	...

so I *like* the current state of affairs.  

  -spc

[1]	https://github.com/spc476/CBOR