在朱莉娅,为什么@printf是宏而不是函数?

Ben*_*ner 62 julia

在Julia中,打印格式化字符串的语法如下:

@printf("Hello %d\n", 5)
Run Code Online (Sandbox Code Playgroud)

为什么是@printf宏而不是函数?它是否可以接受不同数量的参数?

Ste*_*ski 107

对于正常的Julia函数[ 1 ],采用可变数量的参数不是问题.@printf是一个宏,以便它可以在编译时解析和解释格式字符串,并为该特定格式字符串生成自定义代码.人们可能没有意识到每次调用时 C的printf函数都会重新解析并重新解释格式字符串.事实上它和它一样快,代表了疯狂指针编程的一个小小的奇迹.说真的,看看你最近的libc的实现.这完全是疯了.printfprintf

Julia使用了一种不同的方法:@printf是一种宏,它将格式字符串转换为特定于该格式规范的有效代码.如果你考虑一下,printf样式的格式字符串实际上只是一种表达一个函数的方法,该函数接受固定数量和类型的参数并以特定方式打印它们.注意我说的格式字符串是一个函数,而不是printf本身,它在概念上是一个函数发生器,将格式转换为格式化程序.事实上,这一切都塞满了C中的运行时功能,这有点不匹配,因为它是C中唯一合理的选择.事实上,正因为如此,直到最近,它才很容易自己拍摄通过将错误的数字或类型的参数传递给C的printf而在脚中.这只是现在更好,因为编译器特别容易理解printf格式的语义.

从理论上讲,朱莉娅@printf可以比C更快,因为它生成了自定义代码,但在实践中,我有足够的时间匹配C,更不用说击败它了.但我认为这是由于我们的I/O系统的当前设计以及我如何使用它,而不是固有的限制.I/O的东西虽然要进行大修,但是当发生这种情况时,我们实际上可以通过利用@printf宏观的事实在格式化的打印中击败C.

  • 来自@StefanKarpinski的有趣更新[这里](https://github.com/JuliaLang/julia/pull/11941#issuecomment-129966921) (11认同)
  • 看来这种方法的缺点是格式字符串不能包含变量。参见http://julia-programming-language.2336112.n4.nabble.com/string-BigFloat-disable-scientific-notation-td21455.html (3认同)
  • @lucacerone do `x = @sprintf "我的幸运数字是 %d" 42`。 (2认同)
  • 为每个 printf 调用生成自定义代码可能会导致大量代码膨胀。 (2认同)
  • 不能使用变量作为格式字符串这一事实不仅是一个缺点,而且是一个重大限制。如果字符串是静态的,编译器应该执行此静态优化,否则将其保留为运行时解析的 printf 函数。我认为使用可变格式是一个相当常见的用例。 (2认同)

iva*_*rne 5

这是为了表现.的printf宏接受恒定格式字符串(例如,"Hello %d\n")和生成优化代码为该字符串.