yo yo

the more it
seems to me that the name argument of most components in PyConstruct
is misplaced.  It should not be part of the construct::


the name has several technical purposes (struct naming, context naming,
...),
but the most important imho is auto-documentation, as in

x = Struct("ethernet_header", ...)
x
<Struct('ethernet_header')>

  foo = Struct(
       ("bar", UBInt32),
       ("baz", UBInt16),
   )


how would this syntax extend to repeaters and other wrappers?

element = Struct(
   ...
)

foo = Struct(
   ("bar", StrictRepeater(10, element)
)

this makes "element" not a self-contained unit. it's like an unbound method,
i.e., it's missing something in order to work right.

* Some names are unused (e.g. inside Sequence or IfThenElse).


you can use None for that purpose exactly, although i would give them a
meaningful
name that would serve for documentation -- imagine a Switch with lots of
cases --
it would be nice to have a name for each.

besides, Switch() and Select() may be augmented to include the name of the
chosen case (to make the resulting object easier to work with).

* The name of the outermost Struct is repeated twice.


true, but there are many cases where we use
foo = Struct("foo_header")

so that when we use foo in another struct, i.e.
boo = Struct("boo", foo)

the field is named "foo_header" rather than "foo"

* A name can be burrowed deep inside adpters and its effect on some
enclosing Struct can be unobvious and magic.

...

Unfortunately, this doesn't generalize to Sequence embedding, so we
get only half a win here.


i added a FLAG_EMBED to the library, which will make it to the final
release,
so Embed() will no longer change the name of the construct... although when
you embed,
you'll lose the name of the enclosing construct anyway.
Embed() is an API, but the magic it performs inside is implementation
specific.

* Rename is a kludge.  Having the name as part of a component complicates
reuse.


true, but if you have
foo = Struct("foo")

why would you want to call it boo?
the only time i'm using Rename is for things like:

section_entry = Struct("section_entry")
section_table = Rename("section_table",
   StrictRepeater(10, section_entry)
)

i.e., when section_entry is useful on its own, but i'm creating an array of
entries,
which should be called section_table instead of section_entry.

all in all, Rename is not so commonly used to be a factor in the design.

* Most "macro functions" take just the name as an argument, needlessly
complicating them.


i wouldn't call that complicating. it's just the way python performs
variable binding.
it's true that the primitive fields can be singletons, but it's not true for
the general case,
and "Special cases aren't special enough to break the rules." :)

besides, although most fields take only a name, most other macro functions
wrap
a subcon (If, Enum, IfThenElse, PascalString...), and may be conditional.

for example, see String() or UncompressedRows() at
http://sebulbasvn.googlecode.com/svn/trunk/construct/formats/graphics/bmp.py

What do you think?

nope :)


-tomer

On 12/29/06, Beni Cherniavsky <[EMAIL PROTECTED]> wrote:

The more I think about it (and re-read the tutorials), the more it
seems to me that the name argument of most components in PyConstruct
is misplaced.  It should not be part of the construct::

    foo = Struct("foo",
        UBInt32("bar"),
        UBInt16("baz")
    )

but part of the enclosing Struct.  The simplest syntax is ('name',
construct) tuples::

    foo = Struct(
        ("bar", UBInt32),
        ("baz", UBInt16),
    )

It's tempting to try using assignment syntax::

    foo = Struct(
        bar=UBInt32,
        baz=UBInt16,
    )

but that loses orders and envisionable hacks for recovering the order
are too fragile.  Forget it for now.

That would fix several things that stick out from the general elegance
of PyConstruct:

* Some names are unused (e.g. inside Sequence or IfThenElse).
* The name of the outermost Struct is repeated twice.
* A name can be burrowed deep inside adpters and its effect on some
enclosing Struct can be unobvious and magic.
* Rename is a kludge.  Having the name as part of a component complicates
reuse.
* Most "macro functions" take just the name as an argument, needlessly
complicating them.

With the name outside, many macro functions could simply be reusable
singletons::

  UBInt8 = FormatField(name, ">", "B")

but if you don't like that, you can keep them all as functions of no
arguments for consistency of use...

Another clever side effect is that Struct nesting vs. embedding can be
simply indicated by wrapping or not the inner Struct with a name
tuple::

    foo = Struct(
        Struct(
            ("bar", UBInt32),
        ),
        ("quux", Struct(
            ("baz", UBInt16),
        ),
    )
    # this gives `bar` and `quux.baz`

Unfortunately, this doesn't generalize to Sequence embedding, so we
get only half a win here.

If this indeed looks like an improvement, now (2.0) would be a good
time to make the change (I'm willing to help with the rewriting).
What do you think?

--
Beni Cherniavsky <[EMAIL PROTECTED]> (I read email only on weekends)

לענות