Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
return
#1
the language i created long ago that was never finished did returns not as a statement, but as a function call. this was a unique function in each function. so a function could pass its own return function as a value to another function which could call it and that would "return" to where this function that passed return was called. it was a way to let other functions do a return for a function.

i remember going to Python3 where the print statement became the print() function. i wondered about the return statement and even the del statement.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
What is the use case of each function having its own return function? Is there any benefit of this?
Reply
#3
function A calls function B. function B's logic can be arranged with more functions to various parts of B's purpose where those functions could decide that B needs to return and do that return (as long as they had B's return function).

i've run into these cases. what i did instead was have a special return (to B) value (typically None) or some other way to set a value that code in B could check, and then code B to test value and maybe do the return.

i often have big complex logic that nice and small when there are some function calls instead (many times def in the function that will call them). this makes it easier to read (12 lines instead of 48, for example).
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#4
I have a solution using a function object type from my personal library, the below class 'algorithm'
# algorithm/__init__.py
__version__ = '2019.06.18'

from functools import partial, singledispatch
import types

#========================================
# Obtention de la documentation
#========================================

def doctopic_assembly():
    """Returns a assembly of documentation topics for this module"""
    from .doc.main import doctopic_assembly
    return doctopic_assembly()

_property = property

@singledispatch
def property(func):
    return _property(func)

class algorithm_meta(type):
    def __new__(meta, class_name, bases, new_attrs):
        cls = type.__new__(meta, class_name, bases, new_attrs)
        return cls
    
    def __call__(cls, *args, **kwargs):
        instance = cls.__new__(cls)
        instance.kwargs = kwargs
        instance.__dict__.update(kwargs)
        return instance.run(*args)
        #try:
            #return instance.run(*args)
        #except TypeError:
            #print(instance, args)
            #raise

    def __get__(cls, obj, objtype=None):
        # This allows to use the algoritm type as a method
        if obj is None:
            return cls
        return partial(_algorithm_as_method, cls, obj)
    
    property = staticmethod(property)
    
def _algorithm_as_method(cls, obj, *args, **kwargs):
    instance = cls.__new__(cls)
    instance.o = obj
    instance.kwargs = kwargs
    instance.__dict__.update(kwargs)
    return instance.run(*args)

@property.register(algorithm_meta)
def _(cls):
    return _property(partial(_algorithm_as_method, cls))

class algorithm(metaclass=algorithm_meta):
    def run(self, *args):
        return self
To implement the desired behaviour, I now define a subclass 'returnable' of 'algorithm', then I'm ready to implement your tasks B() and A(). Look at the code starting from 'class B(returnable)'
# paillasse/pf/deepreturn.py - example code
from algorithm import algorithm

class Return(Exception):
    pass

class returnable(algorithm):
    def run(self, *args):
        try:
            return self.main(*args)
        except Return as exc:
            if exc.args[0] is self:
                return exc.args[1]
            else:
                raise
    
    def return_(self, value=None):
        raise Return(self, value)

class B(returnable):
    def main(self, x):
        self.subtask0(x)
        self.subtask1(x)
    
    def subtask0(self, x):
        if x == 0:
            self.return_('Hello!')
            
    def subtask1(self, x):
        if x == 1:
            self.return_('World!')
            
def A():
    print(B(0))
    print(B(1))
    print(B(2))
    
if __name__ == '__main__':
    A()
My output
Output:
λ python paillasse/pf/deepreturn.py Hello! World! None
By the way, it seems that the ability to return from any subtask is a nice improvement of the algorithm class. I'm considering incorporating this feature in the library. The main drawback I see is that the code is less explicit because something that looks like a function call may actually be a return statement.
Reply
#5
ah, nice solution!

i'd probably call in do_return() or proxy_return().
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020