>> The generic dilemma is this: *do you want slow programmers, slow 
compilers and bloated binaries, or slow execution times?*

(The Java approach.) Box everything implicitly. 
This slows execution. 

I just want to add some clarification.
This does not slows a whole execution.
All that works fast will remain the same fast.

Of course, new (generic) code will be slightly slower by the following 
reasons.
1. Information about the types will be obtained not at the compile time but 
at the runtime (this requires a some time to access this information).
2. Type checking will be performed not at compile time but at the runtime 
(this also requires a some time to comparsion).

This is true but...
1. Information about the types can obtained at the compile time very fast
2. Requirements of performing the type checking at the runtime will not 
occur so often

Generic programming divides the code (which uses generic types) on the two 
different kinds:
- Generic code
- Parametrized code

Parametrized code used even in C language and, of course, it used currently 
on Go language.

Eg.

func set(slice []string, int i, val string) {
  slice[i] = val
}
func Set(list List<string>, int i, val string) {
  list.Set(i val)

}

This is identical (in purpose) parametrized source code.
Everything (both of them) are computed by the compiler and everything 
compiled into very effective and very fast binary code without the 
requirements to perform some additional work at the runtime (such as the 
type checking).

In contarst, this is a generic code (information about types is not known 
at the compile time).

func (r *List) Set(i int, val E) {
  r.slice[i] = val
}


Compiler, in this generic code, does not know what type of value will have a 
variable `val E` at runtime.

Here arrives is a reasonable question: "Should compiler perform type checking 
before performing such assignment?".

My answer is: ". No. In such case compiler should not perform type checking at 
runtime All required type checks already was performed previously."


Here is a proof:


type List<E> struct {
  slice []E
}


This means that the compiler is the guarantor of that the for some instance of 
the type `List<E>` the field `slice []E` with some type assigned to `E` of 
`List` will have the same type assigned to `E`.


Here is a proof:


list := &List<string>{}
// or

list := NewList<string>()
// where `NewList` is
func NewList<E>() *List<E> {
  i := &List<E>{}
  i.slice = make([]E, 5)
  return i
}


In both cases the compiler ensures that the every member of the generic type, 
which has the type `E`, will be assigned only to the specified type argument 
(in our case, `string`).


Now look again on our questionable code which possible can be slow.


func (r *List) Set(i int, val E) {
  r.slice[i] = val
}



What we (and compiler) know about it?

- The receiver (r *List) has some unknown type

- The parameter (val E) has some unknown type but we know that this type is the 
same as `E` in `List<E>`

- The field (List<E>.slice []E) of the receiver has some unknown type but we 
know that this type is the same as `E` in `List<E>`


Should compiler perform some (possible slow) type checking at runtime to 
compare the type `E` with type `E`?

What does this means?


This means that this generic code also can fast as it possible.


P.S.

The slow code mostly goes in the instantiation process but all the benefits 
from the use of new types cost to put up with it (and this is not very slow, 
and do not forget that arrays and maps in Go also has the "generics code" but 
it hidden from programmers).


Finally.


Question: "Does this code (with two parametrized types) requires the runtime 
type checks?"


var slice []int{}var list List<int>{}var v1 int

v1 = slice[1]
v1 = list.Get(1) // List<E> with the argument `E` set to `int` always returns 
the `int`


No. But will be executed sligtly slower than this code:


v1 = funcWhichAlwaysReturnsOnlyInt(1)


But why?

This is because generic function always returns the pointers that need to 
dereference:


v1 = list.Get(1)


// Compiled to


_temp0 := list.Get(1) // unsafe.Pointer, compiler know that it points to `int`
v1 = *(*int)(_temp0)


-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to