Apparently there's nothing you can do in RubyLanguage that you can't do in SmalltalkLanguage, and there's all these things you can do in Smalltalk, that you can't do in Ruby: * this list * to be filled out * by smalltalk bigots^H^H^H^H^H experts So therefore, we can only conclude that we must stop using Ruby to do whatever it was we were doing, and start doing it in Smalltalk instead. SmugSmalltalkWeenies consider just about all of the purported advantages listed in RubyInsteadOfSmalltalk to be ''disadvantages''. ---- From RichardKulisz Allow me to further explain why Ruby has many advantages over Smalltalk in the meta-object department. This example is contrived, but directly relates to the above "ActiveRecord" example. It is also a very famous example that I did not author, called Dwemthy's Array (you can find the original information at http://mislav.uniqpath.com/poignant-guide/dwemthy/ ). When we're making classes, sometimes we realize that we're making something that lots of people are going to subclass a lot. In prototyping languages, we'd say we're making a prototype that will often be copied and modified, like the I/O prototypes. In these cases, it's usually easy to say why people would want to subclass. "Oh, they'd want to play with the buffering" or "Oh, they'd be changing some constants and probably defining some new relations." How about in a game? We make a Monster class, and in the game Monsters can have lots of different variations on their statistics. What we'd like to be able to do is provide them with a lisp-like meta-language to make monsters quickly. We want the developers to care more about the game than the arcane internals of our complex realtime monster class (now with Uber-AI!) What we'd like to see, is something like this: class Dragon < Creature life 1340 strength 451 charisma 1020 weapon 939 end What we're saying is that you could make new Dragons, and they'd have those stats. Our intrepid heroes could battle each dragon individually, and we could spawn many more as needed. But, what if we had something more exotic, like our heroes? Heroes tend to be weaker, but have lots of special moves. Our rabbit-hero has bombs. So we'd want to be able to mention this so our Game's OS will note it, and keep track of it for us: class Rabbit < Creature traits :bombs life 10 strength 2 charisma 44 weapon 4 bombs 3 ... end Note that these are simply Ruby classes. You can add methods below (or inbetween) if you see fit. What we've done is built a DomainSpecificLanguage just for gaming. And, we've built it in a totally OO fashion, and without us worrying about what bucket these traits go into. Note how we even used one method, "traits" to extend the class's meta language ''as we were defining it!'' It's this meta-object editing that makes Ruby such an awesome OO language. DomainSpecificLanguage''''''s were one of the major draws of Lisp, but it was something that Smalltalk only supported in the most limited of fashions with blocks. Ruby picks up where Smalltalk left off and carries the ball and brings in the touchdown. -- DaveFayram ''(Where it found Lisp waiting to greet it in the end zone. :) -- DanMuller (Indeed. -- DaveFayram))'' ''I think a few smalltalkers might disagree with that assertion. Smalltalk does DSL's better than Ruby, Smalltalk does it so well that there's no need for special keywords in the language like "if/for/while", Ruby can't make that claim, if Ruby's object system and limited version of blocks are so good, why can't they model predicate logic as messages to objects rather than magic keywords? I'll tell you why, because Ruby can't cleanly pass more than one block to a method, and that seriously limits it's capabilities in comparison with Smalltalk blocks, which are much better. Why have the class keyword, why not do class declaration as a message send to an object.'' class Rabbit < Creature end ''would be a simple message send in Smalltalk'' Creature subclass: #Rabbit ''Ruby is elegant in comparison to Java, but it has a long way to go before it can touch Smalltalk, Ruby is still SmalltalkMinusMinus imho.'' ''RamonLeon'' --- ''Challenge to Smalltalk advocates: go ahead and reimplement DwemthysArray then! The Array is a rather short program so it shouldn't take you too long. It's also rather well known, even celebrated, by now so a ST version will reach many people who wouldn't normally even notice ST advocacy. And an elegant implementation will frankly be a lot more convincing than "sure, we could do that" assertions. We've been promised Smalltalk DWEMTHY before: http://redhanded.hobix.com/inspect/theRabbitWillDieInSmalltalk.html - who will deliver?'' -- May 2008 update - we now have a contender: http://softwareengineering.vazexqi.com/2008/05/28/dwemthys-array-in-smalltalk.html If you're ''desparate'' to create classes with a message in Ruby, it turns out that the following will give you the ability: class Object def self.subclass name eval "class #{name} < #{self}; end" end end The Smalltalk example above then translates to: Creature.subclass :Rabbit But I'm not sure exactly what this buys you. I guess in ST, the Creature class responds to the subclass message by opening an editor in the environment (don't have an ST env to hand to verify this), but there's no analogue in the Ruby world, so you'd probably be better off declaring classes idiomatically. *I think the point was that, in Smalltalk, you don't need language constructs to define classes. In Ruby, defining classes uses special syntax. Yes, you can write a wrapper that allows you to do it using normal syntax, but then that wrapper still has to use the special syntax. In other words: you need the special syntax one way or another. This makes Smalltalk the more elegant language, and I think that's a general trend: Smalltalk is more elegant, whereas Ruby is closer to mainstream languages, and thus easier to learn for many people. --- Actually, there is a nicer way to do this in Ruby then #eval: A = Class.new(Object) A.class_eval do #class body as code, not string end This is equivalent to class name < superclass. Playing with #const_set and #const_get you can mimic the ST-Style quite well. This is a rough implementation for illustration: class Object def self.subclass const_name = nil, &block c = Class.new(self); c.class_eval &block const_name ? self.const_set(const_name, c) : c end end c = Object.subclass(:Rabbit) def name "Roger" #the only true rabbit... end end c.name It is easy to extend this for almost all you needs. --FlorianGilcher ---- ''...because Ruby can't cleanly pass more than one block to a method...'' We are to assume this phrase hinges on the word cleanly, thus the following fails as a counterexample? def with_blocks x, y, a, b a.call x b.call a, y end with_blocks :x, :y, proc { |x| puts "a: #{x}" }, proc { |a, y| puts "b: #{y}"; a.call y } ''Yeah, that really is quite ugly. I can tell that much even without being able to tell what it does. Could you provide a Smalltalk version here?'' * ''Here's how to define and call a method with two blocks'' "Define the method" Some''''''Object>>doSomethingUsingBlock: oneBlock andAnotherBlock: anotherBlock oneBlock value. anotherBlock value. "Call the method (on an instance of Some''''''Object)" aSomeObject doSomethingUsingBlock: [self foobar] andAnotherBlock: [self zeetix] * ''For example, True and False are each singleton classes descending from Boolean. They each implement conditionals like the following: True>>ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock ^trueAlternativeBlock value False>>ifTrue: trueAlternativeBlock ifFalse: falseAlternativeBlock ^falseAlternativeBlock value "Calling ..." aBoolean ifTrue:[Transcript show: 'True'] ifFalse: [Transcript show: 'False'] -- TomStambaugh ---- I can get pretty close to the ST example... class Bool def initialize cond @cond = cond end def if_true &block if @cond block.call end self end def if_false &block if !@cond block.call end self end end b = Bool.new(true) b.if_true { puts 'true'}.if_false { puts 'false' } Maybe we don't need to pass more than one block into a function after all... ''This doesn't match the Smalltalk example because you're throwing away the return values of the procs:'' myValue := aBool ifTrue: [1] ifFalse: [2] -- FrankShearar ---- OK, here's a stab at your Some''''''Object example. Mine doesn't have a zeetix method, though - I'll leave that as an exercise for the reader (I just threw in a block for variety). This example is leveraging a hash to do most of the work though, and the end result ends up looking somewhat like Perl! I guess the Smalltalk example is freer of syntactic noise, although I'm not immediately clear where 'value' is passed in in the Smalltalk. class Some''''''Object def with_blocks args args[:some_block].call args[:value] args[:another_block].call args[:value] end def foobar args result = "" args.each { |a| result += "#{a} " } puts "foobar: #{result}" end end obj = Some''''''Object.new obj.with_blocks({ :some_block => obj.method(:foobar), :another_block => proc { |args| puts "#{args.size} things." }, :value => [1, 2, 3, 4, 'Jon'] }) ---- Consider the following: def make_class name eval "class #{name}; end" end How would you go about doing the same thing in Smalltalk? (Please don't infer that that above code is in any way useful, I'm just intregued as to what the equivelent Smalltalk would look like...) ''I'm guessing that's a method that takes one argument, a string, and creates a class of that name.'' Broadly yes - it's a method that takes an argument which is either a String, or an object which responds to to_s with a String. But I am being pedantic, so please ignore me. subclass: aString ^self subclass: aString asSymbol instanceVariableNames: '' classVariableNames: '' poolDictionaries: ''. ''subclass:instance... is the method the browser uses to create classes.'' ''Now, if you want it to produce a string including ST code which the compiler gets to process then,'' subclass: aString ^('^self subclass: ', aString asSymbol printString, ' instanceVariableNames: '''''' classVariableNames: '''''' poolDictionaries: ''''''.') evaluate '' Actually, you'd probably use expandMacros somehow.'' The first example I'm guessing is closer to the SmalltalkWay, and the first 2 lines make sense to me. But what's all this ''instanceVariablenames'', ''classVariableNames'', ''poolDictionaries'' gubbins? Are they strictly necessary? Would: subclass: aString ^super subclass: aString asSymbol. not work? And be closer to the ruby example? It would certainly seem more elegant than my ruby example (unless there is a more RubyWay to do it). ''There's no message "subclass:" because nobody in the Smalltalk world ever, but ever, makes subclasses in code. They make subclasses in the IDE and even the lamest browser will provide you with a template that you can just edit and accept. You never have to bother with classVariables and poolDictionaries unless you know what you're doing, and instance variables are easily specified. In the case of Dolphin, the browser provides you with a template that would recreate the class you've currently got selected if you aren't examining a method in that class.'' * ''Sorry, but the claim that "nobody ... ever, but ever, makes subclasses in code" is utterly false. Subclasses are created quite frequently and -- by the way -- the "IDE" is itself written in Smalltalk. -- TomStambaugh'' Can you provide some concrete examples, aside from the Creature example above, where you'd programmatically create classes? Because I've yet to encounter a single one so it seems strange to hear you say it's done "quite frequently". -- RK * ''One example of creating classes dynamically is described in http://st-www.cs.uiuc.edu/users/hanmer/PLoP-97/Proceedings/lyardet.pdf, "The Dynamic Template Pattern". The literature has many similar references. -- TomStambaugh'' Well, that explains how it's done. Which is not exactly, or at all frankly, what I asked for since I already knew that Smalltalk and Self could implement each other and the dynamic template pattern is just Smalltalk emulating Self (and ugly it is too). Now, can you provide some actual examples of anyone ''using'' it? Say, from your own working experience? -- RK * ''The creation messages themselves are on Class. The selectors are #subclass:classInstanceVariableNames:instanceVariableNames:classVariableNames:poolDictionaries: and subclass:instanceVariableNames:classVariableNames:poolDictionaries:. No, I'm not going to provide code -- because it's long, tedious, and this argument isn't worth it. I did an investor demo for a business process re-engineering company. The product was an application that supported the creation and assembly of networks of various sorts of business process entities. Those entities were placed on a drawing surface, given behavior, and the resulting network used to simulate and draw conclusions about the process being modeled. The user created their own entities, yet the system had to work as a "packaged" image -- no compiler or development tools. Hence, each entity was a new (and very carefully constructed) class that was then instantiated into the drawing surface. A different genre is doing relational/object mapping (and the query generation that goes along with it). Degenerate classes were constructed on the fly, with a single dictionary to hold their state. Properties and various accessors (read and write) are generated from queries and vice versa. In some cases, a "record class" is created automatically and dynamically, which holds the literal contents of a row coming back from or going to the DB. Other dynamically generated classes then delegate to it to store state. Dynamic classes are an important tool in the kit that every practicing Smalltalker should bring to an engagement. -- TomStambaugh'' ---- Here's an (almost) RealWorld example which I think shows one of Ruby's strengths. It's a messaging system. There are three main components, an Address class, a Listener module and a Dispatcher module. The Address class is as follows, each address holds a path object, an array of child Addresses, and an array of Listeners. The path value is interpreted as a string of the form '/a/b' where adding the Address '/a/b' would also create '/a' if it didn't exist, and add '/a/b' as a child of '/a' (and '/a' as a child of '/'). This is a skeleton (i've stripped out most of the implementation, as it's not essential to my point): class Address def self.get path #return address object for path or nil end def self.add path #register an address object for path and return it end def add_child child @child.push child end def add_listener listener @listener.push listener end def each_listener @listener.each { |l| yield l } end def each yield self each_child { |c| yield c } end def each_child @child.each { |c0| c0.each { |c1| yield c1 } } end end Now, as the Address class is doing most of the work, the two modules are pretty simple: module Listener def listen addr a = Address.add addr if a a.add_listener self end nil end end module Dispatcher def broadcast addr, *args a0 = Address.get addr if a0 a0.each { |a1| a1.each_listener { |l| if l != self l.receive *args end } } end nil end end now, if you want to create an object which can both listen for messages and dispatch them, you'd need something like the following (this is why I implemented Listener and Dispatcher as modules rather than classes): class Test include Listener include Dispatcher def receive *args #handle message (*args) here end end Two includes, and one method implementation. That's it. My object can now listen and broadcast as it pleases. t = Test.new t.listen '/some/address' t.boadcast '/', :some_message Maybe I'm easily impressed, but I think that's pretty elegant. ''Yes, mixins are Ruby's coolest feature, good enough that Smalltalk has already stolen the concept, improved upon it, and called em Traits. Traits are mixins, without the dependencies on the order of inclusion that Ruby's mixins have, so they are more well behaved. It's also a good example of why Smalltalk is superior, there's not much you could think up that you couldn't simply add to Smalltalk, implemented in Smalltalk. If Ruby didn't have traits, I don't think you could add traits by hacking a litte Ruby, especially since much of Ruby is implemented not in Ruby, but in C. Smalltalk is a language that can grow into anything you need it to be, to an extent far greater than Ruby. Ruby looks cool as hell, if you're coming from Java or CSharp or some such popular language, but if you look at Ruby from a Smalltalk or Lisp perspective, it's a step down.'' Traits/mixins could be implemented in pure Ruby easily enough. Ruby, like Smalltalk, provides sufficient runtime reflection and metaprogramming capabilities to perform namespace manipulation without resorting to C extensions. It's the reflection and metaprogramming stuff that makes Smalltalk so flexible. The implementation language of the VM is a relatively minor detail. ''That's not saying Ruby is bad or anything, but if you like Ruby, or find it impressive, then take another step up, and try Smalltalk, you'll like it better, especially when you realize how poor Ruby's tools are in comparison. If you think Ruby is impressive, then Smalltalk will blow your mind, hell, Ruby still uses files, how object oriented is that? Live in a Smalltalk image for a while, you'll realize how primitive files are, you'll realize how awesome it is to live in a world of pure living objects in a virtual environment, where you can prototype freely with no need of a database to store your objects. Where you can change a running program, change the implementation of a class while looking at a live instance of it. Ruby on rails is only impressive if you still think you need a database for rapid prototypes. Ruby is a great language, but it's not in Smalltalk's league, not yet. Smalltalk's had 30+ years of some of the most brilliant minds working on it, Ruby's a new kid on the block, it needs time to mature before it's ready to take on Smalltalk.'' *"hell, Ruby still uses files". Hey! I like my files (PowerOfPlainText). I can get started with Ruby just by installing the interpreter and some modules, which sets me back a couple of megabytes, and start coding away with my favorite editor. There's no need to get some fancy development enviroment that is going to require me to put more RAM in my computer and take me several days to learn. ** ''Ohhh, several days... oh the pain.'' *I tried writing Smalltalk with my favorite text editor, and the first thing I had to do was create a new method so that I could subclass without having to include the poolDictionaries: and other things when I don't want to do anything with them. Eventually I got tired of the long message names and went back to coding in Ruby. IMO, coding Smalltalk with a text editor is tedious, whereas the supposedly superior way imposes a steep learning curve. Regardless of how great it is once you've climbed the curve, it does pose a barrier to adoption. ** ''Writing Smalltalk in a text editor is like cutting grass with nail clippers, sure it works, but it misses entirely the point that Smalltalk is much more than just a language, it's an environment, you must use its tools to see the benifit. If you can't spend a couple days to learn a superior environment, then stick with Ruby, nothing wrong with using old fashioned stuff.'' *** See, that's the thing. You MUST use the tools to see the benefit. Why? Why not make the language such that it can be comfortably programmed using a text editor? It's not like you'd have to forego the great development environments. For example, Lisp can be comfortably programmed using a text editor, but many implementations allow you to work on live images, and there at least used to be great development environments for it. *** Another point I would like to make here is that TheIntegratedDevelopmentEnviromentIsNotTheLanguage. Even horrible languages can have IDEs written for them that are easy to program in. To give some examples: when I complained to someone that checked exceptions can force you to change a lot of methods in a very repetitive way, that someone told me: "Huh? Doesn't your IDE take care of that?" To me, that's working around a flaw in the language. The same holds for Smalltalkers using their IDE to spit out the object instantiation mantra. It's not a feature, it's a flaw. In my opinion, of course. It *is* awesome to live in a world of pure objects, but that's not the world most of us live in. The Smalltalk image is fantastic, but Ruby's traditional file-based approach lends it better integration with the rest of the world. It's a tradeoff, and I think the Ruby developers made the right choice given the application domain and environments for which Ruby is intended. ''"better integration with the rest of the world" does not make something better, the rest of the world is wrong, image based development "is" better, one day the world will come to Smalltalk, it's been slowly creeping towards Smalltalk for years, Ruby is proof of that, it's Smalltalk, minus some of the better features of Smalltalk.'' * The rest of the world isn't wrong, it's just unenlightened. And smalltalkers themselves are the reason for this. The smalltalk image orientation is the prime for the language's failure. Narcissistically obsessed with their image, smalltalkers retreated into it leaving the rest of the world behind. If the image was so cool it should have been subclassable and subclassed as files, sockets, fonts, kernels, shells, pipes and all the other OS primitives. Just reimplement them as classes and expose them like any other dynamic language. Whether by failure of vision or simple bigotry the smalltalkers prefer to disappear up their own wazoo, leaving the rest of us non-plussed by their passing. My hypothesis would be that if the rest of the world is going to end up using Smalltalk, it's probably precisely because of languages such as Ruby that they'll find the jump to Smalltalk that little bit easier than it would have otherwise been. ''I agree completely.'' ''In my view, there is an emerging world of totally cool things that tools like Smalltalk, Lisp, perhaps Ruby (I'm unfamiliar with it, and so rely on the opinions of others), and similar languages/environments let me experience more directly. I can get there with Perl and, to a lessor extent, Java, but there's a lot more noise. Python impresses me. The tool is '''not''' the point, though, it's the cool things revealed by the tool. I gladly use anything that lets me live and work in the new world. For too long, Smalltalk was the only game in town. Now, thankfully, Javascript and Python let me get there as well and don't face the market resistance that continues to plague Smalltalk. It doesn't matter to me '''how''' the rest of the programming community gets there or what language they use. Many of these concepts are difficult, their implications subtle and surprising, and I find that my experience in working with them for many years (even in Smalltalk) helps a great deal with those new developers just getting to them through Ruby or Python. To the newcomers, I say "welcome aboard" -- and the language doesn't matter. -- TomStambaugh'' ---- I found this site by asking the very question What does Ruby do that Smalltalk doesn't. (http://www.google.com/search?ie=utf8&oe=utf8&q=what+does+ruby+do+that+smalltalk+doesn%27t). I learnt Smalltalk quite late in my software engineering career and I can see why it's used in education, and also why it has some very vocal supporters. Simply put it has a simplicity and elegance that is unmatched by any language prior or since. Many other languages have borrowed ideas from it. Recently I've had enough time to begin learning Ruby something there is currently a lot of buzz about, I've read enough about it in a couple of days to ask that question. It seems to me that there isn't anything. You see, Smalltalk doesn't have to impress Ruby followers - it came first. To offer anything to one who knows Smalltalk it must improve upon it. Of course anyone moving to either language from say C++ or C# (proof that new does not equal good) will be getting a breath of fresh air. I love Smalltalk, but back in the real world of software development almost no-one uses it. It is a better language from a purist point of view but now a Cocoa-Ruby bridge is part of Mac OS X development tools real desktop applications can be created in something a little closer to the language I love. Objective-C is damn good, but it isn't Smalltalk. Ruby is a step closer. So I say that while Smalltalk is closer to an ideal, a pragmatist will choose Ruby. Aside from that main point I think a possible reason for the Ruby people to not 'get' the image based approach of Smalltalk is that right now Smalltalk VMs exist only inside another host OS, one that is usually file based. It might help to imagine a computer where the operating environment is Smalltalk. Replace the idea of your hard disc with the image. You don't save files, but objects. How liberating! But Smalltalk is not really a language, it's an environment. The language is inseparable from the rest. The parts just don't make sense without each other. So by taking ideas from just the language part and disregarding the rest Ruby will only ever be a side step at best. --Tim Bedford ---- If keywords ("special language constructs") are bad, then Ruby is better than Smalltalk in one way: Ruby doesn't require a keyword to return a value from a method: def foo 'foo' end whereas Smalltalk would require ^'foo'. ---- If at all, then R''''''ubyIsSmalltalkMinusMinusPlusPlusMinusMinus because in that way you can probably reach any language from any other. See LanguagePlusPlusMinusMinus. ---- WikiNow. See RubyInsteadOfSmalltalk for a contrasting view. CategoryProgrammingLanguage