Skip to content

Instantly share code, notes, and snippets.

@kblake
Last active February 18, 2017 21:05
Show Gist options
  • Save kblake/63db44d13a933d6811d80d5ea5c2bd2f to your computer and use it in GitHub Desktop.
Save kblake/63db44d13a933d6811d80d5ea5c2bd2f to your computer and use it in GitHub Desktop.
Outline for Dev Coop meetup (June 29th, 2016)

#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 :”barnode@127.0.0.1”

> 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 :”server@127.0.0.1”
> 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 :”server@127.0.0.1”
> 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment