News for hackers. Stuff that matters.
Re:Greppability is an underrated code metric by koito17 on Tuesday September 03, 2024 @12:57AM (#41431417)
Golang has a similar property as a side-effect of the following design decision.

  ... the language has been designed to be easy to analyze and can be parsed without a symbol table
Taken from https://go.dev/doc/faq

The "top-level declarations" in source files are exactly: package, import, const, var, type, func. Nothing else. If you're searching for a function, it's always going to start with "func", even if it's an anonymous function. Searching for methods implemented by a struct similarly only needs one to know the "func" keyword and the name of the struct.

Coming from a background of mostly Clojure, Common Lisp, and TypeScript, the "greppability" of Go code is by far the best I have seen.

Of course, in any language, Go included, it's always better to rely on static analysis tools (like the IDE or LSP server) to find references, definitions, etc. But when searching code of some open source library, I always resort to ripgrep rather than setting up a development environment, unless I found something that I want to patch (which in case I set up the devlopment environment and rely on LSP instead of grep to discover definitions and references).

Re:Greppability is an underrated code metric by eptcyka on Tuesday September 03, 2024 @03:23AM (#41432217)
Golang gets zero points from me because function receivers are declared between func and the name of the function. God ai hate this design choice and boy am I glad I can use golsp.
Re:Greppability is an underrated code metric by medstrom on Tuesday September 03, 2024 @06:04AM (#41433215)
Is it just hard to get used to, or does it fundamentally make something more difficult?
Re:Greppability is an underrated code metric by eptcyka on Tuesday September 03, 2024 @07:30AM (#41433796)
I have to always add wildcards between func and the function name, because I can never know how the other developer has decided to specify the name of the receiver. This will always be a problem as far as grepping with primitive tools that don't parse the language.
Re:Greppability is an underrated code metric by medstrom on Tuesday September 03, 2024 @08:18AM (#41434211)
FYI, many people use thin wrappers like this, it's still a primitive tool that doesn't parse the language, but it can handle that problem: https://jumpshare.com/s/zMENBSr2LwwauJVjo1wS (GIF)
Re:Greppability is an underrated code metric by eptcyka on Tuesday September 03, 2024 @08:33AM (#41434334)
On machines where I control the tooling, this is not an issue. But I can’t take my config to my colleagues machine.
Re:Greppability is an underrated code metric by lanstin on Tuesday September 03, 2024 @10:49AM (#41435507)
If only AFS had succeeded. What would a modern version of this look like?
Re:Greppability is an underrated code metric by ljm on Tuesday September 03, 2024 @06:28AM (#41433353)
Can’t say I’ve ever had an issue with it, but it does get a bit wild when you have a function signature that takes a function and returns one, unless you clear it up with some types.

  func (s *Recv) foo(fn func(x any) err) func bar(y any) (*Recv, err)
As an exaggerated example. Easy to parse but not always easy to read at a glance.
Re:Greppability is an underrated code metric by kragen on Tuesday September 03, 2024 @06:59AM (#41433544)
this thread is about using `grep` to find things, and this subthread is specifically about how the `func` keyword in golang makes it easy to distinguish the definition of a function from its uses, so yes, because `grep 'func lart('` will not find definitions of `lart` as a method. you might end up with something like `grep 'func .*) *lart('` which is both imprecise and enough noise that you will not want to type it; you'll have to can it in a script, with the associated losses of flexibility and transparency
Re:Greppability is an underrated code metric by medstrom on Tuesday September 03, 2024 @07:21AM (#41433722)
That's fair, I see many examples in this thread where people pass an exact string directly to grep, as you do. I'm an avid grepper, but my grep tool [1] translates spaces to ".*?", so I would just type "func lart(" in that example and it would work.

An incremental grep tool with just this one transformation rule gets you a lot more mileage out of grep.

[1] https://github.com/minad/consult/blob/screenshots/consult-li...

EDIT: Better demo https://jumpshare.com/s/zMENBSr2LwwauJVjo1wS

Re:Greppability is an underrated code metric by kragen on Tuesday September 03, 2024 @07:33AM (#41433818)
that's going to find all the functions that take an argument named lart or of a lart type too, but it also sounds like a thing i really want to try
Re:Greppability is an underrated code metric by vitus on Tuesday September 03, 2024 @07:50AM (#41433964)
Also, anything that contains "func" and "lart" as a substring, e.g. foobar(function), blart(baz).

It's not far off from my manually-constructed patterns when I want to make sure I find a function definition (and am willing to tolerate some false positives), but I personally prefer fine-grained control over when it's in use.

Re:Greppability is an underrated code metric by medstrom on Tuesday September 03, 2024 @08:04AM (#41434100)
Mmh, I type "func\ lart(" when I need the literal string. But it's less often, so it's fair that it's slightly more to type.
Re:Greppability is an underrated code metric by kragen on Tuesday September 03, 2024 @08:12AM (#41434156)
yeah!
Re:Greppability is an underrated code metric by alienchow on Tuesday September 03, 2024 @07:20PM (#41440290)
For functions: grep -P '^func funcName\('

For methods: grep -P '^func [^)]+\) methodName\('

Hope that helps.

Re:Greppability is an underrated code metric by kragen on Tuesday September 03, 2024 @08:23PM (#41440629)
thanks, that definitely looks better! pcre is kind of working against you here tho; i assume you're invoking it out of habit
Re:Greppability is an underrated code metric by alienchow on Tuesday September 03, 2024 @09:09PM (#41440899)
I am actually unaware of downsides of PCRE. Could you explain? I hardly ever use literal grep nowadays.
Re:Greppability is an underrated code metric by kragen on Wednesday September 04, 2024 @02:47AM (#41442588)
oh, i mean that instead of

    grep -P '^func [^)]+\) methodName\('
you could say

    grep 'func [^)]*) methodName('
which is a bit less typing

however, i have to admit that i sort of ensnared myself in my own noose here by being too clever! i forgot that grep's regexp dialect only supports + if you \ it, and it took me six tries to figure out why i wasn't getting any grep hits. there's a lot to be said for the predictability and consistency of pcre!

Re:Greppability is an underrated code metric by kiitos on Wednesday September 04, 2024 @04:08PM (#41450176)
No need for any func, you can just

    grep '\) methodName\('
Re:Greppability is an underrated code metric by kragen on Wednesday September 04, 2024 @05:17PM (#41450940)

    grep: Unmatched ) or \)
but your main point might be right; the few non-method matches to (pcre) '\)\s*\w+\s*\(' in /usr/share/go-1.19 seem to be uncommon things like this:

    static void __attribute__ ((constructor)) sigsetup(void) {
    void poison() __attribute__ ((weak));
    C3 = -(R + I) // ADD(5,6) NEG(-5,-6)
Re:Greppability is an underrated code metric by sethammons on Tuesday September 03, 2024 @07:48AM (#41433941)
I search ") myFunc" to find member functions. It would be nice to search "c myFunc", but a parentheses works
Re:Greppability is an underrated code metric by db48x on Wednesday September 11, 2024 @01:48AM (#41508362)
Yea, that was my workaround for Go as well. Go both gains and loses points here.
Re:Greppability is an underrated code metric by executesorder66 on Tuesday September 03, 2024 @10:16AM (#41435211)
How many God AI's have expressed their hate for this design? /s
Re:Greppability is an underrated code metric by kazinator on Tuesday September 03, 2024 @11:02AM (#41435636)
Receivers are utterly idiotic. Like how could anyone with two working brain cells sign off on something like that?

If you don't want OOP in the language, but want people to be able to write thing.function(arg), you just make function(thing, arg) and thing.function(arg) equivalent syntax.

Re:Greppability is an underrated code metric by Pxtl on Tuesday September 03, 2024 @11:31AM (#41435941)
C# did this for extension methods and it Just Works. You just add the "this" keyword to a function in a pure-static class and you get method-like calling on the first param of that function.
Re:Greppability is an underrated code metric by kazinator on Tuesday September 03, 2024 @11:37AM (#41436004)
If the function has to be modified in any way in order to grant permission to be used that way, then it is not quite "did this".

Equivalent means that there is no difference at the AST level between o.f(a) and f(o, a), like there is no difference in C among (a + i), a[i], i[a] and (i + a).

However, a this keyword is way better than making the programmers fraction off a parameter and move it to the other side of the function name.

Re:Greppability is an underrated code metric by tczMUFlmoNk on Tuesday September 03, 2024 @01:45PM (#41437256)
A search term here is "Uniform Function Call Syntax", as present in (e.g.) D:

https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax

Re:Greppability is an underrated code metric by db48x on Wednesday September 11, 2024 @01:57AM (#41508416)
I completely agree with that.
Re:Greppability is an underrated code metric by alienchow on Tuesday September 03, 2024 @07:17PM (#41440276)
I very rarely use literal grep at all. Perl grep is my standard goto.

For functions: grep -P '^func funcName\('

For methods: grep -P '^func [^)]+\) methodName\('

Re:Greppability is an underrated code metric by aadhavans on Wednesday September 04, 2024 @01:09PM (#41448097)
What about piped grep statements?

grep func | grep functionName

Re:Greppability is an underrated code metric by madeofpalk on Tuesday September 03, 2024 @04:41AM (#41432693)
The culture of single letter variables in golang, at least in the codebases I've seen, undoes this.
Re:Greppability is an underrated code metric by alienchow on Tuesday September 03, 2024 @06:44AM (#41433450)
Single letter variables in Golang are to be used in small, local contexts. Akin to the throwaway i var in for loops. You only grep the struct methods, the same way no one greps 'this' or 'self'.

The code bases you've been reading, and even some of the native libraries, don't do it properly. Probably due to legacy reasons that wouldn't pass readability approvals nowadays.

Re:Greppability is an underrated code metric by VonGallifrey on Tuesday September 03, 2024 @05:02AM (#41432831)
The way I have seen this is that single letter variables are mostly used when declaration and (all) usages are very close together.

If I see a loop with i or k, v then I can be fairly confident that those are an Index or a Key Value pair. Also I probably don't need to grep them since everything interacting with these variables is probably already on my screen.

Everything that has a wider scope or which would be unclear with a single letter is named with a more descriptive name.

Of course this is highly dependent on the people you work with, but this is the way it works on projects I have worked on.

Re:Greppability is an underrated code metric by lelanthran on Tuesday September 03, 2024 @05:27AM (#41432988)
> The culture of single letter variables in golang, at least in the codebases I've seen, undoes this.

The convention, not just in Go, is that the smaller the scope, the smaller the variable reference.

So, sure, you're going to see single-letter variables in short functions, inside short block scopes, etc, but that is true of almost any language.

I haven't seen single-letter variables in Go that are in a scope that isn't short.

Of course, this could just mean that I haven't seen enough of other peoples Go source.

Re:Greppability is an underrated code metric by iudqnolq on Tuesday September 03, 2024 @06:28AM (#41433358)
I like using l for logger and db for database client/pool/handle even if there's a wider scope. And if the bulk of a file is interacting with a single client I might call that c.
Re:Greppability is an underrated code metric by marcosdumay on Tuesday September 03, 2024 @10:37AM (#41435397)
> that is true of almost any language

You'd be surprised how often language-local cultures break that rule on either side. And a few times it's even an improvement.

Re:Greppability is an underrated code metric by lanstin on Tuesday September 03, 2024 @10:47AM (#41435484)
Zipf's law, right - these rules are a formalization of our brain's functionality with language.

Of course, with enough code, someone does everything.

Re:Greppability is an underrated code metric by kazinator on Tuesday September 03, 2024 @11:22AM (#41435843)
E.g. food and art are very important in Japan, so stomach is i and a drawing/painting is e.
Re:Greppability is an underrated code metric by BrandoElFollito on Tuesday September 03, 2024 @01:22PM (#41437083)
Food is very very important in France so we call it nourriture :)
Re:Greppability is an underrated code metric by vitus on Tuesday September 03, 2024 @07:41AM (#41433880)
I'm not so sure about greppability in the context of Go. At least at Google (where Go originates, and whose style guide presumably has strong influence on other organizations' use of the language), we discourage "stuttering":

> A piece of Go source code should avoid unnecessary repetition. One common source of this is repetitive names, which often include unnecessary words or repeat their context or type. Code itself can also be unnecessarily repetitive if the same or a similar code segment appears multiple times in close proximity.

https://google.github.io/styleguide/go/decisions#repetitive-...

(see also https://google.github.io/styleguide/go/best-practices#avoid-...)

This is the style rule that motivates the sibling comment about method names being split between method and receiver, for what it's worth.

I don't think this use case has received much attention internally, since it's fairly rare at Google to use grep directly to navigate code. As you suggest, it's much more common to either use your IDE with LSP integration, or Code Search (which you can get a sense of via Chromium's public repository, e.g. https://source.chromium.org/search?q=v8&sq=&ss=chromium%2Fch...).

Re:Greppability is an underrated code metric by klodolph on Tuesday September 03, 2024 @02:02PM (#41437417)
The thing about stuttering is that the first part of the name is fixed anyway, MOST of the time.

If you want to search for `url.Parse`, you can find most of the usages just by searching for `url.Parse`, because the package will generally be imported as `url` (and you won’t import Parse into your namespace).

It’s not as good as find references via LSP but it is like 99% accurate and works with just grep.

Re:Greppability is an underrated code metric by vitus on Tuesday September 03, 2024 @06:33PM (#41440002)
That works somewhat for finding uses of a native Go module, although I've seen lots of cases where the module name is autogenerated and so you need to import with an alias (protobufs, I'm looking at you). It also doesn't work quite so well in reverse -- you need to find files with `package url;`, then find instances of '\bfunc Parse\('.

Lastly, one of the bigger issues is (as aforementioned sibling commenter mentioned) the application of this principle to methods. This is especially bad with method names for established interfaces, like Write or String. Even with a LSP server, you then need to trace up the call stack to figure out what concrete types the function is being called with, then look at the definitions of those types. I can't imagine wanting to do that with only (rip)grep at my disposal.

Re:Greppability is an underrated code metric by alexvitkov on Wednesday September 04, 2024 @01:14PM (#41448145)
Wild that the people who made the language that forces me to type

  if err != nil {
      return nil, err
  }
after every second statement are advising against code repetition.
Re:Greppability is an underrated code metric by kiitos on Wednesday September 04, 2024 @04:05PM (#41450128)
Wild that you don't distinguish between error handling and name repetition.
Re:Greppability is an underrated code metric by alexvitkov on Wednesday September 04, 2024 @05:28PM (#41451052)
The issue is about "repetition" - a concept that exists on the syntactic level, and is unavoidable in Go.

To put it in a way you may understand, it's when you have to press keys in the same order a lot of times and you get sad.

Re:Greppability is an underrated code metric by kiitos on Thursday September 05, 2024 @04:29PM (#41460145)
Repetition at the syntactic level, as you describe here, is, statistically, zero percent of the time spent in any meaningful software project. It, quite literally, doesn't matter.

Time spent by authors typing source code characters into their editor is almost entirely irrelevant. The only thing that matters is the time spent by readers parsing and understanding the source code in the VCS.

Re:Greppability is an underrated code metric by remram on Tuesday September 03, 2024 @04:50PM (#41439067)
In golang you get `func (someName someType) funcname`, so it's much less greppable than languages using `func funcname`
Re:Greppability is an underrated code metric by tuetuopay on Wednesday September 04, 2024 @04:33AM (#41443247)
Go is horrible due to the absence of specific "interface implementation" markers. Gets pretty hard to find where or how a type implements an interface.
Re:Greppability is an underrated code metric by kiitos on Wednesday September 04, 2024 @04:07PM (#41450162)
Interfaces are consumer contracts, they say "I need this" not "I provide this".

Regardless, any reasonable LSP will let you "Find implementations" of any interface definition.

Re:Greppability is an underrated code metric by tuetuopay on Thursday September 05, 2024 @11:19AM (#41457456)
Yup, but we're talking about grep, not lsp. And that's precisely why I don't write go without an lsp (the rare times I do write go).