This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
gDKdev's profile picture

Error: attempt to call table only in Computecraft not in normal Lua

Started by gDKdev, 03 March 2018 - 03:02 PM
gDKdev #1
Posted 03 March 2018 - 04:02 PM
I'm working on a stream api for a more stream-based programming style and now I am stuck on a weird error: I'm getting a error in computercraft, but in normal lua not.
First I thought I had a error in my code, this is why I asked at StackOverflow for help, but it turns out not to be a Lua error.

Basically as soon as I call the method stream with any table as argument - for example: stream({}), stream({1,2,3}) or stream({a=1,b=2,c=3}) - I'm getting the error:
attempt to call table

Here is a minimal example to try it:

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 _foreach(func)
	for k, v in pairs(input._data) do
	  func(v, k)
	end
  end

  -- ...

  local function _stream(input)
	local result = {
	  _data = input._data or input,
	  -- ...
	  count = _count,
	  foreach = _foreach,
	  -- ...
	}
	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
  input = _stream(input)
  return input
end

-- This fails in CC but not in Lua
stream({})
stream({1,2,3})
stream({a=1,b=2,c=3})

Also here is the full source.

Can anyone help me? Or is this a bug in ComputerCraft or LuaJ?
Bomb Bloke #2
Posted 04 March 2018 - 07:39 AM
Cannot reproduce, either by running your "full" or "minimal" code postings. Code runs with no terminal output or error.

Shot-in-the-dark guess is that what you're actually doing is:

os.loadAPI("stream")  --# Where "stream" is a file containing your posted code.

stream({}) --# This'll throw an "Attempt to call table".

os.loadAPI() operates by running the passed script file, then taking all global variables left in scope afterwards, and dumping them into a table named after that file. Your desired function would hence up as a "stream" key in a "stream" table. If you don't want this behaviour then don't use os.loadAPI().

If in doubt, remember that you can run a pairs loop over a table and print out all the keys found within it:

for key, value in pairs(stream) do print(key .. " is a " .. type(value)) end
gDKdev #3
Posted 04 March 2018 - 04:08 PM
This is exactly what I was doing. What do I need to change / how do I call it?

Yes, I used os.loadAPI("stream"). What do I need to change that it behaves correctly.
I ended up with this:

-- Change the first line of the api to
stream = function(input)
-- Load the api with dofile
doFile("stream")
-- Use it
stream({})

Thank you.
Edited on 04 March 2018 - 05:03 PM
Bomb Bloke #4
Posted 05 March 2018 - 01:31 AM
That's one way to do it. If you're on CC1.80 you've also got access to "require". Prior to that build, there are some code snippets around these boards that can be used to add it in.