[clean-list] Languages Comparison

John van Groningen johnvg@cs.kun.nl
Fri, 25 Jun 2004 18:10:15 +0200


Isaac Gouy wrote:
>--- Geoffrey G Plitt <ggp@andrew.cmu.edu> wrote:
> > Is anyone currently writing code samples in Clean for submission to
> > The Great Computer Language Shootout at
> > http://shootout.alioth.debian.org/lang/gwydion/ ?
> > It's back as a Debian Alioth project!
>...
>They are silly programs but it's childishly pleasing to have Clean
>implementations listed in the top 3 places.
>
>(The IO programs are crippled by the shootout requirement to read files
>from stdin, rather than opening the file.)

On windows the current Clean 2.1 runtime system does not use a buffer when
reading from a redirected stdinput file. I have modified the clean runtime
system to use a buffer in this case (and also for redirected stdoutput)
and now the wc program is more than 40 times faster.

On linux the wc program is also slow because the clean freadc function
is implemented using the getchar() function in the c library, which
is slow.

Unfortunately, the freads and freadline functions of the Clean 2.1
runtime system cannot be used to read from a redirected stdinput file,
because they do not detect the end of file. I have fixed this problem, and
now freads and freadline can be used to read quickly from a redirected
stdinput file.

I have rewritten the wc program (see below) to use freads and with the
new runtime system it is now more than 8 times faster on linux.

The reversefile program (see below) can also be run with the new runtime
system, after removing the call to fend. Instead of using fend, end of
file should be detected by calling freads or freadline until a string of
size 0 is returned (or until freadc returns False). Of course, in this case
it is also possible that an error occurred, instead of end of file, this can
be checked using fclose or ferror.

The improved runtime for linux can be downloaded at:

http://www.cs.kun.nl/~clean/download/Clean21/linux/patch_io_redirection.tgz

The _startup.o and _startupProfile.o files inside the
lib/stdenv/Clean System Files folder should be replaced with the new ones in
this .tgz file.

This runtime system also changes the number of digits returned by toString
of Real's to 15, instead of 7. The same as when printing reals.

Regards,
John van Groningen


module wc
import StdEnv

Start world
	# (console, world) = stdio world
	# (nl, nw, nc) = count_file console 0 0 0 False
	= toString nl +++ " " +++ toString nw +++ " " +++ toString nc +++ "\n"

count_file :: !*File !Int !Int !Int !Bool -> .(Int,Int,Int)
count_file f nc nw nl inside
	# (s,f) = freads f 4096
	# n=size s
	| n==0
		= (nl, nw, nc)
		# (nw,nl,inside) = if inside
							(count_sw 0 n nw nl s)
							(count_s 0 n nw nl s)
		= count_file f (nc+n) nw nl inside

count_s :: !Int !Int !Int !Int !{#Char} -> (!Int,!Int,!Bool)
count_s i n nw nl s
	| i<n
	    # c=s.[i]
	    | c==' ' || c=='\t'
          	= count_s (i+1) n nw nl s
	    | c=='\n'
        	= count_s (i+1) n nw (nl+1) s
          	= count_sw (i+1) n (nw+1) nl s
		= (nw,nl,False)

count_sw :: !Int !Int !Int !Int !{#Char} -> (!Int,!Int,!Bool)
count_sw i n nw nl s
	| i<n
	    | s.[i]>' '
          	= count_sw (i+1) n nw nl s
	    # c=s.[i]
	    | c==' ' || c=='\t'
          	= count_s (i+1) n nw nl s
	    | s.[i]=='\n'
          	= count_s (i+1) n nw (nl+1) s
          	= count_sw (i+1) n nw nl s
		= (nw,nl,True)


module reversefile
import StdEnv

Start world 
   # (console, world) = stdio world
   # (lines,f) =  stacklines_from console []
   # f = write_lines lines f
   = fclose f world

stacklines_from f ls
   # (line, f) = freadline f
   | size line==0
	= (ls,f)
    = stacklines_from f [line:ls]

write_lines [line:lines] f = write_lines lines (fwrites line f)
write_lines [] f = f