On Friday, January 14, 2011 07:34:04 am Jonas P. (zimbatm) wrote:

this is a general census to get developer feedback. Please post the

issues you encounter when developing in ruby. This can range from

syntax issues, to library support, documentation, or anything that is

a roadblock when developing in ruby.

In no particular order…

I wrote a long post because I don’t have time to write a short one. To

summarize:

RubyGems:

Play nice with other package managers

Better installers for end-users

gems/rvm/bundler confusion

Library management:

Better namespacing

Better handling of monkeypatching

Multithreading:

Threads are too primitive

Actors would be cool, but have issues

Wish list:

Lisp-style Macros.

Ruby-in-Javascript.

And now the rant:

Right now, Rubygems is both the biggest win and the biggest blocker for

newbies. I haven’t been keeping track, so I find I now have to learn RVM

and

Bundler just to keep up with the best practices for deploying a Rails

app. And

how do these interact with the system Ruby? If I install a system

package that

depends on a particular version of Ruby, will it get the version it

expects,

or will it get my default RVM version?

Unfortunately, I don’t have a good answer for this, and I don’t really

know

much about the solutions that do exist, but nearly every one I’ve tried

has

been very messy in many ways. Installing gems to my home directory is

just not

a good idea.

Another thing that I’d like to see more work on – though I think

alright

solutions exist, especially for JRuby – is the ability to distribute

Ruby

clients. It seems like there are two solutions, one for developers, and

one

for end-users. The developer solution is to build it as a gem, but it’s

not

reasonable to ask an end-user to install Ruby, Rubygems, and then your

gem.

The end-user solution is to build it as a giant monolithic file which

includes

all relevant gems. Surely there’s a middle ground – a nice, intuitive

installer, but one which actually sets up a system Ruby and Rubygems for

the

user, so that multiple programs don’t have to separately download and

install

the same libraries.

And Rubygems itself – while it seems it’s capable of understanding

reverse

dependencies, I want to be able to automatically clean stuff that I

don’t need

anymore. Gemfiles are kind of a decent start, but I’m thinking something

along

the lines of “manual” vs “automatic” in Debian, or even better, Gentoo’s

/var/lib/portage/world. In particular, I want to be able to install a

gem just

to see what it does, and if I don’t like it, uninstall that gem and then

clean

up every gem that was only installed because it was depended on.

RVM’s gemsets are kind of cool, but they seem to be a workaround for not

having that functionality. The only other reason to have them seems to

be when

developing a gem.

One more thing about gems: How do we know what a good gem is? I love how

decentralized it is now, at least in theory, but occasionally it means I

need

to go through two or three gems and try each of them before I find

either that

none of them does what I want, or some oddly named and maybe

semi-obscure gem

is perfect.

Moving away from rubygems and installation, and to semantics…

A bit more namespacing would be awesome. The current practice of just

dumping

something you hope is appropriate into the global namespace of constants

is

bad enough. It’s worse when we start monkey-patching other stuff.

I don’t know how big a problem this actually is. It doesn’t seem to

actually

cause problems in practice, so maybe I’m overreacting. Still, I like how

Perl

and Python handle this, where there’s a difference between loading a

library

and importing it into your namespace.

Namespacing constants aggressively shouldn’t be too much of a burden, as

Ruby

has the same shortcuts JavaScript does. Take JRuby. Sure, you can do

this:

import java.util.PriorityQueue

But you can also do this:

pq = java.util.PriorityQueue

That’s locally-scoped, which means you aren’t polluting any namespace

past the

end of the current block. Or you could do something like:

module MyMod

PQ = java.util.PriorityQueue

…

end

In both of these cases, you aren’t affecting anything else in the same

runtime. But if you ‘import’ it globally, you’ve declared it, well,

globally.

Point is, I don’t think we should be afraid to do stuff like this,

though we

could use just a bit of sugar to make it easier:

module FooCo

module LibFooVersion213

class Foo

…

end

end

end

Ok, yes, people will get sick of typing that, but again:

foo = FooCo::LibFooVersion213::Foo

Problem solved.

Monkey-patching is harder. Is there a way we can scope things like

Activesupport’s hacks? Stuff like:

‘bird’.pluralize

5.days.ago

foo.should be_valid

I love these things, but I wish there was a way I could declare them to

be

only available in a certain context or scope. This seems like it needs

some

language support to be really effective – we could fake it now by

mixing them

in and out of the core classes as needed, but that would affect any

other

threads, so it kind of defeats the purpose if you’re using

multithreading.

Essentially, the idea here is that when multiple libraries inevitably

end up

using the same name for something, we should be able to work around it.

When

they don’t, we don’t want it to be a burden. (I think JQuery is a

perfect

example of this done right.)

Let’s get some proper multithreading, to start with. It’s 2011. There is

really no excuse for a GIL. Either drop it or mainstream COW GC –

otherwise,

JRuby becomes the only real option for multicore on Ruby.

How about some higher-level threading constructs, too. There are a few

gems

which add interesting ideas… However, there are limits to what you can

do

with Ruby as it is, and these are partly due to the fact that it’s not

Erlang.

Again, I’m not sure of the best way to do this, but…

We have objects, and objects can, in principle, completely encapsulate

their

state. We’ve actually got that implemented properly – just look at

send,

method_missing, the fact that we need accessors, etc. This would be a

perfect fit for the actor model, and it’s something I tried to do once,

but

never really finished – but essentially, why not “just” make all Ruby

objects

actors?

Aside from performance issues, but I was going to do a proof-of-concept

and

ignore those…

Well, I didn’t quite finish it, but one problem I ran into in the design

phase

is the fact that there’s entirely too much Ruby code which wouldn’t work

at

all with this kind of design. For example:

foo.a += 1

Sure, you can override foo.a and foo.a= and either add a giant mutex, or

push

them off to a separate thread. Either way, you’re still going to have a

race

condition between getting the value of a and setting it again. Something

like

this might work:

foo.increment! :a

If you were to view each object as an actor, and each method call as a

message, stuff like that works very, very well. I still want to finish

my

idea, because I think you could get a lot of mileage out of new objects

which

were designed from the start to be actors. I think you could do that

without a

lot of language overhead. I had a proof-of-concept partly done.

But that still doesn’t change the fact that this will never work:

foo.some_hash[:a] += 1

Even after you make sure foo is an actor, and the some_hash it returns

is some

sort of proxy object that serializes all access, you still have the race

condition between the call to [] and the call to []=.

I think that this kind of problem is exactly the kind of thing Ruby

should be

concerned with. The typical Ruby battle cry has been “Hardware is

cheaper than

programmers!” Well, alright, here’s a machine with a few thousand cores.

How

is Ruby going to handle that? Can the language itself be fixed, or does

there

need to be a new one that combines the best of Ruby with the best of

(say)

Erlang? (In other words, is something like Reia the way forward?)

I don’t know, but while it’s sort of workable now, it’s probably the

single

language flaw that keeps me up at night.

There is one other that just annoys the purist in me…

Is there any way we can get anything like Lisp sexps? As I understand

it, we

have a few Ruby parsers, but nothing standardized to the point where I

can ask

the runtime itself to give me a parse tree for a given expression. The

closest

I could find was various implementation-specific things and ruby_parser,

which

is cool but buggy, missing a few of the 1.9 features.

But that I can live without. My rationale is, pretty much any syntactic

ugliness can be worked around with a preprocessor if it’s really

bugging me

(see lazibi), and Ruby is pretty anyway. It’s semantic ugliness that’s

tricky.

Ruby doesn’t have GOTO, it doesn’t have pointers or malloc, it’s done

away

with pretty much every bit of low-level nastiness associated with

single-

threaded programming – but the Thread system makes me feel like I’m in

C

again, where the slightest mental mistake could lead to my entire

program

screwing up in unimaginably arcane ways.

A final point: Browsers are getting fast enough that we should be able

to do

Ruby in Javascript. And not a server-side implementation, either – I

want the

equivalent of JRuby. But this isn’t really a limitation of Ruby, it’s a

limitation of browsers that we’d be working around. The above rants are

things

I actually feel are broken about Ruby as it is today.