dsk61780
2014-10-11 15:01 阅读 44

如何将示例代码从Go转换为Erlang

I thought I could kill two birds with one stone and teach myself a little Go and Erlang by converting the following example code (taken from http://blog.smartbear.com/programming/an-introduction-to-the-go-language-boldly-going-where-no-man-has-ever-gone-before/) from Go to Erlang:

package main

import (
    "fmt"
    "time"
)

type Ball struct{ hits int }

func main() {
    table := make(chan *Ball)
    go player("ping", table)
    go player("pong", table)
    table <- new(Ball) // game on; toss the ball
    time.Sleep(1 * time.Second)
    <-table // game over; grab the ball
}

func player(name string, table chan *Ball) {
    for {
        ball := <-table
        ball.hits++
        fmt.Println(name, ball.hits)
        time.Sleep(100 * time.Millisecond)
        table <- ball
    }
}

However I failed. The code basically creates a shared counter (the ball) and sends it back and forth between the two goroutines (the players). So far so good. But how do I do something similar in Erlang? My problems were:

  • How to create a counter in Erlang? Erlang doesn't seem to allow to change the value of a variable once it is set.
  • How to share such a counter between two erlang processes?
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    dpoppu4300 dpoppu4300 2014-10-11 17:02

    A variable is not mutable in erlang, that means that during the evaluation of one function, the variable is either unbound, either set to a value that cannot change. But you can recall the same function with a new value build from the former one, recursively. The value is stored in a variable generally called the state, and it is modified when a message is received. This is the basic behaviour of a server.

    In your example you don't really need a variable to contain the counter since this value will be exchange between the 2 players. I can be contained in the message exchanged between them for example in a tuple {count,V}.

    The only way to communicate between 2 processes is message passing. The simplest syntax is Pid ! Message, where Pid is the process ID if the receiver, and Message , well the message :o) (Pid can be replaced by a name if the process is registered).

    with this you can write:

    -module(pingpong).
    -export([start/0,player/1,stop/1]).
    
    player(Name) ->
        receive
            {count,From,Val} -> 
                io:format("~p received the ball for the ~p th exchange~n",[Name,Val]),
                ok = timer:sleep(500),
                From ! {count,self(),Val+1},
                player(Name);
            {start,To} ->
                io:format("~p start the exchange~n",[Name]),
                To ! {count,self(),1},
                player(Name);
             stop -> gameover
         end.
    
    start() ->
        Ping = spawn(?MODULE,player,[ping]),
        Pong = spawn(?MODULE,player,[pong]),
        Ping ! {start,Pong},
        {Ping,Pong}.
    
    stop(P1) -> P1 ! stop. 
    

    in the shell:

    1> c(pingpong).
    {ok,pingpong}
    2> {P1,P2} = pingpong:start().
    ping start the exchange
    pong received the ball for the 1 th exchange
    {<0.39.0>,<0.40.0>}
    ping received the ball for the 2 th exchange
    pong received the ball for the 3 th exchange
    ping received the ball for the 4 th exchange
    pong received the ball for the 5 th exchange
    ping received the ball for the 6 th exchange
    pong received the ball for the 7 th exchange
    ping received the ball for the 8 th exchange
    pong received the ball for the 9 th exchange
    ping received the ball for the 10 th exchange
    pong received the ball for the 11 th exchange
    ping received the ball for the 12 th exchange
    pong received the ball for the 13 th exchange
    ping received the ball for the 14 th exchange
    pong received the ball for the 15 th exchange
    ping received the ball for the 16 th exchange
    pong received the ball for the 17 th exchange
    ping received the ball for the 18 th exchange
    pong received the ball for the 19 th exchange
    ping received the ball for the 20 th exchange
    pong received the ball for the 21 th exchange
    ping received the ball for the 22 th exchange
    pong received the ball for the 23 th exchange
    ping received the ball for the 24 th exchange
    3> pingpong:stop(P1).
    stop
    4> pingpong:stop(P2).
    stop
    5>
    
    点赞 评论 复制链接分享

相关推荐