Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Identity function #420

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

l0rem1psum
Copy link

Adds an identity function.

@samber
Copy link
Owner

samber commented Jun 27, 2024

Hi @l0rem1psum and thanks for this first contrib.

Can you explain why this helper would help the Go community?

@ccoVeille
Copy link
Contributor

Same question here.

@l0rem1psum
Copy link
Author

l0rem1psum commented Jun 28, 2024

One use case I can think of now is when you want to dynamically apply a series of operations on a type. For instance:

package main

import "fmt"

type Operation[T any] func(t T) T

func main() {
	value := 1

	// operations are dynamically populated
	operations := []Operation[int]{
		identity, double, triple,
	}

	for _, op := range operations {
		value = op(value)
	}

	fmt.Println(value)
}

func identity(n int) int { return n }
func double(n int) int   { return n * 2 }
func triple(n int) int   { return n * 3 }

Essentially, you want a "no-op" in a series of "op"s, and it's awkward to use nil or other approaches to distinguish the "no-op" from the rest.

There are other more interesting use cases I believe. This is the simplest one I can come up right now since I forgot my original intention.

@ccoVeille
Copy link
Contributor

ccoVeille commented Jun 28, 2024

I assumed it would be something like that, been t I'm unsure about the need

Let's wait for maintainer's feedback

@lesichkovm
Copy link

May be its me, but I still cannot see a use case where this is usable. It basically returns the value without any checks or modifications.

@l0rem1psum
Copy link
Author

l0rem1psum commented Jul 1, 2024

May be its me, but I still cannot see a use case where this is usable. It basically returns the value without any checks or modifications.

I think you basically just explained the purpose of identity function yourself: return the value unchanged.

It's basically like the number 0 in addition and number 1 in multiplication. It's neutral but not unimportant.

I'm no type theorist but I personally think of identity as a "default/placeholder" function for functions. In the above example, imagine how would you represent a no-op amongst other ops.

@lesichkovm
Copy link

I think you basically just explained the purpose of identity function yourself: return the value unchanged.

It's basically like the number 0 in addition and number 1 in multiplication. It's neutral but not unimportant.

I'm no type theorist but I personally think of identity as a "default/placeholder" function for functions. In the above example, imagine how would you represent a no-op amongst other ops.

If there is nothing to do, I would not put it in the array of opperations on the first place:

Instead of:

operations := []Operation[int]{
	identity, double, triple,
}

Just not include the noop operation:

operations := []Operation[int]{
    double, triple,
}

@l0rem1psum
Copy link
Author

l0rem1psum commented Jul 2, 2024

I think you basically just explained the purpose of identity function yourself: return the value unchanged.

It's basically like the number 0 in addition and number 1 in multiplication. It's neutral but not unimportant.

I'm no type theorist but I personally think of identity as a "default/placeholder" function for functions. In the above example, imagine how would you represent a no-op amongst other ops.

If there is nothing to do, I would not put it in the array of opperations on the first place:

Instead of:


operations := []Operation[int]{

	identity, double, triple,

}

Just not include the noop operation:


operations := []Operation[int]{

    double, triple,

}

Yes, but what if the operation comes from another function? (This is most likely the case in reality) For example,

func getIntOperation() Operation[int] {
    // ...
}

How would you determine there is no op?

@lesichkovm
Copy link

lesichkovm commented Jul 6, 2024

@l0rem1psum I think its a case of weird (bad) logic in the application itself, rather than real need. Probably its worth revisiting the case of why you need it in your application. If you do not need to do anything on a variable, leave it out, instead of wrapping it in an empty function.

@samber samber mentioned this pull request Jul 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants