From: Christian Szegedy Date: 2001-05-15T22:26:59+09:00 Subject: [ruby-talk:15160] Re: Discussion on new Ruby features Sorry, I don't know how to reply to this list, so my replay will probably create a new thread. Michael Neumann wrote: > or perhaps with additional range checking: > > def addInteger(a :< Fixnum, b > 0 : Fixnum) > end I don't understand the syntax of the first parameter, but generally, I support your idea. Additional constraint would also enhance optimization possibilities. > Of course sometimes it would be nice to check for types this way, > but it's not often enough used, I guess. > > For that you could befine a method "must" in Object (like the one > in amstd), which can be used this way: > > a.must Fixnum > And raises an exception if the type is not equal. I find the it less readable, and less suggestive and less effective (in terms of possible runtime, assuming optimal implementation of the above feature). To effectiveness: consider the following piece of code: def f(x : X) end def g(x : X) f(x) end A good compiler would easily eliminate the second check, but also a single check could be more effectively performed than now. > The problem is that classes in Ruby are just objects, i.e. they are > dynamic. They have no static signature to check for. I think of a signature which is automatically generated and can be checked faster on need. The main concern here is not just readability, but speed. I could also imagine some check-caching approach: generic tests for classes could be cached and invalidated on extension of the class. In fact, adding such constraints to code has both advantages and disadvantages: Advantage: Optimizability, nicer syntax, better checking at parse time. Disadvantage: Non-generity (i.e. it makes your code less generic => less extendable) It depends on the situation, which one is more important. I think: we need both. > What you could do is define an interface definition, and check if the > object "implements" this interface. > But this could be done in pure Ruby, I think. I agree. Ruby is easy to write, extremely extandable. BUT: hard to optimize. Of course, extandability is an important issue and we should not give it up or even reduce it. I think that the current freeze machanism, and perhaps an optional more agressive one, which does not allow unfreeze at all, e.g something like that: frozen class X ... end would also be an interesting feature, worth considering and could be essential for the usability of such features. For a Ruby code compiled to C, one could consider different scenarios: 1) Shared object: This one is the most extendible, and therefore the one which is the hardest to optimize. Even in this case, a reasonable hiding strategy would expand the optimization possibilities. 2) Stand-alone-object which allows evaluates scripts from files or strings. Roughly the same situation as in 1) 3) Stand-alone-object which does not interprete anything: Much more optimizable than 1) or 2) since a compiler can have all information about the structure of the program (no possible extensions). Disadvantage: unsuitable for large projects, bacause of probable slow compilation time. I could imagine the following mechanism: An own object/library file format which contains the following section: 1) (assembler) compiled code for the private parts of the code (as a normal object file). 2) bytecode for the exported parts: for faster linkage 3) information on external extensions: i.e. a decription on how far this unit tries to extend other units. It would be helpful for optimizing other units. Ruby would have its own linker: Using section 3) determines how far the byte-code objects could be extended by other units and optimizes/compiles them. After that it could call the standard linker. This thoughts are of course very vague, but perhaps a starting point worth consideration. best regards, Christian