PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0
Showing posts with label higher-order-functions. Show all posts
Showing posts with label higher-order-functions. Show all posts

Thursday, November 3, 2022

[FIXED] How can I invoke a function that returns a lambda which also accepts another lambda as its parameter ( () -> Unit ) -> Unit in Kotlin?

 November 03, 2022     function-call, higher-order-functions, kotlin, kotlin-function-type, lambda     No comments   

Issue

The Code A is from the question answered by Roman Y.

The Code A can work well when it invokes with background(appState)() {...}, why can't I remove parentheses ()?

But Code B fails when it invoke with background(appState) {...}, why?

And more Code C can work well when it invokes with val aa=background(appState) aa{...}, why?

Code A

@Composable
fun NiaApp(
        windowSizeClass: WindowSizeClass,
        appState: NiaAppState = rememberNiaAppState(windowSizeClass) 
) {
        NiaTheme {
            background(appState)() {
                Scaffold(
                    ...
                ) { padding ->
                  }
            }     
        }
}
    
@Composable
fun background(appState: NiaAppState): @Composable (@Composable () -> Unit) -> Unit =
        when (appState.currentDestination?.route) {
            ForYouDestination.route -> { content -> 
                NiaGradientBackground(content = content) }
                else -> { content -> NiaBackground(content = content) }
            } 

Code B

@Composable
fun NiaApp(
        windowSizeClass: WindowSizeClass,
        appState: NiaAppState = rememberNiaAppState(windowSizeClass) 
) {
        NiaTheme {
            background(appState){
                Scaffold(
                    ...
                ) { padding ->
                  }
            }     
        }
}

...

Code C

@Composable
fun NiaApp(
        windowSizeClass: WindowSizeClass,
        appState: NiaAppState = rememberNiaAppState(windowSizeClass) 
) {
        val aa=background(appState)

        NiaTheme {
            aa{
                Scaffold(
                    ...
                ) { padding ->
                  }
            }     
        }
}

...

Solution

This is more of a Kotlin function question than a Compose one, so we will omit all Jetpack Compose related codes here, leaving only Kotlin related context to keep everything in focus.

Lets first define key points and mark them with a character.

  • Key point A. Lambda invocaton : lambda .invoke is equal to ()
  • Key point B. Based on the Documentation

Passing trailing lambdas:

According to Kotlin convention, if the last parameter of a function is a function, then a lambda expression passed as the corresponding argument can be placed outside the parentheses:

...

If the lambda is the only argument in that call, the parentheses can be omitted entirely

...

We'll make the background function look like this without the @Composable annotation and the NiaAppState arg, leaving it with NO parameters, but we will keep the function calls the same just so we're on track. I also named the returning lambda's parameter for a clearer picture.

fun background() : (anotherLambda: () -> Unit) -> Unit { ... }

The Code A can work well when it invokes with background(appState)() {...}, why can't I remove parentheses ()?

But Code B fails when it invoke with background(appState) {...}, why?

Let's break down your CodeA and CodeB at the same time to answer your 2 questions above. But remember, we are using our own background function and not the compose one.

1:

Start first by a simple invocation, here we are just calling the background function, and disregarding the value that it returns, nothing unusual here

background()

2:

While here, we are calling the background function, but also INVOKING the returned lambda (Key point A) immediately, we will get a compile error here 'No value passed for parameter anotherLambda' because when we INVOKE it, it requires US to PASS an argument to it which is a type of () -> Unit

background()() // <-- compile error: No value passed for parameter anotherLambda

3: The Code A can work well when it invokes with background(appState)() {...}

Here the compile error disappears when we specified the lambda block { ... } , because

  • We invoked the returned lambda (Key point A) immediately
  • And we supplied it with a lambda argument, and since the code follows Key point B it worked by simply calling the argument lambda's block { ... }
background()() {
   ...
}

4: But Code B fails when it invoke with background(appState) {...}, why?. Why can't I remove parentheses ()?

Here, we'll get another kind of error, 'Too many arguments for public fun background() ...'.

Because we are NOT INVOKING the returned lambda, we are simply calling the background() function itself and it doesn't have any lambda parameters or any parameters at all, check the background function signature we did above and Key point B.

And your actual background function has only one parameter (appState: NiaAppState) and it's not a lambda type parameter, again check Key point B.

background() {  // big chunk of compile error here: Too many arguments for public fun background() ...
   ...
}

5:

This is the version (check #3) without Key point B. We invoke the returned lambda (Key point A) immediately and pass a lambda argument inside of it.

background () ( {
   ...
} )

Equivalent background() calls using the lambda's invoke() instead of a parenthesis ():

// #2
background().invoke() // <-- compile error: No value passed for parameter anotherLambda

// #3
background().invoke {
   ...
}

// #4
background(invoke { // big chunk of compile error here: Too many arguments for public fun background() ... and Unresolved reference invoke
   ...
} )

// #5
background().invoke ( {
    ...
} )

And more Code C can work well when it invokes with val aa=background(appState) aa{...}, why?

Finally lets break down CodeC:

1:

Here we call the background function, and because we have an assignment operation with the type inferred, aa is now the returned lambda value from background() invocation

val aa = background()

// your actual background function equivalent
val aa = background(appState)

2:

Assignment declaration with specified type.

// aa assignment declaration with type specified
val aa : (() -> Unit) -> Unit = background()

// your actual background function equivalent
val aa : @Composable (@Composable () -> Unit) -> Unit  = background(appState)

3:

Assignment declaration with specified type and with a defined name for aa's lambda parameter.

// aa assignment declaration with type specified and named parameter
val aa : (aaLambdaParam : () -> Unit) -> Unit = background()

// your actual background function equivalent
val aa : @Composable (aaLambdaParam: @Composable () -> Unit) -> Unit  = background(appState)

4:

aa is the returned lambda that accepts an argument of type () -> Unit and because of Key point B, we can omit the parenthesis and directly call the block {...} of the passing lambda argument

aa {
   ...
}

5:

But if we call it this way, we'll get an error, 'No value passed for parameter ...', because aa is now a function that expects an argument of type () -> Unit, see Key point A.

aa() // <-- No value passed for parameter 'p1' (#2) or 'No value passed for parameter 'aaLambdaParam' (#3)

6:

This is the version (check #4) without Key point B. We invoke the lambda (Key point A) and pass a lambda argument inside of it.

aa ( {
   ...
} )

Equivalent aa calls using the lambda's invoke() instead of a parenthesis ():

// #4, Key point B
aa.invoke {
   ...
}

// #5
aa.invoke() // <-- No value passed for parameter 'p1' or 'aaLambdaParam'

// #6, not Key point B
aa.invoke( {
   ...
} )

I would suggest re-visiting Kotlin's High-Order Functions and Lambdas.



Answered By - z.y
Answer Checked By - Terry (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Monday, September 5, 2022

[FIXED] How can I explode and trim whitespace?

 September 05, 2022     explode, higher-order-functions, php, trim     No comments   

Issue

For example, I would like to create an array from the elements in this string:

$str = 'red,     green,     blue ,orange';

I know you can explode and loop through them and trim:

$arr = explode(',', $str);
foreach ($arr as $value) {
    $new_arr[] = trim($value);
}

But I feel like there's a one line approach that can handle this. Any ideas?


Solution

You can do the following using array_map:

$new_arr = array_map('trim', explode(',', $str));


Answered By - SeanWM
Answer Checked By - Candace Johnson (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg

Wednesday, July 6, 2022

[FIXED] Why does my std::ref not work as expected?

 July 06, 2022     c++, higher-order-functions, pass-by-reference, pass-by-value, reference     No comments   

Issue

std::ref gives you a lvalue-reference to something. This reference is wrapped into an object that you can then pass around either by reference or by value.

The expected behavior of the code below is that it prints i is 2, but it prints i is 1. Why is that?

Why do I have this expectation? Because I am passing tmp via std::ref to wrapper. In wrapper the reference is then captured by value. I would have assumed that, since I am using std::ref this value is now still a reference to tmp. I am changing tmp and would expect that f reflects that change.

Play with the code here.

#include <iostream>
#include <functional>

template<typename F>
auto wrapper(int i, F func) {
    return [=]() { return func(i); };
}

void f(int i) {
    std::cout << "i is " << i << '\n';
}

int main() {
    int tmp = 1;
    auto func = wrapper(std::ref(tmp), f);
    tmp = 2;
    func();
}

Solution

The reason this does not work is because your wrapper function takes an int as argument.

std::ref returns a std::reference_wrapper. When you pass it to a function that wants an int you will get an implicit conversion and you arre no longer working with a reference.

If you change your function signature to use a std::reference_wrapper it will give the intended result.

#include <iostream>
#include <functional>

template<typename F>
auto wrapper(std::reference_wrapper<int> i, F func) {
    return [=]() { return func(i); };
}

void f(int i) {
    std::cout << "i is " << i << '\n';
}

int main() {
    int tmp = 1;
    auto func = wrapper(std::ref(tmp), f);
    tmp = 2;
    func();
}


Answered By - super
Answer Checked By - Willingham (PHPFixing Volunteer)
Read More
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Older Posts Home

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
All Comments
Atom
All Comments

Copyright © PHPFixing