I am learning Ruby right now, to play with Ruby on Rails, and I don't know yet wether I like it or loathe it, it looks pretty much like the illegitimate child of Perl and Python, which sounds very wrong.
What are your opinions about Ruby?
No, no, Ruby is "the bastard child of Smalltalk and Perl." Not Python, Smalltalk. Let's be consistent in our dissing of Ruby here.
And yeah, I agree completely that that is what it is, but whatever you find useful...
So should I run away while I still have time, or should I pretend I like it until I actually do?
How about pretending to run away until you actually do?
The bastard child of Smalltalk and Perl can't be any worse than the bastard child of Smalltalk and C - hello, Objective-C!
I mean, Perl is messed up from the start, it's not like you could easily make it any more strange.
Hate it. Hate Perl too, though, so it's no surprise.
Love it. It's smalltalk with clear syntax and just the right amount of sugar.
You shouldn't jump straight into rails, though, IMO. Although it's a great web framework, it just doesn't feel like ruby to me.
>>7
I am only learning Ruby so that I can evaluate Rails right now, do you mean that trying out Rails without enough Ruby experience is going to make me waste time, or to make learning Ruby much more difficult?
Ruby is nice, but it looks like it's going to start getting weird syntax in 1.10. Which is a pity.
>>6
What's so similar between Ruby and Perl that it's unsurprising that if you hate one, you hate the other?
How about they start getting rid of some weird syntax first?
Ruby proponents love to joke about semicolons, but then replace that problem with @. There's the really strange ".." vs "..." You can't type variables if you want to. #{} makes some strings look like linenoise. Regex is hamstrung. "end" is questionable.
If you fixed the first three, a significant source of errors would just vanish. Why Ruby replaces s/// with sub/gsub is beyond me. #{} needs to die.
Anyway, Ruby really is superficially quite similar to Perl, which is why I like it. I think of it as Python for Perl coders. If only it was faster (is YARV ready for prime time?).
>>7 It's smalltalk with clear syntax
LOL, what ? Obviously you have never written anything serious in Smalltalk.
>>8 I am only learning Ruby so that I can evaluate Rails
Smalltalk is superior. Take a look at http://www.seaside.st/.
>Smalltalk is superior. Take a look at http://www.seaside.st/.
...that site is kind of b0rked for me.
>>11
So basically your post is stating that smalltalk is superior to ruby, and is backing it up by stating that you have experience in smalltalk and accusing >>7 of not having any?
> Smalltalk is superior. Take a look at http://www.seaside.st/.
Only took like 2 minutes to evaluate it, but I am running away. There are too many big words on the front page and way too little big picture explanation, and of course no real-world example, let alone any large site or commercial site example. Is it really supposed to be used to make real sites?
I hope you can prove me wrong on this.
>>11,14
What does Seaside does better, more, faster or differently that Rails?
> And I can't understand why you want static typing?
Because I don't like it when I mistype a variable, and instead of telling me about it, it silently makes a new one? If it catches something that stupid right off the bat, it saves me wondering why the code doesn't work.
Same applies for @. If I forget the @ in front of the variable, does it tell me about it? Nope, it just makes a new one, because @somevariable and somevariable are different things.
I don't particularly care about the other aspects of static typing, I just want to know if something like the above occurs.
Talking about which, explain to me why sub does two passes.
Okay, Ruby ripped of some ideas from Perl, including regex. GJ! Unfortunately, it didn't include the rather terse s/// syntacitic sugar. Fine, it's not pretty, but I can live with that. However:
i = '\\'
puts i.sub(/\\/, '\\')
The result is a single backslash. What about this:
i = '\\'
puts i.sub(/\\/, '\\\\')
Should give two, right? No, it gives one. If I want two, I need to use either '\\\\\\' or '\\\\\\\\'. Or I can use:
i = '\\'
puts i.sub(/\\/) { '\\\\' }
Least surprise? I think not.
>>16
If you need an object to behave in a certain way, check whether the methods you need are available ("string".respond_to? :split)
If you need an object of a specific class, well, nothing is stopping you from doing "string".is_a? String
Oh, and @somevariable is an instance variable, somevariable is not. They shouldn't be the same.
PS. Static and strong typing aren't the same thing.
That's... Just plain bizarre. Escaping backslashes is a huge pain to get right as it is, and making it even weirder is definitely not a good thing.
> Talking about which, explain to me why sub does two passes.
What do you mean by that?
>>19-20
Could you give me an example of the sort of situation you're talking about? Do you mean doing something like this:
@mister_var = 1
@miszer_var # Oh noes it's returning nil and not raising an error
I know that static and strong typing are different things, my point was that a lot of the issues people usually have with dynamic typing can in fact be solved in other ways.
Close, but a bit artificial.
You might make an error that returns the wrong object, but it's far more likely you'll do something like this:
@color = 10
...
@colour = yield
...
@color
Whoops.
I'd rather that Ruby had something similar to Perl's strict mode and my keyword. Happily enough, Ruby 2.0 apparently will have this (but when it finally comes out is another question).
>>22
Precisely what I said. Apparently the regex engine passes through the string twice.
Don't believe me? Run the posted code and prefix a puts or print in the second expression.
Looks like puts is already there. Just execute it.
>>13 > So basically your post is stating that smalltalk is superior to ruby, and is backing it up by stating that you have experience in smalltalk and accusing >>7 of not having any?
No, not exactly. First I was commenting on >>7 statement about syntax. Because Smalltalk really has best syntax ever, it's very simple, clean and consistent, nothing I have ever seen comes close to it. It is clear that only real reason why someone could not like it is because he has not used Smalltalk for reasonable time.
Then what I was saying was that, if >>1 is learning Ruby just for Rails then as good he could learn Smalltalk for Seaside, because Smalltalk is superior. And I was not backing this up by anything, that's different story for different thread. Feel free to let me know if you would like to hear that story...
As an aside, "simple, clean and consistent" syntax is good for computers, but not for humans. We thrive on redundancy and expressiveness. It is possible to produce turning-complete langauges with a single instruction, which is pretty simple, clean and consistent. Doesn't make it good syntax for programming in, though.
> Is it really supposed to be used to make real sites?
Check out Dable DB [1] ( demo video [2] ), it's one of those fancy and totally useless web applications that kids now days do, but it does look pretty complicate, if something like this can be done than anything else should be possible too, right ?
>>15
I fear that I wont be able to provide any further insight about Seaside, I really don't care neither about it nor Rails.
[1] http://smallthought.com/
[2] http://smallthought.com/clips/lispvan.mov
>>27
I am >>13 and >>1. It sure demonstrates that the system can be used for actual applications, but it just doesn't have "Holy fucking shit I want to use that" factor you can see in this video:
http://www.rubyonrails.com/media/video/rails_take2_with_sound.mov (50MB, 15 min., sound)
I have seen today how it was possible in Rails to put together a form with an autocomplete like Google Suggest that fetches candidates from the database, with only 3 simple lines of code. That's the kind of thing I like having, and I think that unless there's some big issue that has yet to hit me, I'm hooked.
I should receive "Agile Web Development with Rails" from Amazon monday, but thank you for recommanding alternative tools.
Regarding Ruby, I am starting to like it. Learning about the way it does some things was quite the head trip, but then I had no serious experience with a true 100% OO language. I agree that it looks very noisy, though, and since it looks like that comments are against Ruby coders' religious belief, it's a bit difficult to find interesting apps to read. I believe I could get used to it though.
irb(main):003:0> puts "\\".sub(/\\/, '\\\\')
\
=> nil
irb(main):004:0> "\\".sub(/\\/, '\\\\')
=> "\\"
Ahem :O. puts
interprets the string exactly the way it should. The stray "\" at the end is cut off as it doesn't seem to escape anything.
>>31
Waah, regular expressions and backslashes make my head hurt.
You missed the problem, >>31. Let me clarify:
puts "\\".sub(/\\/, '\\')
puts "\\".sub(/\\/, '\\\\')
Result:
>ruby test2.rb
\
\
>Exit code: 0
Also, to make it a bit more readable:
irb(main):002:0> "a".sub(/a/,'\\\\')
=> "\\"
irb(main):003:0> "a".sub(/a/,'\\')
=> "\\"
Wow, that really makes no sense whatsoever.
Argh. I completely forgot that "\\"
is actually a single \
, because irb displays a string escaped >_>. Forget what I said about puts
cutting off an \
.
Also, I found this on the mailinglist: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/99784. So, uh, yeah. >:O.
By the way, what do you need this for, anyway? Just curious.
> By the way, what do you need this for, anyway?
Once I became aware of it, nothing. I'll just use code blocks instead. I'd rather the trap didn't exist though, because (like any language) it's another quirk to be aware of and work around.
Actually, I'd much rather just have s///, but I digress.
I've used this exact construct a number of times. You'd use it when creating string literals that need escaping. In this case, the extra escaping would probably make the code a no-op.
> I don't know yet wether I like it or loathe it
Now ~2 months later I love it, but maybe it's only because of all the concepts it introduced me to or helped me understand better. It's pretty much the only scripting language I use now, and its interactive shell is really great to try out things. I shouldn't have discarded it as some kind of wapanese curiosity when I first heard about it.
I was reading through this thread again and I came across this:
> and since it looks like that comments are against Ruby coders' religious belief
Argh! ARGH! ARGH! I have the same problem with python code. They seem to think they don't need to comment anything!
Recently, as part of my job, I had to interface several python programs together. There were almost no comments in the third-party programs, and the code other people on my team write contains no comments at all, other than the occasional "# XX: fixme". I'm the only person who bothers to comment and document anything.
Sorry guys, I don't give a flip about the details of your code. I just need a general idea of what's going on. Reading every last expression because you're too lazy is a waste of my time.
Tying this back to Ruby: I've found Python a bit of a disappointment. It's a nice language and all, but having fooled around with Ruby first, Python's syntax seems to me to be growing hair everywhere.
>>39
When I wrote that, I didn't know about a lot of ruby idioms, so a lot of 'self-explanatory' code looked like line noise, but now I think that when things are actually commented and documented, then the documentation systems in Ruby and Python are both quite good.
>>40
Yes, when they're actually documented. The problem is that there seems to be a large number of developers who won't comment their code at all. They don't even use doc strings.
Grargh.
Save another developer's sanity: put in a useful comment for every class, method, and unusual paragraph of code.
# XX: fixme
I cannot figure out why to_i returns 0 if it doesn't find a number. We have a language that DEFINES a value for null(nil) AND we have exceptions, but we are just going to straight copy C's atoi because that is what people are used to. Brillant. Also, would it KILL them to call it to_int and to_string?
Also, a specification of the language would be nice.
The only thing worse than programmers who won't comment their code, is programmers who fail to update the comments when the code changes.
I've recently had some serious hair-pulling moments with a (python) library because all the docstrings talk about the API a year ago, while the code has been under active and non-backwards-compatible development for 12 months.
And worse than those are the ones who update the commented algorithm to match the broken code, instead of fixing the code to do what it was meant to.
At one point, php's socket_read($socket, $n); would return $n bytes, but the docs said it would return $n-1.
So they fixed the code.
Not the docs.
>>45
That really belongs in the "PHP programmers are dumb" thread.
RPG tuku-ru XP is cool.
Ruby exists only for it.
I thought I'd resurrect this thread to bitch a little about Ruby's distinction between methods and funcs (and blocks!).
Most sane languages have functions that inherit from their surrounding environment. You'd think Ruby would do something similar. Consider:
def m1( var )
def m2
var
end
m2()
end
m1( 10 )
That looks like a function inside a function (or a method, if you've drunk too much OO koolaid), right? Very Lisp!
You might reasonable assume that the free variable var in m2() refers to the bound variable var in m2()'s surrounding environment, namely m1(). In other words, if you called m1() with 10, then m2() would return 10, thus m1() would return 10.
In reality what you get is:
NameError: undefined local variable or method `var' for main:Object
from (irb):4:in `m2'
from (irb):7:in `m1'
from (irb):10
from :0
O snap. How about something simpler:
var = 10
def m1
var
end
m1()
What could possible go wrong here?
NameError: undefined local variable or method `var' for main:Object
from (irb):4:in `m1'
from (irb):7
from :0
O shi.
So, this means if I want to do something like no.1 above, I have to use procs:
def m1( var )
m2 = Proc.new {
var
}
m2.call()
end
m1( 10 )
So now we know that methods let you stuff other methods/function/whateverthehellthey'recalled inside them, but without any of the benefits of doing so. In addition, why do I have to do a .call() with a proc anyway? What's wrong with a ()?
Can someone explain to me why methods, procs, and blocks are all different things?
Oh wow, that is a mess. I thought Ruby was supposed to be clean and consistent, but that is just horrible. Between that and 0 being true (and of course the whole thing being really slow, which is what I've been waiting to be resolved before I bother trying), my curiosity about the language is really waning.
PS: from :0!
Oh, it gets better, because I didn't mention how blocks are called.
Method: m1(10)
Proc: m1.call(10)
Block: yield 10
Methods/procs/blocks are just a variation on a theme. Any sane designer would merge all three into the single entity they rightfully should be. The different behaviours (and performance characteristics!) of each of these indicates a fundamental misunderstanding of objects and closures.
Which leads me to conclude that Matz is good at cherry-picking ideas from other languages, but not at synthesizing them. This whole subject is, like, really old news in the PL world.
I'm going to repeat a few things already said here, but I need to bitch about Ruby for a while.
#{}
# is a character solely reserved for commenting. I totally understand the need for using "unique" characters so you can interpolate objects in a string, but find some other characters to do the fucking job. puts "#{foo} - #{bar}, #{moreoffoo}" etc is just dumb.
Incrementals (++ and --)
Someone explained the reason for these not to exist is because in the OO world, an object's incremental increase might not be just "1". Hah? Either way, putting it something that just adds/removes 1 to an object that is a known integer is much nicer than foo +=1 in my loops.
Not so nil
One bad programming habit in other people's code I find pop up is failing to return nil if an error occurs. This means of course, that when I assign the value of an object to a method that causes it, things break only when I try to use the said object, because it has an empty value. Hpricot, is a big one to blame. Acessing a specific element that does not exist in a block of HTML will return "". This result is considered "true", so:
foo = Hpricot(lol_webpage/"div.bullshit".to_s)
Someclass.method(foo) if foo
Will always call the method. I've gotta work around it with Someclass.method(foo) if foo = ''.
> Someone explained the reason for these not to exist is because in the OO world, an object's incremental increase might not be just "1". Hah?
"Hah?" indeed. There is no "1" in "++"! Just have it do whatever incrementing means for that goddamn object! If C++ can do it, why the hell can't you? Or is Ruby one of these gimped languages that don't do operator overloading?
> Can someone explain to me why methods, procs, and blocks are all different things?
For one thing, methods belong to an object and procs and blocks don't. For your examples above, if var were an instance variable it would have worked.
Procs and blocks are almost completely interchangeable though, you can set up methods which accept either without ridiculous trickery.
> Incrementals (++ and --)
> Someone explained the reason for these not to exist is because in the OO world, an object's incremental increase might not be just "1". Hah? Either way, putting it something that just adds/removes 1 to an object that is a known integer is much nicer than foo +=1 in my loops.
Their explanation was wrong. It was almost certainly due to laziness.
Doesn't really matter though, because I haven't yet encountered a need to use ++ in Ruby. You have two better options.
If you want to loop, you have a number of ways... for instance:
>> 1.upto(10) do |i|
?> puts i
>> end
1
2
3
4
5
6
7
8
9
10
If you want to increment a variable for some other reason, personally I use a = a.next.
> Or is Ruby one of these gimped languages that don't do operator overloading?
It can do operator overloading but I'm not sure if you can define brand new ones.
> Their explanation was wrong. It was almost certainly due to laziness.
You might be right. Because all this should require is a language feature which defines that "a++" compiles to "a = a.succ". And therefore any class which implements succ would get it for free.
So no, it isn't just integers, becuase...
>> s = "abc"
=> "abc"
>> s = s.succ
=> "abd"
> It can do operator overloading but I'm not sure if you can define brand new ones.
At the very least you can't do it for ++, without changes to the parser.
> If you want to increment a variable for some other reason, personally I use a = a.next.
That's even LONGER than just writing "a=a+1".
> For one thing, methods belong to an object and procs and blocks don't.
Well, yes, I know. I'm claiming that this is a wholly unsatisfactory situation. I can't think of a reason for the artificial distinction between the three to exist. Ignore Ruby for a moment and ponder the difference (or lack thereof) between an object and a closure.
Ruby is the only mainstream language I've seen with such unusual scoping. No matter how you look at it, this is brain-damaged:
irb(main):001:0> var = 10
=> 10
irb(main):002:0> def m1
irb(main):003:1> var
irb(main):004:1> end
=> nil
irb(main):005:0> m1()
NameError: undefined local variable or method `var' for main:Object
from (irb):3:in `m1'
from (irb):5
from :0
That Hpricot example is pretty stupid since nil.to_s always returns an empty string.
And someone already mentioned this, but if you're using incrementals for your loops, you're doing it wrong.
Loops are hardly the only place one would use incrementals.
51 mentioned loops specifically. For other uses I prefer += 1 anyway.
Okay, is there is damned good reason why pipes in regex don't work in sub() and only in gsub? For example...
irb(main):001:0> foo = '">29,000'
=> "\">29,000"
irb(main):002:0> bar = foo.match(/">(.*)$/).to_s.gsub(/">|,/, '')
=> "29000"
irb(main):003:0> bar = foo.match(/">(.*)$/).to_s.sub(/">|,/, '')
=> "29,000"
They work fine.
irb(main):002:0> bar = foo.match(/">(.*)$/).to_s.sub(/">|,/, '').sub(/">|,/, '')
=> "29000"
Objective-C, Fuck yea!
All right. I've been meaning to post this for a while, so:
Today's Q (and A?)
I don't like how Ruby handles optional arguments. Let's first take a look at a language that does it decently:
>>> def x(a = 1, b = 2):
... return a * b
...
>>> x()
2
>>> x(a = 2)
4
>>> x(b = 3)
3
>>> x(2, 3)
6
>>> x(b = 3, a = 1)
3
So, let's take a look at the above. I can pass any optional parameter, and I can do it in any order. If I pass it in proper order I don't even need to include the names. Makes sense, right? Let's try that with Ruby:
001:0> def x( a = 1, b = 2 )
002:1> a * b
003:1> end
=> nil
004:0> x()
=> 2
005:0> x( a = 2 )
=> 4
006:0> x( b = 3 )
=> 6
Whoa. How does that last one work? 1 * 3 = 3, not 6!
Ruby's "optional" parameters are positional. So what's happening above is that Ruby is creating a new variable at the call site (e.g.: the a in x(a = 2)), assigning an object to it (the 2), and then returning the result of the expression (the same object: 2) which is then used as the argument to x().
Thanks to Ruby foolishly not having borrowed Perl's great idea of lexical scoping with strict mode, I'm sure any number of Ruby neophytes have been left scratching their heads. As an aside I'll just add that all dynamically-typed languages should borrow that idea, but it seems some language communities are too busy feeling smug and superior, and they completely miss an a lot of gems hidden inside Perl's terrifying exterior. If I had to write something big in a dynamically-typed language today, I'd reach for Perl first, and the above is only one of the reasons.
To continue: optional parameters that are only positional are quite anemic. In fact, their only real use is if you need a quick refactor of a method to add some extra functionality without breaking old code -- if the signature doesn't already include an optional parameter on the end, you can just tack one on. Of course, that doesn't scale at all, because it's impossible to give an optional parameter in the 5th position if the 4th is also optional, unless you also pass the 4th as well. This is brain-damaged, so you're up the creek if you want more than one optional parameter, bub.
How do you really do it in Ruby? Apparently like this:
001:0> def x( options = {} )
002:1> a = options[ :a ] || 1
003:1> b = options[ :b ] || 2
004:1> a * b
005:1> end
=> nil
006:0> x()
=> 2
007:0> x( :a => 2 )
=> 4
008:0> x( :b => 3 )
=> 3
009:0> x( 2, 3 )
ArgumentError: wrong number of arguments (2 for 1)
from (irb):9:in `x'
from (irb):9
from :0
Whoops. I guess once you start down that path, you have to use :a and/or :b symbols every time you want to pass an argument; no more positional shortcuts, which Python allows. So now we have a more verbose hash with required unpacking inside the method -- an idea Ruby shouldn't have borrowed from Perl -- and the call site is likewise a bit longer.
Does anyone who has better familiarity with Ruby know a less ugly way to do this? I'd prefer it to have named optional parameters which are also positional, but I'll settle for anything less.
Anybody reading this thread might be convinced I detest Ruby.
But that ain't so!
So I'll share one feature of Ruby I wish I saw in more languages: ||=
||= is a cute little feature that checks whether a variable is nil, and assigns what's on the right-hand side if it is. So things like this:
if x
x += [ y ]
else
x = [ y ]
end
...can become this:
x ||= []
x += [ y ]
Five lines into two, and I suspect the latter is also a tad faster. I find myself often using things like "@@var ||= <x>" when caching the results of some expensive operation that's needed in a frequently-invoked method, and while the above example might seem a big usual (why not just x = [] before a loop?), I seem to get it a lot when processing arrays that contain arrays.
I cannot emphasize how much I like the ||= operator. It's a small thing, but oooooh aaaaaah. Now I just wish there were things like ||+= et alia...
This is what happens when you don't preview. D:
>>64
perl has ||=
and //=
...
I've never seen it. Is that Perl6?
What's the difference between the two?
Perl has always had things like $param=$query->param("name") || "default"
. ||=
is just the usual operator shorthand.
>>63
What is so wrong about passing arguments in the order you specified in your own methods? Surely it requires slightly more memory (in your head), but it's not difficult to remember unless you have a vast list of arguments, in which case I think it's neater to use a hash anyway.
Furthermore, Ruby's way of handling it can be looked at as very useful useful. One might want to create a new variable and pass it as an argument at the same time.
> What is so wrong about passing arguments in the order you specified in your own methods?
Nothing, provided it's also possible to name them. If you can't, like with Ruby, there's a problem. Consider the following:
def arg(optional1 = x, optional2 = y, optional3 = z)
Now, how do I pass only optional3 to arg()?
It seems I can't. I have to pass optional1 and optional2 as well, which increases coupling. This behaviour removes what I consider the greatest benefit of optional arguments in the first place, and for no gain.
Ruby's hashes are an unwieldy and quite verbose way to circumvent this.
> One might want to create a new variable and pass it as an argument at the same time.
That's rare. When you need it... use a hash, either explicitly or like Python does with its varargs.
Python's argument passing leaves something to be desired too, but that's a different story.
I can see where you're coming from.
I don't know what to say since I've never run into that problem in particular where a hash wasn't more suitable. Then again, I've never run into a situation where I wanted to create and pass a variable simultaneously, but I still like the idea and imagine either would be useful in the right context. It would be great if both worked, IMO, although I'm not sure what that would look like syntactically.
It might look like Python, although I think it's also not ideal:
>>> def fun(arg1, arg2=3, arg3=7, **kwargs):
... print arg1, arg2, arg3,
...
... for name in kwargs:
... print kwargs[name],
...
>>> fun(1)
1 3 7
>>> fun(1, 2, 3)
1 2 3
>>> fun(1, arg3=5)
1 3 5
>>> fun(1, arg4=21)
1 3 7 21
>>> fun(1, woo=1, hoo=2, looky=3, here=4)
1 3 7 2 1 4 3
arg1 is a required argument. arg2 and arg3 are optional. *args is a dictionary (read: a hash) that catches overflow arguments (an example being the use of arg4=21).
In case you're wondering what happened to the ordering of the last four digits in the last example, that's because dictionaries aren't ordered.
Also, while I've never made use of keyword arguments in Python, I saw a plethora of them in other people's code where I last worked.
A few monthes ago I gave a look to Ruby, because I wanted to give a try to RoR. I felt the syntax being really exciting. What made me give it up is the fact that the interpreter is, for now, very slow for me. So when Ruby have a fast interpreter I'll be happy to dive in it again :)
For now I'm sticking on Lua and Squeak/Smalltalk.
Happy coding,
Fred
Lua is a nice piece of software. I'm actually quite impressed by it, both as a language and as an implementation. Then there's LuaJIT which also adds support for coroutines across C function calls.
It's a bit unfortunate there isn't any MVC or routing in the Kepler project yet, otherwise I'd seriously consider using Lua for webdev. There are a couple projects I'd like to do that could use a fast interpreter.
Wait. Wasn't lua the language with the extreme script language focus? To the point where it would parse floating-point literals according to locale? So that if you were, say, running a German locale, floats would have to be written as "5,67".
I just heard this rumour about Lua 5.0. That was a while ago, of course.
You mean Lua 5,0.
I don't think that's true.
I haven't seen anything like that either.
It'd probably conflict with the rest of the grammar.
Lua seem far too streamlined to bother implementing anything like that.
The main people anyone likes Lua is that it's fast.
But if it's really so fast, people would just write a Ruby to Lua compiler. Then your Ruby app still looks good but runs as fast as a Lua script. Everybody wins!
It doesn't work that way. The Lua VM is targeted quite specifically to the semantics of the Lua language.
You could come up with bytecode that'd emulate Ruby behaviour, but it'd be slower. For example, Lua's strings are immutable, in part due to the hashing and sharing that goes on underneath. Ruby's strings are mutable. Emulating mutable strings with immutable ones will impose significant overhead.
Also, I think that Lua is -- purely as a language -- superior to Ruby. Ruby contains all sorts of strange design decisions which make me believe that Matz was (hopefully he's better now) a haphazard cherry-picker who wasn't very good at synthesizing ideas. There are a number of good ideas in Smalltalk and Perl he never used, and a few half-assed implementations of those he did.
By comparison Lua's syntax is quite simple, it has proper lexical scoping and closures, and those tables are amazingly versatile -- they're used for arrays, lists, hashes, sets, even objects and modules.
However, it doesn't look like Lua will be leaving its stronghold as an embedded language, which limits its usefulness as a general-purpose language. It doesn't have regular expressions, standard and external libraries are limited, support for Unicode doesn't extend much beyond 8-bit clean strings (to be fair, the same problem with Ruby), there is no bignum support, there are no bitwise operators... and so on.
otoh, lua differentiates between statements and values - even though they're syntactically unambiguous. this makes using the lua repl obnoxious and verbose. lua's debugger is run-time-only and is useless for incremental development- which seems to me to be the best possible and imaginable use of a "scripting" language.
finally, lua changes the C-visible API incompatibly in minor versions making lua a moving target.
They don't release so-called "minor" versions too often, though.
RoR is overrated. Django is much better IMHO.
>>85
Don't leave us dangling. Elaborate.
Django fails largely due to the language it is implemented on.
Guys, guys, you've got it all wrong; Ruby is a goddamn fucking blast! Ruby is the best!
I really think Ruby does some awkward shit, like the things dmpk2k has been discussing, but I have to use PHP at work and I'd much rather be using Ruby.
I'd be interested in ruby if there was less hype. Sounds odd, but the WEB TWO-POINT_OHHH bullshit ruined it for me.
>>90
i've been doing php at work and i'd prefer to use brainfuck.
What you'd prefer over php doesn't say much about it.
plugs ears Can't hear you guys, I'm having too much fun programming Ruby.
>>86
Very fast (No need to rewrite shit in C if your site becomes popular) because of Psyco JIT and some awesome new caching features that have been recently added, much more extensible (If it's written in Python, you can easily find a way to incorporate it), top notch FREE documentation at the official site (Instead of "BUY THE BOOK, LOL")
Defining your model in Python then auto-generating the SQL vs auto-generating a model based of the given SQL in Ruby I guess up to personal preference, though beginners would find it much easier to go with the former. There isn't much you can't do in Django database wise, if you absolutely have to do something really tricky you still easily use your own SQL code.
Also using generic view functions seems a lot more sensible and maintainable instead of dumping scaffolding code everywhere. Django lets you define your own URL structure based on Regexes, where as Ruby forces you name your structure after your functions.
Python vs Ruby is a whole other argument, however for me the clear and readable syntax of Python makes reading, writing and maintaining code very easy. I can understand why existing MASTER PERL/LISP PROGRAMMERS would want to use all the funky features of Ruby though.
They're both excellent frameworks, though RoR gets much more and Django much less hype then they deserve IMHO.
> because of Psyco JIT and some awesome new caching features
I've noted the caching in Django, which is one reason why I'm more interested in it compared to, say, Pylons.
Psyco JIT is a bit of a joke for webdev though. While it's great in some other scenarios, I highly doubt it makes more than a few percent difference in a web app. I once used it to try and speed up a non-trivial Zope3 application, and the difference was less than 10%.
> auto-generating a model based of the given SQL in Ruby
There's no SQL in a migration unless you're doing something the ORM doesn't handle by default (some of which are unfortunately pretty basic things to be missing). I presume you're saying that you don't even need a migration?
> Also using generic view functions seems a lot more sensible and maintainable instead of dumping scaffolding code everywhere.
Could you elaborate a bit on this?
f(x = 5 + 6)
puts x # prints 11
Is there honestly a good reason Ruby allows this?
x=5+6 is just an expression- like any other. It isn't a named parameter, if that's what is confusing you.
A lot of the performance problems people have with scripting languages are at startup time too, which is also practically irrelevant for web applications (or any other long-running application.)
Ruby is like this too, the Rails console takes quite some time to start up (I guess it has to load Ruby, a portion of the stdlib, then Rails dependencies, then the app...) but the web application starts when you start the web server and each request is plenty fast enough.
>>94
Dumping scaffolding code everywhere? I take it you mean the ONE LINE OF CODE you put in the controller in order for it to magically work without creating even a single view or a single controller method. Generating scaffold files is optional, and something you do only if you want to modify it somehow.
>>96
Because others do? Personally I find it messy but this sort of chaining has been useful in the past.
No need to tell me. 18 months of Zope3 has left me with deep loathing for anything related to it. I'm still having trouble going near Python because of memories of Zope.
http://mail.python.org/pipermail/python-dev/2003-May/035727.html
You're doing it wrong. Eliminate your startup by only doing it once- dump core, and unexec the result.
I think you guys are all forgetting Ruby's fun factor here.
>>102 has a good point, this was a common trick back when people were complaining about Perl being slow.
Of course I don't know about it being very cross-platform.
Let's talk Ruby's blocks, since they're a feature that is routinely brought up as a point in Ruby's favour. Since the rest of Ruby has broken lexical scoping and no first-class functionsmethods -- a rant for another day if someone asks -- blocks are Ruby's claim to fame.
Ruby borrowed the idea of blocks from Smalltalk. That was probably a good idea. Unfortunately, like almost everything else in Ruby, they're half baked.
First up, lexical scoping. Blocks come pretty close to behaving as they should here. Just one problem:
y = 0
[ 'o shi' ].map { |y| puts y } => 'o shi'
puts y => 'o shi' (should be 0)
Given that the argument to the block, y, is in a different scope to the y outside, you'd expect that after this chunk of code is executed, y would still be 0. No, it's 'o shi'. So arguments to a block stomp all over variables in outer scopes.
The next (much smaller) problem is that blocks are not first-class objects:
x = { |y| }
SyntaxError: compile error
(irb):1: syntax error, unexpected '|', expecting '}'
x = { |y| }
^
from (irb):1
Nope.
In Smalltalk they were first-class objects, but in Ruby procs are. One consequence is that there's no way to pass multiple blocks to a method short of converting them to procs first. Why the nuance? Who knows!
(I suspect it's partly because Ruby's grammar is foobar and uses {} for both blocks and hashes. The more worrisome part is that the performance characteristics are substantially different, which possibly hints at different means of implementation.)
See >>50 for another reason why I am not in favour of this in Ruby. If you want an example of a language that has the whole lexical scoping and first-class everything right, see Lua.
Another annoyance. This is a constant:
VAR = 0
Constants shouldn't change, right?
VAR += 1
(irb):2: warning: already initialized constant VAR
...okay, so you can change it, but there's a warning. Livable, I suppose. But what if it's not a scalar?
VAR = []
VAR.push 1 => VAR now equals [1]
Alas, this little stupidity means I can't do things like the following, since they're all now pointing to -- and can mutate -- the same object:
DEFAULT = [ 0, 0, 0, 0 ]
var1 = DEFAULT
var2 = DEFAULT
var1[0] = 1 => var2 is now -also- equal to [ 1, 0, 0, 0 ]
There are a few alternatives, two being: use .freeze() on the array when assigning to DEFAULT, or use .dup() when assigning to var1 or var2. The problem with freezing the array is that I can no longer mutate var1 or var2 since they're pointing to DEFAULT's frozen array; this defeats the purpose of creating DEFAULT. dup() has its own problems, for example:
DEFAULT = [ [0, 0, 0], [0, 0, 0] ]
var1 = DEFAULT.dup
var1[0][0] = 1
Guess what that does?
There are a number of ways around this. The one I've settled on for now is to create a method named DEFAULT() that returns a new copy of what I want. E.g.:
def DEFAULT
[ 0, 0, 0, 0 ]
end
var1 = DEFAULT()
Nevertheless, Ruby's constants aren't really constant for anything beyond a scalar.
This and a couple other experiences have finally given me an opinion on implicit pass-by-reference semantics: they're a pain. Perl and C have the right idea: the semantics are pass-by-value; if you want a reference or pointer, you know how to get it.
(NB: those of you who want to argue about passing large structures with pass-by-value semantics please see what OS's have been doing for decades: copy on write.)
Yep, this is an issue with other languages too. Java, for instance, has no real notion of a constant either. Instead, you have statics, and as long as you put immutable objects in there then you're okay. Same workaround in Ruby, put an immutable object there instead of an array.
>>107 Neither did Fortran:
CALL FUN(41)
WRITE (10,1) 5
1 FORMAT (I5)
END
SUBROUTINE FUN (I)
I = I + 1
END