
Go’s hidden pragmas - spacey
https://dave.cheney.net/2018/01/08/gos-hidden-pragmas
======
pcwalton
For once, I'm gonna be the one sticking up for Go here. :) Pragmas or
annotations are kind of unavoidable, and I don't think that it was a mistake
to include them. I wouldn't have used comment syntax, but whatever; that's a
minor quibble.

Actually, I wish Rust had done one thing that Go did: namespacing the pragmas.
That would have been a more future-proof thing to do, because macros
effectively give us user-definable pragmas, and once you have user-definable
pragmas you have name collision problems. Kudos to the Go team for being
forward-thinking there. I suspect we'll have to figure out some kind of
solution here, but it won't be as pleasant as if we had just used namespaces
in the first place.

~~~
kibwen
_> Actually, I wish Rust had done one thing that Go did: namespacing the
pragmas._

Yeah, of all the papercuts that the Rust 1.0 macros system had the
idiosyncratic modularization/namespacing rules were the most unfortunate.
Happily there's already an accepted RFC for the design of macro modularization
([https://github.com/rust-
lang/rfcs/blob/master/text/1561-macr...](https://github.com/rust-
lang/rfcs/blob/master/text/1561-macro-naming.md)) that simply makes all macros
operate under the same namespacing rules as all other items, and it looks to
be mostly implemented as well (though it won't hit stable Rust until the
larger macros 2.0 initiative is finished). And as for future-proofing, I'm not
too concerned: all the "standard" macros can be exported from the stdlib
prelude without a problem, and any libs that update to macros 2.0 can easily
export the updated macros just like any other public item and consumers can
update their code with only a single `use` declaration (it's not like the old
macros system doesn't require explicit importing anyway, it's just unique and
janky). Very much looking forward to the simplicity and consistency of the new
system.

~~~
ben0x539
cool, I didn't realize this applied to attribute-style macro application too.

------
bla2
Poor Rob Pike. He always tries to make things simple, and over they time
entropy always does its thing. You can hear his frustration in his cited
comment.

~~~
pjmlp
All languages that tried to fight complexity either grew up to adopt
complexity and stay relevant, or faded away.

Programming languages don't get complex just for fun, their designers are
tackling actual relevant issues.

Go community doesn't seem to have learned much from the past.

~~~
PopsiclePete
>All languages that tried to fight complexity either grew up to adopt
complexity and stay relevant, or faded away.

And yet, to this day, C is just as, if not more popular, than C++. Why is
that? I can do _so much more_ in C++, but I, and my colleagues, pick plain-old
C every time.

~~~
pcwalton
You're in the minority. For new projects, C is much less popular than C++.

~~~
marrs
It might not be that easy to tell. The C++ I write (for myself) is essentially
plain C. No templates, dynamic dispatch, constructors, or exceptions. Most of
the standard libs I use begin with the letter 'c'.

It uses some C++ features, but it's philosophically much closer to C code.

~~~
pjmlp
If it only compiles with a C++ compiler, it is C++, regardless of the amount
of language features being used.

~~~
marrs
That's fine, but I don't think that's what people mean when they say C++. I
certainly wouldn't call myself a C++ coder and, if I applied for a C++ job,
I'm pretty sure that, after I had explained that I don't do exceptions,
virtuals, or the STL, I'd be politely shown the door.

------
tidwall
The page is missing the best one of them all //go:linkname, which allows for
linking in private functions from other packages. Including the Go runtime.
For example:
[https://github.com/tidwall/algo/blob/master/algo.go](https://github.com/tidwall/algo/blob/master/algo.go)

~~~
nickcw
linkname is brilliant thanks! I've done that sort of thing with an assembler
shim in the past.

------
jonathanstrange
Pragmas are always a bad idea. The Ada community has learned that the hard
way. Whatever the pragma does, it should be part of the language standard and
never be implementation-dependent.

It's time that language designers include _language pragmatics_ in the core
language. That includes for example big O information about data structures,
packing of structures, alignment properties, memory access information, etc.
Currently, in most if not all languages this information is spread all over
levels, from nonstandardized compiler flags over pragmas up to the core
language. It's a huge mess.

~~~
masklinn
> Pragmas are always a bad idea. The Ada community has learned that the hard
> way. Whatever the pragma does, it should be part of the language standard
> and never be implementation-dependent.

> It's time that language designers include language pragmatics in the core
> language. That includes for example big O information about data structures,
> packing of structures, alignment properties, memory access information, etc.

So pragmas are "always a bad idea" but you should have them "in the core
language"… Don't you feel your comment is pretty contradictory?

A pragma is a directive for the system (mostly compiler), that's orthogonal to
it being implementation-specific.

~~~
jonathanstrange
You misread my comment. The functionality offered by pragmas must be mandatory
and in the core language, whether you call them pragmas or not. Everything
else leads to problems.

It's true that if pragmas were all fully specified in the core language and
not optional, then they wouldn't pose any problems. In reality, however, some
pragmas are regulated by the core language and others are implementation
specific additions. The result is a huge mess, it's the #1 source of
incompatibility of standardized languages like Ada. Even just having optional
pragmas in the core language is problematic, because at one point or another
developers will start relying on the optional functionality to do something
that one implementation does and another doesn't. Optional optimization and
packing directives are typical examples. In theory they shouldn't be able to
break programs, in reality they do.

~~~
masklinn
> You misread my comment. The functionality offered by pragmas must be
> mandatory and in the core language, whether you call them pragmas or not.
> Everything else leads to problems.

Your previous comment literally states that pragmas are _always bad_ , then
goes on to state that they should be included in the core language. This one
does not retract the original statement that pragmas are "always a bad idea"
but further asserts pragmas "must be mandatory and in the core language".

I don't think I misread your comment, no. You may have miswritten your comment
when you meant that, say pragmas should not be optional and/or implementation
dependent[0], but that's on you.

[0] I've no idea whether that's you mean given again you state that pragmas
should both not exist and be part of the core language.

~~~
jonathanstrange
When I said "pragmas are always a bad idea" I was talking about pragmas as
they are implemented in current languages like e.g. Ada. In most languages
pragmas are added to the language without being integrated into it. For
example, in Ada you write "pragma (Something);" next to other statements to
influence their interpretation by the compiler. Other languages have similar
mechanisms that are somehow outside the core language or added on top of it.
These types of pragmas are _always a bad idea_.

I also argued that the functionality of pragmas must be represented as non-
optional choices in the core languages. This is one of the lessons that the
Ada community has learned over time - but it's too late to change this now in
Ada.

So yes, pragmas are always a bad idea if we talk about the way they are
implemented in most languages. The functionality of pragmas should be part of
the core language, with proper syntax and semantics.

I hope that clarifies what I've stated and which you haven't understood, and
that, your nitpicking aside, my position now makes sense to you. If not, there
is not much I can do, I just wanted to point out a lesson learned in the Ada
community, which is very stringent about language definitions. If you're
interested in these kind of topics, I can recommend Michael Scott's
_Programming Language Pragmatics_.

------
yokohummer7
I hated the idea of using comments as directives when Go 1.4 introduced
//go:generate. But, holy, they were there from the beginning?

They bring back my painful memories of the old days when I had to use
conditional comments to support IE6...

~~~
marcosdumay
Every higher level language has directives nowadays, and those almost every
time encoded in comments.

Honestly, between documentation, compiler pragmas, linter directives,
packaging and linking instructions, and etc, we are getting into a point where
languages will need to specify something like "comments starting with this
string must be ignored".

~~~
lurr
> and those almost every time encoded in comments

which lanugages do that?

------
tapirl
The pragmas in Go are not intended to be used in general user code. They
should be only used in Go runtime implementation and standard packages. The
pragmas in Go are just some hints for compilers. Compilers will ignore many of
the pragmas used in custom user code.

~~~
buro9
Except for the build conditional flags: [https://golang.org/pkg/go/build/#hdr-
Build_Constraints](https://golang.org/pkg/go/build/#hdr-Build_Constraints)

Which are pretty useful when you want to target tests to different versions of
Go when std lib exhibits different behaviour (behaviour changed as std lib
matured).

~~~
vorg
Also when you want to put package-main files in a library package directory,
you need to put

    
    
      // +build ignore
    

near the top of it.

------
nerdponx
This seems like one arugment to be made in favor of giving the language first-
class access to the compiler, à la Lisp.

~~~
nemo1618
Not at all! This a common impulse among programmers: upon seeing a specific
case, you want to make it as abstract and generic as possible. This maximizes
the power and flexibility available to the programmer.

However, the design philosophy of Go pulls in the exact opposite direction! Go
emphasizes simplicity and large-scale engineering -- i.e. standardization.
(gofmt is the canonical example of this.) Giving programmers the power to
manipulate the compiler in arbitrary ways would be a nightmare for Go's
designers. It opens the door to "clever" code that you tear your hair out
debugging 6 months later. The strength of Go is precisely that it makes it
difficult to write "clever" code. Go looks pretty much the same everywhere.
Which is a little boring, sure; but for me (and many others), that's an
acceptable trade-off.

~~~
pjmlp
I rather prefer the Ada, Eiffel, Delphi, C++, Java and C# decisions regarding
large scale engineering.

------
saagarjha
> Given the race detector has no known false positives, there should be very
> little reason to exclude a function from its scope.

Performance, maybe?

~~~
vardump
> Performance, maybe?

Performance for running race detector (debug) binaries? Are you worried slower
code hides a race?

I can't think of a reason to ship or use race detector compiled binaries in
production. Or do you have something in mind?

~~~
saagarjha
Yeah, that’s what I was getting at. Race condition detection would probably
slow down your code, so you probably wouldn’t use it in production.

~~~
LukeShu
Race detection is totally disabled for production binaries, because it does
slow down the code.

The question is: For debug builds that explicitly have the "-race" flag passed
to the compiler, why would you want to disable race detection for a specific
function?

~~~
nemo1618
I actually do have a real example of this.

We use -race during our automated testing. The setup for some of our tests
involves CPU mining (rapid blake2b hashing). This code definitely doesn't have
any races, and it runs waaaaay slower when race detection is enabled. So we
could speed up our tests significantly by disabling race detection just for
the setup phase.

~~~
hmmdar
Have you considered enabling parallel tests for that package? It let's test
functions run in parallel with each other. Might address some of the issue
with the performance.

------
cjslep
Go's "pragmas" are already exposed to the developer via go generate [0].

Edit: Granted, this is not a directive for the compiler though.

[0] [https://blog.golang.org/generate](https://blog.golang.org/generate)

