generic image
Processing...
  • Games
  • Catalog
  • Develop
  • Robux
  • Search in Players
  • Search in Games
  • Search in Catalog
  • Search in Groups
  • Search in Library
  • Log In
  • Sign Up
  • Games
  • Catalog
  • Develop
  • Robux
   
ROBLOX Forum » Game Creation and Development » Scripting Helpers
Home Search
 

Re: LinkedList.new not working?

Previous Thread :: Next Thread 
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 08:08 AM
LinkedList = {
new = function()
return setmetatable({}, {
__newindex = function(tab, var, val)
if type(val) ~= "table" then
error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
else
rawset(tab, var, {})
local Nex = nil
local Pre = nil
for i,v in pairs(tab) do
if v == tab[var] then
Nex = tab[i + 1]
Pre = tab[i - 1]
end
end
local List = {Next = Nex, Prev = Pre, Value = val}
rawset(tab, var, List)
end
end
})
end
}

X = LinkedList.new()
X[1] = {5}
X[2] = {10}
X[3] = {15}

V1 = X[1]

print(V1.Next.Value)


It outputs;

Runtime Error:
LinkedList.lua:32: attempt to index field 'Next' (a nil value)


Any help would be greatly appreciated :D
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 08:30 AM
You're going to have to update each one after you create a new key, or just use the index metamethod

What's happening is when you do X[1] = {5} Next and Pre will be nil (since there is nothing in X[0] or X[2] and when you append to the table, Next and Pre still are nil since it was already set.
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 08:34 AM
So something like:

LinkedList = {
new = function()
return setmetatable({}, {
__newindex = function(tab, var, val)
if type(val) ~= "table" then
error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
else
local tbl = {};
setmetatable(tbl, {
__index = function(_tab, _var, _val)
local Nex = nil
local Pre = nil
for i,v in pairs(tab) do
if v == tab[var] then
Nex = tab[i + 1]
Pre = tab[i - 1]
end
end
local List = {Next = Nex, Prev = Pre, Value = val}
return List[_var];
end;
});
rawset(tab, var, tbl);
end
end
});
end
}

X = LinkedList.new()
X[1] = {5}
X[2] = {10}
X[3] = {15}

V1 = X[1]

print(V1.Next)
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 08:39 AM
Woops made a closure error, 1 second.
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 08:47 AM
I just tried this;


LinkedList = {
new = function()
return setmetatable({}, {
__newindex = function(tab, var, val)
if type(val) ~= "table" then
error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
else
rawset(tab, var, {})
local List = setmetatable({Value = val}, {
__index = function(tab2, val2)
local Loc = nil
for i, v in pairs(tab) do
if v == tab2 then
Loc = i
end
end
if val2 == "Next" then
return tab[Loc + 1]
elseif val2 == "Prev" then
return tab[Loc - 1]
end
end
})
rawset(tab, var, List)
end
end
})
end
}

X = LinkedList.new()
X[1] = {5}
X[2] = {10}
X[3] = {15}

V1 = X[1]

print(V1.Prev.Value[1])



It works!!!

Oh, and I made this after your first post. I never even saw your example for this.

Are there any potential errors that could happen with mine?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 08:51 AM
It should be fine, but you shouldn't put Value directly in the table since they can change it, unless that was intentional?
Anyway filter wouldn't let me repost so I'm going to change some variable names, if yours doesn't work properly (which it should):

LinkedList = {
new = function()
return setmetatable({}, {
__newindex = function(tab, var, val)
if type(val) ~= "table" then
error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
else
local tbl = {};
setmetatable(tbl, {
__index = function(_tab, _var)
local Nex = tab[var + 1];
local Pre = tab[var - 1];
local List = {Next = Nex, Prev = Pre, Value = val[1]};
return List[_var];
end;
});
rawset(tab, var, tbl);
end
end
});
end
}

X = LinkedList.new()
X[1] = {5}
X[2] = {10}
X[3] = {15}

V1 = X[1]
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 08:52 AM
And of course if it wasn't intentional, you should lock the metatable so they can't change it using getmetatable.
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 08:58 AM
I want a LinkedList to simply be a table of values except using tables to include Next and Prev, so yes, it was intentional for them to be able to change the value.

Although I will be locking the metatable...
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:00 AM
1 question, why x[1] = {3} and not x[1] = 3 and handle it as a table inside the __newindex metamethod? Makes using it "cleaner" I guess
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 09:06 AM
This is getting complicated XD

When I first started I was thinking to myself "This'll be simple, I'll just make a function that creates a table with tables that have Next and Prev in them.

Now all of a sudden I have this giant function handling everything with __newindex and __index


What I really hate is that table.insert and rawset can both insert values that aren't tables, without triggering __newindex.

If I handled it with __index though I could fix that too right? I'm trying to figure out how I'd do it...
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 09:08 AM
I don't suppose you could edit my script so that I could say X[1] = 5 and so table.insert/rawset will be useable?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:13 AM
It's possible, there are 2 methods I can think of:
-newproxy (slightly slow, only Lua 5.1 (or less?))
-real table hidden in scope (can cause memory leaks since the table will never get GC'd unless you handle that)
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:15 AM
I can't see a way how using __index will help
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 09:24 AM
I could use __index to detect when someone accesses the value, and return a table?

By the way I'm using Lua 5.2
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:26 AM
How would that help in preventing table.insert/rawset, or do you mean using a fake table (the 2nd option I mentioned)
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 09:34 AM
Exactly, could you do that?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:38 AM
Something like this might work (so they can't insert into the "real table")
LinkedList = {
      new = function()
            return setmetatable({}, {
                  __newindex = function(tab, var, val)
                        if type(val) ~= "table" then
                              error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
                        else
                              local tbl = {};
                              setmetatable(tbl, {
                                    __index = function(_tab, _var)
                                          local Nex = tab[var + 1];
                                          local Pre = tab[var - 1];
                                          local List = {Next = Nex, Prev = Pre, Value = val[1]};
                                          return List[_var];
                                    end;
                                    __metatable = "The metatable is locked.";
                              });
                              local fake = setmetatable({}, {__index = tbl, __newindex = tbl;});
                              rawset(tab, var, fake);
                        end
                  end;
                  __metatable = "The metatable is locked.";
            });
      end
}
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 09:40 AM
But since they can still insert into the fake table, they can still mess with the indexing.

The only fool-proof way I can think of is newproxy but you're on Lua 5.2
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 10:34 AM
local function newproxy() --I'm just gonna assume you need a metatable attached to it...
return setmetatable({}, {
__newindex = function(tab, var, val)
return error("Attempt to add a value into a userdata", 2)
end,
__index = function(tab, var)
return error("Attempt to index a value in a userdata", 2)
end
})
end



That could *kind of* mimic newproxy?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 10:39 AM
No. The same problem applies: you can table.insert and rawset.
Proxies are much like "finalizes" as well, that you can't set properties at all (rawset/table.insert will give you an error, prox[k]=v invokes __newindex

So in Lua 5.1 you could simply do:

local tbl = newproxy(true);
local mt = getmetatable(tbl);
tbl.__index = blah;
tbl.__metatable = blah;
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 02:57 PM
I just realized I'm using Lua 5.2 not Rblx.Lua.

local rawget = nil
local table.insert = function(Tab, Ind, Val)
local Ind = Ind
local Val = Val or Ind
if Val == Ind then
Ind = NumOfTab(Tab) + 1
end
Tab[Ind] = Val
end


Couldn't I just overwrite them?
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 03:00 PM
You have syntax errors but yes, you can.
However you will run into problems replacing rawget/rawset if you use them in your metamethods.

You can do it in Rbx.Lua too, just with a different approach:
local table = {};
do
local _table = table;
table = setmetatable({insert = blah}, {__index = _table;});
end
Report Abuse
cntkillme is not online. cntkillme
Joined: 07 Apr 2008
Total Posts: 44956
24 Jul 2014 03:00 PM
Woops:

local _table = table;
local table = {};
table = setmetatable({insert = blah}, {__index = _table;});
_table = nil;
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 03:47 PM
Hmmm

Well I could make something like

local __G = setmetatable({}, {
rawset = rawset
})
setmetatable(_G, {
__metatable = getmetatable(_G),
__newindex = function(tab, var, val)
__G[var] = val
_G = {}
end,
__index = function(tab, val)
if val == "rawset" then --Did I get that right?
return nil
end
end
})




Is there a way to make that more secure?

lol this is getting more complicated then I had hoped...
Report Abuse
warspyking is not online. warspyking
Joined: 15 Nov 2011
Total Posts: 13947
24 Jul 2014 03:50 PM
By the way, how'd you indent


Something like this might work (so they can't insert into the "real table")
LinkedList = {
new = function()
return setmetatable({}, {
__newindex = function(tab, var, val)
if type(val) ~= "table" then
error("Attempt to add a value " .. type(val) .. " to a LinkedList", 2)
else
local tbl = {};
setmetatable(tbl, {
__index = function(_tab, _var)
local Nex = tab[var + 1];
local Pre = tab[var - 1];
local List = {Next = Nex, Prev = Pre, Value = val[1]};
return List[_var];
end;
__metatable = "The metatable is locked.";
});
local fake = setmetatable({}, {__index = tbl, __newindex = tbl;});
rawset(tab, var, fake);
end
end;
__metatable = "The metatable is locked.";
});
end
}
Report Abuse
Previous Thread :: Next Thread 
Page 1 of 1
 
 
ROBLOX Forum » Game Creation and Development » Scripting Helpers
   
 
   
  • About Us
  • Jobs
  • Blog
  • Parents
  • Help
  • Terms
  • Privacy

©2017 Roblox Corporation. Roblox, the Roblox logo, Robux, Bloxy, and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.



Progress
Starting Roblox...
Connecting to Players...
R R

Roblox is now loading. Get ready to play!

R R

You're moments away from getting into the game!

Click here for help

Check Remember my choice and click Launch Application in the dialog box above to join games faster in the future!

Gameplay sponsored by:
Loading 0% - Starting game...
Get more with Builders Club! Join Builders Club
Choose Your Avatar
I have an account
generic image