Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Method cascade syntax

Tags:

raku

Dart and Smalltalk have method cascades.

It seems that a similar style can be achieved via do with.

For example, here's a simple program which uses GTK::Simple:

use v6;

use GTK::Simple;

my $app = GTK::Simple::App.new(title => "abc");

$app.set-content(
    GTK::Simple::VBox.new(
        my $button_a = GTK::Simple::Button.new(label => 'bcd'),
        my $button_b = GTK::Simple::Button.new(label => 'cde')
    )
);

$app.border-width = 20;

$button_a.clicked.tap({ .sensitive = False; $button_b.sensitive = True });

$button_b.sensitive = False;

$button_b.clicked.tap({ $app.exit });

$app.run;

Here's the equivalent program using do with in a few places to achive an effect similar to method cascades:

use v6;

use GTK::Simple;

my $app;
my $button_a;
my $button_b;

do with GTK::Simple::App.new(title => 'abc')
{
    $app = $_;

    .set-content(
        GTK::Simple::VBox.new(
            $button_a = do with GTK::Simple::Button.new(label => 'bcd')
            {
                .clicked.tap({ .sensitive = False; $button_b.sensitive = True });
                $_
            },
            $button_b = do with GTK::Simple::Button.new(label => 'cde')
            {
                .sensitive = False;
                .clicked.tap({ $app.exit });
                $_
            }
        )
    );

    .border-width = 20;
    .run;
};

My question is, is there a more idiomatic way to express the method cascade style in Perl 6?

A drawback to do with is that you must explictly return $_. With traditional method cascades, the original receiver object is implicitly returned.

For example, here's how $button_a is set:

$button_a = do with GTK::Simple::Button.new(label => 'bcd')
{
    .clicked.tap({ .sensitive = False; $button_b.sensitive = True });
    $_
}

It would be nice if $_ didn't have to be explicly returned. For example, something like:

$button_a = do cascade GTK::Simple::Button.new(label => 'bcd')
{
    .clicked.tap({ .sensitive = False; $button_b.sensitive = True });
}

Another drawback to do with is that the syntax is more heavyweight than Dart and Smalltalk method cascade syntax. Something closer to the Dart style might look like:

$button_a = GTK::Simple::Button.new(label => 'bcd')
    ..clicked.tap({ .sensitive = False; $button_b.sensitive = True });
like image 303
dharmatech Avatar asked Jun 01 '16 05:06

dharmatech


3 Answers

https://doc.perl6.org/routine/andthen

my $obj = IO::Path.new($*CWD) andthen do { .say; 42 }; say $obj.perl
like image 141
ugexe Avatar answered Oct 15 '22 07:10

ugexe


With this subroutine:

sub cascade ($obj, &proc) { proc($obj); $obj; }

the example can be written as follows:

use v6;

use GTK::Simple;

sub cascade ($obj, &proc) { proc($obj); $obj; }

GTK::Simple::App.new(title => 'abc').&cascade: {

    my $app = $_;

    my $button;

    .set-content:
        GTK::Simple::VBox.new(

            GTK::Simple::Button.new(label => 'bcd').&cascade: {
                .clicked.tap({ .sensitive = False; $button.sensitive = True; });
            };

            $button = GTK::Simple::Button.new(label => 'cde').&cascade: {
                .clicked.tap({ $app.exit; });
            }
        );

    .border-width = 20;

    .run;
};
like image 25
dharmatech Avatar answered Oct 15 '22 08:10

dharmatech


I think using given rather than do with is more idiomatic for the exact same functionality. Given just passes whatever through as the topic $_ value for the following block.

like image 25
Matt Oates Avatar answered Oct 15 '22 07:10

Matt Oates