Split Function showing error in Ruby 1.8.7 - ruby-on-rails

I have a piece of code I have written in Ruby 1.8.7
Variable emotes has a list of emoticons separated by a space. However, when I apply the split function, I get an error
lines=[]
keywords=""
emotes=""
Dir["/home/pnpninja/Downloads/aclImdb/train/formatted neg/*"].each do |reviewfile|
sum_emote = 0
sum_keyword = 0
lines = File.foreach(reviewfile.to_s).first(2)
lines[0].gsub!("\n",'')
keywords = lines[0].split(" ")
emotes = lines[1].split(" ")
keywords.each { |keyword| sum_keyword = sum_keyword + keywordhash[keyword] }
emotes.each { |emote| sum_emote = sum_emote + emotehash[emote] }
senti=""
if sum_emote+sum_keyword >= 0
senti = "Positive"
else
senti = "Negative"
end
vv = reviewfile.gsub('formatted neg','analysed neg')
fin = File.open(vv.to_s, 'a')
fin << "Emote Weight = #{sum_emote}\n"
fin << "Keyword Weight = #{sum_keyword}\n"
fin << "Sentiment : #{senti}"
fin.close
end
The error I get is
NoMethodError: private method `split' called for nil:NilClass
at line
emotes = lines[1].split(" ")
THe second line in each file could be empty or not.

The error is telling you that you can't call split on a nil object.
Rewrite your code to ensure there are no nil objects or ensure nothing is done if the object in question is nil
unless lines[1].nil?
emotes = lines[1].split(" ")
emotes.each { |emote| sum_emote = sum_emote + emotehash[emote] }
end

Related

lua open a file with a table and change certain values

I have a file with a large table. Need to open it, get certain values and replace other values with the new ones. With this example, Females and Males Classroom a and b must equal Teachers Classroom a and b.
Read as much as I can on IO, but I cannot seem to get this to work correctly. Any help will be greatly appreciated.
--file with sample data to test, original file has 7000+lines
theData =
{
["theSchool"] =
{
["theTeachers"] =
{
["theClassroom"] =
{
["a"] = 001,
["b"] = 002,
},
},
["theFemales"] =
{
["theClassroom"] =
{
["a"] = 005,
["b"] = 010,
},
},
["theMales"] =
{
["theClassroom"] =
{
["a"] = 012,
["b"] = 014,
},
},
},
}
Then the function file looks like this
local file = io.open(filepath,'r')
local newCa = '["a"] = '..theData.theSchool.theTeachers.theClassroom.a
local newCb = '["b"] = '..theData.theSchool.theTeachers.theClassroom.b
local replaceFa = '["a"] = '..tostring(theData.theSchool.theFemales.theClassroom.a)
local replaceFb = '["b"] = '..tostring(theData.theSchool.theFemales.theClassroom.b)
local replaceMa = '["a"] = '..tostring(theData.theSchool.theMales.theClassroom.a)
local replaceMb = '["b"] = '..tostring(theData.theSchool.theMales.theClassroom.b)
file:close()
--Will it work?
print("Original Values:")
print(newCa)
print(newCb)
print(replaceFa)
print(replaceFb)
print(replaceMa)
print(replaceMb)
file = io.open(filepath,'r+')
function lines_from(filepath)
lines = {}
for line in io.lines(filepath) do
lines[#lines + 1] = line
end
return lines
end
local lines = lines_from(filepath)
for k,v in ipairs(lines) do
if v == replaceFa then
file:write(newCa..'\n')
elseif v == replaceFb then
file:write(newCb..'\n')
elseif v == replaceMa then
file:write(newCa..'\n')
elseif v == replaceMb then
file:write(newCb..'\n')
else
file:write(v..'\n')
end
--('[' .. k .. ']', v)
end
--replaceF = {[a] = newCa, [b] = newCb}
--replaceM = {[a] = newCa, [b] = newCb}
--file:write(replaceF)
--file:write(replaceM)
--print(tostring(theData.theSchool.theFemales.theClassroom.a))
file:close()
file = io.open(filepath,'r')
--Did it work?
print("New Values:")
print(theData.theSchool.theTeachers.theClassroom.a)
print(theData.theSchool.theTeachers.theClassroom.b)
print(theData.theSchool.theFemales.theClassroom.a)
print(theData.theSchool.theFemales.theClassroom.b)
print(theData.theSchool.theMales.theClassroom.a)
print(theData.theSchool.theMales.theClassroom.b)```
> I'll remove all the print things after it works.
try this solution, loading the table in one read of the file will be faster, and writing is also better with one command write
--- read
local handle = io.open("data.lua",'rb')
local data = handle:read("*a")
handle:close()
data = data .. "\n return theData"
local t = loadstring(data)()
-- edit
theData.theSchool.theTeachers.theClassroom.a = theData.theSchool.theTeachers.theClassroom.a + 1
-- write
local function concat(t, r)
r = r or {}
for k,v in pairs(t) do
if type(v)=="table" then
r[#r+1] = string.format('\t["%s"]={\n',k )
concat(v, r)
r[#r+1] = "\t},\n"
else
r[#r+1] = string.format('\t\t["%s"]=%03s,\n',k ,v )
end
end
return r
end
local r = concat(t)
local text = "theData = { \n " .. table.concat(r) .. "}"
print(text) -- just control
local handle = io.open("data.lua",'wb')
local data = handle:write(text)
handle:close()

How to implement the exercise 15.5 in pil4?

I am working on this exercise in pil4.
Exercise 15.5:
The approach of avoiding constructors when saving tables with cycles is too radical. It is
possible to save the table in a more pleasant format using constructors for the simple case, and to use
assignments later only to fix sharing and loops. Reimplement the function save (Figure 15.3, “Saving
tables with cycles”) using this approach. Add to it all the goodies that you have implemented in the previous
exercises (indentation, record syntax, and list syntax).
I have tried this with the code below, but it seems not to work on the nested table with a string key.
local function basicSerialize(o)
-- number or string
return string.format("%q",o)
end
local function save(name,value,saved,indentation,isArray)
indentation = indentation or 0
saved = saved or {}
local t = type(value)
local space = string.rep(" ",indentation + 2)
local space2 = string.rep(" ",indentation + 4)
if not isArray then io.write(name," = ") end
if t == "number" or t == "string" or t == "boolean" or t == "nil" then
io.write(basicSerialize(value),"\n")
elseif t == "table" then
if saved[value] then
io.write(saved[value],"\n")
else
if #value > 0 then
if indentation > 0 then io.write(space) end
io.write("{\n")
end
local indexes = {}
for i = 1,#value do
if type(value[i]) ~= "table" then
io.write(space2)
io.write(basicSerialize(value[i]))
else
local fname = string.format("%s[%s]",name,i)
save(fname,value[i],saved,indentation + 2,true)
end
io.write(",\n")
indexes[i] = true
end
if #value > 0 then
if indentation > 0 then io.write(space) end
io.write("}\n")
else
io.write("{}\n")
end
saved[value] = name
for k,v in pairs(value) do
if not indexes[k] then
k = basicSerialize(k)
local fname = string.format("%s[%s]",name,k)
save(fname,v,saved,indentation + 2)
io.write("\n")
end
end
end
else
error("cannot save a " .. t)
end
end
local a = { 1,2,3, {"one","Two"} ,5, {4,b = 4,5,6} ,a = "ddd"}
local b = { k = a[4]}
local t = {}
save("a",a,t)
save("b",b,t)
print()
And I got the wrong ouput.
a = {
1,
2,
3,
{
"one",
"Two",
}
,
5,
{
4,
5,
6,
}
a[6]["b"] = 4
,
}
a["a"] = "ddd"
b = {}
b["k"] = a[4]
How could I make the text ' a[6]["b"] = 4 ' jump out of the table constructor?

Lua error making 16x16 grid

The following code gives me the following error:
attempt to index a nil value
-- Making grid
grid = {}
local i = 1
local ii = 1
mainx, mainy = love.graphics.getDimensions()
while(i<=mainx) do
if(i%16==0) then
while(ii<=mainy) do
if(ii%16==0) then
grid[i][ii] = nil
end
ii = ii + 1
end
end
i = i+1
end
I know lua is 1-based, but i dont really know what goes wrong here.
A fix will be gladly appericated :)
NOTE: mainx, mainy should be 800 and 600.
You forgot to assign grid[i] to {} before doing grid[i][ii] = nil. Second dereferencing [ii] fails because grid[i] == nil
I refactored your code below a little.
-- Making grid
local grid = {}
local mainx, mainy = love.graphics.getDimensions()
for i = 16,mainx,16 do -- syntax: for i = <start_value>, <max value (included)> [, <step>]
grid[i] = {};
for ii = 16,mainy,16 do
grid[i][ii] = i*ii -- some value
end
end

Lua: Help function: Can I extract the name of a function?

I would like to learn by developing a help function. The code below outlines my plan, and it can be summarized as:
For functions defined in Lua files - look for comments in the source.
For built-in functions and DLLs - look for a text file in .\help\function.txt.
For libraries (if no comments in the source) - look for a text file in .\lib\help\function.txt.
At the end of my code you can see an attempt to build an index of function names using their unique tostring(function) return value. Surely I should be able to do this in a loop?
function learn()
-- learn()
-- Make it easier to learn Lua, based upon Matlab console functions
-- help() print for help text in function source or help directory
-- who() print defined variables (exlcuding those in loaded modules)
-- what() print defined functions (exlcuding those in loaded modules)
-- which() print path to function source file if present
-- list() print the file to the console
-- edit() edit "filename" or function source if present
-- note: edit(_) can be used after any call to list(), help(func),
-- Helper functions
-- table.name() returns table name as string
-- table.length() this is difficult
-- table.keylist() returns a list of keys
-- table.keytype() returns a list of key types
-- edit_source() process function names
-- edit_new() create new "filename" (will use but not make subdirectories)
-- string.split() returns a table from a string
-- io.exists() test if a filename exists
-- io.newfile() creates an empty file
--
-- global variables
-- editor = "P:\\MyPrograms\\EDITORS\\Addins\\Editor2\\editor2.exe "
-- helpindex a list of the names of the inbuilt functions - see end of file
-- topics a table of help topics see topics.lua
-- web = "web"
web = "web"
-- webhelp = "http://www.nongnu.org/gsl-shell/doc/"
webhelp = "http://www.nongnu.org/gsl-shell/doc/"
-- editor = "P:\\MyPrograms\\EDITORS\\Addins\\Editor2\\editor2.exe "
editor = "P:\\MyPrograms\\EDITORS\\Addins\\Editor2\\editor2.exe "
-- required packages
-- lfs - lua file system (binary from lua-files)
require("lfs")
-- topics - for the help system
require("topics")
end
learn()
function who(t,i)
-- who(table)
-- searches the table (or defaults to _G) to print a list of table keys + types
-- the second parameter is to add a prefix for a recursive call to search "sub" tables
-- still having difficulty with the "loaded" table as this is self referencing and sets up an infinate loop!
-- designed for the console, but could be modified to return a table
--
if type(t)~="table" then
t=_G
end
if type(i)~="string" then
i=""
end
local s={}
local u={}
s = table.keylist(t)
u = table.keytype(t)
for k,v in ipairs(s) do
if u[k]=="table" and s[k]~="_G" and s[k]~="loaded" then
who(t[s[k]],i..v..".")
else
if u[k]~="table" and u[k]~="function" and u[k]~="cdata" then
print(u[k], i..v)
end
end
end
end
function what(t,i)
-- what(table)
-- searches the table (or defaults to _G) to print a list of function names
-- the second parameter is to add a prefix for a recursive call to search "sub" tables
-- still having difficulty with the "loaded" table as this is self referencing and sets up an infinate loop!
-- designed for the console, but could be modified to return a table
--
if type(t)~="table" then
t=_G
end
if type(i)~="string" then
i=""
end
local s={}
local u={}
s = table.keylist(t)
u = table.keytype(t)
for k,v in ipairs(s) do
if u[k]=="table" and s[k]~="_G" and s[k]~="loaded" then
what(t[s[k]],i..v..".")
else
if u[k]=="function" then
print(u[k], i..v)
end
end
end
end
function which(funcname)
-- which(funcname)
-- identifies the source for the current definition of funcname
-- designed for the console, but could be modified to return a string
--
if type(funcname)~="function" then return end
local filename = _G.debug.getinfo(funcname).short_src
if filename=="[C]" then
print(tostring(funcname))
else
return filename
end
end
function help(funcname)
-- help(object)
-- for functions prints help text (from source or help\function.txt)
-- adding help text to source as ^--comments is recommended,
-- for builtin functions use a subdirectory from the executable,
-- for uncommented source add a sibling help directory
-- for table prints table name, size and list of contents
-- for variables prints the type of the object
--
if type(funcname)=="boolean" then
io.write("boolean: ")
print(funcname)
return
end
if type(funcname)=="string" then
if funcname=="web" then
os.launch(webhelp)
else
print("string: "..funcname)
end
return
end
if type(funcname)=="number" then
print("number: "..funcname)
return
end
if type(funcname) == 'userdata' then
print(tostring(funcname))
io.write("metadata: ")
print(getmetatable(funcname))
end
if type(funcname) == 'cdata' then
print(tostring(funcname))
-- *** Unfinished
end
if type(funcname)=="table" then
print(tostring(funcname)..", size: "..table.length(funcname))
who(funcname)
what(funcname)
return
end
if type(funcname)=="function" then
-- Test for a source file
local filename = _G.debug.getinfo(funcname).short_src
if io.exists(filename) then
local codestart = _G.debug.getinfo(funcname).linedefined
local codeend = _G.debug.getinfo(funcname).lastlinedefined
if codestart < 1 then
print("Start is less than 1")
codestart = 1
end
if codeend< 1 then
print("End is less than 1")
codeend= 100
end
-- Try to read comments from the source
local output = 0
local count = 0
for line in io.lines(filename) do
count = count+1
if count > codestart and count < codeend then
if line:match("^%-%-") then
print(line)
output = output + 1
end
end
end
if output>0 then
io.write("From : ")
return filename -- to be used with edit(_)
end
-- Test for a help file as a sibling of the source
if output==0 then
-- No comments in the source file so look for a help file
local t = string.split(filename, "\\")
local helppath = table.concat(t,"\\",1,table.length(t)-1).."\\help\\"..t[table.length(t)]
helppath = string.gsub(helppath, "%.lua$" , ".txt")
if io.exists(helppath) then
local filename = list(helppath)
io.write("From : ")
return filename -- to be used with edit(_)
else
print("No help in source file : "..filename)
io.write("No help in: ")
return helppath -- to be used with edit_new(_)
end
end
end
-- Test for a help file in the generic help directory
if helpindex[tostring(funcname)] then
local helppath = "help\\"..helpindex[tostring(funcname)]..".txt"
if io.exists(helppath) then
local filename = list(helppath)
io.write("From : ")
return filename -- to be used with edit(_)
else
io.write("Built in function, but no help in: ")
return helppath -- to be used with edit_new(_)
end
else
print("No help index entry for "..tostring(funcname))
return
end
end
end
function list(filename)
if type(filename)=="function" then
print("list will only accept a string with a valid file name")
return
end
if type(filename)~="string" then
print("list will only accept a string with a valid file name")
return
end
if io.exists(filename) then
for line in io.lines(filename) do
print(line)
end
return filename
else
io.write("Can't find file: ")
return filename
end
end
function edit(filename, linenum)
-- edit(filename[, linenum])
-- loads the file into my editor (defined as global editor)
-- the linenum parameter will move the cursor to linenum
-- you will need to edit the global "editor" and the source command line below
-- or download Editor² from http://www.zabkat.com
--
if type(filename)=="function" then
filename = edit_source(filename)
return filename
end
if type(filename)~="string" then return end
if type(linenum)~="number" then linenum=1 end
if io.exists(filename) then
os.launch(editor.." /P /L:"..linenum.." \""..filename.."\"", " /P /L:"..linenum.." \""..filename.."\"")
else
print("To make a new file edit_new('filename')")
io.write("Can't find file: ")
return filename
end
end
function edit_source(funcname)
if type(funcname)~="function" then return end
local filename = _G.debug.getinfo(funcname).short_src
if io.exists(filename) then
local linenum = _G.debug.getinfo(funcname).linedefined
if linenum < 1 then
linenum = 1
end
edit(filename, linenum)
io.write("Editing : ")
return filename
end
end
function edit_new(filename)
if type(filename)~="string" then return end
io.newfile(filename)
edit(filename) -- This will check for a valid file name
io.write("Editing : ")
return filename
end
function table.name(table)
if type(table)~="table" then return end
for k, v in pairs(_G) do
if v == table then
return k
end
end
return nil
end
function table.length(table)
if type(table)~="table" then return end
local len = 0
for _ in pairs(table) do
len = len + 1
end
if type(len)=="number" then
return len
else
return nil
end
end
function table.keylist(table)
if type(table)~="table" then return end
local keylist={}
local n=0
for key in pairs(table) do
n=n+1
keylist[n]=key
end
return keylist
end
function table.keytype(table)
if type(table)~="table" then return end
local keytype={}
local n=0
for key in pairs(table) do
n=n+1
keytype[n]=type(table[key])
end
return keytype
end
function table.tablelist(table)
if type(table)~="table" then return end
local tablelist={}
local n=0
for key in pairs(table) do
if type(table[key])=="table" then
n=n+1
tablelist[n]=key
end
end
return tablelist
end
function string.split(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
local i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t
end
function io.newfile(filename)
-- io.newfile(filename)
-- Will create a file if this is a valid filename
-- relative paths will work
-- files will not be overwritten
if type(filename)~="string" then
print("This function requires a string")
return
end
if io.exists(filename) then
io.write("This file already exists : ")
return filename
end
file, errormsg = io.open(filename, "w")
if errormsg then
print(errormsg)
else
file:write()
file:close()
io.write("New file created : ")
return filename
end
end
function io.exists(filename)
if type(filename)~="string" then return false end
local f=io.open(filename,"r")
if f~=nil then
io.close(f) return true
else
return false
end
end
function os.launch(command,params)
-- Via a dos box works - but flashes up a dos console
-- would love a way round this problem
command = "start "..command
os.execute(command)
end
helpindex = {
[tostring(assert)] = "assert",
[tostring(collectgarbage)] = "collectgarbage",
[tostring(dofile)] = "dofile",
[tostring(error)] = "error",
[tostring(getfenv)] = "getfenv",
[tostring(getmetatable)] = "getmetatable",
[tostring(ipairs)] = "ipairs",
[tostring(load)] = "load",
[tostring(loadfile)] = "loadfile",
[tostring(loadstring)] = "loadstring",
[tostring(next)] = "next" ,
[tostring(pairs)] = "pairs" ,
[tostring(pcall)] = "pcall" ,
[tostring(rawequal)] = "rawequal" ,
[tostring(rawget)] = "rawget" ,
[tostring(rawset)] = "rawset" ,
[tostring(select)] = "select" ,
[tostring(setfenv)] = "setfenv" ,
[tostring(setmetatable)] = "setmetatable" ,
[tostring(tonumber)] = "tonumber" ,
[tostring(tostring)] = "tostring" ,
[tostring(type)] = "type" ,
[tostring(unpack)] = "unpack" ,
[tostring(xpcall)] = "xpcall" ,
[tostring(coroutine.create)] = "coroutine.create" ,
[tostring(coroutine.resume)] = "coroutine.resume" ,
[tostring(coroutine.running)] = "coroutine.running" ,
[tostring(coroutine.status )] = "coroutine.status ",
[tostring(coroutine.wrap)] = "coroutine.wrap" ,
[tostring(coroutine.yield)] = "coroutine.yield" ,
[tostring(string.byte)] = "string.byte" ,
[tostring(string.char)] = "string.char" ,
[tostring(string.dump)] = "string.dump" ,
[tostring(string.find )] = "string.find",
[tostring(string.format)] = "string.format" ,
[tostring(string.gmatch)] = "string.gmatch" ,
[tostring(string.gsub)] = "string.gsub" ,
[tostring(string.len)] = "string.len" ,
[tostring(string.lower)] = "string.lower" ,
[tostring(string.match)] = "string.match" ,
[tostring(string.rep)] = "string.rep" ,
[tostring(string.reverse)] = "string.reverse" ,
[tostring(string.sub)] = "string.sub" ,
[tostring(string.upper)] = "string.upper" ,
[tostring(table.concat)] = "table.concat" ,
[tostring(table.insert)] = "table.insert" ,
[tostring(table.maxn)] = "table.maxn" ,
[tostring(table.remove)] = "table.remove" ,
[tostring(table.sort)] = "table.sort" ,
[tostring(math.abs)] = "math.abs" ,
[tostring(math.acos)] = "math.acos" ,
[tostring(math.asin)] = "math.asin" ,
[tostring(math.atan)] = "math.atan" ,
[tostring(math.atan2)] = "math.atan2" ,
[tostring(math.ceil)] = "math.ceil" ,
[tostring(math.cos)] = "math.cos" ,
[tostring(math.cosh)] = "math.cosh" ,
[tostring(math.deg)] = "math.deg" ,
[tostring(math.exp)] = "math.exp" ,
[tostring(math.floor)] = "math.floor" ,
[tostring(math.fmod)] = "math.fmod" ,
[tostring(math.frexp)] = "math.frexp" ,
[tostring(math.ldexp)] = "math.ldexp" ,
[tostring(math.log)] = "math.log" ,
[tostring(math.log10)] = "math.log10" ,
[tostring(math.max)] = "math.max" ,
[tostring(math.min)] = "math.min" ,
[tostring(math.modf)] = "math.modf" ,
[tostring(math.pow)] = "math.pow" ,
[tostring(math.rad)] = "math.rad" ,
[tostring(math.random)] = "math.random" ,
[tostring(math.randomseed)] = "math.randomseed" ,
[tostring(math.sin)] = "math.sin" ,
[tostring(math.sinh)] = "math.sinh" ,
[tostring(math.sqrt)] = "math.sqrt" ,
[tostring(math.tan)] = "math.tan" ,
[tostring(math.tanh)] = "math.tanh" ,
[tostring(io.close)] = "io.close" ,
[tostring(io.flush)] = "io.flush" ,
[tostring(io.input)] = "io.input" ,
[tostring(io.lines)] = "io.lines" ,
[tostring(io.open)] = "io.open" ,
[tostring(io.output)] = "io.output" ,
[tostring(io.popen)] = "io.popen" ,
[tostring(io.read)] = "io.read" ,
[tostring(io.tmpfile)] = "io.tmpfile" ,
[tostring(io.type)] = "io.type" ,
[tostring(io.write)] = "io.write" ,
[tostring(os.clock)] = "os.clock" ,
[tostring(os.date)] = "os.date" ,
[tostring(os.difftime)] = "os.difftime" ,
[tostring(os.execute)] = "os.execute" ,
[tostring(os.exit)] = "os.exit" ,
[tostring(os.getenv)] = "os.getenv" ,
[tostring(os.remove)] = "os.remove" ,
[tostring(os.rename)] = "os.rename" ,
[tostring(os.setlocale)] = "os.setlocale" ,
[tostring(os.time)] = "os.time" ,
[tostring(os.tmpname)] = "os.tmpname" ,
[tostring(debug.debug)] = "debug.debug" ,
[tostring(debug.getfenv)] = "debug.getfenv" ,
[tostring(debug.gethook)] = "debug.gethook" ,
[tostring(debug.getinfo)] = "debug.getinfo" ,
[tostring(debug.getlocal)] = "debug.getlocal" ,
[tostring(debug.getmetatable)] = "debug.getmetatable" ,
[tostring(debug.getregistry)] = "debug.getregistry" ,
[tostring(debug.getupvalue)] = "debug.getupvalue" ,
[tostring(debug.setfenv)] = "debug.setfenv" ,
[tostring(debug.sethook)] = "debug.sethook" ,
[tostring(debug.setlocal)] = "debug.setlocal" ,
[tostring(debug.setmetatable)] = "debug.setmetatable" ,
[tostring(debug.setupvalue)] = "debug.setupvalue" ,
[tostring(debug.traceback)] = "debug.traceback" ,
[tostring(module)] = "module" ,
[tostring(package.loadlib)] = "package.loadlib" ,
[tostring(package.seeall)] = "package.seeall" ,
[tostring(print)] = "print" ,
[tostring(require)] = "require" ,
[tostring(graph.fxplot)] = "graph.fxplot"
}
Revised code:
function help(funcname)
-- help(object)
-- for functions prints help text (from source or help\function.txt)
-- adding help text to source as ^--comments is recommended,
-- for builtin functions use a subdirectory from the executable,
-- for uncommented source add a sibling \help directory and function.txt
-- (note that the source file may contain several functions)
-- for table prints table name, size and list of contents
-- for variables prints the type of the object
--
if type(funcname)=="boolean" then
io.write("boolean: ")
print(funcname)
return
end
if type(funcname)=="string" then
if funcname=="web" then
os.launch(webhelp)
else
print("string: "..funcname)
end
return
end
if type(funcname)=="number" then
print("number: "..funcname)
return
end
if type(funcname) == 'userdata' then
print(tostring(funcname))
io.write("metadata: ")
print(getmetatable(funcname))
end
if type(funcname) == 'cdata' then
print(tostring(funcname))
-- *** Unfinished
end
if type(funcname)=="table" then
print(tostring(funcname)..", size: "..table.length(funcname))
who(funcname)
what(funcname)
return
end
if type(funcname)=="function" then
-- Test for a source file
local filename = _G.debug.getinfo(funcname).short_src
if io.exists(filename) then
local codestart = _G.debug.getinfo(funcname).linedefined
local codeend = _G.debug.getinfo(funcname).lastlinedefined
if codestart < 1 then
print("Start is less than 1")
codestart = 1
end
if codeend< 1 then
print("End is less than 1")
codeend= 100
end
-- Try to read comments from the source
local output = 0
local count = 0
for line in io.lines(filename) do
count = count+1
if count > codestart and count < codeend then
if line:match("^%-%-") then
print(line)
output = output + 1
end
end
end
if output>0 then
io.write("From : ")
return filename -- to be used with edit(_)
end
-- Try to read comments from \help\function.txt
if output==0 then
-- No comments in the source file so look for a help file
local t = string.split(filename, "\\")
local helppath = table.concat(t,"\\",1,table.length(t)-1).."\\help\\"..helpindex[funcname]..".txt"
if io.exists(helppath) then
local filename = list(helppath)
io.write("From : ")
return filename -- to be used with edit(_)
else
print("No help in source file : "..filename)
io.write("No help in: ")
return helppath -- to be used with edit_new(_)
end
end
end
-- Test for a help file in the generic help directory
if helpindex[funcname] then
local helppath = "help\\"..helpindex[funcname]..".txt"
if io.exists(helppath) then
local filename = list(helppath)
io.write("From : ")
return filename -- to be used with edit(_)
else
io.write("Built in function, but no help in: ")
return helppath -- to be used with edit_new(_)
end
else
print("No help index entry for "..helpindex[funcname])
return
end
end
end
-- helpindex as a [function literal -> string] mapping of names.
-- many thanks to Ryan Stein
-- http://stackoverflow.com/questions/20269173/lua-help-function-can-i-extract-the-name-of-a-function
helpindex = {}
do
local function indexfn(t, n)
if n == '_G' then n = '' else n = n .. '.' end
for k, v in pairs(t) do
if type(v) == 'function' then
helpindex[v] = n .. k
end
end
end
for k, v in pairs(_G) do -- Iterate all tables in global scope.
if type(v) == 'table' then
indexfn(v, k)
end
end
end
Perhaps this may be what you're looking for:
local helpindex = {}
do
local function indexfn(t, n)
if n == '_G' then n = '' else n = n .. '.' end
for k, v in pairs(t) do
if type(v) == 'function' then
helpindex[v] = n .. k
end
end
end
for k, v in pairs(_G) do -- Iterate all tables in global scope.
if type(v) == 'table' then
indexfn(v, k)
end
end
end
-- helpindex is now a [function literal -> string] mapping of names.
You don't need to convert the functions to strings to use them as table keys, since anything other than nil can be used as a table key in Lua. The functions themselves work just fine.

Ruby/Rails - Converting Google Apps Script to Rails

I'm having a bit of trouble converting the following method in a Google App Script to work with Rails:
Tutorial: Parsing an XML Document
This is the method I'd like to convert:
function parse(txt) {
var doc = Xml.parse(txt, true);
var attr = doc.spellcheck;
if (attr) {
return "Cannot find actor: " + attr.name;
}
var actors = doc.html.head.getElements("actor");
var movies = doc.html.head.getElements("movie");
if (!actors || actors.length ==0) {
return "no match found";
}
var movieIndex = 0;
var r = '';
var firstPerson = true;
for (var i in actors) {
r = r + actors[i].getText();
if (movies[movieIndex]) {
r = r + (firstPerson ? "" : " who") + " was in " +
movies[movieIndex].getText() + " with ";
}
movieIndex++;
firstPerson = false;
}
return r;
}
This is what I have so far:
I'm using Nokogiri to parse the XML:
uri = "http://oracleofbacon.org/cgi-bin/xml?a=Kevin%20Bacon&b=#{to.strip.to_hash}&u=1&p=google-apps"
doc = Nokogiri::XML(open(uri))
My attempt at conversion:
def parse(doc)
attr = doc.xpath("//link//actor").first # => "<actor>Miley Cyrus</actor>"
if (!attr)
return "Cannot find actor: #{attr}"
end
actors = doc.xpath("//link//actor")
movies = doc.xpath("//link//movie")
if (!actors || actors.length == 0)
return "No match found."
end
movieIndex = 0
r = ""
firstPerson = true
actors.each do |actor|
r = r + actor
if (movies[movieIndex])
r = r + (firstPerson ? "" : " who") + " was in #{movies[movieIndex]} with "
end
movieIndex++
firstPerson = false;
end
return r
end
I get an error:
`block in parse': undefined method `+#' for false:FalseClass (NoMethodError)
This is happening on the firstPerson = false line.
actors.each yields each actor node to the block. So your i variable contains an actor element (Nokogiri::XML::Element). Thus actors[i] doesn't make sense, which is why you get the first error.
You're probably looking for
actors.each do |actor|
r = r + actor
[...]
end
although I am not sure what will happen when you attempt to concatenate a Nokogiri::XML::Element to a String.
Also, movieIndex++ doesn't do what you hope. You want movieIndex += 1.
Although, since you're just incrementing movieIndex on every loop, you could remove the line entirely and do actors.each do |actor, movieIndex| instead.

Resources