FAQ
Does anyone think this small inconsistency is somewhat unfortunate?

package main

import "fmt"

func main() {
*// Ok: Functions that return 0, 1, 2, ... values*
f0 := func() {}
f1 := func() (string) { return "1" }
f2 := func() (string, string) { return "1", "2" }

// func Println(a ...interface{}) (n int, err error)

*// Ok: Function that accepts 0, 1, 2, ... values*
fmt.Println()
fmt.Println("1")
fmt.Println("1", "2")

*// Not Ok: 0 values*
*// Ok: 1, 2, ... values*
fmt.Println(f0()) // Error: f0() used as value
fmt.Println(f1())
fmt.Println(f2())
}

http://play.golang.org/p/KT16yTTySZ

Or are there good reasons for this decision in the language spec? I'd like
to know, because I can't think of one.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Jan Mercl at May 29, 2013 at 11:02 pm
    It seems to me that you've forgotten to say where or what is the problem. I
    fail to find it.

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jan Mercl at May 30, 2013 at 12:07 pm

    On Thu, May 30, 2013 at 1:01 AM, Jan Mercl wrote:
    It seems to me that you've forgotten to say where or what is the problem. I
    fail to find it.
    Ok, even without getting any answer, from what others I infer what you
    probably mean. If that's the case then given:

             func foo() {}

    this must be valid as well for you "problem" case:

            a := foo()

    I believe you don't expect the above statement to be legal. Then

            fmt.Println(foo())

    is only the exactly very same "problem". That's why I didn't even
    consider that you're talking about it and was not able to see the
    "problem".

    -j

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dmitri Shuralyov at May 30, 2013 at 3:34 pm
    I am primarily interested in the case of making variadic functions accept
    input from funcs that return 0 values.

    // I think it'd be nice if this was valid
    func g() {}
    func f(...int i) {}
    func h() {
         f(g())
    }

    The problem is that to make it work only in that case, the spec would have
    to be made slightly more complex by adding an exception, as Ian pointed out
    previously:

    So what you are suggesting is that we add a further exception to the
    spec. At the end of that paragraph in the spec, we could say "in [the
    case for variadic functions]
    g is permitted to have no return values."


    I am more indifferent towards making this case work:

    // Not sure if this is good or bad
    func g() {}
    func f() {}
    func h() {
         f(g())
    }

    Making both work can be made by simplifying the spec and removing the "and
    g must have at least one return value" exception.

    However, most other counter-examples that were posted here would remain
    invalid code in either case.

    func foo() {}
    a := foo() // Error: assignment count mismatch: 1 = 0

    // Single-value context, so all funcs are required to return exactly one
    value (not zero, not two, not three, etc.)
    a := []byte{a(), b(), c(), d(), e()} // Therefore len(a) must be 5

    // Single-value context, so all funcs are required to return exactly one
    value (not zero, not two, not three, etc.)
    fmt.Sprintf("%s", a(), b(), c(), d(), e()) => "Guess who I am!" //
    Hypothetical error: zero-value a() in single-value context (actual error:
    a() used as value)
    fmt.Sprintf("%s%s%s%s%s%s%s%s%s%s", a(), b(), c(), d(), e()) => "Guess who
    I am!" // Error: multiple-value a() in single-value context

    On Thursday, May 30, 2013 8:07:02 AM UTC-4, Jan Mercl wrote:

    On Thu, May 30, 2013 at 1:01 AM, Jan Mercl <0xj...@gmail.com <javascript:>>
    wrote:
    It seems to me that you've forgotten to say where or what is the
    problem. I
    fail to find it.
    Ok, even without getting any answer, from what others I infer what you
    probably mean. If that's the case then given:

    func foo() {}

    this must be valid as well for you "problem" case:

    a := foo()

    I believe you don't expect the above statement to be legal. Then

    fmt.Println(foo())

    is only the exactly very same "problem". That's why I didn't even
    consider that you're talking about it and was not able to see the
    "problem".

    -j
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ziad Hatahet at May 30, 2013 at 5:56 pm
    Languages like Scala and Rust allow what Dimitri mentioned in the original
    post, while disallowing the code sample that Ian listed.

    Take for instance:

    def foo() {
       println("foo")
    }

    def bar(): Unit = { // This is a more verbose way of defining "foo()" above.
       println("bar") // Note the Unit return type above.
    }

    def main(args: Array[String]) {
       println("value is: " + foo()) // Prints: "value is: ()"
       println(foo(bar()) // error: too many arguments for method foo: ()Unit
    }


    Hence, the goals are not mutually exclusive.

    --
    Ziad

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Gustavo Niemeyer at May 29, 2013 at 11:06 pm

    On Wed, May 29, 2013 at 7:56 PM, Dmitri Shuralyov wrote:
    // Not Ok: 0 values
    // Ok: 1, 2, ... values
    fmt.Println(f0()) // Error: f0() used as value (...)
    Or are there good reasons for this decision in the language spec?
    You're asking to print something that simply doesn't exist. f0 doesn't
    return anything, so there's no reasonable outcome out of what that
    code is trying to do.


    gustavo @ http://niemeyer.net

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dmitri Shuralyov at May 29, 2013 at 11:20 pm
    You're asking to print something that simply doesn't exist. f0 doesn't
    return anything, so there's no reasonable outcome out of what that

    code is trying to do.


    That's not true. Println() prints its operands, separated by spaces, and
    appends a newline. fmt.Print() is valid Go code that prints a newline,
    despite there being no operands.

    I can imagine fmt.Println(f0()) behaving exactly like fmt.Println() does
    (except, f0() is executed first, and then fmt.Println()).

    ---

    I'm not a language design expert (but I'd like to learn more about the
    topic, hence I'm posting the question here), but to me, a hypothetical
    language Go' where the above program compiles without error seems
    *simpler*than Go.

    One of the following two options must be true:

    1. Either that hypothesis is wrong, and in fact the Go' language where the
    above program compiles without error is actually more *complex* than the
    existing Go language (with the error above). If so, can someone please
    explain why that's the case?

    2. Or, the hypothesis is right and Go' is indeed simpler, but there are
    other reasons why the *added complexity* of having the above-mentioned
    error included is deemed to be *worth it*. In which case, I'd also like to
    know what the reasons are.

    Thank you.

    On Wed, May 29, 2013 at 7:06 PM, Gustavo Niemeyer wrote:
    On Wed, May 29, 2013 at 7:56 PM, Dmitri Shuralyov wrote:
    // Not Ok: 0 values
    // Ok: 1, 2, ... values
    fmt.Println(f0()) // Error: f0() used as value (...)
    Or are there good reasons for this decision in the language spec?
    You're asking to print something that simply doesn't exist. f0 doesn't
    return anything, so there's no reasonable outcome out of what that
    code is trying to do.


    gustavo @ http://niemeyer.net
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Martin Schnabel at May 29, 2013 at 11:24 pm

    On 05/30/2013 01:20 AM, Dmitri Shuralyov wrote:
    You're asking to print something that simply doesn't exist. f0 doesn't

    return anything, so there's no reasonable outcome out of what that

    code is trying to do.


    That's not true. Println() prints its operands, separated by spaces, and
    appends a newline. fmt.Print() is valid Go code that prints a newline,
    despite there being no operands.

    I can imagine fmt.Println(f0()) behaving exactly like fmt.Println() does
    (except, f0() is executed first, and then fmt.Println()).
    http://play.golang.org/p/KDF8JVKcOr ?

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Gustavo Niemeyer at May 29, 2013 at 11:50 pm

    On Wed, May 29, 2013 at 8:20 PM, Dmitri Shuralyov wrote:
    You're asking to print something that simply doesn't exist. f0 doesn't
    return anything, so there's no reasonable outcome out of what that
    code is trying to do.
    That's not true. Println() prints its operands, separated by spaces, and
    appends a newline. fmt.Print() is valid Go code that prints a newline,
    despite there being no operands.
    If you have an empty glass, you cannot drink what is inside, or boil
    it, or do anything else with it, because it does not exist.

    The result of f0() does not exist. You cannot print it, or provide it
    as a parameter to anything, or assign it to a variable, or do anything
    else with it, because it simply does not exist.


    gustavo @ http://niemeyer.net

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ian Lance Taylor at May 29, 2013 at 11:52 pm

    On Wed, May 29, 2013 at 4:20 PM, Dmitri Shuralyov wrote:
    I'm not a language design expert (but I'd like to learn more about the
    topic, hence I'm posting the question here), but to me, a hypothetical
    language Go' where the above program compiles without error seems simpler
    than Go.

    One of the following two options must be true:

    1. Either that hypothesis is wrong, and in fact the Go' language where the
    above program compiles without error is actually more complex than the
    existing Go language (with the error above). If so, can someone please
    explain why that's the case?

    2. Or, the hypothesis is right and Go' is indeed simpler, but there are
    other reasons why the added complexity of having the above-mentioned error
    included is deemed to be worth it. In which case, I'd also like to know what
    the reasons are.
    The part of the spec that invalidates your example is the phrase "and
    g must have at least one return value" in the section
    http://golang.org/ref/spec#Calls . This is there specifically to
    disallow code like this:

    func g() {}
    func f() {}
    func h() {
         f(g())
    }

    This code appears to pass the result parameters of g() as the
    arguments to f(), but it is actually just confusing.

    So what you are suggesting is that we add a further exception to the
    spec. At the end of that paragraph in the spec, we could say "in this
    case g is permitted to have no return values."

    Based on that, I'm going with your option 1: supporting this case
    would make the Go language (slightly) more complicated.

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dmitri Shuralyov at May 30, 2013 at 12:19 am
    mb0, that's a neat way to go around the type system.

    Ian, thanks, your post was insightful.

    So what you are suggesting is that we add a further exception to the
    spec. At the end of that paragraph in the spec, we could say "in this
    case g is permitted to have no return values."

    Actually, what I was suggesting is to remove the "and g must have at least
    one return value" exception, i.e.:

    The call of f must contain no parameters other than the call of g, and g
    must have at least one return value. If f has a final ... parameter, it is
    assigned the return values of g that remain after assignment of regular
    parameters.


    Could become more simply:

    The call of f must contain no parameters other than the call of g. If f has
    a final ... parameter, it is assigned the return values of g that remain
    after assignment of regular parameters.


    Which is simpler. However, that would permit the code you pointed out.

    func g() {}
    func f() {}
    func h() {
         f(g())
    }

    I can see there may be some value in disallowing that.

    Is that the only reason for the "and g must have at least one return value"
    clause or are there more?

    On Wednesday, May 29, 2013 7:52:18 PM UTC-4, Ian Lance Taylor wrote:
    On Wed, May 29, 2013 at 4:20 PM, Dmitri Shuralyov wrote:

    I'm not a language design expert (but I'd like to learn more about the
    topic, hence I'm posting the question here), but to me, a hypothetical
    language Go' where the above program compiles without error seems simpler
    than Go.

    One of the following two options must be true:

    1. Either that hypothesis is wrong, and in fact the Go' language where the
    above program compiles without error is actually more complex than the
    existing Go language (with the error above). If so, can someone please
    explain why that's the case?

    2. Or, the hypothesis is right and Go' is indeed simpler, but there are
    other reasons why the added complexity of having the above-mentioned error
    included is deemed to be worth it. In which case, I'd also like to know what
    the reasons are.
    The part of the spec that invalidates your example is the phrase "and
    g must have at least one return value" in the section
    http://golang.org/ref/spec#Calls . This is there specifically to
    disallow code like this:

    func g() {}
    func f() {}
    func h() {
    f(g())
    }

    This code appears to pass the result parameters of g() as the
    arguments to f(), but it is actually just confusing.

    So what you are suggesting is that we add a further exception to the
    spec. At the end of that paragraph in the spec, we could say "in this
    case g is permitted to have no return values."

    Based on that, I'm going with your option 1: supporting this case
    would make the Go language (slightly) more complicated.

    Ian
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ian Lance Taylor at May 30, 2013 at 12:37 am

    On Wed, May 29, 2013 at 5:19 PM, Dmitri Shuralyov wrote:
    Which is simpler. However, that would permit the code you pointed out.

    func g() {}
    func f() {}
    func h() {
    f(g())
    }

    I can see there may be some value in disallowing that.

    Is that the only reason for the "and g must have at least one return value"
    clause or are there more?
    That's the only reason I recall. I remember discussing it when we
    added the ability to write f(g()) when g has multiple result
    parameters. For that it's worth, I'm pretty sure that preceded the
    current notion of variadic functions.

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Gustavo Niemeyer at May 30, 2013 at 2:00 am

    On Wed, May 29, 2013 at 9:37 PM, Ian Lance Taylor wrote:
    On Wed, May 29, 2013 at 5:19 PM, Dmitri Shuralyov wrote:

    Which is simpler. However, that would permit the code you pointed out.

    func g() {}
    func f() {}
    func h() {
    f(g())
    }

    I can see there may be some value in disallowing that.

    Is that the only reason for the "and g must have at least one return value"
    clause or are there more?
    That's the only reason I recall. I remember discussing it when we
    added the ability to write f(g()) when g has multiple result
    parameters. For that it's worth, I'm pretty sure that preceded the
    current notion of variadic functions.
    The idea of allowing nothing to be used as a value is flawed in several fronts..

         fmt.Sprintf("%s", a(), b(), c(), d(), e()) => "Guess who I am!"


    gustavo @ http://niemeyer.net

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Jesse McNelis at May 30, 2013 at 2:05 am

    On Thu, May 30, 2013 at 12:00 PM, Gustavo Niemeyer wrote:

    The idea of allowing nothing to be used as a value is flawed in several
    fronts..

    fmt.Sprintf("%s", a(), b(), c(), d(), e()) => "Guess who I am!"
    and that's basically the same as:
    a := []byte{a(),b(),c(),d(),e()} //what is the len() of a?
    which is quite a bit more scary.

    --
    =====================
    http://jessta.id.au

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dan Kortschak at May 30, 2013 at 2:20 am

    On Thu, 2013-05-30 at 12:05 +1000, Jesse McNelis wrote:
    and that's basically the same as:
    a := []byte{a(),b(),c(),d(),e()} //what is the len() of a?
    which is quite a bit more scary.
    Except that non-unity result parameter lists are not allowed in literal
    []T assignments, whereas they are in function calls.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Martin Schnabel at May 30, 2013 at 10:02 am

    On 05/30/2013 02:19 AM, Dmitri Shuralyov wrote:
    mb0, that's a neat way to go around the type system.
    i actually meant to write this http://play.golang.org/p/eN38hsTrCH
    to highlight the variadic nature of Println.
    i understand an empty fmt.Println() as a fmt.Println(nil...) with an
    empty slice as parameter.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedMay 29, '13 at 10:56p
activeMay 30, '13 at 5:56p
posts16
users8
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase