Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

What if Perl had an OO standard library?

by awncorp (Acolyte)
on Aug 23, 2022 at 11:39 UTC ( [id://11146308]=perlmeditation: print w/replies, xml ) Need Help??

Programming in Perl is choices all the way down. An OO standard library would make it a lot easier to write Perl in a way that avoids having to come up with similar or the same solutions to common computing tasks, but, ... sustained object-orientation in Perl is difficult because the concept and mechanisms were bolted onto the language as an afterthought, and because it's optional, so one has to oscillate between this paradigm and others, i.e. some things are objects, most things are not, so when using Perl you have to constantly reaffirm your object-orientation. What do you think?

http://blogs.perl.org/users/al_newkirk/2022/08/introducing-venus-a-new-world-for-perl-5.html

"I am inevitable." - Thanos
  • Comment on What if Perl had an OO standard library?

Replies are listed 'Best First'.
Re: What if Perl had an OO standard library?
by haj (Vicar) on Aug 23, 2022 at 14:39 UTC

    Venus is a rich demonstration that it is possible to implement "Everything is an object" in Perl. But honestly, I doubt that it is much more than that.

    Objectification of arrays and hashes makes it look like Java, which isn't bad, but no particular benefit either. It gets weird when primitives like numbers and strings are objectified. Venus::Number objects can, thanks to overload, be manipulated with the usual arithmetic operators. However, as soon as I apply an arithmetic operator on a Venus number, the result loses its object properties and is just a plain number. There are no methods like $one->add($two) which would allow to return new Venus::Number objects.

    Here's some experiments I ran. Some results weren't as I expected.

    use 5.028; use Venus qw(catch); use Venus::Number; my $one = Venus::Number->new(1); my $two = Venus::Number->new(2); say "one = ", $one; # one = 1 say "one = $one"; # Argument "one = " isn't numeric in addition (+) .... # 10 <---- Venus::Number objects don't interpolate print "two = "; $two->print_string; print "\n"; # two = 2 <--- Methods don't interpolate either # Arithmetics my $three = $one + $two; say "three = ", $three; # three = 3 <---- Now it does interpolate print "three = "; $three->print_string; print "\n"; # Can't locate object method "print" via package "3" # <---- but has lost its blessing # Strings use Venus::String; my $just = Venus::String->new('Just'); my $another = Venus::String->new('another'); my $perl = Venus::String->new('Perl'); my $hacker = Venus::String->new('hacker'); say "$just $another $perl $hacker"; # ----> hackerPerlanotherJust

      Thanks for your feedback. It's much appreciated. While I understand your perspective I maintain a difference of opinion. For example:

      Your take:

      "it is possible to implement "everything is an object" in Perl ... which isn't bad, but no particular benefit either"

      My take:

      You're right to call out that this is a move towards "everything is an object" in Perl. As mentioned in another comment/reply, "the lack of a native type system means that your classes and methods can’t be certain of the type of data they’re being passed, which forces you into a position of defensive programming".

      Your observation:

      "Venus::Number objects can, thanks to overload, be manipulated with the usual arithmetic operators. However, as soon as I apply an arithmetic operator on a Venus number, the result loses its object properties and is just a plain number."

      My response:

      You're correct and this is intentional. All value class methods, intentionally, return native data types. I refer to this in the article under "guiding principles" where I state that "the library should ease the multi-paradigm identity crisis" and "be a compliment, not a cudgel", i.e. if I'm using Venus and (in a particular context) I only want to leverage the Venus::Array#any algorithm (e.g. Venus::Array->new([1..8])->any(sub{$_ > 5})) I can use that and have the result be a basic arrayref, OR, if I want to opt-into "everything is an object" and chaining method calls via autoboxing I can do that easily too (e.g. Venus::Array->new([1..8])->box->any(sub{$_ > 5})->count->unbox).

      P.s. Thanks again for the great feedback. Based on it I'll be adding the simple math routines to the Number class in an upcoming release, as well as fixing the string interpolation bug.

      "I am inevitable." - Thanos
        the lack of a native type system means that your classes and methods can’t be certain of the type of data they’re being passed, which forces you into a position of defensive programming

        Well, in my view Perl does never force me into any position, but, depending on the task, defensive programming is recommended.

        Using objects as a surrogate for a type system is just a thin layer. For safety, this only helps if the classes do the appropriate validations on object creation. For example, Venus::Number accepts any value, so my classes and methods still can't be certain of the type of data they're being passed:

        use 5.028; use warnings; use Venus::Number; use File::Temp; my $n; # These two come with warnings say Venus::Number->new($n); # '' say Venus::Number->new($n,$n); # 0 $n = 1; say Venus::Number->new($n); # 1 $n = "abc"; say Venus::Number->new($n); # abc $n = [3,2,1]; say Venus::Number->new($n); # ARRAY(0x...) say Venus::Number->new($n)->abs; # 94653281131368 $n = File::Temp->new; say Venus::Number->new($n); # /tmp/ER2Mi14BOz
Re: What if Perl had an OO standard library?
by afoken (Chancellor) on Aug 23, 2022 at 12:22 UTC

    (Standards)

    Programming in Perl is choices all the way down. [...] object-orientation in Perl is difficult because the concept and mechanisms were bolted onto the language as an afterthought, and because it's optional, so one has to oscillate between this paradigm and others, i.e. some things are objects, most things are not [...]

    I don't mind that at all. In fact, being able to choose how I want to implement $stuff is a strength of Perl, not a weakness. Forcing everything to be OO is a waste of time, because some things can be done easier and/or better without OO.

    This?

    my @stuff=getSomeList(); for my $thing (sort @stuff) { say "$thing"; # quoted to force stringifcation }

    Or this?

    say "$_" for sort getSomeList(); # quoted to force stringifcation

    Or this?

    SomeGlobal::StdLib::Class->getFactoryInstance()->getSomeList()->sort() +->forEach(SomeOtherGlobal::StdLib::Class->getInstance()->createStdout +WriterFunction());

    Yes, all are made up. I don't like the last one. It is everything but readable, and it is everything but obvious. The second one is ok if it does not get longer.

    How much the last one sucks can be seen by looking at LINQ. Microsoft invented a whole new syntax for C#, somewhat similar to SQL, so that coders no longer have to write that ugly chained method calls. Yes, it's mostly syntactic sugar plus Lambda expressions plus yet another standard library plus a way to inject methods into other classes. The result is that you can write this:

    // Copied from Wikipedia var results = from c in SomeCollection where c.SomeProperty < 10 select new {c.SomeProperty, c.OtherProperty}; foreach (var result in results) { Console.WriteLine(result); }

    Instead of this:

    // Copied from Wikipedia var results = SomeCollection .Where(c => c.SomeProperty < 10) .Select(c => new {c.SomeProperty, c.OtherProperty}); results.ForEach(x => {Console.WriteLine(x.ToString());})

    ... which is what happens behind the scenes, as far as I understand C#. But the point here is: You don't see those OO chains, you see a much more convienent syntax that hides the ugly OO stuff.

    And this is how it could be written in perl, completely without OO:

    my @results=map { [ $_->{'SomeProperty'}, $_->{'OtherProperty'} ] } grep { $_->{'SomeProperty'} < 10 } @SomeCollection; say join(' ',@$_) for @results;

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

      I'm very tempted to agree with you "wholesale" given that I've been doing Perl since the mid-late 90s and through many many many bouts of trial and error have learned how to write well-reasoned succinct very Perlish code. However, I recognize that I'm only able to do so because of the amount of time I put into learning the language, and all of my failures along the way.

      People (other than us) needing to use Perl, who may not have the time or interest in learning "the ways of the force", who may be coming from other (typically OO) languages, would be much more comfortable in Perl if they could find corollaries to the idioms they already know.

      Some examples:

      In JavaScript:

      ['a', 'b', 'c'].forEach(item => console.log(item.toUpperCase()));

      In Ruby:

      ['a', 'b', 'c'].each(|item| puts item.upcase);

      In Perl:

      print uc("$_"), "\n" for ('a', 'b', 'c');

      In Venus:

      Venus::Array->new(['a', 'b', 'c'])->call('map', 'say', 'uppercase');

      In Venus:

      Venus::Array->new(['a', 'b', 'c'])->map(sub{ print uc $_, "\n" })

        Your examples here just reinforce my general opinion that full-OO languages where everything is an object are just overly verbose when it comes to simple operations. By eschewing this and having intrinsic non-object types we (in Perl and in other languages which do the same) can write much cleaner and therefore maintainable code.

        The contrast is slightly hidden by an overly verbose Perl entry. I think in most cases I would be using

        say uc for 'a', 'b', 'c';

        or perhaps with qw/a b c/ instead.


        🦛

Re: What if Perl had an OO standard library?
by hv (Prior) on Aug 23, 2022 at 16:51 UTC

    sustained object-orientation in Perl is difficult because the concept and mechanisms were bolted onto the language as an afterthought

    I disagree with this characterization: I consider the way OO capabilities were introduced to perl (in the transition from v4 to v5) by adding support for bless() and $obj->method(...)* was beautiful in its elegance, simplicity and power. I still love it to this day.

    What difficulties do you actually find in your search for "sustained object-orientation"? If you could describe those with some examples, it might be easier to discuss whether Venus would be a good solution for them.

    (*) plus maybe a couple of other bits and pieces

      No offense intended.

      The remark that "sustained object-orientation in Perl is difficult …" is just my own fancy way of saying that “treating everything as an object is difficult/manual in Perl”. Data will always enter your program in its raw primitive form, and while you can objectify it (bless it), the lack of a native type system means that your classes and methods can’t be certain of the type of data they’re being passed, which forces you into a position of defensive programming. Consider the following examples (you made a routine and you want to compare anything passed in) ...

      Note: smatchmatch is experimental and not recommended for production use

      sub compare_things { $_[0] ~~ $_[1] }

      example #1

      compare_things(1, '') ''

      example #2

      compare_things('', '') 1

      example #3

      compare_things(1, []) ''

      example #4

      compare_things(1, bless{}) Died! Smart matching a non-overloaded object breaks encapsulation

      example #5

      compare_things(0, '') ''

      example #6

      Venus::Number->new(0)->eq('') # DMMT and DWIM 1

      example #7

      Venus::Number->new(0)->tv('') # (tv) type and value equality 0

      example #8

      Venus::Number->new(0)->eq(bless{}) # DMMT and DWIM 0

      "I am inevitable." - Thanos
Re: What if Perl had an OO standard library?
by stevieb (Canon) on Aug 23, 2022 at 20:32 UTC

    I much prefer the option to create either an object orientated distribution, or a non-oo one.

    If I don't need to keep any state, why bother with the added complexity? OO adds overhead, no matter how slight.

    Among my list of familiar languages, Python is one. Python is "everything is an object". I'm a guy who prefers simplicity, and freedom to choose. If I want to create a list of functions for very basic mathematical calculations purely written in C fronted by Perl with no OO overhead, I like that choice. If I want to represent a Tesla vehicle that has thousands of always-changing parameters that requires a mechanism to maintain that state, I want that choice. When I want to wrap another language's API where I want to provide both a procedural and an OO interface, I want that choice. I feel that everything is an object is a bit overkill. That's why I didn't diverge with the then Perl6 crowd (in fairness, I did give it a very good run to be certain though).

    Important part is the availability to choose. Even when I do write OO distributions (most of mine are), I don't use anything but the core perl OO functionality. No Moose or equivalents etc. Even when Corinna comes into play, I very much doubt I'll change my ways.

      "Even when I do write OO distributions (most of mine are), I don't use anything but the core perl OO functionality"

      Is this because you dislike the Moose-like syntax, because of speed concerns, or because you don't want to create dependencies on non-core modules for end users.

      If it's because of speed or dependencies, you should look at Mite. Mite allows you to write Moose-like code, "compile" it on your machine into plain Perl, and distribute the compiled result so your end users don't need any non-core modules.

Re: What if Perl had an OO standard library?
by Your Mother (Archbishop) on Aug 23, 2022 at 12:33 UTC

    Al is a terrific dev and nice dude. Venus is built on Mars. That was fun to write. I have yet to try either but I’ve been planning to do so. I do know that they are quite performant and Mars is faster than everything other than raw hand-roled objects or similar tiny/optimized packages like Mo.

      Venus is built on Mars.
      It doesn't use it, though. It duplicates the code.

        With all due respect, that's a distinction without a difference.

        "I am inevitable." - Thanos

      :bow: @YourMother. Thanks for the kind words. Here's some cool stuff I haven't blogged about yet that you can do with Venus:

      # throw exceptions easily
      Venus::Path->new('/path/to/nowhere')->throw->error({message => 'Missin +g file'}) "Missing file"
      # catch exceptions easily
      Venus::Path->new('/path/to/nowhere')->catch('open')->message "Can't open /path/to/nowhere: No such file or directory"
      # determine and call methods on each item in an array
      Venus::Array->new(['a'..'d'])->call('map', 'uppercase'); [ 'A', 'B', 'C', 'D' ]
      # use indirect dispatching to nest calls (in this case, on each item in an array)
      Venus::Array->new(['a'..'d'])->call('map', 'box', 'uppercase'); [ bless({'value' => bless({'value' => 'A'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'B'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'C'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'D'}, 'Venus::String')}, 'Venus: +:Box ) ]
      # use MORE POWER and force return an "autoboxing" object so you can continue chaining things
      Venus::Array->new(['a'..'d'])->box('call', 'map', 'box', 'uppercase'); bless({'value' => bless({'value' => [ bless({'value' => bless({'value' => 'A'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'B'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'C'}, 'Venus::String')}, 'Venus: +:Box'), bless({'value' => bless({'value' => 'D'}, 'Venus::String')}, 'Venus: +:Box ) ]}, 'Venus::Array')}, 'Venus::Box'});
      "I am inevitable." - Thanos
      Mars uses dualvar instead of use real true false !!0 !!1

        I'm not sure what you mean by "real" true and false. Perl doesn't have real true and false yet. If you're talking about "true" and "false" from the "builtin" pragma, that's still very experimental and only available from Perl 5.36+. What we have now are different conventions for representing true and false, i.e. the legacy 1 and 0 (and the problems they have, i.e. cross-language interoperability), the YAML/JSON spurred \1 and \0 (but that doesn't play nice with legacy code), and now my dualvar-based 1|"1" and 0|"0" which is (IMHO) better than all the rest because it's fully backward-compatible (i.e. legacy code expecting 1 or 0 works just fine) yet easy to identify as a boolean (via is_dualvar).

        "I am inevitable." - Thanos
Re: What if Perl had an OO standard library?
by Anonymous Monk on Aug 23, 2022 at 12:23 UTC

      Corrina/Object::Pad is an object system. Venus is a fully OO standard library. While it's true that Venus has its own object system that’s just incidental.

      I do assume that once Corinna has seen mass adoption, there "may" be an effort mounted to use it to create a OO standard library. Who knows if and when that will happen?!

      While Corinna is trying to achieve mass adoption people will still need and use what's available now. For this reason, I don't see Venus as being in competition with Corinna.

      On the question (and potential future) of a Corinna-based standard library: (personally I feel) "A Venus-inspired Corinna-based standard library would be fine by me, so long as it's extendable (via inheritance and plugins), and makes core behaviors available to us as roles (traits) for use in our own downstream software."

      "I am inevitable." - Thanos
Re: What if Perl had an OO standard library? (perl5i)
by Anonymous Monk on Aug 26, 2022 at 18:34 UTC
Re: What if Perl had an OO standard library?
by AlexP (Pilgrim) on Aug 24, 2022 at 13:43 UTC

    Hello and thank you!
    I have a positive attitude towards any serious work that makes PERL richer and more convenient. We are lack of big and useful MODERN projects here. So please don't stop.
    As for me, I see several areas where Venus can be very handy and will use it.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://11146308]
Approved by marto
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2024-04-19 12:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found