Stab : un langage pour découvrir C# quand on ne connait que java
Ce billet est issu de la concomitance de deux évènements :
- je me pose la question "comment peut-on écrire quelque chose proche de C# mais qui tourne avec une JVM ?" et je découvre le langage "stab"
- je lis ce billet "Sélection FooBarQix" où un même programme a été implémenté dans 13 langages différents ayant pour seul point commun la JVM.
Il ne m'en a pas fallu plus pour écrire un FooBarQix en stab.
Et je crois que ce programme a un intérêt pour montrer ce que l'on peut écrire quand on rajoute quelques éléments basiques de C# 3 à java 6.
Le code complet est dispo sur github.
J'ai fait au plus simple avec seulement deux fichiers.
Un fichier de tests qui utilise junit :
using java.lang;
using junit.framework;
public class TestFooBarQix : TestCase
{
delegate void Action<T1,T2>(T1 t1, T2 t2);
public void testFBQ()
{
Action<Integer,String> check = (src,dst) => { assertEquals(src+" => "+dst, dst, FooBarQix.from(src)); };
check(1,"1");
check(2,"2");
check(3,"FooFoo");
check(4,"4");
check(5,"BarBar");
check(6,"Foo");
check(8,"8");
check(9,"Foo");
check(10,"Bar");
check(11,"11");
check(12,"Foo");
check(13,"Foo");
check(15,"FooBarBar");
check(7,"QixQix");
check(14,"Qix");
check(16,"16");
check(17,"Qix");
check(18,"Foo");
check(19,"19");
check(20,"Bar");
check(21,"FooQix");
}
}
Et un fichier de code qui tire profit de quatre éléments majeurs de C# :
- les lambda expressions
- les générateurs
- les types anonymes
- LINQ (qui n'est presque rien de plus que la résultante des éléments précédents)
using java.lang; using stab.query;public static class FooBarQix { public static String from(Integer numberToConvert) { var fbqDigits = sequence( new { Value=3, Text="Foo" }, new { Value=5, Text="Bar" }, new { Value=7, Text="Qix" } );
Predicate<Integer> isNumberToConvertDivisibleBy = n => (numberToConvert % n == 0); var divisors = fbqDigits.where(x => isNumberToConvertDivisibleBy(x.Value)); var digitsReplacement=digitsLeftToRight(numberToConvert).selectMany(digit => fbqDigits.where(x => x.Value==digit)); var fbqConversions = divisors.concat(digitsReplacement); if( fbqConversions.count() == 0 ) return Integer.toString(numberToConvert); else return fbqConversions.select(x => x.Text).aggregate((a,b)=>a+b);}
static Iterable<Integer> digitsLeftToRight(Integer number) { return digitsRightToLeft(number).reverse(); }
static Iterable<Integer> digitsRightToLeft(Integer number) { while(number != 0) { yield return number % 10; number = number / 10; } }
delegate Boolean Predicate<T>(T t);
static Iterable<T> sequence<T>(params T[] items) { return Query.asIterable(items); } }