Require at end of file

Hi,

I would like to know if put the require(s) at the end of file change
anything ?

I come from C and it seems a little weird for me.

I found nothing on google about that.

Bests,

Sébastien

···

--
Sébastien Puyet

Well, you can't use what is defined in another file until you require it. For
example

# FILE a.rb

class A
end

···

On Thursday 07 July 2016 06:33:31 Sébastien Puyet wrote:

Hi,

I would like to know if put the require(s) at the end of file change
anything ?
Plex-Ruby/lib/plex-ruby.rb at master · ekosz/Plex-Ruby · GitHub

I come from C and it seems a little weird for me.

I found nothing on google about that.

Bests,

Sébastien

-----------------
# FILE b.rb

require 'a'
A.new
-----------------
# FILE c.rb

A.new
require 'a'
-----------------

The file b.rb is correct ruby code, while c.rb isn't, because it uses class A
before reading its definition from file a.rb.

The file you linked is a bit of a special case as it doesn't use anything of
what is defined in the files it requires: it's just a convenience file to require
everything needed for the library requiring a single file.

I hope this helps

Stefano

Hi,

I don't know about the specific code that you linked through, but it's easy to see why you're confused - I have also spent a lot of time in C/C++, so I can see why you may be surprised.

Hi,

I would like to know if put the require(s) at the end of file change anything ?
Plex-Ruby/lib/plex-ruby.rb at master · ekosz/Plex-Ruby · GitHub

I come from C and it seems a little weird for me.

One of the things is that require is not exactly "#include" - it does "bring in" the literal lines of text from the required file at that point. However, bringing in lines doesn't just stop there. The Ruby interpreter will, "after bringing the lines", interpret the text that was just brought in. So, effectively, what you have done is that you have made your code file larger and the interpreter will continue to execute that code.

Since the code you point to is setting up the library for being used by other programs, it is doing something like:
> initialize what the module is
> bring in code for functionality 1
> bring in code for functionality 2
> bring in code for functionality 3
> bring in code for functionality 4
...

after this, your code comes in to use the library.

Does that make sense?

Best Regards,
Mohit.

···

On 7/7/2016 2:33 PM, Sébastien Puyet wrote:

Thanks for your answer Stefano.

In this case (a gem), i know that this file is the entrypoint for rubygem
and all the files need to be required here.

I was wondering if it's impact the execution time efficiency or if it's a
best practice i do not know.

bests,

···

Le jeu. 7 juil. 2016 à 08:54, Stefano Crocco <stefano.crocco@alice.it> a écrit :

On Thursday 07 July 2016 06:33:31 Sébastien Puyet wrote:
> Hi,
>
> I would like to know if put the require(s) at the end of file change
> anything ?
> Plex-Ruby/lib/plex-ruby.rb at master · ekosz/Plex-Ruby · GitHub
>
> I come from C and it seems a little weird for me.
>
> I found nothing on google about that.
>
> Bests,
>
> Sébastien

Well, you can't use what is defined in another file until you require it.
For
example

# FILE a.rb

class A
end
-----------------
# FILE b.rb

require 'a'
A.new
-----------------
# FILE c.rb

A.new
require 'a'
-----------------

The file b.rb is correct ruby code, while c.rb isn't, because it uses
class A
before reading its definition from file a.rb.

The file you linked is a bit of a special case as it doesn't use anything
of
what is defined in the files it requires: it's just a convenience file to
require
everything needed for the library requiring a single file.

I hope this helps

Stefano

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
Sébastien Puyet

In this case (a gem), i know that this file is the entrypoint for rubygem
and all the files need to be required here.

Maybe there is some preliminary code executed before it makes sense to
require other files. For example, if you define something like a
registry where all other items register themselves then of course the
registry needs to be instantiated before it can be used.

I was wondering if it's impact the execution time efficiency or if it's a
best practice i do not know.

Well, you need to require a file as soon as you, um, require its content. :slight_smile:

The only reasonable "optimization" I can think of is to include the
require in specific methods. As long as they are not invoked there is
no IO overhead for reading the required file. I cannot remember though
a case where that really made a difference for me. Because on the
downside you incur the cost of checking whether the file has been
loaded already on all method invocations (unless you redefine that
method after first requiring which seems quite messy to me).

Kind regards

robert

···

On Thu, Jul 7, 2016 at 10:20 AM, Sébastien Puyet <sebastienpuyet@gmail.com> wrote:

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can
- without end}
http://blog.rubybestpractices.com/

No, this is false.

require is not at all like C's #include. What you're describing with "bringing in" and "made your code file larger" is exactly what C's #include does. That's why in C you need to wrap your headers with extra #ifndef+#define checks to avoid double or circular inclusions.

In ruby require handles all of that for you including bitching at you if you have circular requires set up. It doesn't "bring in" anything. It loads and executes the file in question as a separate method call and doesn't have any effect on the calling require's scope at all. That's why local variables won't be changed when you require something that also messes with those variables.

In the project in question, you often want to define a top level namespace and any common utilities before you require the rest of your library. That lets the rest of your library have flattened namespaces (eg MyProject::MyClass) and the like.

Also remember, require is just a method call. That's why things like bundler or rubygems are able to do what they do. And once the method call is executing, it returns to the call site and continues.

···

On Aug 3, 2016, at 03:19, Mohit Sindhwani <mo_mail@onghu.com> wrote:

One of the things is that require is not exactly "#include" - it does "bring in" the literal lines of text from the required file at that point. However, bringing in lines doesn't just stop there. The Ruby interpreter will, "after bringing the lines", interpret the text that was just brought in. So, effectively, what you have done is that you have made your code file larger and the interpreter will continue to execute that code.

Thanks for all your explanations guys !

As i understand when i require a file, all the content is loaded and
evaluated.

I have another question:

require 'koala' # true

{}.to_json # NoMethodError: undefined method `to_json' for {}:Hash

I does not understand why an exception raised. The 'json' gem is a
dependency of the 'koala' gem and however when i execute:

$LOADED_FEATURES.select{ |s| s.match /json/ }

it returns:
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/options.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/version.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/adapter_error.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/parse_error.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json.rb"]

The 'json' gem does not seem to be loaded.

I missed something ?

···

Le mer. 3 août 2016 à 23:19, Ryan Davis <ryand-ruby@zenspider.com> a écrit :

> On Aug 3, 2016, at 03:19, Mohit Sindhwani <mo_mail@onghu.com> wrote:
>
> One of the things is that require is not exactly "#include" - it does
"bring in" the literal lines of text from the required file at that point.
However, bringing in lines doesn't just stop there. The Ruby interpreter
will, "after bringing the lines", interpret the text that was just brought
in. So, effectively, what you have done is that you have made your code
file larger and the interpreter will continue to execute that code.

No, this is false.

require is not at all like C's #include. What you're describing with
"bringing in" and "made your code file larger" is exactly what C's #include
does. That's why in C you need to wrap your headers with extra
#ifndef+#define checks to avoid double or circular inclusions.

In ruby require handles all of that for you including bitching at you if
you have circular requires set up. It doesn't "bring in" anything. It loads
and executes the file in question as a separate method call and doesn't
have any effect on the calling require's scope at all. That's why local
variables won't be changed when you require something that also messes with
those variables.

In the project in question, you often want to define a top level namespace
and any common utilities before you require the rest of your library. That
lets the rest of your library have flattened namespaces (eg
MyProject::MyClass) and the like.

Also remember, require is just a method call. That's why things like
bundler or rubygems are able to do what they do. And once the method call
is executing, it returns to the call site and continues.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
Sébastien Puyet

You can forget it. The '2.4.0' koala version does not require 'json', it
was an issue in the gem, now fixed:

···

Le ven. 5 août 2016 à 11:48, Sébastien Puyet <sebastienpuyet@gmail.com> a écrit :

Thanks for all your explanations guys !

As i understand when i require a file, all the content is loaded and
evaluated.

I have another question:

require 'koala' # true

{}.to_json # NoMethodError: undefined method `to_json' for {}:Hash

I does not understand why an exception raised. The 'json' gem is a
dependency of the 'koala' gem and however when i execute:

$LOADED_FEATURES.select{ |s| s.match /json/ }

it returns:
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/options.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/version.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/adapter_error.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json/parse_error.rb",
"/Users/spuyet/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/multi_json-1.11.0/lib/multi_json.rb"]

The 'json' gem does not seem to be loaded.

I missed something ?

Le mer. 3 août 2016 à 23:19, Ryan Davis <ryand-ruby@zenspider.com> a
écrit :

> On Aug 3, 2016, at 03:19, Mohit Sindhwani <mo_mail@onghu.com> wrote:
>
> One of the things is that require is not exactly "#include" - it does
"bring in" the literal lines of text from the required file at that point.
However, bringing in lines doesn't just stop there. The Ruby interpreter
will, "after bringing the lines", interpret the text that was just brought
in. So, effectively, what you have done is that you have made your code
file larger and the interpreter will continue to execute that code.

No, this is false.

require is not at all like C's #include. What you're describing with
"bringing in" and "made your code file larger" is exactly what C's #include
does. That's why in C you need to wrap your headers with extra
#ifndef+#define checks to avoid double or circular inclusions.

In ruby require handles all of that for you including bitching at you if
you have circular requires set up. It doesn't "bring in" anything. It loads
and executes the file in question as a separate method call and doesn't
have any effect on the calling require's scope at all. That's why local
variables won't be changed when you require something that also messes with
those variables.

In the project in question, you often want to define a top level
namespace and any common utilities before you require the rest of your
library. That lets the rest of your library have flattened namespaces (eg
MyProject::MyClass) and the like.

Also remember, require is just a method call. That's why things like
bundler or rubygems are able to do what they do. And once the method call
is executing, it returns to the call site and continues.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
Sébastien Puyet

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk&gt;

--
--

Sébastien Puyet