Perl Junkie: Bad form?

U

/usr/ceo

Ok where do I start? :) A little background...

I've been declaring up and down for 6 years now I'm going to stop using
Perl and start using Ruby. One thing that has always held me back is
not having libraries I've put together in Perl available to me in Ruby.
Instead, I've ported little Ruby tricks over into Perl to the extent
possible. Now I've decided the only way I'm going to use Ruby is start
porting some of the stuff I use in Perl to Ruby.

Here's a little bit of a delimma I have going that I hope to illustrate
using something simple.

I wrote this routine in Perl called "puts" that mostly simulates Ruby's
"puts" statement. (I intend to illustrate something bigger than "puts"
emulation here, so don't let that drag you in. I'm more interested in
the module interaction and EXPORTS [in Perl] and include [in Ruby]
interaction...). Here's the puts() routine in Perl:

sub puts { for (@_) { print "$_\n" } }

That routine is in a Perl module called Utils.pm under a My directory
with puts() EXPORTed. So in a Perl script, I can:

#!/usr/bin/perl
$|++;

use My::Utils;

puts(
"This is line 1",
"This is line 2",
"This is line 3",
);

Now, in Ruby, I find if I construct something similar in a module, I
might create a utils.rb file, place it in the "my" directory under the
Ruby site_ruby directory and have:

module Utils
def Utils.mputs( *args )
args.each { |n| puts n }
end # def
end # module

Then in a Ruby script:

#!/usr/bin/env ruby

require "my/utils"

Utils.mputs(
"This is line 1",
"This is line 2",
"This is line 3"
)

But I don't like having to write "Utils.mputs". In Perl, I exported
the "puts" routine, so in Perl it's in the main namespace and I can
just say: puts( "A", "B", "C" ), etc. I want to be able to do the same
thing in Ruby. Instead of Utils.mputs( blah ), I want to just write
mputs( blah ). So in Ruby, I did this to the Utils module:

module Utils
def mputs( *args )
args.each { |n| puts n }
end # def
end # module

include Utils

Now in my Ruby script, I can do:

#!/usr/bin/env ruby

require "my/utils"

mputs(
"This is line 1",
"This is line 2",
"This is line 3"
)

This is what I would rather be doing, generally, for imported utility
type routines -- making them look "native." I understand (pretty much)
about the separate namespace issue, and namespaces are certainly nice
(both in Perl and in Ruby). But sometimes I want to pretend I have
something "natively" available to me, and this seemed to work.

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

Thanks!
/usr/ceo
 
E

Eero Saynatkari

/usr/ceo said:
Ok where do I start? :) A little background...

I've been declaring up and down for 6 years now I'm going to stop using
Perl and start using Ruby. One thing that has always held me back is
not having libraries I've put together in Perl available to me in Ruby.
Instead, I've ported little Ruby tricks over into Perl to the extent
possible. Now I've decided the only way I'm going to use Ruby is start
porting some of the stuff I use in Perl to Ruby.

Here's a little bit of a delimma I have going that I hope to illustrate
using something simple.

I wrote this routine in Perl called "puts" that mostly simulates Ruby's
"puts" statement. (I intend to illustrate something bigger than "puts"
emulation here, so don't let that drag you in. I'm more interested in
the module interaction and EXPORTS [in Perl] and include [in Ruby]
interaction...). Here's the puts() routine in Perl:

<snip explanation />

This is what I would rather be doing, generally, for imported utility
type routines -- making them look "native." I understand (pretty much)
about the separate namespace issue, and namespaces are certainly nice
(both in Perl and in Ruby). But sometimes I want to pretend I have
something "natively" available to me, and this seemed to work.

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

The problem is you might be tromping all over the library
user's namespace, possibly overriding methods etc. It is
better to give the 'namespace' and then allow the client
programmer #include the module if they desire shorter access.

Those who remember, I actually advocate allowing the client
programmer create a namespace for libraries instead of the
library writer, too, but that is another discussion.
 
U

/usr/ceo

Eero said:
/usr/ceo said:
Ok where do I start? :) A little background...

I've been declaring up and down for 6 years now I'm going to stop using
Perl and start using Ruby. One thing that has always held me back is
not having libraries I've put together in Perl available to me in Ruby.
Instead, I've ported little Ruby tricks over into Perl to the extent
possible. Now I've decided the only way I'm going to use Ruby is start
porting some of the stuff I use in Perl to Ruby.

Here's a little bit of a delimma I have going that I hope to illustrate
using something simple.

I wrote this routine in Perl called "puts" that mostly simulates Ruby's
"puts" statement. (I intend to illustrate something bigger than "puts"
emulation here, so don't let that drag you in. I'm more interested in
the module interaction and EXPORTS [in Perl] and include [in Ruby]
interaction...). Here's the puts() routine in Perl:

<snip explanation />

This is what I would rather be doing, generally, for imported utility
type routines -- making them look "native." I understand (pretty much)
about the separate namespace issue, and namespaces are certainly nice
(both in Perl and in Ruby). But sometimes I want to pretend I have
something "natively" available to me, and this seemed to work.

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

The problem is you might be tromping all over the library
user's namespace, possibly overriding methods etc. It is
better to give the 'namespace' and then allow the client
programmer #include the module if they desire shorter access.

Those who remember, I actually advocate allowing the client
programmer create a namespace for libraries instead of the
library writer, too, but that is another discussion.

So are you advocating this (by your last statement especially)?

my/utils.rb:

module Utils
def mputs( *args )
args.each { |n| puts n }
end # def
end # module

myscript.rb:

#!/usr/bin/env ruby

require 'my/utils'
include Utils

mputs(
"Line 1",
"Line 2",
"Line 3"
)

BTW, I am familiar with the fact the one can use "here documents" in
Ruby as well. Again, the simple mputs() routine was intended to
illustrate the require/include interaction -- not to illustrate a way
to write multiple lines (in case someone else comes along and reads it
that way.)

/usr/ceo
 
D

David Vallner

So are you advocating this (by your last statement especially)?

my/utils.rb:

module Utils
def mputs( *args )
args.each { |n| puts n }
end # def
end # module

myscript.rb:

#!/usr/bin/env ruby

require 'my/utils'
include Utils

mputs(
"Line 1",
"Line 2",
"Line 3"
)

If I understood right, he advocates adding into ruby a construct that
would do:

my/utils.rb:

def mputs( *args )
args.each { |n| puts n }
end

myscript.rb:

require 'my/utils' as Utils
Utils.mputs("Womble", "Fluff")

where if you'd omit the 'as' clause, mputs would be in the global
namespace.

Which is a nifty idea, but I'd also like to see file-scoped or
lexically-scoped require along with it, since this still lets someone
thrash the global namespace for scripts that are unaware of this.
 
S

Sander Land

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

Thanks!
/usr/ceo

If you're going to put the include statement in the file itself you
might as well add these methods to the Kernel module (where puts is),
but you should be really careful with this if you expect others to use
your code.

Some examples of gems that add methods to Kernel:
Facets can add a lot
(http://facets.rubyforge.org/api/core/classes/Kernel.html) , but lets
you include every method separately.
HighLine has everything in modules, but has an extra file that adds
some of these methods to Kernel
(http://highline.rubyforge.org/doc/classes/Kernel.html)
 
P

phrogz

This is what I would rather be doing, generally, for imported utility
type routines -- making them look "native." I understand (pretty much)
about the separate namespace issue, and namespaces are certainly nice
(both in Perl and in Ruby). But sometimes I want to pretend I have
something "natively" available to me, and this seemed to work.

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

You understand the namespace issue, but you know what you want. I'd say
"Go for it!". The power is in your hands. Ruby lets you open up classes
and redefine them after the fact. Why shouldn't you do this at the
global or Kernel level?

(In case it helps, let me plug
http://phrogz.net/RubyLibs/RubyMethodLookupFlow.png to help you discern
the various areas where you might choose to inject your addons. The
'main' object is an Object.)

One other thing - if you KNOW you always want global functions, why not
just define them as such in the included file?
If you're not sure, then probably you should pull the 'include'
statement out of your separate file. That means when you DO want them
global, you'll need to do:
require 'foo'
include Foo

but at least you'll still have an option.
 
L

Logan Capaldo

Eero said:
/usr/ceo said:
Ok where do I start? :) A little background...

I've been declaring up and down for 6 years now I'm going to stop
using
Perl and start using Ruby. One thing that has always held me
back is
not having libraries I've put together in Perl available to me in
Ruby.
Instead, I've ported little Ruby tricks over into Perl to the
extent
possible. Now I've decided the only way I'm going to use Ruby is
start
porting some of the stuff I use in Perl to Ruby.

Here's a little bit of a delimma I have going that I hope to
illustrate
using something simple.

I wrote this routine in Perl called "puts" that mostly simulates
Ruby's
"puts" statement. (I intend to illustrate something bigger than
"puts"
emulation here, so don't let that drag you in. I'm more
interested in
the module interaction and EXPORTS [in Perl] and include [in Ruby]
interaction...). Here's the puts() routine in Perl:

<snip explanation />

This is what I would rather be doing, generally, for imported
utility
type routines -- making them look "native." I understand (pretty
much)
about the separate namespace issue, and namespaces are certainly
nice
(both in Perl and in Ruby). But sometimes I want to pretend I have
something "natively" available to me, and this seemed to work.

Ugly? Right? Hackish? A better way? Looking for the Ruby
perspective here because this is probably one of my more unsolved
delimmas -- how to view, approach and implement cases like this.

The problem is you might be tromping all over the library
user's namespace, possibly overriding methods etc. It is
better to give the 'namespace' and then allow the client
programmer #include the module if they desire shorter access.

Those who remember, I actually advocate allowing the client
programmer create a namespace for libraries instead of the
library writer, too, but that is another discussion.

So are you advocating this (by your last statement especially)?

my/utils.rb:

module Utils
def mputs( *args )
args.each { |n| puts n }
end # def
end # module

myscript.rb:

#!/usr/bin/env ruby

require 'my/utils'
include Utils

mputs(
"Line 1",
"Line 2",
"Line 3"
)

BTW, I am familiar with the fact the one can use "here documents" in
Ruby as well. Again, the simple mputs() routine was intended to
illustrate the require/include interaction -- not to illustrate a way
to write multiple lines (in case someone else comes along and reads it
that way.)

/usr/ceo

Yes, this is SOP. The only other thing I would suggest is for modules
like Util (where it's just a collection of "functions" and not
methods) is you do

module Util
def mputs(*args)
args.each { |item| puts item }
end
module_function :mputs
end

This lets you say

Util.mputs

or

include Util
mputs

similar to the Math module.
 
J

Jake McArthur

This is your code. You can do whatever you want. It doesn't seem too
far from where many others go here.

That said, why wrap the mputs definition in a module at all if you
are including it into the global namespace immediately after inside
the same file? How about something like this? (mostly untested)

def require_and_include(filename)
require filename
include Kernel.const_get(filename.match(/.*\/?([A-Z][a-z0-9_]*)
(\.rb)?/)[1])
end

require_and_include "my/Utils"

It should work when the name of the file is the same as the name of
the module to include. In this case, you must also make the first
letter of the file name capitalized, but it could be modified easily
to not require that.

- Jake McArthur
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,124
Latest member
JuniorPell
Top