My first real-world Nice experience: impressions and proposals

View: New views
1 Messages — Rating Filter:   Alert me  

My first real-world Nice experience: impressions and proposals

by Yauheni Akhotnikau :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi!

I’ve done my first Nice program which performs real-world task. It is a  
quick and dirty program written for solving one of unexpected problem in  
my work. The program reads log of SMPP data exchanges from the standard  
input, searches log records for SMS exchanges, analyzes SMS bodies and  
detects bad message bodies. I implemented the same task some time ago in D  
1.0 (with Tango library) and Eiffel (with EiffelStudio 6.0). So it is  
interesting to compare solutions on different languages. My Nice  
implementation could be found here:  
http://eao197.narod.ru/better_language/test_tasks/decode_7bit_bodies/decode_7bit_bodies.nice.html

Here I want to tell about some my impressions and make some proposals for  
Nice language and its standard library.

First of all I want to express my admiration about Daniel Bonniot and  
others Nice’s contributor’s work – you’ve made very attractive and usable  
language! Thanks for your efforts!

My Nice solution is very similar to D’s one. These languages propose  
similar set of features for user. D language is more actively developed  
now and has bigger community than Nice. However Nice is more attractive  
for me because it offers some features which I miss in D (for example,  
option types, multi methods) and provides access to large set of Java  
libraries. So I can say that Nice is more attractive language for every  
day programming for me than D.

However there are some small drawbacks which I’ve met during development.

= Drawbacks =

== Nice compiler’s error reporting ==

At first it is error reporting of the Nice compiler. I use VIM editor and  
run compilation from it. But, unfortunately VIM doesn’t understand format  
of Nice compiler error messages even with ‘--editor‘ argument. So I think  
it is good to have yet another format of such messages in the form:

<file>:<line>:<column>: <error description>

For example:

test/main.nice:1:1: undefined symbol X

Such format is already supported by several languages/compilers/tools  
(e.g. C/C++, D, Ruby) and because of that many editors already have  
support of that format.
And Nice compiler shouldn’t tell anything except errors/warning in this  
mode, i.e. no errors/warnings – no output.

== An absence of switch statement ==

The next is an absence of switch statement in the language. I know that  
value dispatch mechanism allows write code which illuminates need of  
switch. But sometimes switch requires much less coding, than using  
overloaded methods. For example I needed to parse escape sequences in a  
string. With switch such operation requires simple and obvious switch:

if( ‘\\’ == c )
   switch( line[ i + 1 ] ) {
     case ‘r’ : // ‘\r’ processing
     case ‘t’ : // ‘\t’ processing
     …
     case ‘x’: // ‘\xXX’ processing.
   }

But without switch I need to write some top-level overloaded methods for  
each kind of escape sequence:

SomeRetType onChar(current_char, line, index) { … }
onChar( ‘r’, line, index) { … }
onChar( ‘t’, line, index) { … }

onChar( ‘x’, line, index) { … }

if( ‘\\’ == c )
   … = onChar( line[i + 1], line, i+1);

or write sequence of if-else-if statements:

if( ‘\\’ == c ) {
   let next = line[i+1];
   if( ‘r’ == next ) …
   else if( ‘t’ == next ) …

}

I think that support of value dispatch for local functions could help  
there, because if allows to write less code then in the case of top-level  
overloaded methods:

if( ‘\\’ == c ) {
   void onChar( char ch ) { … }
   onChar( ‘r’ ) { … }
   onChar( ‘t’ ) { … }
   …
   onChar( line[i+1] );
}

== Error reporting in getopt library ==

The next is a error reporting in nice.getopt library. When  
nice.getopt.parse finds unknown option it prints error messages on the  
standard error stream and continues argument parsing. But such approach  
not always desirable. I think it is necessary to have mode in which  
nice.getopt.parse raises exception on unknown option.

== No source file name/line number in the exception stack trace ==

I use Nice 0.9.13 under Windows and on exception I have that:

java.lang.ArrayIndexOutOfBoundsException: 0
         at t1.fun.main(Unknown Source)
         at t1.dispatch.main(Unknown Source)

for the program:

void main( String[] args )
   {
     try
       {
         println( args[ args.length ] );
       }
     catch( Exception x )
       {
         x.printStackTrace();
       }
   }

May be it is a bug?

= Some proposals =

== A kind of Ruby/SmallTalk’s code blocks in Nice ==

Nice already has syntax sugar for methods with ()->void as last argument:

void f( ()-> void action ) { …; action(); … }
f() { bla-bla-bla }

And may be Nice could support such sugar for other types of lambdas. For  
example:

void g( (A, B, C)-> void action ) {
   …;
   action( p1, p2, p2 );
   …
}
g() { |a, b, c|
   …
}

where a, b and c will have types A, B and C.
It could allow writing less code. For example, I created helper function

String formatHelper( PrintStream => void printAction ) {
   … let ps = new PrintStream( … );…
   printAction( ps );
   … return …
}

which was used like this:

formatHelper( PrintStream printer => { … some actions … } );

Repeating “PrintStream printer =>” on every formatHelper invocation was a  
boring task. So the form:

formatHelper() { |printer| …some actions…}

looks more attractive.

== Ranges in the form [low,high) ==

AFAIK, Nice provides Range only in the form [low, high] (each limit  
included). Because of that sometimes I need to write:

for( i : 0..(array.length-1) ) …

I think it would be useful if there would be Ranges in the form [low,  
high) (excluding upper limit). Like in Ruby `…` operator could create such  
Range:

for( i : 0…array.length ) …

== Helper method eachLine in the standard library ==

The standard library contains readLine method. And I know from Ruby that  
such eachLine could be very useful sometimes:

void eachLine ( InputStream from, String->void action )
   {
     let reader = new BufferedReader( new InputStreamReader( from ) );
     var line = readLine( reader );
     while( line != null )
       {
         action( line );
         line = readLine( reader );
       }
   }

== Helper method sprintf in the standard library ==

Sometimes it is necessary to create description of something in the  
program (for example before raising exception). In that case the following  
sprintf method could help:

String sprintf( String formatString, Object[] args )
   {
     let buffer = new ByteArrayOutputStream();
     let printer = new PrintStream( buffer );
     printer.printf( formatString, args );
     return buffer.toString();
   }

Example of usage:

throw new IllegalValue( sprintf( “value ‘%d’ is out range [%d,%d]”,  
[ value, low, high ] ) );


--
That’s all now. Thanks for patience.
I’ll investigate Nice language further.


--
Regards,
Yauheni Akhotnikau
Senior Programmer
Intervale
e-mail:eao197@... <mailto:eao197@...>

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Nice-info mailing list
Nice-info@...
https://lists.sourceforge.net/lists/listinfo/nice-info
LightInTheBox - Buy quality products at wholesale price