gpt4 book ai didi

polymorphism - 如何在 Elixir 中实现函数/进程多态性

转载 作者:行者123 更新时间:2023-12-02 03:22:13 24 4
gpt4 key购买 nike

我想以多种(独立的)方式“扩展”Elixir 的内置 IO/文件功能。

我想出了以下代码模式:

defmodule FileExtension1 do
# arguments are different for different extensions,
# but I guess I could just stick with single map/list
# argument for uniformity
def open!(filename, some_param \\ true) do
filename
|> File.open!
|> attach(some_param)
end

def close(io) do
io |> File.close
end

def attach(io, some_param \\ false) do
spawn_link fn ->
file_manager(io, some_param)
end
end

def detach(io) do
io |> send {:detach, self}
receive do
{:will_detach, ^io} -> :ok
end
end

defp file_manager(io, some_param, state \\ <<>>) do
if Process.alive?(io) do
receive do
{:detach, sender} ->
sender |> send {:will_detach, self}
{:custom_request, sender, reference, count} ->
# {result, new_state} = do_job(...)
sender |> send {:custom_reply, reference, result}
file_manager(io, some_param, new_state)
{:io_request, sender, reference, {:some_pattern}} ->
# {result, new_state} = do_job(...)
sender |> send {:io_reply, reference, result}
file_manager(io, some_param, new_state)
x ->
io |> proxy(x)
file_manager(io, some_param, state)
end
end
end

defp proxy(io, data) do
{request_type, original_from, original_reference, command} = data
reference = make_ref
io |> send {request_type, self, reference, command}
receive do
{response_type, ^reference, result} -> original_from |> send {response_type, original_reference, result}
end
end
end

基本上,它执行以下操作:

  • 根据自定义协议(protocol)处理自定义 IO 请求
  • 修改一些标准 IO 请求的处理
  • 将其他一切代理到底层 File

现在我可以透明地将这些东西堆叠在一起(即 attach 第一个到 File,然后第二个到第一个,等等)。

问题是:现在我有三个模块,它们遵循我上面描述的相同模式。我想以某种方式删除代码重复。

我应该检查什么?

  • 只是创建另一个具有共享功能的模块?像 IO 包含多个设备的共享函数,或者 Enum 包含多个类型的共享函数。你能给我一个小例子吗?这对我的情况有何影响?
  • 协议(protocol)?我不太明白这里如何使用协议(protocol),因为我要实现的目标不属于“为不同(内置)类型使用某些功能”模式。
  • 行为?看起来我可以从创建一些 GenServer 的变体中获益,并根据我的需要进行调整。再一次,如果我应该使用它,小例子会在这里有所帮助。

奖励问题:如何使用 ExUnit 测试共享功能?

最佳答案

将一个函数传递给另一个函数的一个非常简单的例子:

#PassInFunction
defmodule PIF do
def hello(name), do: IO.puts("Hello #{name}!")
def execf(name, f), do: f.(name)
end

PIF.execf("Onorio",&PIF.hello/1)

在您的特定情况下,我会使用文件类型(或扩展名,视情况而定)来确定要传入的函数。

关于polymorphism - 如何在 Elixir 中实现函数/进程多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32565489/

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