【发布时间】:2019-05-10 22:43:56
【问题描述】:
对于标量(即非类数组)可选参数,我会使用这种模式:
[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test1 ([<ExcelArgument(Description= "Optional. This is a double. Default is 42.0.")>] arg1 : obj) : double =
match arg1 with
| :? ExcelMissing -> 42.0 // the argument was missing
| :? double as d -> d // the argument was a double
| _ -> -1.0 // otherwise
我不确定这段代码在 Excel-Dna / F# 中是否“惯用”,但它似乎“有效”。
但是我不确定如何处理可选的类似数组的参数。例如:
[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test2 ([<ExcelArgument(Description= "Optional. This is a double. Default is [42, 42].")>] arg1 : obj[]) : double[] =
match arg1.[0] with
| :? ExcelMissing -> [42.0; 42.0] |> List.toArray // the argument was missing OR it was an empty array
| :? double as d -> arg1 |> castToDouble // the argument was an array and its first argument was a double
| _ -> Array.empty // otherwise
以上似乎适用于大多数情况,但不允许正确处理边缘情况:例如,如果 arg1 是一个空数组。 (castToDouble是自定义的obj[] -> double[]转换函数)
在 F#/Excel-Dna 中处理 可选 双数组的正确/惯用方法是什么,然后我该如何重写 test_test2?
=========== 编辑 ===
按照 Govert 的建议,我尝试了以下方法:
[<ExcelFunction(Category= "Test", Description= "Test optional arguments.")>]
let test_test3 ([<ExcelArgument(Description= "Optional. This is a double. Default is [42, 42].")>] arg1 : obj) : double[] =
match arg1 with
| :? (double[]) as ds -> [1.0; 2.0] |> List.toArray // the argument was a array of double elements
| :? ExcelMissing -> [42.0; 42.0] |> List.toArray // the argument was missing OR it was an empty array
| _ -> Array.empty // otherwise
...但不幸的是,当我传递一个双精度数组(或其他任何东西)时,我得到了一个#NUM! 输出。只有当我什么都不传递时,我才能正确获得 [42.0, 42.0] 数组。
【问题讨论】:
-
最好将类型声明为 'obj',然后从那里检查。
-
谢谢,我试过了(请参阅我的编辑部分),但没有成功。我做错了什么?
-
“| :? (double[])” 真的适合你吗?我希望它以 obj 数组的形式出现。
-
另外,你不能真正返回 Array.empty 作为结果。这有几个问题,一个很明显,一个更微妙。明显的问题是您必须返回 Excel 一些它认为可以放入单元格(或多个单元格,如果您将 UDF 称为数组公式)中的内容。这意味着,数字(所有数字实际上都是浮点数)、字符串、布尔值或特殊的 Excel 错误值之一。 Excel 不知道如何处理空数组。更微妙的问题是语义:在这种情况下,您打算返回错误值还是默认值?
-
@Jim Foye,
| :? (double[])似乎不匹配。| :? (obj[])也不匹配,但| :? (obj[,])匹配。