shortcut for if

113 views
Skip to first unread message

calle

unread,
Nov 21, 2010, 2:10:40 PM11/21/10
to golang-nuts
Hi,

Im just playing around with go, and I found it quite intresting,
though im missing a shortcut for "if" expression.
Maybe there exists one, but i haven't been able to find it.

Something like C shortcut:

( test ? "True" : "False" )

This little feature makes the code more compact and easy to read ( in
my opinion ).

Cheers

Alexander Surma

unread,
Nov 21, 2010, 2:28:29 PM11/21/10
to golan...@googlegroups.com
This has been discussed before (search the list). The basic argument is that

"This little feature makes the code more compact and easy to read"

turns out to be wrong. There's no performance benefit, but it suggests
one. As a consequence, people tend to use this construct heavily to
increase performance, making code just plain ugly and distorted, without
any benefit. Write wrapper functions instead.

Surma

Ostsol

unread,
Nov 21, 2010, 2:53:49 PM11/21/10
to golang-nuts
On Nov 21, 12:28 pm, Alexander Surma <alexander.su...@googlemail.com>
wrote:
I would like to extend this statement by saying that Go would better
be served by inline functions, rather than such syntactic sugar.
(Yes, I know that an explicit "inline" keyword has already been
declared a no-go, but it has been stated that automatic inlining of
trivial functions is possible in the future.) Such wrapper functions
would likely be trivial, anyway -- perfect for inlining.

-Daniel

chris dollin

unread,
Nov 21, 2010, 2:56:07 PM11/21/10
to Alexander Surma, golan...@googlegroups.com
On 21 November 2010 19:28, Alexander Surma

<alexand...@googlemail.com> wrote:
> This has been discussed before (search the list). The basic argument is that
>
> "This little feature makes the code more compact and easy to read"
>
> turns out to be wrong. There's no performance benefit, but it suggests one.

?! Really?

I've never ever thought of if-expressions of having a performance
benefit; it's purely an expressiveness benefit (compactness,
readability, and doing what it says on the can and no more).

Things like
return (a ? b : c)
f( x, (y ? z: w), h )
a = (b ? c : d)

are all, to me, more readable than the tangled dependencies
that you need to express the same effect without them.

(The C micro-syntax for it I unprefer, but that's a minor detail.)

Chris

--
Chris "allusive" Dollin

Johann Höchtl

unread,
Nov 22, 2010, 4:08:41 AM11/22/10
to golang-nuts
Which makes runtime behaviour rather unpredictable. I do not like
that. Explicit would be an architectural decission while implicit is
an optimisation.

> -Daniel

Russ Cox

unread,
Nov 22, 2010, 11:28:36 AM11/22/10
to golan...@googlegroups.com

chris dollin

unread,
Nov 22, 2010, 12:31:05 PM11/22/10
to golan...@googlegroups.com
On 22 November 2010 16:28, Russ Cox <r...@golang.org> wrote:
> http://golang.org/doc/go_faq.html#Does_Go_have_a_ternary_form

That only says that it doesn't, and gives the solution in
the trivial case. (For example, very often you have to
introduce the variable n because it doesn't already
exist, and you have to type it, because the initialisation
statement isn't to hand).

Yes, of course one can manage without it. One can manage
without :=, return variables, and statement preambles for if
conditions as well.

Peter Bourgon

unread,
Nov 22, 2010, 12:48:35 PM11/22/10
to golan...@googlegroups.com
On Mon, Nov 22, 2010 at 6:31 PM, chris dollin <ehog....@googlemail.com> wrote:
> Yes, of course one can manage without it. One can manage
> without :=, return variables, and statement preambles for if
> conditions as well.

I also see no compelling downside/risk for this "syntax sugar," and
make quite effective use of it, when it's available.

Compare

func will_it_blend(unfortunate_object interface{}) bool {
// processing
return pieces > 100 ? true : false // straightforward
}

with

func will_it_blend(thing interface{}) bool {
// processing
if pieces > 100 {
return true
}
return false // unnecessarily verbose and arguably ugly
}

jimmy frasche

unread,
Nov 22, 2010, 12:53:15 PM11/22/10
to peter....@gmail.com, golan...@googlegroups.com
> func will_it_blend(unfortunate_object interface{}) bool {
> // processing
> return pieces > 100 ? true : false // straightforward
> }

You picked an unfortunate example.

func will_it_blend(unfortunate_object interface{}) bool {
// processing

return pieces > 100 // even more straightforward
}

Daniel Smith

unread,
Nov 22, 2010, 12:56:30 PM11/22/10
to jimmy frasche, peter....@gmail.com, golan...@googlegroups.com
The place I miss this the most is when printing a bool:

s := fmt.Sprintf("You %s a featherless biped", isChicken ? "are not" : "are")

Peter Bourgon

unread,
Nov 22, 2010, 12:55:22 PM11/22/10
to golan...@googlegroups.com
Ah, dangit ;)
Still, you get the idea.

jimmy frasche

unread,
Nov 22, 2010, 1:01:21 PM11/22/10
to dan...@lukenine45.net, peter....@gmail.com, golan...@googlegroups.com

For that I find myself doing something like:

transliterate := map[bool]string{true: "are not", false: "are"}
s := fmt.Sprintf("You %s a featherless biped", transliterate[isChicken])

(though generally I'd have the map defined outside the func so it's
only created once at import time)

Gustavo Niemeyer

unread,
Nov 22, 2010, 1:25:33 PM11/22/10
to peter....@gmail.com, golan...@googlegroups.com
>       return false // unnecessarily verbose and arguably ugly
>   }

This looks very nice and readable to me, without even considering the
obvious spelling:

func will_it_blend(thing interface{}) bool {

return pieces > 100
}

I'm sure you can come up with a more compelling example than you have,
but here is a compelling example *not* to have it, though:

rc = rc < 0 ? rc : add_void_completion(zh, h.xid, 0, 0);
rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
get_buffer_len(oa));
return rc<0 ? rc : adaptor_send_queue(zh, 0);

and another one:

fallback('cancelControl', (options.cancelLink ? 'link' :
(options.cancelButton ? 'button' :
options.cancelLink == options.cancelButton == false ? false : undefined)));
fallback('okControl', (options.okLink ? 'link' : (options.okButton ?
'button' :
options.okLink == options.okButton == false ? false : undefined)));

These are taken from real code, and unlike the alternatives, they're
not readable anymore.

I don't miss much using the ternary operator, and definitely don't
miss *at all* reading it back.

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter

Peter Bourgon

unread,
Nov 22, 2010, 1:47:44 PM11/22/10
to golan...@googlegroups.com
On Mon, Nov 22, 2010 at 7:25 PM, Gustavo Niemeyer <gus...@niemeyer.net> wrote:
> These are taken from real code, and unlike the alternatives, they're
> not readable anymore.
>
> I don't miss much using the ternary operator, and definitely don't
> miss *at all* reading it back.

This argument applies equally to every language feature.

I'm receptive to the idea that a complex feature should be avoided to
keep the grammar/parser/toolchain/etc. straightforward (eg. generics).

I'm receptive to the idea that a feature should be avoided if it is
(provably or self-evidently) easily/often abused (eg. operator
overloading or default arguments).

I'm even receptive to the idea that a given piece of syntax sugar
should be avoided because it is somehow outside of the "philosophy" of
a language (eg. feature requests that would bend Go's strict
formatting rules).

But I'm not receptive, and actually quite perplexed, by opposition to
a feature that imposes no cost on the compiler toolchain and is by any
measure highly idiomatic, simply on the strength of a hypothetical and
irregular _potential_ for misuse. Maybe I'm missing something.

Gustavo Niemeyer

unread,
Nov 22, 2010, 2:02:50 PM11/22/10
to peter....@gmail.com, golan...@googlegroups.com
> I'm receptive to the idea that a feature should be avoided if it is
> (provably or self-evidently) easily/often abused (eg. operator
> overloading or default arguments).

That's where I personally classify the ternary operator. Little
benefit, often abused.

Just an opinion, though.

chris dollin

unread,
Nov 22, 2010, 2:50:30 PM11/22/10
to Gustavo Niemeyer, peter....@gmail.com, golan...@googlegroups.com
On 22 November 2010 18:25, Gustavo Niemeyer

> I'm sure you can come up with a more compelling example than you have,
> but here is a compelling example *not* to have it, though:
>
>    rc = rc < 0 ? rc : add_void_completion(zh, h.xid, 0, 0);

Let's rewrite this using if-statements:

if rc < 0 { rc = rc; } else { rc = add_void_completion(zh, h.xid, 0, 0); }

What? That's silly? Well, if one can object that that is silly,
one can object that the "compelling example" is silly too.

People will write silly code -- I know I have -- using any
feature of a programming language -- nested arithmetic
expressions, function calls, initialised declatations, break
(and (fx:spit) continue), first-class functions, inheritance,
&co. Even an advocate for conditional expressions (I would
put myself in that class) doesn't require that every condition
be an expression.

Since that code is /hiding/ that rc need only be updated if
if its >= 0, it's not good code /for a conditional expression/
and is compelling example of "don't do that".

>    rc = rc < 0 ? rc : queue_buffer_bytes(&zh->to_send, get_buffer(oa),
>            get_buffer_len(oa));

Likewise.

>    return rc<0 ? rc : adaptor_send_queue(zh, 0);

This, however, seems appropriate. You're going to return
something; what you return depends on rc.

> and another one:
>
>  fallback('cancelControl', (options.cancelLink ? 'link' :
> (options.cancelButton ? 'button' :
>    options.cancelLink == options.cancelButton == false ? false : undefined)));
>  fallback('okControl', (options.okLink ? 'link' : (options.okButton ?
> 'button' :
>    options.okLink == options.okButton == false ? false : undefined)));
>
> These are taken from real code, and unlike the alternatives, they're
> not readable anymore.

You can't enforce readability in the syntax, and you don't
need to: that's what social processes -- like code reviews and
pair programming -- are for.

> I don't miss much using the ternary operator, and definitely don't
> miss *at all* reading it back.

I miss it every day, but that in itself isn't a good argument for it.

Russel Winder

unread,
Nov 22, 2010, 3:13:41 PM11/22/10
to chris dollin, Gustavo Niemeyer, peter....@gmail.com, golan...@googlegroups.com
Chris,

I agree that the conditional expression is a good thing to have; it
makes coding easier and more expressive. Witness the fact that Python
introduced it, albeit with the wrong choice of syntax. I think Go would
be better if it had a conditional expression, so much would be so much
easier.

The argument that "it is dangerous", is I think totally fallacious, and
indeed FUD. Similar in style to the argument that the for statement is
redundant because there is a while statement.

[ . . . ]

--
Russel.
=============================================================================
Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel...@ekiga.net
41 Buckmaster Road m: +44 7770 465 077 xmpp: rus...@russel.org.uk
London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder

signature.asc

Gustavo Niemeyer

unread,
Nov 22, 2010, 3:19:18 PM11/22/10
to chris dollin, peter....@gmail.com, golan...@googlegroups.com
> People will write silly code -- I know I have -- using any
> feature of a programming language -- nested arithmetic

Ok, I can't help you specifically, then. ;-)

> You can't enforce readability in the syntax, and you don't

Indeed, but I'm generally very happy to help where I can.

Andrew Gerrand

unread,
Nov 22, 2010, 5:04:29 PM11/22/10
to rus...@russel.org.uk, chris dollin, Gustavo Niemeyer, peter....@gmail.com, golan...@googlegroups.com
On 23 November 2010 07:13, Russel Winder <rus...@russel.org.uk> wrote:
> I agree that the conditional expression is a good thing to have;  it
> makes coding easier and more expressive.  Witness the fact that Python
> introduced it, albeit with the wrong choice of syntax.

Python is a totally different language to Go. Python already had
myriad ways of writing unreadable code, so I can understand they had
no qualms introducing another.

> I think Go would
> be better if it had a conditional expression, so much would be so much
> easier.

We're genuinely open to suggestions. If anyone can propose syntactical
improvements that are worth their weight, we'd be keen to adopt them.
(and we have, in the past)

So far this thread has painted a pretty clear picture of the benefits
and drawbacks the ternary operator. Gustavo's examples are
particularly illustrative.

Andrew

David Roundy

unread,
Nov 23, 2010, 8:12:47 AM11/23/10
to Andrew Gerrand, rus...@russel.org.uk, chris dollin, Gustavo Niemeyer, peter....@gmail.com, golan...@googlegroups.com
On Mon, Nov 22, 2010 at 5:04 PM, Andrew Gerrand <a...@golang.org> wrote:
>> I think Go would
>> be better if it had a conditional expression, so much would be so much
>> easier.
>
> We're genuinely open to suggestions. If anyone can propose syntactical
> improvements that are worth their weight, we'd be keen to adopt them.
> (and we have, in the past)
>
> So far this thread has painted a pretty clear picture of the benefits
> and drawbacks the ternary operator. Gustavo's examples are
> particularly illustrative.

I don't much like the C ternary operator, but I do miss being able to
use conditional expressions. I really like in Haskell being able to
write the equivalent of:

count := switch y := f(x); y {
case 0: "no widgets"
case 1: "one widget"
default: fmt.Sprint(y, " widgets")
}

Unfortunately, it's hard to see how this would work with go, which is
imperative rather than declarative, and conditionals always involve
statements rather than expressions.

David Roundy

Mikael Tillenius

unread,
Nov 24, 2010, 5:46:36 AM11/24/10
to golang-nuts
David Roundy wrote:
> count := switch y := f(x); y {
>              case 0: "no widgets"
>              case 1: "one widget"
>              default: fmt.Sprint(y, " widgets")
>              }
>
> Unfortunately, it's hard to see how this would work with go, which is
> imperative rather than declarative, and conditionals always involve
> statements rather than expressions.

I would suggest the simple rule that a switch (or if) in expression
context contain expressions rather than statements:

max := if a>b { a } else { b }

This would be ok as long as a and b have the same type. This would not
be ok:

x := if a>b { a++ } else { b++ } // Error

This might be legal but very bad style:

_ := if a>b { fmt.Print(a) } else { fmt.Print(b) }

If used for simple idioms like the max example I think this would be a
short and nice expression.

/Mikael

chris dollin

unread,
Nov 24, 2010, 5:56:39 AM11/24/10
to Mikael Tillenius, golang-nuts
On 24 November 2010 10:46, Mikael Tillenius <mt...@tillenius.com> wrote:
> David Roundy wrote:
>> count := switch y := f(x); y {
>>              case 0: "no widgets"
>>              case 1: "one widget"
>>              default: fmt.Sprint(y, " widgets")
>>              }
>>
>> Unfortunately, it's hard to see how this would work with go, which is
>> imperative rather than declarative, and conditionals always involve
>> statements rather than expressions.
>
> I would suggest the simple rule that a switch (or if) in expression
> context contain expressions rather than statements:
>
>  max := if a>b { a } else { b }

I suspect that this would break the grammar, or make it rather
fragile. (Could be wrong.) My deeper reservation is that makes
if-expressions lexically heavy, which is not what I'd want. Compare
the C-style:

max := a > b ? a : b

or Algol68-style:

max := (a > b | a | b)

or adhoc:

max := (? a > b : a : b ?)

Mikael Tillenius

unread,
Nov 24, 2010, 6:50:37 AM11/24/10
to golang-nuts


On Nov 24, 11:56 am, chris dollin <ehog.he...@googlemail.com> wrote:
> On 24 November 2010 10:46, Mikael Tillenius <mt...@tillenius.com> wrote:
> >  max := if a>b { a } else { b }
>
> I suspect that this would break the grammar, or make it rather
> fragile. (Could be wrong.) My deeper reservation is that makes
> if-expressions lexically heavy, which is not what I'd want. Compare
> the C-style:

Sure, I like the C-style "?" operator. But I would also like to use
"switch" in an expression context. How would you spell that? Nested
"?" gets unreadable fast.

/Mikael

Gustavo Niemeyer

unread,
Nov 24, 2010, 7:22:13 AM11/24/10
to Mikael Tillenius, golang-nuts
Hey Mikael,

> Sure, I like the C-style "?" operator. But I would also like to use
> "switch" in an expression context. How would you spell that?

I would personally spell that as E-r-l-a-n-g or H-a-s-k-e-l-l. :-)

chris dollin

unread,
Nov 24, 2010, 7:06:19 AM11/24/10
to Mikael Tillenius, golang-nuts

C-style in Go?

wossname :=
x == A ? yes1 :
x == B ? yes2 :
x == C ? yes3 :
otherwise

looks readable enough to me. (Personal preference would put the
:s at the beginning of the test line, not the end, but Go's semicolon-insertion
rule makes that infeasible. Unless, I suppose, we allow semicolons
before : in the syntax.)

For a switch I'm happier for the lexical load to be heaver because
I expect there to be more cases anyway: if push came to shove I'd
retreat into history and suggest we use BCPL's valof-resultis syntax.

Mikael Tillenius

unread,
Nov 24, 2010, 7:39:58 AM11/24/10
to golang-nuts
On Nov 24, 1:22 pm, Gustavo Niemeyer <gust...@niemeyer.net> wrote:
> Hey Mikael,
>
> > Sure, I like the C-style "?" operator. But I would also like to use
> > "switch" in an expression context. How would you spell that?
>
> I would personally spell that as E-r-l-a-n-g or H-a-s-k-e-l-l. :-)

Or Lisp.

The fact that other good languages have a feature is not a good
argument for not adding the same feature to Go.

"We want to keep Go simple" would be a good argument for not adding a
new feature.

I'm just saying that I like to put (simple) conditionals within
expression and this is something I miss in Go. I still think Go is
very nice language even without this particular feature.

/Mikael

Gustavo Niemeyer

unread,
Nov 24, 2010, 7:49:57 AM11/24/10
to Mikael Tillenius, golang-nuts
> The fact that other good languages have a feature is not a good
> argument for not adding the same feature to Go.

Agreed, and I'm sure you'll also agree with this version:

The fact that other good languages have a feature is not a good

argument for adding the same feature to Go.

> I'm just saying that I like to put (simple) conditionals within
> expression and this is something I miss in Go. I still think Go is
> very nice language even without this particular feature.

The point I was implying with my joke is that you are requesting a
feature common to functional languages which doesn't fit well with the
overall structure of Go.

chris dollin

unread,
Nov 24, 2010, 8:05:14 AM11/24/10
to Gustavo Niemeyer, Mikael Tillenius, golang-nuts
On 24 November 2010 12:49, Gustavo Niemeyer <gus...@niemeyer.net> wrote:

> The point I was implying with my joke is that you are requesting a
> feature common to functional languages

And non-functional ones: C & C++, BCPL, Java, and Ruby, for example.
And Go is more function-friendly than all of those bar Ruby (by virtue
of having full lexical scope & function literals).

> which doesn't fit well with the overall structure of Go.

How so?

Mikael Tillenius

unread,
Nov 24, 2010, 8:20:49 AM11/24/10
to golang-nuts


On Nov 24, 1:49 pm, Gustavo Niemeyer <gust...@niemeyer.net> wrote:
> Agreed, and I'm sure you'll also agree with this version:
>
> The fact that other good languages have a feature is not a good
> argument for adding the same feature to Go.

Indeed.

> The point I was implying with my joke is that you are requesting a
> feature common to functional languages which doesn't fit well with the
> overall structure of Go.

Since I think it would fit well I suppose we have to agree to
disagree. Speaking of functional languages:

max := func() int { switch { case a>b: return a }; return b } ()

(Note the "()" at the end)

/Mikael

Gustavo Niemeyer

unread,
Nov 24, 2010, 8:52:34 AM11/24/10
to chris dollin, Mikael Tillenius, golang-nuts
Hi again Chris,

> And non-functional ones: C & C++, BCPL, Java, and Ruby, for example.

You seem to have missed the statement context. Switches are not
expressions in these languages.

chris dollin

unread,
Nov 24, 2010, 9:09:20 AM11/24/10
to Gustavo Niemeyer, Mikael Tillenius, golang-nuts
On 24 November 2010 13:52, Gustavo Niemeyer <gus...@niemeyer.net> wrote:
> Hi again Chris,
>
>> And non-functional ones: C & C++, BCPL, Java, and Ruby, for example.
>
> You seem to have missed the statement context.

Oops. But:

> Switches are not expressions in these languages.

They are in Ruby (but "switch" is spelt "case" and "case" is spelt "when"),
and in BCPL, you use VALOF-RESULTIS to get switch expressions out
of switch statements. Algol 68 also has a switch expression but it's the
horrible kind (the cases are labelled with ascending integers) and I
can't remember the long-form spelling.

So even with the correction to switch syntax there are multiple
non-functional languages with switch expressions.

Chris

Looks like Bliss had them too.

--
Chris "allusive" Dollin

Reply all
Reply to author
Forward
0 new messages