[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: The relevant_lines package
- From: Steve Litt <slitt@...>
- Date: Fri, 28 Jan 2011 23:15:33 -0500
On Friday 28 January 2011 17:33:16 Petite Abeille wrote:
> On Jan 28, 2011, at 9:40 PM, Steve Litt wrote:
> > I hope you enjoy it, and please be gentle when you tell me all the things
> > I did wrong with it. :-)
>
> Nothing fundamentally wrong per say, but... just wondering... isn't it a
> bit overkill? :))
Might be. I'll have to do timing tests to see whether it saps performance.
As far as programming overkill, no. The application programmer just pubs a
filename and maybe a 4 line callback function in a table, passes it on in, and
gets back only the needed lines, while line numbers stay intact for error
messages.
>
> My 2¢...
>
> > function relevant_lines(tab)
>
> Why a table as a parameter? What's wrong with explicit parameters? E.g.:
>
> relevant_lines( aFile, is_relevant, tweak )
That's how I did it the first time. Trouble is, I can't guess what logic the
programmer might use in selecting valid lines. There could be fascinating
break logic, or, who knows. Me -- I'd probably try to steer clear from putting
actual application logic in the callbacks, but by putting all info in the
table this tool can be adapted in any imaginable way, and probably some
unimaginable ones too.
>
> > if tab == nil then .. io.stderr:write... os.exit...
>
> Look into assert(), e.g.:
>
> assert( function() return type( tab ) == 'table' end(), 'Expected a table,
> got ' .. type( tab ) .. ' instead' )
Good idea. I forgot about the concat operator.
>
> http://www.lua.org/manual/5.1/manual.html#pdf-assert
>
> > if .. elseif... elseif... else
>
> A common idiom if you have many such simple condition is to use a table
> instead, e.g.:
>
> -- define a mapping between type and function
> aMap = { string = function( aValue ) return io.open( aValue , 'rb' ), ... }
> -- lookup a function
> aFunction = aMap[ type( aValue ) ]
> -- invoke it
> aFunction( aValue )
>
> > elseif type(tab.file) == "userdata" then
>
> Perhaps try io.type(obj) == 'file' instead
Thanks! I was looking for something like that. That definitely goes in the
next time I modifiy this thing.
>
> http://www.lua.org/manual/5.1/manual.html#pdf-io.type
>
> > if not tab.is_relevant then
>
> Another handy idiom to provide default values:
>
> tab.is_relevant = tab.is_relevant or function() ... end
>
> > tab.this_line_text = ...
>
> What about simply passing the value directly to your is_relevant()
> function? Is that shared table really adding anything?
It adds a lot of flexibility. You're guaranteed that absolutely anything is
available to is_relevant() and tweak(). They can communicate with each other.
They can even leave Easter Eggs for the program after all lines are iterated
(counts, totals, etc). Like I said, I probably wouldn't use it that way, but
it's available.
>
> All in all, wouldn't it be clearer to simply say what you mean? E.g.:
>
> for aLine in aFile:lines() do
> if Accept( aLine ) then
> Transform( aLine )
> end
> end
Yes and no. I assume here you mean instead of the relevant_lines() iterator
maker. It's obviously simpler on the face of it, but maybe not so much when
you have to add "skip all blank lines and lines beginning with %s*#" to
Accept(). The point of it is to blow off obviously bad lines very early so you
needn't even consider them in Accept().
Also, I think my main point in putting in tweak() (and therefore tweak() may
be a very bad name for it) was to facilitate more complex break logic when
rejecting lines from further scrutiny. I haven't thought it all through yet.
Thanks. You've given me a lot to think about.
SteveT
Steve Litt
Recession Relief Package
http://www.recession-relief.US
Twitter: http://www.twitter.com/stevelitt