[24363] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 6552 Volume: 10

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Tue May 11 09:06:38 2004

Date: Tue, 11 May 2004 06:05:08 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Tue, 11 May 2004     Volume: 10 Number: 6552

Today's topics:
        ANNOUNCE: Initial release of OOPS - Object Oriented Per <muir@idiom.com>
    Re: Confused Newbie question: Decimal to IP (Monica Roman)
        Making array elements Unique <georgekinley@hotmail.com>
    Re: Making array elements Unique <thepoet_nospam@arcor.de>
    Re: Making array elements Unique (Anno Siegel)
    Re: Making array elements Unique <bernard.el-haginDODGE_THIS@lido-tech.net>
    Re: Making array elements Unique <nobull@mail.com>
    Re: Need example of module+cgi+data distribution <nomail.please@no.mail.com>
        Net::Telnet getting control  over root shell (Ramprasad A Padmanabhan)
    Re: Parse::RecDescent: special treatment for keywords (Anno Siegel)
    Re: Printing Array's content with carriage return (\n) <tadmc@augustmail.com>
    Re: Using match variables ($1, $2 ...) as variables. <tadmc@augustmail.com>
    Re: Using match variables ($1, $2 ...) as variables. (GreenLight)
    Re: Very urgent: plz someone answer <tadmc@augustmail.com>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Tue, 11 May 2004 05:48:16 GMT
From: David Muir Sharnoff <muir@idiom.com>
Subject: ANNOUNCE: Initial release of OOPS - Object Oriented Persistent Store
Message-Id: <HxJnyw.vut@zorch.sf-bay.org>

You can find this in CPAN at 

http://www.cpan.org/authors/id/MUIR/modules/OOPS-0.1001.tar.gz

or (until CPAN picks it up) at

ftp:://ftp.idiom.com/users/muir/CPAN/modules/OOPS-0.1001.tar.gz

-Dave


 ...POD.........................................................

NAME
     OOPS - Object Oriented Persistent Store

SYNOPSIS
     use OOPS;

     transaction(sub {
            $oops = new OOPS 
                    dbi_dsn => $DBI_DSN, 
                    username => $username, 
                    password => $password,
                    table_prefix => "MY";

            $oops->{h} = { a => b};
            $oops->{foobar} = $myobject;
            $oops->{abcd} = getref(%{$oops->{h}}, 'a');

            $oops->commit;
     });

DESCRIPTION
    The goal of OOPS is to make perl objects transparently persistent. OOPS
    handles deeply nested and cross-linked objects -- even object
    hierarchies that are too large to fit in memory and (with a hint)
    individual hash tables that are too large for memory. Objects will be
    demand-loaded into memory as they are accessed. All changes to your
    object hierarchy will be saved with a single commit().

    Full transactional consistenty is the only operational mode. Either all
    of your changes are saved or none of them are. During your program, you
    will see a consistent view of the data: no other running transactions
    will change the data you see. If another transaction changes data that
    you are using then at least one of the transactions must abort. This
    happens automatically.

    OOPS maps all perl objects to the same RDBMS schema. No advance schema
    definition is required on the part of the user of OOPS. The name comes
    from the realization that perl's data model is much more complicated
    than I initially understood. Internally, the RDBMS schema uses four
    tables: a table of objects, a table of attributes (keys and values), a
    table of large attributes that big the normal column widths, and a table
    of counters.

    At this time, OOPS is expecting a web-like workflow:

     create OOPS instance

     load some ojbects

     modify some objects

     commit

     exit

    If you need more than one transaction in a program, create more than one
    OOPS instance.

    To make your data persistent, make a reference to your data from the
    OOPS object. To later retrieve your data, simply access it through the
    OOPS object.

EXAMPLE PROGRAM
     use OOPS;

     transaction(sub {
            my $oops = new OOPS 
                    dbi_dsn => 'DBI:mysql:database=MY-DATABASE-NAME;host=localhost', 
                    username => 'MY-USERNAME', 
                    password => 'MY-PASSWORD',
                    table_prefix => "MY-TABLE-PREFIX";

            my $p = $oops->{pages}{"/some/path"};

            $p->{next} = $oops->{pages}{"/some/other/path"};
            $p->{jpgs} = [ read_file("x.jpg"), read_file("y.jpg") ];

            $oops->commit;
     });

     exit;

SUPPORTED DATA TYPES
    Perl HASHes, REFs, SCALARs, and ARRAYs are supported. Currently, HASH
    keys may not be longer than 255 characters. Class names may not be more
    than 128 characters long. References to hash keys and array elements are
    supported.

    At the current time, large ARRAYs are not efficient. Use HASHes instead
    if this matters to you. References to array elements and hash values are
    not efficient.

    Large HASHes are supported by only loading keys that are accessed.

    HASHes, array elements, and REFs are implmented with tie(). ARRAYs are
    not currently tie()d because of bugs in perl. Multiple references to the
    same scalar are supported. References to array elements and hash values
    are supported. Persistent data is reference counted and cycles must be
    manually broken to assure de-allocation.

SUPPORTED PLATFORMS
    The following RDBMSs are supported in the code:

    PostgreSQL     OOPS has been tested with PostgreSQL version 7.4.2 and
                   7.3.5. 7.4.2 on Linux 2.4.23 performs okay. 7.3.5 on
                   pre-release DragonflyBSD is slow.

    mysql          OOPS has been tested with mysql 4.0.16 and 4.0.18 using
                   InnoDB tables.

    Perl versions 5.8.2 and 5.8.3 are supported. Prior to 5.8.2, it wasn't
    possible to untie scalars from within the a tied scalar access method.
    An ugly workaround is possible if there is enough interest.

    OOPS has been tested on Linux 2.4.23 (Debian unstable as of April '04)
    and on DragonflyBSD prerelease.

FUNCTIONS
    "transaction($funcref, @args)"
        "transaction()" is a wrapper for a complete transaction.
        Transactions that fail due to deadlock with other processes will be
        re-run automatically.

        The first parameter is a reference to a function. Any additional
        parameters will be passed as parameters to that function. The return
        value of "transaction()" is the return value of "&$funcref()".

        It is not necessary to use the "transaction()" method. Beware that
        nearly any operation on persistent date (even read operations) can
        cause deadlock.

        Any use of persistent data can trigger a deadlock. The
        "transaction()" function catches this and retries automatically upto
        $OOPS::transaction_maxtries times (15 times unless you change it).
        If you don't use "transaction()" you might want to catch the
        exceptions that "transaction()" catches. To do this, you can regex
        match $@ against $OOPS::transfailrx.

    "getref(%hash, $key)"
        References to tied hash keys are buggy in all perls through 5.8.3.
        Use getref(%hash, $key) to create your reference to a tied hash key.
        See: <http://rt.perl.org/rt3/Ticket/Display.html?id=27555> and
        <http://rt.perl.org/rt3/Ticket/Display.html?id=29224>.

         $ref = getref(%hash, $key);

        Alternatively, use "$oops-"workaround27555($ref)>.

        Getref() and workaround27555() work around all the perl bugs with
        tied hash key references. Failure to use them may result in
        unexpected and inconsistent results.

PUBLIC CLASS METHODS
    "OOPS->new(dbi_dsn => $dbi_dsn, user => $user, password => $password,
    table_prefix => $prefix)"
        Creates a OOPS object instance. In addition to the normal DBI
        default environment variables of $DBI_DSN, $DBI_DRIVER, $DBI_USER,
        $DBI_PASS, OOPS has its own set that overrides the DBI_ set:
        $OOPS_DSN, $OOPS_DRIVER, $OOPS_USER, $OOPS_PASS.

        OOPS allows a prefix to be supplied for it's internal table names.
        If you set a prefix of "FOO_" then it will use a "FOO_object" table
        instead of an "object" table. This can be set as an argument to
        "new()" or it can be set with the environment variable $OOPS_PREFIX.
        This allows multiple separate object spaces to exist within the same
        SQL database. It's intended use is to support testing.

    "OOPS->inital_setup(dbi_dsn => $dbi_dsn, user => $user, password =>
    $password, table_prefix => $prefix)"
        Drops and recreates the database tables. Don't use it too often :-)
        The regression suite drops and re-creates the tables many times. Be
        careful.

PUBLIC OBJECT METHODS
    "->commit()"
        Writes any changed objects back to the database and commits the
        transaction. Currently only one commit() call is allowed. Do not
        access your persistent data after commit() -- it may work but this
        is not covered well in the regresssion suite.

    "->virtual_object(\%hash [,$new_value])"
        Queries [and sets] the load-virtual flag on a persistent hash.
        Hashes that load virtual will do separate queries for each key
        rather than load the entire hash. This is a good thing if your has
        has many keys. This flag takes effect the next time the hash is
        loaded. The value is a perl boolean.

        This may be handled automatically in the future.

    "->workaround27555($reference)"
        References to tied hash keys are buggy in all perls through 5.8.3.
        Use workaround27555($reference) to register your new tied hash key
        references so that they can be transformed into references that
        actually work correctly.

         $ref = \%hash{$key};
         $oops->workaround27555($ref);

        "workaround27555()" is harmless if called on other sorts of
        references so it is safe to use indescriminately. See
        <http://rt.perl.org/rt3/Ticket/Display.html?id=27555>.

        Alternatively, use "getref(%hash, $key)".

ERRATA, DEVELOPMENT STATUS, BUGS, AND BUG BOUNTY
    OOPS has been thoroughly tested. At this time of the initial release,
    OOPS has no current users. Do not let that stop you from trying it. The
    regression suite is very well developed: there is twice as much code in
    the test suite as there is in the module itself. The suite does over
    1.5million tests. On my fastest computer it takes over six hours to run.
    I have so much confidence in my test suite, I'm offering a bounty on
    bugs!

    I'll pay (via paypal) US$5.00 to anyone who submits a new bug (with
    regression test) that is caused by a problem in my OOPS module. To
    qualify, bugs must be serious: they must cause data corruption, false
    results, or program failure. Bugs must not be listed here.

    I'll report the number of bounties paid in the CHANGELOG.

  Known fixable bugs in OOPS
    memory leaks
        OOPS currently has memory leaks. This may or may not matter to your
        application. The leaks do not appear to be serious.

    delayed DESTROY
        Additional references to the in-memory copies of persistent data are
        kept by OOPS. These extra references will prevent DESTORY methods
        from being called as soon as they otherwise would be.

    other magic
        Other perl magic attributes are not currently stored persistently.
        Many probably could be supported, but many could not. For example,
        taint does not work on tied hashes:
        <http://rt.perl.org/rt3/Ticket/Display.html?id=6758>.

    unreferenced blessed scalars
        When you bless a reference to a scalar value, the blessing is stored
        with the scalar, not the reference. The blessing remains even if
        there is no reference to the scalar. The following code prints
        "true".

         my $x = 'foobar';
         my $y = \$x;
         bless $y, 'baz';
         $y = 7;
         $y = \$x;
         my $z = ref($y);
         print "true\n" if $z eq 'baz';

        At the current time, OOPS does not store such blessings. OOPS does
        remember blessings when there is a reference.

    re-blessing the OOPS object
        If you re-bless the OOPS object, your data is likely to become
        inaccessable. I list this here so nobody claims a bounty for
        breaking OOPS in this way.

  Bugs in perl that effect OOPS
    references to hash keys
        Persistent hashes are implemented with tie. There are bugs with
        perl's implementation of references to tied hash keys. These bugs
        will be triggered in several situations: creating a reference to
        tied hash key that doesn't exist yet; deleting a key that has a
        reference tied to it; assigning through a reference to a key that
        has multiple references.

        All of the above can either be avoided or you can workaround them by
        either calling "workaround27555"($YOUR_REFERENCE) whenver you create
        a tied hash key reference or by using "getref(%hash, $key)" to
        create your reference.

        The perl bugs are documented in:
        <http://rt.perl.org/rt3/Ticket/Display.html?id=27555> and
        <http://rt.perl.org/rt3/Ticket/Display.html?id=29224>.

    "local" and tie
        "local(%some_tied_hash)" doesn't work right. Thus
        "local(%some_persistent_hash)" won't work right either:
        <http://rt.perl.org/rt3/Ticket/Display.html?id=6017>.

    "scalar(%hash)"
        "scalar(%hash)" support was added in perl 5.8.3 and does not exist
        in 5.8.2.

    tied arrays don't work right
        There are a couple of bugs with tied arrays that prevent OOPS from
        using them. <http://rt.perl.org/rt3/Ticket/Display.html?id=22571>
        and <http://rt.perl.org/rt3/Ticket/Display.html?id=22571>. This
        isn't a big deal unless you've got big arrays.

FUTURE DIRECTIONS
    OOPS isn't done. There are a bunch of things that I am considering
    adding to it. If any of these things is important to you, speak up so
    that I know there is interest...

    fix the bugs
        There are bugs listed in the DEVELOPMENT STATUS section that could
        be fixed. First up is fixing the memory leak.

    code cleanup and general performance enhancements
        The initial release of OOPS concentrated on correct behavior and
        other aspects of the module were somewhat ignored. The code could be
        cleaned up a bunch.

    better concurency
        With the transaction model of SERIALIABLE on mysql, there are
        serious performance issues surrounding access to the main hash.
        Change to a different transaction model or DBMS.

    perl-syntax sql query translator
         SELECT Employee WHERE $Employee->{salary} > 5000

        It's possible to translate perl-syntax queries into real SQL that
        can be used to query the object store.

    better grouping
        Objects are loaded in groups rather than individually. There is much
        room for improvement in choosing how groups are formed. This is
        largely undeveloped as yet.

    support for databases other than mysql
        PostgreSQL is the next likely supported backend.

    caching
        Many possibilities. A cache-invalidation daemon to note when objects
        have changed. Re-verification of touched data from the database.
        Ability to call commit() more than once.

    weak references
        Support for persistent weak references is possible.

    external references to objects
        Currently objects are reference counted internally. You must have a
        reference to something from an already existing object for it to
        continue to exist.

    contracts
        OOPS has to do a lot of scanning of objects to see if they've
        changed. Explicit notification of changes would improve performance.

        OOPS could call functions before saving and after loading to
        transform objects for a better or cleaner on-disk representation.

    support for 'base' & accessor methods
        This isn't something that I care about but maybe someone else does?

    schema enforcement
        Allow explicit schemas to be defined. Do not save objects that don't
        conform.

    RDBMS -> object mapping
        Map existing RDBMS schemas into objects.

    data viewer
        Viewing large datasets of deep and cross-linked data is difficult.
        Perhaps a CGI-based or Tk-based data navigator would help.

    support for tied data structures
        It is possible to support storing tied data. The tied object is what
        would need to be persistent. This would only work on some kinds of
        ties.

    garbage collect circular references
        Like perl, OOPS uses reference counting to know when to delete an
        object. Unlike perl, restarting your program does not clear out the
        circular references.

    support for other base types.
        Right now, just HASH, SCALAR, REF, and ARRAY are supported. Regular
        expressions, file handles, I don't know it's possible to support
        code references.

WRITING SQL QUERIES BY HAND
    If you want to query your data, then until a translator is written, your
    only choice for making queries is to write them by hand. Using your data
    does not require a query: anything you've got a reference to will be
    loaded as you access it. Queries are for performing searches that don't
    have a perl-object index.

    Each perl HASH, REF/SCALAR, or ARRAY has a row in the "object" table and
    multiple rows in the "attribute" and "big" tables.

    Here are the columns you'll care about:

    object      There is one row per perl object.

                id        The object id.

                class     The blessed class name (limited to 255
                          characters).

                otype     The type of object:

                          'H'  A HASH.

                          'A'  An ARRAY.

                          'S'  A SCALAR or REF.

    attribute   This is a table of key/value pairs. The keys corrospond to
                perl hash keys and perl array indexes. The values corrospond
                to perl hash values and array element values.

                id        The object id.

                pkey      The hash key or array index.

                pval      he hash value or array value. Limited to 255
                          characters.

                ptype     Flags the type of the value. Possible values are:

                          '0'  A normal value. Numeric or string.

                          'B'  An big value. "pval" will be a copy of the
                               start of the value for the first N
                               characters. The end of "pval" will be a MD5
                               checksum of the full big value.

                          'R'  A reference to another object.

    big         This is a table of values that were too large for the normal
                columns. Even with databases that support wide columns, a
                separate big table is used so that you don't load large
                scalars unless you actually need the value.

                id        The object id.

                pkey      The hash key or array index.

                pval      The hash value or array value. Limited to whatever
                          the underlying database will support as it's
                          largest blob.

    REFs are are special. There are several types of REFs: references to
    scalar values; references to objects; secondary references to scalar
    values; references to scalar values that are part of another object
    (references to hash keys and references to array elements).

    The representation of references is designed so that you don't need to
    care what sort of REF it is when you're doing a query.

    The basic REF is a ref to a value inside another object. An example:

     OBJECT TABLE
     id             class           otype

     1              OOPS::NamedObj  H
     383            SCALAR          R
     384            SCALAR          R
     385            SCALAR          R
     386            REF             R
     400            HASH            H
     500            ARRAY           A

     ATTRIBUTE TABLE
     id             pkey            pval            ptype

     1              A500            500             R
     1              H400            400             R
     1              R383            383             R
     1              R384            384             R
     1              R385            385             R
     1              R386            386             R

     383            400             'a-key'         0

     384            384             'nopkey'        0
     384            'nokey'         'a-value'       0

     385            384             'nopkey'        0

     386            386             'nopkey'        0
     386            'nopkey'        500             R

     400            'a-key'         'a-value        0
     400            'another-key'   'another-value' 0
     400            'A500'          500             R

     500            0               'a-value'       0
     500            1               'another-value' 0

    HASH 1 is %$oops.

    REF 383 is a reference to the key 'a-key' in object #400 (a HASH).

    REF 384 is a ref to scalar. It uses two rows to make writing queries
    easier.

    REF 385 is a duplicate reference to a scalar value. It duplicates REF
    384. In behavior, these two REFs should be identical even though they
    are represented differently in the database.

    REF 386 is a ref to an object: #500 (an ARRAY).

    HASH 400 is a normal hash.

    ARRAY 500 is a normal hash.

    This example data is what you would end up with after running code like:

     my $oops = new OOPS 
            dbi_dsn => 'DBI:mysql:database=MY-DATABASE-NAME;host=localhost', 
            username => 'MY-USERNAME', 
            password => 'MY-PASSWORD';

     $oops->{A500} = [ 'a-value', 'another-value' ];

     $oops->{H400} = { 
            'a-key' => 'a-value',
            'another-key' => 'another-value',
            'A500' => $oops->{A500},
     };

     $oops->{R383} = \$oops->{H400}{'a-key'};
     $oops->workaround27555($oops->{R383});

     $oops->{R384} = \'a-value';

     $oops->{R385} = $oops->{R384};

     $oops->{R386} = \$oops->{A500};

     $oops->commit;

    SQL queries require a bunch of joins to link data structures together.
    Here are some examples.

    "SELECT Foobar WHERE $Foobar->{xyz} = 'abc'"
         SELECT object
         FROM   object, attribute
         WHERE  object.class = 'Foobar'
         AND    object.id = attribute.id
         AND    attribute.pkey = 'xyz'
         AND    attribute.pval = 'abc'
         AND    attribute.ptype = '0'

    "SELECT Foobar WHERE ${$Foobar->{xyz}} = 'abc'"
        This example should show why an automatic translator would be a good
        idea...

         SELECT ohash.object
         FROM   object AS ohash,
                attribute AS ahash,
                object AS oref,
                attribute AS aref,
                attribute AS target
         WHERE  ohash.class = 'Foobar'
         AND    ohash.otype = 'H'
         AND    ahash.id = ohash.id
         AND    ahash.pkey = 'xyz'
         AND    ahash.ptype = 'R'
         AND    oref.id = ahash.pval
         AND    oref.otype = 'S'                # this is the outer ref
         AND    oref.id = aref.id               
         AND    aref.pval = target.pkey         # here's the reference indirection
         AND    target.pval = 'abc'
         AND    target.ptype = '0'

    If you construct a query like these examples that return object id's,
    then use "$object = $oops->load_object($id)" to load them into memory.

    I reccomend that hand-written queries by read-only as there are
    additional columns that must be kept consistent. For example, the object
    table includes a reference count column to handle garbage collection of
    the persistent data.

RUNNING THE REGRESSION TEST SUITE
    The regression test suite empties and re-creates the persistent store
    over and over again. To prevent the accidental erasure of production
    data, all of the tests require a special environment variable to be set
    $OOPSTEST_DSN. This variable replaces the normal $DBI_DSN or $OOPS_DSN.
    Correspondingly there is a $OOPSTEST_USER, $OOPSTEST_PASS, and
    $OOPSTEST_PREFIX.

    Set these variables to something different than what you use for your
    production data!

    Most of the tests take a long time to run and are disabled by default.
    If you can run the full suite in less than six hours please tell me
    about your configuration.

    Beware mysql logging. On Debian unstable, the default configuration for
    mysql logs every SQL statement. Running the test suite to completion
    will generate several gigabytes of log file. Running out of disk space
    will cause the tests to fail. On DragonflyBSD (FreeBSD 4.9) the default
    mysql configuration includes making replication master logs.

THE COMPETITION
    There are a number of other modules that make perl objects persistent.
    For each module, I'll provde a sentence or two that explains why I wrote
    OOPS rather than using that one.

    OOPS does not require any schema defintion. Most other persistence
    package requires schema definition and allows the nature of the
    underlying RDBMS to show in both the kinds of objects you can use and
    how you use them. OOPS tries to let you work with perl objects without
    concerning yourself about how they'll be stored persistently.

    Persistence::Object::Postgres
        Uses Data::Dumper to serialize objects into BLOBs. Cannot handle
        cross-linking. No query support.

    pop Only supports Sybase. Uses a fixed schema defined in XML.

    SPOPS
        Objects are HASHes, values are scalars only. No nesting.

    DBIx::RecordSet
        Thin layer on top of DBI. Removes much pain from using DBI. Does not
        change basic relationship to data -- still relational.

    Object::Transaction
        Uses Storable to preserve objects in files. No query support. No
        cross-linking. Lightweight. Transactions.

    Class::DBI
        Must define schema and relationships to RDBMS. Accessor methods.
        Doesn't support many2many. Close tie to underlying RDBMS.

    Alzabo
        Must define schema and relationships as relates to RDBMS. Close tie
        to underlying RDBMS. Can help create RDBMS schema. Complex. Can
        cache database rows.

    Tangram
        Must define schmea. RDBMS schema is created from perl schema.

    Pixie
        Less trasnparent. Requires user to remember a cookie to retreive
        objects. Cannot handle cross-linking of objects? No query support?

    MLDBM / Tie::MLDBM / MLDBM::Easy / MLDBM::Sync
        Uses Data::Dumper or Storable or such to serialize objects and store
        them as strings. Lock granularity is the whole file. No query
        support. Only one (or two with MLDBM::Easy) level of access is
        automated.

    ObjStore
        Proprietary. Not as transparent as OOPS.

    see also
        <http://poop.sourceforge.net/> has an overview of options.

LICENSE
    Copyright(C) 2004 David Muir Sharnoff <muir@idiom.com>

    All rights reserved except as granted by a license or contract. This
    module is licensed both commercially and as free software. The free
    software license follows.

    The Play-Fair-To-Play Software License

    Preamble.

    I wish to let people use this software for free as long as they don't
    abuse the free software community or Internet in particular ways. I want
    all derrivitives of this software to be free. I want to be able to
    license this software commercially.

    This license is not compatabile with the GPL. It was not written by a
    lawyer and the exact wording will probably change when a legal expert
    examines it. This license applies only to this version of this program:
    other versions may exist with other licenses.

    I.     This software may be used, copied, modified, and redistributed
           with no fee paid to the copyright holder (original licensor) so
           long as all the parts of this license are honored. Should any
           part be deemed invalid or otherwise contradicted, the entire
           license is invalidated and no right to use, copy, modify or
           redistribute exists.

    II.    Any redistribution of this software must retain this license. Any
           redistribution of this software must include it's original
           (source code) form. When redistributing this software, you may
           not add additional licensing terms that would prevent the new
           recipient of the software from using, copying, modifying, or
           redistributing this software themselves under the terms of this
           license.

    III.   This software is licensed free of charge. To the extent permitted
           by applicable law, there is no warranty for the software. The
           software "as is" without warranty of any kind, either expressed
           or implied, including, but not limited to, the implied warranties
           of merchantability and fitness for a particular purpose. The
           entire risk as to the quality and performance of the software is
           with you. should the software prove defective, you assume the
           cost of all necessary servicing, repair or correction.

    IV.    All useful modifications to this software must be licensed back
           to the original licensor such that the original licensor can
           relicense the modifications to third parties under terms of their
           own choosing with no restrictions whatsoever and need not even
           acknowledge the origin of such modifications. An easy way to
           accomplish this is to put all such modifications into the public
           domain.

    V.     Under this license, use, modification, and redistribution of this
           software is expressly forbidden to all entities that have
           willfully violated an open source license. For example, SCO for
           violating the GPL.

    VI.    Under this license, use, modification, and redistribution of this
           software is expressly forbidden to all entities that have
           attempted to enforce a software patent (except as a defensive
           move like IBM's counter to SCO). For example, Unisys for
           enforcing a patent on GIF image creation.

    VII.   Under this license, use, modification, and redistribution of this
           software is expressly forbidden to all entities that engage in or
           encourage sending SPAM emails.

    VIII.  Under this license, use, modification, and redistribution of this
           software is expressly forbidden to all entities that challenges
           this license in court.

    IX.    This license does not apply to the following entities or their
           sucessors or subsideraries: Network Solutions; Verisign; ICANN;
           and Internet-Journals.

-- 




------------------------------

Date: 11 May 2004 05:55:47 -0700
From: monicaroman@yahoo.com (Monica Roman)
Subject: Re: Confused Newbie question: Decimal to IP
Message-Id: <9eb77af5.0405110455.212808ea@posting.google.com>

Thank you Mark, John, Tad, for all your answers. John, I'll try all
the options you gave me...nothing better than something tangible to
start learning Perl, a question with the answer, perfect. I have two
Perl books on my desk right now and I'm excited about learning it.

Thanks again,

Monica


------------------------------

Date: Tue, 11 May 2004 11:19:32 GMT
From: "George Kinley" <georgekinley@hotmail.com>
Subject: Making array elements Unique
Message-Id: <8F2oc.16081$k4.324223@news1.nokia.com>

Hi

I have an array of duplicate elements "char", I want to make the elements
Unique and throw the redundant
what solution came to my mind is I take element by element out of an array
and create a hash checking the elements with "exists" and populate the hash
is there any more intelligent way to do
--




------------------------------

Date: Tue, 11 May 2004 13:35:12 +0200
From: Christian Winter <thepoet_nospam@arcor.de>
Subject: Re: Making array elements Unique
Message-Id: <40a0ba70$0$26345$9b4e6d93@newsread4.arcor-online.net>

George Kinley schrieb:
> I have an array of duplicate elements "char", I want to make the elements
> Unique and throw the redundant
> what solution came to my mind is I take element by element out of an array
> and create a hash checking the elements with "exists" and populate the hash
> is there any more intelligent way to do

That's a FAQ, and "perldoc -q duplicate" shows you
the answer.

HTH
-Christian


------------------------------

Date: 11 May 2004 11:38:37 GMT
From: anno4000@lublin.zrz.tu-berlin.de (Anno Siegel)
Subject: Re: Making array elements Unique
Message-Id: <c7qdvt$dbp$2@mamenchi.zrz.TU-Berlin.DE>

George Kinley <georgekinley@hotmail.com> wrote in comp.lang.perl.misc:
> Hi
> 
> I have an array of duplicate elements "char", I want to make the elements
> Unique and throw the redundant
> what solution came to my mind is I take element by element out of an array
> and create a hash checking the elements with "exists" and populate the hash
> is there any more intelligent way to do

It's the standard way.  See "perldoc -q duplicate".

Anno


------------------------------

Date: Tue, 11 May 2004 13:39:50 +0200
From: "Bernard El-Hagin" <bernard.el-haginDODGE_THIS@lido-tech.net>
Subject: Re: Making array elements Unique
Message-Id: <Xns94E68B081BDE1elhber1lidotechnet@62.89.127.66>

"George Kinley" <georgekinley@hotmail.com> wrote:

> Hi
> 
> I have an array of duplicate elements "char", I want to make the
> elements Unique and throw the redundant
> what solution came to my mind is I take element by element out of
> an array and create a hash checking the elements with "exists" and
> populate the hash is there any more intelligent way to do


No.


-- 
Cheers,
Bernard


------------------------------

Date: 11 May 2004 12:52:24 +0100
From: Brian McCauley <nobull@mail.com>
Subject: Re: Making array elements Unique
Message-Id: <u9wu3jji4n.fsf@wcl-l.bham.ac.uk>

"George Kinley" <georgekinley@hotmail.com> writes:

> I have an array of duplicate elements "char", I want to make the elements
> Unique and throw the redundant
> what solution came to my mind is I take element by element out of an array
> and create a hash checking the elements with "exists" and populate the hash
> is there any more intelligent way to do

If there were then it is unlikely that the solution you describe above
would be the one given in the FAQ.  It is.  Well almost.  For details,
see FAQ. 

-- 
     \\   ( )
  .  _\\__[oo
 .__/  \\ /\@
 .  l___\\
  # ll  l\\
 ###LL  LL\\


------------------------------

Date: Tue, 11 May 2004 12:50:05 +0000 (UTC)
From: Irving Kimura <nomail.please@no.mail.com>
Subject: Re: Need example of module+cgi+data distribution
Message-Id: <c7qi5t$gvs$1@reader2.panix.com>

In <87d65b2xek.fsf@odyniec.odyniec.net> Michal Wojciechowski <odyniec-usenet@odyniec.net> writes:

>Irving Kimura <nomail.please@no.mail.com> writes:

>> I'm trying to create a distribution featuring
>> 
>>   1. a CGI script (Perl)
>>   2. a collection of Perl modules used by the CGI script
>>   3. data files used by the CGI script
>> 
>> I'm having a hard time coaxing MakeMaker to write a reasonable
>> Makefile for the above distribution.  (Specifically, MakeMaker
>> doesn't seem to be design to install items such as (1) and (3)
>> above.)

>I've had a similar experience trying to create a MakeMaker script that
>installs an utility along with a few data files. After some struggle,
>I've come up with a (kind of) satisfactory result.

>The code is available at
>http://odyniec.net/projects/cdlist/cdlist-0.1.tar.gz. Makefile.PL is
>rather simple and you should have no problem understanding what it
>does.

>Hope that helps (at least a little bit),

Hey, that's pretty nice.  I'll adapt it to my task for the time
being (but I've decided that I really have to find something better
than MakeMaker, something more flexible that doesn't require these
workarounds just to get simple things done...) 

Thanks,

Irv
-- 
NOTE: In my address everything before the period is backwards.


------------------------------

Date: 11 May 2004 04:45:18 -0700
From: ramprasad.padmanabhan@oracle.com (Ramprasad A Padmanabhan)
Subject: Net::Telnet getting control  over root shell
Message-Id: <6e094b7d.0405110345.3c14c462@posting.google.com>

Hi, 

  I am using Net::Telnet and getting a new shell on a remote machine
all my commands work fine with 

$telnet->cmd("foo") format

Now suppose I become root using "su" and "pass" I am not able to
execute commands on this root shell

Can anyone show me How  I can do this

THanks
Ram


------------------------------

Date: 11 May 2004 11:13:09 GMT
From: anno4000@lublin.zrz.tu-berlin.de (Anno Siegel)
Subject: Re: Parse::RecDescent: special treatment for keywords
Message-Id: <c7qcg5$dbp$1@mamenchi.zrz.TU-Berlin.DE>

A. Farber <Alexander.Farber@t-online.de> wrote in comp.lang.perl.misc:
> Hi,
> 
> I'm trying to parse this kind of texts:
> 
> TARGET                  Snake.app
> TARGETTYPE              app
> UID                     0x100079be 0x103F5BE8
> TARGETPATH              \system\apps\Snake
> SOURCEPATH              ..\UiSrc
> SOURCE                  CSApplication.cpp CSAppUI.cpp CSDocument.cpp
> CSView.cpp CSViewControl.cpp CSSettingsDialog.cpp
> SOURCE                  CSHighScoreDialog.cpp CSKeyboardReader.cpp
> CSGameDrawer.cpp CSPauseNoteDialog.cpp
>                         CSHighscoreStore.cpp CSPlayDialog.cpp
> CSHelpDialog.cpp
> SOURCE                  CSConnectionNoteDialog.cpp
>                         CSAsyncWait.cpp          // added 13.02.2004
>                         CSGameOverNoteDialog.cpp // added 24.7.2001
> SOURCE                  ..\audiosrc\CSoundBank.cpp CdBitmapManager.cpp
> DOCUMENT                ..\group\Snake.loc
> 
> by the following grammar:
> 
> startrule: comment(s) | directive(s)

This will allow a sequence of comments, or a sequence of directives,
but not both.  Your example data has trailing comments mixed with
directives.  How do you expect this grammar to parse those?

> comment: m{//[^\\n]*}
> directive: keyword value(s)
>         { print "KEYWORD: $item{keyword}\n" }
> value: file | type | uid

Since "file" matches "type" and "uid" items too, file must be the
*last* alternative.  Otherwise "file" will catch everything, and
"type" and "uid" don't get a chance.

> file: m{[\\w\\\\/.-]+}

I don't know how you quoted that string, but there seem to be too many
backslashes in that pattern.

> type: 'app' | 'dll'
> uid: /0[xX][0-9a-fA-F]+/
> keyword: 
>         'AIF' |
>         'DOCUMENT' |
>         'LANG' |
>         'LIBRARY' |
>         'RESOURCE' |
>         'SOURCE' |
>         'SOURCEPATH' |

Again, "SOURCE" will match before "SOURCEPATH" gets a chance.  Swap them.

>         'SYSTEMINCLUDE' |
>         'TARGET' |
>         'TARGETPATH' |
>         'TARGETTYPE' |

Same problem.  "TARGET" should come last.

>         'UID' |
>         'USERINCLUDE'
> 
> But only get the single line printed out:
> 
> KEYWORD: TARGET
> 
> Probably because the very first line is being
> parsed as the "keyword" TARGET with all the rest
> words in the file being parsed as "value"s.

Right, that's what happens.

By default, Parse::RecDescent assumes a free-form grammar where any
kind of while space can serve as a token separator.  Since the line
structure is important in your case, you must change the default
token prefix to something that doesn't eat line feeds.

    $Parse::RecDescent::skip = '[ \t]*';

is a way of doing this, but a <skip: ...> directive may be more
appropriate.  You will then *somehow* have to include an end-of-line
element in your grammar to control the effect of line-ends.

What follows is an example grammar that (at least) distinguishes
correctly between lines with a keyword and those without.  It is
still a ways off from what you eventually want to achieve, but
it is a step in the right direction:

    my $grammar = <<'EOG';
    startrule: line(s)
    line: key_line | continuation_line
    key_line: keyword value(s) eol
        { print "keyword: $item{ keyword}, value(s): @{ $item{ 'value(s)'}}\n" }
    continuation_line: value(s) eol
        { print "continuation value(s): @{ $item{ 'value(s)'}}\n" }
    eol: /\n/

    value: type | uid | file
    file: m{[\w/\\.-]+}
    type: 'app' | 'dll'
    uid: /0[xX][0-9a-fA-F]+/
    keyword:
            'AIF' |
            'DOCUMENT' |
            'LANG' |
            'LIBRARY' |
            'RESOURCE' |
            'SOURCEPATH' |
            'SOURCE' |
            'SYSTEMINCLUDE' |
            'TARGETPATH' |
            'TARGETTYPE' |
            'TARGET' |
            'UID' |
            'USERINCLUDE'
    EOG

    $Parse::RecDescent::skip = '[ \t]*';
    my $p = Parse::RecDescent->new( $grammar) or die "boo";

Anno


------------------------------

Date: Tue, 11 May 2004 07:52:11 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: Printing Array's content with carriage return (\n)
Message-Id: <slrnca1j3r.3nt.tadmc@magna.augustmail.com>

l v <lv@aol.com> wrote:
> Tad McClellan wrote:
>> l v <lv@aol.com> wrote:
>> 
>>>I usually use with preference on #2:
>>>
>>>print map {"$_\n"} @myarray;
>>>or
>>>map {print "$_\n"} @myarray;
>> 
>> 
>> _Why_ do you prefer #2?
>> 
>> I think most people would prefer #1 because it says "print bunch 'o stuff"
>> while #2 says "bunch 'o stuff print".
>> 
> 
> "print bunch 'o stuff" --  I like it!


It is just an uneconomical way of saying "list".  :-)


> #2 purely for comprehension by those in my work area which are VERY 
> inexperienced with Perl.  


map() is a foreach() in disguise.


> They see the print block and understand what 
> is to occur.


These inexperienced people are expected to know that map is
a foreach in disguise?

Why not just use a literal foreach? 

   foreach ( @myarray ) 
      {print "$_\n"}

or

   print "$_\n" foreach @myarray;


Seems that would be even easier to understand...


> I've never really studied which is faster, 'print map ...'
> or 'map {print ...'  or for.  I guess I now have something to do tonight 
> after all.


Don't do anything tonight.

You should be optimizing for labor (comprehension) before speed,
so choose whichever is easier to read and understand without
regard to how many microseconds can be saved.


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


------------------------------

Date: Tue, 11 May 2004 07:27:02 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: Using match variables ($1, $2 ...) as variables.
Message-Id: <slrnca1hkm.3nt.tadmc@magna.augustmail.com>

gnari <gnari@simnet.is> wrote:

>       my @matches = $string =~ /<Size>(\d+)</Size>([^<]*)/gs;


m//s only affects dot.

You never need a m//s when there is no dot in the pattern.


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


------------------------------

Date: 11 May 2004 06:00:42 -0700
From: google@milbaugh.com (GreenLight)
Subject: Re: Using match variables ($1, $2 ...) as variables.
Message-Id: <c4b60ce1.0405110500.3570d242@posting.google.com>

Ravi Parimi <parimi@none.nowhere.com> wrote in message news:<Pine.GSO.4.58.0405101802580.18191@shellfish.ece.arizona.edu>...
> Hi,
> 	I have a string that gets generated on the fly. Based on the
> number of times a particular word appears in this string, I generate my
> matching pattern. As an example..
> 
> $string = "<Data><Size>12</Size>one string<Size>100</Size>Another
>            string</Data>";
> 
> Now, based on the number of <Size> tags in the string, I create a regular
> expression such as
> 
> my $count = $string =~ s#<Size>##gs;
> my $str = "";
> for ($i = 1;$i <= $count;++$count) {
> 	 $str .= "<Size>(\\d+)</Size>(.*)";
> }
> 
> And now I wish to extract all odd-numbered match variables from the
> matching($1, $3, $5 etc..)
> 
> $string =~ /$str/; # Match always succeeds as I know what's in $string
> 
> In a for loop, I wish to check if each of the $1,$2,$3...variables are
> defined, and am not quite sure how to do that.
> 
> 
> Usage of ${$i} is incorrect and doesnt make sense. Can someone suggest a
> method by which I can find out if $1, $2, $3 ..are defined?
> 
> 
> As an alternative, I have tried XML Parser to parse the above string but
> had no luck with it.. Any help is appreciated.
> 
> Thanks,
> --ravi

Perhaps you are trying to overcomplicate the solution. Look at this:

my $string = "<Data><Size>12</Size>one string<Size>100</Size>Another
string</Data>"; # <-- this string should not be wrapped
my @rows = ($string =~ /<Size>(\d+)<\/Size>/gi);
foreach (@rows) {
  print "$_\n";
}

That snippet of code produces this:
12
100

When you capture the result of the pattern match ("my @rows =...") in
list context, you get all of the matches as a list.

Is that what you want to accomplish?
--
my real address is perl - at - milbaugh - dot - com


------------------------------

Date: Tue, 11 May 2004 07:58:53 -0500
From: Tad McClellan <tadmc@augustmail.com>
Subject: Re: Very urgent: plz someone answer
Message-Id: <slrnca1jgd.3nt.tadmc@magna.augustmail.com>

gnari <gnari@simnet.is> wrote:
> "Neo" <me4uwithluv@yahoo.com> wrote in message
> news:639fa221.0405092052.4b4c36a7@posting.google.com...
>> I have a question:
>>
>> I am asked in an interview:
>>
>> How is an array interpolated in Perl.
> 
> what kind of interview is this, that this question is so urgent,
> that you have no time to look at the docs, or even make a few
> simple tests, but still not so urgent that you can wait for your
> question and the answers to propagate through usenet?


Think he got the job?


-- 
    Tad McClellan                          SGML consulting
    tadmc@augustmail.com                   Perl programming
    Fort Worth, Texas


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

#The Perl-Users Digest is a retransmission of the USENET newsgroup
#comp.lang.perl.misc.  For subscription or unsubscription requests, send
#the single line:
#
#	subscribe perl-users
#or:
#	unsubscribe perl-users
#
#to almanac@ruby.oce.orst.edu.  

NOTE: due to the current flood of worm email banging on ruby, the smtp
server on ruby has been shut off until further notice. 

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

#To request back copies (available for a week or so), send your request
#to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
#where x is the volume number and y is the issue number.

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V10 Issue 6552
***************************************


home help back first fref pref prev next nref lref last post