Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions tlv/record_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,15 @@ type OptionalRecordT[T TlvType, V any] struct {
// TlvType returns the type of the record. This is the value used to identify
// this type on the wire. This value is bound to the specified TlvType type
// param.
func (t *OptionalRecordT[T, V]) TlvType() Type {
func (o *OptionalRecordT[T, V]) TlvType() Type {
zeroRecord := ZeroRecordT[T, V]()
return zeroRecord.TlvType()
}

// WhenSomeV executes the given function if the optional record is present.
// This operates on the inner most type, V, which is the value of the record.
func (t *OptionalRecordT[T, V]) WhenSomeV(f func(V)) {
t.Option.WhenSome(func(r RecordT[T, V]) {
func (o *OptionalRecordT[T, V]) WhenSomeV(f func(V)) {
o.Option.WhenSome(func(r RecordT[T, V]) {
f(r.Val)
})
}
Expand All @@ -126,7 +126,7 @@ func (o *OptionalRecordT[T, V]) UnwrapOrFailV(t *testing.T) V {
return inner.Val
}

// UnwrapOrErr is used to extract a value from an option, if the option is
// UnwrapOrErrV is used to extract a value from an option, if the option is
// empty, then the specified error is returned directly. This gives the
// underlying value of the record, instead of the record itself.
func (o *OptionalRecordT[T, V]) UnwrapOrErrV(err error) (V, error) {
Expand All @@ -141,10 +141,19 @@ func (o *OptionalRecordT[T, V]) UnwrapOrErrV(err error) (V, error) {
}

// Zero returns a zero value of the record type.
func (t *OptionalRecordT[T, V]) Zero() RecordT[T, V] {
func (o *OptionalRecordT[T, V]) Zero() RecordT[T, V] {
return ZeroRecordT[T, V]()
}

// ValOpt returns an Option of the underlying value. This can be used to chain
// other option related methods to avoid needing to first go through the outer
// record.
func (o *OptionalRecordT[T, V]) ValOpt() fn.Option[V] {
return fn.MapOption(func(record RecordT[T, V]) V {
return record.Val
Copy link
Collaborator

@ProofOfKeags ProofOfKeags Apr 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pondering...

This makes me wonder if we should extract out Val as a function. We have the following issue here:

-- we have these
type OptionalRecord t v = Option (Record t v)
valOpt :: Option (Record t v) -> Option v
mapOption :: (a -> b) -> Option a -> Option b

-- if we had this
val :: Record t v -> v

-- then we could do this
valOpt :: OptionalRecord t v -> Option v
valOpt = mapOption val

Porting this go to is tricky since there's no (to my knowledge) easy way for us to refer to a method without yet supplying its receiver argument. So defining something like this wouldn't fix the ergonomics:

func (r RecordT[T, V]) Val() V { ... }

func (o *OptionalRecordT[T, V]) ValOpt() fn.Option[V] {
        return fn.MapOption(RecordT.Val)(*o) // no sir
}

// but we could do this
func Val[T, V any](r Record[T, V]) V { ... }

// and then do this
func (o *OptionalRecordT[T, V] ValOpt() fn.Option[V] {
        return fn.MapOption(Val)(*o) // can do
}

I say all this because if we have to create new names for things every time we want to map a function over some functor, then Map<FUNCTOR> loses a lot of its luster.

If you have ideas and/or opinions here, lmk. This code is fine, it just points to the fact that there's room for improvement on our functional patterns.

})(o.Option)
}

// SomeRecordT creates a new OptionalRecordT type from a given RecordT type.
func SomeRecordT[T TlvType, V any](record RecordT[T, V]) OptionalRecordT[T, V] {
return OptionalRecordT[T, V]{
Expand Down Expand Up @@ -181,8 +190,8 @@ func (b BigSizeT[T]) Int() T {
}

// Record returns the underlying record interface for the record type.
func (t *BigSizeT[T]) Record() Record {
func (b *BigSizeT[T]) Record() Record {
// We use a zero value for the type here as this should be used with
// the higher order RecordT type.
return MakeBigSizeRecord(0, &t.v)
return MakeBigSizeRecord(0, &b.v)
}