Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Consistency, syntax, and little minds

by belg4mit (Prior)
on Oct 02, 2002 at 18:55 UTC ( [id://202352]=perlmeditation: print w/replies, xml ) Need Help??

I've had an idea rattling around in my head for awhile now, and thought I'd run it up the flag pole to see who salutes. The gist of it is this, in the spirit of anything the core can do the user can to, syntax for many functions should be tweaked. Instead of push @foo, 'bar' the syntax would be push \@foo, 'bar'; Afterall, this is what user defined code must do. One could go the other way and allow user-defined code to act as push etc. do now. However, I suggest that where an array or hash is to be modified a reference should be passed. In this manner, any unescaped hash or array in code could be read as an in place expansion of that variable; removing ambiguity and making the code easier to understand for beginners. This also has the advantage of rendering syntax such as push @{ $arrayref }, 'scalar'; unnecessary. This is purely hypothetical as I realize this is a rather major change and unlikely to happen. What do you think?

PS> On a seperate but related note, things like keys might then be reasonably expected to except a hash or hash reference; which IMHO would be most useful.

--
perl -wpe "s/\b;([mnst])/'$1/g"

Replies are listed 'Best First'.
Re: Consistency, syntax, and little minds
by Felonious (Chaplain) on Oct 02, 2002 at 19:06 UTC
    One could go the other way and allow user-defined code to act as push etc. do now.

    Prototypes can do exactly that.
    From perlsub:
    sub mypush (\@@)

    [TINPC@perlcabal.com shh]$ su real
      True enough, and I should know that, however I eschew prototypes. That however, does not allow push itself to take a reference. Which was my point, as I gave reasons why I believe such a route would be superior to this method (of allowing subs the same abailities as CORE).

      --
      perl -wpe "s/\b;([mnst])/'$1/g"

Re: Consistency, syntax, and little minds
by chromatic (Archbishop) on Oct 02, 2002 at 20:34 UTC
    I suggest that where an array or hash is to be modified a reference should be passed.
    my @foo = (1, 2, 3); \@foo = (1, 2, 3); # ? \@foo = [ 1, 2, 3 ]; # ??

    Too much "consistency", I fear.

      What? No, not at all. Neither of your "?" constructs would exist. In both those cases you are defining the list, and in neither case is a function being called to act upon a named list.

      --
      perl -wpe "s/\b;([mnst])/'$1/g"

        Ahh, I see. You and I mean different things by the word defining. I use it as a synonym for "declaring", while you are using it as a synonym for "assigning to".

        I also disagree that there's no modification of an array happening. @foo is indeed a name, and the data structure to which it refers is indeed being modified.

        Regardless, you're still trying to solve the problem for which prototypes already exist. If you don't like them, that's fine, but you might as well argue that all instances of push can be replaced by:

        @foo = (@foo, 'extra element');

        Proposing a backwards-incompatible modification to the core of Perl to remove a parser exception intended to make everyone's life a little easier for the sake of more explicit knowing what-goes-on-under-the-covers-consistency is, in my opinion, a mistake. Doubly so since you have access to a mechanism which gives you nearly the same power.

        Update: It also occurs to me that it's inconsistent to say that in-place use of an aggregate automatically expands. How would one explain that "This single name refers to a bunch of things, but it's always a bunch of things in an uncollected sense when it's referred to with the name, but when it's referred to with the name and another token, it's the collected bunch of things."

Re: Consistency, syntax, and little minds
by jepri (Parson) on Oct 02, 2002 at 22:29 UTC
    IIRC Perl6 does this. Or maybe that was some other language I was looking at recently. Certainly it's a good idea - what else could a programmer have meant if he passes a reference to an array?

    It's just one of those things in Perl5 that could and should be tweaked, like the 'No comma after filehandle in print statement' error. If perl can detect the problem, why can't it do what I want? (The answer, of course, is that I haven't gotten off my arse and patched perl).

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

      Well I guess I didn't want to bring it up but the lines between parentheses and square brackets are being seriously blurred in perl6. Read this longish thread for the full scoop. It's still waiting for a ruling from Larry but in general lists treated as scalars return array references and array references treated as lists dereference themselves.

      http://www.perl.com/pub/a/2002/09/p6pdigest/20020929.html?page=2

      __SIG__
      printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE

Re: Consistency, syntax, and runtime optree mangling
by diotalevi (Canon) on Oct 03, 2002 at 12:59 UTC

    This is my first crack at hacking the opcode tree at compile time but the general idea is to dereference any array references given to push() as the first argument. This doesn't address forms like push(.., ..), push(\@a, ..) or really anything beyond retrieving the array reference from a global or lexical value. I was following the lead from the perl.com article http://www.perl.com/pub/a/2002/05/07/optree.html. Right now the code just exits and I'm sure that I'm doing things incorrectly (I just picked '0' as an arbitrary value for the new rv2av opcode) but don't have the expertise to get further. I'm sharing the code so you can at least see that in perl 5.8 you can have whatever you want as long as you're willing to get your hands dirty.

    #!/usr/local/bin/perl CHECK { require B::Generate; use B::Utils qw(opgrep walkallops_filtered); walkallops_filtered ( sub { opgrep( { name => 'push', first => { sibling => { name => [ 'padsv', 'g +vsv' ] } } }, $_[0] ) }, sub { my $kid0 = $_[0]->first; my $ref = $kid0->sibling; my $val = $ref->sibling; my $rv2av = B::UNOP->new( 'rv2av', 0, $ref ); $kid0->sibling( $rv2av ); $rv2av->sibling( $val ); $ref->sibling( undef ); $rv2av->first( $ref ); $kid0->next( $ref ); $ref->next( $rv2av ); $rv2av->next( $val ); } ); } my @a = 1; my $a = \@a; push @{$a}, 2; push $a, 4; # alter this to do @$a print join(', ',@a) . "\n";

    No modifications: This is the original opcode tree that is generated with no modifications

    $ /usr/local/bin/perl -MO=Concise over.pl
    Type of arg 1 to push must be array (not private variable) at over.pl line 31, near "4;"
    over.pl had compilation errors.
    1aq <@> leave@a:128,131 KP/REFC ->(end)
    19s    <0> enter ->19t
    19t    <;> nextstate(main 128 over.pl:28) ->19u
    19y    <2> aassignt2 KS ->19z
    -        <1> ex-list lK ->19w
    19u          <0> pushmark s ->19v
    19v          <$> const(IV 1)t10 s ->19w
    -        <1> ex-list lK ->19y
    19w          <0> pushmark s ->19x
    19x          <0> padav@a:128,131 lRM*/LVINTRO ->19y
    19z    <;> nextstate(main 129 over.pl:29) ->1a0
    1a4    <2> sassign sKS/2 ->1a5
    1a2       <1> refgen sK/1 ->1a3
    -           <1> ex-list lKRM ->1a2
    1a0             <0> pushmark sRM ->1a1
    1a1             <0> padav@a:128,131 lRM ->1a2
    1a3       <0> padsv$a:129,131 sRM*/LVINTRO ->1a4
    1a5    <;> nextstate(main 131 over.pl:30) ->1a6
    
    ----> this is the push @$a, 2 line
    1aa    <@> pusht5 sK/2 ->1ab
    1a6       <0> pushmark s ->1a7
    1a8       <1> rv2avt4 lKRM/1 ->1a9
    -           <@> scope sK ->1a8
    -              <0> ex-nextstate v ->1a7
    1a7             <0> padsv$a:129,131 sM/32 ->1a8
    1a9       <$> const(IV 2)t11 s ->1aa
    
    
    1ab    <;> nextstate(main 131 over.pl:31) ->1ac
    
    
    ----> this is the push $a, 2 line. Here you see
    the raw lexical being passed to push().
    1af    <@> pusht6 K/2 ->1ag
    1ac       <0> pushmark s ->1ad
    1ad       <0> padsv$a:129,131 ->1ae
    1ae       <$> const(IV 4)t12 s ->1af
    
    
    1ag    <;> nextstate(main 131 over.pl:32) ->1ah
    1ap    <@> print K ->1aq
    1ah       <0> pushmark ->1ai
    1ao       <2> concatt9 K/2 ->1ap
    1al          <@> joint7 K/2 ->1am
    1ai             <0> pushmark ->1aj
    1aj             <$> const(PV ", ")t13 ->1ak
    1ak             <0> padav@a:128,131 ->1al
    1an          <@> stringifyt8 K/1 ->1ao
    -              <0> ex-pushmark ->1am
    1am             <$> const(PV "\n")t14 ->1an
    

    Modified opcode tree: Here I've attempted to instert a rv2av and thread execution through it. I'm not sure why that rv2av is now the end point but that's my own ignorance peeking.

    $ /usr/local/bin/perl -MO=Concise over.pl
    Type of arg 1 to push must be array (not private variable) at over.pl line 30, near "4;"
    over.pl had compilation errors.
    1an <@> leave@a:128,131 KP/REFC ->(end)
    19p    <0> enter ->19q
    19q    <;> nextstate(main 128 over.pl:27) ->19r
    19v    <2> aassignt2 KS ->19w
    -        <1> ex-list lK ->19t
    19r          <0> pushmark s ->19s
    19s          <$> const(IV 1)t10 s ->19t
    -        <1> ex-list lK ->19v
    19t          <0> pushmark s ->19u
    19u          <0> padav@a:128,131 lRM*/LVINTRO ->19v
    19w    <;> nextstate(main 129 over.pl:28) ->19x
    1a1    <2> sassign sKS/2 ->1a2
    19z       <1> refgen sK/1 ->1a0
    -           <1> ex-list lKRM ->19z
    19x             <0> pushmark sRM ->19y
    19y             <0> padav@a:128,131 lRM ->19z
    1a0       <0> padsv$a:129,131 sRM*/LVINTRO ->1a1
    1a2    <;> nextstate(main 131 over.pl:29) ->1a3
    
    
    ----> Again, this is the push @$a, 2 line.
    1a7    <@> pusht5 sK/2 ->1a8
    1a3       <0> pushmark s ->1a4
    1a5       <1> rv2avt4 lKRM/1 ->1a6
    -           <@> scope sK ->1a5
    -              <0> ex-nextstate v ->1a4
    1a4             <0> padsv$a:129,131 sM/32 ->1a5
    1a6       <$> const(IV 2)t11 s ->1a7
    
    
    1a8    <;> nextstate(main 131 over.pl:30) ->1a9
    
    -----> and this is what that CHECK{} block was tying up in knots.
    1ac    <@> pusht6 K/2 ->1ad
    1a9       <0> pushmark s ->1aa
    -        <1> rv2avt15 K/1 ->1ab
    1aa          <0> padsv$a:129,131 ->-
    1ab       <$> const(IV 4)t12 s ->1ac
    
    
    1ad    <;> nextstate(main 131 over.pl:31) ->1ae
    1am    <@> print K ->1an
    1ae       <0> pushmark ->1af
    1al       <2> concatt9 K/2 ->1am
    1ai          <@> joint7 K/2 ->1aj
    1af             <0> pushmark ->1ag
    1ag             <$> const(PV ", ")t13 ->1ah
    1ah             <0> padav@a:128,131 ->1ai
    1ak          <@> stringifyt8 K/1 ->1al
    -              <0> ex-pushmark ->1aj
    1aj             <$> const(PV "\n")t14 ->1ak
    $
    

    __SIG__
    printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE

Re: Consistency, syntax, and little minds
by japhy (Canon) on Oct 03, 2002 at 00:23 UTC
    Well, that's why we should have methods of data types, not functions. (See Ruby.)

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker, who'd like a job (NYC-area)
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Consistency, syntax, and little minds
by shotgunefx (Parson) on Oct 03, 2002 at 01:41 UTC
    Just FYI, in 5.8 a new prototype is available.
    sub pushit(\[$@%&]) { # All args are passed as refs. }


    -Lee

    "To be civilized is to deny one's nature."
Re: Consistency, syntax, and little minds
by BUU (Prior) on Oct 02, 2002 at 23:57 UTC
    I see a problem here, namely that it could lead into a situation where i do my $foo=\@_; print $foo; and it prints @_. I would consider that a Bad Thing, as it blurs the line between references and actual data structures even more so then it already is. If i do "print $foo", i expect to see "ARRAY(0x97ca44)", thus telling me its an array ref. (Ok, i could use ref to do the same thing.. but this is perl. Must be more then one way. If i want to expand the ref, i'll bloody well dereference it.
      Nope, not at all. This is the same "mistake" others have made in misinterpreting my idea. This problem would not exist.

      --
      perl -wpe "s/\b;([mnst])/'$1/g"

Re: Consistency, syntax, and little minds
by Abigail-II (Bishop) on Oct 04, 2002 at 14:34 UTC
    However, I suggest that where an array or hash is to be modified a reference should be passed. In this manner, any unescaped hash or array in code could be read as an in place expansion of that variable; removing ambiguity and making the code easier to understand for beginners.
    There is already a language addressing the sentiments expressed above. It's called Python.

    Abigail

      Maybe. However my point was not to create a language to solve a "problem" (and this certainly is not a "problem" in the sense of one which a language would be created to be solve), but a "problem" with the language. I simply wished to see what others thought of the matter, and whether the reasoning was sound. Not to be pointed at Ruby/Python/Flavor-of-the-month, as a means of sidestepping the issue.

      --
      perl -wpe "s/\b;([mnst])/'$1/g"

        I wasn't side stepping any issue. I was just pointing to a language that was created not to have "problem"s as the one you described regarding push. Python has a much more regular syntax than Perl - and that's what you like push to have.

        I don't think the syntax of push is a problem, not at all. By being non-regular, it's easier to program, and to learn. One doesn't have to know references to be able to use push.

        Abigail

Re: Consistency, syntax, and little minds
by Hercynium (Hermit) on Jan 30, 2013 at 16:39 UTC

    Wow, talk about a time warp! (it's just a jump to the left)

    I ran across this thread looking for examples of the use of B::Generate (see diotalevi's post, below), for some enlightenment of my own.

    When I read through the rest of the thread, I had a little chuckle realizing that few of the other commenters seem to have understood what you were asking for all those years ago - and it seems that none really saw the utility and advantage of it! Well, fast forward 9+ years but your idea is now in core, (more or less, unless I failed to understand it as well :), as of perl 5.14!

    Recently I have been able to code on perl 5.14 and I find myself using this feature more and more often. I like that it adds a carefully-considered bit of DWIM in a places where I once added a lot of syntax that always felt tedious and distracting. I myself have wished explicit deref for push/keys/shift/etc. was unnecessary - and now it is! In the code where I am using this feature, other people working on or reviewing that code have expressed that they like the feature quite a bit.

    More info here: http://perldoc.perl.org/perl5140delta.html#Syntactical-Enhancements
    Original Patch and rationale from David Golden (xdg++) here: http://code.activestate.com/lists/perl5-porters/157092/
      I was looking forward to this feature too, but when 5.14 was released the docs had this to say e.g. from push:
      Starting with Perl 5.14, push can take a scalar EXPR, which must hold a reference to an unblessed array. The argument will be dereferenced automatically. This aspect of push is considered highly experimental. The exact behaviour may change in a future version of Perl.
      ... which has discouraged me from using it :(

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (4)
As of 2024-04-25 05:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found