📜  Julia 中的表达式和宏

📅  最后修改于: 2021-11-25 04:36:18             🧑  作者: Mango

元编程是一种构建良好代码的方法。如果精确地使用这种技术,那么它可以产生更简洁和可读的代码。 Julia 是一种同形语言,这意味着 Julia 可以将自己的代码拟人化为语言本身的数据结构。程序可以在没有任何额外构建步骤的情况下重建自己的代码。作为元编程语言的 Julia 的另一个特性是运行程序的能力,以动态地遇到自身的特性。表达式和宏是 Julia 元编程的重要组成部分。

Julia 中的表达式

表达式是 Julia 语言中的特殊类型对象。 Julia 代码似乎是从 Expr 类型的 Julia 数据结构扩展而来的语法树。这使得从 Julia 内部设置和更改 Julia 代码变得简单,而无需推断原始文本。

任何未被评估的代码块都可以说是一个表达式。有一个特定的函数用于评估表达式。

例如,

上面这段代码刚刚形成了一个对象“Expr”,它将保持原样,除非任何函数对该对象采取行动,例如eval()

这一切似乎有点复杂,因为您只需要添加两个数字。这个复杂表达式背后的原因是它向 Julia 程序员展示了新的强大功能。

创建表达式

在 Julia 中有多种创建表达式的方法,下面列出了其中的一些:

使用 Expr()函数

Julia 提供了一个预定义的函数Expr(),可用于创建用户选择的表达式。

这里, my_exp = Expr(:(=), :x, 10)是语法的前缀表示法,第一个参数是 head ,其余是表达式的参数。头部决定要执行的操作,这里将值 10 分配给 x。

引用

使用引号创建表达式的基本语法是冒号( 🙂后跟括号 () 围绕代码的单个语句,即:()

您可以通过其他各种方式构造此表达式a*b+c+10 ,例如使用 Meta.parse 和 Expr

使用报价…结束

这使得创建多行表达式成为可能。

插值

Julia 允许在表达式中插入字面量,即它允许将值插入到表达式中。

内插为表达式的元组示例,

注意:如果表达式不加引号,则会显示编译时错误:

$ 只允许插入单个表达式,如果您想插入多个表达式,请使用$(exps…),其中 exps 是一个表达式数组。

评估表达式

可以使用预定义的eval()方法评估表达式。

在上面的例子中,表达式构建时的a值被视为表达式中的中间值,因此a=0无关紧要。这里, a 的值被视为30

表达式上的函数

Julia 的一项非常有用的功能是能够在 Julia 本身内生成和操作 Julia 代码。我们已经看到了一个返回 Expr 对象的函数示例:解析函数,它接受字符串Julia 代码并返回相应的 Expr。 Expr 对象也可以作为函数的参数,函数返回另一个 Expr 这是一个例子,

Julia 中的宏

现在您知道了如何在 Julia 中处理表达式,现在是修改它们的步骤,这是使用宏完成的。宏是评估输入表达式并给出结果输出表达式的方法之一。 Julia 语言中的过程如下:首先解析并评估宏,然后宏产生的处理后的代码最终像普通表达式一样进行评估。宏可以称为代码的代码。下面是语法:

macro e(x)
   if typeof(x) == Expr  
      println(x.args)
   end
   return x
end

宏使用字符“@”作为前缀运行,

@name exp1 exp2 ...
@name(exp1, exp2, ...)

这是两种写作风格,不应混用。

julia> @e 10
10

传递数字“10”时,它返回数字本身,因为数字不是表达式。这里还有一些宏的例子。

示例 1:

示例 2:

有一些方法可以知道宏的参数。这可以使用宏体中的show()函数来完成:

让我们看看@asset宏,下面是例子:

它可以按如下方式使用:

上面的代码实际上是这样的:

10 == 10.0 ? nothing : throw(AssertionError("10 == 1.0"))
10 == 0 ? nothing : throw(AssertionError("10 == 0"))

整个表达式被放入@assert 宏调用发生的语法树中,然后在执行时,如果测试表达式的计算结果为真,则不返回任何内容,而如果测试为假,则会引发错误,指示断言错误的表达。

让我们看看另一个宏@eval。您一定在考虑eval()但它们在某些方面有所不同。 eval()是一个函数,@ eval是一个宏。您熟悉 eval()函数,它首先扩展和评估表达式,但 @eval 不做同样的事情。它不会扩展表达式,如果您想评估表达式,您可以使用插值过程。这可以按如下方式完成:

基本上,

@eval $(ex) == eval(ex)

上面的代码块将返回 true。