Among the various ways of declaring variables, will Perl 6 have a way to say, "this variable is highly temporary, and may be re-declared within the same scope, or in a nested scope without concern"? I often find myself doing:
my $sql = q{...}; ...do some DB stuff... my $sql = q{...}; ...do more DB stuff...
This of course results in re-defining $sql, so I take out the second "my", but then at some point I remove the first one, and strict chews me out over not declaring $sql, so I make it "my" again.
This is a cycle I've repeated with dozens of variations on more occasions than I care to (could?) count.
without problems. Of course, "throwawaytmpvar" is a bit long, but you get the idea.
It should probably be illegal to:
throwawaytmpvar $sql = q{...}; my $sql = q{...}; # Error: temporary became normal lexical
or for that matter even give it a new type:
throwawaytmpvar int $i = 0; throwawaytmpvar str $i = "oops"; # Error: redefinition of type
There might be other assumptions that this implies. For example, it might be considered always thread-private and might be required to be a core, unboxed type. These extra assumptions are only worth it if they enhance the optimization possibilities surrounding such a value.
-- Aaron Sherman <a...@ajs.com> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
On Fri, Apr 15, 2005 at 11:45:16AM -0400, Aaron Sherman wrote:
: Among the various ways of declaring variables, will Perl 6 have a way to : say, "this variable is highly temporary, and may be re-declared within : the same scope, or in a nested scope without concern"? I often find : myself doing: : : my $sql = q{...}; : ...do some DB stuff... : my $sql = q{...}; : ...do more DB stuff... : : This of course results in re-defining $sql, so I take out the second : "my", but then at some point I remove the first one, and strict chews me : out over not declaring $sql, so I make it "my" again. : : This is a cycle I've repeated with dozens of variations on more : occasions than I care to (could?) count.
And at that point, why not just change it to this?
my $sql; $sql = q{...}; ...do some DB stuff... $sql = q{...}; ...do more DB stuff...
It seems to me that assignment does a pretty good job of clobbering a variable's value without the need to redeclare the container. If you really want to program in a definitional paradigm that requires every new definition to have a declaration, then you ought to be giving different definitions different names, seems like, or putting each of them into its own scope. Or write yourself a macro. Or just turn off the redefinition warning...
It doesn't seem to rise to the level of a new keyword for me.
On Fri, Apr 15, 2005 at 06:04:32PM +0200, Juerd wrote:
: No, Ucfirst it can't be, I think. And ALLCAPS is ugly. @ is taken (and : ugly). Suggestions?
Maybe we could define an "ok" operator that suppresses only the *first* warning produced by its argument(s). Then if you get multiple warnings, you at least get some indication that you've overgeneralized, even if the "wrong" warning comes out. Or maybe it only suppresses the first warning till you get a second warning, and then it prints both.
> What I'd really like to say is: > throwawaytmpvar $sql = q{...}; > throwawaytmpvar $sql = q{...};
I like the idea and propose "a", aliased "an" for this.
> It should probably be illegal to: > throwawaytmpvar $sql = q{...}; > my $sql = q{...}; # Error: temporary became normal lexical > or for that matter even give it a new type: > throwawaytmpvar int $i = 0; > throwawaytmpvar str $i = "oops"; # Error: redefinition of type
Giving it a new type should be valid. That is, I think the variable is more useful if the old one is thrown away and a new one is created. This can perhaps be optimized by re-using the same thing if it has no external references anymore.
In fact,
a Str $foo = $foo;
is a nice way to indicate that from now on, you don't care about its numeric value anymore.
All in all, I think a|an can just be my without warnings and then do what you want.
Hm. Funny idea just occurred to me. What if something in ALLCAPS, or better, just Ucfirst would disable all warnings for just that thing?
my $foo; say $foo; # warning about undef $foo Say $foo; # no warning
$closed_fh.print(Int($foo)); # just a warning about the closed fh
my $foo; # warning about new $foo masking first My $foo; # no warning
If you think this looks much like PHP's @, you're right. It's not so bad an idea, actually. The problem with PHP is that everything's a warning and almost nothing actually dies.
No, Ucfirst it can't be, I think. And ALLCAPS is ugly. @ is taken (and ugly). Suggestions?
On Fri, Apr 15, 2005 at 09:17:13AM -0700, Larry Wall wrote: > On Fri, Apr 15, 2005 at 06:04:32PM +0200, Juerd wrote: > : No, Ucfirst it can't be, I think. And ALLCAPS is ugly. @ is taken (and > : ugly). Suggestions?
> Maybe we could define an "ok" operator that suppresses only the > *first* warning produced by its argument(s). Then if you get multiple > warnings, you at least get some indication that you've overgeneralized, > even if the "wrong" warning comes out. Or maybe it only suppresses > the first warning till you get a second warning, and then it prints both.
And after the third warning, it sends you to your room with no supper.
Larry Wall wrote: >On Fri, Apr 15, 2005 at 06:04:32PM +0200, Juerd wrote: >: No, Ucfirst it can't be, I think. And ALLCAPS is ugly. @ is taken (and >: ugly). Suggestions?
>Maybe we could define an "ok" operator that suppresses only the >*first* warning produced by its argument(s). Then if you get multiple >warnings, you at least get some indication that you've overgeneralized, >even if the "wrong" warning comes out. Or maybe it only suppresses >the first warning till you get a second warning, and then it prints both.
Wouldn't some form of trait make more sense:
my $sql = '...' is ok;
Only trick would be getting "is ok" to bind to the thing in the preceding expression that produces the warning the programmer was expecting. Certainly
{my $sql = '...'} is ok;
get the point across that warnings are somewhat ignorable for the block, but that starts getting to look a lot like
{my $sql = '...'} CATCH {default};
Except that one is run-time, the other compile-time.
So one could interpret this thread as a cry for a compile-time exception handler. I see some interesting uses for this in conjunction with C<eval>, but I doubt I'm seeing the whole story.
Aaron Sherman writes: > Among the various ways of declaring variables, will Perl 6 have a way to > say, "this variable is highly temporary, and may be re-declared within > the same scope, or in a nested scope without concern"? I often find > myself doing:
> my $sql = q{...}; > ...do some DB stuff... > my $sql = q{...}; > ...do more DB stuff...
There's a pretty common idiom for this:
{ my $sql = q{...}; # ... do some DB stuff ... } { my $sql = q{...}; # ... do more DB stuff ... }
On Fri, 2005-04-15 at 11:21 -0500, Patrick R. Michaud wrote: > On Fri, Apr 15, 2005 at 09:17:13AM -0700, Larry Wall wrote: > > Maybe we could define an "ok" operator that suppresses only the > > *first* warning produced by its argument(s). Then if you get multiple > > warnings, you at least get some indication that you've overgeneralized, > > even if the "wrong" warning comes out. Or maybe it only suppresses > > the first warning till you get a second warning, and then it prints both. > And after the third warning, it sends you to your room with no supper.
Talk about a strict permission system. If that's the case, I want a "I'm the human here, darnit!" option to bypass it.
Yes, moving things around breaks it, as does removing the first. There is no real dependency on the first $sql and it'd be great if declaration wouldn't add one.
On Fri, 2005-04-15 at 13:10, Luke Palmer wrote: > Aaron Sherman writes: > > Among the various ways of declaring variables, will Perl 6 have a way to > > say, "this variable is highly temporary, and may be re-declared within > > the same scope, or in a nested scope without concern"? I often find > > myself doing:
> > my $sql = q{...}; > > ...do some DB stuff... > > my $sql = q{...}; > > ...do more DB stuff...
> There's a pretty common idiom for this:
> { > my $sql = q{...}; > # ... do some DB stuff ... > } > { > my $sql = q{...}; > # ... do more DB stuff ... > }
> You see it in test suites all over the CPANdom.
You see it all over my code too... it is always possible to simulate many kinds of trickery that way. For example, if you want to write a loop with a counter that is visible one statement after the loop completes, you can say:
{ my int $i; loop $i=0;...;$i++ { ... } do_stuff($i); }
But isn't:
loop my int $i=0;...;$i++ { ...; LAST{do_stuff($i)} }
much cleaner? I think so, if for no other reason than it explicitly says what it means. That's one of the reasons that LAST is so handy.
So too would my mythical declarator would prevent a few steps that are otherwise quite easy, but cumbersome in the large.
Whatever, though. It was a simple suggestion, and seems to have sparked FAR more controversy than the small win warrants.
-- Aaron Sherman <a...@ajs.com> Senior Systems Engineer and Toolsmith "It's the sound of a satellite saying, 'get me down!'" -Shriekback
On Fri, 2005-04-15 at 18:04 +0200, Juerd wrote: > Aaron Sherman skribis 2005-04-15 11:45 (-0400): > > What I'd really like to say is: > > throwawaytmpvar $sql = q{...}; > > throwawaytmpvar $sql = q{...};
> I like the idea and propose "a", aliased "an" for this.
Too short. Having such a short identifier does two things:
* Robs that identifier from any future possible use * Creates incentive to use this over "my"
You want there to be a general tendency to use "my" first. If I were to choose a word, it would be "temp" (which I think already exists, though I forget what it does vs "my"), or "let" (to correspond with its use in rules).
> > It should probably be illegal to: > > throwawaytmpvar $sql = q{...}; > > my $sql = q{...}; # Error: temporary became normal lexical > > or for that matter even give it a new type: > > throwawaytmpvar int $i = 0; > > throwawaytmpvar str $i = "oops"; # Error: redefinition of type
> Giving it a new type should be valid. That is, I think the variable is > more useful if the old one is thrown away and a new one is created. This > can perhaps be optimized by re-using the same thing if it has no > external references anymore.
The reason I didn't want a new type to be valid was as an extra precaution against problematic boilerplating. It's a minor thing, and probably not that big a deal.
> On Fri, 2005-04-15 at 18:04 +0200, Juerd wrote: > > > throwawaytmpvar $sql = q{...}; > > > throwawaytmpvar $sql = q{...}; > > I like the idea and propose "a", aliased "an" for this. > Too short.
There is a rule of thumb, I don't know who came up with it, that says that the length of a variable name should be proportional to its scope. This works well, very well. The same principle can be applied to the declaring operator, and holds for my/our already.
The usual idiom for these throwaway variables is to use blocks. The reason to want a different way to write this, I thought was wanting to type less, especially because it's repeated throughout code.
> * Robs that identifier from any future possible use
That's with every identifier, and if the function it provides is good enough, this cannot be considered a problem, or we can no longer invent any new keyword that's both short and powerful.
> * Creates incentive to use this over "my"
This is true, and the reason I now prefer a warningless my to a/an. For this I like Larry's suggestion to use "ok", so you get "ok my $foo = ...;". Again, a short keyword, but its power warrants it, IMO.
Even if this does mean (and it does) we need something else for unit tests.
At least for the usage described in this thread, I don't see any need at all to add new syntax to Perl 6. The existing syntax provides for a much simpler solution yet, which also is in Perl 5.
This is the format of what I do to solve the same problem right now in my Locale::KeyedText test suite:
my ($sql, $foo, $bar);
$sql = q{...}; ...do some db stuff, also using $foo and $bar... $sql = q{...}; ...do some db stuff, also using $foo and $bar... $sql = q{...}; ...do some db stuff, also using $foo and $bar...
In other words, the simple solution is to declare the variable and use it on SEPARATE LINES! Then you can cut/copy/paste/reorder usage lines with impunity as you wanted.
Not only does this not require a new dubious language feature, but it also wins for brevity.
Keep it simple, as it is said.
Reserve any new syntax for when it is genuinely useful.