What We Can Learn From Other Languages

Ovid on 2007-03-01T09:45:26

I'm thinking that a talk about what we can learn from other languages would be extremely fun, though it would be tough to go to in-depth in an hour long talk. So here's a snippet of Java:

public static int someMethod (int foo) {
    // ... method 1 code
}

public static int someMethod (int foo, int bar) {
    // ... method 1 code
}

And here's how that might get replicated in Perl:

sub someMethod {
    my $self = shift;
    my $foo  = shift;
    if (@_) {
        # method 2 code
    }
    else {
        # method 1 code
    }
}

Needless to say, the Perl version has scope for plenty of bugs that the Java version is less prone to.

Or how about some SmallTalk?

hello: times say: text
    (times > 100)
        ifTrue: [ Transcript show: 'You will get bored!']
        ifFalse: [1 to: times do: [:i | (Transcript show: text) cr]]

ifTrue and ifFalse are messages sent to boolean objects. Once I grokked this, I started grepping my OO code for 'if' statements and finding subtle bugs all over the place.

Or some Prolog:

likes('Ovid', 'Perl 5').
likes('Ovid', 'Perl 6').
likes(alice, 'Perl 6').

Extracting information from those facts is trivial in Prolog, but in Perl, often involves annoying while loops and if statements.

In fact, many of my thoughts about such a talk seemed related to "here's how other languages avoid bugs by minimizing procedural code".

Other examples welcome.


Re: What We Can Learn From Other Languages

jmcnamara on 2007-03-01T10:40:23

I'm not sure if the first example is fair. Simple method overloading in Java or C++ is generally used for functions that can take different parameter types, which isn't an issue in Perl, or to have functions with optional parameters which again isn't much of a problem in Perl:

sub someMethod {
    my $self = shift;
    my $foo  = shift || 1;
    ...
}

I think that method overloading is more tied to the fact the a language is statically typed and not necessarily something that Perl can learn from.

Which isn't to say that there aren't many things that we could learn from other languages. :-)

John.
--

Re: What We Can Learn From Other Languages

Ovid on 2007-03-01T11:00:35

Well, you say it's not much of a problem, but look at the snippet you posted:

sub someMethod {
    my $self = shift;
    my $foo  = shift || 1;
    ...
}

Can $foo be 0? Your code says 'no', but that might or might not be what you meant. Also, by the time you've finished the $foo line, you no longer can easily tell whether or not you even passed an argument for $foo.

In my original example, the code might do strange things if too many arguments are passed, or if they're not integers, even though that's what's expected. Params::Validate helps to mitigate many of these problems, but doesn't do anything for the multi-method dispatch bugs which can arise from sloppy programming (i.e., you dispatch to different methods based on the arguments or you have an ugly if/else construct). I've seen so many bugs arise from problems just with this.

Re: What We Can Learn From Other Languages

jmcnamara on 2007-03-01T13:05:59

When I said that it wasn't a problem I meant that it wasn't a problem to implement. Which isn't to say that there won't be problems in the implementation.

Some of these problems could be solved efficaciously with method overloading. Nevertheless, I still think that method overloading is mainly a necessity of static typing. Which for me is a more useful language feature and one that we have learned from since it will be included in Perl 6.

John.
--

Pop-11 / Lisp / Eiffel

Adrian on 2007-03-01T11:09:45

Off the top of my head...

Pop-11: Assignment was done with the right-arrow operator.

;;; perl's $x = 10 would be written as
10 -> x;

Which has the advantage (as far as I'm concerned anyway :-) of reading naturally ("10 goes into x") and allowing us to use "=" to indicate equality as god intended, removing all of those "if x=10" type errors.

Pop-11: The "updaterof" idiom (see this example) that gave a nice way of separating access/mutate methods.

Pop-11: direct access to the parser/compiler for the language so we could write our own extensions to the base language if we so wished. See this example.

Poplog: Of course the whole Pop-11/Lisp/ML/Prolog compiling to the same VM was pretty neat too - its why I still hope Parrot takes off:-)

Lisp: decent macros of course :-)

Eiffel: The elegant way they handle multiple inheritance.

Why is the Smalltalk way superior?

Shlomi Fish on 2007-03-02T09:30:18

I still don't understand why the Smalltalk way of ifTrue: and ifFalse: is superior to if/else. Can you please explain?

Other than that, one thing I can think of is the Scheme/SICP way of handling linked lists using car, cdr, cons, and recursion. This makes the code much more robust and much less error prone than using pointer games, as is often the case in C. Funnily enough, when I wrote similar code in Common Lisp, the people on #lisp on Freenode told me that I shouldn't use recursive helper functions like that.

minimizing control structures

riffraff on 2007-03-06T12:57:45

I recall that in "thinking in forth" there was a whole chapter about this :)

Anyway I'd say: predicate dispatch, which encompasses both pattern matching, overloading/mmd, and eliminates the need for if statements and switch/case.

The nice thing about predicate dispatch is that even your basic control structures remains open for change, it's the same shift from a huge switch/case and OO design.

Already in perl6 afaict :).