What is a Functor in Python?

Question:

I am new to Python. Can someone explain where the functor value is coming from. Functor = msg.functor, but there is no explanation for the word functor, I’ve tried googling it and came up with nothing. Also the .val keyword isn’t explained anywhere, I’m probably being dim but i cannot find any examples.

def process_action(self, msg, sender):  
    assert msg.get_type() == pedroclient.PObject.structtype
    functor = msg.functor
    assert functor.get_type() == pedroclient.PObject.atomtype
    cmd_type = functor.val
    cmd = msg.args[0]
    if cmd_type == 'stop_':
        assert cmd.get_type() == pedroclient.PObject.structtype
        cmd_functor = cmd.functor.val
        #if cmd_functor in ['pickup', 'putdown']:
        self.stop_arm(cmd.args[0].val)
        #else:
        #    self.stop_arm(cmd.args[0].val)

    elif cmd_type in ['start_', 'mod_']:
        self.start_animate()
        assert cmd.get_type() == pedroclient.PObject.structtype
        cmd_functor = cmd.functor.val
        if cmd_functor == 'pickup':
            self.pickup(cmd.args[0].val, cmd.args[1].val, sender)
        elif cmd_functor == 'putdown':
            if cmd.args[1].get_type() == pedroclient.PObject.inttype:
                self.putdown_on_block(cmd.args[0].val, cmd.args[1].val, 
                                      sender)
            else:
                self.putdown_on_table(cmd.args[0].val, cmd.args[1].val, 
                                      sender)
        elif cmd_functor == 'go_home':
             self.go_home(cmd.args[0].val)

Edit: Sorry there is a lot more code, I have skimmed it as much as i could.

def process_msg(self, term):
    msg = term.args[2]
    sender_process = term.args[1].args[0].args[1].val
    robotID = int(sender_process[-1])-1
    #print msg
    if str(msg) == "initialise_":
        robotID = int(sender_process[-1])-1

def data_cb(self, event):
    self.env.process_msg(event.notification)

The best I can understand it is that the functor is an attribute of msg, which in turn is the argument of system input, where system input is a event notification. Am i correct or completely going of in the wrong direction.

Asked By: MFree

||

Answers:

functor is an attribute of the msg object; without seeing the definition of that object we can’t tell you anything more. Similarly, val is in turn an attribute of msg.

Answered By: Daniel Roseman

Searching via Google I have found documentation, which shall probably explain part of your :
The Pedro 1.6 Reference Manual

Regarding the functor I did not find a not about that (but did not spend much time on it). It is likely, Pedro is used as messaging system for sending commands to some (real or virtual) robot. The robot is controlled by messages, which have some structure, including functor, being probably identification of what type of action shall be performed, and values, which are are defining parameters of that action.

Answered By: Jan Vlcinsky

Since Python allows passing functions as values a Functor is basically an object which is a function. Note that on the code that you post you are comparing many times which function is this.

On the line cmd_type = functor.val you actually attributed to cmd_type the function itself and later on you compare it to know which function it is exactly.

if cmd_type == 'stop_':
is the function stop()?

elif cmd_type in ['start_', 'mod_']:
is one of these functions, start(), mod()?

And so on… Further reading here

Edit: I found this topic to be very related to understand the concept of functors, though it doesn’t quotes python but python has a lot of Functional programming features.

Answered By: user5245279

Basic stuff – msg & functor might be in these places:

  • Defined in this file
  • In a local module that is imported by the import statements at the top of this file, this would be a .py file in the directory structure of the app
  • In an installed package from someone else

.val – this is most likely an attribute containing data. It is not a Python keyword of any kind that I can find. I’m sure you thought that it is probably short for “value”. It is either defined in the objects it is a part of (functor, cmd.args[]) or in some superior object that they import and thus inherit val from.

Answered By: JackW327

A functor (also known as a "function object"), is something other than a function which behaves like a function; a functor is like a function, but with more extra code added, which is a good thing sometimes.

Normally, we have classes like this:

class HoundDog:
    """
        The `Dog` class is a dog-making machine. 
        It makes dogs.  
        Each dog has a name.
    """  

   def __init__(this_dog, name:str):
       this_dog._name = str(name)  

We have a problem: Dogs made from the class shown above does not like parentheses.

copper = HoundDog()
balto  = HoundDog()
chief  = HoundDog()

result = copper()
# error!, 
# ERROR!!, 
# ERROR!!!

# parentheses, such as `()`, are not allowed to the right of a dog, such as
# copper, balto, chief, or other good dogs from themovie "Fox and the Hound" (1981)   

We have to define a method named __call__ in order to create a class object which behaves like a function.

class HoundDog:
    """
        The `Dog` class is a dog-making machine. 
        It makes dogs.  
        Each dog has a name.
    """  

   def __init__(this_dog, name:str):
       this_dog._name = str(name)  

Below is another example of a functor (a function object):

# inky_the_inkrementor is a functor. 

inky_the_inkrementor = Inkrementor(1)
# running total is 1

inky_the_inkrementor(10)
# running total is 11

inky_the_inkrementor(100) 
# running total is 111

inky_the_inkrementor(1000)
# running total is 1111

inky_the_inkrementor(10000) 
# running total is 11111

inky_the_inkrementor(100000)
# running total is 111111

inky_the_inkrementor(9)(1)(10)(100) # 
# running total is 111111

inky_the_inkrementor(500000, 50000, 5000)
# the running total is 

inky_the_inkrementor(9*10**9)(8*10**8, 7*10**7)

print(int(inky_the_inkrementor))
# prints 9871555111

In the mess of code below, is might be best to focus on the fact that there is a method named __call__:


class Inkrementor:
    # also known as...
    # ... an "ACCUMULATOR"
    # ... a running total               

    def __init__(this, *args):
        this._num = 0
        this(*args)

    def __call__(this, *args):
        # convert args[0] into a decimal number, such as 53.91982
        dn = float(args[0])

        # assign the decimal number to a variable named `left`
        left = float(dn)

        # add the left-overs altogether recursively  
        leftovers  = this(*args[1:])

        this._num += left
        this._num += leftovers 
        this._num = sum(float(arg) for arg in args) 
        

    def __float__(this):
        return this._num    

What makes functors useful is that you can store so-called state variables inside of a function-like-thing which has inputs and outputs.

Answered By: Samuel Muldoon
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.