#Elixir chat client & functional programming talk outline http://www.meetup.com/dev-coop/events/232116993/
- Review previous weeks
- https://github.com/kblake/functional-programming
- Functional Programming
- OOP has lead to complex software patterns
- Multicore, distributed, concurrent world
- Functions: pure, no side-effects, deterministic
- Immutability: known data, copy and alter, avoid race-conditions
- higher order functions: receive and/or return functions
- recursion, map, reduce, filter, etc.
- Elixir
- Pipe operator to transform data
- concurrency
- distributed
- nodes
- review last time (nodes)
iex --name foonode@<local ip> --cookie monster
> Node.self
iex --name barnode@<local ip> --cookie monster
> Node.ping :”[email protected]”
> Node.list
> greeting = fn -> IO.puts "Hello from #{Node.self}" end
> greeting.()
Easier, Global registry:
> :global.register_name(:one, self)
> :global.registered_names
from other node
> one = :global.whereis_name(:one)
> :global.register_name(:two, self)
receive do
msg -> IO.puts msg
end
On node one
> send two, “hello from one”
EchoServer (on two)
defmodule EchoServer do
def echo do
receive do
msg -> IO.puts “Message received: #{msg}”
echo
end
end
end
from node one
> send two, “hello there”
##Chat client:
> mix new chat_client
open chat_client.ex
defmodule ChatClient do
def hello do
IO.puts "hello world!!!"
end
end
mix —name karmen -S mix
> ChatClient.hello
Add this code:
@server_name :chat_server
def server_name do
@server_name
end
def join_server server_id, cookie \\ :"cookiemonster" do
Node.set_cookie(Node.self, cookie)
Node.connect server_id
end
def server do
:global.whereis_name(server_name)
end
> recompile
> ChatClient.join_server :”[email protected]”
> ChatClient.server
Add code to last line in join_server:
:global.register_name(Node.self, self())
def friends do
recipients = List.delete :global.registered_names, server_name
List.delete recipients, Node.self
end
> recompile
> ChatClient.friends
All clients can call friends to see who’s on the network
NEXT: Listen for messages
def message_listener do
receive do
{sender, message} ->
IO.puts "#{sender}: #{message}"
message_listener
end
end
end
IN join_server update/add
pid = spawn(__MODULE__, :message_listener, [])
:global.register_name(Node.self, pid)
Stop REPL, start it, test the message listener
> ChatClient.join_server :”[email protected]”
> send :global.whereis_name(:"karmen@Karmens-MacBook-Pro"), {Node.self, "sup sup"}
ADD broadcast:
def broadcast message do
send server, {:all, Node.self, message}
:ok
end
> recompile
> ChatClient.broadcast "hello world"
Direct Message:
def direct_message friend, message do
send server, {:private_message, Node.self, friend, message}
:ok
end
> recompile
> ChatClient.friends
> ChatClient.direct_message :"bar@Karmens-MacBook-Pro", "private message"
Final Result:
https://gist.github.com/kblake/f0093c0f9c5d6c02f19af613c777a38c