The place for web

The place for simple tutorials, software reviews, and many things tech.

Saturday, June 28, 2014

Rust note 6: Checking to see if a file exists in Rust

Today, I, a beginner who has used Rust for less than a week, patched a bug in the rust compiler. It had to do with overwriting existing files, and it lead to the creation of this function:

use std::path;
fn alreadyExists(items: Vec<Path>, quer: &str) -> bool {
    items.iter().any(|nms: &Path| -> (bool) {nms == &Path::new(quer)})
}


This searches over the items iterator, checking each path against a filename, and returns "true" if the file exists in the directory, or "false" otherwise.

Rust Note 5: Keyboard input in Rust

Rustlang is all about its functions. You barely have to run your program to make sure it works, and when you do, you write unit tests for them. But, what about good old days of taking keyboard input and faffing about without end in your program? Here's how to bring that back in Rust.

The Program
This program will take input and parrot it back to you. It's as simple as simple gets.

use std::io;

fn main(){
    print!("Input: ");
    println!("{}", io::stdin().read_line().unwrap());
}

 

io::stdin() returns a BufferedReader on stdio (the input stream). read_line() returns an IoResult (just used for handling some errors) that .unwrap()  turns into a normal string. That is then printed by the println! macro.

 Just be careful with .unwrap(). Part of Rust's power is being able to match against errors, and you lose that with .unwrap().
 

Thursday, June 26, 2014

Rust note 4: Rust unit tests

Unit tests are a crucial part of "real world" development. Manually testing code in some kind of REPL (which rust no longer has) is time-consuming and cannot be verified across distributions of your code. Luckily, rust provides unit testing right inside of its compiler, so you don't even need a third-party solution to bolster your code. Here's how to do it.

The assert! Macro
assert! is a simple concept that can be used in complex ways. It tests to see if a boolean is true, and, if it is, does nothing. Otherwise, it will call the fail!() macro, causing the program to terminate.

The test function
So, before we can test anything we need functions.

fn add_one(x: int) -> int { x + 1 }
fn subtract_one(x: int) -> int { x - 1}


Obviously, add_one(1) will be 2. And subtract_one(1) is zero. So, we put these assertions in a function called "test", which takes no arguments and returns nothing.

#[test]
fn test(){
  assert!(add_one(1) == 2, "It's all gone wrong!");
  assert!(subtract_one(1) == 0);
  assert!(add_one(subtract_one(1)) == 1);
}

The test pragma ("#[test]") will tell rustc that this is a test. The function that tests the code can be named anything, as long as it returns nothing and takes no arguments. The tests inside of the function are just standard boolean expressions, and an optional message for if the code fails ("It's all gone wrong!"). Now, compile put this in a file and compile it with rustc --test file.rs.  

Run the resulting executable. It should say "test result: ok. 1 passed, 0 failed; 0 ignored; 0 measured". The number of passed tests refers to how many #[test] pragmas are found. There can be a variable number of tests, so try to group up tests of a related domain under a single function. 

Just out of curiosity, what would happen if you made the test fail? Well, it's not pretty. 

Rust Note 3: For loops in Rust

Rust is a very progressive language. It tries to not make the same mistake that D made, and include parts of the language just because its predecessors had them. One such removal is the for loop.

For the uninformed, a for loop syntax in most languages is as such: for(declaration; guard; statement). An example:

 for(int x = 0; x < 100;  x++){;} 

This for loop will do nothing 100 times. But, Rust doesn't have a for loop? How can you do an equal amount of nothing? The answer is to use the range() function of the standard library. Range() is an iterator, meaning that the rust version of the for loop can act over it. You can generate a list of numbers with range(lowerBounds, higherBounds) and iterate over it. Here's the translation of that loop from above:

for x in range (0, 100){ }

Splendid! You're doing nothing just as efficiently as in a traditional language. However, what if you want to do something other than increment x by one each time? Well, you're in luck. You could either
  • Implement the iterator trait for the type of data you're working on
  • Do it the lazy way
Lazy sounds easy, so here's how to get every third number in a for loop in rust.

let mut x: int = 0;
while x < 100{
  // Awesome stuff here
  x = x + 3

}

Rust Note 2: Map and Filter

There are two things that any functional programmer will try to implement when they find out that their language of choice has lists and function literals: map and filter. Here is how you do that in Rust:

Like with many things in Rust, it's important to consider the types involved with writing these functions. Map will take a list of any type of data (in this case, a slice of borrowed references (&[T])) and return a shiny new list. Filter will take a list of borrowed references as well, and either return a list of references to references passing the predicate (any function returning a boolean value), or return a new list. Since map is returning a new list, we will make filter do that as well.

Without further adieu, here's the code for filter:

fn filter<T: Clone>(lst: &[T], function: |x: &T| -> bool) -> Vec<T>{
    let mut lVec = vec![];
    for x in lst.iter(){
        if (function(x)) { lVec.push(x.clone()); }
    }
    lVec
}


Note that whatever type you are filtering over must be a member of the Clone trait. It means that it can return something that's not a reference. So, this code will take any slice and a predicate, and return only the values for which the predicate is true.

Here is the map function:

fn map<T, U>(lst: &[T], function: |x: &T| -> U) -> Vec<U>{
    let mut lVec = vec![];
    for x in lst.iter(){
        lVec.push(function(x));
    }
    lVec
}







This doesn't need a member of Clone, because it returns a different type, as specified by the parameter "function". Function is a function literal (technically, a closure), meaning that you can give this any function that takes the type of the list and returns any other value.

Friday, June 20, 2014

Rust Note 1: Found Self in Ident Position

If you're anything like me, you know what it's like to wrestle with new technology. No documentation, no guidance, no hope. This series is an attempt to document the pitfalls of the Rust programming language. In the first quickfix, we will fix the "Found Self in Ident Position" error.

Example code:     fn rest(&self) -> self;
Fixed code:          fn rest(&self) -> Self;

Explanation
The return type is affected by the case of the letter, much like Haskell's types. In most "self in ident position" cases, you just need to swap the case.

Thursday, April 3, 2014

Why Microsoft Open Sourced .NET

20:26 derive: Troll Harder

That's the response from an IRC channel chatter after the news came out about Microsoft's .NET. It left a lot of developers in shock, some in disbelief... But mainly a lot in curiosity. Obviously something provoked Microsoft, a vehemently anti-Open source entity, to Open Source .NET, but what was it? By looking into the technical, political, and commercial implications of what this means, their reasoning becomes obvious.


The announcement for the relicensing of most of the .NET stack came on April 3rd, 2014, which is exactly 5 days before the XPocolypse, Microsoft's termination of their most widely used, widely popular desktop operating system. They need to gain market leverage again, and no legal paradigm has risen to popularity quicker during XP's reign than Open Source. A lot has changed in the decade since XP, and now Microsoft is being forced to catch up to companies like Apple and Google, who learned far sooner than Microsoft that Open Source technologies have technical and managerial advantages over closed source development.

However, the motivation isn't all an act of kindness. Microsoft's watching its Empire be chipped away by community projects that recreate Microsoft functionality. The Mono project, for instance, was a (somewhat) successful attempt at an open source .NET. With Microsoft filling this niche, the only card that Mono has to play is cross-compatibility, a technical feat not far off from possibility with the .NET source code released today.


Let's follow this tangent a little bit more. This isn't a one-off thing. Open source code is part of the new .NET foundation goals. What could the future hold for other community projects similar to Mono, like, say, MingW, if the source for other development tools gets released?

Is it a positive thing that Microsoft is moving into Open Source? Absolutely. But do not confuse business strategy with kindness, for the motives for the move are clouded by the drive for market dominance in a post-XP era.