top | item 32123133

(no title)

jonnytran | 3 years ago

This is simply false. Ruby modules are first class. They're objects that you can pass around like any other object. You can put them in a local variable. You can define methods on them. You can do metaprogramming using them. You can build classes by mixing modules together. You can create modules (and classes) at runtime. Many things that need to be built-in in other languages are just a library in Ruby.

Files and modules in Ruby are two distinct things. While Python makes files one-to-one with modules, Ruby allows you to define as many modules as you like in a file, zero or more.

It's true that if you define a constant at the top-level of a file, it uses the global namespace.

By convention, if you have a file named `foo.rb`, you'd write:

    module Foo
      # Code here
    end
and it's equivalent to what's done in Python. But it also has all the other features.

discuss

order

choward|3 years ago

Your claiming anything wrapped in a module block is a module. My point is that they aren't "real" modules. I know it's debatable what a module is but Ruby's don't meet my definition. Here's why:

Let's say a file had a module in it. It can behave differently based on context.

For example, let's say I have a module A that requires modules B and C. Module C could use module B without explicitly pulling it in because modules are just globals. However, if a different module just requires module C but not module B and no other files required B either, then module C would break when it tries to use model B. If modules weren't global B, would have to require it to use it directly regardless but since it doesn't it's easy to get unexpected results.

In ruby a file doesn't have to declare the modules it uses which is why I don't consider them modules but just global namespaces. So if another module that got required earlier happens to require B, then B can be used because it's just a global.

I'm summary, modules in Ruby aren't modules but just global namespaces.

jonnytran|3 years ago

When I was new to Ruby and hadn't learned the available tools yet, I had similar problems because I brought practices from other languages that didn't work.

Typically, what you're describing is solved, in different ways depending on your setup. I literally never think about the issue you're describing when using Ruby.

- With Rails/ActiveSupport in development mode: Module B is autoloaded lazily when C refers to it.

- With Rails/ActiveSupport in production mode: All modules are eagerly loaded at startup.

- Plain Ruby: There's a few ways, but most gems simply have a file at the top level that eagerly requires all files when the gem is required. Same with an app.

If startup time becomes an issue, you can configure the autoloading at the top level, and the appropriate file will be required lazily when it's referred to. But at that point, just use ActiveSupport.

hnfong|3 years ago

That’s kind of what the GP meant…

A require in ruby would just import whatever those files defined in the global space. They may be “modules” (which probably have different meaning in ruby vs Python), but they’re globals nonetheless and inventive coders put all sorts of weird things into the global space instead of following convention of one file one module.

It’s a fundamental philosophical difference between the two languages - is it a good thing to let programmers do the wrong thing? Python makes it hard to do so, Ruby celebrates the flexibility.