in reply to Re: perl 5.38: can the body of a class declaration contain arbitrary code?
in thread perl 5.38: can the body of a class declaration contain arbitrary code?

Code in a class block behaves like code in a package block: It is evaluated once.

Ok, thanks. I can see the reason for that. Principle of least surprise. But I was kinda hoping they had gone for something like Scala's semantics, where all code in the class definition outside of methods constitutes the constructor.

Today's latest and greatest software contains tomorrow's zero day exploits.
  • Comment on Re^2: perl 5.38: can the body of a class declaration contain arbitrary code?

Replies are listed 'Best First'.
Re^3: perl 5.38: can the body of a class declaration contain arbitrary code?
by haj (Vicar) on Jul 05, 2023 at 14:40 UTC

    There is a place for code which goes into the constructor: It is the ADJUST block. So you can have both: Class initialization as in my $next_count = 1, and constructor code.

    "Class methods" in Perl 5.38 are just subs. So, to expand your example:

    use 5.038; use feature 'class'; no warnings 'experimental'; class WithACounter { my $next_count = 1; # class initialization, called once my sub last_one_was_bad() { 0 } my sub delete_last_one() { ...; } field $count = $next_count++; ADJUST { if (last_one_was_bad()) { delete_last_one(); $next_count--; } } }

      But that's not the same. That performs the "adjustment" after the initialization of the field, whereas in my example it happens before. But reading the doco a little closer, it looks like ADJUST code is executed "in line" where it occurs in the class definition. So the following would in fact be equivalent to my original (invalid) suggestion:

      class WithACounter { my $next_count = 1; ADJUST { if (last_one_was_bad()) { delete_last_one(); $next_count- +-; } } field $count = $next_count++; }

      Given that, then it would appear that Scala-like class definition is possible; one simply has to wrap any statements other than my/field in ADJUST blocks.

        Careful, that is misleading. The field initializers run before ADJUST, regardless of the order in which they are written. This has been specified in the Corinna RFC and is how it is implemented. I don't see it specified in the docs, though, which is a bad omission and should be fixed for 5.38.1. Demo code here:

        use 5.038; use feature 'class'; no warnings 'experimental'; class WithACounter { my $next_count = 1; ADJUST { say "Next count in ADJUST: $next_count"; } field $count = do { say "Next count in field init: ", $next_count; $next_count++; }; method count { $count } } say "Next count in the object: ",WithACounter->new->count;

        Output:

        Next count in field init: 1 Next count in ADJUST: 2 Next count in the object: 1
        Given that, then it would appear that Scala-like class definition is possible; one simply has to wrap any statements other than my/field in ADJUST blocks.

        This is true. Since $count = $next_count++; is an initialization with a side effect (incrementing a class variable), I would also move that into the ADJUST block. It is the only way to get it executed after other code in ADJUST.