What does it mean for a constant to be untyped?

huangapple go评论77阅读模式
英文:

What does it mean for a constant to be untyped?

问题

《Go编程语言规范》中提到:

> 常量可以是有类型的或无类型的。

我对此有一点疑问。
考虑规范中的这个例子:

const l = "hi"             // l == "hi"  (无类型字符串常量)
const m = string(k)        // m == "x"   (有类型字符串)

规范中说:

> 常量可以通过常量声明或转换显式地给定类型,也可以在变量声明、赋值或表达式中隐式地给定类型。

根据这个说法,为什么<code>l</code>没有类型,因为它明显是一个常量声明呢?

这个行为在另一个例子中更加清晰:

type Foo string
func f(a Foo) {}

func main() {
  f("sarkozy")

  const t = "julie gayet"
  f(t)

  s := "hollande"

  // 编译错误
  // f(s)
  
  f(Foo(s)) // 正常
}

<code>f("sarkozy")</code>能够编译通过的原因是规范中关于可赋值性的说明吗?

> x 是一个可以用类型 T 表示的无类型常量。

我的观点如下:

  • "sarkozy" 是一个无类型字面量。
  • 因此,"sarkozy" 可以表示为 <code>Foo</code>,这意味着我可以进行类型强制转换,如 <code>Foo("sarkozy") </code>。
  • <code>f(s)</code> 失败是因为 s 不是无类型的。
英文:

The Go Programming Language Specification says that:

> Constants may be typed or untyped

I am having a little doubt in my understanding.
Consider this example in the spec:

const l = &quot;hi&quot;             // l == &quot;hi&quot;  (untyped string constant)
const m = string(k)        // m == &quot;x&quot;   (type string)

The spec says:

> constant may be given a type explicitly by a constant declaration or
> conversion, or implicitly when used in a variable declaration or an
> assignment or as an operand in an expression

By this statement, why isn't <code>l</code> typed since it is clearly a constant declaration?

This behaviour is clearer with another example

type Foo string
func f(a Foo) {}

func main() {
  f(&quot;sarkozy&quot;)

  const t = &quot;julie gayet&quot;
  f(t)

  s := &quot;hollande&quot;

  //compile error
  // f(s)
  
  f(Foo(s)) // ok
}

Is the reason that <code>f("sarkozy")</code> compiles be due to this statement on Assignability in the spec?

> x is an untyped constant representable by a value of type T.

My argument is the following:

  • "sarkozy" a an untyped literal.
  • Thus "sarkozy" being representable by <code>Foo</code> means I can type coerce like this <code> Foo("sarkozy") </code>
  • <code>f(s)</code> fails because s is not untyped.

答案1

得分: 25

为什么 l 没有被声明为常量,明明它是一个常量声明?

是的,根据你的引用,它明显是一个常量声明:

> 常量可以通过常量声明来显式指定类型

然而,在你的例子中,并没有显式指定类型。只有在“在变量声明、赋值或表达式中用作操作数时”才会隐式指定类型。

f("sarkozy") 能够编译通过的原因是因为未类型化的常量 "sarkozy" 在作为表达式的操作数时隐式地获得了类型,就像在你的例子中一样。

"sarkozy" 隐式地获得了类型 Foo

那么为什么 f(s) 不能编译通过呢?(好吧,这不是问题中的问题,但问题仍然存在)

你的论点是:“f(s) 失败是因为 s 不是未类型化的。”

确实,s 不是未类型化的。s 是一个变量而不是常量,而变量不能是未类型化的。

Go 语言规范中关于变量声明的说明如下:

> 如果类型缺失且相应的表达式求值为未类型化的常量,则声明变量的类型如 §Assignments 中所述。

根据我的理解,这指的是以下内容:

> 首先,将常量转换为 bool、rune、int、float64、complex128 或 string 类型,具体取决于该值是布尔、符文、整数、浮点数、复数还是字符串常量。

因此,下面这行代码:

s := "hollande"

将声明一个类型为 string变量(而不是常量),因为右侧表达式是一个未类型化的字符串常量。类型是在变量声明时隐式给定的,而不是通过分析稍后将在其中使用的上下文来确定的。

f(s) 将导致编译错误,因为你试图使用一个类型为 string 的值,而期望的是一个类型为 Foo 的值。

英文:

Why isn't l typed since it is clearly a constant declaration?

Yes, it is clearly a constant declaration, as your quote says:

>constant may be given a type explicitly by a constant declaration

However, in your case there is no explicitly given type. You can only have an implicitly given type when "used in a variable declaration or an assignment or as an operand in an expression".

Is the reason that f("sarkozy") compiles be due to this statement on Assignability in the spec?

Yes, the reason that f(&quot;sarkozy&quot;) compiles is because the untyped constant of "sarkozy" has a type given implicitly when used as an operand in an expression such as in your case.

"sarkozy" is implicitly given the type of Foo

So why doesn't f(s) compile? (okay, that was not in the question, but the question remains)

Your argument states that: "f(s) fails because s is not untyped."

True that s is not untyped. s is a variable and not a constant, and variables cannot be untyped.

The Go specs states for Variable Declarations:

>If the type is absent and the corresponding expression evaluates to an untyped constant, the type of the declared variable is as described in §Assignments.

And that refers, from what I understand to the following:

> the constant is first converted to type bool, rune, int, float64, complex128 or string respectively, depending on whether the value is a boolean, rune, integer, floating-point, complex, or string constant.

So, the following line:

s := &quot;hollande&quot;

will declare the variable (not constant) s of type string because the right-hand expression is an untyped string constant. The type is implicitly given during the declaration of the variable, not by analyzing what context it which it later on will be used.

f(s) will then result in a compile error because you try to use a value of type string where a value of type Foo is expected.

huangapple
  • 本文由 发表于 2014年3月25日 10:01:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/22624124.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定