Delete array element from inside function

Discussion in 'Perl Misc' started by JS Bangs, Jul 1, 2003.

  1. JS Bangs

    JS Bangs Guest

    Hey, all:

    I've got a function that would like to be able to delete an array element
    from an array in the caller's scope, given only the array element (not the
    array itself, or a reference to it). The idea is to have something that
    duplicates the functionality of delete(), but which tacks a bit of
    other processing onto it. The existing code is quite simple, and looks
    like this:

    ##########

    sub delete_seg {
    return undef unless is_segment($_[0]);
    $_[0]->clear;
    delete($_[0]);
    }

    #########

    In the calling script (which has imported the function delete_seg()):

    #########

    delete_seg($word[3]);

    #########

    Unfortunately, this does not work. $word[3] remains firmly in place with a
    defined value. What can I do to make this work?


    Jesse S. Bangs
    http://students.washington.edu/jaspax/
    http://students.washington.edu/jaspax/blog
     
    JS Bangs, Jul 1, 2003
    #1
    1. Advertising

  2. JS Bangs <> writes:

    > Hey, all:
    >
    > I've got a function that would like to be able to delete an array element
    > from an array in the caller's scope, given only the array element (not the
    > array itself, or a reference to it).


    I don't think this is possible, since $word[3] is a scalar and
    contains no reference to @word as a whole. If you don't need it to be
    a general solution, and for some reason you're opposed to passing an
    array ref, I suppose you could do something like:

    $word[3] = {val => $word[3],
    parent => \@word};
    delete_seg($word[3]);

    and then:

    sub delete_seg {
    my @parent = @{$_[0]->{parent}};
    ...
    }

    but I don't see why that would be useful.

    Again, I don't think there's a general solution (but would be happy to
    be proved wrong). You could also probably use tie() for a specific
    solution, but again I think it's unlikely to be a better solution than
    just passing the array ref.

    ap

    --
    ----------------------------------------------------------------------
    Andrew J Perrin - http://www.unc.edu/~aperrin
    Assistant Professor of Sociology, U of North Carolina, Chapel Hill
    * andrew_perrin (at) unc.edu
     
    Andrew Perrin, Jul 1, 2003
    #2
    1. Advertising

  3. JS Bangs <> writes:

    > I've got a function that would like to be able to delete an array element
    > from an array in the caller's scope, given only the array element (not the
    > array itself, or a reference to it). The idea is to have something that
    > duplicates the functionality of delete(), but which tacks a bit of
    > other processing onto it.


    Short answer is you can't.

    Slightly longer answer is defined(prototype("CORE::delete")) is false
    meaning that the inbuilt delete() cannot be simulated by a subroutine.

    Slightly longer answer still is that the scalars that are elements of
    an array have an existance independant of the array. When I delete()
    the second element of an array it has no actual effect on the the
    scalar that holds the second element, instead if just disconnects if
    from the array.

    my @array = (1,2,3);
    my $r = \$array[1];
    delete $array[2];
    print $$r;

    Similarly if I use the for() or subroutine call mechansims to make $_
    or and element of @_ into an alias for an array element it becomes an
    alias to the scalar that contains the value of the array element - the
    alias is in no way associated with the array.

    > The existing code is quite simple, and looks
    > like this:
    >
    > ##########
    >
    > sub delete_seg {
    > return undef unless is_segment($_[0]);
    > $_[0]->clear;
    > delete($_[0]);
    > }
    >
    > #########
    >
    > In the calling script (which has imported the function delete_seg()):
    >
    > #########
    >
    > delete_seg($word[3]);
    >
    > #########
    >
    > Unfortunately, this does not work. $word[3] remains firmly in place with a
    > defined value. What can I do to make this work?


    You cannot, you need to avoid wanting to do it.

    Without more background I can't be sure, but at a guess I'd say you
    appear to be trying to work arround the misconception that Perl
    doesn't have destructors.

    If this is the case forget about delete_seg() function totally and
    rename the 'clear' method to 'DESTROY'.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
     
    Brian McCauley, Jul 1, 2003
    #3
  4. JS Bangs wrote:
    >
    > I've got a function that would like to be able to delete an array element
    > from an array in the caller's scope, given only the array element (not the
    > array itself, or a reference to it). The idea is to have something that
    > duplicates the functionality of delete(), but which tacks a bit of
    > other processing onto it. The existing code is quite simple, and looks
    > like this:
    >
    > ##########
    >
    > sub delete_seg {
    > return undef unless is_segment($_[0]);
    > $_[0]->clear;
    > delete($_[0]);
    > }
    >
    > #########
    >
    > In the calling script (which has imported the function delete_seg()):
    >
    > #########
    >
    > delete_seg($word[3]);
    >
    > #########
    >
    > Unfortunately, this does not work. $word[3] remains firmly in place with a
    > defined value. What can I do to make this work?


    It looks like you need to use splice:

    splice @word, 3, 1;



    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Jul 1, 2003
    #4
  5. JS Bangs

    JS Bangs Guest

    Brian McCauley sikyal:

    > JS Bangs <> writes:
    >
    > > I've got a function that would like to be able to delete an array element
    > > from an array in the caller's scope, given only the array element (not the
    > > array itself, or a reference to it). The idea is to have something that
    > > duplicates the functionality of delete(), but which tacks a bit of
    > > other processing onto it.

    >
    > Short answer is you can't.
    >
    > Slightly longer answer is defined(prototype("CORE::delete")) is false
    > meaning that the inbuilt delete() cannot be simulated by a subroutine.


    Which also means that delete() is not goto-able, as a simple test
    revealed. Well, drat. That was my last hope.

    > > Unfortunately, this does not work. $word[3] remains firmly in place with a
    > > defined value. What can I do to make this work?

    >
    > You cannot, you need to avoid wanting to do it.


    It sure looks like I do.

    >
    > Without more background I can't be sure, but at a guess I'd say you
    > appear to be trying to work arround the misconception that Perl
    > doesn't have destructors.


    Nah, I'm not worried about object destruction. The kink here is that I
    often want to "delete" a segment object, but "deletion" can take the form
    of actually delete()-ing it, or in clearing all of its values, depending
    on context. I was hoping to have a function that would do both and so
    avoid me having to think about the difference.



    Jesse S. Bangs
    http://students.washington.edu/jaspax/
    http://students.washington.edu/jaspax/blog

    Jesus asked them, "Who do you say that I am?"

    And they answered, "You are the eschatological manifestation of the ground
    of our being, the kerygma in which we find the ultimate meaning of our
    interpersonal relationship."

    And Jesus said, "What?"
     
    JS Bangs, Jul 2, 2003
    #5
  6. JS Bangs

    Islaw Guest

    Andrew Perrin (CLists) wrote:
    > JS Bangs <> writes:
    >
    >> Hey, all:
    >>
    >> I've got a function that would like to be able to delete an array
    >> element from an array in the caller's scope, given only the array
    >> element (not the array itself, or a reference to it).

    >
    > I don't think this is possible, since $word[3] is a scalar and
    > contains no reference to @word as a whole. If you don't need it to be
    > a general solution, and for some reason you're opposed to passing an
    > array ref, I suppose you could do something like:
    >
    > $word[3] = {val => $word[3],
    > parent => \@word};
    > delete_seg($word[3]);
    >
    > and then:
    >
    > sub delete_seg {
    > my @parent = @{$_[0]->{parent}};
    > ...
    > }
    >
    > but I don't see why that would be useful.
    >
    > Again, I don't think there's a general solution (but would be happy to
    > be proved wrong). You could also probably use tie() for a specific
    > solution, but again I think it's unlikely to be a better solution than
    > just passing the array ref.


    Very creative though! (If a tad overkill for the task at hand.) As you
    mentioned, a array ref would be a bit cleaner (and more general.)

    --
    Islaw
     
    Islaw, Jul 2, 2003
    #6
  7. JS Bangs

    Islaw Guest

    Brian McCauley wrote:
    >


    [Line numbers added]
    > 1 my @array = (1,2,3);
    > 2 my $r = \$array[1];
    > 3 delete $array[2];
    > 4 print $$r;


    I think you meant
    delete $array[1];
    @ line 3 :)

    --
    Islaw
     
    Islaw, Jul 2, 2003
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rick
    Replies:
    1
    Views:
    2,215
    =?ISO-8859-1?Q?G=F6ran_Andersson?=
    Jul 19, 2007
  2. =?utf-8?B?5YiY5piK?=
    Replies:
    13
    Views:
    794
    Diego Martins
    Aug 20, 2007
  3. HANM
    Replies:
    2
    Views:
    729
    Joseph Kesselman
    Jan 29, 2008
  4. Al Cholic
    Replies:
    18
    Views:
    277
    Al Cholic
    Jul 28, 2007
  5. Sur
    Replies:
    4
    Views:
    196
Loading...

Share This Page