Tolti esempi prototipo

main
Antonio De Lucreziis 3 years ago
parent c80b23c93d
commit a11a034355

@ -1,60 +0,0 @@
package genericmethods_test
type Cons[L, R any] struct {
Left L
Right L
}
// interface cast type check
func _[T any]() LiftLower[BoxT, T] { return &Box[T]{} }
type BoxT struct{}
type Box[T any] struct {
Content T
}
func (c Box[T]) Lift() V[BoxT, T] {
return c
}
func (c *Box[T]) Lower(v V[BoxT, T]) {
*c = v.(Box[T])
}
// interface cast type check
func _[T any]() LiftLower[ChestT, T] { return &Chest[T]{} }
type ChestT struct{}
type Chest[T any] struct {
Treasure T
}
func (c Chest[T]) Lift() V[ChestT, T] {
return c
}
func (c *Chest[T]) Lower(v V[ChestT, T]) {
*c = v.(Chest[T])
}
type LiftLower[F ~struct{}, T any] interface {
Lift() V[F, T]
Lower(v V[F, T])
}
func BoxToChest[T any](b Box[T]) Chest[T] {
return Chest[T]{b.Content}
}
func BoxToChestLifted[T any](b V[BoxT, T]) V[ChestT, T] {
var bb Box[T]
bb.Lower(b)
return Chest[T]{bb.Content}.Lift()
}
type V[F ~struct{}, T any] any
type ConsF[F, T, R any] struct{}
func _() {
// l1 := Cons[Box[int], Box[string]]{}
}

@ -1,134 +0,0 @@
package genericmethods_test
import (
"database/sql"
"encoding/json"
"fmt"
"net/http"
"strings"
"testing"
)
type Validator interface {
Validate() error
}
type FooRequest struct {
A int `json:"a"`
B string `json:"b"`
}
func (foo FooRequest) Validate() error {
if foo.A < 0 {
return fmt.Errorf(`parameter "a" cannot be lesser than zero`)
}
if !strings.HasPrefix(foo.B, "baz-") {
return fmt.Errorf(`parameter "b" has wrong prefix`)
}
return nil
}
func DecodeAndValidateJSON_Generic[T Validator](r *http.Request) (T, error) {
var value T
err := json.NewDecoder(r.Body).Decode(&value)
if err != nil {
var zero T
return zero, err
}
if err := value.Validate(); err != nil {
var zero T
return zero, err
}
return value, nil
}
func TestDecodeAndValidateJSON_Generic(t *testing.T) {
m := http.NewServeMux()
m.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
foo, err := DecodeAndValidateJSON_Generic[FooRequest](r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(foo)
})
}
func DecodeAndValidateJSON_Interface(r *http.Request, target *Validator) error {
err := json.NewDecoder(r.Body).Decode(target)
if err != nil {
return err
}
if err := (*target).Validate(); err != nil {
return err
}
return nil
}
func TestDecodeAndValidateJSON_Interface(t *testing.T) {
m := http.NewServeMux()
m.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
var foo Validator = FooRequest{}
if err := DecodeAndValidateJSON_Interface(r, &foo); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(foo)
})
}
type WithPrimaryKey interface {
PrimaryKeyPtr() *string
}
type Ref[T WithPrimaryKey] string
type Table[T WithPrimaryKey] struct {
Name string
PkColumn string
}
func IdToRef[T WithPrimaryKey](table Table[T], id string) (Ref[T], error) {
if !strings.HasPrefix(id, table.Name+":") {
var zero Ref[T]
return zero, fmt.Errorf(`invalid reference %v for table %v`, id, table)
}
return Ref[T](id), nil
}
func Read[T WithPrimaryKey](db *sql.DB, table Table[T], ref Ref[T]) (*T, error) {
result := db.QueryRow(
fmt.Sprintf(
`SELECT * FROM %s WHERE %s = ?`,
table.Name, table.PkColumn,
),
string(ref),
)
var value T
if err := result.Scan(&value); err != nil {
return nil, err
}
return &value, nil
}
type User struct {
Username string
FirstName string
LastName string
}
var _ WithPrimaryKey = &User{}
func (u *User) PrimaryKeyPtr() *string {
return &u.Username
}

@ -1,31 +0,0 @@
package genericmethods_test
import (
"testing"
"golang.org/x/exp/constraints"
)
func Min[T constraints.Ordered](x, y T) T {
if x < y {
return x
}
return y
}
type Liter int
func TestInt(t *testing.T) {
{
var a, b int = 1, 2
Min(a, b)
}
{
var a, b float64 = 3.14, 2.71
Min(a, b)
}
{
var a, b Liter = 1, 2
Min(a, b)
}
}

@ -1,29 +0,0 @@
package genericmethods_test
type Stack[T any] []T
func (s *Stack[T]) Push(value T) {
*s = append(*s, value)
}
func (s Stack[T]) Peek() T {
return s[len(s)-1]
}
func (s Stack[T]) Len() int {
return len(s)
}
func (s *Stack[T]) Pop() (T, bool) {
items := *s
if len(items) == 0 {
var zero T
return zero, false
}
newStack, poppedValue := items[:len(items)-1], items[len(items)-1]
*s = newStack
return poppedValue, true
}

@ -1,99 +0,0 @@
package main
import (
"fmt"
"log"
)
//
// Database
//
type QueryResult interface {
Scan(v any) error
}
type Database interface {
Get(query string, values ...any) QueryResult
}
//
// Library
//
// DatabaseTable represents a typed database table with
type DatabaseTable[T any] struct {
Table string
IdKey string
GetIdPtr func(entry T) *string
}
func (t DatabaseTable[T]) RefForId(id string) DatabaseRef[T] {
return DatabaseRef[T]{id}
}
func (t DatabaseTable[T]) RefForValue(v T) DatabaseRef[T] {
return t.RefForId(*t.GetIdPtr(v))
}
type DatabaseRef[T any] struct{ Id string }
func DatabaseRead[T any](db Database, table DatabaseTable[T], ref DatabaseRef[T]) (*T, error) {
query := fmt.Sprintf(`select * from %s where %s = ?`, table.Table, table.IdKey)
result := db.Get(query, ref.Id)
var value T
if err := result.Scan(&value); err != nil {
return nil, err
}
return &value, nil
}
// DatabaseWrite creates a new entry in the db using the provided id in the value, this returns a typed ref to the db entry
func DatabaseWrite[T any](db Database, table DatabaseTable[T], value *T) (DatabaseRef[T], error) {
panic("not implemented")
}
// DatabaseCreate creates a new entry in the db retrieving the new generated id and returning it as a typed ref
func DatabaseCreate[T any](db Database, table DatabaseTable[T], value *T) (DatabaseRef[T], error) {
panic("not implemented")
}
//
// Client code
//
type User struct {
Username string
FirstName string
LastName string
}
var UsersTable = DatabaseTable[User]{
Table: "users",
IdKey: "username",
GetIdPtr: func(u User) *string {
return &u.Username
},
}
func _(db Database) error {
u1 := &User{"j.smith", "John", "Smith"}
log.Println(u1)
ref1, err := DatabaseWrite(db, UsersTable, u1)
if err != nil {
return err
}
u2, err := DatabaseRead(db, UsersTable, ref1)
if err != nil {
return err
}
log.Println(u2)
return nil
}

@ -1,49 +0,0 @@
package main
// type Option[T] = Some(T) | None
type Option[T any] interface {
Match(
caseSome func(value T),
caseNone func(),
)
}
type Some[T any] struct{ Value T }
func (v Some[T]) Match(caseSome func(value T), caseNone func()) {
caseSome(v.Value)
}
type None[T any] struct{}
func (v None[T]) Match(caseSome func(value T), caseNone func()) {
caseNone()
}
// type Either[A, B] = Left A | Right B
type Either[A, B any] interface {
Match(
caseLeft func(value A),
caseRight func(value B),
)
}
type Left[A, B any] struct{ Value A }
func (v Left[A, B]) Match(
caseLeft func(value A),
caseRight func(value B),
) {
caseLeft(v.Value)
}
type Right[A, B any] struct{ Value B }
func (v Right[A, B]) Match(
caseLeft func(value A),
caseRight func(value B),
) {
caseRight(v.Value)
}

@ -1,45 +0,0 @@
package main
type Expr[T any] interface{}
func Match() {
}
type numExpr struct {
value int
}
func Num(value int) Expr[int] {
return &numExpr{value}
}
type sumExpr struct {
lhs, rhs Expr[int]
}
func Sum(lhs, rhs Expr[int]) Expr[int] {
return &sumExpr{lhs, rhs}
}
type leqExpr struct {
lhs, rhs Expr[int]
}
func Leq(lhs, rhs Expr[int]) Expr[bool] {
return &leqExpr{lhs, rhs}
}
type ifExpr[R any] struct {
cond Expr[bool]
ifTrue Expr[R]
ifFalse Expr[R]
}
func If[R any](cond Expr[bool], ifTrue Expr[R], ifFalse Expr[R]) Expr[R] {
return &ifExpr[R]{cond, ifTrue, ifFalse}
}
func main() {
}

@ -1,61 +0,0 @@
package example5_test
import (
"bytes"
"io"
"testing"
)
func WriteSingleWithInterface(w io.Writer, data byte) {
w.Write([]byte{data})
}
//go:noinline
func WriteSingleWithInterfaceNoInline(w io.Writer, data byte) {
w.Write([]byte{data})
}
func WriteSingleWithGeneric[T io.Writer](w T, data byte) {
w.Write([]byte{data})
}
//go:noinline
func WriteSingleWithGenericNoInline[T io.Writer](w T, data byte) {
w.Write([]byte{data})
}
func Test1(t *testing.T) {
t.Log(`Ok!`)
}
func BenchmarkInterface(b *testing.B) {
d := &bytes.Buffer{}
for i := 0; i < b.N; i++ {
WriteSingleWithInterface(d, 42)
}
}
func BenchmarkInterfaceNoInline(b *testing.B) {
d := &bytes.Buffer{}
for i := 0; i < b.N; i++ {
WriteSingleWithInterfaceNoInline(d, 42)
}
}
func BenchmarkGeneric(b *testing.B) {
d := &bytes.Buffer{}
for i := 0; i < b.N; i++ {
WriteSingleWithGeneric(d, 42)
}
}
func BenchmarkGenericNoInline(b *testing.B) {
d := &bytes.Buffer{}
for i := 0; i < b.N; i++ {
WriteSingleWithGenericNoInline(d, 42)
}
}
Loading…
Cancel
Save