Jump to content




Function not returning multiple values


  • You cannot reply to this topic
6 replies to this topic

#1 HDeffo

  • Members
  • 214 posts

Posted 12 March 2015 - 02:56 PM

I am attempting to make a function return an unpacked table. Testing showed the table does have multiple values. As well separating the function from the rest of the program it returned values as expected...so something else in the program is making it not return correctly. I have spent some hours trying to fix this so figured maybe someone can give me some new ideas on whats wrong. Currently it is only returning the first value in the table "concat"

Spoiler



function which is failing:
  fileSnipeNew.getLine = function(self,...)
	if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
	self:handle(false)
	local concat = {}
	for _,line in ipairs(arg) do
	  line=line<0 and #self.fileData+(line+1) or line
	  table.insert(concat,line<#self.fileData and line>0 and self.fileData[line])
	end
	return unpack(concat)
  end



I understand this is a ton of tightly packed messy code so I don't expect too many people to try and help as its difficult to even read but thanks to anyone who does try to figure this out in advance!



extra note: there may be a few bugs after the replace function as I am currently going through and revamping the code. This is the dev of the update and can't continue update/bug cracking without fixing this return issue. These bugs shouldn't be of any effect to the returning issue since the function only references to items defined before it.


EDIT:
to save effort I am assuming the cause is in lines 65-72 where im saving the function as a table using a __call metamethod. I don't know why this would cause it to not return multiple values though and I haven't managed to isolate the exact cause.

Edited by HDeffo, 12 March 2015 - 03:32 PM.


#2 Dragon53535

  • Members
  • 973 posts
  • LocationIn the Matrix

Posted 12 March 2015 - 04:46 PM

Couple of questions
1. I don't believe self is going to be exactly passed in the way that you want because it's not in the __index metatable?
2. Where in the love of all that is holy is arg defined? I noticed that down the way is it being defined inside a different function as a global variable, but why?

If you're thinking that ... is renamed to the variable of arg, then you're mistaken, you need to insert that into a table.

local function foo(...)
  local arg = {...}
end


Edit: If for some reason i'm also mistaken, you also need to catch the other values returned. If you're doing this:
local function derp()
  return unpack({1,2,3,4,5,6,7})
end
local a = derp()
then a will ONLY be 1, and 2,3,4,5,6,7 will disappear

Edited by Dragon53535, 12 March 2015 - 04:48 PM.


#3 HDeffo

  • Members
  • 214 posts

Posted 12 March 2015 - 05:13 PM

Already tested and self is passed correctly dragon. It is defined by newindex as t and sent through the call using that variable previously passed. Check the __newindex metamethod for how it handles new indexes that are functions.


arg is predefined it's a table version of ... And doesn't need to be defined. Also tested and works just fine.

I am using methods to catch all variables to test the issue save the file I posted as "fileSnipe",try opening lua in a computer and type
os.loadAPI("fileSnipe")
file = fileSnipe.open("fileSnipe")
print(file.getLine(1,2,3,4))

Print can handle multiple arguments as if they were concat using .. So this should work just fine however it prints line one only even though the unpacked table contains all 4 lines.i also tested using
tbl = {file.getLine(1,2,3,4)}
print(textutils.serialize(tbl))

Edited by HDeffo, 12 March 2015 - 05:15 PM.


#4 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 12 March 2015 - 07:40 PM

Haven't tested yet, but I believe it is because of this:

__newindex = function(t,k,v)
          if type(v)=="function" then
                func = setmetatable({},{
                  __call = function(_,...)
                        return rawequal(t,({...})[1]) and v(...) or v(t,...) <-- right here
                  end;
                })
                rawset(t,k,func)
          else

The thing is 'and', 'or' and other operators don't accept a 'varlist' (variable list), but rather take the first variable from it. I'd suggest to make an if statement and two different return statements. Also, I believe with just a function it would be more efficient than with a function and a metatable:

if type(v)=="function" then
  func = function(...)
    if rawequal(t,select(1, ...)) then <-- there is a 'select' function specifically made for that in Lua ;)/>, looks cleaner
      return v(...)
    else
      return v(t,...)
    end
  end

  rawset(t,k,func)
else

Edited by MKlegoman357, 12 March 2015 - 09:21 PM.


#5 HDeffo

  • Members
  • 214 posts

Posted 12 March 2015 - 07:54 PM

View PostMKlegoman357, on 12 March 2015 - 07:40 PM, said:

-snip-
You're probably right I didn't even think about the and,or staments applying the want is being returned although I do wonder why this doesn't screw up a thousand times worse than just only sending one result

if rawequal(t,arg[1]) and x,y,z or x,y,z

I feel like this would either return
x,y,z,y,z
OR
y,z,x,y,z
Instead of just x


(Will test a fix when I get home and let you know if it works)


Also I'm not really sure why I chose to use a metatable actually...you have a really good point on just making it a function :P

Edited by HDeffo, 12 March 2015 - 08:02 PM.


#6 MKlegoman357

  • Members
  • 1,170 posts
  • LocationKaunas, Lithuania

Posted 12 March 2015 - 09:28 PM

Function returns don't translate like that, it's just how they work with operators: they give the operator only the first return value discarding the others. Oh, and that above would return: false/x,y,z/x,y,z - 5 variables, unless x,y,z would actually be a function call, then - always x.

Edited by MKlegoman357, 12 March 2015 - 09:28 PM.


#7 HDeffo

  • Members
  • 214 posts

Posted 12 March 2015 - 11:29 PM

View PostMKlegoman357, on 12 March 2015 - 09:28 PM, said:

Function returns don't translate like that, it's just how they work with operators: they give the operator only the first return value discarding the others. Oh, and that above would return: false/x,y,z/x,y,z - 5 variables, unless x,y,z would actually be a function call, then - always x.

Thanks for the help this bug was really tormenting me! :P





3 user(s) are reading this topic

0 members, 3 guests, 0 anonymous users