[PD] pdlua output

Frank Barknecht fbar at footils.org
Wed Jan 23 22:30:58 CET 2008


Hallo,
robcanning hat gesagt: // robcanning wrote:

> i add a list to a table with:
> 
> -- "insert [list]" into 1st inlet:
> function M:in_1_insert(list)
>    table.insert(self.mydata, list)
> end
> 
> then i search the table for the pattern "score = 1" and ask it to print 
> the lines containing the matched pattern
> 
> -- what to do on "scores" into 1st inlet:
> function M:in_1_scores()
> for i, v in ipairs(self.mydata) do
> if string.match(v, "score = 1", 1, true) then
> self:outlet(1, "list", v) end
> end
> end
> 
> the problem is that the string.match is expecting a string and getting a 
> table and i'm not sure how to fix this - i thought the ipairs was 
> iterating the table into a string  but its not.
> 
> here is the error from pd:
> [string "rob2"]:19: bad argument #1 to 'match' (string expected, got table)

Okay, that's an issue with the general kinds of types in Lua, which
can be a bit confusing at first. Basically in Lua/Pd you will have to
deal with these three types: numbers, strings and tables. (There are
more types e.g. functions.)

Now the first two are easy: numbers are 1, 2, 3.141, ... and strings
are "this" and "that, too". Tables however are a bit trickier: For one
they can be like lists in Pd: 

 counts = {1, 2, 3, "four", "and five"}
 print(counts[4]) -- prints: "four"
 print(type(counts[4])) -- it's a string

These kinds of tables which are indexed with numbers are also called
"arrays" in Lua parlance. In Pd they are called lists. 

Arrays also can contain other arrays and tables:

 counts = {1, 2, 3, "four", "and five", 
    {"x", "y", "z"} 
 }

But the outlet functions in pdlua generally only work with flat
arrays! So you first need to convert your data to a flat array using a
pairs/ipairs iterator for example.

In the "in_*_something(args)" methods, args generally is an array as
well (except for the bang, float and symbol methods).

The self.mydata table in rob2.lua is not flat, so it needs to be made
flat like that. 

self.mydata also is a key/value table (containing flat arrays indexed
by string or numeric keys).

Tables in Lua can be key/value containers, which is something, Pd
doesn't have directly: 

 veggies = {apples = 4, potatoes = 10}
 print(veggies.apples)  -- prints: 4

And to make things worse, tables can contain tables: 

 stuff = {counts, veggies}
 print(stuff[2].potatoes) -- prints: 10

or even stuff like functions: 

 stuff.func = function() 
     -- does nothing
     end

 for k,v in pairs(stuff) do 
     print (k,v)
 end

So, you see in that part here: 

 for i, v in ipairs(self.mydata) do
    if string.match(v, "score = 1", 1, true) then
         self:outlet(1, "list", v) 
    end
 end

You have one "v" which is expected to be a string in string.match(),
and another which is expected to be a table/array in self:outlet()!

This won't work, and the error message of Lua tells you, that "v" (the
values of self.mydata) is a table, so it won't work in string.match()

I hope this clears it up a bit.

Now for the fix: You can convert a (flat) list/array to a string with
table.concat(somelist, sep) where sep is the separator. If you use a
space for sep, you can use 

 string.match(table.concat(v, " "), "score = 1")

or a bit better:

 string.find(table.concat(v, " "), "score = 1", 1, true)

Better because string.find doesn't try to build and return a string,
which you wouldn't be interested in anyhow.

Ciao
-- 
 Frank Barknecht                                     _ ______footils.org__
-------------- next part --------------
local NAME_OF_CLASS = "rob2"
local M = pd.Class:new():register(NAME_OF_CLASS)

function M:initialize(name, args)
    self.outlets = 2
    self.inlets = 1
    self.mydata = {} 
    return true
end

-- "insert [list]" into 1st inlet:
function M:in_1_insert(list)
    table.insert(self.mydata, list) 
end

-- what to do on "scores" into 1st inlet:
function M:in_1_scores()
for i, v in ipairs(self.mydata) do 
    if string.find(table.concat(v, " "), "score = 1", 1, true) then 
        self:outlet(1, "foo", v) end 
    end 
end

-- what to do on "print" into 1st inlet:
function M:in_1_print()
    for k,v in pairs(self.mydata) do
        pd.post(k .. ": " .. table.concat(self.mydata[k], " "))
    end
end

-- what to do on "reset" into 1st inlet:
function M:in_1_reset()
    self.mydata = {}
end


More information about the Pd-list mailing list