所有这些都从一个简单的想法开始:如何在ocaml中编写python样式的格式化字符串 .
pythoners可以初始化一个字符串:
str = "this var: %s" % this_var
str2 = "this: %s; that: %s" % (this_var, that_var)
但ocaml的格式化字符串代码为:
let str = Printf.sprintf "this var: %s" this_var
let str2 = Printf.sprintf "this: %s; that: %s" this_var that_var
我相信我可以做ochl字符串格式化代码python-like首先,我定义了一个函数如下:
let (%) s x = Printf.sprintf s x
那么,我可以直接写作:
let str = "this: %s" % "sth"
但是简单的函数不能处理两个或多个变量的更复杂的情况 . 所以我想编写一个复杂的函数来使它完美地模拟python方式 . 我写的如下:
let (%) s li =
let split_list = Str.full_split (regexp "%[a-z]") s in
let rec fmt result_str s_list x_list = match s_list with
| [] -> result_str
| shd::stl -> match shd with
| Text t -> fmt (result_str^t) stl x_list
| Delim d -> match x_list with
| [] -> fmt result_str stl []
| xhd::xtl -> fmt (result_str^(Printf.sprintf d xhd)) stl xtl
in
fmt "" split_list li
但是函数只是无法工作,因为类型错误和ocaml的列表不能包含多种类型 . 如果你写的像: "name: %s; age: %d" % ["John"; 20]
ocaml编译器世界嘲笑代码并告诉你一些类型错误 .
显然,我必须使用Tuple来替换List . 但我只是不知道如何尾递归一个可变长度的元组 .
任何建议都受到欢迎 . 我确实有两个问题 .
-
如何编写pythonic ocaml代码来格式化字符串 .
-
如果Ocaml无法动态生成某些字符串作为format6 str并将其传递给sprintf?代码:
在printf.sprintf的“你好”中让s =“%s”
将生成错误信息:
错误:此表达式具有类型字符串,但表达式需要类型('a - >'b,unit,string)format =('a - >'b,unit,string,string,string,string)format6
5 回答
如果操作符以
#
字符开头,则实际上这是可行的,因为该字符的优先级高于函数应用程序 .(1)我不是一个比直接使用_1232675更好的方法 . 我的意思是,你可以扩展你已经提出的东西:
这是有效的,但由于优先权所必需的括号,因此很难看 .
(2)在运行时生成格式字符串非常困难,因为格式字符串在编译时被解析 . 它们可能看起来像字符串文字,但它们实际上是一种不同的类型,这是“格式6” . (它根据推断类型确定您是否需要字符串或格式字符串)事实上,格式字符串的确切类型取决于格式中的占位符;这是它能够键入检查格式参数的数量和类型的唯一方法 . 最好不要弄乱格式字符串,因为它们与类型系统密切相关 .
为什么要用静态格式替换静态检查的sprintf? OCaml的Printf使用紧凑,运行时安全 . 将它与C printf相比较,C printf是紧凑但不安全的,而C流是安全但冗长的 . Python的格式绝不比C printf好(除了你得到异常而不是crashdump) .
唯一可以想象的用例是来自外部源的格式字符串 . 通常最好将其移动到编译时 . 如果不可能,那么只有一个需要回退到手动动态格式化并进行错误处理(如前所述,您不能将Printf与动态格式字符串一起使用) . 顺便说一下这种情况 - 国际化 - 涵盖existing libraries . 通常,如果想要动态组合不同类型的多个值,则必须使用变体(如
['S "hello"; 'I 20]
)和打印方面的模式匹配来包装它们 .您应该查看OCaml Batteries Included的扩展/可扩展
printf
. 我觉得你可以用它做你想做的事 .如果我们绕过打字系统怎么办...
在查看邮件列表http://pauillac.inria.fr/caml/FAQ/FAQ_EXPERT-eng.html#printf和ocaml的src后,我不知道't claim this to be the ultimate solution, but that' .