Method or Property Transparency

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Method or Property Transparency

Post by Ollie Saunders »

I have this bit of code

Code: Select all

public function equal($member, $value, $limit = 0)
{
    $limitChk = 0;
    if (self::_isMemberMethod($member)) {
        for ($i=0; $i<$this->_size; $i++) {
            if ($this->_array[$i]->$member() == $value) {
                $this->_mask[$i] = $this->_state;
                $limitChk++;
                if ($limitChk == $limit) {
                    break;
                }
            }
        }
    } else {
        for ($i=0; $i<$this->_size; $i++) {
            if ($this->_array[$i]->$member == $value) {
                $this->_mask[$i] = $this->_state;
                $limitChk++;
                if ($limitChk == $limit) {
                    break;
                }
            }
        }
    }
}
$member is a string that can be referring to either a method or a property. self::_isMemberMethod($method) returns true if it is a member and false otherwise. I need to perform the same loop either way but obviously one with () and one without, as you can see this is what I am doing.

The repetition of this is stark. I thought of using eval but I don't like that very much. Are there any suggestions as to how I should improve the repetition?
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

Code: Select all

public function equal($member, $value, $limit = 0)
{
    $limitChk = 0;
    $method = self::_isMemberMethod($member);
    for ($i=0; $i<$this->_size; $i++) {
        $element = $this->_array[$i];
        if ( ($method ? $element->$member() : $element->$member) == $value ) {
            $this->_mask[$i] = $this->_state;
            if (++$limitChk >= $limit)
                break;
        }
    }
}
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Superb.
Why didn't I think of that?

Not that I'm complaining or anything but I would just like to note that with '?' the truth evaluation of $method is repeated for every iteration of the loop.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

Not that I'm complaining or anything but I would just like to note that with '?' the truth evaluation of $method is repeated for every iteration of the loop.
That's the price of removing second loop. Since the $method is Boolean, the price perhaps isn't high enough to consider.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

you may simplify it further as :

Code: Select all

for ($i=0; $i<$this->_size; $i++) {
        $property = $this->_array[$i]->$member;
        if ( ($method ? $property() : $property) == $value ) {
            $this->_mask[$i] = $this->_state;
            if (++$limitChk >= $limit)
                break;
        }
    }
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

That's the price of removing second loop. Since the $method is Boolean, the price perhaps isn't high enough to consider.
No, it isn't. I'm using it, thanks! :)
you may simplify it further as:

Code: Select all

$property = $this->_array[$i]->$member;
I'm not sure that will work Weirdan, if $member is a method then you will get an undefined property error surely?
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

I'm not sure that will work Weirdan, if $member is a method then you will get an undefined property error surely?
Image
...just used to work with functions as first-class values Image
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Hmmmm OK got more repetition to solve now hehehe = : - P

Code: Select all

public function equal($member, $value, $limit = 0)
    {
        $limitChk = 0;
        $isMethod = self::_isMemberMethod($member);
        for ($i=0; $i<$this->_size; $i++) {
            $elem = $this->_array[$i];
            if (($isMethod ? $elem->$member() : $elem->$member) == $value) {
                $this->_mask[$i] = $this->_state;
                if (++$limitChk >= $limit) {
                    break;
                }
            }
        }
    }
    public function identicial($member, $value, $limit = 0)
    {
        $limitChk = 0;
        $isMethod = self::_isMemberMethod($member);
        for ($i=0; $i<$this->_size; $i++) {
            $elem = $this->_array[$i];
            if (($isMethod ? $elem->$member() : $elem->$member) === $value) {
                $this->_mask[$i] = $this->_state;
                if (++$limitChk >= $limit) {
                    break;
                }
            }
        }
    }
    public function greaterThan($member, $value, $limit = 0)
    {
        $limitChk = 0;
        $isMethod = self::_isMemberMethod($member);
        for ($i=0; $i<$this->_size; $i++) {
            $elem = $this->_array[$i];
            if (($isMethod ? $elem->$member() : $elem->$member) > $value) {
                $this->_mask[$i] = $this->_state;
                if (++$limitChk >= $limit) {
                    break;
                }
            }
        }
    }
    public function lessThan($member, $value, $limit = 0)
    {
        $limitChk = 0;
        $isMethod = self::_isMemberMethod($member);
        for ($i=0; $i<$this->_size; $i++) {
            $elem = $this->_array[$i];
            if (($isMethod ? $elem->$member() : $elem->$member) < $value) {
                $this->_mask[$i] = $this->_state;
                if (++$limitChk >= $limit) {
                    break;
                }
            }
        }
    }
Thinking about __call() but that would involve a switch (either slow or still bulky) or eval (bit greasey all over).
Weirdan, to the rescue? :P
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

make general iteration method and pass a comparator to it
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

I'd have to use eval then.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

I'd have to use eval then.
not really, either variable function or call_user_func would be sufficient
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

There's never a "have to use eval then" ;)
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Post by Weirdan »

There's never a "have to use eval then"
Extremely argueable position. Eval is there for a reason, just like any other function in PHP. But it's being used in all the wrong ways possible though...Image
User avatar
Benjamin
Site Administrator
Posts: 6935
Joined: Sun May 19, 2002 10:24 pm

Post by Benjamin »

You both have some weird looking avatars lol.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

astions wrote:You both have some weird looking avatars lol.
Thanks. I do find the hedgehog genitals somewhat disturbing however = : - P
Post Reply