lua-users home
lua-l archive

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



On 10/12/14 03:32 PM, Sean Conner wrote:
It was thus said that the Great Andrew Starks once stated:
On Wed, Dec 10, 2014 at 8:52 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:
2014-12-10 16:44 GMT+02:00 Rena <hyperhacker@gmail.com>:

Interesting. Why is __tostring not a core metamethod? The distinction
seems arbitrary to me.
A core metamethod is a fallback. It is called when Lua does not
know what to do, as a last resort instead of throwing an error.
__tostring, __pairs etc are called _instead_ of what Lua knows
to do.

I don't make that distinction, even when I'm reminded that the authors do.

The reason is that, to me, it's meaningless. It works or it does not
work and remembering where it works and doesn't is not something that
I care to invest the time to memorize. At best, I know that whenever I
define `__ipairs`... sort of worry that it may not work, if my table
is handed to a library that may not honor it. To my way of thinking,
there are fields that are attached to metatables that begin with `__`
and end with the name of the method that they modify. Anything beyond
this, to paraphrase the Bible, is complex.

I don't know if this is important enough to bring up in another
thread, but I also don't like the deprecation of `__ipairs`. Whatever
the redundancy it may suffer, it is clear to the writer or reader of
the code that a sequence of key/value pairs, iterated in a consistent
order, is expected. If `ipairs` and `pairs` exist and we allow for a
way to override `pairs`, then consistency would require a
corresponding way to override ipairs.
   To recap:  in Lua 5.2, ipairs() will attempt to call __ipairs(), which
should return an iterator function, self and an initial value; otherwise,
ipairs() supplies the iterator function, self and an initial value.

   The default iterator function goes from index 1 until self[index] returns
nil.  I suspect that most (if not all) iterator functions returned from
__ipairs() will do the exact same thing, although it doesn't have to be:

	mt =
	{
	  __ipairs = function(t)
	    local function iter(s,k)
	      if k == -1 then
	        return 'one',"ONE"
	      elseif k == 'one' then
	        return 'two',"TWO"
	      elseif k == 'two' then
	        return 'three',"THREE"
	      else
	        return nil
	      end
	    end
	
	    return iter,t,-1
	  end
	}

	x = setmetatable({},mt)

	for index,value in ipairs(x) do
	  print(index,value)
	end

	one	ONE
	two	TWO
	three	THREE

   At this point, you could use __pairs().  Okay, ipairs() could then check
to see if the initial value returned from __ipairs() is '0' (the default
value if __pairs() doesn't exist) but then, why even bother with __ipairs()?
I suppose it *could* check for an integer initial value, but then, is it
then a sequence as Lua even defines it?  Is that an issue? Consistent even?

   I know, there's signalling intent.  But the default iterator from ipairs()
supports __index, and in Lua, a sequence for ipairs() is defined as a
sequence of integer keys from 1 to n with non-nil values.  [1]

I may be misunderstanding this issue and I may be mistaken about 5.3
deprecating it. If I am correct, then it appears to me that the
evolution of Lua is such that  eradicating redundancy is valued over
consistency. "Consistency" can be argued about (see math library
change).
   If that were true, then ipairs() would be removed as you can always do:

	for i = 1 , #t do ... end

   -spc (Viewing this from a userdata perspective ... )

[1]	I would really expect Thiago, Rena and Coroutines [2] to be upset
	over the removal of __ipairs() as (to me) they seem like the type of
	people that love overriding how the language works.

[2]	What ever happened to Coroutines anyway?

local dummy = {}
ipairs = function(t) -- if you really need __ipairs
return (rawget(debug.getmetatable(t) or dummy, "__ipairs") or (function(t) return function(t,k) k = k + 1 local v = rawget(t, k) if v ~= nil then return k, v end return nil end, t, 0 end))(t) -- I guess actual ipairs() has some type checking and stuff, for example this accepts __call-ables too and idk about actual ipairs()
end

--
Disclaimer: these emails are public and can be accessed from <TODO: get a non-DHCP IP and put it here>. If you do not agree with this, DO NOT REPLY.