Scala 2.11 to Java 8 : Cheat sheet

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

It's very uncommon to migrate from Scala to another language. Yet this happens. It happened to me.

During a second jobs interview, the secretary asked me in advance not to code in Scala but only Java or Python because this is what the interviewers understood. Even if I am likely to get a whole team to start using Scala if I were hired, I cannot ask my interviewers the same...

"Hey please make my interview easier, learn scala, and come back to me".

Instead I had to prove them that I was able to code in Java. That way, It would be much easier to defend switching to Scala later.

Below is the cheat sheet that  I developed in order to be more productive during my interview. It really helped me a lot. Hoping it saves you time too !

Happy coding !

 

In scala In Java 8
Int, Long, Short, Char,
Byte, Boolean, Double
int, long, short, char,
byte, boolean, double
(a: A, b: B) => f(a)
(A a, B b) -> f(a)
(a: A, b: B) => {
   F
   f(a)
}
(A a, B b) -> {
  F;
  return f(a);
}
var x: A = ...
A x = ...;
val x: A = ...
final A x = ...;
var x = new Array[Int](15)
x(0) = 2
val a = x[2]
int[] x = new int[15]
x[0] = 2;
int a = x[2];
var x = Array(1, 2, 3)
int[] x = { 1, 2, 3 };
var m = List(4, 2, 3)

m =  m.sortBy(i => i*i-4*i)
List<Int> m = Arrays.asList(4, 2, 3;
Collections.sort(m, (Int i) -> i*i-4*i);
def theMethod(a: String, b: A => Unit) {
  val theA: A = convert(a)
  b(theA)
}
void theMethod(String a, Block b) {
  A theA = convert(a)
  b.apply(theA)
}
theMethod(“test”,
  (a: A) => println(“true”))
theMethod(“test”,
  (A a) -> println(“true”))
for(i &lt collection) {

}
for(Elem i: collection) {

}
val a: Photo => Unit
a(photo)
Consumer<Photo> a
a.accept(photo)
val  a: Photo => Boolean
a(photo)
Predicate<Photo> a = … ;
a.test(photo)
val a: X => Y
a(x)
Function<X, Y> a = …;
a.apply(x)
val photos = List(...)
val output = photos.filter(p => p.sizeKb < 10)
List<Photo> photos = 
  Arrays.asList(...)
List<Photo> output = photos.filter(
  (Photo p)-> p.getSizeInKb()<10);
val photos = photos.filter(p => p.sizeKb > 10000)
            .map(p => p.name)
List<Photo> photos = Arrays.asList(...)
List<Photo> output = photos.filter(
  (Photo p) -> p.getSizeInKb() > 10000)
  .map(p -> p.name);
def heavyComputation = (0 to 10).toList.par.foreach(
  i => heavyComputation(i))
IntStream.range(0,500).boxed()
  .collect(Collectors.toList())
  .parallel().forEach(
  (int i) -> heavyComputation(i))
object Sex extends Enumeration {
  val MALE, FEMALE = Value
}
public enum Sex {
    MALE, FEMALE
}
case class Person(age: Int, name: String)
class Person {
  int age;
  String name;

  Person(int _age, String _name) {
    age = _age
    name = _name
  }
}
trait A {
  def methodToOverride(b: B): C
}
public interface A {
  C methodToOverride(B b);
}
def methodTest(a: A) = ???
methodTest(new A {
  def methodToOverride(b: B) = convertToC(b)
})
methodTest((B b) -> convertToC(b));
.toStream
.stream()
.foreach(lambda)
.forEach(lambda)
def m() = {
  var x = 2
  x = 3
  val consume = (i: Int) => println(i + x)
  consume(5)
}
void m() {
  int x = 2
  int y = 3 // Different variable !
  val consume = (i: Int) => println(i + y)
  consume(5)
}
def m(a: A*) { }
def m(A... a) {}
trait A {
  val log: String => Unit
  def debug(msg: String) = { 
    log(msg)
  }
}
public interface A {
  Consumer<String> log
  void debug(String msg) default { 
    log.accept(msg);
  }
}
month match {
  case 1 => “January”
  case _ => “Invalid month”
}
switch (month) {
    case 1:  monthString = "January";
         break;
    default: monthString = "Invalid month";
                     break;
}
object A {

}
class A {
  static A instance = new A
  private A() {
  }
}
val P= “a(b*)”.r
P.findFirstIn(“abbacabbbbd”).map{
  m =>
   println(s”I found the text${m.group} starting at ${m.start} and ending at index ${m.end} \n”)
}.getOrElse(println(“No match found”))
Pattern P = Pattern.compile(“a(b*)”)
Matcher matcher = P.matcher(“abbacabbbbd”);
boolean found = false;
while (matcher.find()) {
    console.format("I found the text" +
        " \"%s\" starting at " +
        "index %d and ending at index %d.%n",
        matcher.group(),
        matcher.start(),
        matcher.end());
    found = true;
}
val res = for(i 
List<CT> res = A.filter(pred)
  .flatMap((int j) -> B(j))
  .map((K j) -> C(j));
val myNums: ArrayBuffer[T forSome {T 
List<? extends Number> myNums = new ArrayList<Integer>();
val myNums: ArrayBuffer[T forSome {T >: Number}] = ArrayBuffer()
List<? super Number> myNums = new ArrayList()
def copy[U : Number](source: ArrayBuffer[U],
               destiny ArrayBuffer[V]) {
   for(number 
public void copy(List<? extends Number> source,
                        List<? super Number> destiny) {
   for(Number number : source) {
      destiny.add(number);
   }
}
var s = Set[A]()
s += new A
s(a)
s.isEmpty
for(i 
HashSet<A> s = new HashSet<A>();
s.add(new A);
s.contains(a)
s.isEmpty()
for(A i: ()->s.iterator())
var m = Map[A, B]()
m += a -> b
HashMap<A, B> m = new HashMap<A, B>()
m[a] = b
val m = new concurrent.collection.HashMap()
Map m = Collections.synchronizedMap(new HashMap(...));
val s = m.toSet
Set<Map.Entry<A, B>> s = m.entrySet
val t = (“test”, 2)
t._1
t._2
java.util.Map.Entry t = new java.util.AbstractMap.SimpleEntry<>(“test”, 2)
t.getKey()
t.getValue()
Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Scala on Android: Database cursors made easy

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Ever wanted to iterate over Android cursor in the scala way ? This article will explain how with scala 2.11 we can write a library to do this awesome calls.

import AugmentedCursor._

val uri =
  Uri.parse("content://com.android.calendar/events")
val cursor = getContentResolver().query(uri,
  Array("calendar_id", "title", "description"),
  null, null, null)
for((calendar_id, title, description) <-
     cursor.toIterator[Int, String, String]) {
   /// ... Do something with calendar_id, title
   ///     and description for each entry
}

This is so much better than writing complicated code, and besides, it provide types  for the iteration variables !

Here is how we can make this magic happen.

First, we need to create an implicit class so that the method .toIterator[Int, String, String] can be defined.

object AugmentedCursor {
  implicit class RichCursor(c: Cursor) {
    def toIterator[T, U, V] = ???
  }
}

Now, the method toIterator should return an Iterable[(T, U, V)] to be able to write the initial code. Thus:

implicit class RichCursor(c: Cursor) {
  def toIterator[T, U, V] = new Iterable[(T, U, V)] {
    def iterator = ???
  }
}

The iterator itself must be an iterator over the triplet. Since we will only call it once and then close it, we can inline its construction.

implicit class RichCursor(c: Cursor) {
  def toIterator[T, U, V] = new Iterable[(T, U, V)] {
    def iterator = new Iterator[(T, U, V)] {
      def hasNext: Boolean = ???
      def next: (T, U, V) = ???
    }
  }
}

The hasNext method can compare the position of the cursor against the length of the result. Since during iterations, hasNext is called only once per iteration, we can close the cursor when there is nothing more to fetch.

def hasNext: Boolean = {
  val res = c.getPosition < c.getCount - 1
  if(!res) c.close()
  res
}

The method next is as simple, it will move the cursor to one place and then extract the right positions.

def next: (T, U, V) = {
  c.moveToNext()
  ???
}

Here we have a new problem. There is no such method as c.get[T](0) (take the first element of the cursor, and cast it to T). To the contrary, there are some methods such as c.getString, c.getLong, c.getInt, etc.

This is the time to set up a constraint: T, U and V can only be of type that the cursor can extract. We can enfore this by requiring that there exist implicit objects which can extract the type T out the cursor. For that, we define the trait Iter and two implicit objects implementing it, in the top-level object:

trait Iter[T] { def apply(c: Cursor, i: Int): T
implicit object IterS extends Iter[String] {
  def apply(c: Cursor: i: Int):String = c.getString(i)
}
implicit object IterI extends Iter[Int] {
  def apply(c: Cursor: i: Int):Int = c.getInt(i)
}

Nice, but how to be able to include them now in the next function? Simply, we can use implicitly[Iter[T]] to retrieve the implicit object and call its apply method. Sorry, we cannot use the syntactic sugar of removing the word "apply" since the method implicitly does not take parameters and this would be ambiguous. Thus:

def next: (T, U, V) = {
  c.moveToNext()
  (implicitly[Iter[T]].apply(c,0),
   implicitly[Iter[U]].apply(c,1),
   implicitly[Iter[V]].apply(c,2))
}

Now the compiler complains that there is no guarantee that there is an implicitly[Iter[T]].  How can we ensure that so that T is restrained? There is a funcitonality in scala: implicit parameters.  If the compiler can resolve them, no need to specify them ! This means that the method toIterator[T, U, V] introducing the three  type parameters requires the implicit objects to work, that is:

def toIterator[T, U, V](implicit objT: Iter[T], objU: Iter[U], objV: Iter[V])

There is also an even better syntax for that in scala, syntactic sugar:

def toIterator[T: Iter, U: Iter, V: Iter]

What's next? Abstraction ! We did it for three parameters, but perhaps we want to have one, two or more ! The refactoring is left as an exercise for the reader. For the impatient reader, the solution is below:

You need to  to get the syntactic sugar above. Voilà !

// AugmentCursor.scala
import android.database.Cursor
object AugmentedCursor {
  trait Iter[T] {
    def apply(cursor: Cursor, index: Int): T
  }
  implicit object IterInt extends Iter[Int] {
    def apply(c: Cursor, i: Int) = c.getInt(i)
  }
  implicit object IterString extends Iter[String] {
    def apply(c: Cursor, i: Int) = c.getString(i)
  }
  implicit class RichCursor(c: Cursor) {
    private def implicitIterator[T](f: => T) = new Iterator[T] {
      def hasNext = {
        val res = c.getPosition < c.getCount - 1
        if(!res) c.close()
        res
      }
      def next() = {
        c.moveToNext()
        f
      }
    }
    private def implicitIter[T](f: => T) = new Iterable[T] {
      def iterator = implicitIterator[T] {
        f
      }
    }
    def toIterator[T : Iter] = implicitIter {
      implicitly[Iter[T]].apply(c, 0)
    }
    def toIterator[T : Iter, U: Iter] = implicitIter {
      (implicitly[Iter[T]].apply(c, 0),
       implicitly[Iter[U]].apply(c, 1))
    }
    def toIterator[T : Iter, U: Iter, V: Iter] = implicitIter {
      (implicitly[Iter[T]].apply(c, 0),
       implicitly[Iter[U]].apply(c, 1),
       implicitly[Iter[V]].apply(c, 2))
    }
 }

 

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Converting Javascript to Scala on Scala-js

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Besides the lessons (for functions) given by Sebastian, the author of Scala-js, here are some more lessons I learned while porting javascript code to Scala to use Scala-js.

  • Wrap your code. First, wrap your code in an object's body. You need this since scala does not authorize code outside of objects or classes. Extend JSApp to benefit from variables such as document, window, etc.
    object YourApp extends JSApp { ... }
    Put your code inside the brackets.
  • Object literals: To convert the following javascript snippet:
    { action: "bind", data=42, check=true }
    you can use the literal import and use one of the following two constructions:

    import js.Dynamic.{literal => l}
    l(action="bind", data=42, check=true)
    l("action"->"bind", "data"->42, "check"->true)
  • Order of val/var/def: The order of var/val and defs inside an anonymous function matter. You will have to correct all back-references. Hence, the following:
    function changeValue() { value = 5; }
    var value = 0

    which is valid in javascript, will has to be rewritten as

    var value = 0
    function changeValue() { value = 5; }
  • Implicit converters from Dynamic to Boolean: Because js.Dynamics are sometimes used in boolean conditions or for comparison, I added implicit converters so that it does not throw errors.
    object Implicits {
      implicit def dynamicToBoolean(d: js.Dynamic): Boolean = d.asInstanceOf[Boolean]
      implicit def dynamicToString(d: js.Dynamic): String = d.asInstanceOf[String]
    }
  • Warning comparing dynamic with strings: To remove the annoying warnings which arrive when you compare dynamic with strings, you can add the following implicit:
  • object Implicits {
      implicit class ComparisonOp(d: js.Dynamic) {
        def ==(other: String) = d.asInstanceOf[String] == other
      }
    }
  • Use of the javascript "in" keyword
    if(key in obj) has to be translated to if(!js.isUndefined(obj(key)))
  • for...in
    for(a in obj) has to be translated to:
    for(a <- js.Object.keys(obj))
  • String extraction: Instead of extracting chars with
    string(index)
    prefer the following
    string.substring(index, 1)
    which returns a String instead of a Char. It is hard to convert from Char to String.
  • Zero-argument functions: Careful when you translate zero-arg functions to def. If you pass them as parameter, you need to add the modifier _ so that they are not evaluated. For example:
    function loadSomething() { ... }
    $("#button").change(loadSomething)

    has to be translated to:

    def loadSomething() { ... }
    $("#button").change(loadSomething _)
  • setTimeout:  You will have to translate setTimeout using another construct, with a lazy evaluated block. Thus, this:
    setTimeout(function() { ... }, 999)
    becomes:
    js.timers.setTimeout(999){ ... }Do not put anonymous function inside the brackets like { () => ...} else they the function body will never be evaluated !
  • console.log: In order to use console.log directly in your code, import the following which provides a statically typed object
    import org.scalajs.dom._
    console.log("Whatever")

    or alternatively, you can use the dynamic global variable:

    import js.Dynamic.{global => g}
    g.console.log("Whatever")
  • Call object's main method. Last but not least. If you define your methods in an object, especially some jQuery onLoad event, you need to call at least one method from the object for it to be initialized. Indeed, objects are lazily created.
    For example, if your initializer object is:

    package your.app
    import scala.scalajs.js.JSApp
    import org.scalajs.jquery.{jQuery => $}
    object YourApp extends JsApp {
      $(document).ready(() => { ...
       })
     def main() = {}
    }

    you need to include a script in your html like this:
    <body onload="your.app.YourApp().main()">

  • Bracket access on custom objects. For the call point["name"] with objects like the following, add a method for custom bracket access. You may factorize this method in a custom trait.
    val point = new Object {
      val name = "Mikael"
      val age = 18
      @JSBracketAccess
      def apply(index: String): js.Dynamic = js.native
    }
    //point("name") will retrun "Mikael" as a js.Dynamic
  • String-to-int conversion:
    • If you use JQuery and  observe $("something").value()*1, since  value() returns a js.Dynamic, simply converting this to $("something").value().toInt will fail at run-time (the toInt method is not defined on object of type string). However, you can do the following:
      $("something").value().asInstanceOf[String].toInt
    • If you find the pattern 1*s , where s is a string which might be null, don't use s.toInt directly in scala. It fails if s is null, whereas 1*null  == 0 in javascript. Instead, do the following:
      implicit class OrIfNull[T](s: T) {
        def orIfNull(e: T): T = if(s == null) e else s
      }
      s.orIfNull("0").toInt

Remember, next time, to directly start with scala-js :-)

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Integrating Scala-JS into an existing project, part 2

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

After integrating basic scalajs support into the project (part 1), we now want to include the following libraries (described here):

  • dom for manipulating the DOM structure of the HTML page
  • jquery to have an easier access to the DOM. And of course, we want to use the shortcut "$" instead of the verbose jQuery

To do so, add the following settings to your mainprojectfolder/build.sbt file describing the js project defined in the last article.

lazy val js = (project in file("js")).enablePlugins(ScalaJSPlugin).settings(
  libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.8.0",
  libraryDependencies += "be.doeraene" %%% "scalajs-jquery" % "0.8.0"
)

This is the safest way to ensure that the libraries are imported.
Now in your scala file compiling to javascript (myscript.scala), you can include these import statements:

package your.package
import org.scalajs.dom
import dom.document
import org.scalajs.jquery.{ jQuery => $ }
import scala.scalajs.js.annotation.JSExport

object YourApp extends JSApp {
  @JSExport def addClickedMessage(): Unit = {
    val message = "You clicked the button!"
    //appendPar(document.body, message) (DOM version)
    $("body").append(s"<p>$message</p>")
  }
 
  def main(): Unit = {
    println("Hello world!")
  }
}

Now in your html you can include something like this, and this will work:

<button id="click-me-button" type="button" onclick="your.package.YourApp().addClickedMessage()">Click me!</button>

I hope that you will enjoy Scala-js as much as I do !

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Integrating Scala-js into an existing project, Part 1

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

It can be useful to get rid of Javascript and switch to a better typed language such as Typescript or Scala. Both compile to Javascript.

In this blog post, I will describe how work with scala-js to transform the existing javascript files of a project to scala and have the compilation pipeline work as usual.

Assuming you are working with sbt > 0.13, and your project is inside the folder mainprojectfolder, do the following:

    1. Make sure the file mainprojectfolder/project/plugins.sbt exists and contains the following line :
      addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.4")
    2. Modify the build.sbt file of your top-level project to compile the javascript project when it is built. Add the following lines:
      lazy val js = (project in file("js")).enablePlugins(ScalaJSPlugin)
      scalaVersion in js := "2.11.1" // Or the right version
      addCommandAlias("runWithJS", ";fastOptJS;run")
    3. Make sure the definition of the root includes the following aggregation keyword.
      lazy val root = project(...).aggregate(js)
    4. Create your scala file(s) at  mainprojectfolder/js/src/main/scala/your/package/myscript.scala with the following content (or something from the tutorial):
    5. package your.package
      import scala.scalajs.js.JSApp
      object YourApp extends JSApp {
        def main(): Unit = {
          println("Hello world!")
        }
      }

      Now, after running sbt  inside mainprojectfolder I, you can launch the following  new tasks:
      fastOptJS  which compiles the new scala file above to javascript
      runWithJS  which performs the fastOptJS  above plus the run command (you can customize this according to your needs).

      These two tasks both create the following files inside mainprojectfolder/js/target/scala-2.11 :
      jsproject-fastopt.js: This file needs to be included in the final html.
      jsproject-fastopt.js.map: This is the source map
      jsproject-jsdeps.js: This file needs to be included in the final html. It contains all the remaining dependencies.

    6. You may be interested to copy the generated javascript files to another folder like mainprojectfolder/public/js. For that, add the following line in the build.sbt file:
      lazy val copyjs = TaskKey[Unit]("copyjs", "Copy javascript files to target directory")
      copyjs := {
        val outDir = baseDirectory.value / "public/js"
        val inDir = baseDirectory.value / "js/target/scala-2.11"
        val files = Seq("js-fastopt.js", "js-fastopt.js.map", "js-jsdeps.js") map { p =>   (inDir / p, outDir / p) }
        IO.copy(files, true)
      }

      and of course update the custom command in the same file:

      addCommandAlias("runWithJS", ";fastOptJS;copyjs;run")

Next: Part 2: Integrating DOM and jQuery

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Typescript does not (yet) correctly type check programs.

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Motivating example

Recently, I came across different errors in Typescript which bothered me. Although I am not an expert in type theory and I love Typescript, let me explain what I think could be made better.

A method returns an IIterable<TreeElement>, where the TreeElement is called a type parameter. The method fromArray is generic and accepts an argument of type T[] and returns an IIterable<T> for any T.
Resharper 9. gives me the following suggestion.

typescript1-1

When I accept the suggestion, I get the following new error.

typescript1-2

Why is Typescript, like many other languages, unable to perform such correct type checking?

It is because type checking is not just about verifying types. It is really about proving program properties. For that, I believe that engineers can really learn a lot from Academia.

First, let me show that it is possible to correctly type-check the sentence above.

How to solve the type equation

For example, with the first example, it gives the following type equations:

TreeElement[] <: T[]
IIterable<TreeElement> >: IIterable<T>

This means that

  1. An array of TreeElements should be viewed as an array of T to pass to the method .fromArray
  2. The result, and IITerable<T> should be viewed as an IIterable of TreeElements

A trivial solution exists: T = TreeElement. Is it really the only solution? How to solve it in the general case?

A word about variance and contravariance

The type parameter of an array is nor covariant nor contravariant. This means that:

  1. No covariance: Covariance would mean that an array of apple is an array of fruits. If it were, then we could put a cherry in the array of fruits and the original array would not be an array of apple anymore.
    a =  [,,,] is an array of apples.
    An apple is itself a fruit.
    But if we say, to abstract, that a is also an array of fruits, we would put a cherry at the first element.
    a[0] = 
    but then a would be  [,,,] which is NOT an array of apples.
  2. No contravariance. Contravariance would mean that an array of fruits is also an array of apples. This is obviously wrong.

Therefore the first equation yields the unique solution T = TreeElement which satisfies the second.

Without the explicit type parameter?

The equations become trickier if we remove the explicit type parameter, as the suggestion tells it. In this case, the array can be an array of anything, let's say an array of U where U is an unknown type variable.

U[] <: T[]
IIterable<TreeElement> >: IIterable<T>

Because there is no way to define covariance and contravariance in Typescript (as of 1.4), the only way IIterable<T> can be a sub-type of IIterable<TreeElement> is that T = TreeElement. Filling this solution to the first, we get:

U[] <: TreeElement[]

where we have the result that U should also be TreeElement for that to work. So this should work as well...

Why does Typescript fails there?

Like many other examples, Typescript does not set up type equations or type constraints. It solves equations in a greedy manneer, without back-tracking. Although this is viable for small programs, this does not scale and it's a shame.

Alternatives to Typescript?

if not developping with Visual Studio, I would recommend modern languages such as Scala, which now can compile to Javascript.

The type checker does this thinking and we can define the following statements without error.

class IIterable[T]
object IIterable { def fromArray[T](input: Array[T]): IIterable[T] = ??? }
def testMethod: IIterable[TreeElement] = IIterable.fromArray(Array())

It will correctly infer the missing type parameter for the array. Besides, thanks to the huge collection available, no need to reinvent the wheel.

But what are types?

Although the question of solving type equations is trivial here, this question is less trivial in general, because if the type system is sound and complete, types can generally encode arbitrary mathematical notions. Even without predicates types, like a simple int {x=> %2=0 x=>x>3} x , we can encode many mathematical problems in types which the compiler will have to solve, and sometimes will fail.

This is why it's hard.

Conclusion: Please add a modern type checker into Typescript.

Here is what is currently missing in Typescript 1.4

  • Support for abstract classes.
  • Support for type constraints, like mentionned above.
  • A solver for type constraints.
  • Support for F-bounded polymorphism.
  • Support for traits or mixins.

It's worth it for many reasons:

  • Types help refactoring
  • Types provide guarantees about your program
  • Types structure any home-made library and make component reusable
  • Types provide clever code completion
  • ...

Useful references:

A Core Calculus for Scala Type Checking, 2006, Vincent Cremet, François Garillot , Sergueï Lenglet, Martin Odersky

 

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Easter egg in Android Ice Cream Sandwich

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

I recently came accross a nice easter egg provided by the Google Android Team - as they often do it - on my galaxy tab s1.
By visiting the Settings page and typing multiple times on the version number (4.0.2), it opens an android in a sandwich.

2014-12-17 01.14.392014-12-17 01.13.58

By taping around, it gets bigger. Finally, it becomes like a kind of Nyan cat of droids without sound.

2014-12-17 01.14.552014-12-17 01.15.11

This was so funny I decided to try the same on my phone which runs on JellyBean.

2014-12-17 01.15.382014-12-17 01.15.54

Note how the jelly seems happy to draw attention from important men. The background picture is mine, not Android's of course.

 

 

 

Enjoy !

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Reflex4You.com: Dans les coulisses

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

On m'a demandé récemment à plusieurs reprises de me dire comment est arrivé reflex4you.com, et quels ont été les défis. Alors j'ai décidé d'écrire un article à ce sujet. Cet article. Votre article. Sans soldes. L'idée de représenter les fonctions complexes, comme toute idée géniale qui se respecte, est née d'une frustration en Terminale S. Alors que j'apprenais avec curiosité comment un nombre i mis au carré pouvait faire -1, je me suis demandé s'il n'y avait pas une manière visuelle de voir les choses. En effet, quand on calculait des carrés comme a^2, on imaginait un carré de longueur a puis on calculait son aire. Mais qu'est-ce que ça voulait dire un carré d'aire négative? Mes profs, tous autant théoriques les uns que les autres, essayaient vainement de nous dessiner des graphes au tableau noir. Vraiment pas très attirant. Encore pire s'ils utilisaient la craie rose. C'est alors que j'ai eu l'idée - ou plutôt l'idée m'a eu - de représenter ces nombres en deux dimensions avec deux dimensions de couleur. Le noir serait zéro, l'infini serait blanc, et on utiliserait les couleurs pour les autres nombres.... L'idée en tête - on est en 2003 -, je demande à mon grand frère s'il ne pourrait pas faire un programme pour cela. Il n'a pas le temps, et je le comprends, il est en train de passer ses concours. Arrivé en classes préparatoires quelques mois plus tard, en septembre 2003, j'ai découvert mon premier langage de programmation, Caml, qui contrairement à un paquet éponyme n'est normalement pas dangereux pour la santé, sauf s'il on en devenait accro au point d'y passer des nuits blanches. Heureusement, ce n'était pas trop mon cas. A l'époque, je dormais 8h30 par nuit et quelques soirées m'ont permit de développer mon premier prototype de traceur complexe. La première image que j'ai obtenue ressemblait à ça:

Identité
Identité

Des couleurs vives, un zéro noir, un infini blanc, c'est ce que je voulais! Entre cette version et la version actuelle, il y a très peu de différences. Maintenant les couleurs sont un peu moins vives et mieux réparties pour qu'on ait la propriété suivante: la reflex de \frac{1}{\overline{z}} est exactement celle de z mais en négatif,

-1/conj(z)
-1/conj(z)

Les premières fonctions non complexes

Une fois que ça marchait, je me suis mis avec frénésie à tester mes premières fonctions. Au fur et à mesure de mes trouvailles, je les montrais à ma famille qui observait le tout avec délectation! Ainsi, je leur ai montré un soleil couchant complexe. Pour la troisième image, j'ai retrouvé la formule, alors vous pouvez la retrouver et même la personnaliser sur reflex4you en cliquant dessus.

Coucher de soleil 1

coucher de soleil 2

coucher de soleil 3

Coucher de soleil 4

Si vous êtes matheux, vous vous rendrez compte que ces fonctions n'ont rien de "complexe" à part avoir deux variables. Mais peu importe, je me suis aperçu qu'avec des formules simples on pouvait obtenir de beaux résultats. Par exemple:

Spirale multicolore
Spirale multicolore

Les premières fonctions complexes

Je n'avais pas fait tout ce chemin pour des spirales multicolores.  Je me suis vite remis à l'analyse des fonctions complexes. Quand j'ai redécouvert les polynômes et les fractions rationnelles, ils n'étaient plus vraiment les même. Au lieu d'avoir des courbes de chameaux ou dromadaires, j'avais des points noirs aux milieux de symphonies multicolores.

z^2
z^2

-z+1/z
-z+1/z

-z+1/z
\frac{z^5-(1+2i)*z^2-i*z+2}{pi/1*z^5+z^2-3*z}

1/(1-z^2/2+z^4/24)"
\frac{1}{1-z^2/2+z^4/24}

J'ai tout de suite remarqué un théorème élémentaire: Pour une fraction \frac{P}{Q}, si P est de degré p et Q de degré q, alors il y a p points noirs et q points blancs ! Il s'agit du théorème de d'Alembert. Et ce n'est pas tout : Si p>q,  alors la fonction devient blanche (c'est à dire que son module vers l'"infini") quand z s'éloigne de zéro. En revanche, si p<q, la fonction devient noire.

Les premières fractales

La vie est pleine de trucs. Il suffit d'avoir une nouvelle invention pour qu'on lui trouve des "trucs". Vous savez, le truc qui fait que d'un seul coup, ça prend une autre dimension. Un des premiers "trucs" que j'ai réalisé, c'est que si je composais plusieurs fois de telles fonctions par elles-mêmes, j'obtenais... des fractales ! Et des tonnes, pour pas cher !

-z^2+i/(z^2-2)+0.5 composé 10 fois
-z^2+i/(z^2-2)+0.5 composé 10 fois

La raison? Elle était simple. En fait, quand on trace une fonction complexe genre à quatre racines, ce qu'on fait en réalité c'est remplacer l'identité par la fonction.

z
z

0.3*z^4-2*z
0.3*z^4-2*z

Vous voyez la suite ?... Si on continue sur chacune des "petites identités", on répète le motif à l'infini. Pour peu que pour certaines valeurs on observe une convergence, on obtient de belles fractales que l'on peut modifier à souhait.

oo(0.3*z^4-2*z,2)
0.3*z^4-2*z composé 2 fois

oo(0.3*z^4-2*z,3)
0.3*z^4-2*z composé 3 fois

Captures d'écran d'époque

Revenons à nos moutons (colorés). Je ne voulais pas écrire un article mathématique, mais juste historique. Si vous voulez plus de détails, vous pouvez directement aller sur mon blog reflex. Continuons plutôt vers notre nouveau site www.reflex4you.com.

Lorsque j'ai commencé le développement, mon premier vrai langage de programmation était Caml, et j'avais donc accès aux primitives graphiques. Voici quelques captures d'écran qui me rappellent le bon vieux temps, où on voit même des tests de couleur qui n'ont pas marché (troisième image). Dans l'ordre, on a une exponentielle renversée, un cosinus, un polynôme qui a raté, une expônentielle, un polynôme du quatrième degré et un sinus.

(expiz+1 div exp-iz) div2i 2cosinusz
2ème essai polynômes Exponentielle
polynôme 4e degré sin z

Pour ceux qui aimeraient en savoir plus, voici le rapport du traceur Reflex et de ses premières applications assez complet écrit en 2007. Toutes les images ont été tracées à la main.

Le secret?

Ah oui il y avait un secret. Rapidement, j'ai codé un générateur de formules aléatoires assez particulier, dont je ne dévoilerai pas la recette ici. Pour simplifier, il créait des arbres et les remplissait avec des formules, des nombres complexes, des cosinus, des exponentielles, des polynômes, etc.
Et c'est de là que m'est venue l'idée de reflex4you.com. Si on parvenait à avoir une formule pour chaque lettre, on pourrait faire des prénoms en fonctions complexes ! Facile à dire... mais je ne m'y suis pas attardé à l'époque.

De Caml au C++ : PDA

Reflex Tracer sur PDA

Bien sûr, peu de personnes allaient pouvoir profiter de ce logiciel développé totalement en local et qui n'était pas accessible ailleurs. C'est pour cela que lorsque les PDA (Personnal Digital Assistant) sont arrivés dans notre famille, j'ai installé Microsoft Embedded Visual Tools et j'ai codé ma première application qui traçait sur l'écran des fonctions complexes. Avec le style et et tous les paramètres visuels - on pouvait zoomer-, c'est une version dont je n'étais pas peu fier.

Mais le PDA avait ses défauts: S'il n'avait plus de batterie, tout était reformaté. Question partage sur internet, il ne fallait même pas y penser. On était encore loin de l'Android tel qu'on le connait maintenant. C'était plutôt une calculatrice de poche. L'interface était difficile à mettre à jour, il fallait trouver mieux.

Du PDA à l'ordinateur de bureau

Même en Caml, ce n'était pas pratique en fin de compte. On voulait rapidement générer des fractales, on ne le pouvait pas. Il y avait toute une procédure longue à suivre : Ouvrir Caml, Ouvrir le fichier, taper la commande suivante, ouvrir les graphiques. Je ne vous dis pas pour enregistrer !

C'est pour cela que j'ai commencé à créer l'interface en Autoit3 avec leur éditeur d'interface très bien fait Koda. Là, non seulement je pouvais ajouter des boutons à gogo, ce dont je ne me suis pas privé, mais en plus j'ai pu mettre le bouton genre "J'ai de la chance" qui faisait en un clic une fractale. J'ai pu préparer des scripts pour pouvoir modifier la formule avec coloration syntaxique, une barre de chargement, des variables que l'on pouvait changer, un créateur de séquence d'images pour réaliser des vidéos... Une belle panoplie qui s'est avéré assez fructueuse.

Reflex Tracer sur PC

Mais personne n'y avait encore accès. Et pour cause: je n'avais pas mis cette version en ligne. Je peux toujours vous l'envoyez si vous voulez.

Un premier test: Internet

Avant de partir en mission, j'ai voulu mettre en ligne une version de traçage de Reflex.
Elle est encore en ligne
à l'heure actuelle mais pas très performante. Je ne voulais pas refaire toute une interface comme pour le PC. Déjà, ça m'avait pris beaucoup de temps pour mettre tous les fichiers en ligne, les compiler à distance sur le serveur bluehost, et les lier à un fichier php/html.

Le départ et le retour

Puis je suis parti en mission prêcher l'évangile, parce que dans la vraie vie, je suis chrétien - Saint des Derniers Jours - et c'est une chose pour laquelle je suis vraiment reconnaissant. Cela m'a arraché un peu à mon monde et m'a fait découvrir l'humain tel qu'il est, ses bons comme ses mauvais côtés et finalement l'harmonie du monde de la même manière que les fonctions complexes. C'était vraiment une expérience incroyable qui m'a beaucoup appris et m'a donné beaucoup d'optimisme et fortifié dans ma foi.

Je ferme la parenthèse, mais deux ans s'étaient écoulés, et je suis rentré en février 2012. L'idée de faire un site avec les fonctions complexes ne m'avait pas quitté. Au contraire, j'y voyais même encore plus clair qu'avant. Je ne voulais pas refaire un n-ième Mathematica/Maple/Wolfram Alpha en ligne où les gens pourraient taper leur formule et être content de l'image. Non, on pouvait faire BEAUCOUP mieux. Je m'y suis vaguement remis, mais j'avais d'autres choses en tête au début: Thèse, boulot, etc.

Réalisation finale

L'idée est apparue progressivement. Un prof de mathématiques à Montpellier aimait bien ces représentations de fonctions complexes et en faisait régulièrement part à ses élèves. Il m'a contacté, et vers septembre 2013 l'idée lui est venue de proposer à l'un de ses lycéens de m'aider dans un projet lié aux Reflex. Non seulement il en avait plusieurs d'intéressés, mais il m'a mis en contact avec l'un d'eux spécialement doué dans la programmation web. Je lui ai proposé quelques idées, et zou ! il avait déjà réalisé un site très rapidement. Le travail collaboratif que nous avons eu a été très fructueux puisqu'en moins de six mois à travailler sur le site, nous avons réussi à

  • Recompiler Reflex Tracer depuis le C++ en ligne
  • Ajouter autant de fonctions qu'il y a de lettres dans l'alphabet, et même plus
  • Avoir une interface où en quelques clics on peut générer des formules personnalisées et les partager sur de multiples sites.
  • Présenter une riche palette de filtres pour que la modification soient encore plus rapide et plus belle
  • Trouver des moyens d'afficher la formule en LaTeX pour que les personnes se rendent compte qu'il s'agit de leur prénom.
  • Connecter un magasin, en l'occurence zazzle,  pour permettre aux internautes de commander leur motifs préférés
  • Et même, cerise sur le gâteau,  programmer un jeu 2048 en version complexe qui sert à passer le temps en attendant la commande.

C'était vraiment une aventure hors du commun.  J'espère que vous aurez autant de plaisir à découvrir le site que nous à l'avoir programmé.

C'est la fin de ce billet de blog. Si vous n'avez pas encore cliqué sur le lien pour accéder au site, le revoilà, et bonne visite !

http://www.reflex4you.com/

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

Reflex4you lancé !Reflex4you launched!

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone

J'ai le plaisir de vous annoncer que Reflex4you a été lancé. Il s'agit d'un site pour tracer des fonctions mathématiques personnalisées et en créer des cadeaux. Il est accessible ici: www.reflex4you.com Vous pouvez même profiter du mode expert pour créer vos fonctions uniques.

I have the pleasure to announce you that Reflex4you has been launched. It is a website to draw beautiful complex functions and create gifts out of them. It is available here: www.reflex4you.com You can even enjoy the expert mode to create your unique functions.

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInEmail this to someone