For discussion, semantic construct

castironpi at gmail.com castironpi at gmail.com
Wed Feb 20 20:48:55 EST 2008


Here is a construction for passing parameters.  I include the Python
idea, a C/C++ equivalent, and write a little about it.  (Blech.)

It is a little obscure, and my use cases are not as good as yours.  So
say yours.

The presentation is structured: problem, solution.

Problem:

Sometimes you need to signal a particular meaning of a parameter.

These examples are from my library.

uniform( node.toprettyxml, indent, newl, encoding )

It is in a proxy class for the xmlnode class; outer modules call
node.dump(), and can specify these parameters.

@guibind( listbox, "<Key-Enter>" )
def onenter( event ):
   <processing>

It is a time-saving function to keep my train of thought up to speed
when I'm writing, one of the reasons Python suits me.

@execute_func( start_new_thread )
def anonproc():
   <processing>

It makes more sense (*subjective) to me to write "and execute the
'next thing' in a new thread", than to write the thing, and then go
back and say execute.  A lot more, in fact.  (*If it doesn't to you,
then ignore the application, and just consider the construct
independently.)  Like the prior, it maintains the speed and level of
the time that I'm spending on code.

Last but not least,

class Workbook( EasyXML ):
   descripts= Descp( "bold", req= "1" ), Descp( "text" )

It keeps a list of constructor descriptions, which the base class
constructor uses, roughly stated, as domain knowledge, that is further
information, in parsing constructor parameters.

In 'guibind', sometimes it makes sense to include the control that is
being bound in a parameter, and sometimes it distinctly doesn't.  In
'uniform', the next layer may or may not specify a particular
argument, but to the end of abstraction/encapsulation, middle layers
do not specify default values for parameters.  In 'execute_func', the
specified function may occur in varying places in the argument list,
including as a keyword-only argument.  In 'Descp', one descriptor is
allowed to

I am suggesting that these examples have a common thread, and there is
an elegant resolution.  It may not even be 'recipie' material, let
alone 'std. lib.' material, but it is interesting, and I want to know
what others think about the merits and demerits of it.  Where is it
strong and weak?

The thread they share is the meaning of flags.

In 'uniform', the outer user can call a target function in a uniform
way; regardless of what decisions the calling code makes, the actual
call can still only occur once in it.  If outer code decides to
specify one parameter in one branch, and another in another, it can
merely initialize both to a special flag, and non-defaults will only
be specified if that flag is replaced.  The flag is a value that is
guarateed to be unique, regardless of what semantic meaning the
parameter has, though pretty only applicable in cases where the
default is not None, as well as somewhat trivialized if the default is
the flag too.  It is most useful where default arguments are
complicated, or their use is contrary to abstraction.

In 'guibind', the flag value allows the user to specify his or her own
calling signature, and placement of the variable of the control.  Is
it the first parameter?  The last?  Always a specific name?  These
questions are left for the outer user to answer, varying on a case by
case basis.

In execute_func, the function is the same.  The meaning that the
function has in the call to the tertiary function is open to the outer
user to decide.

And in 'Descp', the argument that sets the content of the XML node, as
opposed to child nodes of it, as well as whether it's required or not,
is open to the outer user's discretion.

The idiom looks a little funny (*subjective).  Who knows why?, but
here it is, in an abstracted case from the above.

for ar in ars:
   if ar is SpecialFlag:
      replace it with meaning
for kwar, kwarval in kwars.items():
   if kwarval is SpecialFlag:
      replace it with meaning

SpecialFlag itself has a pretty simple definition.

SpecialFlag= object()

It is never an int, so never confused with an int, nor ever a special
case of int, such as MAX_INT or -1.  It is never a string either, so
the user can pass any value -or- -this- to outside functions as a
parameter.  It is a signal that always stays out of the way.

Here are the same examples with SpecialFlag present.  As the names
have meaning too, and I haven't (as yet!) completed the abstraction
abstraction, the flag is a different object with a different name in
these cases.

uniform( node.toprettyxml, DefaultA, '\n', DefaultA )
uniform( node.toprettyxml, '\t', '', DefaultA )
uniform( node.toprettyxml, ' ', DefaultA, 'UTF-8'  )

The signatures are identical: three parameters, no keywords.  Prior to
this invocation, set indent, newl, encoding= DefaultA, DefaultA,
DefaultA, and then only call node.toprettyxml once.

uniform( node.toprettyxml, indent, newl, encoding )

And the parameters have the right meaning, whether you specify them or
not.

@guibind( listbox, "<Key-Enter>", EventN, ControlN )
@guibind( listbox, "<Key-Enter>", ControlN )
@guibind( listbox, "<Key-Enter>", EventN, cont= ControlN )

Then the function specified has the right parameters, although at the
extra cost of rearranging argument and keyword argument lists, once at
each call.

@execute_func( start_new_thread, func= FuncA )
@execute_func( Thread, target= FuncA )
@execute_func( urlretrieve, 'what.com', reporthook= FuncA )

In the two cases of the wrappers, they offer the interesting property
that the function name after execution contains the return value from
the calls.  The function can be accessed in a different way, and
that's somewhat open.

class Workbook( EasyXML ):
   descripts= Descp( "bold", req= "1" ), Descp( "text", DataN )

So instantiating a workbook is a snap.

book= Workbook( bold= False, text= "Bus hours and server hours per day
per week" )

And the constructor of Workbook, which simply defaults to that of
EasyXML, checks the class definition of 'self' for the descriptor
list, and reads that 'text' now refers to a string that will merely be
the content of a node, and bold refers to a node attribute.

I'm sure there are other ways to do this.  This is one of them; how
does it measure up?



More information about the Python-list mailing list