45c6812bb181e5406f96515625b5d04be6cc04d8
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,
31 "sequential?" => fn arg
-> vector
?(arg
) or list
?(arg
) end,
32 "vector" => fn list
-> {:vector
, list
} end,
33 "keyword?" => fn
[type] -> is_atom(type) end,
34 "nil?" => fn
[type] -> type == nil
end,
35 "true?" => fn
[type] -> type == true
end,
36 "false?" => fn
[type] -> type == false
end,
37 "symbol" => fn
[name
] -> {:symbol
, name
} end,
38 "list" => fn args
-> args
end,
39 "read-string" => fn
[input
] -> Mal
.Reader
.read_str(input
) end,
40 "throw" => fn
[arg
] -> throw({:error
, arg
}) end,
44 defp
convert_vector({:vector
, list
}), do: list
45 defp
convert_vector(other
), do: other
48 convert_vector(a
) == convert_vector(b
)
51 def list
?([arg
]) when
is_list(arg
), do: true
52 def list
?([_arg
]), do: false
54 def empty
?([[]]), do: true
55 def empty
?([{:vector
, []}]), do: true
56 def empty
?(_
), do: false
58 def
count([arg
]) when
is_list(arg
), do: length(arg
)
59 def
count([{:vector
, arg
}]), do: length(arg
)
64 |
> Enum
.map(&Mal
.Printer
.print_str
/1)
70 |
> Enum
.map(&(Mal
.Printer
.print_str(&1, false
)))
83 |
> Enum
.map(&(Mal
.Printer
.print_str(&1, false
)))
89 def
slurp([file_name
]) do
90 case File
.read(file_name
) do
91 {:ok
, content
} -> content
92 {:error
, :enoent
} -> throw({:error
, "can't find file #{file_name}"})
93 {:error
, :eisdir
} -> throw({:error
, "can't read directory #{file_name}"})
94 {:error
, :eaccess
} -> throw({:error
, "missing permissions #{file_name}"})
95 {:error
, reason
} -> throw({:error
, "can't read file #{file_name}, #{reason}"})
99 def
nth([list
, index
]) do
100 case Enum
.at(convert_vector(list
), index
, :error
) do
101 :error
-> throw({:error
, "index out of bounds"})
106 def
first([{:vector
, [head | tail
]}]), do: head
107 def
first([[head | tail
]]), do: head
108 def
first(_
), do: nil
110 def
rest([{:vector
, list
}]), do: do_rest(list
)
111 def
rest([list
]), do: do_rest(list
)
113 defp
do_rest([head | tail
]), do: tail
114 defp
do_rest([]), do: []
116 def
map([{_function_type
, function}, list
]), do: do_map(function, list
)
117 def
map([function, list
]), do: do_map(function, list
)
119 defp
do_map(function, list
) do
121 |
> Enum
.map(fn arg
-> function.([arg
]) end)
124 def
apply([{_function_type
, function} | tail
]), do: do_apply(function, tail
)
125 def
apply([function | tail
]), do: do_apply(function, tail
)
127 def
do_apply(function, tail
) do
128 [list | reversed_args
] = Enum
.reverse(tail
)
129 args
= Enum
.reverse(reversed_args
)
130 func_args
= Enum
.concat(args
, convert_vector(list
))
134 def symbol
?([{:symbol
, _
}]), do: true
135 def symbol
?(_
), do: false
137 def vector
?([{:vector
, _
}]), do: true
138 def vector
?(_
), do: false
140 def
keyword([atom]) when
is_atom(atom), do: atom
141 def
keyword([atom]), do: String
.to_atom(atom)
143 def
cons([prepend, {:vector
, list
}]), do: [prepend | list
]
144 def
cons([prepend, list
]), do: [prepend | list
]
147 Enum
.map(args
, &convert_vector
/1)