Generic constant type parameters?

266 views
Skip to first unread message

Robert Engels

unread,
Oct 15, 2024, 8:01:42 PM10/15/24
to golang-nuts
Hi,


I could make the type and interface and add a method for ‘decimal places’, but I would like all of the constants to be resolved at compile time.

Also, if I make it an interface, it is far less efficient than passing a single int64 with generics and letting the compiler figure it out.

I know constexpr is not available, but I would think that if I could do it with methods the compiler would eventually inline the function calls anyway - possibly as constants.

I read through the docs, and it doesn’t seem possible.

I got it kind of working here https://go.dev/play/p/5ztum5NAkUp but I would really like it to be method based rather than standalone function based, and the method based I would seemingly need to duplicate a lot of code for every possible number of decimal places.

What am I missing? Ideas?

Thanks for the help.

Cleberson Pedreira Pauluci

unread,
Oct 15, 2024, 10:17:05 PM10/15/24
to golang-nuts
Hi.

Maybe you can use encapsulation instead of standalone function and generics.
Encapsulation is a fundamental principle in software engineering. It controls which parts of a package are visible from the outside and which are not.
It hides implementation details, allowing changes that do not affect dependent code.

Check it out: https://go.dev/play/p/xqwMPgB0IND

I really hope I can help you.

Cheers.
Cleberson

Ian Lance Taylor

unread,
Oct 15, 2024, 10:39:32 PM10/15/24
to Robert Engels, golang-nuts
On Tue, Oct 15, 2024 at 5:01 PM 'Robert Engels' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> Is there someway of doing this with Go generics? https://github.com/robaho/cpp_fixed/blob/6770b217acd84e4b723449e4c4bb42c92e7f2af1/fixed.h#L18-L23

Not at present, sorry.

Ian

Robert Engels

unread,
Oct 15, 2024, 10:46:36 PM10/15/24
to Cleberson Pedreira Pauluci, golang-nuts
I think you misunderstood the question or it wasn’t clear. The struct can only contain a single int64 - so you cannot add another value to hold the number of decimal places. 

The idea is to track the number of decimal places via the type (or method on the type) so the compiler knows it while generating the code. 

It’s clear in the C++ code. 

On Oct 15, 2024, at 9:17 PM, Cleberson Pedreira Pauluci <pauluci....@gmail.com> wrote:

Hi.
--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/fb1a8dd2-e1d6-499d-aabb-683afc8720a1n%40googlegroups.com.

Cleberson Pedreira Pauluci

unread,
Oct 15, 2024, 11:35:23 PM10/15/24
to golang-nuts
Hi, Robert.

I'm sorry. Now I got it.

But I think what you are trying to do is not possible in Go yet.
@Ian already answered about this.

Have you thought of another way to do this? Maybe reading the "nPlaces" value from something like a configuration file and storing it as an encapsulated field instead of a constant?
Even reading at runtime the value of an environment variable when creating the structure and storing it as a field?

Are any of these questions a possibility for you?


Robert Engels

unread,
Oct 15, 2024, 11:54:03 PM10/15/24
to Cleberson Pedreira Pauluci, golang-nuts
Not really. The idea is that use multiple types with different number of decimal places. Eg. 7 for intermediate operations and 2 for summary values, etc. 

Thanks for trying to help though. 

On Oct 15, 2024, at 10:35 PM, Cleberson Pedreira Pauluci <pauluci....@gmail.com> wrote:

Hi, Robert.

Robert Engels

unread,
Oct 15, 2024, 11:56:04 PM10/15/24
to Cleberson Pedreira Pauluci, golang-nuts
Obviously one way to do it is to copy and paste the code and/or generate under different type or package with different decimal place values. 

On Oct 15, 2024, at 10:53 PM, Robert Engels <ren...@ix.netcom.com> wrote:



Robert Engels

unread,
Oct 16, 2024, 1:19:28 AM10/16/24
to Ian Lance Taylor, golang-nuts
Hmm, I thought I had it “working” using this code https://go.dev/play/p/pzKacmi3aPe but there is a compiler error, but according to the accepted proposal documentation this should be valid https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#embedded-type-parameter-methods

Is this a compiler bug?

Marvin Renich

unread,
Oct 16, 2024, 6:57:57 AM10/16/24
to golan...@googlegroups.com
* 'Robert Engels' via golang-nuts <golan...@googlegroups.com> [241016 01:19]:
> Hmm, I thought I had it “working” using this code
> https://go.dev/play/p/pzKacmi3aPe <https://go.dev/play/p/pzKacmi3aPe>
> but there is a compiler error, but according to the accepted proposal
> documentation this should be valid
> https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#embedded-type-parameter-methods
> <https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#embedded-type-parameter-methods>

Does adding a name to the embedded type do what you want, as in
<https://go.dev/play/p/Jlso9S-LuAo>? sizeof(Fixed8) is still 8.

...Marvin

Robert Engels

unread,
Oct 16, 2024, 8:58:57 AM10/16/24
to golan...@googlegroups.com
It does! Interestingly it jumps to 24 I’m I embed Places.

This looks like a compiler bug to me - as the down usages don’t show errors - adding a property shouldn’t be required. @Ian?

> On Oct 16, 2024, at 5:57 AM, Marvin Renich <mr...@renich.org> wrote:
>
> * 'Robert Engels' via golang-nuts <golan...@googlegroups.com> [241016 01:19]:
> --
> 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.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/Zw%2BcFj7KNCcFpuFb%40basil.wdw.

Robert Engels

unread,
Oct 16, 2024, 9:04:25 AM10/16/24
to golan...@googlegroups.com
And thanks Marvin for taking a look and finding a work-around.

> On Oct 16, 2024, at 5:57 AM, Marvin Renich <mr...@renich.org> wrote:
>
> * 'Robert Engels' via golang-nuts <golan...@googlegroups.com> [241016 01:19]:

Ian Lance Taylor

unread,
Oct 16, 2024, 9:09:15 AM10/16/24
to Robert Engels, golang-nuts
On Tue, Oct 15, 2024 at 10:18 PM Robert Engels <rob...@me.com> wrote:
>
> Hmm, I thought I had it “working” using this code https://go.dev/play/p/pzKacmi3aPe but there is a compiler error, but according to the accepted proposal documentation this should be valid https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#embedded-type-parameter-methods
>
> Is this a compiler bug?

No, we decided not to implement that feature. At least not yet. See
https://go.dev/issue/43621.

Ian

robert engels

unread,
Oct 16, 2024, 9:25:26 AM10/16/24
to Ian Lance Taylor, golang-nuts
Thanks. Is there something in the language spec that covers this ? The design doc is the only thing that appears in a Google search.

> On Oct 16, 2024, at 8:09 AM, Ian Lance Taylor <ia...@golang.org> wrote:

Marvin Renich

unread,
Oct 16, 2024, 10:13:43 AM10/16/24
to golan...@googlegroups.com
* Robert Engels <ren...@ix.netcom.com> [241016 08:58]:
> It does! Interestingly it jumps to 24 I’m I embed Places.

That is expected. Embedding the interface needs to embed the value of
the interface, which consists of two pointers. This way embeds the
struct implementing the interface, which is empty.

...Marvin

Ian Lance Taylor

unread,
Oct 16, 2024, 11:30:34 AM10/16/24
to robert engels, golang-nuts
On Wed, Oct 16, 2024 at 6:24 AM robert engels <rob...@me.com> wrote:
>
> Thanks. Is there something in the language spec that covers this ? The design doc is the only thing that appears in a Google search.

I have to admit that I don't see it in the current spec.

Ian

Robert Engels

unread,
Oct 16, 2024, 1:04:00 PM10/16/24
to Ian Lance Taylor, golang-nuts
I was able to convert the fixed package to use generics to allow a variable number of decimal places.

benchmark                     old ns/op     new ns/op     delta
BenchmarkAddFixed-8           0.98          0.96          -1.66%
BenchmarkMulFixed-8           5.44          22.8          +318.15%
BenchmarkDivFixed-8           3.71          12.9          +246.97%
BenchmarkCmpFixed-8           0.26          0.54          +108.74%
BenchmarkStringFixed-8        51.8          55.2          +6.44%
BenchmarkStringNFixed-8       51.9          55.8          +7.51%

I assume the decrease in performance is due to the methods calls to determine the number of places, scaling factor etc.

Even though the method calls return constants, it doesn’t seem the compiler is inlining the constant. I suspect because I needed to declare the struct at

type FixedN[T Places] struct {
     places T
     fp int64
}

and it is determining that places is not a constant.

I think if the original generics design was implemented, so:

type FixedN[T Places] struct {
     T
     fp int64
}

then it would be able to determine that the implementation is constant for the type.

Although to be honest, I am uncertain how the struct size is 8 in the first case - because then the compiler must be able to determine that places is a constant.

The full code is available here - https://github.com/robaho/fixed/blob/generics/fixed.go - maybe I am doing something wrong?

Thoughts?
Reply all
Reply to author
Forward
0 new messages