Elia Giaccardi Old
Elia Giaccardi Old

Reputation: 262

Call function with a parameter from another function

I have a function that repeatedly calls another function.

The second function has a bool parameter that changes the way it behaves, so when I call the first function I want to have a parameter that specifies the way the second function behaves.

void Function1(int n, bool differentBehavior = false)
{
    int a = Function2(n, differentBehavior);
    int b = Function2(1, differentBehavior);
    int c = Function2(2, differentBehavior);

    return a + b + c;
}

int Function2(int x, bool differentBehavior)
{
     if (!differentBehavior) // do something
     else // do something else
 }

The code itself is obviously an example (in reality the second function is called over 20 times and for code readability I would love to not have to specify the second parameter every time), but I put it there to explain what I'm currently doing. Is there no better way to achieve this?

Upvotes: 1

Views: 2437

Answers (3)

IV.
IV.

Reputation: 9148

One thing to look at when a lot of parameters are being passed on the stack is whether there is some higher-level state that could be represented by a member variable of the class.

Here's some code for the most basic kind of state machine. This general approach might help solve the problem you're having:

class Program
{
    enum Behaviors
    {
        BehaviorA,
        BehaviorB,
        BehaviorC,
    }
    static Behaviors State { get; set; }
    static void Main(string[] args)
    {
        for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
        {
            Console.WriteLine($"Function returned { Function1(0)}");
        }

        int Function1(int n)
        {
            int a = Function2(n);
            int b = Function2(1);
            int c = Function2(2);

            return a + b + c;
        }
        int Function2(int x)
        {
            switch (State)
            {
                case Behaviors.BehaviorA:
                    return x * 10;
                case Behaviors.BehaviorB:
                    return x * 20;
                case Behaviors.BehaviorC:
                    return x * 30;
                default:
                    throw new NotImplementedException();
            }
        }
    }
}

Upvotes: 1

Dai
Dai

Reputation: 155105

While C# doesn't support true function Currying nor first-class partial function application, you can always use a new locally scoped function (aka a local function) to wrap your Function2 with predefined arguments... which is conceptually almost the same thing as partial application, just without referential-transparency, and awkward delegate types.


Anyway, if you want to pass the outer Function1's differentBehavior argument value to Function2 then you will need to use a closure, which will capture the variable, but this will introduce slight runtime performance complications: as a closure generally means a GC heap allocation and copying function local state from the stack onto the heap and yada yada.

However, if you're only using constant parameter values - or you're okay with using different wrappers for different predefined argument values, then you can use a static local function (requires C# 8.0 or later) which prevents you from unintentionally creating a closure.


For example:

void Function1(int n, bool differentBehavior = false)
{
    // Look ma, no closure!
    static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
    static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );

    int a = PartiallyAppliedFunc2_False(n);
    int b = PartiallyAppliedFunc2_False(1);
    int c = PartiallyAppliedFunc2_True(2);

    return a + b + c;
}

int Function2(int x, bool differentBehavior)
{
     if (!differentBehavior) // do something
     else // do something else
 }

Upvotes: 2

Matthew Watson
Matthew Watson

Reputation: 109567

You can introduce a local function to capture the second argument like so:

int Function1(int n, bool differentBehavior = false)
{
    int func(int n) => Function2(n, differentBehavior);

    int a = func(n);
    int b = func(1);
    int c = func(2);

    return a + b + c;
}

This is called "partial function application". See more here:

https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/

Upvotes: 4

Related Questions