Re: Why do I get a "used only once" warning here?
by moritz (Cardinal) on Mar 13, 2009 at 12:06 UTC
|
I don't see why you should do anything else than no warnings "once"; in a small scope. It does what you want, and every reader of the code immediately know what you wanted to achieve. | [reply] [d/l] |
Re: Why do I get a "used only once" warning here?
by ikegami (Patriarch) on Mar 13, 2009 at 13:49 UTC
|
%MyApp::once if 0; # Suppress warning
| [reply] [d/l] |
|
Isn't there an error in this ?!
It neighter seems to suppress the warning, nor do I understand how this is supposed to work. :(
Thanks,
| [reply] |
|
>perl -wle"$MyApp::once{x} ||= 1;"
Name "MyApp::once" used only once: possible typo at -e line 1.
>perl -wle"%MyApp::once if 0; $MyApp::once{x} ||= 1;"
>
| [reply] [d/l] |
Re: Why do I get a "used only once" warning here?
by bellaire (Hermit) on Mar 13, 2009 at 12:04 UTC
|
Well, presumably you are storing keys in %MyApp because you intend to check them at some other point in your package. As soon as that check is in place, the warning will go away on its own. I'm not sure why you'd want to suppress the warning unless you are literally going to store a variable that you will never check or use, and then I'm not sure why you'd want to do that. So I guess the question is, why is it necessary for you to set the value but not check it? Or are you only wanting to suppress warnings until such time as you get around to adding the code to check the variable? | [reply] |
|
presumably you are storing keys in %MyApp because you intend to check them at some other point in your package.
Actually, I do check them, but not at another point in the package, but at the same. Note the usage of ||=.
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] [select] |
|
Ah, I missed the side-effect of the function, sorry. In fairness, Perl has no way of knowing (as I should have from the name of the function, "log") that your function has a side-effect. If this function were to simply return a value, then the warning would make sense, because you would be storing a value and never using it. With the side-effect, though, everything becomes clear.
If you really want that syntax, then you should turn warnings off as others have suggested. Alternatively, you could use a syntax which mentions the variable twice. I don't know if the fact that I missed the meaning of your code is indicative of unclear syntax, or if it's just me being blind this morning.
| [reply] |
|
|
|
Re: Why do I get a "used only once" warning here?
by JavaFan (Canon) on Mar 13, 2009 at 12:05 UTC
|
We don't have local statics in Perl,
What's wrong with state? Seems to me:
sub f {
state $once1 = log('some information') || 1;
}
will do.
As for the warning in your solution, that's the stuff no warnings is for. I don't get the point of not wanting to use it. | [reply] [d/l] |
|
Most people are still on Perl 5.8.x or earlier, and so do not have state available.
They do have statics through the horrible my $foo if 0; hack, but that is a bad way to do it.
You can also use my module Tie::Static, with the associated speed penalty that ties always have.
| [reply] [d/l] |
Re: Why do I get a "used only once" warning here?
by AnomalousMonk (Archbishop) on Mar 13, 2009 at 18:10 UTC
|
Clearly I can't use use vars nor our here.
I don't get this point. Why can't they be used? Either one seems to do the job without the need to turn off warnings, although with perhaps a bit more verbosity (but also less worry about proper scoping).
>perl -wMstrict -le
"package L;
use vars qw(%lone);
our %once;
sub l { return print __PACKAGE__, qq{: @_} }
package main;
print 'do some stuff in ', __PACKAGE__;
package L;
use vars qw(%singular);
our %onetime;
package main;
$L::once{x} ||= (L::l('hi from', __PACKAGE__), 1);
$L::lone{x} ||= (L::l('hello from', __PACKAGE__), 1);
$L::onetime{x} ||= (L::l('hiya from', __PACKAGE__), 1);
$L::singular{x} ||= (L::l('greets from', __PACKAGE__), 1);
$L::once{foo} ||= L::l('this should print');
$L::once{foo} ||= L::l('but this should NOT print!');
"
do some stuff in main
L: hi from main
L: hello from main
L: hiya from main
L: greets from main
L: this should print
Update: Replaced rather verbose example with much more succinct one. | [reply] [d/l] [select] |
|
Indeed, the way you wrote it, it would work. In my original design, the variable would be in a different package, so neither
use vars qw(%MyApp::once);
nor
our %MyApp::once;
would have worked, because package qualifications are not allowed in use vars and our; put actually I don't need to put once in its own package; I can simply have it in my current package, and this would make your solution indeed feasible.
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] [select] |
|
>perl -wMstrict -le
"package Some::Package;
our $scalar = 'foo';
package Some::Other::Package;
print $Some::Package::scalar;
print 'current package is ', eval { scalar caller };
"
foo
current package is Some::Other::Package
Update: Oops... Forgot to include example code.
| [reply] [d/l] [select] |
|
|
Re: Why do I get a "used only once" warning here?
by Porculus (Hermit) on Mar 13, 2009 at 23:44 UTC
|
sub f {
our $OnceOnly{+__LINE__} ||= (log(...),1);
}
which would, ISTM, be largely equivalent (and somewhat simpler), but with no risk of warnings? | [reply] [d/l] |
|
I was not aware that I can use 'our' this way inside a block, and to my surprise, no warning appears! Thanks for the suggestion!
UPDATE: I did not look closely enough. Your solution would not work, because
our $v{...}=...
is syntactically invalid. After all, you can only put the name of a variable after "our", not a hash element.
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] |
Re: Why do I get a "used only once" warning here?
by ig (Vicar) on Mar 13, 2009 at 19:58 UTC
|
package MyModule;
my %OneTime;
sub f {
$OneTime{+__FILE__.' '.__LINE__} ||= (print("logging\n"), 1);
return();
}
1;
| [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
package MyModule;
use strict;
use warnings;
sub f {
$MyApp::OneTime{+__FILE__.' '.__LINE__} ||= (print("logging\n"), 1
+);
return();
}
1;
| [reply] [d/l] |
|
$MyApp::once{+__LINE__} ....
and so the + stayed there and when posting my problem, I copied it without much thinking. If you have only __LINE__ as key, the + is needed because __LINE__ is a bareword.
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] |
Re: Why do I get a "used only once" warning here?
by repellent (Priest) on Mar 15, 2009 at 04:05 UTC
|
You seem to be spreading functionality that can be contained within the logging function. Why not:
use warning;
use strict;
{
my %log_seen;
sub log_info {
# do not continue if done before
return if $log_seen{(caller(1))[3]}++;
warn(@_, "\n");
}
}
sub f {
log_info('some information');
print "called f()\n";
}
f();
f();
__END__
some information
called f()
called f()
| [reply] [d/l] |
|
The reason why I haven't put it into the log package is that this "log once" logic is supposed to be done only for a few selected logs. If I put it into the log package, I would have to write a new logging function, say log_once. Actually this is a serious alternative and I was thinking to do it, but when I started to implement this feature, I thought it would be easily possible too to have this logic implemented without changing/extending the logging package, then was trapped by the unexpected warning, and then my curiosity took over....
--
Ronald Fischer <ynnor@mm.st>
| [reply] [d/l] |
|
Understood - you have to weigh the pros and cons of a log_once(). Just some thoughts:
If you had a logging package that expected all other functions to be logged, except for a select few, and then for the select few you sprinkle some state variables around, doesn't that introduce some action-at-a-distance & maintenance difficulties in the far future?
Granted, if there was just one or two state variables around, it would just be easy to remember, but wouldn't it also be that much harder to locate later?
| [reply] [d/l] |
|
Re: Why do I get a "used only once" warning here?
by sundialsvc4 (Abbot) on Mar 16, 2009 at 16:36 UTC
|
How interesting... I had never encountered the phrase "XY problem" before. (Well, except in reference to the inhabitants of Venus and Mars ...) ;-) | |