-1

When I call the method stream that I made, with any table as argument, I get the error "attempt to call table".

As far as I know this error only occurs when I use a for wrong, but I don't have a for in the code that is executed...

function stream(input)
  ...
  local function _stream(input)
    local result = {
      _stream = true,
      _data = input._data or input,
      -- Without the Operation-wrapping no function could access the input
      -- Intermediate Operations
      concat = function(str) return _concat(input,str) end,
      distinct = function(func) return _distinct(input,func) end,
      filter = function(func) return _filter(input,func) end,
      limit = function(n) return _limit(input,n) end,
      map = function(func) return _map(input,func) end,
      skip = function(n) return _skip(input,n) end,
      sort = function(func) return _sort(input,func) end,
      split = function(func) return _split(input,func) end,
      -- Terminal Operations
      allmatch = function(func) return _allmatch(input,func) end,
      anymatch = function(func) return _anymatch(input,func) end,
      collect = function(coll) return _collect(input,coll) end,
      count = function() return _count(input) end,
      foreach = function(func) return _foreach(input,func) end,
      max = function(func) return _max(input,func) end,
      min = function(func) return _min(input,func) end,
      nonematch = function(func) return _nonematch(input,func) end,
      reduce = function(init,op) return _reduce(input,init,op) end,
      toArray = function() return _toArray(input) end
    }
    return result
  end

  if input == nil then
    error("input must be of type table, but was nil")
  elseif type(input) ~= "table" then
    error("input must be of type table, but was a "..type(input)..": "..input)
  end
  return _stream(input)
end

table.stream = stream

Full Source - Older Version (where the argument gets deleted for some reason)

I want to use the method for a more stream-based programming style. Very similar to this project, but more not only for numbers and with named keys.

Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64
gDKdev
  • 3
  • 3
  • I suspect that it may be the `_foreach` call that does that but can you also post the traceback with your error? I think it'll help us pinpoint it – kingJulian Mar 01 '18 at 21:23
  • Please give a traceback (at which line the error is raised?) and show how do you call the method `stream`. – Egor Skriptunoff Mar 02 '18 at 08:25
  • I don't think that `_foreach` causes the error because the project I mentioned uses the same names, also in the old version this works fine, but the methods don't get access to the input for some reason. I call the method like `stream({})`, `stream({1,2,3})` or `stream({a=1,b=2,c=3})` and the only thing that I'm getting back is `lua:1: attempt to call table`. – gDKdev Mar 02 '18 at 12:10
  • @gDKdev - I can't reproduce your error. Your program works fine for me. Please test your script at [Lua demo](https://www.lua.org/demo.html) to make sure it indeed causes an error. – Egor Skriptunoff Mar 02 '18 at 17:10
  • That's odd, on the Lua demo it behaves like the old version, I also don't get an error Which means I maybe don't need the wrapper stuff... The problem that i'd tried to fix with the wrappers is that when I call any function on the stream like `stream({1,2,3}).count()` for some reason I can't access the data, its just `nil`: `input:116: attempt to get length of a nil value (field '_data')` (to try this in the lua demo you need the complete new or old source (or at least the function) and increase the character limit on the input field). Note: `count()` only can count numeric keys. – gDKdev Mar 02 '18 at 17:39
  • @gDKdev - Please prepare example of code which generates the error on Lua demo. We can't fix an error we don't see. – Egor Skriptunoff Mar 02 '18 at 19:23
  • [Here](https://pastebin.com/2gHjGRGL) is a example code for the Lua demo – gDKdev Mar 02 '18 at 22:46

1 Answers1

0

In your code

function stream(input)
  -- ...

  local function _count()
    local count = 0
    for k, v in pairs(input._data) do
      count = count + 1
    end
    return count
  end

  -- ...

  local function _stream(input)
    local result = {
      _stream = true,
      _data = input._data or input,
      -- ...
      count = _count,
      -- ...
    }
    return result
  end

  return _stream(input)
end

print(stream({1,2,3}).count())

the created object _stream(input) does contain _data field, but input upvalue still refers to your argument {1,2,3} which doesn't have _data field.

It could be fixed by working with the object instead of input argument:

function stream(input)
  -- ...

  local obj

  local function _count()
    local count = 0
    for k, v in pairs(obj._data) do
      count = count + 1
    end
    return count
  end

  -- ...

  local function _stream(input)
    local result = {
      _stream = true,
      _data = input._data or input,
      -- ...
      count = _count,
      -- ...
    }
    return result
  end

  obj = _stream(input)

  return obj
end

print(stream({1,2,3}).count())
Egor Skriptunoff
  • 23,359
  • 2
  • 34
  • 64