xml pull parser

classic Classic list List threaded Threaded
21 messages Options
12
Reply | Threaded
Open this post in threaded view
|

xml pull parser

Petite Abeille
Hello,

Here is yet another XML pull parser of sort. Nothing fancy. Just enumerate through all the tags.

Usage example:

local anInputStream = LUXMLInputStream.new( aContent )

while ( true ) do
local aType, aContent, aName, someAttributes = anInputStream.read()

        if ( aType == nil ) then
                break
        elseif ( aType == LUXMLInputStream.Text ) then
                print( aType, aContent )
        elseif ( someAttributes ~= nil ) then
print( aType, aName, someAttributes.keys().sort().toString() )
        else
                print( aType, aName )
        end
end

Each call to the read() method returns 4 values:

- The type of the tag (either Tag, EndTag, Text or nil)
- The tag content (either the tag itself or the text)
- The tag name if any
- The tag attributes if any

Here is an output sample of the above code for http://www.lua.org/

1       HTML
1       HEAD
1       TITLE
3       The Programming Language Lua
2       TITLE
1       LINK    { "HREF", "REL", "TYPE" }
1       META    { "CONTENT", "NAME" }
1       META    { "CONTENT", "NAME" }
2       HEAD
1       BODY
1       HR
1       CENTER
1       H1
1       IMG     { "ALT", "SRC" }

http://dev.alt.textdrive.com/file/lu/LUXMLInputStream.lua

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Adam D. Moss
Hi!

This:
                aString = string.gsub( aString, "&lt;", "<" )
                aString = string.gsub( aString, "&gt;", ">" )
                aString = string.gsub( aString, "&amp;", "&" )
                aString = string.gsub( aString, "&apos;", "'" )
                aString = string.gsub( aString, "&quot;", "\"" )
... isn't safe against stuff like &amp;apos;
The correction is fairly obvious. :)

Regards,
--Adam
--
Adam D. Moss   -   [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille

On Mar 21, 2005, at 12:08, Adam D. Moss wrote:

... isn't safe against stuff like &amp;apos;

Oooops... my brain freeze when confronted with anything remotely related to angle brackets :P

http://www.eod.com/devil/archive/xml.html

The correction is fairly obvious. :)

I added an additional string.gsub( aString, "&amp;", "&" ) before decoding the other entities. Is it what you had in mind?

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Adam D. Moss
PA wrote:
The correction is fairly obvious. :)

I added an additional string.gsub( aString, "&amp;", "&" ) before decoding the other entities. Is it what you had in mind?

Well... no. :)

I meant that this:
                aString = string.gsub( aString, "&lt;", "<" )
                aString = string.gsub( aString, "&gt;", ">" )
                aString = string.gsub( aString, "&amp;", "&" )
                aString = string.gsub( aString, "&apos;", "'" )
                aString = string.gsub( aString, "&quot;", "\"" )
Should become this:
                aString = string.gsub( aString, "&lt;", "<" )
                aString = string.gsub( aString, "&gt;", ">" )
                aString = string.gsub( aString, "&apos;", "'" )
                aString = string.gsub( aString, "&quot;", "\"" )
                aString = string.gsub( aString, "&amp;", "&" )

Actually I just noticed that you have a similar problem with
&#XXX; entities which can't be solved with merely re-ordering
the substitutions.  But you can fold every &*; case into the
aFunction and be happy (likely somewhat faster too).

--Adam
--
Adam D. Moss   -   [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Javier Guerra Giraldez
In reply to this post by Petite Abeille
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

PA wrote:
> 
> On Mar 21, 2005, at 12:08, Adam D. Moss wrote:
> 
>> ... isn't safe against stuff like &amp;apos; The correction is 
>> fairly obvious. :)
> 
> I added an additional string.gsub( aString, "&amp;", "&" ) before 
> decoding the other entities. Is it what you had in mind?

i guess the string.gsub( aString, "&amp;", "&" ) should be the last
replacement.


in your original example:

while ( true ) do
        local aType, aContent, aName, someAttributes = anInputStream.read()

        if ( aType == nil ) then
                break
....


could be a bit more 'lua like':

for aType, aContent, aName, someAttributes = anInputStream.read()
	if ( aType == ....
.....
.....
end


it's a very small point, but i mention it, because in general i've seen
your code is well structured, but very 'unlua', making it less efficient
and less useful to others

You're writing code at an incredible rate, but at the same time you're
creating your own style and drifting away from the others.  I don't want
to reignite the discussion about OOP vs FP vs anything else; just
remember that not everything has to be an object.

i think it was you (hope i'm not mixing memories) who said that you're
fairly new to Lua, and that you liked to learn a language by
reimplementing on it what you already know.  It's obvious that by now
you have a more than average hold of the Lua language itself; why don't
you try to restructure some of your work more closely to the 'lua way' ?
 you'll find that you won't have to fight against the language anymore!

OTOH, maybe some people here like your style... if that's so, i should
shut up.

- --
Javier
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCPrzWsIoGnxsRK/ERAo0pAJwICTvp5iiHuQ8DxVZ4C73ve5NHKgCeL80N
MTUCmDd/qF0L0HqTDN2gABM=
=k4/j
-----END PGP SIGNATURE-----

Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille
In reply to this post by Adam D. Moss

On Mar 21, 2005, at 13:22, Adam D. Moss wrote:

Actually I just noticed that you have a similar problem with
&#XXX; entities which can't be solved with merely re-ordering
the substitutions.  But you can fold every &*; case into the
aFunction and be happy (likely somewhat faster too).

Well... not sure about happiness... but is the current concoction:

-- class method to decode a given string
thisClass.decode = function( aString )
        if ( aString ~= nil ) then
                local aFunction = function( aValue )
                                if ( aValue == "lt" ) then
                                        return "<"
                                elseif ( aValue == "gt" ) then
                                        return ">"
                                elseif ( aValue == "apos" ) then
                                        return "'"
                                elseif ( aValue == "quot" ) then
                                        return "\""
elseif ( string.sub( aValue, 1, 1 ) == "#" ) then local aNumber = tonumber( string.sub( aValue, 2 ) )

if ( ( aNumber ~= nil ) and ( aNumber > 0 ) and ( aNumber < 255 ) ) then return string.char( aNumber )
                                        end
                                end

                                return string.format( "&%s;", aValue )
                      end

                aString = string.gsub( aString, "&(%w+);", aFunction )
                aString = string.gsub( aString, "&amp;", "&" )
        end

        return aString
end

Alternatively, somebody, somewhere, somehow must have written this a dozen time already. Is there not a little code sample somewhere to show how to decode an XML string in Lua? Sigh...

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille
In reply to this post by Javier Guerra Giraldez

On Mar 21, 2005, at 13:23, Javier Guerra Giraldez wrote:

i guess the string.gsub( aString, "&amp;", "&" ) should be the last
replacement.

Getting there. Little by little :P

could be a bit more 'lua like':

I would love to use a for loop.

But this doesn't compile:

for aType, aContent, aName, someAttributes = anInputStream.read()

lua: TestXML.lua:56: `in' expected near `='

What would be the proper syntax then?

One way or another, I need to read more about this fabled generic for loop.

it's a very small point, but i mention it, because in general i've seen
your code is well structured, but very 'unlua', making it less efficient
and less useful to others

First... make it work... then... perhaps... make it work well...

You're writing code at an incredible rate, but at the same time you're
creating your own style and drifting away from the others.

This is not unheard of.

I don't want to reignite the discussion about OOP vs FP vs anything else; just
remember that not everything has to be an object.

Sure. Same applies for random piles of functions.

But frankly speaking, I haven't seen a great deal of reuse in Lua. At all. Quite a let down, if you ask me. And here I am writing a dumb little function to decode XML strings. Duh.

i think it was you (hope i'm not mixing memories) who said that you're
fairly new to Lua, and that you liked to learn a language by
reimplementing on it what you already know.

Guilty at charge.

 It's obvious that by now
you have a more than average hold of the Lua language itself; why don't
you try to restructure some of your work more closely to the 'lua way' ?

Because I'm not sure what this fabled "Lua way" is. Concrete suggestion warmly welcome :)

 you'll find that you won't have to fight against the language anymore!

I'm not fighting it. Au contraire, I'm subverting it. Resistance is futile. You will be assimilated ;)

OTOH, maybe some people here like your style... if that's so, i should
shut up.

Stylistic issues aside, I would love to incorporate more Lua'ism in my code. Just not sure what those are. Palpable suggestions very much welcome :)

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Javier Guerra Giraldez
In reply to this post by Petite Abeille
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

PA wrote:
> Alternatively, somebody, somewhere, somehow must have written this a
> dozen time already. Is there not a little code sample somewhere to show
> how to decode an XML string in Lua? Sigh...

nontested:

reptable = {
	lt = "<",
	gt = ">",
	apos = "'",
	quot = '"',
	amp = "&",
}

outstring = string.gsub (instring, "&([^;]*);", function (s)
	local rep = reptable[s]
	if rep then return rep end

	if sub (s, 1,1) == "#" then
		local n = tonumber ( string.sub( s, 2 ) )
		if ( ( n ~= nil ) and ( n > 0 ) and ( n < 255 ) ) then
			return string.char( n )
		end
	end
end
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCPsgtsIoGnxsRK/ERAqezAKCc9QcAISH780dk0BOHkuLVKKqybACgkdBi
3RrO8soOT5Iq9kPpu7uNeuU=
=adAj
-----END PGP SIGNATURE-----

Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Rici Lake-2
In reply to this post by Petite Abeille

On 21-Mar-05, at 7:54 AM, PA wrote:

Alternatively, somebody, somewhere, somehow must have written this a dozen time already. Is there not a little code sample somewhere to show how to decode an XML string in Lua? Sigh...

Probably. Although the issues are subtle. I don't address any of them here; this is simply a working reimplementation of the same transformation.

do
  local ents = {
    lt = '<',
    gt = '>',
    amp = '&',
    quot = '"',
    apos = "'"
  }

  local maxutf8 = tonumber('10FFFF', 16)

  local function entity2char(hash, str)
    if hash == '#' then
      -- turn hex into c-style hex
      local utfcode = tonumber((string.gsub(str, '^x', '0x')))
      if utfcode and utfcode < 256 then
         return string.char(utfcode)
      end
    elseif ents[str] then
      return ents[str]
    end
    return '&'..hash..str..';'
  end

  function decode(str)
    return str and string.gsub(str, '&(#?)(%w+);', entity2char)
  end
end

--- some tests
=decode '&amp;apos; is how you write &apos;'
=decode '&#38;amp; is an ampersand.'
=decode '&quot;I said &apos;Stop right there!&apos; &amp; I &lt;strong&gt;meant it!&lt;/strong&gt;&quot; the webmaster shouted, htmlifying instinctively'
-- Codes and noncodes
=decode 'Some invalid numeric escapes include &#7b2;, &#x24g;'
=decode "Take out the &garbage;! Don't leave it for ma&#xf1;ana! The sooner the &#x3b2;!"
-- What was I saying about iso-8859-1?
=decode 'ma&#xf1;ana or ma&#xc3;&#xb1;ana?'

-->

> =decode '&amp;apos; is how you write &apos;'
&apos; is how you write '
> =decode '&#38;amp; is an ampersand.'
&amp; is an ampersand.
> =decode '&quot;I said &apos;Stop right there!&apos; &amp; I &lt;strong&gt;meant it!&lt;/strong&gt;&quot; the webmaster shouted, htmlifying instinctively' "I said 'Stop right there!' & I <strong>meant it!</strong>" the webmaster shouted, htmlifying instinctively
> -- Codes and noncodes
> =decode 'Some invalid numeric escapes include &#7b2;, &#x24g;'
Some invalid numeric escapes include &#7b2;, &#x24g;
> =decode "Take out the &garbage;! Don't leave it for ma&#xf1;ana! The sooner the &#x3b2;!" Take out the &garbage;! Don't leave it for ma?ana! The sooner the &#x3b2;!
> -- What was I saying about iso-8859-1?
> =decode 'ma&#xf1;ana or ma&#xc3;&#xb1;ana?'
ma?ana or mañana?



Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Adrian Sietsma
Alternatively, somebody, somewhere, somehow must have written this a dozen time already. Is there not a little code sample somewhere to show how to decode an XML string in Lua? Sigh...

decoding simple xml = easy
handling the full range of xml syntax (entities, i18n, etc) is a
non-trivial task.

but i have to agree - an xml parser is a great learning exercise.

i have written 2 xml parsers in lua, both sax-type (callback) -
the first one with a c lib, the second one pure lua : the devil is in
the detail :)

(and no, i couldn't make it handle all cases with gsub)

Adrian


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille
In reply to this post by Rici Lake-2

On Mar 21, 2005, at 14:40, Rici Lake wrote:

Probably. Although the issues are subtle. I don't address any of them here; this is simply a working reimplementation of the same transformation.

Excellent! Thanks :)

Now the infamous gsub() function looks something like this:

charWithEntity = function( aSymbol, anEntity )
        if ( aSymbol == "#" ) then
local aCode = tonumber( ( string.gsub( anEntity, "^x", "0x" ) ) )

                if ( ( aCode ~= nil ) and ( aCode < 256 ) ) then
                        return string.char( aCode )
                end
        else
                local aValue = thisClass.entities().get( anEntity )

                if ( aValue ~= nil ) then
                        return aValue
                end
        end

        return string.format( "&%s%s;", aSymbol, anEntity )
end

http://dev.alt.textdrive.com/file/lu/LUXMLInputStream.lua

Is that Lua-esque enough? :))

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Javier Guerra Giraldez
In reply to this post by Petite Abeille
Quoting PA <[hidden email]>:

> lua: TestXML.lua:56: `in' expected near `='
> 
> What would be the proper syntax then?

my mistake, use 'in' instead of '=' (that's a mistake i repeat all the time)

> One way or another, I need to read more about this fabled generic for 
> loop.

you won't regret it.  iterators are a great way to traverse anything, specially
when done with coroutines (i think they're called 'generators' in that case?)

> > it's a very small point, but i mention it, because in general i've seen
> > your code is well structured, but very 'unlua', making it less 
> > efficient
> > and less useful to others
> 
> First... make it work... then... perhaps... make it work well...

it's not an optimization, it's more a mindframe thing.  in low level languages
you mostly choose your algorithms, but in higher level it's important to see
what the language offers you and follow the path of least resistance.

.... unless you want a good fight! ;-)

> >   I don't want to reignite the discussion about OOP vs FP vs anything 
> > else; just
> > remember that not everything has to be an object.
> 
> Sure. Same applies for random piles of functions.

yep.  and there are lots of things done best with an object (i think a XML pull
parser IS one of them)

personally, i do use object-like constructs in Lua all the time.  i like the
obj:func() form, and since i seldom use any inheritance, i haven't find the need
for a full OOP scheme in Lua.

Even in C++, the data-managing parts of my programs are very shallow class
hierarchies.  the GUI parts do get deep... but mostly because of the framework i
happen to use.

> But frankly speaking, I haven't seen a great deal of reuse in Lua. At 
> all. Quite a let down, if you ask me. And here I am writing a dumb 
> little function to decode XML strings. Duh.

very true.  i think code reuse is more at a module level than at object or
function level.

and at the copy-paste level, of course!

> Because I'm not sure what this fabled "Lua way" is. Concrete suggestion 
> warmly welcome :)

rici's example is a nice one (much better than mine!)
concrete 'luaisms' used on his decoder:

- wrap a small module on a do...end block, so a single function is exported
(decode()), but it has access to local vars (ents[] and maxutf8) and functions
(entity2char())
- use a lookup table
- use a standard function (gsub()), and give it another function as a parameter
- use 'str and gsub(....)' idiom to check parameters before using them

>......
> local aValue = thisClass.entities().get( anEntity ) 
>........
>Is that Lua-esque enough? :)) 

is that line a lookup table? if so, why not use tables???

------
Javier

Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille

On Mar 21, 2005, at 17:13, Javier Guerra wrote:

What would be the proper syntax then?

my mistake, use 'in' instead of '=' (that's a mistake i repeat all the time)

Thanks :)

One way or another, I need to read more about this fabled generic for
loop.

you won't regret it. iterators are a great way to traverse anything, specially when done with coroutines (i think they're called 'generators' in that case?)

Yes. I see. I remember now why I don't use the generic for loop. It requires a function. That function is then invoked for each iteration by the loop itself. In my case, anInputStream.read() return the results themselves. So to use the generic for loop I would need the rewrite my loop like this:

for aType, aContent, aName, someAttributes in anInputStream.read

Note the lack of parenthesis. This is a gratuitous deviation from how I invoked functions: always use parenthesizes.

On the other hand, I would gladly use the generic loop if I could write it like this:

for aType, aContent, aName, someAttributes in anInputStream.read()

Note the explicit parenthesis. I favor consistency over magic :)

it's not an optimization, it's more a mindframe thing. in low level languages you mostly choose your algorithms, but in higher level it's important to see
what the language offers you and follow the path of least resistance.

Agree. That said, Lua itself allow many variation on the same theme. Which you may view as either beneficial or detrimental. I think too many variation in how to express the exact same thing is a liability overall. How many "for" construct does a language needs? One seems to be plenty enough.

.... unless you want a good fight! ;-)

I'm careful avoiding any such fight :)

yep. and there are lots of things done best with an object (i think a XML pull
parser IS one of them)

personally, i do use object-like constructs in Lua all the time. i like the
obj:func() form,

I found the colon notation too much of a good thing and I'm not using it at all. I favor the plain dot instead. That way, there is no additional confusion: dot or colon. The dot it is always :)

 and since i seldom use any inheritance, i haven't find the need
for a full OOP scheme in Lua.

Well, even my LU concoction is far from a full blown OO system. It simply boil down to a packaging system to bundle named functions in tables. All in all, its main benefit is to provide an organizational principal. The OO benefit, as I see it, being mostly polyphormism instead of hard core inheritance.

Even in C++, the data-managing parts of my programs are very shallow class hierarchies. the GUI parts do get deep... but mostly because of the framework i
happen to use.

But frankly speaking, I haven't seen a great deal of reuse in Lua. At
all. Quite a let down, if you ask me. And here I am writing a dumb
little function to decode XML strings. Duh.

very true. i think code reuse is more at a module level than at object or
function level.

Well, my so called "objects" are just plain table of functions. It's more a packaging scheme than anything else.

and at the copy-paste level, of course!

Oh, my... :P

Because I'm not sure what this fabled "Lua way" is. Concrete suggestion
warmly welcome :)

rici's example is a nice one (much better than mine!)
concrete 'luaisms' used on his decoder:

- wrap a small module on a do...end block, so a single function is exported (decode()), but it has access to local vars (ents[] and maxutf8) and functions
(entity2char())
- use a lookup table
- use a standard function (gsub()), and give it another function as a parameter
- use 'str and gsub(....)' idiom to check parameters before using them

Yes. I pretty much follow such idioms.

For example, I use anonymous functions quite extensively. As an illustration, in my HTTP server, a service accepts an anonymous function which acts as an authenticator, by returning true or false for a given context:

local anAuthenticator = function( aContext )
if ( aContext.request().headers().get( "authorization" ) ~= nil ) then
	    return true
    end

    return false
end

http://dev.alt.textdrive.com/file/LW/Test.lua

Such function is in turn used when the service has to decide to give access to a given resource:

if ( ( anAuthenticator == nil ) or ( anAuthenticator( aContext ) == true ) ) then
    this[ aMethod ]( aTask, aContext )
else
local aChallenge = string.format( "Basic realm=\"%s\"", aContext.session().realm() )

    aResponse.headers().put( "www-authenticate", aChallenge )
    aResponse.writeStatus( 401 )
end

http://dev.alt.textdrive.com/file/LW/LWService.lua

......
local aValue = thisClass.entities().get( anEntity )
........
Is that Lua-esque enough? :))

is that line a lookup table?

Yes.

if so, why not use tables???

I do. Indirectly. I have a wrapper module/package/library/object/whatever around Lua tables which provides commonly used functionalities:

http://dev.alt.textdrive.com/file/lu/LUMap.lua

Getting to this lookup table involves a couple of steps:

(1) local aBundle = LUBundle.bundleWithName( "LUXMLInputStream" )
(2) local aFile = LUFile.new( aBundle.path(), "LUXMLInputStream.txt" )
(3) cvars.entities = LUMap.new().load( aFile )

(1) locate where the code is
(2) get the relative path to the specific resource
(3) load the table

By itself, the underlying Lua code is not much, but I use such functionality all over the place. And I for once don't enjoy copy & paste programming much :P So the code is centralized and reused if possible :)

http://dev.alt.textdrive.com/file/lu/LUBundle.lua
http://dev.alt.textdrive.com/file/lu/LUFile.lua

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Rici Lake-2

On 21-Mar-05, at 12:12 PM, PA wrote:

Note the lack of parenthesis. This is a gratuitous deviation from how I invoked functions: always use parenthesizes.

oh, so you would want to write:

   map(table, increment())

rather than the obviously-correct

   map(table, increment)

How about

   sort(table, compare())

instead of

   sort(table, compare)

Are those gratuitous deviations? Or simply a logical way of saying which function to use? Which is exactly the same thing as the for statement.





Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Aaron Brown-2
In reply to this post by Petite Abeille
PA wrote:

> This is a gratuitous deviation from how I invoked
> functions: always use parenthesizes.

But you don't want to invoke the function here, you want to
give it to Lua so that Lua can invoke it the appropriate
number of times, with the appropriate arguments.

This is indeed different from, for instance, C.  In C, you
can write a bit of code ("i++", for instance) to control
your loop variable(s) and put that code right in the third
for-expression, where it will get executed once every
iteration.  In Lua, you write a bit of code to control your
loop variable(s) and put it in a function, and then hand
that function itself to Lua.  The advantage of this is that
it allows the relevant code to be generated at runtime
(e.g., by using a closure).

As Rici pointed out, the appropriate thing to compare this
to is higher-order functions such as table.sort.

-- 
Aaron


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille
In reply to this post by Rici Lake-2

On Mar 21, 2005, at 18:34, Rici Lake wrote:

Are those gratuitous deviations?

Nope. They are a way to pass a function as a parameter.

 Or simply a logical way of saying which function to use?

Yes. To pass a function as a parameter.

Which is exactly the same thing as the for statement.

No. At least not for me. I don 't see any function I'm passing a parameter to. This is too confusing for me. I therefore try to avoid it.

At first glance there are 4 different ways to write a "for" loop ( "=", "in", "in ipairs()", "in pairs()" ). That's 3 too many for me :}

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Petite Abeille

On Mar 21, 2005, at 20:15, PA wrote:

At first glance there are 4 different ways to write a "for" loop ( "=", "in", "in ipairs()", "in pairs()" ).

Let make that 5. There is a "in next()" as well. Sigh...

Cheers

--
PA, Onnay Equitursay
http://alt.textdrive.com/


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Rici Lake-2
In reply to this post by Petite Abeille

On 21-Mar-05, at 2:15 PM, PA wrote:

No. At least not for me. I don 't see any function I'm passing a parameter to. This is too confusing for me. I therefore try to avoid it.

Let me try to make it easier then.

  for <vars> in method, object do

Arguably, this would have been better written with 'of' instead of ',' but the ',' allows for the use of computed messages.

The object method is invoked to produce the next element of the loop. It is, therefore, an iterator function being specified to the for loop. It takes a single argument, beyond the self argument, which is the iteration key; it returns the next iteration key and whatever values might be associated with it, if any. These values, starting with the iteration key, are bound to the local variables.

At first glance there are 4 different ways to write a "for" loop ( "=", "in", "in ipairs()", "in pairs()" ). That's 3 too many for me :}

Just two. However, it is common to use functions to create the message, as described above.

So, for example, pairs(t) is no more complicated than this:

function pairs(t) return next, t end

and you could, if you wished, just write that:

for k, v in next, t do ... end



By the way, I lied a little bit. You can actually specify the first iteration-key argument to the iterator function as well, but by convention iterator functions use nil as the "start of iteration" marker.


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Aaron Brown-2
In reply to this post by Petite Abeille
PA wrote:

>> At first glance there are 4 different ways to write a
>> "for" loop ( "=", "in", "in ipairs()", "in pairs()" ).
>
> Let make that 5. There is a "in next()" as well. Sigh...

At second glance, you can think of there being three:  A
numeric one that just iterates through different numbers:

  for i = start, end do

and two "foreach"-type loops that iterate through elements
of a table:

  for k, v in pairs(t) do
  for i, v in ipairs(t) do

(Which one you use depends on how you've populated the
table.)

It's well worth the trouble to wrap your head around the
generic 'for' so that you can write your own iterators or do
hacks with the stock ones, but until you do, just think of
the other types of 'for' as being power-user stuff that you
can safely ignore -- other languages get by with much less
powerful loop constructs.  (I admit that this advice is less
helpful when reading someone else's code rather than writing
your own.)

By the way (you may already know this), the

  for k, v in t do

syntax is just a deprecated way of writing

  for k, v in pairs(t) do

-- 
Aaron

"PHP combines the orthogonality of sh with the elegance
of <font color=ad0000> Fatal error: Cannot redeclare
quuxitate() (previously declared in -:4) in - on line 6
</font>


Reply | Threaded
Open this post in threaded view
|

Re: xml pull parser

Aaron Brown-2
In reply to this post by Rici Lake-2
Rici wrote:

> By the way, I lied a little bit. You can actually specify
> the first iteration-key argument to the iterator function
> as well, but by convention iterator functions use nil as
> the "start of iteration" marker.

Here's an example that makes use of something other than
nil.  The following code iterates through all two-member
subsets of the Beatles; the trick is that the inner loop
starts partway through the table.

Beatles = {
  John = "rhythm",
  Paul = "bass",
  George = "lead",
  Ringo = "drums"}

for p1, i1 in next, Beatles, nil do
  for p2, i2 in next, Beatles, p1 do
    print(p1, i1, p2, i2)
  end -- for
end -- for

-- 
Aaron

"PHP combines the orthogonality of sh with the elegance
of <font color=ad0000> Fatal error: Cannot redeclare
quuxitate() (previously declared in -:4) in - on line 6
</font>


12