如何将字符串转换为lambda表达式? [英] How to convert a string to a lambda expression?
问题描述
我想了一下并想出了一个有趣的问题,假设我们有一个配置(输入)文件:
I was thinking a bit and came up with an interesting problem, suppose we have a configuration (input) file with:
x -> x + 1
x -> x * 2
x -> x * x
x -> -x
此外,我们有一个整数列表
s:
And furthermore we have a list of Integer
s:
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.toList(1, 2, 3, 4, 5));
有没有办法转换字符串
s( x - > x + 1
等)到对象
表示lambda表达式?然后可以用作:
Is there a way to convert the String
s (x -> x + 1
, etc.) to Object
s that represent a lambda expression? Which could then be used as:
Object lambda = getLambdaFromString("x -> x + 1");
if (lambda.getClass().equals(IntFunction.class) {
list.stream().forEach()
.mapToInt(x -> x)
.map(x -> ((IntFunction)lambda).applyAsInt(x))
.forEach(System.out::println);
}
我如何编写这样的方法 getLambdaFromString
?
How would I write such a method getLambdaFromString
?
- 我可以从JDK / JRE中重复使用吗?
- 我是否需要自己编写所有内容?
- 是否可以将
Object lambda
缩小到仅捕获lambdas的其他内容?
- Is there something I could reuse from the JDK/JRE?
- Would I need to write it all by myself?
- Is it possible to narrow down the
Object lambda
to something else that only captures lambdas?
推荐答案
Marko对这个问题的评论是正确的。你不能从文件中读取一个简单的Java lambda表达式,因为这样的表达式没有定义上下文提供的目标类型。例如,考虑以下方法声明:
Marko's comment on the question is correct. You can't read a bare Java lambda expression out of a file, since such an expression isn't defined without a target type provided by the context. For example, consider the following method declarations:
void method1(BiFunction<String,String,String> f) { ... }
void method2(BiFunction<Integer,Integer,Integer> f) { ... }
然后在下面的代码中,
method1((x, y) -> x + y);
method2((x, y) -> x + y);
两个lambda表达式(x,y) - > x + y
意味着完全不同的事物。对于method1, +
运算符是字符串连接,但对于method2,它表示整数加法。
the two lambda expressions (x, y) -> x + y
mean completely different things. For method1, the +
operator is string concatenation, but for method2, it means integer addition.
这是徘徊你的问题有点远,但你可以使用动态语言阅读和评估lambda或函数表达式。在Java 8中有Nashorn JavaScript引擎。因此,您可以使用从Java调用的Nashorn来读取和评估 JavaScript 函数,而不是尝试读取Java lambda表达式。
This is wandering a bit far afield from your question, but you can read and evaluate a lambda or function expression using a dynamic language. In Java 8 there is the Nashorn JavaScript engine. So instead of attempting to read an evaluate a Java lambda expression, you could read and evaluate a JavaScript function using Nashorn, called from Java.
以下代码在arg [0]中使用函数并将其应用于每个后续函数,打印结果:
The following code takes a function in arg[0] and applies it to each subsequent, printing the results:
import java.util.function.Function;
import javax.script.*;
public class ScriptFunction {
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
@SuppressWarnings("unchecked")
Function<Object,Object> f = (Function<Object,Object>)engine.eval(
String.format("new java.util.function.Function(%s)", args[0]));
for (int i = 1; i < args.length; i++) {
System.out.println(f.apply(args[i]));
}
}
}
例如,运行命令
java ScriptFunction 'function(x) 3 * x + 1' 17 23 47
给出结果
52.0
70.0
142.0
函数字符串的包装在中新的java.util.function.Function
是必要的,以便在Nashorn的JavaScript函数概念和Java的Function接口之间创建一个适配器。 (可能有更好的方法,但我不知道一个。) eval
的返回值转换为函数< Object,对象>
导致未经检查的强制转换警告,我认为这是不可避免的,因为这是JavaScript(动态类型语言)和Java(静态类型)之间的边界。最后,没有进行错误检查。如果某些假设被违反,我肯定会以各种令人讨厌的方式爆炸,例如第一个参数实际上并不代表JavaScript函数。
The wrapping of the function string inside of new java.util.function.Function
is necessary in order to create an adapter between Nashorn's notion of a JavaScript function and Java's Function interface. (There might be a better way, but I'm not aware of one.) The cast of the return value of eval
to Function<Object,Object>
results in an unchecked cast warning, which is unavoidable, I think, since this is the boundary between JavaScript, a dynamically-typed language, and Java, which is statically-typed. Finally, no error checking is done. I'm sure this will blow up in a variety of nasty ways if certain assumptions are violated, such as the first argument not actually representing a JavaScript function.
仍然,你如果您需要评估从文件中读取的表达式或函数,可能会发现此技术很有用。
Still, you might find this technique useful if you have a need to evaluate expressions or functions read from a file.
这篇关于如何将字符串转换为lambda表达式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!