Is it necessary to kill ipairs()?

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Is it necessary to kill ipairs()?

Duck-2
Please help a nonexpert here...

Without ipairs(), how do I code this convenient (and clear) idiom:

--

for _,v in ipairs{'lumpi','ist','mein',hund'} do
   print(v)
end

--

lumpi
ist
mein
hund

--

Visitors to Lua from other languages reasonably expect to write code like this:

--

for v in {45,56,67,78} do
  --use the next v in the table
end

--

They can't, of course, but the code at the top provides a literate and usable alternative.

Am I right that the idiom above will become:

--

local kinderbuch = {'lumpi','ist','mein',hund'}
for i =1,#kinderbuch do
  print(kinferbuch[i])
end

--

If this is the intended new idiom, I contend that it doesn't look like literate code. (Is it just me, or does the # operator make Lua code look ugly? A syntactic device chosen because it was lexically convenient, rather than linguistically suitable?)

Is there a cleaner way to rewrite my code in 5.2?





 
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

M Joonas Pihlaja

On Sat, 22 May 2010, Duck wrote:

> Please help a nonexpert here...
>
> Without ipairs(), how do I code this convenient (and clear) idiom:
>
> --
>
> for _,v in ipairs{'lumpi','ist','mein',hund'} do
>    print(v)
> end

Using pairs().

for _,v in pairs{'lumpi','ist','mein',hund'} do
   print(v)
end
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Klaus Ripke
On Sat, May 22, 2010 at 03:42:23PM +0300, M Joonas Pihlaja wrote:

> > Without ipairs(), how do I code this convenient (and clear) idiom:
> >
> > --
> >
> > for _,v in ipairs{'lumpi','ist','mein',hund'} do
> >    print(v)
> > end
>
> Using pairs().
>
> for _,v in pairs{'lumpi','ist','mein',hund'} do
>    print(v)
> end

this might as well print Yoda-ish "mein hund lumpi ist".
("my dog lumpi is")
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Ben Kelly
In reply to this post by M Joonas Pihlaja
M Joonas Pihlaja wrote:
> Using pairs().
>
> for _,v in pairs{'lumpi','ist','mein',hund'} do
>    print(v)
> end

Which doesn't guarantee ordering. The current implementation might, but
that's not to be relied on.

I guess you can always roll your own if you need it, but the same is
true of pairs().

        Ben
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Daurnimator
In reply to this post by Klaus Ripke
On 22 May 2010 22:56, Klaus Ripke <[hidden email]> wrote:

> On Sat, May 22, 2010 at 03:42:23PM +0300, M Joonas Pihlaja wrote:
>> > Without ipairs(), how do I code this convenient (and clear) idiom:
>> >
>> > --
>> >
>> > for _,v in ipairs{'lumpi','ist','mein',hund'} do
>> >    print(v)
>> > end
>>
>> Using pairs().
>>
>> for _,v in pairs{'lumpi','ist','mein',hund'} do
>>    print(v)
>> end
>
> this might as well print Yoda-ish "mein hund lumpi ist".
> ("my dog lumpi is")
>

or in the rare situations you do actually need the ipairs function:
provide/write it.
otherwise how often are you providing literals in your fors?
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

steve donovan
On Sat, May 22, 2010 at 3:50 PM, Quae Quack <[hidden email]> wrote:
> or in the rare situations you do actually need the ipairs function:
> provide/write it.

Ah, but there are thousands of lines of Lua code using ipairs; why break them?

What will happen is a compat52 library, which will re-introduce all
the things we liked in 5.1 ;)

> otherwise how often are you providing literals in your fors?

It's not a common use-case.  I tend to define little iterators called
'iter' or 'list' which just iterate over the values (in order ;))

steve d.

PS I have mixed feelings on this one. On the one hand, if I was
introducing a person to the language, then having both pairs and
ipairs to explain would be tricky - whereas everyone gets numeric for.
  On the other hand, 'active' deprecation leaves little patches of Lua
code out there that tend to break nastily - like 'for k,v in t do'
which I was very fond of at the time.
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Joshua Jensen
  ----- Original Message -----
From: steve donovan
Date: 5/22/2010 7:57 AM
> On Sat, May 22, 2010 at 3:50 PM, Quae Quack<[hidden email]>  wrote:
>> or in the rare situations you do actually need the ipairs function:
>> provide/write it.
> Ah, but there are thousands of lines of Lua code using ipairs; why break them?
I concur.

I'm well aware of the performance issue with ipairs, as I find myself
often rewrite nice looking ipairs() code into "for index = 1, #t do
local value = t[index]".  I've been meaning to get into the Lua VM and
write a couple custom opcodes to allow ipairs to work at full speed.

otherwise how often are you providing literals in your fors?

PS I have mixed feelings on this one. On the one hand, if I was
> otherwise how often are you providing literals in your fors?
>
> PS I have mixed feelings on this one. On the one hand, if I was
> introducing a person to the language, then having both pairs and
> ipairs to explain would be tricky - whereas everyone gets numeric for.
>    On the other hand, 'active' deprecation leaves little patches of Lua
> code out there that tend to break nastily - like 'for k,v in t do'
> which I was very fond of at the time.
I am still fond of 'for k,v in t do'.  I was very sad to see it go.  It
was simple.  Lua is supposed to be simple, but ipairs/pairs complicated it.

Josh
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Jonathan Castello-2
On Sat, May 22, 2010 at 11:33 AM, Joshua Jensen
<[hidden email]> wrote:
> I am still fond of 'for k,v in t do'.  I was very sad to see it go.  It was
> simple.  Lua is supposed to be simple, but ipairs/pairs complicated it.
>
> Josh
>

Could we perhaps return to "for k,v in t do", and have the generic-for
use the __pairs metamethod of its target as the iterator factory? If
no __pairs exists, default to next(). So this:

for k,v in t do
  print(k, v)
end

would normally act like you used pairs(). But if you set a metatable:

setmetatable(t, {
  __pairs = function(t)
    return function(t, i)
      i = i + 1
      local v = t[i]
      if v then
        return i, v
      end
    end, t, 0
  end,
})

then it iterates over the numeric indices in order. Further, you could
easily define a "false ipairs()" that returns a table with the __pairs
metamethod set:

function ipairs(t)
  local copy = {}
  for k,v in t do
    copy[k] = v
  end
  return setmetatable(copy, {
    __pairs = the_iter, -- same as above
  })
end

~Jonathan
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Stuart P. Bentley
I like this. In fact, I'd say that replacing the __pairs and __ipairs  
metamethods with an __iter metamethod (that is used by the generic "for"  
when encountering non-functions, with the default case of next()) would be  
"cleaner" (as you're now not mixing up standard library functions like  
pairs with language features like metatables).

On Sat, 22 May 2010 11:48:11 -0700, Jonathan Castello <[hidden email]>  
wrote:

> On Sat, May 22, 2010 at 11:33 AM, Joshua Jensen
> <[hidden email]> wrote:
>> I am still fond of 'for k,v in t do'.  I was very sad to see it go.  It  
>> was
>> simple.  Lua is supposed to be simple, but ipairs/pairs complicated it.
>>
>> Josh
>>
>
> Could we perhaps return to "for k,v in t do", and have the generic-for
> use the __pairs metamethod of its target as the iterator factory? If
> no __pairs exists, default to next(). So this:
>
> for k,v in t do
>   print(k, v)
> end
>
> would normally act like you used pairs(). But if you set a metatable:
>
> setmetatable(t, {
>   __pairs = function(t)
>     return function(t, i)
>       i = i + 1
>       local v = t[i]
>       if v then
>         return i, v
>       end
>     end, t, 0
>   end,
> })
>
> then it iterates over the numeric indices in order. Further, you could
> easily define a "false ipairs()" that returns a table with the __pairs
> metamethod set:
>
> function ipairs(t)
>   local copy = {}
>   for k,v in t do
>     copy[k] = v
>   end
>   return setmetatable(copy, {
>     __pairs = the_iter, -- same as above
>   })
> end
>
> ~Jonathan

Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Jonathan Castello-2
On Sat, May 22, 2010 at 12:21 PM, Stuart P. Bentley
<[hidden email]> wrote:

> I like this. In fact, I'd say that replacing the __pairs and __ipairs
> metamethods with an __iter metamethod (that is used by the generic "for"
> when encountering non-functions, with the default case of next()) would be
> "cleaner" (as you're now not mixing up standard library functions like pairs
> with language features like metatables).
>
> On Sat, 22 May 2010 11:48:11 -0700, Jonathan Castello <[hidden email]>
> wrote:
>
>> On Sat, May 22, 2010 at 11:33 AM, Joshua Jensen
>> <[hidden email]> wrote:
>>>
>>> I am still fond of 'for k,v in t do'.  I was very sad to see it go.  It
>>> was
>>> simple.  Lua is supposed to be simple, but ipairs/pairs complicated it.
>>>
>>> Josh
>>>
>>
>> Could we perhaps return to "for k,v in t do", and have the generic-for
>> use the __pairs metamethod of its target as the iterator factory? If
>> no __pairs exists, default to next(). So this:
>>
>> for k,v in t do
>>  print(k, v)
>> end
>>
>> would normally act like you used pairs(). But if you set a metatable:
>>
>> setmetatable(t, {
>>  __pairs = function(t)
>>    return function(t, i)
>>      i = i + 1
>>      local v = t[i]
>>      if v then
>>        return i, v
>>      end
>>    end, t, 0
>>  end,
>> })
>>
>> then it iterates over the numeric indices in order. Further, you could
>> easily define a "false ipairs()" that returns a table with the __pairs
>> metamethod set:
>>
>> function ipairs(t)
>>  local copy = {}
>>  for k,v in t do
>>    copy[k] = v
>>  end
>>  return setmetatable(copy, {
>>    __pairs = the_iter, -- same as above
>>  })
>> end
>>
>> ~Jonathan
>
>

I agree, __iter sounds like a much better choice of name.

As a point of interest, if numbers had a default __iter of their own,
you could do voodoo like this:

for i in 50, 100 do
  print(i)
end

Presumably, __iter would be called with 100 as the second argument,
just like you'd expect for an iterator factory. You could even pass a
third value, the step:

for i in 1, 100, 5 do
  print(i)
end

That pretty much obsoletes the numeric-for, actually.

~Jonathan
Reply | Threaded
Open this post in threaded view
|

Re: Is it necessary to kill ipairs()?

Jonathan Castello-2
In reply to this post by Jonathan Castello-2
On Sat, May 22, 2010 at 11:48 AM, Jonathan Castello <[hidden email]> wrote:
> Could we perhaps return to "for k,v in t do", and have the generic-for
> use the __pairs metamethod of its target as the iterator factory? If
> no __pairs exists, default to next().

For posterity, I meant "default to pairs()".

~Jonathan