Dataweave 中的尾递归
Tail Recursion in Dataweave
有没有办法采用递归函数(如下所示)并使其尾递归?我有这样的输入:
{
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
和这个 Dataweave 函数
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {
($$): $ match {
case is String -> trim($)
case is Object -> trimWS($)
case is Array -> $ map trimWS($)
else -> $
}
}
case is String -> trim($)
else -> $
}
我对您现有的功能进行了一些修改以简化它,我还 运行 在 Mule 4.2.1 下进行了一些测试。
通过构建深度超过 840 层的数据结构,我能够导航 trim 字段。我的猜测是由于数据的结构和懒惰的评估,我能够超过 256 深度,这是 DW 2.0 抛出 Whosebug 的默认值。
您还可以通过传递 运行time 参数来增加默认值,它的名称是 com.mulesoft.dw.stacksize
(例如 com.mulesoft.dw.stacksize=500
)或您的系统可以处理的任何其他数字。
正如我所说,创建一个尾递归版本并不容易,它会使代码复杂化,与现有版本相比,它的可维护性会大大降低,等等。
即使我没有直接回答你的问题,我也希望它能对你有所帮助。
%dw 2.0
output application/json
var ds = {
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
var deepData = (0 to 840) as Array reduce (e, acc=ds) -> {value: " TO_TRIM ",next: acc}
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {($$): trimWS($)}
case is String -> trim($)
else -> $
}
---
trimWS(deepData)
我注意到这个函数通过了@TailRec()注解测试。
%dw 2.0
output application/json
var in1 = [
{"id": "1", "environment": "dev"},
{"id": "2", "environment": "test"},
{"id": "3", "environment": "uat"},
{"id": "4", "environment": "prod"},
{"id": "2", "environment": "test"}
]
@TailRec()
fun format(x: Any, formatter: (String)-> String) =
x match {
case obj is Object -> obj mapObject (format($$,formatter)): format($,formatter)
case arr is Array -> arr map format($,formatter)
case key is Key -> formatter(key as String) as Key
case str is String -> formatter(str)
else -> format(null, formatter)
}
---
format(in1, upper )
我也可以得到 orig 函数通过这个测试:
%dw 2.0
output application/json
var ds = {
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
var deepData = (0 to 700) as Array reduce (e, acc=ds) -> {value: " TO_TRIM ",next: acc}
@TailRec()
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {($$): trimWS($)}
case is String -> trim($)
//case other if( !(other is Null ))-> other
case other if(true) -> other
else -> trimWS($)
}
---
trimWS(deepData)
但是这些都不是尾递归的。
有没有办法采用递归函数(如下所示)并使其尾递归?我有这样的输入:
{
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
和这个 Dataweave 函数
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {
($$): $ match {
case is String -> trim($)
case is Object -> trimWS($)
case is Array -> $ map trimWS($)
else -> $
}
}
case is String -> trim($)
else -> $
}
我对您现有的功能进行了一些修改以简化它,我还 运行 在 Mule 4.2.1 下进行了一些测试。
通过构建深度超过 840 层的数据结构,我能够导航 trim 字段。我的猜测是由于数据的结构和懒惰的评估,我能够超过 256 深度,这是 DW 2.0 抛出 Whosebug 的默认值。
您还可以通过传递 运行time 参数来增加默认值,它的名称是 com.mulesoft.dw.stacksize
(例如 com.mulesoft.dw.stacksize=500
)或您的系统可以处理的任何其他数字。
正如我所说,创建一个尾递归版本并不容易,它会使代码复杂化,与现有版本相比,它的可维护性会大大降低,等等。
即使我没有直接回答你的问题,我也希望它能对你有所帮助。
%dw 2.0
output application/json
var ds = {
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
var deepData = (0 to 840) as Array reduce (e, acc=ds) -> {value: " TO_TRIM ",next: acc}
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {($$): trimWS($)}
case is String -> trim($)
else -> $
}
---
trimWS(deepData)
我注意到这个函数通过了@TailRec()注解测试。
%dw 2.0
output application/json
var in1 = [
{"id": "1", "environment": "dev"},
{"id": "2", "environment": "test"},
{"id": "3", "environment": "uat"},
{"id": "4", "environment": "prod"},
{"id": "2", "environment": "test"}
]
@TailRec()
fun format(x: Any, formatter: (String)-> String) =
x match {
case obj is Object -> obj mapObject (format($$,formatter)): format($,formatter)
case arr is Array -> arr map format($,formatter)
case key is Key -> formatter(key as String) as Key
case str is String -> formatter(str)
else -> format(null, formatter)
}
---
format(in1, upper )
我也可以得到 orig 函数通过这个测试:
%dw 2.0
output application/json
var ds = {
"message": "Test ",
"read": [
{
"test": " t "
}
]
}
var deepData = (0 to 700) as Array reduce (e, acc=ds) -> {value: " TO_TRIM ",next: acc}
@TailRec()
fun trimWS(item) = item match {
case is Array -> $ map trimWS($)
case is Object -> $ mapObject {($$): trimWS($)}
case is String -> trim($)
//case other if( !(other is Null ))-> other
case other if(true) -> other
else -> trimWS($)
}
---
trimWS(deepData)
但是这些都不是尾递归的。