6

I'd like to do something like this:

{ param -> if ( <condition over param> ) process ( param ) } ( provider () );

i.e., param is a value returned by a method (which, let's say, takes a long time to run, so I want to invoke it once only) and I want to pass on such value only if it fulfils a condition.

The alternative would be:

Param param = provider(); if ( <cond> ) process ( param );

But the lambda-based version, if I could make it working, would be shorter. The code above doesn't compile in Java and I cannot figure out if what I'm thinking about is possible and how.

4
  • Well, as your question shows, the alternative, which compiles, is actually shorter. And it's also much clearer. Commented Oct 24, 2016 at 10:56
  • 1
    "" is never equal to an instance of Param. Further, process seems to take a parameter in one variant, but no parameters in the other… Commented Oct 24, 2016 at 11:03
  • Yes, sorry, I'll rewrite it. Commented Oct 24, 2016 at 11:52
  • "shorter", I don't know why I feel like something similar to the first form look better, especially when I have many likes like that. Maybe I'm becoming addicted to functional programming, closures and the like :-) Commented Oct 24, 2016 at 11:59

4 Answers 4

6

Well, you can do something like

                                        // use Type::process for a static method
Stream.of(provider()).filter( «cond» ).forEach(this::process);

though there is really no benefit over an ordinary imperative statement here

If you want to limit the scope of the newly introduced variable, you can create a block.

{ Param param = provider(); if( «cond» ) process(param); }

and, as a side note, debugging will be much easier with this conventional construct.

Sign up to request clarification or add additional context in comments.

Comments

2

Thanks all for your replies. I've found an approach similar to what @Holger suggests:

Optional.of ( provider() ).map ( v -> { if ( <cond> ) process ( v ); return null; } )

(return only needed if process() returns void). I agree it's quicker to define an intermediate variable and probably I'll end up to do so. Yet, there must be some psychological reasons why I'm attracted more to functional forms like the above. When they're many, they seem quicker to write, maybe because you don't need to think of new variable names (you need multiple variable definitions if there are different types involved).

Comments

2

Following complete example program has syntax that is fairly close to what you said you would like. This depends on a generic "invoke" function that can be used for other similar scenarios. The body of the lambda needs to be in braces as it is a statement, not an expression. The example has String param type but it could be any type.

import java.util.function.Consumer;

public class invoke_lambda_directly
{
    void run()
    {
        invoke(param -> { if (param.equals("x")) process(param); }, provider() );
    }

    private void process(String p) { System.out.println("processed " + p); }

    private String provider() { return "x"; }

    public static <T> void invoke(Consumer<T> i, T t) { i.accept(t); }

    public static void main(String args[])
    {
        new invoke_lambda_directly().run();
    }
}

3 Comments

that's nice, but my question was basically how to use lambdas to define a function in line and immediately invoke it, without too many definitions.
The only dependency is the one-liner "invoke" function. I would put it in something like a "Lambdas" class in a library and add an "import static org.mine.utility.Lambas.invoke" at the top of any class wanting to invoke a "Consumer" lambda directly.
yes, it's interesting. I was thinking that sometimes I would need to do this for multi-param lambdas, but that too could be arranged in a utility method. Thanks.
1

Without knowing your exact situation I'd agree with JB Nizet's comment, that the alternative solution is preferrable. Apart from that, to write it as a lambda expression, you just need to change some punctuation. Furthermore, the functional interface which the lambda expression implements, must be known, for example a java.util.function.Consumer:

    Consumer<Param> consumer = param -> { if ( !"".equals ( param ) ) process ( param ); };
    consumer.accept(provider());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.