lecture 05
This commit is contained in:
7 files changed
+175
No files matched your search
@@ -0,0 +1,32 @@
|
|||||||
|
defmodule M do
|
||||||
|
def if_fun(predicate, do: do_block, else: else_block) do
|
||||||
|
cond do
|
||||||
|
predicate -> do_block
|
||||||
|
true -> else_block
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro inspect(x) do
|
||||||
|
IO.inspect(x)
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro if_macro(predicate, do: do_block, else: else_block) do
|
||||||
|
quote do
|
||||||
|
cond do
|
||||||
|
unquote(predicate) -> unquote(do_block)
|
||||||
|
true -> unquote(else_block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro while(condition, do: do_block) do
|
||||||
|
quote do
|
||||||
|
try do
|
||||||
|
for _ <- Stream.cycle [:ok] do
|
||||||
|
if unquote(condition), do: unquote(do_block),
|
||||||
|
else: throw :break
|
||||||
|
end
|
||||||
|
catch :throw, :break -> :ok end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
defmodule M do
|
||||||
|
defmacro context() do
|
||||||
|
# macro's context
|
||||||
|
IO.inspect(__MODULE__)
|
||||||
|
quote do
|
||||||
|
# caller's context
|
||||||
|
IO.inspect(unquote(__MODULE__))
|
||||||
|
IO.inspect(__MODULE__)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro twice(x) do
|
||||||
|
quote do
|
||||||
|
unquote(x) + unquote(x)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro twice_v2(x) do
|
||||||
|
quote bind_quoted: [x: x] do
|
||||||
|
x + x
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Test do
|
||||||
|
import M
|
||||||
|
|
||||||
|
def test() do
|
||||||
|
context()
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
defmodule M do
|
||||||
|
defmacro say(msg) do
|
||||||
|
name = String.to_atom("say_#{msg}")
|
||||||
|
quote do
|
||||||
|
def name() do
|
||||||
|
IO.puts(unquote(msg))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Test do
|
||||||
|
import M
|
||||||
|
|
||||||
|
say("hello")
|
||||||
|
end
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# unquote fragments
|
||||||
|
defmodule M do
|
||||||
|
for {k, v} <- [homer: 55, bart: 76] do
|
||||||
|
def unquote(k)(), do: unquote(v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
M.homer()
|
||||||
|
M.bart()
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define CHECK(pred) printf("%s ... %s\n", pred ? "passed" : "FAILED", #pred)
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
CHECK(1 + 1 == 2);
|
||||||
|
CHECK(1 + 2 == 4);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# see abstract syntax tree (ast)
|
||||||
|
quote do: 1 + 2
|
||||||
|
# {:+, [context: Elixir, imports: [{1, Kernel}, {2, Kernel}]], [1, 2]}
|
||||||
|
#
|
||||||
|
# +
|
||||||
|
# / \
|
||||||
|
# 1 2
|
||||||
|
#
|
||||||
|
|
||||||
|
alias String, as: S
|
||||||
|
# {:__aliases__, [alias: String], [:S]}
|
||||||
|
|
||||||
|
### Abstract literal
|
||||||
|
quote do: 1 # -> 1
|
||||||
|
quote do: "hello" # -> "hello"
|
||||||
|
quote do: [1, 2, 3] # -> [1, 2, 3] # a list of ast literals is an ast literal
|
||||||
|
quote do: {1, 2} # -> {1, 2} # doubles are ast literals but not triples
|
||||||
|
|
||||||
|
|
||||||
|
### Macro - something that takes an AST and returns an AST
|
||||||
|
x = 2
|
||||||
|
quote do: x # -> {:x, [], Elixir} # doesnt evaluate it, just ast of expression
|
||||||
|
quote do: unquote(x) # -> 2
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
defmodule Testing do
|
||||||
|
defmacro check(predicate) do
|
||||||
|
test = Macro.to_string(predicate)
|
||||||
|
quote do
|
||||||
|
cond do
|
||||||
|
unquote(predicate) -> IO.puts("passed ... #{unquote(test)}")
|
||||||
|
true -> IO.puts("FAILED ... #{unquote(test)}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro test(description, do: block) do
|
||||||
|
name = "test_#{description}"
|
||||||
|
fn_name = String.to_atom(name)
|
||||||
|
quote do
|
||||||
|
@tests [unquote(fn_name) | @tests]
|
||||||
|
def unquote(fn_name)() do
|
||||||
|
IO.puts(unquote(name) <> ":")
|
||||||
|
unquote(block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro __before_compile__(_env) do
|
||||||
|
# defmacro make_run_tests() do
|
||||||
|
quote do
|
||||||
|
def run_tests() do
|
||||||
|
Enum.each(Enum.reverse(@tests), fn f -> apply(__MODULE__, f, []) end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmacro __using__(_opts) do
|
||||||
|
quote do
|
||||||
|
import unquote(__MODULE__)
|
||||||
|
@tests []
|
||||||
|
@before_compile unquote(__MODULE__)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule Tests do
|
||||||
|
use Testing # this requires Testing and call Testing.__using__
|
||||||
|
|
||||||
|
test "equality" do
|
||||||
|
check(1 + 1 == 2)
|
||||||
|
check(1 + 2 == 4)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "greater" do
|
||||||
|
check(1 > 2)
|
||||||
|
check(1 < 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
# make_run_tests()
|
||||||
|
end
|
||||||
Reference in new issue
Block a user