#851 Change |,| to |->|

tactics Fri 4 Dec 2009

Something that I feel might be confusing to beginners is the type signature |,| It's completely unsearchable, since it has no identifier in it, and it is pretty much arbitrary.

I'd personally like to see |Void| instead. It'd give newcomers a little something to work with when they come across it in the docs.

Additionally, and I don't know the syntax well enough to know if this is possible, would it be possible to allow it block syntax to be used where ever a void method is needed?

andy Fri 4 Dec 2009

That's sorta an artifact. You can leave that completely off in most use cases now:

Button 
{
  text = "Click me!"
  onAction.add { onSave }
}

For ambiguous cases where its required, I don't have any big problems requiring |Void| - doesn't seem like I run across that case very often anyways.

tactics Fri 4 Dec 2009

doesn't seem like I run across that case very often anyways

Yeah, it's a little thing. But it's one of those little quirks that could be easily fixed without too much hassle, so I figured I'd propose it.

brian Fri 4 Dec 2009

Originally you used |,| all over the place so we wanted something short (originally it was just ||). The |,| was designed to be consistent with [,] and [:]. But now with it-blocks you don't use |,| quite as much anymore (although you still need it sometimes). I don't particularly love it, but I am not sure it worth changing. I guess if we came up with something better, but I don't particularly like |Void| either.

DanielFath Fri 4 Dec 2009

Wouldn't |->| be more consistent with [,] and [:] than |,|? To me if |Int->Bool| takes Int and returns Bool, |->Bool| takes nothing returns Bool, then |->| should take nothing and return nothing.

brian Fri 4 Dec 2009

It really came down to a quick vote Andy made back in 2006.

DanielFath Fri 4 Dec 2009

I demand a re-vote!!! ;-)

I dunno, I think |->| would be more newcomer friendly (me being new to Fan) but |,| is way shorter so it has its merits.

As it stands neither way is search friendly.

helium Fri 4 Dec 2009

but |,| is way shorter

One character. |->| seems to make much more sense.

tcolar Fri 4 Dec 2009

I also think |->| is way more intuitive.

As a matter of fact a month ago I wrote such a method and put a dummy thing in there because I did not know the syntax and never thought of |,| ... i'm pretty sure I actually tried |->| .

The vote needs a recount ;)

andy Fri 4 Dec 2009

Yeah, I rescind my vote - I like |->| better than |,|.

lbertrand Fri 4 Dec 2009

Looking at the vote, back in 2006, it was just between the 2 brothers... Is this really a vote ;-)

I think |->| is much more consistent and comprehensible than |,|

DanielFath Sat 5 Dec 2009

I'm pretty sure Brian wouldn't be saying guys to just Andy. I think f00biebletch was there too.

qualidafial Sat 5 Dec 2009

I don't mind |Void| but I like |->| as well. Sucks to type the arrow though: shift down, pipe, shift up, hyphen, shift down, bracket, pipe. Ugh. That may not be such a big deal though since it-blocks mostly do away with it.

alexlamsl Sat 5 Dec 2009

|->| - {Shift Down} | {Shift Up} - {Shift Down} > |

|,| - {Shift Down} | {Shift Up} , {Shift Down} |

--------------

Is the arrow really that much of a problem?

Or are you referring to the pipes on both ends? ;-)

(I don't really mind either syntax.)

DanielFath Sat 5 Dec 2009

|->| - {Shift Down} | {Shift Up} - {Shift Down} > |

Unless you use NumPad- in which case you can keep shift down. Anyway once you written it, you can always just use Copy/Paste for the rest.

Yuri Strot Sat 5 Dec 2009

Actually |->| is the first I tried before looking to doc. So +1 for |->|

brian Sat 5 Dec 2009

Promoted to ticket #851 and assigned to brian

Proposal is to replace |,| with |->| for a no-arg, void closure.

I sort of hate to make a breaking change for one bit of syntax for another.

But if everyone prefers the -> syntax and no one has an objection for the pain involved in fixing existing code then I'll make the change for the next build.

Any more votes?

Any objections?

KevinKelley Sat 5 Dec 2009

I vote against - the arguments for |,| make enough sense; |->| really is awkward to type. What I really wish though is that it could go away completely -- usually the following bracketed block is enough syntax; I'd like if it always was.

I wonder about conflict with (possibly future) type-inference? You're talking about using |->| to mean |->Void|; should it not mean "unspecified/inferred"?

Thinking a little about the "spirit of Fantom" -- one thing I've noticed is that we seem to have gone away from the C philosophy of treating brackets as an ad hoc means of limiting scope; in Fantom, mostly anyway, brackets aren't allowed except where they're needed.

This fits well with the emphasis on closures: in a way, any bracket-enclosed block is a closure. A method def is like a closure on this. an if/else/while block is like an anonymous closure that gets called based on the test. (I think switch syntax is weird, though; but it seems to work).

So anyway, with our emphasis on use of closures, they ought to be easy to use, syntax-wise. Huffman-coding style; make the thing you do most be the easiest.

brian Sun 6 Dec 2009

Not having some "prefix" syntax for a closure was a very contentious topic during the discussion of it-blocks. Just to recap, what I believe Kevin is proposing is that this is a no-arg void closure:

f := { echo("called!") }
f()

Today we require it-blocks only be appended to some other expr, so they can never stand alone like the code above.

I can't remember all the issues regarding making {} a closure, but I believe some of the top problems:

  • having {} create a closure in a C/Java/C# like language might be confusing and hard to read where those languages just introduce a scope
  • using return inside a {} closure with no clear obvious indication that you would be returning from the closure, not the outer method would be confusing

The first issue is of course subject to debate and personal preferences. The latter issue I solved by disallowing return statements inside a closure that didn't have the |...| syntax to clearly mark it as a closure.

I wouldn't say I'm 100% sold on allowing {} closures, but I think I would support that direction. This was my original design, but I had to change it when I added with-blocks. But now with-blocks are it-blocks which are closures - so I believe the design would work. Although there might be some ambiguities which could bite us (or make IDEs more difficult).

So let's open this discussion to the proposal to allow no arg closures simply as {...} and do away with |,| syntax completely if you have no parameters or return value.

jodastephen Sun 6 Dec 2009

Certainly, I think |->| is clearer than |,| but both are annoying and basically unclear. I would also object to the use of {...} without any other sign, as the meaning of return is then highly confused.

However, overall I remain firmly in the camp that arguments to a block should always be passed in round brackets. One rule for this in Fantom is just far more obvious. Why is there different argument syntax for closures as opposed to methods? This leads to a prefix being the best way to distinguish a closure. This allows the round brackets to be dropped if there are no arguments:

f := #(Str s) { echo(s) }
g := # { echo("called!") }  // no-args, so () optional

Since Java may now be using this syntax (closures in JDK 7), perhaps we should be (re)considering it?

brian Mon 7 Dec 2009

without any other sign, as the meaning of return is then highly confused.

I think we have solved that problem by disallowing return when there might be confusion. General rule is that if there no obvious closure prefix syntax such as |->| or whatever, then using return is a compile time error.

Since Java may now be using this syntax (closures in JDK 7), perhaps we should be (re)considering it?

I personally still love the Ruby style |a, b| {} syntax and like that it stands out. Although I've been using C# lambda expressions for another query language I'm working on, and I'm really digging those too. I don't really like the #() {} style, however I would love to have a syntax that allowed leaving off the braces in simple situations more like a simple lambda (which perhaps an alternate syntax might support). And I am also worried about IDE support since | is highly ambiguous with bitwise or. I would say it is way too early to tell what Java will end up with - Java is pretty schizophrenic on whole closure issue.

cbeust Tue 8 Dec 2009

As much as both |->| and |,| are consistent with the syntax, they look a bit too Perlish ("line noise") to me and I think this might be a good opportunity to break consistency for a degenerate but common situation.

How about just ||?

brian Tue 8 Dec 2009

How about just ||?

Original problem with || was its ambguity with logical-or. Although now that the parser has gotten more sophisticated with two passes, maybe that isn't a problem anymore.

After some more thought, I think we should do away with a prefix symbol and just allow {...} closures. We are already 80% there with it-blocks, and we can keep same no-return rule unless you have |...| prefix.

KevinKelley Tue 8 Dec 2009

After some more thought, I think we should do away with a prefix symbol and just allow {...} closures

...in keeping with a philosophy of not requiring things that don't add information. Especially things that are awkward to type, and look like line noise. I'm strongly in favor of this (assuming it works, of course); I really like the |a, b->Int| {...} syntax we have, except that in the degenerate case ( |,| {...} ) it's noisy and redundant (I agree with the original poster in this thread, that |->| {...} is a bit clearer, but that also is noisy and redundant).

andrey Tue 8 Dec 2009

What about to introduce optional keyword for closure definition, such as do? So we can use:

f := do { echo("hi there") }
f := |Int i| { echo(i) }
f := do |Int i| { echo(i) }

This does not solve a problem of |,| syntax for type definition, but let's avoid to type |,| everywhere we need it now.

brian Tue 8 Dec 2009

What about to introduce optional keyword for closure definition, such as do?

I like that, although I feel having optional, redundent syntax is probably not quite the right solution. I agree with KevinKelley that the only reason two reasons for |,| or any prefix syntax is 1) grammar ambiguity and 2) readability of the code to indicate a closure. If we can solve number 1, then I think we have pretty good agreement on number 2 that no syntax is better readability (keeping no-return rule that is)

andy Tue 8 Dec 2009

(keeping no-return rule that is)

Are you suggesting I can't use the return keyword in a no-arg closure?

brian Tue 8 Dec 2009

Are you suggesting I can't use the return keyword in a no-arg closure?

I've said it many times, but just to clarify - if there is no closure signature then you can't use the return keyword:

Foo {}            // it-block, no return
f := {}           // no sig closure, no return
f := |->Void| {}  // return ok

Independent of {}, we may still want to keep |,| or |->| - although using return inside a void closure is pretty rare - so my vote would be remove |,| completely and just say you have to use |->Void| if you really need a sig to enable return.

jodastephen Tue 8 Dec 2009

I can live with this approach (no return in closures without args). I would remove |,| and require |->Void|.

(Note that I still believe a # and round brackets is clearer and more consistent. Its part of my general language design principles that typical programmers prefer and conceptualise distinct language features with clear "boundaries" like # to very general concepts, such as those in LISP like languages.)

andy Tue 8 Dec 2009

That is fine for it-blocks, but definitely not for closures. Restricting the use of the return keyword based on a prefix does not seem right at all. I guess this is to make the code more "readable" by not confusing control structure blocks with closures - but I think that just makes things more complicated.

andy Tue 8 Dec 2009

typical programmers prefer and conceptualise distinct language features with clear "boundaries"

I agree. All closures should be clearly delineated - keeps things consistent and simple. So I see two options:

  1. Require |->Void| for no-arg closures
  2. Change the |...| syntax so it works "empty"

tcolar Tue 8 Dec 2009

I'm against ||, that's a logical OR and should stay only that.

Anything that require two compiler passes is a Nightmare for IDE support ... the PIPE is already difficult to parse as it is.

I don't really like round brackets LISP style either.

So for me it's either:

  • f := |->| {} which I find to be the clearest by far, and easy to identify (can add Void as Andy said)
  • f := {} Which is the simplest of all

The second option is the simplest but I have two reservations about it:

  • Is it easily parseable in the grammar ... I think if it always follows an assignment operator then it should be fine since I don't think another braced block can ... is it the case ?
  • For somebody not as familiar with closures, it's probably easier to figure what's going on with |->| {} (visual clue).

freddy33 Tue 8 Dec 2009

that just makes things more complicated.

Confusing may be, but complicated I don't see why?

Frankly, if you have return in your closure it starts to be a good size closure, and having |->Void| seems logical and greatly increase readability.

Since I'm not doing a lot of UI, most of the closures (and especially the small ones) I use have args and/or return types, so I for me Solution 1 sounds good.

The space where there is a lot of small closure with no-args is in UI (actions, ...). If, Andy says that adding |->Void| all over will make his code extremely ugly, need to find a better syntax.

Thinking about [,] or [:], I think |->| looks more coherent than |,|. Now, I agree with Kevin |->| feels awkward to type!

My conclusion, I support brian vote:

so my vote would be remove |,| completely and just say you have to use |->Void| if you really need a sig to enable return.

qualidafial Tue 8 Dec 2009

+1 to allow omitting the |,| at the closure site, but you still need to have some signature for method args / field defs.

My first preference is |Void|, followed by |->|, and finally |->Void|. Putting -> and Void side by side is redundant--any time you see Void in a Func signature, it is obvious we are talking about the return type anyway.

DanielFath Tue 8 Dec 2009

Putting -> and Void side by side is redundant--any time you see Void in a Func signature, it is obvious we are talking about the return type anyway.

Perhaps, but when I see |Void| I just assume by analogy that it takes nothing. I only later remember that it must return nothing as well.

brian Tue 8 Dec 2009

After talking it thru with Andy, he is pretty dead set against the change to {} with no prefix and no return support.

So let's drop back to original proposal which is to keep everything the same except that we will use |->| instead of |,|.

It-blocks will continue to be special in that they require no prefix and have the implicit it and can't use a return statement. So in most cases you can still use it-blocks as the short convenience syntax. But we won't change any of the other rules for non-it-block closures (other than |->|).

brian Sat 12 Dec 2009

Renamed from Void method signature to Change |,| to |->|

brian Sat 12 Dec 2009

Ticket resolved in 1.0.48

The no-arg closure syntax has been changed from |,| to |->|. The old syntax will continue to work with a warning until build 1.0.49.

Login or Signup to reply.