Import Rust file to RustyCage
The import Rust file wizard will copy a file from your file system into your current workspace in Eclipse. So from the “File” menu chose Import.
Then from the Import wizard you have the Rust category and in there you can chose Rust file. The Import Rust Project is not implemented as for now. Sorry.
Then press the “next>” button and chose the “src” folder.
Then press the “browse” button or enter the path to your file.
Then press the “Finish” button.
And viola, your Rust file is imported/copied into your workspace and project.
String split method to return a tuple
So basically I thought this would be a cool thing to do in Scala, returning a tuple from the String split method.
val (str1,str2) = text.split(":")
But it doesn’t, String split returns an array.
val array:Array[String] = text.split(":")
So what can we do, so I was thinking “I can solve this with implicit conversion can’t I?”. Of course I can, so here is what I did. First I created a class with a function splitToTuple returning a tuple from the split. I wanted to split on io::println in Rust so that I could get content assist for the editor, if io:: is pressed I wanted the tuple to be returned as (“io”,””) to return all the functions in the io package.
class StringSplitToTuple(s: String) { def splitToTuple(regex: String): (String, String) = { s.split(regex) match { case Array(str1, str2) = (str1, str2) case Array(str1) = (str1, "") case _ = error("too many colons") } } }
Then I needed an object to hold the implicit conversion.
object SplitToTuple { implicit def splitToTuple(regex: String) = new StringSplitToTuple(regex) }
And viola, now I can get a tuple from Strings split method.
import SplitToTuple._ object Main extends App { val (str1, str2) = "io::println".splitToTuple("::") }
Java 8 and mixin with default methods
I wanted to check out “mixins” in Java 8 or so called default methods in interfaces. So what is default methods in interfaces in Java. Interfaces in JDK 8 can have full method definitions by using the default keyword. Since I am an Scala fanboy I wanted to test the Stackable Trait Pattern. So here goes. First I created an interface called IntQueue with the default methods get and put. I can not extend an abstract class to an interface, so IntQueue must be an interface or else I can not mix it in.
package com.reidarsollid.eight.mixins; import java.util.Queue; public interface IntQueue { Queue getQueue(); default int get() { return getQueue().remove(); } default void put(int x) { getQueue().add(x); } }
So far so good, so then I want to mix in WithDoubling I want to double what comes inn to the put method. I can not call super on an inherited interface but I can call i through the interface like an inner class calling an outer class.
package com.reidarsollid.eight.mixins; public interface WithDoubling extends IntQueue { default void put(int x) { IntQueue.super.put(x * 2); } }
So I wanted to create a BasicIntQueue and mix in the WithDoubling interface. This works as I wanted 🙂
package com.reidarsollid.eight.mixins; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedDeque; public class BasicIntQueue implements IntQueue, WithDoubling { private Queue integerQueue = new ConcurrentLinkedDeque<>(); @Override public Queue getQueue() { return integerQueue; } }
Then I created a WithFilter interface to check if the numbers are above 0.
package com.reidarsollid.eight.mixins; public interface WithFiltering extends IntQueue { default void put(int x) { if (x > 0) IntQueue.super.put(x); } }
Then i mixed in the WithFiltering interface in the BasicIntQueue.
package com.reidarsollid.eight.mixins; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedDeque; public class BasicIntQueue implements IntQueue, WithDoubling, WithFiltering { private Queue integerQueue = new ConcurrentLinkedDeque<>(); @Override public Queue getQueue() { return integerQueue; } }
Thats when the fun stopped, when compiling this I get this compiler error. java: class com.reidarsollid.eight.mixins.BasicIntQueue inherits unrelated defaults for put(int) from types com.reidarsollid.eight.mixins.WithDoubling and com.reidarsollid.eight.mixins.WithFiltering
But then again I can solve this puzzle with decorator pattern So first I create an IntQueue interface.
package com.reidarsollid.eight.decorator; public interface IntQueue { int get(); void put(int x); }
Then I created the IntQueueDecorator
package com.reidarsollid.eight.decorator; public abstract class IntQueueDecorator implements IntQueue { protected final IntQueue intQueueDecorator; public IntQueueDecorator(IntQueue intQueue) { this.intQueueDecorator = intQueue; } public int get() { return intQueueDecorator.get(); } public void put(int element) { intQueueDecorator.put(element); } }
And now I can add on as many decorators as I want. The Doubling decorator.
public class Doubling extends IntQueueDecorator { public Doubling(IntQueue intQueue) { super(intQueue); } @Override public int get() { return super.get(); } @Override public void put(int element) { element = element * 2; super.put(element); } }
The Filtering decorator.
package com.reidarsollid.eight.decorator; public class Filtering extends IntQueueDecorator { public Filtering(IntQueue intQueue) { super(intQueue); } @Override public int get() { return super.get(); } @Override public void put(int element) { if (element >= 0) { super.put(element); } } }
The Increment decorator.
package com.reidarsollid.eight.decorator; public class Increment extends IntQueueDecorator { public Increment(IntQueue intQueue) { super(intQueue); } @Override public int get() { return super.get(); } @Override public void put(int element) { element += 1; super.put(element); } }
And then the test class.
package com.reidarsollid.eight.decorator; import org.junit.Test; import java.util.NoSuchElementException; import static junit.framework.Assert.assertEquals; public class IntQueueDecoratorTest { @Test public void testDecorating() throws Exception { IntQueue intQueue = new BasicIntQueue(); intQueue.put(2); int actualBasic = intQueue.get(); int expectedBasic = 2; assertEquals(expectedBasic, actualBasic); intQueue = new Doubling(intQueue); intQueue.put(2); int actualWithDoubling = intQueue.get(); int expectedWithDoubling = 4; assertEquals(expectedWithDoubling, actualWithDoubling); intQueue = new Increment(intQueue); intQueue.put(2); int actualWithDoublingAndIncrement = intQueue.get(); int expectedlWithDoublingAndIncrement = 6; assertEquals(expectedlWithDoublingAndIncrement, actualWithDoublingAndIncrement); } @Test(expected = NoSuchElementException.class) public void testDecoratingWithFilter() { IntQueue intQueue = new Filtering(new Doubling(new Increment(new BasicIntQueue()))); intQueue.put(-1); int actual = intQueue.get(); } }
And we have a green deck. Using decorator pattern adds a little more code, but is easy to use and is readable.
Introducing Rust Task
So what is Rust then, from Wikipedia “Rust is an experimental, concurrent, multi-paradigm, compiled programming language developed by Mozilla Labs. It is designed to be practical, supporting pure-functional, concurrent-actor, imperative-procedural, and object-oriented styles.”
The most exiting thing for me is that it is influenced by Erlang and Limbo. Limbo with ports and channels and Erlang with the lightweight processes. I guess that Rust is designed with the purpose of writing web browser and to handle concurrency in a multi-core environment, these characteristics are well suited for backend systems as well.
In Rust we spawn out a new task, with the spawn keyword. This creates a lightweight process/task in which we can communicate with messages through channels. Default behavior for a variable in Rust is to be immutable, if you want a mutable variable you must explicitly declare it mutable with the mutable keyword.
So here is a little silly demo code of how to spawn a task and to send and receive messages from it.
use std; import print = io:: println; fn main() { let port = comm:: port::(); let chan = comm:: chan::(port); do task:: spawn || { let result = compute_some(); comm:: send(chan, result); } let first_result = compute_another(); let second_result = comm::recv(port); print(#fmt("First, %s", first_result)); print(#fmt("Second, %s", second_result)); } fn compute_some() -> str { ret "Some computation"; } fn compute_another() -> str { ret "Another computation"; }
I create two functions compute_some() and compute_another() in which only returns a string to recognize which function has been executed. Then in the main function I create a port and creates a channel connected to the port.Then I spawn out a task to compute where I execute the compute_some() function and sends the result on the channel.Then I execute one function and assign the result to a variable and then fetches the result from the channel and assigns it to a second variable. Then prints the result. Not very needy of concurrency here, but I guess you get the point.
For more on Rust Rust-lang I recommend the tutorial. Rust tutorail
RustyCage a Rust-lang IDE plugin for Eclipse
I have created a Rust plugin for Eclipse, so here is a small intro how to use it.
First you need to chose the Rust perspective.
If you want code completion from the std libs, you need to download the rust source code and add rust home your rust preferences.
Then in the Rust perspective chose New RustProject
This opens the rust project wizard.
The default is lib, so if you want a executable you need to check of the lib check box. And fill inn version and author. Here is an example.
Press Finnish and your rust project is created. A crate file is created for your project.
No you probably want a rust file, chose new rust file.
This will open the new rust file wizard. Give the file a name. The must be a .rs or .rc file.
Then your crate file has been updated with your new rust file.
Now enter your code in the rust file. And you have the compile and the run buttons in your task bar. Compile and run uses the context of the file you are in, so you can either compile the crate or just one file.
Compile output in the console window.
And finally press the run button and you get the result in the console window.
You can fetch the plugin via github from
https://github.com/reidarsollid/RustyCage
Or get it from update site
https://sourceforge.net/projects/rustycage/files/updatesite/
RustyCage is writen in Scala so you need the Scala compiler to install it.
http://download.scala-ide.org/sdk/e38/scala210/stable/site
Build your own update site with maven and tycho
https://bitbucket.org/rsollid/tycho-rustycage