en_dmitriid


Tigers, and lions, and bears, oh my!


Keep'em languages coming!
happy
dmitriid
Past Friday I got myself acquainted to Python.

Different people view Python as "nothing to learn" or as "if only I had time to learn" or even as "very difficult to learn".

I had to learn it quick for a very simple reason. I have lots of photos taken at different resolutions. I need to resize them to different sizes (much like Flickr does), create several thumbnails of each image, upload them to a host (Amazon S3) and load information on uploaded images to a database.

The process must be automated, of course.

It all started when I convinced myself that Python Imaging Library is the best library to manipulate images. Indeed:

  1. import Image
  2.  
  3. im = Image.open('path/to/image')
  4. im.thumbnail((800, 800), Image.ANTIALIAS)
  5. im.save('path/to/image')


The line with im.thumbnail((800, 800), Image.ANTIALIAS) is absolute genius. If your image is, say, 1024х768px, then what you get in the end is not a skewed 800х800px, but a proportional 800x600px.

Combined with MySQLDb and Boto this yields a very easy solution to my task. However, that's not the point.

As it turns out, getting to know many languages (even superficially) may give you a huge head start in learning a new programming language. I've had an overview or, sometimes, more than an overview of such languages as Lisp, Haskell, Erlang... How does that help me with Python? Well, I got an imeddiate understanding of the following:

Note: I can bear no responsibility for Haskell codes in the examples :)


Tuples and destructuring assignment

A tuple is a fixed-length list. This list may contain elements that are very different in nature:
  1. # Python tuple
  2. (1, 2, 'hello')
  1. -- Haskell tuple
  2. (1, 2, "hello")
  1. %% Erlang tuple
  2. {1, 2, 'hello'}


Looks similar, doesn't it? :)

Let now get data out of our tuples:
  1. # Python
  2. # А will contain 1
  3. # В will contain 2
  4. # С will contain 'hello'
  5. A, B, C = (1, 2, 'hello')
  1. -- Haskell
  2. -- a will contain 1
  3. -- b will contain 2
  4. -- c will contain 'hello'
  5. (a, b, c) = (1, 2, "hello")
  1. %% Erlang
  2. %% А will contain 1
  3. %% В will contain 2
  4. %% С will contain 'hello'
  5. {A, B, C} = {1, 2, 'hello'}


Certainly, the principles of theses examples are very different. Haskell and Erlang use pattern matching that Python doesn't have. However, it looks very similar and is very easy to understand once you know the other examples. PHP, by the way, has a similar thing:
  1. // А will contain 1
  2. // В will contain 2
  3. // С will contain 'hello'
  4. list($A, $B, $C) = array(1, 2, 'hello')


This, of course, is very different and the inner workings are absolutely different :) One thing about this is quite peculiar, though. Once you get used to these sorts of destructuring assignments, you start using PHP's list and Python's tuples much more often. Because it's so convenient.

Named parameters

I once talked about named parameters. As it turns out, Pythons has them.
  1. # define a function
  2. def myfunc(param='', another_param=1)
  3.     print param, another_param
  4.  
  5.  
  6. # call the function
  7.  
  8. # will print hello 5
  9. myfunc(another_param=5, param='hello')
  10.  
  11. # will print hello 1
  12. myfunc(param='hello')
  13.  
  14. # will print 1
  15. myfunc()


Anonymous functions (lambdas)

  1. # Python
  2. # define a list
  3. li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. # get only evens out of the list
  6. li_even = filter(lambda item: item % 2 == 0, li)


Very similar to code in other languages:

  1. -- Haskell
  2. -- define a list
  3. li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. -- get only evens out of the list
  6. li_even = filter (\item -> (mod item 2) == 0) li
  1. %% Erlang
  2. %% define a list
  3. Li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. %% get only evens out of the list
  6. Li_even = lists:filter(fun(Item) -> Item rem 2 == 0 end, Li)


List comprehensions

Remember how we used to define lists in mathematics? For instance:
  1. S = [1, 2, 3, 4]
  2. M = {x | x in S, x even}


M is all x's where x belongs to S and x is even. Nice languages have ways to define lists in a very mathematical way. This is called list comprehensions. One downside to Python's comprehensions is the syntax. Here are previous examples rewritten to use list comprehensions instead of lambdas:

  1. # Python
  2. # define a list
  3. li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. # get only evens out of the list
  6. li_even = [x for x in li if x % 2 == 0]
  1. -- Haskell
  2. -- define a list
  3. li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. -- get only evens out of the list
  6. li_even = [x | x <- li, (mod x 2) == 0]
  1. %% Erlang
  2. %% define a list
  3. Li = [1, 2, 3, 5, 9, 10, 256, -3]
  4.  
  5. %% get only evens out of the list
  6. Li_even = [X || X <- Li, X rem 2 == 0]




Anyhow, thanks to other languages the new language (a more or less mainstream language, not K :)) ) is not just easy, it's extreamly easy and can be learned in, say, 15 minutes.



Update: Corrections to Haskell code. Thanks, deni_ok

Pragmatic Erlang
happy
dmitriid
Almost 60 dollars left my pocket to get Joe Armstrong. "Programming Erlang. Software for a Concurrent World". It's finally mine! As a PDF only so far. I'll get to reading it eventually......

Yeah, baby! :)
Tags:

NY
happy
dmitriid
HAPPY NEW YEAR TO ALL FRIENDS AND ENEMIES!!!
Tags:

Orcas official site
happy
dmitriid
Orcas has been moved to http://orcas.dmitriid.com/

Project description etc etc can be accessed via project wiki at http://orcas.dmitriid.com/wiki
Tags: ,

Refactoring, pattern matching, function guards and Erlang
happy
dmitriid
I'm still late on my promise to talk about pattern matching even though today's post is related to patern matching.

In brief here is what pattern matching all about. The all-knowing Wikipedia defines pattern matching as
  the act of checking for the presence of the constituents of rigidly specified pattern

What does this mean though? This means that when a function (especially in dynamically typed languages) accepts parameters of different kinds/types we can define this function like this::
  
fun([H|T]) ->
    do_smth();

fun({a, tuple}) ->
    do_smth_else();

fun(value) ->
   do_a_third_thing();

fun(DefaultValue) ->
   do_default_thing().

What happens in the code above?
  
1. First function accepts a list/array as its parameter. The list consists of a Head and a Tail. So, if we pass [1, 2, 3, 4] to this function, the variable H will contain 1 and variable T will contain [2, 3, 4]

2. The second function accepts a tuple, that consists of two immutable values, "a" and "tuple"

3. The third function accepts an immutable value of "value"

4. The fourth function accepts everything rejected by the first three functions

So. If we call a function like this:
  
fun([2, 5, 72]).

we will trigger the first function, since it accepts an array/list.

However, if we call the function like so:
  
fun({another, tuple}).
 

we will trigger the fourth function. Why? Because even though we pass a tuple, the third function accepts only one tuple, {a, tuple} whereas we pass a different tuple, {another, tuple}.

So what's refactoring got to do with all this? And what's function guards?

A couple of things about function guards. Consider the ubiquitous Fibonacci function. First, pattern matching:
  
fib(1) -> 1; 

fib(2) -> 1; 

fib(X) -> fib(X-1) + fib(X-2).


Now, function guards:
  
 
fib(X) when X =< 3 -> 1; 

fib(X) -> fib(X-1) + fib(X-2).

The first line reads: "If X is less than 3, return 1".

Guards can check for a wide range of conditions, including such thnigs as is_list(X), is_tuple(X) etc. They can also be stacked using such keywords as "and", "or" etc. More on them in forecoming topics. Back to the topic at hand.

A question was raised over at RSDN with regard to implementation of the Factory pattern. For instance, in creating a wrapper for various database connections. The following С++ code was given as an example:
  
class Driver
{
public:
  virtual void connect() = 0;
};

class MysqlDriver : public Driver {}; //implements connect() using some mysql API calls.
class OracleDriver : public Driver {}; //implements connect() using some oracle API calls.
 


And, finally,
  
class DriverFactory
{
public:
  static Driver * createDriver( string name ) //creates necessary driver
  {
    Driver * driver = 0;
    if("mysql" == name ) driver = new MysqlDriver();
    else if( "oracle" == name ) driver = OracleDriver();
    else throw 1;
    return driver;
  }
};
 


The key to this factory, is of course the following:
  
if("mysql" == name ) driver = new MysqlDriver();
    else if( "oracle" == name ) driver = OracleDriver();
    else throw 1;
 


Ok. Let's rewrite it using Erlang.

First that springs to mind is the obvious line-by-line translation of the C++ code:
  
start(Driver) ->
    case Driver of
        mysql ->
            % connection happens here
            {};
        mnesia ->
            % connection happens here
            {};
        odbc ->
            % connection happens here
            {}
    end.


It's clear that you would call the function as follows:
  
start(mysql).
start(mnesia).
start(odbc).

Note that the "case" construct in Erlang also employs pattern matching.

What if connection i a bulky piece of code spanning 10-20 lines? We could employ function guards of course::
  
 
start(Driver) when Driver == mysql ->
    % connection happens here
    {};

start(Driver) when Driver == mnesia ->
    % connection happens here
    {};

start(Driver) when Driver == odbc ->
    % connection happens here
    {}.

This is more like it. Function call hasn't chaned a bit: start(driver_name). Guards, however, are not expressive enough. You have to read the definition of the function and only after that your eye cathes the guard. Is there a better way to do this? Of course!

Recall that pattern matching involves a "rigidly defined pattern". What's more rigid than
  
start(mysql) ->
    % connection happens here
    {};

start(mnesia) ->
    % connection happens here
    {};

start(odbc) ->
    % connection happens here
    {};


We can improve on our example and introduce options that will be passed to the connection code:
  
start(Driver) ->
    start(Driver, []).
        
start(mysql, Options) ->
    % connection happens here
    {};
    
start(mnesia, Options) ->
    % connection happens here
    {};
    
start(odbc, Options) ->
    % connection happens here
    {};
    
start(_, _) ->
    {error, driver_not_supported}.

Last lines simply states that for any other type of connection we through an error. Underscore means "any variable", a sort of "joker".

That's a part of what, to me, is the "Erlang Way". Very shortly and quite inaccurately this could be defined as: focus on what you need. A slight improvement of this definition is described in the concept of "aggressve programming". See. Erlang programming rules for a description.

That is, a program/module/function should do only the things it's meant to do. Under all other circumstances it should fail specifying why it failed, because it really should be the problem of the person who decided to (ab)use the program/module/function in the wrong way. As a result you end up with a small number of functions/modules which only do what they are meant to do. And this is quite handy

The same page lists other things in the "Erlang way", in particular:
  
- top-down programming (you start with abstractions and work towards details),
- "make it work correctly now and worry about otimizations later",
- principle of least astonishment (the system must behave predictably)
- "aggressive" programming etc.


Actually, this approach can be used - and is used! - in mainstream languages such as C++, Java, C#. However, in order to employ this approach in these languages, you need experience (quite a lot of it some times - a nod to C++). Erlang, on the other hand, encourages this approach right from the start.

I general, I'm not going to give up on Erlang in the forseeable future :) Unless it's in favour of Ne,erle, perhaps :))
Tags:

erlsoap
happy
dmitriid
Opensource projects, eh? They make you involve in all sorts of things :) Thanks to the ever unpredictable Lady Luck, Anton Fedorov decided to bring the aforementioned erlsoap library up to date.

So the battle ensued between me and the shiny new 0.4 version of erlsoap. This version decided it didn't like RSDN's webservice. After some fruitful discussion with Anton a new, 0.4.1, version of erlsoap appeared. This version, however, didn't suit qrilka in the least :)) The problem lay with the inets library distributed with Erlang and used by erlsoap. Inets, as it turned out, doesn't support proxy authentication.

So what's a developer got to do? I geared up and went to hunt... ehm... to add support for a more advanced ibrowse library. As a result, I've officially added my first patch to an opensource project which even brought me a mention in the soapclient module in erlsoap's new version 0.4.2.

Now I'm tuly happy :)
Tags: ,

The cavalry is coming!
happy
dmitriid
Camrade qrilka has shown interest in Orcas. Right now we are not quite sure as to what is the best approach to SOAP in Erlang.

Since RSDN's webservice is quite small, one approach would be to implement all calls and parse all responses by hand. But that's boring, isn't it? :)

Today I've braced myself and went to war with erlsoap, which has been stagnating for the past two years. Well, you can check out the code yourself. The file is test_soap.erl, and you run it by
  
test_soap:run().


qrilka suggested that we use Smerl. This still leaves quite a lot to do by hand. Anyway, tomorrow, time permitting, we'll take a look into the matter.
Tags: ,

Orcas
happy
dmitriid
Well, I've slowly started working on an offline client for RSDN.ru in Erlang.

Here's the project page: Orcas
Here's anouncement of the fact on RSDN (in Russian)

(no subject)
happy
dmitriid
Kosma Prutkov. Fruits of thought. # 66

Many a thing we do not understand not because our reasoning is weak, but because we have no notion of them

Dynamic languages rule
happy
dmitriid
It seems to me that dynamic languages...That is, languages which have more dynamics built in... That is, nice languages to put it simply :)) Well, they rule.

I've been browsing Jakarta Commons' source code using http://www.koders.com/ (I actualy only needed their WordUtils in order to rewrite them in ColdFusion). An then I see Validate.java:
    public static void isTrue(boolean expression, String message, Object value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression, String message, long value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression, String message, double value) {
        if (expression == false) {
            throw new IllegalArgumentException(message + value);
        }
    }

    public static void isTrue(boolean expression) {
        if (expression == false) {
            throw new IllegalArgumentException("The validated expression is false");
        }
    }


:)) Static typing is the answer to everything they say, but at what cost? :))) I wonder if this could be rewritten... ColdFusion-style:
<cffunction name="isTrue">
    <cfargument name="expression" type="boolean" required="yes">    
    <cfargument name="message" type="string" required="no">
    <cfargument name="value" type="any" required="no">  
	
	<cfset msg=IIF(IsDefined('arguments.message'), DE(arguments.message), DE("The validated expression is false"))>
	<cfset v=IIF(IsDefined('arguments.value'), DE(arguments.value), DE(""))>
	
	<cfif arguments.expression EQ false>
		<cfthrow type="IllegalArgumentException" message=msg & ToString(v)>
    </cfif>
</cffunction>


Key moments here are required="true|false" in argument definitions and the IsDefined('arguments....') function which, well, defines whether optional arguments exist. Oh, and don't forget about type="any" which allows you to pass arguments of any type. And the ToString function :)

Function overloading - is, undoubtedly, great. But I'll trade it IsDefined most of the time (when it's uses are justified, of course :) )

PS. Correct me if I'm wrong, but does Java really not have access to the array of arguments passed to a function? And I'm not talking about Variable arity.

?

Log in