Stab : un langage pour découvrir C# quand on ne connait que java
20 déc. 2011 Olivier Azeau En français 0
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); } }