teal-language / tl

The compiler for Teal, a typed dialect of Lua
MIT License
2.11k stars 109 forks source link

Overly narrow handling of iterators? #525

Closed shviller closed 2 years ago

shviller commented 2 years ago

Typechecking the following code

local t: {integer:integer} = {1,2,3}

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

leads to this error:

expression in for loop does not return an iterator
unknown variable: k
unknown variable: v

However, barring its redefinition (or the presence of the __pairs metamethod in Lua 5.3 and up), using pairs(t) is actually equivalent to providing those three values (next,t,nil) directly. People have been using this specifically to avoid the metamethod, but, of course, that's not the only use. I myself tried to use it grab the first value out of a table if the initial value for reduce isn't provided:

local function reduce<K,V,A>
( t     : {K:V}
, lambda    : (function(V,A): A)
, initial   : A
): A
  local index: K
  local accumulator = initial
  if initial == nil then
    index, accumulator = next(t)
  end
  for _, v in next,t,index do
    accumulator = lambda(v, accumulator)
  end
  return accumulator
end

This isn't a dealbreaker in any way, since such functions can always be kicked out into a separate Lua file, but it would be nice to have it in Teal.

hishamhm commented 2 years ago

Ah, this form for <vars> in <fn>, <args> do was supposed to work in Teal, and in fact it does with plain iterator functions. It only failed with next because it is a "special" polymorphic function (i.e., with two type signatures in the Teal standard library definition, one for maps and one for arrays). Adding a case for poly types made the example above work.