Geo*_*rge 5 macros jvm scala scala-2.12
我想要的是一个能够从它被调用的地方打印行+文件的函数。
行为将是这样的:
log("x") //Called at line 15 of file Blax.scala
Run Code Online (Sandbox Code Playgroud)
应该打印
Blax.scala, line 15, message: x
Run Code Online (Sandbox Code Playgroud)
类似于以下 C++ 代码的东西:
void _log(const char* message, const char* file, int line) { std::cout << file << ", " << line << ", message: " <<
message
<< "\n";}
#define log(message) _log(message, __FILE__, __LINE__)
Run Code Online (Sandbox Code Playgroud)
这可以在 Scala 中做到吗?是否有可能以一种半可读且与未来和旧版本的编译器兼容的方式来完成?
我一直在尝试基于这里的宏部分实现类似的东西:https : //docs.scala-lang.org/overviews/macros/overview.html
但是代码非常难以阅读,而且这些文章似乎没有涵盖与我需要的内容密切相关的任何内容。
我想我的问题可以分为两三个:
a) 是否可以通过像函数一样调用宏来在 Scala 中内联任何类型的“传统”代码?
所以基本上调用blax(a)whichimpl_blax(a, "b", __C__)在编译之前扩展为。
b) 在 Scala 编译时获取当前行号和文件名的“推荐”方式是什么?
c) 如果 a 或 b 是不可能的,还有没有办法完成我想要的?
澄清:
是的,使用 Stack 跟踪很容易做到这一点,但是抛出异常并获取 Stack 跟踪的速度慢得难以忍受,并且除了某些特定的调试情况外不适合任何其他情况。我正在寻找一种无开销或低开销的解决方案,因此我要求使用宏
编辑(为了回答标志):
@Seth Tisue 关于将问题标记为重复
如果您将此标记为重复的问题解决了我的问题,我很想听听如何。原始问题中的一些链接导致 404,最高投票答案的代码(未标记为正确)似乎没有做任何与我想要的相关的事情,并且其中的一部分在 Scala 2.12 中被标记为已弃用。 .. 我确实偶然发现了这个问题,但我希望更明确地说明这个问题可能会产生一个以前链接 4 岁的问题所没有的答案。
除非您想将此作为练习并因此推出您自己的解决方案,否则我会说推荐的方法是重用现有的、经过测试并满足您的要求的库。
我找到了两个候选人:
该源代码库是基于宏和在编译时提供的元数据。
示例(取自根据您的问题调整的页面):
object Main extends App {
def log(message: String)(implicit line: sourcecode.Line, file: sourcecode.File) =
println(s"${file.value}, line ${line.value}, message: $message")
log("x")
}
Run Code Online (Sandbox Code Playgroud)
这将打印:
/Users/jhoffmann/Development/sourcecode/src/main/scala/Main.scala,第 5 行,消息:x
作为标准的替代方案,只需使用普通的旧日志记录即可。看看scala-logging。使用logback作为后端,您可以在您的模式中使用%file,%line和%message。
例如,请考虑在 中配置的以下模式logback.xml:
<pattern>%file, line %line, message: %message%n</pattern>
Run Code Online (Sandbox Code Playgroud)
然后这段代码:
object Main extends App with LazyLogging {
logger.info("x")
}
Run Code Online (Sandbox Code Playgroud)
将打印:
Main.scala,第 4 行,消息:x
| 归档时间: |
|
| 查看次数: |
897 次 |
| 最近记录: |