问题标签 [scala-macros]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
383 浏览

scala - 如何将类型编程与 Scala 宏结合起来

我想使用一个使用“type”关键字定义的类型的宏。我如何引用它?

我的起始代码是

我在示例中标记了编译器错误。很清楚发生了什么:关键字定义的类型 T 与我传入的类型 T 不同。

我尝试过的事情 关于 scala-macros 的文档还不是很多。http://docs.scala-lang.org/overviews/macros/overview.html中的部分非常有助于让我走到这一步,但它的示例使用了类级别和方法级别的泛型。我浏览了 Expecty 和 macrocosm 的代码,它们是文档中引用的项目,但找不到这样的代码。

0 投票
1 回答
420 浏览

scala - Scala宏分配解构函数的参数

我目前正在玩一些宏,无论如何这可能是个坏主意,但这是我的问题:

我有以下宏:

在 a 的情况下Select,我只需调用该函数并关闭资源,就可以正常工作。但是在 a 的情况下Function,我想将参数值分配给资源并调用正文。当我使用已弃用的创建者时ValDef,需要 aSymbol和 a Tree,一切正常。如果我使用的是注释掉的 4-args 创建器,我会收到一个编译器错误,指出该值x$1不在范围内。当我查看两个版本生成的代码时,它看起来完全一样:

有没有办法简单地使用params.head和分配一个值?谢谢你的帮助!

编辑

我这样称呼宏:

正如我所说,如果我使用的是注释掉的版本,它会给我一个编译器错误,它会打印 AST,最后会显示以下消息:[error] symbol value x$1 does not exist in Test$delayedInit$body.apply

我正在使用 2.10.1。

0 投票
0 回答
117 浏览

scala - Scala 宏和 Eclipse - 如何在类路径上获取 JDBC jar 以进行宏扩展

我正在尝试使用 Scala 宏,并且正在使用 Eclipse 和 ScalaIDE 插件。按照这个问题和答案,我为宏创建了一个单独的 Eclipse 项目。

那行得通,但后来我尝试编写一个调用 JDBC 来帮助生成代码的宏实现。

postgresql-9.1-901.jbc4.jar在两个项目的构建路径中都有,但是宏扩展给出了这个错误:

java.sql.SQLException: No suitable driver found for jdbc:postgresql://...

问:如何控制用于宏扩展的类路径,并解决这个问题?

更新

我已经部分回答了我的问题......我可以添加Class.forName("org.postgresql.Driver")到宏实现中,然后一切正常。但是我仍然不知道为什么这与普通代码不同,我不必编写它。通常在类路径上有 postgres jar 就足够了。

0 投票
3 回答
1981 浏览

debugging - Scala:代码仅在调试时运行(#ifdef 等效?)

在 C++ 中,我可以写:

Scala中有没有等价物?

0 投票
1 回答
151 浏览

scala - 为什么在这个宏中类型相等失败,但类型一致性成功?

我试图确定在编译时传递给宏的参数类型。它似乎在我使用时有效,<:<但在我使用时无效=:=。我不确定为什么。谁能指出我正确的方向?我在下面包含了示例代码。

这个宏:

由此代码调用:

回报:

但是,如果我检查类型是否相等 ( =:=),则宏会返回:

任何帮助将非常感激。

0 投票
2 回答
2157 浏览

scala - Scala 宏,生成类型参数调用

我正在尝试概括设置 Squeryl(Slick 提出了同样的问题 AFAIK)。我想避免必须为许多通用方法显式命名每个案例类。

这也适用于生成索引,并为每个案例类围绕 CRUD 方法创建包装器方法。

所以理想情况下我想做的是有一个类列表并将它们制作成表,添加索引并添加一个包装器方法:

我认为 Scala 宏将适用于此处,因为我认为您不能将值作为类型参数。我还需要为每种类型的表单生成方法:

我对宏的示例有所了解,但我不知道如何生成通用数据结构。

我得到了这个简单的例子来说明我想要什么:

我该怎么做呢?还是 Scala 宏是错误的工具?

0 投票
1 回答
150 浏览

scala - Scala 2.10 中的抽象反射 API

Scala 2.10 带有一个很棒的反射 API。但是,它有两个入口点:运行时 Universe 和宏上下文 Universe。

使用运行时反射时,您应该导入scala.reflect.runtime.universe. 在宏实现中使用反射时,您应该从上下文中导入 Universe。

是否可以编写一些适用于两种环境的代码?应该如何获得universe

考虑这个例子:

由于类型不匹配,这不会编译。同时,很明显,在这个例子中,两者scala.reflect.runtime.universe.MemberScope共享MyReflection.u.MemberScope相同的 API。有没有办法对不同的宇宙进行抽象?

或者我可能在尝试导出反射工件(MemberScope在本例中)时做一些哲学上的错误?

0 投票
2 回答
3076 浏览

java - Scala 宏和 JVM 的方法大小限制

我正在用 Scala 宏替换 Java 程序中的一些代码生成组件,并且遇到了 Java 虚拟机对单个方法(64 KB)生成的字节码大小的限制。

例如,假设我们有一个很大的 XML 文件,它表示从整数到我们想要在程序中使用的整数的映射。我们想避免在运行时解析这个文件,所以我们将编写一个宏来在编译时进行解析并使用文件的内容来创建我们方法的主体:

在这种情况下,编译的方法将刚好超过大小限制,但不是一个很好的错误说明,而是给我们一个巨大的堆栈跟踪,其中包含很多调用,TreePrinter.printSeq并被告知我们已经杀死了编译器。

我有一个解决方案,包括将案例分成固定大小的组,为每个组创建一个单独的方法,并添加一个顶级匹配,将输入值分派到适当的组的方法。它可以工作,但令人不快,而且我不希望每次编写宏时都必须使用这种方法,其中生成的代码的大小取决于某些外部资源。

有没有更清洁的方法来解决这个问题?更重要的是,有没有办法更优雅地处理这种编译器错误?我不喜欢图书馆用户收到一个难以理解的“那个条目似乎已经杀死了编译器”错误消息的想法,只是因为某个宏正在处理的 XML 文件已经超过了一些(相当低的)大小阈值。

0 投票
2 回答
1752 浏览

scala - StringContext 和宏:一个简单的例子

我正在尝试实现一个StringContext扩展,它允许我写这个:

但是需要注意的是,如果提供的时区无效(假设可以在编译时确定) ,它应该无法编译。

这是一个辅助函数:

我可以很容易地创建一个非宏实现:

然后:

到目前为止,一切都很好。除了如果时区是无意义的(例如),这不会导致编译失败zone"foobar";代码在运行时崩溃。我想将它扩展到一个宏,但是,尽管阅读了文档,我真的在细节上苦苦挣扎(准确地说,所有的细节。)

谁能帮我从这里开始?全部唱歌,全部跳舞的解决方案应该查看是否StringContext定义了任何参数,并且(如果是)将计算推迟到运行时,否则尝试在编译时解析区域


我尝试了什么?

好吧,宏定义似乎必须在静态可访问的对象中。所以:


根据下面 som-snytt 的建议,这是最新的尝试:

在使用站点,有效zone"UTC"的编译失败并出现错误:

大概我不应该用 aLiteral(Constant( .. ))来包围它。我应该用什么?


最后一个例子 - 基于 Travis Brown 在下面的回答

0 投票
1 回答
1176 浏览

scala - Reading resources from a macro in an SBT project

Suppose I have a Scala project with three sub-projects, with files like this:

Foo.scala contains a simple macro that reads a resource at a given path:

If the resource can be opened, countLines returns the number of lines; otherwise it's empty.

The other two Scala source files just call this macro:

And:

The contents of the resources don't really matter for the purposes of this question.

If this is a Maven project, I can easily configure it so that the root project aggregates the three sub-projects and baz depends on bar, which depends on foo. See this Gist for the gory details.

With Maven everything works as expected. Bar can see the resources for foo and bar:

And Baz can see all of them:

Now I try the same thing with SBT:

But now Bar can only see the resources in foo:

And Baz can only see foo and bar:

What's going on here? This SBT build file seems to me to be a pretty literal translation of the Maven configuration. I have no problem opening a console in the bar project and reading /bar.txt, for example, so why can't these projects see their own resources when calling a macro?