-
Notifications
You must be signed in to change notification settings - Fork 74
Expand file tree
/
Copy pathedge.ex
More file actions
80 lines (65 loc) · 2.34 KB
/
edge.ex
File metadata and controls
80 lines (65 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
defmodule Graph.Edge do
@moduledoc """
This module defines the struct used to represent edges and associated metadata about them.
Used internally, `v1` and `v2` typically hold vertex ids, not the vertex itself, but all
public APIs which return `Graph.Edge` structs, return them with the actual vertices.
"""
defstruct v1: nil,
v2: nil,
weight: 1,
label: nil,
properties: %{}
@type t :: %__MODULE__{
v1: Graph.vertex(),
v2: Graph.vertex(),
weight: integer | float,
label: term,
properties: map
}
@type edge_opt ::
{:weight, integer | float}
| {:label, term}
| {:properties, map}
@type edge_opts :: [edge_opt]
@doc """
Defines a new edge and accepts optional values for weight, label, and properties.
## Options
- `:weight` - the weight of the edge (integer or float, default: `1`)
- `:label` - the label for the edge (default: `nil`)
- `:properties` - an arbitrary map of additional metadata (default: `%{}`)
An error will be thrown if weight is not an integer or float.
## Examples
iex> edge = Graph.Edge.new(:a, :b, label: :foo, weight: 2, properties: %{color: "red"})
...> {edge.label, edge.weight, edge.properties}
{:foo, 2, %{color: "red"}}
iex> Graph.new |> Graph.add_edge(Graph.Edge.new(:a, :b, weight: "1"))
** (ArgumentError) invalid value for :weight, must be an integer
"""
@spec new(Graph.vertex(), Graph.vertex()) :: t
@spec new(Graph.vertex(), Graph.vertex(), [edge_opt]) :: t | no_return
def new(v1, v2, opts \\ []) when is_list(opts) do
{weight, opts} = Keyword.pop(opts, :weight, 1)
{label, opts} = Keyword.pop(opts, :label)
%__MODULE__{
v1: v1,
v2: v2,
weight: weight,
label: label,
properties: Keyword.get(opts, :properties, %{})
}
end
@doc false
def options_to_meta(opts) when is_list(opts) do
label = Keyword.get(opts, :label)
weight = Keyword.get(opts, :weight, 1)
case {label, weight} do
{_, w} = meta when is_number(w) ->
meta
{_, _} ->
raise ArgumentError, message: "invalid value for :weight, must be an integer"
end
end
def options_to_meta(nil), do: nil
@doc false
def to_meta(%__MODULE__{label: label, weight: weight}), do: {label, weight}
end