lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Volkan Civelek wrote:
>>>
This is my first email and fyi i am very new born in Lua. 

Now the question is;

why does the below code gives me 

"error: bad argument #1 to `write' (string expected, got nil)
stack traceback:
   1:  function `write' [C]
   2:  main of file `ask.lua' at line 10

Error: Script failed"

this???

--case.lua

function foo (rt, from, s)
 for i=1,10 do
  tinsert (rt, from, strsub(s,i,i+1))
 end
end
local combi = {}
local var1 = {"1234567890"}
foo(combi, 34, var1[1])
write (combi[34], "\n")
write (combi[35], "\n")  --this guy has a problem

--EOF

and combi[34] writes 0 ?? 
<<<

Welcome to Lua, I hope you will enjoy your discovery of this wonderful
little language.
I am still a newbie myself (although I am beginning to grasp some concepts),
that's why I enjoy taking a look at other people's code... :-)

Stepping mentally on your code (good exercice), I can say that you first
insert 12, 23, ..., 90, 0 at position 34, each value pushing to higher position
the previous one (insert operation). That's why you got a '0' at position 34
(no other digit after it, so it is a single character).

Now, I dumped the table, using Jon Kleiser's asText function (Peter, your
function uses the tadd function, but we don't have it...).
It shows that tinsert seems to overwrite the previous value, instead of
pushing the values.
That's why you got nil on combi[35].
Now, I am confused. Is it a bug in tinsert? (I remember a discussion on this
function, I can't recall if it is related, or just on the "n" value.)

The official (from the manual) algorithm for tinsert is:

function tinsert (t, ...)
  local pos, value
  local n = getn(t)
  if arg.n == 1 then
    pos, value = n+1, arg[1]
  else
    pos, value = arg[1], arg[2]
  end
  t.n = n+1;
  for i=n,pos,-1 do
    t[i+1] = t[i]
  end
  t[pos] = value
end

Now, we can see where the problem is:
the "for i=n,pos,-1 do" loop is never run because pos > n (the first getn
returns 0). So we always end up to "t[pos] = value", ie. we overwrite the
previous value.
Perhaps it is on purpose?

A way to get the result you expect is to rewrite the tinsert function as
follow:

function tinsert (t, ...)
  local pos, value
  local n = getn(t)
  if arg.n == 1 then
    pos, value = n+1, arg[1]
  else
    pos, value = arg[1], arg[2]
  end
  if pos <= n then
    t.n = n+1;
    for i=n,pos,-1 do
      t[i+1] = t[i]
    end
  else
    t.n = pos
  end
  t[pos] = value
end

ie. if we are inserting a value at a position higher than the current
"size", it becomes the new size. Works at least with your code, I didn't tested it
thoroughly....

PS.: Since it is useful, I put here a copy of asText, as I copied from this
mailing list. I don't know if there is an improved version. Works fine with
simple tables (those I use :-).

--# From: kleiser@online.no (Jon Kleiser)

function asText(obj)
   -- Returns a textual representation of "any" Lua object,
   -- incl. tables (and nested tables).
   -- Functions are not decompiled (of course).
   -- Try: print(asText({{"a", "b"}; c=3}))

   visitRef = {}
   visitRef.n = 0

   asTxRecur = function(obj, asIndex)
      if type(obj) == "table" then
         if visitRef[obj] then
            return "@"..visitRef[obj]
         end
         visitRef.n = visitRef.n +1
         visitRef[obj] = visitRef.n

         local begBrac, endBrac
         if asIndex then
            begBrac, endBrac = "[{", "}]"
         else
            begBrac, endBrac = "{", "}"
         end
         local t = begBrac
         local k, v = nil, nil
         repeat
            k, v = next(obj, k)
            if k ~= nil then
               if t > begBrac then
                  t = t..", "
               end
               t = t..asTxRecur(k, 1).."="..asTxRecur(v)
            end
         until k == nil
         return t..endBrac
      else
         if asIndex then
            -- we're on the left side of an "="
            if type(obj) == "string" then
               return obj
            else
               return "["..obj.."]"
            end
         else
            -- we're on the right side of an "="
            if type(obj) == "string" then
               return '"'..obj..'"'
            else
               return tostring(obj)
            end
         end
      end
   end -- asTxRecur

   return asTxRecur(obj)
end -- asText

I keep it in a file, and when I need it, I put a dofile("_AsText_.lua") at
the beginning of the program, and use it as "print(asText(combi))".

PPS.: Suggestion: use subject lines more explicit than "Question", since
most of the primary posting here are such questions, this make hard to browse
the archives:-)
I would rename it, say... "Problem with tinsert" or "Problem with write", or
something like that.

Regards.

-- 
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--

Sent through GMX FreeMail - http://www.gmx.net