Tuesday, April 5, 2011

Verbosity

One of my favorite features in the Factor programming language is its general concise-ness. Certain problems can be expressed in a very modest amount of code. Mind you, we're not talking about the extremes that some languages go through to be good at Code Golf, but minimized to some extent.

A tutorial was posted a couple days ago that demonstrated how to write a program to generate a "variable length string full of random characters". I wanted to contrast the solution in the tutorial with a simple version written in Factor.

Note: this is not meant as a critique of the tutorial, nor a critique of the C# programming language.

The finished "random string" class (with tutorial comments removed):

using System;
using System.Text;

namespace RandomStringTutorial {

    public class RandomString {

        private char c;
        private int n;
        private Random r = new Random();
        private StringBuilder sb = new StringBuilder();

        public string GenerateString(int Length) {

            for (int i = 0; i < Length; i++) {
                sb.Append(RandomChar());
            }

            return sb.ToString();
        }

        private char RandomChar() {

            n = r.Next(65, 122);

            if (n > 65 && n < 90 || n > 97 && n < 123) {
                c = Convert.ToChar(n);
            } else {
                RandomChar();
            }

            return c;
        }
    }
}

And then a "main" method to run this as a program:

using System;

namespace RandomStringTutorial {

    class Program {

        static void Main() {

            RandomString rs = new RandomString();
            Console.Write(rs.GenerateString(8));
            Console.ReadLine();
        }
    }
}

Doing something similar in Factor, including a main word so that the vocabulary could be deployed as a binary, or run from the command-line:

USING: io kernel literals math.ranges random sequences ;

IN: random-string

CONSTANT: valid-chars $[
    CHAR: A CHAR: Z [a,b] CHAR: a CHAR: z [a,b] append
]

: random-string ( n -- string )
    [ valid-chars random ] "" replicate-as ;

: run-random-string ( -- )
    8 random-string print readln drop ;

MAIN: run-random-string

The code for this is on my Github.

4 comments:

roma_marks said...

Hi,
I'm sorry John my comment is just one question.
I write a cyclic code were after each cycle I need to print out some between results in the listener. But at the moment I have results printing only when all cycles a down. Is it possible to do this things in a right way? Thanks.
Roman.

mrjbq7 said...

Hi Roman,

I'd be happy to help. Perhaps you could share the code on a pastebin (like http://paste.factorcode.org) and I could help improve it. Also, you could join the #concatenative IRC channel and ask some questions there. There are several people that can help with that.

Philipp said...

Hi roma_marks,

This is the result of the fact that Factor uses cooperative threads; the display thread is only activated when the thread that does the computation is finished or yields. So to make the printing work, insert a yield call after each cycle or after each print statement.

roma_marks said...

Yes, yield.:)
Thank you guys! I have fun to coding with Factor. Its make possible to write non-trivia code in few lines.
Brevity.))