Having some problems with Perl debugger in Eclipse and PadWalker. Only used it for simple one-file scripts before. Variables declared using "my". They appear fine in the debugger "variables" window.
Now I am using someone else's more complicated script and I don't see the variables declared using "our". To investigate, I boiled it down to one very simple example
junk.pl:
use strict;
use warnings;
require 'junk2.pl';
package Junk;
my $simon = "SOMETHING";
print "JUNK " . $Junk2::james . "\n";
print "JUNK " . $simon . "\n";
junk2.pl:
package Junk2;
our $james;
$james = "FOO";
1;
Stepping through the code, the vairable my $simon displays in the debugger window fine but variable our $james does not. The debugger is working OK: the program runs and the output window shows the correct output... it's just the variables window that fails to show $james.
The screen shot below demonstrates the problem. As you can see the variable $james from the Junk2 package prints ok, but does not appear in the variables display.
Been searching a while for a solution but can't find anything that matches well... any ideas?
EDIT: Have found out that I can "see" the package variables if I use the Perl debugger:
.
Is there a way to have the same output in a friendly manner in the IDE like padwalker shows?
Thank you to guys who have answered so far :)
You can toggle viewing local and global variables under the variables view menu. Variables declared with our are outside of the local scope, and are therefore visible when the global variables option is selected. (I am running eclipse 4.2.1)
To access the variables view menu click the small down arrow on the top right of the variables pane.
Variables declared with our are lexical variables, aliased to package variables (thank you #ikegami for the correction):
our makes a lexical alias to a package variable of the same name in the current package for use within the current lexical scope.
brian d foy has a recent post discussing symbol tables.
The short answer is, you access package variables by looking at the package's symbol table.
In addition, PadWalker has a peek_our method. Package::Stash provides other useful helpers.
In the Eclipse Debug Configuration at -X to the Perl command line to show current package variables.
Edit:
In this case you might need to use the -V command instead.
See http://perldoc.perl.org/perldebug.html
Edit:
It would probably be easier to just assign the Junk2::James variable to local variable.
my $james = $Junk2::james;
Related
Here is my system configuration.
Perl-Epic 0.7.8
Strawberry Perl 5.32.1 64 bit.
PadWalker 2.5 installed with Strawberry perl
Here is what I have already read.
http://www.epic-ide.org/faq.php#debug
In my case, the message "perl5db.pl did not return a true value." is not displayed in the console. Also the bug report mentioned in that FAQ has been resolved so I would think that things should be working on the latest windows version of Perl by now. Also that issue appears to be related to a win32 specific subroutine that doesn't exist in my perl installation since it is a win64 install.
https://sourceforge.net/p/e-p-i-c/bugs/711/
This might be related, but not sure. My program which only involves two variables follows.
Unable to view locals in Eclipse + EPIC
I do tried the latest stable and testing versions of EPIC. Both produced the same result.
Here is a simple test program.
#!/usr/bin/perl
$a = 1;
$b=2;
print($a+$b);
[
Update
If I declare the variables explicitly then they show in the debugger. Within one of the other threads I noticed that the asker did not declare using the my keyword either. That is an opportunity for someone to answer with a confirmation of whether this is how PadWalker works. The documentation for it mentions that it works on lexical variables which are in scope. I'm new to Perl programming and learning it due to scripts that I have to learn to maintain so I am unsure if my interpretation of the documentation is correct. However, I think that is the answer that the variables must be declared so that each has a scope. Please advise.
The answer appears to lie in the module documentation for PadWalker which states, "PadWalker is a module which allows you to inspect (and even change!) lexical variables in any subroutine which called you. It will only show those variables which are in scope at the point of the call." The key point is that declaring the variable with the my keyword is what causes the variable to be declared with scope.
Moreover, the PERL-EPIC documentation for Eclipse indicates that it relies on PadWalker to provide a debug capability. Therefore the ability to inspect variables in the Eclipse debugger using that specific plugin depends on explicitly declaring variables.
You can see in the image here that the variables show up when declared.
Background
The perl command has several idiot-proofing command line options described in perldoc perlrun:
-c causes Perl to check the syntax of the program and then exit without executing it.
-w prints warnings about dubious constructs, such as variable names that are mentioned only once and scalar variables that are used before being set, etc.
-T forces "taint" checks to be turned on so you can test them.
After reading through these options, I could not find one that detects undefined functions. For example, I had a function I used called NFD() that imports the Unicode::Normalize package. However, being a perl novice, I did not know if this was already under the fold of the standard perl library or not. And perl -c nor any of the other options uncovered this error for me, rather a coworker noticed that it was somehow undefined (and not inside the standard libraries). Therefore, I was curious about the following:
Question
Is there an option in the perl command to automatically detect if there is an undefined function not already inside an imported package?
I did not know if this was already under the fold of the standard perl library or not.
It sounds like you want to distinguish imported subs from other subs and builtin functions.
If you always list your imports explicitly instead of accepting the defaults like I do, then you'll not only know which subs are imported, you'll know from which module they were imported.
use Foo::Bar; # Default imports
use Foo::Bar qw( ); # Import nothing ("()" also works)
use Foo::Bar qw( foo bar ); # Import subs foo and bar.
Is there an option in the perl command to check for undefined functions?
On the other hand, if you are trying to identify the subs that you call that don't exist or that aren't defined at compile time, then this question is a duplicate of How can I smoke out undefined subroutines?.
Aside from the particular technical details, you can't know if a function will be defined at some time in the future when you plan to use it. As a dynamic language, thinks come into and go out of existence, and even change their definitions, while the programming is running.
Jeffrey Kegler wrote Perl Cannot Be Parsed: A Formal Proof that relied on this idea. The details of the halting problem aren't as interesting as workings of a dynamic language.
And, for what it's worth, those command-line options don't make programs idiot-proof. For example, in Mastering Perl I show that merely adding -T to a program doesn't magically make it secure, as many would have you believe.
What were you doing with Unicode::Normalize? It has an NFD already but your question makes it sound like you were wrapping it somehow:
use Unicode::Normalize qw(NFD);
Hello I would like to master VIM as my primary IDE. I know there are many plugins etc. but I have one question: Is possible for VIM to understand the particular language (in case I wont plugin for my language) in which code is written? I mean some rules that I can define and then use e.g. for auto-completion, refactoring, folding etc. For example consider following two perl codes in which I want refactor variables. In first example there are variables with same names but one is scalar and another are array and hash, in second example same name of variable as was defined before was used in another scope (loop etc.). Thus refactoring using simple text matching is not elegant way I thing:
1st example:
my #same_name;
my $same_name; # How to refactor this variable without affecting all other variables?
my %same_name;
$same_name[0] = 5;
$same_name{"key"} = 5;
$same_name = 5;
2nd example:
my #array;
my $already_existing_variable; # How to refactor this variable
foreach my $already_existing_variable (#array){
print $already_existing_variable; # Without affecting this variable
}
print $already_existing_variable; # Variable that should be also refactorized
Or how can I achieve that when I type $arr {and hit TAB here} it will automatically extend to $array[ ? For this VIM must to know that when I prepend $ before variable which was declared with # I want to access array elements.
Another example would be: how to fold code using e.g. BEGIN and END keywords? Those was jut trivial examples but I think you get the point. I think it is similar task to write own compiler or something. Thank you.
I'm using vim with my perl scripts almost all days:
Rename variables
App::EditorTools gives you the function to rename variables like Padre.
install App::EditorTool $ cpanm App::EditorTools
install vim plugin $ editortools install-vim
move cursor on the variable name in vim.
type \pL
I'm not sure why it parses wrong scope in the 2nd example, but you can temporarily wrap the foreach brock with lambda and rename variables inside the code block first.
sub {
foreach my $already_existing_variable (#array){
print $already_existing_variable; # Without affecting this variable
}
}->();
Reformat script indent
Perl::Tidy has perltidy command line tool to format your script.
install Perl::Tidy $ cpanm Perl::Tidy
create ~/.perltidyrc according to your taste. like folowing:
-pbp
-pt=2
-sbt=2
-bt=2
-bbt=2
-ce
-nbbc
set equalprg to perltidy in your ~/.vimrc
au FileType perl setl ep=perltidy
type gg=G in your script.
Syntax Check
vim's built-in compiler plugin for perl does very well.
set :compilerto perl in your ~/.vimrc
au FileType perl :compiler perl
type :make in normal mode
type :copen to open up quickfix window
if you don't want warnings in your quickfix list, you can unset the flag for it.
let g:perl_compiler_force_warnings = 0
$PERL5LIB is also important while invoking :make, you can give specific directories in it.
let &l:path = './lib,./blib/lib,./blib/arch,' . &l:path
let $PERL5LIB = substitute(&l:path, ',', ':', 'g')
Completions
vim has nice completion tool out of the box. see :help comple-generic
type $ar in insert mode and press CTRL-N
You might be interested in ctags too.
I can already tell something is wrong when the first sentence is "Hello I would like to master VIM as my primary IDE."
Vim is not an IDE. Vim is a text editor. (You can use google to find out more)
If you feel that the features an IDE provides (refactoring, smarter auto-completion...) are more important than the features that vim provides (fast movement, never take your hands off the home row, programmable editor...) then you should use an IDE, or an IDE with a vim plugin. Usually, if you want to mix IDE features with vim features, you do it with a plugin to the IDE, not the other way around (there are some exceptions such as eclim).
I need to import all our variables from the unnamed Perl module (Module.pm) and use them inside the Perl script (Script.pl).
The following code works well without the "use strict", but failed with it. How can I change this code to work with "use strict" without the manual listing of all imported variables (as described in the answer to other question)?
Thanks a lot for your help!
Script.pl:
use strict;
require Module;
print $Var1;
Module.pm:
our $Var1 = "1\n";
...
our $VarN = "N\n";
return 1;
Run the script:
$> perl Script.pl
Errors:
Global symbol "$Var1" requires explicit package name at Script.pl line 3.
Execution of Script.pl aborted due to compilation errors.
NOTE (1): The module is unnamed, so using a Module:: prefix is not the option.
NOTE (2): Module.pm contains also a set of functions configured by global variables.
NOTE (3): Variables are different and should NOT be stored in one array.
NOTE (4): Design is NOT good, but the question is not about the design. It's about forcing of the listed code to work with minimal modifications with the complexity O(1), i.e. a few lines of code that don't depend on the N.
Solution Candidate (ACCEPTED): Add $:: before all imported variables. It's compliant with strict and also allows to differ my variables from imported in the code.
Change your script to:
use strict;
require Module;
print $Module::Var1;
The problem is the $Var1 isn't in the main namespace, it's in Module's namespace.
Edit: As is pointed out in comments below, you haven't named your module (i.e. it doesn't say package Module; at the top). Because of this, there is no Module namespace. Changing your script to:
use strict;
require Module;
print $main::Var1;
...allows the script to correctly print out 1\n.
If you have to import all the our variables in every module, there's something seriously wrong with your design. I suggest that you redesign your program to separate the elements so there is a minimum of cross-talk between them. This is called decoupling.
You want to export all variables from a module, and you want to do it in such a way that you don't even know what you're exporting? Forget about use strict and use warnings because if you put them in your program, they'll just run screaming out, and curl up in a corner weeping hysterically.
I never, and I don't mean hardly ever, never export variables. I always create a method to pull out the required value. It gives me vital control over what I'm exposing to the outside world and it keeps the user's namespace pure.
Let's look at the possible problems with your idea.
You have no idea what is being exported in your module. How is the program that uses that module going to know what to use? Somewhere, you have to document that the variable $foo and #bar are available for use. If you have to do that, why not simply play it safe?
You have the issue of someone changing the module, and suddenly a new variable is being exported into the program using that module. Imagine if that variable was already in use. The program suddenly has a bug, and you'll never be able to figure it out.
You are exporting a variable in your module, and the developer decides to modify that variable, or even removes it from the program. Again, because you have no idea what is being imported or exported, there's no way of knowing why a bug suddenly appeared in the program.
As I mentioned, you have to know somewhere what is being used in your module that the program can use, so you have to document it anyway. If you're going to insist on importing variables, at least use the EXPORT_OK array and the Exporter module. That will help limit the damage. This way, your program can declare what variables its depending upon and your module can declare what variables it knows programs might be using. If I am modifying the module, I would be extra careful of any variable I see I am exporting. And, if you must specify in your program what variables you're importing, you know to be cautious about those particular variables.
Otherwise, why bother with modules? Why not simply go back to Perl 3.0 and use require instead of use and forget about using the package statement.
It sounds like you have data in a file and are trying to load that data into your program.
As it is now, the our declarations in the module only declare variables for the scope of that file. Once the file finshes running, to access the variables, you need to use their fully qualified name. If your module has a package xyz; line, then the fully qualified name is $xzy::Var1. If there is no package declaration, then the default package main is used, giving your variables the name $main::Var1
However, any time that you are making many variables all with numeric name changes, you probably should be using an array.
Change your module to something like:
#My::Module::Data = ("1\n", "2\n" ... )
and then access the items by index:
$My::Module::Data[1]
This appears in the Eclipse text editor the first time EPIC encounters use of the special %ENV variable in a Perl script.
I'm not running anything in this environment, I just want the warning to go away.
I fiddled around in the "run configurations" section, but that didn't seem to help.
UPDATE 1: All these answers are about changing the code, which should not be necessary. Yes, I can get the same error to happen on the command line if I un-set the environment variable. But I want to define the environment variable in Eclipse, to match the normal command line environment, so that the warning does not happen. I've tried defining it in the Eclipse 'Run configuration', but it doesn't seem to take effect.
I also tried setting the variable in ~/.bashrc and related places, and creating a startup script for Eclipse that sets the variable. None of that fixed the warning.
I can make the warning disappear by right-clicking and selecting 'Source' and then 'Clear All EPIC Markers', but the warning appears again the next time the file is changed.
UPDATE 2: If I define the environment variables in the Run Configuration, and then run the script, it gets past those lines okay. However, there is still a squiggly red underline and a warning displayed in the text editor pane while I'm editing -- it's that warning I want to get rid of.
This happens in any other context, too, when warnings are enabled and you try to use an undefined value.
$ perl -we 'print $ENV{NOT_DEFINED}'
Use of uninitialized value in print at -e line 1.
Some solutions are
(1) to define the variable before you use it
$ perl -we '$ENV{NOT_DEFINED} //= ""; print $ENV{NOT_DEFINED}'
(2) use || or // operators to substitute a "default" value for your variable
$ perl -we 'print $ENV{NOT_DEFINED} // ""'
(3) disable the specific warnings
$ perl -we 'no warnings "uninitialized"; print $ENV{NOT_DEFINED}'
(4) disable all warnings
$ perl -we 'no warnings; print $ENV{NOT_DEFINED}'
(don't do #4).
Since this is Perl, there are several more ways to do it.
In Perl <= v5.8, you have to use || and ||= instead of // and //=, which has some subtly different behavior.
Define the environment variable before startup or fix the code so that it doesn't emit the warning. You might get more useful suggestions if you included the entire warning so that the reader would know where the it's coming from.
Actually I believe this is not currently possible, see this feature request and forum post
Not sure if this will help, but try adding:
our %ENV
...before the first use of %ENV.
[Edit: I am assuming that the relevant environment variable actually is defined, and this error is coming from the IDE. On second thought, perhaps this is a poor assumption.]