brownplt / pyret-lang

The Pyret language.
Other
1.06k stars 106 forks source link

standalone annotations for nested bindings #1192

Open shriram opened 6 years ago

shriram commented 6 years ago

Now that we can write standalone annotations (as opposed to inside the function header) for top-level functions [and top-level bindings in general], it's a bit sad we can't do the same for nested ones. E.g., I can't write

f :: Number -> Number
fun f(x):
  g :: Number -> Number
  fun g(y):
    x + y
  end
  g(x)
end

where g is annotated in a way analogous to f. It's a bit jarring that I can ship the annotation for f but not one for g.

I understand this is technically messy, and also that the argument for uniform treatment is not strong (the top-levels can be exported and are externally visible while the internal ones are not). Still, if the machinery now exists to permit it, it sure would be nice…

blerner commented 6 years ago

IMO, this qualifies as feature-creep. We had introduced the top-level statement syntax because it was needed for Bootstrap. We explicitly considered it to be inferior to inline annotations, and said that by the time students were capable of writing nested functions, by golly they could suckitup and learn the inline annotation syntax instead.

Technically, this might be feasible. Might. But I'm not convinced we want it.

shriram commented 6 years ago

I guess it's not so obvious to me that these are "inferior". I believe I've always argued that both forms have their uses. When there are lots of arguments, it can be easy to lose track of what's what in the top-level version (especially if there are lots of repeated types), though the ability to name the arguments goes a long way (hampered slightly by having choose the same names as the function itself, but hey) to erasing even that advantage for the in-line form.

In many cases the top-level version is really handy. Just consider the case of trying to write a homework assignment: would you prefer to ask students to implement

fun sort<T>(l :: List<T>, cmp :: (T, T -> Boolean)) -> List<T>: …

(what is that? it's half of a proper syntax…my skin crawls every time I write that into a homework) or

sort<T>:: List<T>, (T, T -> Boolean) -> List<T>

which is actual Pyret syntax, and even better, something they can paste into their code (or we can put in a starter file) and is subsequently checked, without feeling like we're starting to write the implementation.