<br><br><div><span class="gmail_quote">On 8/11/07, <b class="gmail_sendername">Milen Georgiev Dzhumerov</b> <<a href="mailto:gamehack@gmail.com">gamehack@gmail.com</a>> wrote:</span><br><div> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
And I definitely have got to ask this - how are we supposed to mutate<br>state? Using processes? Function calls? I just can't wrap my head<br>around how some C code is going to be translated.</blockquote><div><br>If your code is a basic block, you are effectively writing in a form where each
<br>value you declare is 'fresh':<br><br>A1 = foo(),<br>A2 = bar(A1),<br>A3 = baz(A2). % etc<br><br>In the above case you are lucky and able to change that into:<br><br>baz(bar(foo())).<br><br>So as long as no loops are involved, things are somewhat uncomplicated. As soon
<br>as you want a loop, you must think in recursion and preferably tail-recursion at that<br>so you won't produce any excess stack. It will take a couple of days to wrap your brain<br>around. And then you will never ever look back >:-)
<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Let's take a simple example. I'm writing a network app in Erlang<br>which accepts "messages" on a socket, where a "message" is defined as
<br>length:content. If I was to do this in C, I would have a function<br>which gets called every time bytes arrive on the socket and then<br>depending on which state I'm in, I'm either going to append the bytes<br>
to a length buffer and when I reach the ":" character, I'll change<br>the state and start appending to the content buffer (while<br>decrementing the number of bytes still left to be read).<br>Now all of this depends on having access to mutable buffers (& a
<br>counter) outside the scope of the functions - at this point I'm lost<br>on how to do it in Erlang. How would guys start solving this problem?<br>Obviously, the more experience you have, the less thinking you're
<br>going to put into this and the solution is going to come up<br>naturally, but what about people who haven't had any real world<br>experience with FP?</blockquote><div><br>The above looks a lot like a bittorrent bencoding. The socket reads apart, that
<br>can be parsed with:<br><br>attempt_string_decode(String) -><br> {Number, Data} = lists:splitwith(charPred($:), String),<br> {ParsedNumber, _} = string:to_integer(Number),<br> Rest1 = tl(Data), % Skip the $:
<br> {StrData, Rest} = lists:split(ParsedNumber, Rest1),<br> {{string, StrData}, Rest}.<br><br>Since we expect a number, we use lists:splitwith to find the first occurence of a ':' character.<br>Then we are given back a Number and some Data. In the next line, we convert the Number (which is
<br>a string) into an integer. Then we skip the ':' character in the original data stream. Now, the call<br>lists:split can break apart the Data you call 'content'. We return the string with a tag and the part
<br>of the original string we did not parse in this run. Subsequent calls with different functions on this<br>Rest parameter can parse the following data in the String.<br><br>Note, though, that we are not taking the socket into account with the above. If you want to do that, you must
<br>read enough data off the socket to do the integer-part of the parse and then read the missing amount of<br>bytes in order to fetch the whole message. If you have control over the socket-format you may wish to chose a<br>
format where data arrives as a 4-byte 32-bit big endian integer which is the size of a message that follows. That is, the format is<br><br><<Size:32/integer, Rest/Binary>><br><br>where size(Rest) = Size. The reason for this is that a process controlling a socket may then call
<br><br>inet:setopts(Socket, [{active, true}, {packet, 4}]).<br><br>which will wire the socket such that Erlangs C-layer will parse the 4-byte 32-bit big endian size, fetch the message<br>and send it as a message to your process as {tcp, Socket, Message}. For more information, see the kernel
<br>documentation for inet and gen_tcp.<br><br><br> </div></div>