gpt4 book ai didi

erlang - 是否可以重新创建 erlang 的 :math functions as elixir macros?

转载 作者:行者123 更新时间:2023-12-04 15:29:12 25 4
gpt4 key购买 nike

我正在创建一个宏来计算两组经纬度值之间的距离。

iex()> calc_distance(posA, posB)
2 # distance is in km

目前,这与常规功能类似。我希望它成为宏的原因是我可以在保护子句中使用它。
例如
fn(posA, posB) when calc_distance(posA, posB) < 10 -> "close enough" end

但是,要在保护子句中使用宏,它必须是“ follow the rules”。这意味着不允许使用许多函数和运算符。

我最初的宏看起来像这样......
defmacro calc_distance(ll1, ll2) do
quote do
lat1 = elem(unquote(ll1), 0)
long1 = elem(unquote(ll1), 1)
lat2 = elem(unquote(ll2), 0)
long2 = elem(unquote(ll2), 1)

v = :math.pi / 180
r = 6372.8

dlat = :math.sin((lat2 - lat1) * v / 2)
dlong = :math.sin((long2 - long1) * v / 2)
a = dlat * dlat + dlong * dlong * :math.cos(lat1 * v) * :math.cos(lat2 * v)
res = r * 2 * :math.asin(:math.sqrt(a))
res
end
end

我已经开始通过删除宏中定义的所有变量来使其“保护子句友好”。
defmacro calc_distance(ll1, ll2) do
quote do
:math.sin((elem(unquote(ll2), 1) - elem(unquote(ll1), 1)) * (3.141592653589793 / 180) / 2)
|> square()
|> Kernel.*(:math.cos(elem(unquote(ll1), 0) * (3.141592653589793 / 180)))
|> Kernel.*(:math.cos(elem(unquote(ll2), 0) * (3.141592653589793 / 180)))
|> Kernel.+(square(:math.sin((elem(unquote(ll2), 0) - elem(unquote(ll1), 0)) * (3.141592653589793 / 180) / 2)))
|> :math.sqrt()
|> :math.asin()
|> Kernel.*(2)
|> Kernel.*(6372.8)
end
end

这仍然可以作为宏使用,但是由于 :math,当我尝试将它用作保护子句时仍然会出错。正在使用的功能。

如果我可以将此函数的自己版本编写为宏,这将解决问题。

有谁知道这是否可能?如果是这样,我该怎么办?

最佳答案

不,不可能将此作为保护测试来实现。

或者好吧,如果您允许精度损失,这是可能的:this approximation of the sine function可以仅使用 guard 中允许的操作来实现。

但最有可能的是,在您的程序中,准确性比节省几行代码更重要。在这种情况下,我可能会让我的函数调用 call_distance并将结果作为参数传递给另一个函数,该函数可以对结果使用保护测试:

def my_function(ll1, ll2) do
my_function(ll1, ll2, calc_distance(ll1, ll2))
end

defp my_function(ll1, ll2, distance) when distance < 10 do
"close enough"
end
defp my_function(ll1, ll2, distance) do
"too far"
end

关于erlang - 是否可以重新创建 erlang 的 :math functions as elixir macros?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55024921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com