| /******************************************************************************* |
| * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| *******************************************************************************/ |
| package org.eclipse.xtext.xbase.lib; |
| |
| import org.eclipse.xtext.xbase.lib.Functions.Function0; |
| import org.eclipse.xtext.xbase.lib.Functions.Function1; |
| import org.eclipse.xtext.xbase.lib.Functions.Function2; |
| import org.eclipse.xtext.xbase.lib.Functions.Function3; |
| import org.eclipse.xtext.xbase.lib.Functions.Function4; |
| import org.eclipse.xtext.xbase.lib.Functions.Function5; |
| import org.eclipse.xtext.xbase.lib.Functions.Function6; |
| import org.eclipse.xtext.xbase.lib.Procedures.Procedure0; |
| import org.eclipse.xtext.xbase.lib.Procedures.Procedure1; |
| |
| import com.google.common.annotations.GwtCompatible; |
| |
| /** |
| * This is an extension library for {@link Functions functions}, e.g. closures. |
| * |
| * @author Sven Efftinge - Initial contribution and API |
| * @see Functions |
| */ |
| @GwtCompatible public class FunctionExtensions { |
| |
| /** |
| * Curries a function that takes one argument. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed argument. |
| * @return a function that takes no arguments. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, RESULT> Function0<RESULT> curry(final Function1<? super P1, ? extends RESULT> function, final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function0<RESULT>() { |
| @Override |
| public RESULT apply() { |
| return function.apply(argument); |
| } |
| }; |
| } |
| |
| /** |
| * Curries a function that takes two arguments. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed first argument of {@code function}. |
| * @return a function that takes one argument. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, P2, RESULT> Function1<P2, RESULT> curry(final Function2<? super P1, ? super P2, ? extends RESULT> function, |
| final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function1<P2, RESULT>() { |
| @Override |
| public RESULT apply(P2 p) { |
| return function.apply(argument, p); |
| } |
| }; |
| } |
| |
| /** |
| * Curries a function that takes three arguments. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed first argument of {@code function}. |
| * @return a function that takes two arguments. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, P2, P3, RESULT> Function2<P2, P3, RESULT> curry(final Function3<? super P1, ? super P2, ? super P3, ? extends RESULT> function, |
| final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function2<P2, P3, RESULT>() { |
| @Override |
| public RESULT apply(P2 p2, P3 p3) { |
| return function.apply(argument, p2, p3); |
| } |
| }; |
| } |
| |
| /** |
| * Curries a function that takes four arguments. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed first argument of {@code function}. |
| * @return a function that takes three arguments. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, P2, P3, P4, RESULT> Function3<P2, P3, P4, RESULT> curry( |
| final Function4<? super P1, ? super P2, ? super P3, ? super P4, ? extends RESULT> function, final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function3<P2, P3, P4, RESULT>() { |
| @Override |
| public RESULT apply(P2 p2, P3 p3, P4 p4) { |
| return function.apply(argument, p2, p3, p4); |
| } |
| }; |
| } |
| |
| /** |
| * Curries a function that takes five arguments. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed first argument of {@code function}. |
| * @return a function that takes four arguments. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, P2, P3, P4, P5, RESULT> Function4<P2, P3, P4, P5, RESULT> curry( |
| final Function5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends RESULT> function, final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function4<P2, P3, P4, P5, RESULT>() { |
| @Override |
| public RESULT apply(P2 p2, P3 p3, P4 p4, P5 p5) { |
| return function.apply(argument, p2, p3, p4, p5); |
| } |
| }; |
| } |
| |
| /** |
| * Curries a function that takes six arguments. |
| * |
| * @param function |
| * the original function. May not be <code>null</code>. |
| * @param argument |
| * the fixed first argument of {@code function}. |
| * @return a function that takes five arguments. Never <code>null</code>. |
| */ |
| @Pure |
| public static <P1, P2, P3, P4, P5, P6, RESULT> Function5<P2, P3, P4, P5, P6, RESULT> curry( |
| final Function6<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? super P6, ? extends RESULT> function, final P1 argument) { |
| if (function == null) |
| throw new NullPointerException("function"); |
| return new Function5<P2, P3, P4, P5, P6, RESULT>() { |
| @Override |
| public RESULT apply(P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { |
| return function.apply(argument, p2, p3, p4, p5, p6); |
| } |
| }; |
| } |
| |
| |
| /** |
| * Returns a composed function that first applies the {@code before} |
| * function to its input, and then applies the {@code after} function to the result. |
| * If evaluation of either function throws an exception, it is relayed to |
| * the caller of the composed function. |
| * |
| * @param <V> the type of input to the {@code before} function, and to the |
| * composed function |
| * @param <T> the type of output of the {@code before} function, and input to the |
| * {@code after} function |
| * @param <R> the type of output to the {@code after} function, and to the |
| * composed function |
| * @param after the function to apply after the before function is applied |
| * @param before the function to apply before the after function is applied |
| * @return a composed function that first applies the {@code before} |
| * function and then applies the {@code after} function |
| * @throws NullPointerException if {@code before} or {@code after} is <code>null</code> |
| * |
| * @see #andThen(Functions.Function1, Functions.Function1) |
| * @since 2.9 |
| */ |
| public static <V,T,R> Function1<V, R> compose(final Function1<? super T, ? extends R> after, final Function1<? super V, ? extends T> before) { |
| if (after == null) |
| throw new NullPointerException("after"); |
| if (before == null) |
| throw new NullPointerException("before"); |
| return new Function1<V,R>() { |
| @Override |
| public R apply(V v) { |
| return after.apply(before.apply(v)); |
| } |
| }; |
| } |
| |
| /** |
| * Returns a composed function that first applies the {@code before} |
| * function to its input, and then applies the {@code after} function to the result. |
| * If evaluation of either function throws an exception, it is relayed to |
| * the caller of the composed function. |
| * |
| * @param <V> the type of input to the {@code before} function, and to the composed function |
| * @param <T> the type of output of the {@code before} function, and input to the {@code after} function |
| * @param <R> the type of output to the {@code after} function, and to the composed function |
| * @param before the function to apply before the after function is applied |
| * @param after the function to apply after the before function is applied |
| * @return a composed function that first applies the {@code before} |
| * function and then applies the {@code after} function |
| * @throws NullPointerException if {@code before} or {@code after} is <code>null</code> |
| * |
| * @see #compose(Functions.Function1, Functions.Function1) |
| * @since 2.9 |
| */ |
| public static <V,T,R> Function1<V, R> andThen(final Function1<? super V, ? extends T> before, final Function1<? super T, ? extends R> after) { |
| return compose(after, before); |
| } |
| |
| /** |
| * Returns a composed function that first applies the {@code before} |
| * function to its input, and then applies the {@code after} function to the result. |
| * If evaluation of either function throws an exception, it is relayed to |
| * the caller of the composed function. |
| * |
| * @param <V1> the type of the first parameter to the {@code before} function, and to the composed function |
| * @param <V2> the type of the second parameter to the {@code before} function, and to the composed function |
| * @param <T> the type of output of the {@code before} function, and input to the {@code after} function |
| * @param <R> the type of output to the {@code after} function, and to the composed function |
| * @param before the function to apply before the {@code after} function is applied |
| * @param after the function to apply after the {@code before} function is applied |
| * @return a composed function that first applies the {@code before} |
| * function and then applies the {@code after} function |
| * @throws NullPointerException if {@code before} or {@code after} is null |
| * |
| * @see #compose(Functions.Function1, Functions.Function1) |
| * @since 2.9 |
| */ |
| public static <V1,V2,T,R> Function2<V1, V2, R> andThen(final Function2<? super V1,? super V2, ? extends T> before, final Function1<? super T, ? extends R> after) { |
| if (after == null) |
| throw new NullPointerException("after"); |
| if (before == null) |
| throw new NullPointerException("before"); |
| return new Function2<V1, V2, R>() { |
| @Override |
| public R apply(V1 v1, V2 v2) { |
| return after.apply(before.apply(v1, v2)); |
| } |
| }; |
| } |
| |
| |
| /** |
| * Returns a composed {@code Procedure1} that performs, in sequence, the {@code before} |
| * operation followed by the {@code after} operation. If performing either |
| * operation throws an exception, it is relayed to the caller of the |
| * composed operation. If performing the {@code before} operation throws an exception, |
| * the {@code after} operation will not be performed. |
| * |
| * @param <T> the type of input for the {@code before} operation |
| * @param before the operation to perform first |
| * @param after the operation to perform afterwards |
| * @return a composed {@code Procedure1} that performs in sequence the {@code before} |
| * operation followed by the {@code after} operation |
| * @throws NullPointerException if {@code before} or {@code after} is null |
| * @since 2.9 |
| */ |
| public static <T> Procedure1<T> andThen(final Procedure1<? super T> before, final Procedure1<? super T> after) { |
| if (after == null) |
| throw new NullPointerException("after"); |
| if (before == null) |
| throw new NullPointerException("before"); |
| return new Procedures.Procedure1<T>() { |
| @Override |
| public void apply(T p) { |
| before.apply(p); |
| after.apply(p); |
| } |
| }; |
| } |
| |
| /** |
| * Returns a composed {@code Procedure1} that performs, in sequence, the {@code before} |
| * operation followed by the {@code after} operation. If performing either |
| * operation throws an exception, it is relayed to the caller of the |
| * composed operation. If performing the {@code before} operation throws an exception, |
| * the {@code after} operation will not be performed. |
| * |
| * @param before the operation to perform first |
| * @param after the operation to perform afterwards |
| * @return a composed {@code Procedure1} that performs in sequence the {@code before} |
| * operation followed by the {@code after} operation |
| * @throws NullPointerException if {@code before} or {@code after} is null |
| * @since 2.9 |
| */ |
| public static Procedure0 andThen(final Procedure0 before, final Procedure0 after) { |
| if (after == null) |
| throw new NullPointerException("after"); |
| if (before == null) |
| throw new NullPointerException("before"); |
| return new Procedures.Procedure0() { |
| @Override |
| public void apply() { |
| before.apply(); |
| after.apply(); |
| } |
| }; |
| } |
| |
| } |