Intellisense and the psychology of typing

So, you save typing four letters.

In Ruby you don't need to type 'boolean'. You save writing 'dim',
'as', 'boolean' and the name of the variable too.

Saving four words instead of four letters sounds like a good trade off to me!

Douglas

···

On 5/28/05, James D Carroll <jamesdcarroll@hotmail.com> wrote:

And frankly if I
have to type 'boolean' instead of 'boo<tab>' I get real cranky real fast.

Because I don't want foo to only accept String objects. Suggestions
have been made for applying this information as metadata for the
purposes of parameter suggestions and RPC mapping, but they never seem
to take off very much. Something like:

  param :bar => :String
  return_as :String
  def foo(bar)
    bar.upcase
  end

Yes, it's more typing. No, it doesn't restrict my code at all.

-austin

···

On 5/26/05, Lothar Scholz <mailinglists@scriptolutions.com> wrote:

Sometimes i think that the missing typeing eats up very much of the
time that is saved by being typeless as Code is much harder to read
and understand. That's why i simply can't understand people who are
against "optional" type declarations.

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

do you really think so in the general case?

i think things like

   j = (char (*)[20]) malloc( 20 );

and

   char * const *(*next)();

and

   int (* foo())

take a considerable amount of time to read - at least for me.

scroll way down to see explanations of above - i'm curious how long it might
take people to de-code them.

in the end i've decided that there are only two reasonable forms of typing:
dynamic (a la ruby) or strong and automatic (a la ml langs). other kinds are
evil IMHO.

that being said i'm not against optional typing - but coding the compiler to
understand all of them can be tricky unless it's just simplistic. eg. how
would you like to declare, in ruby, a that takes a string parameter, and a
hash of strings to arrays of int as args? and, if you would only say 'proc' -
then what good is that typing system?

   hash = { 'key' => [42] }

   block = lambda{|string, hash| p hash[string]}

···

On Fri, 27 May 2005, Lothar Scholz wrote:

Hello Thomas,

> On Fri, May 27, 2005 at 01:35:19AM +0900, andrew.queisser@hp.com wrote:

1) Intellisense is really just another crutch that does more harm than
good? There were a few hardcore defenders of this position but not many.

> I'm indifferent. It depends what mood I'm in as to whether it is useful
> or not -- and invariably I tend not to use it, if only because, being
> the author, I know what formal parameters most methods expect.

Intellisense is most useful for the case where you use libraries or
modify/extend code that you don't have written (aka multi person projects).

Sometimes i think that the missing typeing eats up very much of the time
that is saved by being typeless as Code is much harder to read and
understand. That's why i simply can't understand people who are against
"optional" type declarations.

   #
   # how to declare callback?
   #
   callback = block

   callback[ key ]

cheers.

-a
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

explanations:
1) j is a pointer to a freshly malloc'd array 20 of char
2) next is a pointer to function returning pointer to const pointer to char 3) foo is a function returning pointer to array of int

man cdecl

ES ha scritto:
<snip>

When using procedural code it is easy and not comparable with autocompletition for Ruby.

Er, Lisp is a procedural language?

I think what Lothar is saying is that you use prefix syntax in lisp, where you don't expect completion to behave based on the type of an object, even if you're using CLOS.
Typing

f<tab> obj
is different than typing
obj.f<tab>
since in the former case you don't expect that the completion is done based on the type of the arguments, which you have not inserted yet.

Hello ES,

···

Le 29/5/2005, "Lothar Scholz" <mailinglists@scriptolutions.com> a écrit:

Hello Vincent,

I have rapidly skimmed over the few responses here. Auto completion is
definitly possible in dynamic languages: Common Lisp has it with its
Emacs mode, SLIME.

If you're in a slime buffer, you type (get-un then press C-c Tab and
Emacs will auto-complete with (get-universal-time), if there are many
choices, they will be displayed in a split window, if the function
takes parameters, those will appear in the mini-buffer, like so:

When using procedural code it is easy and not comparable with autocompletition for Ruby.

Er, Lisp is a procedural language?

At least Lisp is not a functional language. Lisp is Lisp.

With all the possible side effects etc. it has much more in common
with procedural languages then with true functional languages. And as
gabriele renzi already pointed out the point was that you simply want
prefix auto completition. I don't know of any autocomplete that works
with CLOS in a way like Java/C++.

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

Lothar Scholz wrote:

Hello Thomas,

1) Intellisense is really just another crutch that does more harm than
good? There were a few hardcore defenders of this position but not
many.
     
I'm indifferent. It depends what mood I'm in as to whether it is useful
or not -- and invariably I tend not to use it, if only because, being
the author, I know what formal parameters most methods expect.

Intellisense is most useful for the case where you use libraries or
modify/extend code that you don't have written (aka multi person
projects).

Sometimes i think that the missing typeing eats up very much of the
time that is saved by being typeless as Code is much harder to read
and understand. That's why i simply can't understand people who are
against "optional" type declarations.

Me too. Ruby is a great language and it has given birth to a really great collection of libraries, but I think that a little type information goes a long way; both in helping people who are reading the code (perhaps in the form of facilitating IDE annotations), and helping the compiler. Some RubyDocs seem to have type declairations, e.g. RMagick, does anyone know off hand how these come about?

In this thread someone mentioned an example of some code containing a function that takes either an int, or a hash of strings to ints. That sounds like a case for function overloading to me, aka

def do_something(a: Int): String
...

def do_something(a: (String, Int) Hash): Int
...

Of course everyones favorite trick it to stick Ints and Strings into the same array, which, in my book, leaves you with an Unknown Array, Unknown being the type of your good old dynamic language object on which you can call any method (possibly getting a method not defined exception). Yes, type systems and type inference is a can of worms.

One argument against a little type information is that: Oh, it's too restrictive, I wrote that function to work on Ints or Strings or whatever has a plus. But beware, just because the function has apparently correct behaviour for Ints and Strings doesn't mean that it correct (or expected) behaviour for Matricies's or Hash Tables or Proxies. That's where interfaces that embody some notion of semantics come in. An interface for example might be able to make explicit what it is that is in common between a String and an Int.

Crystaline program structures can take a while to form and so an advantage of allowing part of the program to go untyped is that it makes the type system more fluid in that the interfaces are implicit, and they don't get locked in due to the man hours required to create them. The other advantage of implicit interfaces is that, since they're an automatic product of what you and others have constructed, you don't miss out on them just cause they're not explicit as you would in a language like Java --- If the join of Integer and String in Java is Object, too bad, no amount of wishing is going to make it ObjectWithPlus, or if the join of HashSet and TreeSet is Set then you can't come along later and say, hey it should be CloneableSet, where as in Ruby you get all these joins (most specific generalisations) for free because they are implicit. No-one had to write them, and no-ones failure to write them makes them disappear.

An example of an implicit interface is that String and Array both provide an "each" function, but there is no explicit interface in Ruby that defines this shared property. Just some documentation (and a few language shortcuts the like the for loop).

On to my second point: a little type information helps the compiler. When skimming articles about optimising compilers for smalltalk I keep seeing comments like: such and such an optimiser couldn't infer that the inner loop operates over floats, so it ran 10 times slower than the equivalent C program.

There are times when you want to restrict the types to make the program run faster, e.g. programming an FFT, but who wants to leave the nice Ruby landscape and muck about in the C/C++ or Java dirt?

regards,

Richard.

PS: Are there any Ruby to Common Lisp bridges? Just out of curiosity.

···

On Fri, May 27, 2005 at 01:35:19AM +0900, andrew.queisser@hp.com wrote:

Hello Ara.T.Howard,

i think things like
   j = (char (*)[20]) malloc( 20 );
and
   char * const *(*next)();
and
   int (* foo())

take a considerable amount of time to read - at least for me.

Taking a specific not very good implementation might not be a good
argument for or against a general feature. If you have choosen Eiffel or even
lisps (the ....) code, the type declaration might look much better.

And when i say optional i don't mean to document each type. 90% of the
types are simple class names (yes i know many rubyists don't like it
to call classes types).

in the end i've decided that there are only two reasonable forms of typing:
dynamic (a la ruby) or strong and automatic (a la ml langs). other kinds are
evil IMHO.

I like Lisp. Sometimes at least.

that being said i'm not against optional typing - but coding the compiler to
understand all of them can be tricky unless it's just simplistic. eg. how
would you like to declare, in ruby, a that takes a string parameter, and a
hash of strings to arrays of int as args? and, if you would only say 'proc' -
then what good is that typing system?

I don't want a (complete) typing "system". If it gets complicated
change your app or don't use the optional type hints.

If my IDE could use it or the YARV JIT-Compiler could produce more productive
code for some methods it is enough.

I think that step of pragmatism is what very very few people until now
really understands. Maybe it takes a few years of Lisp experience to
see the value of typing hints.

···

On Fri, 27 May 2005, Lothar Scholz wrote:

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

Lothar Scholz wrote:

Sometimes i think that the missing typeing eats up very much of
the time that is saved by being typeless as Code is much harder
to read and understand. That's why i simply can't understand
people who are against "optional" type declarations.

Me too. Ruby is a great language and it has given birth to a
really great collection of libraries, but I think that a little
type information goes a long way; both in helping people who are
reading the code (perhaps in the form of facilitating IDE
annotations), and helping the compiler. Some RubyDocs seem to have
type declairations, e.g. RMagick, does anyone know off hand how
these come about?

These are probably noted by hand.

In this thread someone mentioned an example of some code
containing a function that takes either an int, or a hash of
strings to ints. That sounds like a case for function overloading
to me, aka

def do_something(a: Int): String ...

def do_something(a: (String, Int) Hash): Int ...

No, thank you. This is Not Ruby. This is precisely why I don't
*want* type declarations in Ruby; it's ugly and stupid.

Type *hints* are something else, but should be applied indepenently
of the method declaration.

Of course everyones favorite trick it to stick Ints and Strings
into the same array, which, in my book, leaves you with an Unknown
Array, Unknown being the type of your good old dynamic language
object on which you can call any method (possibly getting a method
not defined exception). Yes, type systems and type inference is a
can of worms.

Sorry, but that's no better than Java's horrid hack of casting to
Object. If you have to cast, you're not dealing with a real dynamic
language. Sorry, but you don't want Ruby if you want this.

One argument against a little type information is that: Oh, it's
too restrictive, [...]

No, that's why I document what the method is supposed to do, and
what the user is to expect. The rest of the paragraph is nonsense
once you get to the point where you understand that this is the
responsibility of documentation, not excessively strict type
notations. If I have type notations, then I run into the problem
that I have restricted users of my class and methods. If someone
else makes something that acts just the way that I want it to, why
shouldn't they be able to use my methods just because I was arrogant
(stupid?) enough to restrict the method in the first place.

[...]

An example of an implicit interface is that String and Array both
provide an "each" function, but there is no explicit interface in
Ruby that defines this shared property. Just some documentation
(and a few language shortcuts the like the for loop).

And who needs that explicit interface? I sure as hell don't need to
say:

  class Foo implements EnumerableInterface
    ...
  end

Sorry, but that's not Ruby.

On to my second point: a little type information helps the
compiler. When skimming articles about optimising compilers for
smalltalk I keep seeing comments like: such and such an optimiser
couldn't infer that the inner loop operates over floats, so it ran
10 times slower than the equivalent C program.

When were these articles written? Frankly, modern compiler
technology -- and type inferencing -- will help far more than type
specification.

There are times when you want to restrict the types to make the
program run faster, e.g. programming an FFT, but who wants to
leave the nice Ruby landscape and muck about in the C/C++ or Java
dirt?

Those who want to make the program run faster.

-austin

···

On 5/30/05, Richard Cole <rcole@itee.uq.edu.au> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Richard Cole wrote:

the compiler. Some RubyDocs seem to have type declairations, e.g. RMagick, does anyone know off hand how these come about?

In RMagick's case, they were painstakingly inserted by hand by the library writer, i.e. me.

Timothy Hunter wrote:

Richard Cole wrote:

the compiler. Some RubyDocs seem to have type declairations, e.g. RMagick, does anyone know off hand how these come about?

In RMagick's case, they were painstakingly inserted by hand by the library writer, i.e. me.

And are very much appeciated by me, a user of your library.

regards,

Richard.

Hello Austin,

reading the code (perhaps in the form of facilitating IDE
annotations), and helping the compiler. Some RubyDocs seem to have
type declairations, e.g. RMagick, does anyone know off hand how
these come about?

These are probably noted by hand.

Yes and a standart how these are annotated by hand is missing, so no
tool can get help from it. By the way FXRuby also has type hints, but
also with its own notation.

No, thank you. This is Not Ruby. This is precisely why I don't
*want* type declarations in Ruby; it's ugly and stupid.

Type *hints* are something else, but should be applied indepenently
of the method declaration.

In lisp you can put a (the 'Integer 'method-argument-one) whereever
you want. Also in Python you give type hints with statements
independent of the method declaration.

No, that's why I document what the method is supposed to do, and
what the user is to expect. The rest of the paragraph is nonsense
once you get to the point where you understand that this is the
responsibility of documentation, not excessively strict type
notations. If I have type notations, then I run into the problem
that I have restricted users of my class and methods. If someone
else makes something that acts just the way that I want it to, why
shouldn't they be able to use my methods just because I was arrogant
(stupid?) enough to restrict the method in the first place.

Because you want to keep a garantee about what works with with what
types. Sorry but i don't see restriction as a bad thing.

And who needs that explicit interface? I sure as hell don't need to
say:

  class Foo implements EnumerableInterface
    ...
  end

Sorry, but that's not Ruby.

Yes thats not ruby 1.X, not sure if it shouldn't be ruby 2.0
If benefits outweight the problems we should try this. But i also
would like to support another syntax and something optional like
the protocol notation from SmallTalk. Then we use tools to verify that
the implements relationships are right.

On to my second point: a little type information helps the
compiler. When skimming articles about optimising compilers for
smalltalk I keep seeing comments like: such and such an optimiser
couldn't infer that the inner loop operates over floats, so it ran
10 times slower than the equivalent C program.

When were these articles written? Frankly, modern compiler
technology -- and type inferencing -- will help far more than type
specification.

Type Inferencing is still almost impossible for far to many situations
and this will not change because it is fundamental problem.

There are times when you want to restrict the types to make the
program run faster, e.g. programming an FFT, but who wants to
leave the nice Ruby landscape and muck about in the C/C++ or Java
dirt?

Those who want to make the program run faster.

I've never seen any ruby program where i didn't wished that it would
run faster.

···

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

Hello Austin,

reading the code (perhaps in the form of facilitating IDE
annotations), and helping the compiler. Some RubyDocs seem to
have type declairations, e.g. RMagick, does anyone know off hand
how these come about?

These are probably noted by hand.

Yes and a standart how these are annotated by hand is missing, so
no tool can get help from it. By the way FXRuby also has type
hints, but also with its own notation.

Then perhaps one of the things you can suggest, Lothar, is what such
a standard might look like, and perhaps even add some stuff to rdoc
to complement this. Maybe:

    # :parameter bar: aString
    # :parameter baz: anArray or +nil+
    # :returns: true if aString ...
  def foo(bar, baz = nil)
    :
  end

This would give potential type hints to various tools. This would
be complicated, of course, by the fact that what we really need to
know is

No, thank you. This is Not Ruby. This is precisely why I don't
*want* type declarations in Ruby; it's ugly and stupid.
Type *hints* are something else, but should be applied
indepenently of the method declaration.

In lisp you can put a (the 'Integer 'method-argument-one)
whereever you want. Also in Python you give type hints with
statements independent of the method declaration.

Right. What I want is type hints independent of the method
declaration. Emphasis there: I *WANT* type hints. I have believed
that they are useful for things like SOAP from the beginning. I
don't, however, want anything that looks like type declarations in
the method declaration. That, to me, is a step down the path toward
static typing -- and that's precisely what we don't need in Ruby.
That step is an important one, conceptually. If you provide people
the ability to do something, they will do it. Thus, if we allow
people to do:

  def foo(bar: String, baz: [ NilClass, Array ] = nil)
    :
  end

They will. And all of the clean, easy-to-read-and-use Ruby code that
we've come to love will go away. Especially the -use part, because
if I want to use a StringIO object now, I'll either need to modify
the library, or get the String out of the StringIO before I can use
it.

No, that's why I document what the method is supposed to do, and
what the user is to expect. The rest of the paragraph is nonsense
once you get to the point where you understand that this is the
responsibility of documentation, not excessively strict type
notations. If I have type notations, then I run into the problem
that I have restricted users of my class and methods. If someone
else makes something that acts just the way that I want it to,
why shouldn't they be able to use my methods just because I was
arrogant (stupid?) enough to restrict the method in the first
place.

Because you want to keep a garantee about what works with with
what types. Sorry but i don't see restriction as a bad thing.

It has been conclusively shown that type restrictions based on class
names precisely do NOT do that in Ruby. Those restrictions, in fact,
do NOT make the code more robust, and are therefore bad things.

And who needs that explicit interface? I sure as hell don't need
to say:
  class Foo implements EnumerableInterface; ...; end
Sorry, but that's not Ruby.

Yes thats not ruby 1.X, not sure if it shouldn't be ruby 2.0 If
benefits outweight the problems we should try this. But i also
would like to support another syntax and something optional like
the protocol notation from SmallTalk. Then we use tools to verify
that the implements relationships are right.

I am absolutely positive that this should not be Ruby 2.0. It
complicates things unnecessarily. I think that we can agree that
Java-style Interfaces are poor substitutes for mixins; the proposal
for interfaces in Ruby are equally poor.

On to my second point: a little type information helps the
compiler. When skimming articles about optimising compilers for
smalltalk I keep seeing comments like: such and such an
optimiser couldn't infer that the inner loop operates over
floats, so it ran 10 times slower than the equivalent C program.

When were these articles written? Frankly, modern compiler
technology -- and type inferencing -- will help far more than
type specification.

Type Inferencing is still almost impossible for far to many
situations and this will not change because it is fundamental
problem.

Mmm. I'm not sure that I agree. Part of what I'm thinking here has
to do with what Microsoft has done with the .NET platform and Java
has done with Hotspot compiling. Programs are shipped as MSIL. There
is then an initial compile phase of the MSIL to processor-specific
*optimized* instructions. An implementation of Ruby 2.0 could do
something similar, where long-running programs, or programs that are
run often, have cached compiled versions of code that are based on
type inferencing.

This might be something that uses a binary other than "ruby" to run
these programs, as you don't necessarily want cached compiles
littering your hard drive, but these could be used to gain the
benefits of type inferencing. In the use of one-off scripts, this
will obviously be of no benefit, but type hints would be of little
benefit in any case. Rails, Nitro, and other programs (including
PDF::Writer) would benefit greatly.

I've applied a similar concept in one of my demo programs for
PDF::Writer. Because the hardest work is generating the PDF
structure in memory, I have made it so that the TechBook interpreter
can *cache* the generated structure. Once cached, the resulting PDF
can be generated in an almost immeasurably short time.

I won't pretend that I know how to do what I've written about above,
but given that type inferencing exists and that MSIL-to-binary
compiles exist, we aren't talking about something radically new.
We're just talking about a natural evolution, which uses multiple
runs (or long-term runs) of a program to provide continuous
optimisation to the execution of a program.

There are times when you want to restrict the types to make the
program run faster, e.g. programming an FFT, but who wants to
leave the nice Ruby landscape and muck about in the C/C++ or
Java dirt?

Those who want to make the program run faster.

I've never seen any ruby program where i didn't wished that it
would run faster.

But have you wanted that at the cost of restricting its utility? If
you have, then I wonder if you've really wanted that in Ruby.

I'll be honest -- there are some things in PDF::Writer that would
benefit from a bit of type restriction. But they are few and far
between. My biggest computing cost in generating PDF documents with
PDF::Writer is on the need to have transactional object support for
tables and similar objects. That said, I generate the manual (which
is growing toward 75+ pages with at least two dozen tables and lots
of live code examples) in about 2 1/2 minutes on my 3Ghz P4. It
takes about 6 minutes on my 1Ghz Transmeta CPU. Average one or two
page reports that I expect people will generate take consistently
fifteen seconds or less.

-austin

···

On 5/31/05, Lothar Scholz <mailinglists@scriptolutions.com> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Austin Ziegler ha scritto:

Type Inferencing is still almost impossible for far to many
situations and this will not change because it is fundamental
problem.

Mmm. I'm not sure that I agree. Part of what I'm thinking here has
to do with what Microsoft has done with the .NET platform and Java
has done with Hotspot compiling. Programs are shipped as MSIL. There
is then an initial compile phase of the MSIL to processor-specific
*optimized* instructions. An implementation of Ruby 2.0 could do
something similar, where long-running programs, or programs that are
run often, have cached compiled versions of code that are based on
type inferencing.

Sorry, but If I recall correctly MSIL brings explicit type informations, so that is not the same thing.
  The runtime inference may happen, at least in HotSpot, when you are doing stuff like using boxed structures and the JIT can transform them in a native array once it figures they will hold integers.

But some informations can't be inferred that easily. Think for example of the information about an object representing a 32bit/nativesize integer.
We will always pay the penalty due to the need to consider that it could, at any moment, become a Bignum, even if there is a guarantee that this will never happen.

(not that I care too much about performance, but I still think optional typing is great for documentation)

Austin Ziegler wrote:

  # :parameter bar: aString
  # :parameter baz: anArray or +nil+
  # :returns: true if aString ...
def foo(bar, baz = nil)

I *WANT* type hints. I have believed
that they are useful for things like SOAP from the beginning. I
don't, however, want anything that looks like type declarations in
the method declaration.

Thus, if we allow people to do:

def foo(bar: String, baz: [ NilClass, Array ] = nil)
  :
end

They will. And all of the clean, easy-to-read-and-use Ruby code that
we've come to love will go away.

I don't see how what you propose is all that different, semantically,
from calling out the type in the method header. You seem to be arguing
that: 'I want X like in other languages, but I don't want it to look
like it looks in other languages, because programmers from other
languages can import their bad habits.' And to add a feature that
doesn't at least resemble the syntax for that feature in most other
languages is to compromise the (currently much battered) principle of
least surprise, at least for those programmers coming to ruby from
another language. The usual syntax where the type is embedded in the
variable definition has some advantages: it's compact, and it keeps
related things together. It's not for no reason that langauge after
language that actually implements this has done it (more-or-less) the
same way.

Especially the -use part, because
if I want to use a StringIO object now, I'll either need to modify
the library, or get the String out of the StringIO before I can use it.

Specifying an overly restrictive type is an error. One can write a bad
program in any language, as the various obfuscated programming
contests have shown. Just because this is possible is no reason to
limit what good programs can do.

It has been conclusively shown that type restrictions based on class
names precisely do NOT do that in Ruby. Those restrictions, in fact,
do NOT make the code more robust, and are therefore bad things.

Type and class are not the same thing. Class is one variety of type,
but there are others. For instance, there is the 'method signature',
(or duck type,) the set of methods that can be called. You try to
rebut this notion:

I am absolutely positive that this should not be Ruby 2.0. It
complicates things unnecessarily. I think that we can agree that
Java-style Interfaces are poor substitutes for mixins; the proposal
for interfaces in Ruby are equally poor.

You manage to criticize without letting us know what your actual
objections are. What things are complicated, and how? Java interfaces
are a poor substitute for mixins, but that's because they're not meant
to be mixins. I would say instead: Java interfaces are a poor
substitute for duck types, (since, like everything else in Java, they
require a big pile of declarations ahead of time) but we can make the
Ruby version work the right way, with a lot less declarations. (Only a
little pile.)

Mmm. I'm not sure that I agree. Part of what I'm thinking here has
to do with what Microsoft has done with the .NET platform and Java
has done with Hotspot compiling.

People expect too much from hotspot and the like. It works great for
Java, sure, but that's in large part because Java is statically typed.
Expecting the same performance in a language with no type information
on variables whatsoever is unrealistic.

And no, type inferencing _by_itself_ will not solve the problem. Type
inferencing works in ML, but ML, like Java and C# is not a dynamic
language. ML lacks a feature that Ruby has: method_missing. To
understand why this is important, let me briefly explain type
inferencing.

Type inferencing works by examining the methods actually used by a
particular variable. This method signature (duck type) is compared to
the declared method signature of known classes. From this, a set of
all known classes that could legally be assigned to the variable is
inferred.

Method_missing throws this all to heck. A class with method_missing
might implement any duck type, and so has to be added as a possibility
to every variable. That's why dynamic languages (like SmallTalk) that
use type inference still require some type hints in some
circumstances.

Speed is only one advantage to a static typing system. In general,
static typing makes it easier (for programs as well as people) to
analyse programs that use it.

Austin Ziegler wrote:

# :parameter bar: aString
# :parameter baz: anArray or +nil+
# :returns: true if aString ...
def foo(bar, baz = nil)

I *WANT* type hints. I have believed that they are useful for
things like SOAP from the beginning. I don't, however, want
anything that looks like type declarations in the method
declaration.

Thus, if we allow people to do:
  def foo(bar: String, baz: [ NilClass, Array ] = nil)
    :
  end
They will. And all of the clean, easy-to-read-and-use Ruby code
that we've come to love will go away.

I don't see how what you propose is all that different,
semantically, from calling out the type in the method header. You
seem to be arguing that: 'I want X like in other languages, but I
don't want it to look like it looks in other languages, because
programmers from other languages can import their bad habits.'

Then you're not paying attention. Sorry if that offends you, but
you're just not paying attention. Type hints are primarily a
documentation feature. Let me repeat that for emphasis: it is a
documentation feature. If an optimizing Ruby compiler is able to
take advantage of it -- great. If not ... too bad. This is intended
as both human and machine documentation for automatic documentation
tools (rdoc), IDE autocompletion, and SOAP method descriptions (and
the like).

And to add a feature that doesn't at least resemble the syntax for
that feature in most other languages is to compromise the
(currently much battered) principle of least surprise, at least
for those programmers coming to ruby from another language.

DO *NOT* USE POLS in your argument. It doesn't apply. Matz has
indicated that it's just so much crap. I don't particularly *care*
if programmers coming from other languages are confused by a type
hinting system that doesn't look remotely like their static typing
system -- it isn't the same. It shouldn't be the same. It shouldn't
give them a false sense of understanding as to what it is.

The usual syntax where the type is embedded in the variable
definition has some advantages: it's compact, and it keeps related
things together. It's not for no reason that langauge after
language that actually implements this has done it (more-or-less)
the same way.

It also carries tons of disadvantages, as I've expounded before, but
will happily repeat again for those not paying attention:

1. It looks like the stuff in other languages, but because Ruby
   isn't statically typed (thank GHU for that), it won't have the
   same meaning as it does in those languages.
2. If it does have the same meaning in those languages, we're no
   longer talking about Ruby.
3. It will encourage people to use it for the wrong reasons in the
   wrong way.
4. It becomes more than informational.

All of these are killer problems. Type hinting in Ruby should be
informational. No more.

Especially the -use part, because if I want to use a StringIO
object now, I'll either need to modify the library, or get the
String out of the StringIO before I can use it.

Specifying an overly restrictive type is an error. One can write a
bad program in any language, as the various obfuscated programming
contests have shown. Just because this is possible is no reason to
limit what good programs can do.

You haven't been paying attention. StringIO doesn't inherit from
String or IO, but it will act like either. If I add a #read method
and a #write method to a random object, it will act a lot like an
IO. If I add #to_str to said object, it acts a lot like a String.

Specifying a restrictive (that is, non-informative) type AT ALL
prevents me from using many of these features that make the language
we're using Ruby.

Emphasis: restrictive type indicators will make the language that
does this Not Ruby.

It has been conclusively shown that type restrictions based on class
names precisely do NOT do that in Ruby. Those restrictions, in fact,
do NOT make the code more robust, and are therefore bad things.

Type and class are not the same thing. Class is one variety of type,
but there are others. For instance, there is the 'method signature',
(or duck type,) the set of methods that can be called. You try to
rebut this notion:

Oh, please *don't* try to lecture me on this stuff, Caleb. You'll
just piss me off. The method signature is not related to the "duck
type." If you've used Ruby for any length of time, you recognise
that as well. I'm not Matz -- or even Dave Thomas -- but duck typing
is, ultimately, not *caring* about the type of object you're
provided. It's just using the type of object.

I am absolutely positive that this should not be Ruby 2.0. It
complicates things unnecessarily. I think that we can agree that
Java-style Interfaces are poor substitutes for mixins; the
proposal for interfaces in Ruby are equally poor.

You manage to criticize without letting us know what your actual
objections are. What things are complicated, and how? Java
interfaces are a poor substitute for mixins, but that's because
they're not meant to be mixins. I would say instead: Java
interfaces are a poor substitute for duck types, (since, like
everything else in Java, they require a big pile of declarations
ahead of time) but we can make the Ruby version work the right
way, with a lot less declarations. (Only a little pile.)

No, we can't. Interface declarations are simply wasted code time and
space. It's that simple. (And Java interfaces *are* a poor
substitute for mixins; they are the way that Java implements MI, but
they require independent implementation in all cases. Ruby
implements MI through mixins, but like C++'s STL, they have a common
implementation.)

Simple rebut of your attempt at justification: at what point in a
class definition can you conclusively say that it is -- or is not --
an Enumerable? Given that classes in Ruby are open, you can't say it
until you try to use it like an enumerable.

  class Foo
    include Enumerable
  end

  a = Foo.new

  a.inject(0) { |a, b| a + b }
  # NoMethodError: undefined method `each' for #<Foo:0x2b5f290>

  class Foo
    def each
      yield self
    end
  end

  a.inject(0) { |a, b| a + b }

Obviously, this class won't work -- there are other parts missing,
but not until I've defined an #each method is Foo an enumerable.
What value would be something like a NoEnumerableInterface error be
as opposed to the simple "undefined method `each'" that we get?

Enumerable's documentation clearly states that it requires the #each
method be implemented for the Enumerable methods to work. Why do we
need an "interface" for that? The interface -- and implementation --
is in Enumerable. We don't need anything more than that.

Mmm. I'm not sure that I agree. Part of what I'm thinking here
has to do with what Microsoft has done with the .NET platform and
Java has done with Hotspot compiling.

People expect too much from hotspot and the like. It works great
for Java, sure, but that's in large part because Java is
statically typed. Expecting the same performance in a language
with no type information on variables whatsoever is unrealistic.

Not at all. Self is an indication that my suggestion will work:

  [...] the compiled method is specialized on the type of the
  receiver. If the same message is later sent to a receiver of
  different type (e.g., a float instead of an integer), a new
  compilation takes place. This technique is called customization
  [...] the compiled methods are placed into a cache from which they
  can be flushed for various reasons; therefore, they might be
  recompiled from time to time. Furthermore, the current version of
  the compiler will recompile and reoptimize frequently used code,
  using information gathered at run-time as to how the code is being
  used [...]

      http://rubyurl.com/aFVmq
  (http://research.sun.com/self/release_4.0/
          Self-4.0/manuals/Self-4.1-Pgmers-Ref.pdf)

Gee. It looks like I'm right. Self is an untyped language -- and the
HotSpot technology in Java is *based on the research for Self*.
(Indeed, note the point about the compiled cache and recompile and
reoptimize. That describes HotSpot exactly.)

And no, type inferencing _by_itself_ will not solve the problem.
Type inferencing works in ML, but ML, like Java and C# is not a
dynamic language. ML lacks a feature that Ruby has:
method_missing. To understand why this is important, let me
briefly explain type inferencing.

IIRC, Haskell also supports type inferencing, and is far more
closely considered a dynamic language. Method missing is a simple
case of unoptimizable code. At any rate, it's rather moot, since the
support (above) for the original point that I made rather shoots
down what you've said.

[...]

Speed is only one advantage to a static typing system. In general,
static typing makes it easier (for programs as well as people) to
analyse programs that use it.

Bullshit. This is a lie told by proponents of statically typed
languages that has been shown false again and again and again.
Static typing doesn't increase safety, ability to be analysed, or
anything else -- that doesn't help the compiler of said statically
typed language. There are side benefits from IDEs that have been
observed in the last serveral years, but statically typed languages
have been around a lot longer than autocompletion. And we *still*
get buffer overruns.

Sorry, but I question even the belief that speed is an advantage to
a static typing system -- remember that C++ was *slower* than C for
years (and in some cases, still is), and they're both statically
typed languages.

(Hint: even statically typed languages need to break the chains more
often than proponents want to admit. In Java it's Object. In C/C++
it's void*. Both require a lot of care and work to make them
happen.)

-austin

···

On 5/31/05, Caleb Clausen <vikkous@gmail.com> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Austin Ziegler ha scritto:

Type Inferencing is still almost impossible for far to many
situations and this will not change because it is fundamental
problem.

Mmm. I'm not sure that I agree. Part of what I'm thinking here
has to do with what Microsoft has done with the .NET platform and
Java has done with Hotspot compiling. Programs are shipped as
MSIL. There is then an initial compile phase of the MSIL to
processor-specific *optimized* instructions. An implementation of
Ruby 2.0 could do something similar, where long-running programs,
or programs that are run often, have cached compiled versions of
code that are based on type inferencing.

Sorry, but If I recall correctly MSIL brings explicit type
informations, so that is not the same thing. The runtime inference
may happen, at least in HotSpot, when you are doing stuff like
using boxed structures and the JIT can transform them in a native
array once it figures they will hold integers.

Mmmm. Not really. See my rather pointed post to Caleb. Self managed
this as an dynamically typed language. HotSpot is based on Self's
VM. Self would reoptimize based on cache and analysis. That's all
I'm saying would have to happen here, in Ruby. Easy? Not at all. But
a lot easier than changing the very nature of Ruby into something it
isn't.

HotSpot, as I understand it, took *longer* to get working right
because it now had to work on a statically typed language.

Additionally, the example of MSIL is just that: an example. It's an
intermediate step that results in an optimized binary.

(And, really, it's not anything like #method_missing that makes Ruby
a hard language to optimize; it's #eval. The reality is that even
things like #method_missing can be optimized because they will be
called in a predictable way in most programs.)

But some informations can't be inferred that easily. Think for
example of the information about an object representing a
32bit/nativesize integer. We will always pay the penalty due to
the need to consider that it could, at any moment, become a
Bignum, even if there is a guarantee that this will never happen.

Mmmm. Disagree. You only pay the penalty when you make the switch,
just as you do now in Ruby. Again, see the response to Caleb which
points out Self's optimization.

(not that I care too much about performance, but I still think
optional typing is great for documentation)

If it's made in a documentation format. That's my whole point --
typing as documentation is good. Anything else is bad.

-austin

···

On 5/31/05, gabriele renzi <surrender_it@remove-yahoo.it> wrote:
--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

From your history of posts, you definitely are not sorry that
you are offending. Insulting people will not help convince
anybody that you are right. You will get much further being
nice and attempting to see where they are coming from.

BTW, I happen to agree with you on this topic. I like no/duck
typing in the language. It provides much more flexibility and
power.

···

--- Austin Ziegler <halostatue@gmail.com> wrote:

Then you're not paying attention. Sorry if that offends you,
but you're just not paying attention.

__________________________________
Do you Yahoo!?
Yahoo! Small Business - Try our new Resources site

Austin Ziegler ha scritto:

Sorry, but If I recall correctly MSIL brings explicit type
informations, so that is not the same thing. The runtime inference
may happen, at least in HotSpot, when you are doing stuff like
using boxed structures and the JIT can transform them in a native
array once it figures they will hold integers.

Mmmm. Not really. See my rather pointed post to Caleb. Self managed
this as an dynamically typed language. HotSpot is based on Self's
VM. Self would reoptimize based on cache and analysis. That's all
I'm saying would have to happen here, in Ruby. Easy? Not at all. But
a lot easier than changing the very nature of Ruby into something it
isn't.

I think I understand what the point of our debate is:
you are thinking of a "fast" thing (i.e. the self system, which in the paper [1] is claimed to be from 5 to 2 times slower than equivalent C code).

I am thinking of a "as-fast-as-C" implementation such as those claimed
by the CL people, and also thinking that the fastest *available platform * with a ruby-like enviroment, VisualWorks, is fast but again quite slower than C.

[1]
http://research.sun.com/self/papers/iterative-type-analysis.html

Hello Austin,

Not at all. Self is an indication that my suggestion will work:

  [...] the compiled method is specialized on the type of the
  receiver. If the same message is later sent to a receiver of
  different type (e.g., a float instead of an integer), a new

Which simply means that it is optimized with exactly one type hint.
It's easy as inside a method "self" can never it's type. But it's
not possible to optimize very much with this. Eiffel and D are using the
feature to transform most of the virtual method calls to binary calls.
But you get very few optimizations that you can get from better
hinting.

Gee. It looks like I'm right. Self is an untyped language -- and the
HotSpot technology in Java is *based on the research for Self*.
(Indeed, note the point about the compiled cache and recompile and
reoptimize. That describes HotSpot exactly.)

I've never seen very good documentation about HotSpot internals, what
does compiled cache mean, what does recompile and reoptimze mean. As
long is don't see some implementation details this is for me just
marketing hype.

Sure recompile can be something in the oder to check the arguments so
that if i have: x + y and in the past i knew that x and y are often
integers then something like

if (ISINTEGER(x) && ISINTEGER(y)) return x+y;
callinfix(x,'+',y)

The if statement can be transformed to one (SUN Sparc V8 architecture)
or multiple machine code operations.

Speed is only one advantage to a static typing system. In general,
static typing makes it easier (for programs as well as people) to
analyse programs that use it.

Bullshit. This is a lie told by proponents of statically typed
languages that has been shown false again and again and again.
Static typing doesn't increase safety, ability to be analysed, or
anything else -- that doesn't help the compiler of said statically
typed language. There are side benefits from IDEs that have been
observed in the last serveral years, but statically typed languages
have been around a lot longer than autocompletion. And we *still*
get buffer overruns.

Buffer Overruns have nothing to do with statically typed langauges.
And i don't see any evidence why your argument should be right other
then "religious believe in dynamically typed language".

Sorry, but I question even the belief that speed is an advantage to
a static typing system -- remember that C++ was *slower* than C for
years (and in some cases, still is), and they're both statically
typed languages.

Sorry but this is wrong. Seems that you never ever looked at
compiler generation.

Also your argument is that one statically typed language implementation is
slower then another statically typed language implementation. What a
huge surpise.

···

--
Best regards, emailto: scholz at scriptolutions dot com
Lothar Scholz http://www.ruby-ide.com
CTO Scriptolutions Ruby, PHP, Python IDE 's

> Then you're not paying attention. Sorry if that offends you,
> but you're just not paying attention.
From your history of posts, you definitely are not sorry that
you are offending. Insulting people will not help convince
anybody that you are right. You will get much further being
nice and attempting to see where they are coming from.

Actually, I am sorry if he's offended. I *am* exasperated that this
keeps coming up and that no one ever looks at this history of the
topic before bringing it up again, or that certain people bring it up
regardless.

If you were offended by the stridence that I've used in opposing some
of the proposals you've made, I am sorry. That doesn't mean I won't be
strident about opposing things that I think are bad for Ruby, but that
I don't mean to cause offence with that.

BTW, I happen to agree with you on this topic. I like no/duck
typing in the language. It provides much more flexibility and
power.

I do want hinting -- or at least a documentation "standard" -- for the
reasons mentioned in this thread (documentation, IDEs, etc.). But I
don't want anything that can reasonably be considered remotely close
to static typing.

-austin

···

On 5/31/05, Eric Mahurin <eric_mahurin@yahoo.com> wrote:

--- Austin Ziegler <halostatue@gmail.com> wrote:

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca