in reply to [Perl 6] Object methods on the fly?

First: you can do it for all objects by extending the class that provides the Array functionality. Let's assume it's called Array (I don't know, I have to confess), then you could extend it with the is also trait:

class Array is also { method insert ($self: $x){ $self.push($x) unless $self.first($x); } }

Now to return to your original question: There are are surely ways to do it, I don't know if there is a clean one. For example you could write a Role, and assign that Role to the object (I think with the but or does keyword).

Replies are listed 'Best First'.
Re^2: [Perl 6] Object methods on the fly?
by TimToady (Parson) on Jul 18, 2007 at 18:27 UTC
    You're on the right track. You want something like:
    @array does role { method insert ($x) { @.push($x) unless any(self) eqv $x; } }
    Arguably we could provide syntactic sugar to reduce that to:
    @array does method insert ($x) { @.push($x) unless any(self) eqv $x; }
    Perhaps that use of does is redundant with but= and could be removed, but it does read better, I think. In any case, doing an operation like this on an object ends up creating an anonymous class that derives from the original class and adds in the extra method, so you don't clobber the original Array class.
      @array does role { method insert ($x) { @.push($x) unless any(self) eqv $x; } }

      Whoa! And it evens runs on Pugs:

      pugs> my @array does role { ....> method insert ($x) { @.push($x) if none(self) eqv $x } ....> } () pugs> my @array=(1..5); pugs> @array.insert($_) for 1,2,6; pugs> say @array 123456 Bool::True

      BTW: Could I put the initialization in the definition too? I tried with

      pugs> my @array does role { ....> method insert ($x) { @.push($x) if none(self) eqv $x } ....> } = (1..5); (1, 2, 3, 4, 5)

      and it works, but it doesn't with the assignment directly to the right of @array, OTOH I'm sure most people would find it to be more intuitive, while this way they would just say: "for clarity, initialize it in a separate statement."

      BTW: why doesn't the following work, instead?

      pugs> my @array does role { ....> multi method insert ($x) { @.push($x) if none(self) eqv $x } ....> multi method insert (@x) { @.insert($_) for @x } ....> } = 1..5; (1, 2, 3, 4, 5) pugs> @array.insert(3..7); pugs> say @array 1234534567 Bool::True

      (If I use *@x, pugs "hangs", instead.)

      BTW: (the last, really!) what is self supposed to be? After all no suitable and short enough variable/pronoun was found? The following is all that pugs can tell me:

      pugs> self macro {Prim ([Pugs.AST.Internals.Val] -> Pugs.AST.Eval.Eval Pugs.AST.I +nternals.Val)}

      Update: Two of the questions asked here were reposted in separate new threads in

        self is just a built-in function returning the invocant. If you want a different name for it, you can always declare it explicitly.

        Also, it's probably bogus to say any(self). It should probably be a function that is not context sensitive, in which case we'd have to say any(self[]) or some such to pull out the elements.

        Finally, I think the failure of the multi form is just hitting some things that aren't completely implemented in pugs yet.

Re^2: [Perl 6] Object methods on the fly?
by blazar (Canon) on Jul 19, 2007 at 18:53 UTC
    First: you can do it for all objects by extending the class that provides the Array functionality.

    Well, of course I knew that... but I specifically wanted to act on a specific object, which is why I mentioned prototype-based languages.

    Now to return to your original question: There are are surely ways to do it, I don't know if there is a clean one.

    Well, it would be nice if there were: of course what is easy in such relatively simple languages must be simple enough for a language that's supposed to be very complex but still to make hard things easy, and thinking of huffmanization: yes, one wouldn't this kinda things as often as other OO contructs, so it is ok to be slightly more difficult to achieve, but not too much. How much is too much?