[Types-sig] Issue: binding assertions

Greg Stein gstein@lyra.org
Sun, 19 Dec 1999 11:47:27 -0800 (PST)


On Sun, 19 Dec 1999, Paul Prescod wrote:
>...
> def brian(a) -> int:
> 	a.spam=42
> 	somefunc( a )
> 	return a.spam+a.parrot
> 
> Without getting into nightmares of "const" and so forth, we need to deal
> with the fact that we can't know the type of a.spam and a.parrot without
> analyzing somefunc and maybe other code. We don't have that option.
> Therefore we must be able to guarantee at least the type, if not the
> values, of a.parrot and a.spam. 

You cannot know the type of <a> because you did not add a type declaration
to the parameter. If you had the following code:

class Foo:
  decl member spam: Int
  decl member parrot: Int
  ...

def somefunc(x: Foo):
  ...

def brian(a: Foo) -> Int:
  ...


THEN, you could assert type-safety. But if you don't even tell the thing
what type your inputs are: well... your problem.

What I believe is a distinct issue: while the interface specification of
Foo tells you what a.spam *is*, I believe we have a separate problem of
deciding whether to *enforce* that. While I am not strictly opposed to
enforcing type safety during assignment, I would ask that you please list
this as two problems: 1) declaring an interface, 2) enforcing type-safety
during assignments.

> Now if a is a module object then hard-coding the values is equivalent to
> declaring the static, unchanging type of global variables. So in at

Declaring module globals is really declaring the module *interface*, IMO.
The fact that the interface happens to be implemented with globals is
beside the point.

In fact, it might be neat to have something like this:

module Foo:
  decl member a: Int
  decl member b: Int
  def foo(x: String) -> String:
    "doc string"
    # no code!
  def bar(y: String) -> None:
    "doc string"

Then at some point in your code, you could do:

def baz(a: Foo) -> Int:
  ...


While all this is neat, you'll notice that the "module Foo:" is exactly
the same as doing "interface Foo:".

> least the module and class instance cases, we are binding types to
> names, not values. This begs the question: is there any reason to treat
> parameters differently and allow parameters to vary over their lifetime?
> And what about declared local variables? Surely they must behave the
> same as global variables!

I think you are binding types as part of an interface declaration. That is
quite different than binding locals.

> My personal vote is that we treat all variables the same. Someone who
> wants to allow some particular name to vary its type over its lifetime
> has the following options:
> 
>  * turn off type checking
>  * declare it to be of type Any
>  * declare it to be of type dict | list of string
> 
> If we are too strict at first then we could ease the rule based on
> feedback. I *do* understand that the vast majority of local variables
> (not parameters) should have their types inferred (perhaps just as
> "Any") rather than declared.

I believe that if we add syntax to declare locals, then we are going to
have a real hard time getting rid of that syntax. I would rather proceed
with caution in this regard: if we simply can't get the type inferencing
(or deduction as some people would say) working, then I'll relent and
advocate declaring locals. But until we reach that step, I'd like to avoid
adding new syntax for declaring locals.

If people want to use local declarations for commentary purposes, I would
just tell them:

def foo(a, b):
  #decl local c: Int
  ...
  c = 5
  ...

In other words, Python isn't going to provide direct assistance for
declaring the things.

Note that, for a function, I do not believe there is much merit to
declaring types for enforcement purposes. I don't want to add syntax and
the resulting non-cleanliness to deal with people who do the following:

def foo():
  decl local c: Int
  c = "foo"

Tough for them. I think most programmers can easily keep track of types
within a single function. We will be helping them out, certainly, with the
type checking, but it just doesn't happen as a type-enforcement at assign
time.
[ in other words: I think type problems occur at boundaries (func calls)
  rather than within the code/variables of a single function ]

Cheers,
-g

-- 
Greg Stein, http://www.lyra.org/