Function overloading

614 views
Skip to first unread message

orcasar...@gmail.com

unread,
Nov 20, 2013, 4:56:55 PM11/20/13
to golan...@googlegroups.com
I'm trying to make a string package that does simple string handling and testing like converting a string to all caps and testing whether or not the passed byte/rune is a letter or not. I want to make a function that takes a character and determines if it is a letter or not. My initial plan was to make two functions with the same name but took different typed arguments. One would be accept a rune for unicode and the other would accept a byte for ascii. To my disappointment I find out that Go does not do overloading. That is, in my opinion counter productive. Now I have to make one function and require the client to know that he/she must CAST the character to a rune/byte depending on the circumstance or I have to make two functions with two different names. As Jeremy Clarkson would say "It's shtyupid! Shtyupid!". Golang team just put overloading into Go please. I beg you.

Dan Kortschak

unread,
Nov 20, 2013, 7:39:15 PM11/20/13
to orcasar...@gmail.com, golan...@googlegroups.com
Why not just take a rune and test for < 0x80?


abbed Idriss

unread,
Nov 20, 2013, 8:04:26 PM11/20/13
to Dan Kortschak, golan...@googlegroups.com
what if I went var s string = "some string" which is ultimately a slice of bytes then called the function that accepts runes as so FuncName(s[0]). It would not work unless I cast the index to a rune first. .

Dan Kortschak

unread,
Nov 20, 2013, 8:05:36 PM11/20/13
to orcasar...@gmail.com, golan...@googlegroups.com

Dan Kortschak

unread,
Nov 20, 2013, 8:10:02 PM11/20/13
to abbed Idriss, golan...@googlegroups.com
On Wed, 2013-11-20 at 20:04 -0500, abbed Idriss wrote:
> what if I went var s string = "some string" which is ultimately a
> slice of bytes then called the function that accepts runes as so
> FuncName(s[0]). It would not work unless I cast the index to a rune
> first. .
>
Two versions: http://play.golang.org/p/pHh4dWF7z8


abbed Idriss

unread,
Nov 20, 2013, 8:27:04 PM11/20/13
to Dan Kortschak, golan...@googlegroups.com
I know of these links that you're sending me. My point is that it is stupid that I have to depend on the client of the package I'm making to know that he/she has to cast from one primitive to another in order to use my package. If the Go team just included overloading this would not be a problem. If they continue to insist on no overloading then at least include generic types. and what about fmt's print functions how are they able to print runes and bytes without having to cast anything. I bet that in that case they did some kind of overloading.

Jesse McNelis

unread,
Nov 20, 2013, 8:33:43 PM11/20/13
to abbed Idriss, Dan Kortschak, golang-nuts
On Thu, Nov 21, 2013 at 12:27 PM, abbed Idriss <orcasar...@gmail.com> wrote:
I know of these links that you're sending me. My point is that it is stupid that I have to depend on the client of the package I'm making to know that he/she has to cast from one primitive to another in order to use my package. If the Go team just included overloading this would not be a problem. If they continue to insist on no overloading then at least include generic types. and what about fmt's print functions how are they able to print runes and bytes without having to cast anything. I bet that in that case they did some kind of overloading.


fmt's print functions take parameters of type interface{} and use reflect to dynamically figure out the type at runtime.
 

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

abbed Idriss

unread,
Nov 20, 2013, 8:37:37 PM11/20/13
to Jesse McNelis, Dan Kortschak, golang-nuts
So maybe I should try that?

Dan Kortschak

unread,
Nov 20, 2013, 8:38:26 PM11/20/13
to abbed Idriss, golan...@googlegroups.com
On Wed, 2013-11-20 at 20:27 -0500, abbed Idriss wrote:
> I know of these links that you're sending me. My point is that it is
> stupid that I have to depend on the client of the package I'm making
> to know that he/she has to cast from one primitive to another in order
> to use my package. If the Go team just included overloading this would
> not be a problem. If they continue to insist on no overloading then at
> least include generic types. and what about fmt's print functions how
> are they able to print runes and bytes without having to cast
> anything. I bet that in that case they did some kind of overloading.

There are two points to my previous post:

1. The functionality you are providing already exists in the
standard library.
2. A conversion is not onerous. The design decisions in Go tend to
be simplicity and transparency - this is at odds with
overloading.

Stupid is a strong (and subjective) claim. I reckon I could safely say
that the vast majority of people here are quite happy with the current
situation.

abbed Idriss

unread,
Nov 20, 2013, 8:49:12 PM11/20/13
to Dan Kortschak, golang-nuts
I know that the functionality already exists but I want to make a package that does what the other package does amongst some other things without having to worry about what standard the text you're using is encoded in. 
I'm not saying a conversion is difficult it's just inconvenient.
I have never run into a person who though overloading was complicated. If anything overloading simplifies things. I think making a function that accepts an interface then tests what encoding the text is, is more complicated than overloading.

abbed Idriss

unread,
Nov 20, 2013, 8:49:33 PM11/20/13
to Dan Kortschak, golang-nuts
I know that the functionality already exists but I want to make a package that does what the other package does amongst some other things without having to worry about what standard the text you're using is encoded in. 
I'm not saying a conversion is difficult it's just inconvenient.
I have never run into a person who though overloading was complicated. If anything overloading simplifies things. I think making a function that accepts an interface then tests what encoding the text is, is more complicated than overloading.

Jesse McNelis

unread,
Nov 20, 2013, 9:58:42 PM11/20/13
to abbed Idriss, Dan Kortschak, golang-nuts
On Thu, Nov 21, 2013 at 12:49 PM, abbed Idriss <orcasar...@gmail.com> wrote:
I know that the functionality already exists but I want to make a package that does what the other package does amongst some other things without having to worry about what standard the text you're using is encoded in. 
I'm not saying a conversion is difficult it's just inconvenient.
I have never run into a person who though overloading was complicated. If anything overloading simplifies things. I think making a function that accepts an interface then tests what encoding the text is, is more complicated than overloading.

Creating an example where overloading is complicated is rather simple.

func SomeFunc(a io.Writer, b io.Reader)
func SomeFunc(a io.Reader, b io.Writer)

var foo io.ReadWriter
var bar io.ReadWriter
SomeFunc(foo,bar) 

Which function is called? 
What would you specify as a way to remove the ambiguity?
Given that function overloading is a rarely used feature, If you specified this do you think you'd be able to remember that rule in a year?

The only purpose of function overloading is to allow you to reuse a function name within the same scope, this doesn't buy you much and is better done by creating methods of the same name on different types or putting those functions in different packages so that you're explicit about what function is being called.


abbed Idriss

unread,
Nov 20, 2013, 10:40:14 PM11/20/13
to Jesse McNelis, Dan Kortschak, golang-nuts
Well that function call probably would not work in the first place because you're passing types that are not in the perimeter list of either of the two functions(I could be wrong I'm still kind of new to Go and have not used a lot of its libraries and features.). If one uses function overloading sensibly and responsibly then overloading would not be an issue. Creating two functions with the same name that do the opposite thing is not responsible nor is it sensible. Programming languages don't write bad code. Programmers do. Not putting features in a language because some programmers are going to make bad decisions is insulting. It's punishing everyone for the crimes of some.

Dan Kortschak

unread,
Nov 20, 2013, 10:58:15 PM11/20/13
to abbed Idriss, golang-nuts
On Wed, 2013-11-20 at 20:49 -0500, abbed Idriss wrote:
> I'm not saying a conversion is difficult it's just inconvenient.

All it requires is 6 additional kestrokes per call or the definition of
a function that performs this (which amortises to approximately zero
cost in typing). I don't understand why this is so much of an issue.

> If anything overloading simplifies things.

There's a wonderful passage in the Red Dwarf novel "Better Than Life"
that discusses this kind of thinking. In this passage Arnold Rimmer
fantasises about the existence of a button to start the engines of their
ailing spaceship, and particularly about how even if the button were
gold plated, and encrusted in rubies and diamonds that it would not add
a significant cost to production of the space ship as a whole. Lister
points out that the cost is not in the button, but the miles of cabling
and so on that connect the button to the engines themselves.

abbed Idriss

unread,
Nov 20, 2013, 11:32:59 PM11/20/13
to Dan Kortschak, golang-nuts
To your first paragraph: It is not the inconvenience of additional typing. Its the inconvenience in the fact the client has to know that he/she must cast the primitive to use the function. 
To your second paragraph: I think your implying that adding function overloading to Go would be to costly. If that were the case then Google should have never developed Go in the first place.

Gerard

unread,
Nov 21, 2013, 12:40:37 AM11/21/13
to golan...@googlegroups.com, Dan Kortschak, orcasar...@gmail.com
@kortschak: I really like the second paragraph.
@abbed Idriss: It's not about costs. It's about *unforseen hidden costs*. These can get huge. And those are created because of complexity and no clear oversight of the problem.

abbed Idriss

unread,
Nov 21, 2013, 1:01:25 AM11/21/13
to Gerard, golang-nuts, Dan Kortschak
I see where your coming from if we were talking about something completely new and untested. But function overloading has been tested in many many many languages and has been shown to work just fine.

Dave Cheney

unread,
Nov 21, 2013, 1:08:08 AM11/21/13
to abbed Idriss, Gerard, golang-nuts, Dan Kortschak
On Thu, Nov 21, 2013 at 5:01 PM, abbed Idriss <orcasar...@gmail.com> wrote:
> I see where your coming from if we were talking about something completely
> new and untested. But function overloading has been tested in many many many
> languages and has been shown to work just fine.

This is not a question about if function overloading could be made to
work in Go. Clearly it could be made to work, but at a cost. The cost
that everyone is reminding you of is complexity.

Earlier in this thread Jesse gave a concrete example (which you
ignored) of where allowing function overloading would make Go more
complicated, not just from the compiler authors point of view, but for
people writing and using Go code.

func SomeFunc(a io.Writer, b io.Reader)
func SomeFunc(a io.Reader, b io.Writer)

var foo io.ReadWriter
var bar io.ReadWriter
SomeFunc(foo,bar) // which version of SomeFunc is called ? The first,
the second ?

This is an excellent example of how adding function overloading to the
language adds ambiguity, which lead to fiat rules defined in a spec,
rather than flowing cleanly from a design.

To that end, the language authors made a _choice_ not to implement
function overloading (or operator overloading for that matter) to
simplify the language, for the writer, the compiler author, but most
importantly the reader and user of Go code.

Dave
> --
> 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...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.

Gerard

unread,
Nov 21, 2013, 1:08:39 AM11/21/13
to golan...@googlegroups.com, Gerard, Dan Kortschak, orcasar...@gmail.com
I disagree with you about this. It's about the mindset.

You want function overloading. Another one wants generics. And developer nr 3 wants vectors.

Go is not like that. The spec is about 50 pages. Compare that with the 1000 of Java or C++. It's intend to be minimalistic.

And yes, that means that you have to think more about what you want to do in this situation. But most of the time it helps you a lot.

Kevin Gillette

unread,
Nov 21, 2013, 4:55:22 AM11/21/13
to golan...@googlegroups.com, Dan Kortschak, orcasar...@gmail.com
On Wednesday, November 20, 2013 9:32:59 PM UTC-7, abbed Idriss wrote:
Its the inconvenience in the fact the client has to know.

That's a good argument for why Go doesn't and won't add function overloading: the application programmer is supposed to know what they're doing. Consider C++ as a prime example of function (and template) overloading, and all the mysterious bugs that appear only days, weeks, or months later when you finally realize the compiler made bad choices for you.

Additional arguments: 1) overloading encourages abuse from both sides (library developers make bloated libraries with implementations for every conceivable combination of parameter types, often with subtle variations in semantics, and users either get confused by or don't read the documentation for the particular implementation they're using and make false assumptions about those semantics). 2) runtime selection of implementations (including through the use of reflect) would be exceptionally complex and comparatively slow; if you don't realize that, then you should stop telling Google to never have invented languages in the first place.
 
In virtually all the languages I've seen that lack operator overloading, that lack was due to deliberate choice rather than oversight or inadequate effort.

Andrew Gerrand

unread,
Nov 21, 2013, 5:39:08 AM11/21/13
to orcasar...@gmail.com, golang-nuts
Hi Abbed,

Go was designed for programming at scale; that is, teams of thousands of programming working on code bases of many millions of lines.

At scale, readability is a key concern. The faster a programmer can read and understand code, the better they can get their job done.

There's no denying that overloading is a convenient language feature. However—as others have pointed out—this convenience comes at a cost. With overloading, it's unclear which function is called when looking at a call site. To understand the function call you must know the types of its arguments. Go's system of interfaces is good at abstracting away concrete types in many situations and so, with overloading, you might need to trace through several packages' source code to figure out which function is called.

This is a real concern drawn from years of experiences with large code bases.
While a single programmer or small team might effectively use overloading, the cost at scale can be great.

You might be interested in this article that discusses Go's design goals: http://talks.golang.org/2012/splash.article

To solve your immediate problem you could use interface{}: http://play.golang.org/p/jEymSBMFsH
This is what the fmt package does internally.
But generally it's clearer and safer to just bite the bullet and write separate functions to handle each types with unique names.

Andrew

RickyS

unread,
Nov 21, 2013, 6:30:50 AM11/21/13
to golan...@googlegroups.com, orcasar...@gmail.com
"One would be accept a rune for unicode and the other would accept a byte for ascii"

In terms of numeric value, the byte is a subset of a rune.  That is, a byte is uint8 and a rune is int32.

I don't see how, in Go, you can have a source of data that alternates between type byte and type rune.  The generated machine code for comparing the two different types cannot, in general, be the same.

Go has function overloading only in the method form, where A.foo() and B.foo() are entirely different functions.   Would that work?

I don't know if your user has two different types of data to process.  If so, the packages for those data types can have something.IsPrint() and somthingElse.IsPrint().    The actual 'something' can be wrapped in an interface, so there's only one call in the user source code, but you still have to write two different isPrint functions in the two packages.

The right answer depends on your user's situation.  In particular, the Types of the users data streams.

Kevin Gillette

unread,
Nov 21, 2013, 4:15:27 PM11/21/13
to golan...@googlegroups.com, orcasar...@gmail.com
On Thursday, November 21, 2013 4:30:50 AM UTC-7, RickyS wrote:
"One would be accept a rune for unicode and the other would accept a byte for ascii"

In terms of numeric value, the byte is a subset of a rune.  That is, a byte is uint8 and a rune is int32.

byte(0xff) is semantically and numerically distinct from both []rune("\xff")[0] and '\u00ff'. It's unlikely that anyone would be using "rune" as the explicit type name for anything besides unicode ordinals.

Kevin Malachowski

unread,
Nov 22, 2013, 11:34:11 AM11/22/13
to golan...@googlegroups.com, orcasar...@gmail.com
The "Go" way to solve your problem is actually very simple:

Instead of having

func IsLetter(b byte) {...}
func IsLetter(r rune) {...}

Just do this:

func IsByteLetter(b byte) {...}
func IsRuneLetter(r rune) {...}


Aka just encode the method signature into your method name. Very clear, still concise (enough for me personally, at least), no annoying casting or having a single method do two things depending on a possibly confusing constraint on a variable.

All overloading gives us programmers is the convenience to only remember one function name and know that it can take multiple types and do the same sort of thing with it. In Go we don't have this automatic overloading, so we have to do it manually.

Also, C doesn't have overloading and it seems to be doing fine still.

-Kevin
Reply all
Reply to author
Forward
0 new messages