Archive for the ‘Perl’ Category
Scala: Post-Functional, Post-Modern, or Just Perl++? March 6, 2010 | 10:30 pm

Let’s start with some background.

I complained that Scala did not seem to be very functional to me, but I didn’t really know how best to express what was fundamentally wrong with it. I did know that if “functional languages have a fixed set of features” like Scala’s creator, Odersky, claims, then it wasn’t simply “first-class functions in there, function literals, closures”, “types, generics, [and] pattern matching”. Scala has missed the functional boat in some basic way.

After a kerfuffle in the comments, Brian enlightened us all by telling us what is a functional programming language. His explanation (while being a self-admitted generalization) is summarized as follows:

So, what is it that differentiates the functional programming languages from all the other programming languages? It is simply this: the functional programming languages use, as their fundamental model of computation, the lambda calculus, while all the other programming languages use the Turing machine as their fundamental model of computation.

Six months later, Odersky responds with a very interesting post, which actually agrees that Scala is not a functional language in Brian’s sense, but instead argues that any language is functional if it “makes programming centered around functions easy and natural”. He then runs through a list of features which is in common with functional languages, noting that Scala has them within handwave enough (more on that later). He ends wishing that people would “stop thinking of functional programming as a different, novel, or exotic way to code”. Even more, though, Scala is apparently “an early example of a new breed of postfunctional languages”.

And that gets us to this blog post.

First of all, Odersky is still missing the point. It’s not about whether you use fold, map, and iter, or whether you can write closures easily. It’s not even really about pure functions vs. side-effects. To code in a functional style is a fundamentally different way of thinking about problems: instead of thinking about problems as nouns that are doing things, functional programming views a problem as a series of transformations to the world which results in an answer. This is why functional programming is considered “a different, novel, or exotic way to code”: it is a different, novel, and (as of yet) exotic way to code. It’s as different, novel, and exotic from OO as OO was from procedural. It’s a different way of thinking about the entire issue. You can check out this snippet of an IRC conversation from #ocaml for more on that.

The paragon of this way of programming is point-free programming, where you are quite literally building up a mega-function that describes how your program works, and then executing that one, single function when you run that program. If your language doesn’t lead people to re-discover point free programming at least in the small, then the language really isn’t taking function manipulation and functional language type conceptions seriously. And that’s the case with Scala: even Odersky admits that in Scala, “currying is more verbose and much less used than in other functional languages”. (Protip to Scala people: If one of the fundamental stunts of a style is pervasive in all the code but yours, you’re not in the same style of programming.)

What really gets me, though, is the claim that Scala is “an early example of a new breed of postfunctional languages”, because aside from the static typing, all the language features that Odersky trots out already exist in Perl. It’s hard to be a vanguard of a new breed of programming languages when there’s prior art from the 1980s.

Don’t believe me? The existence of a book on the topic unconvincing? Then let’s run the list of functional language features from Odersky.

  • Functions as first class values: check.
    sub apply(&$) {  # Take a function as an argument no problem
      $_[0]->($_[1]);
    }
     
    sub times2($) {  # Create a function to take
      print $_[0]*2 . "n";
    }
     
    apply(&times2, 3);
  • Convenient closure syntax: check
    my $x = 2;
    apply { print $_[0]*$x . "n" } 3;
     
    my $times_x = sub($) {
      print $_[0]*$x . "n";
    };
    $times_x->(3);
  • List comprehensions: check. (See perlfunc on list data.)
  • “Curried” function definitions and applications: check-ish.
    Okay, so calling this a “check” on Scala is a bit of a reach (cite, cite, cite, although note thishere is a more sympathetic run-down on Scala currying). Ignoring the foo(2,_:Int) syntax for a moment, we can implement basically the same style of “‘curried’ function definitions” such as Scala’s List#foldLeft.

    sub add {
      my $x = shift;
      return sub { $x + shift };
    }
    add(2)->(3);  # Okay, so you do need an extra ->

    In the case of our apply function above (where we take a function as the first argument), it’s even easier.

    apply { print $_[0]*$x . "n" } 8;

    Now, there isn’t really argument skipping (i.e.: foo(_:Int,3)) as a syntax feature, and there isn’t a built-in curry function, but if you want Scala’s Function.curried in perl, here it is:

    # This code released under Creative Commons 0 and WTFPL.
    sub curry(&@) {
      my($f,@args) = @_; 
      return sub { $f->(@args, @_); };
    }
     
    sub add($$) {
      return $_[0] + $_[1];
    }
     
    my $curried = curry(&add, 2); 
    print $curried->(3) . "n";
  • Lazy evaluation: check. See Scalar::Defer for lazy val equivalents and Tie::LazyList for lazy seq equivalents. People generally use a double-return approach for generators (which I realize are different than lazy seqs and only kinda-sorta lazy).
  • Pattern matching: check (okay, check-ish). See Switch. The decomposition isn’t there, which is the biggest weakness. But the general cumbersomeness and lack of real algebraic data types hamstrings the coolest parts of pattern matching anyway, so I’m calling it a draw. (This should be read as a generous and sympathetic ruling for Scala: Cedric Beust, for instance, rails against pattern matching/case classes and says “it’s hard for me to see case classes as anything but a failure“.)

In addition, perl’s got a few features in its favor for functional programming, like more flexible arguments, autovificiation, list/argument coercion, and dynamic symbol table mangling. Since perl also has OO capabilities, perl is at least as convincing a “post-functional language” as Scala. But there’s even more in common between the two than that.

Odersky’s “post-functional language” is really a subtype of Larry Wall’s “post-modern language”: it’s an attempt to create a language that is a grab-bag of multiple paradigms. And when you do that, you’re just begging for the complaints that you hear leveled against both perl and Scala: it’s too complicated, its syntax is weird, it’s too magical, people write in entirely distinct subsets of the language, etc. (cite, cite, cite) Now, those who master the language (or master their favorite subset of it) love the TIMTOWTDI aspect. But it also means that the language is left as a jack-of-all-trades, master of none. Yes, Scala and perl integrate a lot of powerful tools from functional languages—but learning OCaml still blew my mind, despite knowing perl for years. As I started off saying, Scala is not a functional programming language. It is a statically typed object oriented language with closures.

Now, there is a sense in which Odersky is really onto something. The world of programming is forever transformed with closures and list comprehensions as being mandatory for new high-level languages, even if they’re otherwise object oriented. And software developers are going to need how to work with them effectively if they want to read code moving forward. Yes, after 20+ years, the rest of the programming world finally caught up to one of perl’s fundamental insights.

My Fundamental Issue with Ruby February 1, 2009 | 04:25 pm

Given a method like…

def myFun(val) puts(val+3) end

If I accidentally call it with the String “5″, I get a type error, which looks like this:

test.rb:2:in `+': can't convert Fixnum into String (TypeError)
	from test.rb:2:in `myFun'
	from test.rb:4

That’s fine by me, but now I’d like to give a more meaningful error message (“Hey, buddy, you meant to pass in something that can +3. Like a Vorpal Sword.”). At that point, though, I’m basically hand-rolling my own static typing, except without all the useful compile-time enforcement or automatic checking.

Note the corresponding Perl subroutine Does The Right Thing:

sub my_fun($) {
  print ($_[0] + 3)
}
my_fun("5")

And I don’t mind that. If you’re going to play it fast-and-loose with types, that really is fine by me. But Ruby gets on my nerves with the way it does not let me do typing when useful and yet eagerly punishes me for using the wrong types. If a language is going to give me the responsibility of handling types, give me the power to handle them well. If it’s going to take responsibility for handling types, then it can have the power. There are domains where each of these is an appropriate take on things. But giving me the responsibility while not giving me the power simply irks me.

Functional (Meta)?Programming Stunts for Ruby and Groovy (and a Little Perl) June 24, 2008 | 11:04 am

After I learned OCaml, my coding mindset was totally distorted. I started writing Java code that looked like this:

  public Collection<foo> getCertainFoos() {
    return
      CollectionUtils.select(getFoos(), new Predicate() { 
         public boolean evaluate(Object o) {
            return SOME_CONSTANT.equals(((Foo)o).getProperty());
         }
      });
  }
</foo>

This is kinda ugly in Java, but it’s simply what comes out when I was thinking this in OCaml:

List.find_all (fun i -> SOME_CONSTANT = i#getProperty()) #getFoos()

I also started slapping final everywhere — see Yet Another Reason final Is Your Friend. A ubiquitous use of final actually gave some nice patterns (in the “macro” sense of patterns), but raised all kinds of eyebrows and made my code unmistakable. This lead up to a unique coding style which you can see in my most involved open source project, JConch. Meanwhile, my co-blogger was talking about “The Hole in the Middle” Pattern, which is also a lay-up within FP circles but required some backflips to implement in Java (functional interfaces) and C# (delegates).

It wasn’t until the advent of Ruby and Groovy, though, that functional programming skills really became easier to use. Basically, because of the inline closure’s succinct syntax (and ability to access non-final variables), I could suddenly do all kinds of really fun stuff. This “fun stuff” was exactly the kind of stunts I was pulling in Perl back in the day (see the BEGIN block in my Text::Shift code for a reasonably accessible example), and it was part of the reason I loved Perl so much at the time.

So, I thought I’d share some more of these cute stunts with you.
Read the rest of this entry

I Made This For All My Perl Peeps February 29, 2008 | 08:17 am

Laziness, Impatience, and Hubris: Larry Wall Haz Dem
(If you don’t get the joke, read this. The industry-standard CPAN Perl library also hosts a bunch of Larry Wall witticisms, right next to The Perl Purity Test. There’s some real software over there, too. Oh, and I mean Peeps1, not peeps.)

1 OMG, my eyes!!!

A Defense of Prototypes, or, Why Does Tom Christiansen Hate Perl? October 19, 2005 | 07:03 am

I recently started a bit of a ruckus on the Minneapolis PerlMongers list by suggesting that Perl prototypes are Good, not Evil. This is going up against the saints of Perl, particularly Tom Christiansen, and so the position was pretty much dismissed out of hand.

I’d like to take this opportunity to say that, after serious consideration, I stand by my position. I will unequivicably state that I think Perl prototypes (with minor reservations) are a Good Thing, and that all new code should use them. After considering his complaints, I will furthermore assert that I think Tom secretly hates Perl, and that he’s blaming prototypes for his fundamental disappointments with the language.

The fundamental issue is whether it is better to allow PI - 1 to secretly and silently become PI(-1), or to allow people to pass arguments as a list — as far as I’m concerned, the issue with the first is bigger than the advantage of the second, and therefore I support prototypes. I believe that if you’re talking about scalars, you should use $, so if you want to pass scalar parameters into a function, you should have to draw scalars out of your array somehow — it’s broken to automagically draw for you.

Now, before continuing I’d want to state that I certainly would agree that there are bugs in prototypes. Here’s the start of a list, although I reserve the right to append onto it:

  • The fact that passing an array into a scalar slot is silently converted is certainly a bug — there is the scalar function, it should be used. It should be a warning (at least) to do this in code with the warnings and/or strict pragma in play.
  • The ability to write anything after a @ prototype symbol is a bug. Since the @ prototype symbol consumes all remaining elements, the concept of arguments “after” the @ is nonsensical.
  • The existence of the % prototype symbol is also a bug. The concept of a \% prototype symbol is legitimate (there are hash references), but the concept of a % prototype symbol is nonsense (there is no “hash context”). Perl prototypes force context and silently reference variables, and that’s it.
  • The nature of the * and & prototypes need to be made more clear, because they’re awkward and buggy.
  • Like any new feature of a language, prototypes shouldn’t be retrofitted to code, but should be used in all new code.

Once you get past these (fixable) issues, though, the rest of Tom’s complaints are actually complaints about the Perl language as a whole, in that I can find equivalent problems in the core Perl functions.

Now let’s address Tom’s complaints directly.

The first surprise is that when Perl programmers see “$”, “@”, and “%”, they usually think “scalar”, “array”, and “hash” respectively. This isn’t completely accurate in all cases, but it is, nevertheless, what they often think.

So, in short, Tom is saying that since people haven’t taken the time to really understand what prototypes are, we shouldn’t use them. If you understand that prototypes ONLY force context and magically take references, you’re not going to think “scalar” when you see the “$” prototype: you’re going to think “scalar context”. Assuming that we can make that minor adjustment to the way people think, we gain the major advantage of actually being able to write rand 10, rand 10, rand 10 without it becoming rand(10, rand(10, rand(10))) or something equally nonsensical.

So when the user sees a “prototype” of “$”, the primrose programming path leads them to believe, lamentably, that the compiler will complain if they pass something in that’s not a scalar. Nothing could be further from the truth!

Granted. As stated above, this is a bug: it’s a fixable problem, not built into the design of Perl prototypes. If Tom really doesn’t like it so much, he should hack the Perl code to fix it. Still, even without it being implemented, all that means is that people who use your code wrong are going to get garbage results: GIGO. This problem is also not unique to prototypes (remember Tom hating Perl?): the code length(@arr) will silently and cleanly succeed, which means the issue exists in the core of the language.

@array = (1 .. 10);
print length(@array);

You might think that would be an error, but it’s not, because there exists an implicit coercion rule for arrays taken in scalar context: it’s the number of elements in that array.

In the particular example of length(@array), non-prototyped code would also gleefully and secretly succeed, returning the length of the first element of the code. Since the same class of problem exists whether or not prototypes are there, it’s not prototypes that are the problem. The problem is the intuitive behavior, but that problem is really with the length function’s name being misleading. Even more, without prototypes, the calls length(), length($a, $b, $c), and length(@arr1, @arr2) would all silently succeed.

There’s more similar arguments laid out, so I’m going to skip over them unless there’s some real insistance. The upshot is that the problems are with Perl’s insistance on trying to do the right thing even when it doesn’t always make sense: the , operator that evaluates expressions and returns the value of the last one, the implicit coercion of lists into scalars, etc., etc. So Tom’s problem isn’t with prototypes, but with Perl’s behavior in those cases. The prototypes are doing precisely what they’re supposed to be doing by forcing context, and when you pass garbage into them, they get you garbage out — the fact that the compiler doesn’t whine is a bug which should be fixed, but not sufficient cause to be rid of them completely.

Let’s examine the “@” “prototype”. What’s that? Is it an array? No, it’s not. It just looks like that. It’s merely a list. Is it a required list? Why no, it’s not. You’re welcome to supply a list of no elements; that is, omit it altogether.

Granted. You need to keep in mind that “@” means “all remaining arguments, possibly zero”. Once you know that’s the case, though, you can code with it. Perl happilly has zero-length lists everywhere else: why does Tom expect prototypes to be different?

Finally, he has this complaint:

To see how this works when you use “\@” in the “prototype”, you haven’t declared a function as taking a reference to an array. Rather, you’ve declared one that takes an array, which the compiler will pass by (implicit) reference to you.

Granted. Perl will take implicit references for you all over the place: for instance, push(@arr1, @arr2), which Tom acknowledges. The fact that you can’t tell that the first is being treated as a reference and the second is being treated as a list isn’t a problem with prototypes, it is a decisison explicitly made to Do The Right Thing while keeping the number of \ characters to a minimum. If you don’t like it, you don’t like that aspect of Perl’s nature, so the problem is much larger than prototypes. Blaming prototypes for them is like blaming a carpenter’s hammer because you don’t like the architecture of your house.

Think of how often you’ve been forced to do something like

push @{ $hash{$string} }, $value;

Why can’t you just do this:

push $hash{$string}, $value;

It’s because of the “prototype”.

Actually, it’s because Larry Wall didn’t want to have to type push \@arr1, @arr2 every time the push function was used, and because he made the decision that Perl did NOT do implicit dereferencing so that $hash{$string} = $arrref didn’t get silently dereferenced. Again, the problem isn’t the prototype, it’s other aspects of the language that happen to involve calling subroutines.

Given those considerations, I’ve got to say that I just think Tom’s railing against prototypes really exposes a very superficial consideration for how the langauge actually works and how prototypes fit in there — he aggrandizes them to blame them for things that aren’t their fault (the compiler not issuing warnings), and then is annoyed when they don’t do things the language explicitly is designed not to do (implicit dereferencing). It’s not prototypes that Tom has a problem with, it’s Perl.