Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • Ah ha! Now you can see the problem. The syntax makes it very easy for the programmer to accidentally split up related sections of code and that makes maintenance harder.

    Well, this makes the assumption that the two methods are related in some way other than having the same name. When you think of classes being a collection of methods and attributes (or fields or instance variables or whatever you wanna call them), then the idea of splitting up this multi-method across 300 lines of code is horrid. But if you flip that assumption over (because it is only an assumption, and not a hard and fast rule of all OO systems) and look at methods as being first class things on par with classes, it does not seem to be such a problem.

    I think the difference is best illustrated in how a method is called. Do you call the method like this:

    $obj->foo(); # send the message foo to the instance $obj
    or do you call the method like this:

    foo($obj); # dispatch a varient of foo on the instance $obj
    They can produce the same results, but the approach is completely different.
    Imagine a system that let's you supply signatures to fall back on if you don't have the exact class you want:
    multi sausage (AnyThing $thing { void cry_for_help(void) } ) {
        $thing->cry_for_help;   # before being ground
        make_sausage($thing);
    }

    There is no need to imagine it, you can have it today! Ladies and Gentlemen i give you, ... Ocaml

    class anything =
    object (self)
        method cry_for_help = print_string ("Help anything\n")
        method foo = 1
    end;;

    class anywho =
    object (self)
        method cry_for_help = print_string ("Help anywho\n")
        method bar = 1
    end;;

    let sausage x =
        x#cry_for_help
    ;;

    sausage (new anything);
    sausage (new anywho);

    Here I have defined two classes who have the following "class signatures", which are (and this is what the ocaml REPL will print out for you):

    class anything : object
      method cry_for_help : unit
      method foo : int
    end
    class anywho : object
      method bar : int
      method cry_for_help : unit
    end

    And I have a function (sausage), who (through the magic of type inference) has been determined to have the following signature

    val sausage : < cry_for_help : 'a; .. > -> 'a = <fun>

    What this is saying is that sausage must be passed an object (not a class, only an instance) which has a method cry_for_help. When I run this in the OCaml REPL I get this:

    Help anything
    Help anywho

    What is basically going on here (as best as I understand it) is called "structural typing". Where instead of just comparing the type's by name (Foo->isa(Foo)) it is comparing them structurally.

    And of course my favorite part of OCaml is that I didn't have to actually write down any of this type information at all. The type inferencer just figured it all out for me. It determined that I would be calling the cry_for_help method on the object passed into sausage and built all the type signatures I needed. It then determined that the instance of anything and anywho properly fit that signature, and so it let me compile the code.

    Of course, this all comes at a price. OCaml is statically typed, so things like runtime code generation, runtime class creation or even auto-converting a string to an int are pretty much impossible to do. However, you do get blazing fast code (comparable to C/C++ in all the shootouts) and the warm fuzzy feeling that only static typing can bring you.

    - Stevan