Page 1 of 1

Understanding the limits of type inference

PostPosted: Thu Sep 02, 2010 3:43 pm
by gradha
Hello.

In the example at http://github.com/gradha/Cobralation/tr ... 2%20cobra/ there's the file shapes.cobra where it defines a shape's constructor as:
Code: Select all
   cue init(side as int, id as String)
      base.init(id)
      _mySide = side

It's my first time with a type inference language, so here it goes. Why does the code not compile if I remove the types for the parameters of the constructor? Since the code immediatelly calls the base constructor (which is defined as accepting String) and the _mySide variable is of type int, shouldn't Cobra detect this? Or does this only work for variables, and never for function prototypes?

I just want to know where's the limit of the type inference.

Re: Understanding the limits of type inference

PostPosted: Fri Sep 03, 2010 5:40 am
by hopscc
If you remove the explicit typing on params they default to 'dynamic' which eventually become Object in the C# source code
I'd venture the failure messages for the compile refers to inability to convert 'Object' types to 'String' or int in passing the now dynamic params into the baseclass initializer.
(It would help immensely for 'compilation fails' type questions if you posted the error message.)

For it to work the types of the params on the methods need to match or be convertible ( i,e the baseclass needs to take a dynamic (unspecified arg Type as well and the type used is resolved at runtime)

This isnt type inference as such more typing compatibility across methods as you've explicitly specified the types on the initializers.

i.e This fails due difference in Types fro the baseclass initialiser and its call from the subclass
Code: Select all
class Shape is abstract
    var _myId as String

    cue init(s as String)
        base.init
        .id = s

    pro id as String
        get
            return _myId
        set
            _myId = value

    pro area as float is abstract
        get

    def toString as String is override
        return .id + " Area = " + String.format("{0:F2}", .area)


class Square inherits Shape
    var _mySide as int
   
    cue init(side, id )
        base.init(id)
        _mySide = side
   
    pro area as float is override
        """Given the side, return the area of the square."""
        get
            return _mySide * _mySide


    def main is shared
        pass   

with
Code: Select all
TypeInfer.cobra(24): error: The best overloaded method match for "Shape.Shape(string)" has some invalid arguments (C#)
TypeInfer.cobra(24): error: Argument "1": cannot convert from "object" to "string" (C#)
Compilation failed - 2 errors, 0 warnings


This succeeds (base initialiser and subclass call both same (unspecified,dynamic) type
Code: Select all
class Shape is abstract
    var _myId as String

    cue init(s)
        base.init
        .id = s

    pro id as String
        get
            return _myId
        set
            _myId = value

    pro area as float is abstract
        get

    def toString as String is override
        return .id + " Area = " + String.format("{0:F2}", .area)


class Square inherits Shape
    var _mySide as int
   
    cue init(side, id )
        base.init(id)
        _mySide = side
   
    pro area as float is override
        """Given the side, return the area of the square."""
        get
            return _mySide * _mySide


    def main is shared
        pass   



Type inference in itself is relatively simple - if you are creating a variable and its not already typed it'll take the type of its assignment expression (rvalue type) but you need to realise that the variable
still ends up staticly typed ( inferred not explicitly set)
Dynamic types confuse this some as a dynamic type sez that the variable type can be anything and change depending on whats assigned to it.
BUT as this gets converted to C# ( statically typed language currently) the implementation type for 'dynamic' is Object which means that you can make programs that compile fine wrt Cobra
but that the C# compiler balks at (mostly around implicit conversions from Object to some other type).

For classes I find this usually means that you either want to explicitly type all the params and vars (except where you definitely want a type morphing value - rare SFAICT) OR you leave all (most) of the values as dynamic and let them get the types from their construction/assignment types. Its arbitrary mixtures that cause problems especially up inheritance (method) chains.

I'd expect most of the issues with this are back end compiler specifics wrt what it allows with casting Object to

Re: Understanding the limits of type inference

PostPosted: Fri Sep 03, 2010 10:02 am
by Charles
-- Type inference happens for "var" declarations that are given an initialization expression such as "var _x = 0" and for local variables declared for the first time through assignment such as "x = 0".

-- When you omit the type of a "var" declaration and there is no initialization expression, Cobra infers "dynamic". Likewise for properties without types and parameters without types.

-- So when you write "cue init(side, id)" that is equivalent to "cue init(side as dynamic, id as dynamic)".

-- You are in fact, supposed to be able to pass a dynamically typed expression anywhere, resulting in a typecast at run-time that will either succeed or throw an exception. However, this is broken in the case of calling base.init.

-- However, it's unlikely that you actually want to type your parameters as "dynamic" when overriding cue.init. Especially for those parameters that are passed to "base", there is no apparent advantage.

-- Regarding style, since this is a tutorial that will be seen my others, I recommend having a blank line after "class Foo inherits Bar" lines, and also changing "_myFoo" declarations to simply be "_foo".

If you need me to expand or clarify anything, let me know.

HTH

Re: Understanding the limits of type inference

PostPosted: Sun Sep 05, 2010 2:38 pm
by gradha
Thanks for the clarifications. WRT the style, certainly maintaining the ugly camel case isn't desired.

Re: Understanding the limits of type inference

PostPosted: Sun Sep 05, 2010 10:08 pm
by Charles
Camel case is fairly normal in Cobra such as types named "FooBar" and other things named "fooBar". See:

-- http://cobra-language.com/samples/

-- http://cobra-language.com/how-to/

Using "my" is not.

Re: Understanding the limits of type inference

PostPosted: Mon Sep 06, 2010 12:56 am
by gradha
In that case I'll strive to avoid multi word names!