Debugging Question

Hey Guys!

Nice too meet you all! I just finished the debugging section but I’m having a difficult understanding the use of the “trick” __FILE__==$PROGRAM_NAME.
My question is What exactly does it do and Whats its significance?

The description was a little vague some elaboration would be nice :slight_smile:

Hello Julian,

Not sure I’m able to explain this “Trick”

But, I’m going to try my best to explain it my way of understanding the trick.

#In bash:

indent preformatted text by 4 spaces
if you haven't run any bash file, and just open the terminal and type "echo $0"
--> -bash # which tells us that you haven't run any bash shell script
 However, if you run a bash script file, $0 will change to the file name that is being executed.

#In Java (main method):

  Hello.java
  public Hello{
      public static void main(String[] args){ ...}
   }

args is an array of strings which contains the arguments from the command line

For example:
In the terminal:

 javac Hello.java # --> Hello.class
 java Hello name1 name2 other

Then, args[0] = “name1”, args[1] = “name2”, args[2] = “other”

In Python:

#hello.py
 print "hello world"

In the terminal, run python in interactive mode:

python -i hello.py
>>> import sys
>>> sys.argv[0]
>>> 'hello.py'

So argv[0] here is the file name “hello.py”

#In Ruby:

From ruby doc $0, and FILE

 " 
 $0
 Contains the name of the script being executed. May be assignable.
 "
  __FILE__ is the magic variable that contains the name of the current file. $0 is the name of the file used to start         
the program. This check says “If this is the main file being used…” This allows a file to be used as a library, and 
not to execute code in that context, but if the file is being used as an executable, then execute that code.

In ruby, $PROGRAM_NAME and $0 are the same variable, they’re global variables.

  • $PROGRAM_NAME or $0 is the name of file that is being executed.
  • FILE_ is the name of the current file or program (source file, library, debugger)

Example:

# hello.rb
def hello
   puts "Hello World"    
end

if __FILE__ == $PROGRAM_NAME
   hello
end

In the terminal:

run “ruby hello.rb”

indent preformatted text by 4 spaces
 >>> ruby hello.rb
 >>> Hello World

In this case FILE is the same as $PROGRAM_NAME (which is true) , then your program will executed the block that is between “if FILE__ == $PROGRAM_NAME” and “end”, it prints “Hello World”

Different case:

# hello.rb
require 'byebug'
def hello
   puts "Hello World"    
end

if __FILE__ == $PROGRAM_NAME
   byebug
   hello
end

in the terminal, run “ruby hello.rb” , you will be in the debugging mode “byebug”

 ***** We are in the debugging mode *****
 >>> __FILE__
 >>>  "(byebug)"
 
 >>> $0
 >>> "hello.rb"

 >>> $PROGRAM_NAME
 >>> "hello.rb"

 >>> $PROGRAM_NAME  == $0
 >>> true

 >>> $PROGRAM_NAME == __FILE__
 >>> false

In this case, $PROGRAM_NAME == FILE_ is false because the current source/program we are running is byebug( FILE_ ). So, we’re in the debugging mode “byebug”, it allows us to execute “hello.rb” isolated with byebug.

I usually treat

   if _FILE__ == $PROGRAM_NAME
    
   end

as my main method. If I want to run my program, create class object, invoke a method, and prints stuff, I will put it there (main method)

I hope it helps :slight_smile:

Wonderful Thai, thanks for that rapid response. I needed an example that I could relate to for it to become clear, and yours helped a million.

Just a slight fog that has me still unsure.

When I run :

# hello.rb
require 'byebug'
def hello
   puts "Hello World"
end
puts "__FILE__ = #{__FILE__}"
puts " $PROGRAM_NAME = #{$PROGRAM_NAME}"

if __FILE__ == $PROGRAM_NAME
   byebug
   hello
end

Terminal returns this (minus all excess):

__FILE__ = hello.rb $PROGRAM_NAME = hello.rb


I was expecting __FILE__==$PROGRAM_NAME => false but returned => true

Is it when we require a gem such as byebug it should become the source file (though it didnt work that way)?

Also what is the real significance of this trick?

Thanks again Thai!

Hello Julian,
I actually played around with it, and learned so much from your question, so I hope this makes sense to you.
Thank you !

Consider I have a ruby file hello.rb:

#Run “ruby hello.rb” without byebug and pry

#Run hello.rb with pry, without byebug

During the process of ‘hello.rb’ with the program ‘pry’, $PROGRAM_NAME is pry, and the FILE_ is current source file “hello.rb”. This is make sense, because the program we are using is pry and and we run on the source “hello.rb”.
However, after load “hello.rb” and run “hello.rb”, now FILE_ and $PROGRAM NAME will be ‘pry’ .
It tells us that we’re using pry and running no other file than the current file itself which is pry

#Run hello.rb with byebug

Like your example above
*** Inside debugging mode ****
if you type FILE_ , it output “byebug”. However, the actual FILE in “hello.rb” is not byebug, but “hello.rb”.
The next, continue, break,… commands come from the byebug source file
Well, I think byebug did a good job of doing what it needs to as a debugger program. It does its task as a debugger in order to debug “hello.rb” without mess up with the “hello.rb” 's source file (library,…)

Run “hello.rb” with byebug after loading “hello.rb” in pry

I think the values of $PROGRAM_NAME and FILE_
depends on what program we’re using, and what file is being executed by a program (any sources, any imported library, and classes) and where we are in the process of executing and debugging.

I think my grasp is much better now. You’re excellent a
breaking it down.

I did a final example of my own just to concretize what we covered and it checks out.

I made two scripts, hello.rb and primes.rb

hello.rb :

primes.rb:

where primes require hello

After running in terminal this was the result:

Which makes complete sense as __FILE__(hello) == hello.rb reflects the fact that hello is the source file and $PROGRAM_NAME(hello)=primes.rb which also makes sense as primes.rb is the program where hello.rb is executed. NOTE however this is all within the hello.rb script; so its the ‘perspective’ of `hello.rb’

Now when we enter primes.rb we see that primes is our source file (___FILE___) and our program being executed ($PROGRAM_NAME). Which again makes sense since we called loaded 'ruby primes.rb` and its the script being executed.

Now I also ran it with Pry repl and the results were as you predicited:

We are running the source file hello.rb in Pry

I think we covered some good ground here. Thanks for the help.

Cheers!

1 Like

great! good stuff. thank you @Julian.

1 Like