#504 Closure Type Inference

brian Sun 5 Apr 2009

One of the bits of infrastructure I have to build in order to implement it-blocks is closure type inference. For example:

// foo method takes a function typed as |Bar|
Void foo(|Bar|) {...}

// it-block with inferred type of it
foo { ... }  

// actual inferred signature of snippet above
foo |Bar it| {...}

Because all the hard work of closure type inference will be there, we could potentially add full type inference for all closures:

// current syntax
files.sort |File a, File b->Int| { a.modified <=> b.modified }

// with type inference
files.sort |a, b| { a.modified <=> b.modified }

So the question is: would you guys like to add type inference on all closures to the language?

If so, would you be willing to give up using the "|" pipe symbol for bit-wise OR to have this feature?

jodastephen Sun 5 Apr 2009

I'm not sure there is any viable alternative symbol to a pipe for bit-wise OR. Its very well known too. (You also didn't explain why there is a syntax/grammer problem)

Other options would be:

files.sort #(a, b) { a.modified <=> b.modified }
files.each #(a) { a.modified }
files.handle #{ ... }

files.sort {a, b | a.modified <=> b.modified }
files.each {a | a.modified }
files.handle {| ... }

files.sort {a, b : a.modified <=> b.modified }
files.each {a : a.modified }
files.handle {: ... }

Personally, I prefer the # version as it fits with using return to return to the closure (and the closure is therefore the definition of a special kind of method). The other two options are closer to other closure languages.

I know I keep mentioning the return aspect of closures, but so long as return is short, it must be possible for the code-reader to easily identify where the closure starts.

brian Sun 5 Apr 2009

I'm not sure there is any viable alternative symbol to a pipe for bit-wise OR. Its very well known too. (You also didn't explain why there is a syntax/grammer problem)

Well it is already a problem, but I handle it now with a two pass parser. I expect that I can handle this ambiguity with the two passes also, just not positive yet. So for argument sake, let's assume I can make it work without giving up pipe as bit-wise OR (anyone else building IDE tooling will need to use the same two pass parsing).

Creating an alternate syntax for closures is pretty much a non-starter for me. I believe the closure syntax should be consistent. So I say we either decide to do type inference with current syntax, or not do it at all.

jodastephen Sun 5 Apr 2009

I believe the closure syntax should be consistent.

My proposals were for all closures, not just type inferred ones.

qualidafial Sun 5 Apr 2009

So the question is: would you guys like to add type inference on all closures to the language?

+1

If so, would you be willing to give up using the "|" pipe symbol for bit-wise OR to have this feature?

Wouldn't the { token following the second | token disambiguate the two?

KevinKelley Sun 5 Apr 2009

I'm not qualified to answer this, I think. I like type inferencing, it lets us avoid typing in a bunch of redundant information that the compiler should know anyway. So your examples at the top look good.

I don't like breaking the | operator, though; it's too ingrained as bitwise OR, and part of what's good about Fan is, it's consistent with the basics of Java and C#, with some cleanup and some additions.

Without actually figuring it out, because off the top of my head I can't, I'd guess that the complications could be pushed into the compiler. So, from the perspective of a user of the language, all would be well. But I kind of hate the idea of complicating the grammar. Part of what's good here is the simple consistency. The grammar is clean. That means tools are easier to build. It also means things are easier to explain.

Another left-field comment, I'm not sure how significant it is, but the closure symbol | is unique in that it's the only one where the open and the close are the same symbol. It looks nice in the source, but there's no way to disambiguate by matching the open- and the close- symbol, like you can with (), [], {}. I wonder, does the phrase nested closures have any meaning?

One thing I do know, this makes me more sure I want to continue to leverage the existing parser, rather than try to write and maintain a parallel one. :-)

JohnDG Mon 6 Apr 2009

So the question is: would you guys like to add type inference on all closures to the language?

An unqualified yes. It's a pain to type closures.

If so, would you be willing to give up using the "|" pipe symbol for bit-wise OR to have this feature?

Sure. Although an alternate syntax for closures would be better.

tactics Mon 6 Apr 2009

I don't think bitwise-OR is a very common operation for the kind of programming you are marketing towards. The only two uses I've ever seen | used for are bit fields and low-level bit-twiddling. If you need to twiddle the bits quickly, you're better of with some FFI anyway. I don't personally use bit fields very often and I'm sure there's a "more object oriented" solution to the problem they solve in most cases.

I definitely believe type inference on closures is a must. At least in the case where it is used as a parameter to some existing API, explicit typing on closures forces the programmer to do a pointless lookup in the documentation for the spelling. I'd love to see closure type inferencing in Fan.

andy Mon 6 Apr 2009

So the question is: would you guys like to add type inference on all closures to the language?

Yes.

If so, would you be willing to give up using the "|" pipe symbol for bit-wise OR to have this feature?

I think that should be avoided if at all possible. I really don't like that, but if we had to do it, we need to change all of them IMO. Its better to have them all different, then just one, which would be confusing.

brian Mon 6 Apr 2009

Sounds like everybody fully supports closure type inference.

I think I can handle the grammar problem with bitwise by scanning the tokens looking for "| {" in the first past. It gets a little ugly when the closure signature actually has function types in it, but I should be able to just count them.

I will try and get this feature done this week as part of the grand it-block refactoring.

tompalmer Mon 6 Apr 2009

+5 on closure parameter type inference.

When I tried adding this to Fan last summer, I didn't have much trouble with parsing (using the | { to disambiguate), but I did have trouble figuring out the right way to get the info into the right phase of the compiler.

Side note, on the bitwise or operator, I've had hankerings in my own designs to completely leave out bitwise operators from languages. People just don't often twiddle bits anymore. Let people use more awkward constructs for less common needs. However, if ~, ^, &, and | are generalized to set operations (which they really are in the first place), then they still have some value, I think.

freddy33 Mon 6 Apr 2009

In the plugin parser we did a 2 pass. | activate closure parsing with rollback if not successful, so continue with the bit or expression... So, doing the inference look straight forward from my current view.

BTW: The only main issue I have with the grammar is List and Map literals with type declaration. I'll open a discussion on this!

jodastephen Mon 6 Apr 2009

I think I can handle the grammar problem with bitwise by scanning the tokens looking for "| {" in the first past. It gets a little ugly when the closure signature actually has function types in it, but I should be able to just count them.

I'm not sure I understand the desire to keep pipes as the closure parameter markers. Parameters elsewhere in Fan are in round brackets, why use pipes for closures? It certainly makes it harder given there is no open and close pipe.

brian Mon 6 Apr 2009

Parameters elsewhere in Fan are in round brackets, why use pipes for closures?

Parens are overloaded for too many uses including calling functions, grouping, and casting. So they would never work. The only matching symbols you might use are "< >", but that doesn't really help the issue - you would still require a two pass parser to scan for "> {" since lt/gt are valid operators too. But I really like pipes, so that is unlikely to change.

tompalmer Mon 6 Apr 2009

I personally prefer parentheses for params. They are used for function params, and I'd prefer all params to look the same. But we've already discussed this, so I didn't want to bring it up again. That's where I am on this.

brian Fri 10 Apr 2009

I got closure type inference working - its the cat's meow!

tompalmer Fri 10 Apr 2009

Sweetness.

Login or Signup to reply.