4 "+" => fn
[a
, b
] -> a
+ b
end,
5 "-" => fn
[a
, b
] -> a
- b
end,
6 "*" => fn
[a
, b
] -> a
* b
end,
7 "/" => fn
[a
, b
] -> div(a
, b
) end,
8 ">" => fn
[a
, b
] -> a
> b
end,
9 "<" => fn
[a
, b
] -> a
< b
end,
10 "<=" => fn
[a
, b
] -> a
<= b
end,
11 ">=" => fn
[a
, b
] -> a
>= b
end,
12 "concat" => &concat
/1,
15 "empty?" => &empty
?/1,
17 "pr-str" => &pr_str
/1,
20 "println" => &println
/1,
27 "keyword" => &keyword
/1,
28 "symbol?" => &symbol
?/1,
30 "vector?" => &vector
?/1,
32 "dissoc" => &dissoc
/1,
34 "hash-map" => &Mal
.Types
.hash_map
/1,
35 "sequential?" => fn arg
-> vector
?(arg
) or list
?(arg
) end,
36 "vector" => fn list
-> {:vector
, list
} end,
37 "keyword?" => fn
[type] -> is_atom(type) end,
38 "map?" => fn
[type] -> is_map(type) end,
39 "nil?" => fn
[type] -> type == nil
end,
40 "true?" => fn
[type] -> type == true
end,
41 "false?" => fn
[type] -> type == false
end,
42 "symbol" => fn
[name
] -> {:symbol
, name
} end,
43 "list" => fn args
-> args
end,
44 "read-string" => fn
[input
] -> Mal
.Reader
.read_str(input
) end,
45 "throw" => fn
[arg
] -> throw({:error
, arg
}) end,
46 "contains?" => fn
[map
, key
] -> Map
.has_key
?(map
, key
) end,
47 "keys" => fn
[map
] -> Map
.keys(map
) end,
48 "vals" => fn
[map
] -> Map
.values(map
) end
52 defp
convert_vector({:vector
, list
}), do: list
53 defp
convert_vector(other
), do: other
56 convert_vector(a
) == convert_vector(b
)
59 def list
?([arg
]) when
is_list(arg
), do: true
60 def list
?([_arg
]), do: false
62 def empty
?([[]]), do: true
63 def empty
?([{:vector
, []}]), do: true
64 def empty
?(_
), do: false
66 def
count([arg
]) when
is_list(arg
), do: length(arg
)
67 def
count([{:vector
, arg
}]), do: length(arg
)
72 |
> Enum
.map(&Mal
.Printer
.print_str
/1)
78 |
> Enum
.map(&(Mal
.Printer
.print_str(&1, false
)))
91 |
> Enum
.map(&(Mal
.Printer
.print_str(&1, false
)))
97 def
slurp([file_name
]) do
98 case File
.read(file_name
) do
99 {:ok
, content
} -> content
100 {:error
, :enoent
} -> throw({:error
, "can't find file #{file_name}"})
101 {:error
, :eisdir
} -> throw({:error
, "can't read directory #{file_name}"})
102 {:error
, :eaccess
} -> throw({:error
, "missing permissions #{file_name}"})
103 {:error
, reason
} -> throw({:error
, "can't read file #{file_name}, #{reason}"})
107 def
nth([list
, index
]) do
108 case Enum
.at(convert_vector(list
), index
, :error
) do
109 :error
-> throw({:error
, "index out of bounds"})
114 def
first([{:vector
, [head | tail
]}]), do: head
115 def
first([[head | tail
]]), do: head
116 def
first(_
), do: nil
118 def
rest([{:vector
, list
}]), do: do_rest(list
)
119 def
rest([list
]), do: do_rest(list
)
121 defp
do_rest([head | tail
]), do: tail
122 defp
do_rest([]), do: []
124 def
map([{_function_type
, function}, list
]), do: do_map(function, list
)
125 def
map([function, list
]), do: do_map(function, list
)
127 defp
do_map(function, list
) do
129 |
> Enum
.map(fn arg
-> function.([arg
]) end)
132 def
apply([{_function_type
, function} | tail
]), do: do_apply(function, tail
)
133 def
apply([function | tail
]), do: do_apply(function, tail
)
135 def
do_apply(function, tail
) do
136 [list | reversed_args
] = Enum
.reverse(tail
)
137 args
= Enum
.reverse(reversed_args
)
138 func_args
= Enum
.concat(args
, convert_vector(list
))
142 def symbol
?([{:symbol
, _
}]), do: true
143 def symbol
?(_
), do: false
145 def vector
?([{:vector
, _
}]), do: true
146 def vector
?(_
), do: false
148 def
keyword([atom]) when
is_atom(atom), do: atom
149 def
keyword([atom]), do: String
.to_atom(atom)
151 def
cons([prepend, {:vector
, list
}]), do: [prepend | list
]
152 def
cons([prepend, list
]), do: [prepend | list
]
155 Enum
.map(args
, &convert_vector
/1)
159 def
assoc([hash_map | pairs
]) do
160 Map
.merge(hash_map
, Mal
.Types
.hash_map(pairs
))
163 def
dissoc([hash_map | keys
]) do
164 Map
.drop(hash_map
, keys
)
167 def
get([map
, key
]) when
is_map(map
), do: Map
.get(map
, key
, nil
)
168 def
get([_map
, _key
]), do: nil