[erlang-questions] escript cutting output

Bob Gustafson bobgus@REDACTED
Sun Nov 20 07:53:55 CET 2011


My adventure in writing Erlang..

To check the output of the 'escript cutting output' program, we can
count the number of characters in the output. There should be 10000 'a's
and 1 'b' and some miscellaneous characters, quotes, line endings, etc.

It also would be good to check the script with the dropped buffer - to
see just how many characters were output. This would give more of a clue
about what is happening inside the system parts of the erlang OS.

------------

I am really just a beginner with Erlang, so I brought along my blanky -
a ruby program that does what I want to do.

First create the input file using the previous Erlang buffer script.
$ escript buffer.erl 2>&1 | tee buffer.out

$ cat b_read.rb
#!/usr/env ruby

fin = File.open("buffer.out","r")
count = {}
fin.each_line do |line|
  line.each_char do |c|
    if count[c] == nil
       count[c] = 1
    else
       count[c] += 1
    end
  end
end

count.each_pair do |c,cnt|
  puts sprintf("%c %d  %d\n",c,c.ord, cnt)
end
$ 

I will try to write down my *thinking* at each step as I put things
together. (Note that I can only do this once - next time I will know
how).

I have an input list of characters and I want a list of tuples, each
with a character as a label and a count of how many of that character
have been seen so far. The count is a variable (??).

(I'm following along on page 42 of "Programming Erlang" - but changing
things)

count(L) -> count(L,[]). % The count of a list - start

count([], Z) -> Z;                % End condition, output is Z.
count([H|T], Z) -> count(T, xxx). % action for each character.

Hmm, don't know what xxx should be as yet. It is a function with a list
of tuples as output and a single character H as input. It also needs a
previous list of tuples - which starts with the empty list.

The function xxx will have two parts, one where the input character H
matches a character in the previous list, and one where the input
character H does not match a previous character.

Maybe xxx would look like:

        xxx(H,[]) -> Z = fun({c,Z}) -> {{H,1}};
                            ({c,Z}) -> {{c,1},Z}
                         end.
        
Not quite..  Lets go a little slower.

-----------

As I have it at the moment, looking at an Erlang program structure:

AA(L) -> AA(L,[]).

This ends in a period, so it is done once. The input AA(L) is
transformed into an AA(L,[]) which is a new pattern of arity 2. The []
is just the initial condition of the output list of tuples.

Now, we go further, looking to transform AA of arity 2 into patterns
that look more like the solution.

Starting out with the solution:

AA([],Z) -> Z;  % note ending in ';'

When we reach the point where the input is an empty list and the thing
Z, then we reach the end and the output is just Z. This output pattern
has arity 0 and doesn't fit anything else, so it would cause the
computation loop to end with Z as the output.  (Is this the erlang
theory?)

We need a pattern of arity 2 that shows what happens when we peel one
character 'H' off the front of the input list [H | T], leaving the rest
or tail 'T'.

The end result Z could be {{a,10000},{b,1},{...}}

This would be similar to a Ruby array [['a',10000],['b',1],[...]]

But I need something 'smarter' than just an array or list of tuples.

Hmm, where is my Ruby hash variable when I need it..

Help

On Sat, 2011-11-19 at 09:45 +0000, Tim Watson wrote:
> Hilarious. :)
> 
> I was wondering if waiting on receive would help, but of the course
> the issue was the time being taken by the io:format call and that
> didn't change until you added the extra call(s). I've certainly
> learned something useful about the io subsystem on this thread and
> will poke around in the code to learn more.
> 
> On 19/11/2011, Bob Gustafson <bobgus@REDACTED> wrote:
> > Yes, I agree. That cartoon sums up my motivation..
> >
> > On Sat, 2011-11-19 at 01:26 +0000, Tim Watson wrote:
> >> You forgot the most important line:
> >>
> >>
> >> %% Example: http://xkcd.com/386/
> >>
> >> Perhaps, like me, you were typing on a phone whilst standing on a
> >> crowded train.
> >>
> >>
> >> On 19 November 2011 00:29, Bob Gustafson <bobgus@REDACTED> wrote:
> >>         After spending too much time learning Erlang over the last few
> >>         hours, I
> >>         think I have come up with a 'solution' to Matthias' well posed
> >>         example
> >>         script. See below.
> >>
> >>         #!/usr/bin/env escript
> >>          main(_) ->
> >>            S = self(),
> >>            spawn_link(fun() ->
> >>               io:format("~p~p~n", [lists:duplicate(100000, $a), b]),
> >>
> >>               io:format(""), %**
> >>               S ! finished
> >>            end),
> >>            receive
> >>              finished ->
> >>
> >>                  io:format(""), %**
> >>                  halt(0);
> >>              _Other ->
> >>                  halt(1)
> >>            end.
> >>
> >>
> >>         This script emits a string which *does* end in 'b'.
> >>
> >>         If you comment out either of the added lines followed by %**,
> >>         then it
> >>         will emit a shorter string not ending in 'b'.
> >>
> >>         Bob G
> >>






More information about the erlang-questions mailing list