booleancat / go-functional Goto Github PK
View Code? Open in Web Editor NEWgo-functional is a library that offers functional programming in Go using generics
License: MIT License
go-functional is a library that offers functional programming in Go using generics
License: MIT License
Is your feature request related to a problem? Please describe.
No, just an idea.
It should be convenient because this pattern can be seen in other languages.
examples: Python, JavaScript, Kotlin
Describe the solution you'd like
Creating iterator from imperative function.
Provide code snippets to show how this new feature might be used.
func ExampleGenerator() {
it := iter.Generator[string](func(yield func(v string)) {
yield("hello")
yield("generator")
})
fmt.Println(iter.Collect(it))
// Output: [hello generator]
}
Does this incur a breaking change?
no.
Do you intend to build this feature yourself?
Maybe.
Feel free to comment if someone intend to commit.
Additional context
I'm not sure whether it is good feature or not.
It's because following reasons.
Justifications exist, but weak.
Is your feature request related to a problem? Please describe.
Iterators often call underlying iterators (such as Map
or Filter
). Sometimes an iterator can become exhausted before its underlying iterator has been exhausted (e.g. Take
). Currently there is nothing defined in documentation or dictated by tests that prevents iterators from consuming from inner iterators, which will cause unnecessary runtime overhead and possibly surprising users if they re-use the inner iterators later.
Describe the solution you'd like
Count
). A "second-order" iterator is one which depends on another iterator (e.g. Take
).Next
.iter
package should have tests that guarantee this behaviour.Provide code snippets to show how this new feature might be used.
N/A documentation change.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe - I'd prefer to give someone else the opportunity to contribute.
Additional context
PRs that implement part of this are OK, this issue can be closed one all 4 points are addressed.
Hint - I've thought about using counterfeiter to generate a fake iterator in order to make call count testing easier. If you use this, please place a fake iterator inside the internal
package of this project.
Alternatively, I'm open to a conversation about the failure of a fake iterator as something iter
exposes to make testing easier but that should probably be a separate issue.
Is your feature request related to a problem? Please describe.
Contributors are doing a kindness by raising pull requests their job could be made easier by offering a pull request template to reduce the likelihood that their PR would be rejected and reduce the back-and-forth on the PR.
Describe the solution you'd like
A pull request template that contains a set of standard questions could act as a forcing function to ensure PRs are raised with as much context as is needed. The template should:
Provide code snippets to show how this new feature might be used.
Not applicable.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Yes.
Additional context
N/A.
Is your feature request related to a problem? Please describe.
I can imagine using the built in operators (see this list) in iterators like Map
or collectors like Fold
as a common use case. Some operators are commutative (the order of argument does not matter) whilst others are not. I'm not yet convinced of the value of providing non-commutative operators so am considering those out of scope for this feature request.
Currently users of Map
-like iterators or Fold
-like collectors would have to define these themselves.
Describe the solution you'd like
Offer the following operators to users of go-functional
via the ops
package:
+
)*
)&
)|
)^
)Provide code snippets to show how this new feature might be used.
func ExampleSum() {
fmt.Println(iter.Fold[string](iter.Lift([]{"hello ", "there"}), "", ops.Sum[string]))
// Output: hello there
}
func ExampleProduct() {
fmt.Println(iter.Fold[int](iter.Lift([]{1, 2, 3, 4}), 1, ops.Product[int]))
// Output: 24
}
func ExampleBitwiseAnd() {
fmt.Println(iter.Fold[int](iter.Lift([]{1, 3}), 1, ops.BitwiseAnd[int]))
// Output: 1
}
func ExampleBitwiseOr() {
fmt.Println(iter.Fold[int](iter.Lift([]{1, 3}), 0, ops.BitwiseOr[int]))
// Output: 3
}
func ExampleBitwiseXor() {
fmt.Println(iter.Fold[int](iter.Lift([]{1, 3}), 0, ops.BitwiseXor[int]))
// Output: 2
}
Does this incur a breaking change?
Yes.
Do you intend to build this feature yourself?
No - I'd like to offer this out to folks who wish to practice Go or open-source contribution.
Additional context
Within the ops
package there is already a Add
operation. This should be renamed to Sum
and incurs a breaking change (which is fine since we're not at version 1.0.0 yet.
Is your feature request related to a problem? Please describe.
No.
Describe the solution you'd like
When browsing the README, there's a clickable link to the report card (https://goreportcard.com/report/github.com/BooleanCat/go-functional)
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Yes.
Is your feature request related to a problem? Please describe.
Fold
ing an iterator is achieved by using the iter
package's Fold
function. This can lead to deeply nested code that can be difficult to read. The issue belongs to a series of issues that remedy that problem. See #55 for more details.
Describe the solution you'd like
Each iterator (except Count
and Repeat
because Fold
will never terminate) should allow Fold
ing via a method rather than the function iter.Fold
.
For example, this test:
func ExampleFold() {
sum := iter.Fold[int](iter.Take[int](iter.Count(), 4), 0, ops.Add[int])
fmt.Println(sum)
// Output: 6
}
Could instead read like:
func ExampleFold() {
sum := iter.Take[int](iter.Count(), 4).Fold(0, ops.Add[int])
fmt.Println(sum)
// Output: 6
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No - I'd like to offer this to first-time contributors ideally.
Checklist
.Fold(initial, biop)
on each iterator except Count
and Repeat
Fold
is already comprehensively tested elsewhere).Example...
tests or README references to Fold
to use the method.See #57 for an example of where this was implemented for Collect
.
Is your feature request related to a problem? Please describe.
Add function Find
to iter package.
Describe the solution you'd like
iter
package should have a Find
function that takes an iterator and a predicate, Find
will
repeatedly call the underlying iterator and test the returned values using the predicate, if the
predicate returns true then the value is returned wrapped in a Some
variant if the underlying
iterator is exhausted option.None
is returned.
Provide code snippets to show how this new feature might be used.
package main
import "github.com/BooleanCat/go-functional/iter"
func main() {
isFour := func (x int) bool { return x == 4 }
isHundred = func (x int) bool { return x == 100 }
numbers := []int{1, 2, 3, 4, 5}
fmt.Println(iter.Find(iter.Lift(numbers)), isFour) // Some(4)
fmt.Println(iter.Find(iter.Lift(numbers)), isHundred) // None
}
Does this incur a breaking change?
No
Do you intend to build this feature yourself?
Yes
Is your feature request related to a problem? Please describe.
I'd like to release version 1.0.0 to indicate that the project is ready for use and I'll continue supporting it.
I'm concerned that people may choose not to use the project because of it's 0.
status. I'm feeling confident in the usage of the package and the iter interface as it is now.
Describe the solution you'd like
Version 1.0.0 released or some good reasons why it's not a good idea.
Provide code snippets to show how this new feature might be used.
N/A.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
N/A.
I am willing to pay 50 USD if you resolve this issue #60 by 27th August
For more details visit https://mintycode.io
Is your feature request related to a problem? Please describe.
Chaining different iterators is not currently possible due to limitations around Go's type system (new generic types cannot be introduced on type methods, they must be declared on the type).
This can cause the chaining of operations to be verbose:
iter.Take(iter.Filter(iter.Count(), isEven), 5)
Describe the solution you'd like
iter.Count().Filter(isEven).Take(5)
This isn't possible for all types because it's not possible to know the output type at Iterator type declaration: for example MapIter can return any type on Next, but Filter needs no additional type information.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Parts of it, maybe.
Additional context
From a brief scan, the iterators than could be chained are Filter, Exclude, Take, Drop and Chain.
In addition the collection methods could be chained also: Collect, ForEach, Fold, Find.
Primary iterators cannot be chained (e.g. Count) because that's nonsensical, and Map and Zip are excluded because of type system limitations.
As such this chaining should be thought of as a feature of each iterator individually rather than a general feature of iterators.
Work list
.Collect()
to all iterators except Count
and Repeat
(#57).ForEach(op)
to all iterators except Count
(#68).Find(filter)
to all iterators (#69).ToChannel()
to all iterators except Count
and Repeat
.Chain(iter)
to all iterators except Count
and Repeat
.Drop(n)
to all iterators (#61).Filter(filter)
to all iterators (#59).Exclude(filter)
to all iterators (#60).Take(n)
to all iterators (#67)For iterators that call other iterators (such as iter.Take
), there should be a guarantee that underlying iterators are never call again once a parent iterator becomes exhausted. This may already be the case in some or all iterators but this would be by chance - it certainly isn't tested.
To satisfy this issue, write tests to guarantee this behaviour and document that iterator authors should do likewise in the README.
In order for generated documentation to include examples, go-functional must include Example
tests. Write short examples (<10 lines of code) for each iterator, filter and op in this package.
To see an existing example in this library, see the Example tests for Take
and Drop
.
Is your feature request related to a problem? Please describe.
Currently, in order to "Chain" two iterators, users of go-functional must do something like appending slices together and then lifting. It should be possible to chain a variable number of iterators.
Describe the solution you'd like
A new iterator iter.Chain(iter ...Iterator[T])
will take a variable number of iterators. For each iterator, from left to right, it shall yield all values to exhaustion and move to the next iterator. The chain iterator is exhausted once all iterators are exhausted. Chain may be passed no arguments, in which case it behaves like iter.Exhausted
.
Provide code snippets to show how this new feature might be used.
func ExampleChain() {
fmt.Println(iter.Collect[int](iter.Chain[int](iter.Lift([]int{1, 2}), iter.Lift([]int{3, 4}), iter.Lift([]int{0, 9}))))
// Output: [1 2 3 4 0 9]
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No.
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
Printing as a string today (0.17.0
) looks ugly:
counter := iter.Count()
fmt.Println(counter)
fmt.Printf("%s\n", counter)
// &{{%!s(*iter.CountIter=&{{0xc0000a6000} 0})} %!s(int=0)}
This makes it hard to debug issues when you need to print iterators.
Describe the solution you'd like
Implement the stringer interface for each iterator. The text should make it clear that it's an iterator and the kind of iterator that it is. Perhaps something like:
fmt.Printf("%s\n", iter.Count()) // Iterator<Count>
fmt.Printf("%s\n", iter.Count().Take(4)) // Iterator<Take>
I'm open to better ideas about how it should be represented.
Provide code snippets to show how this new feature might be used.
The fmt.Stringer()
interface should be implemented for each iterator.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe.
Additional context
Doesn't all need to be in one PR, I'd accept a PR for 1+ iterators. This issue is closed when all are implemented.
Fold is often used in functional paradigms for collect items from an iterator and apply a transformation during collection. As an example, imagine we wanted to find the sum of all numbers from 1 to 50, one way to achieve this would be to Fold over the iterator with a sum method:
add := func(a, b int) int { return a + b }
total := iter.Fold[int](iter.Take[int](iter.Count(), 51), add, 0)
Fold takes a value from the iterator and applies it to the provided function along with the result of the previous application, using a provided seed value for the first application. In the example above, 0 (the seed value) and 0 (the first value from Count
) are passed to add
which returns 0. The result (0) is then passed again along with 1 (the next value in the iterator) until the iterator is exhausted.
I can imagine Add
being ubiquitous enough that it's worth adding to the ops
package and making the arguments a and b any type for which +
is a valid operator.
LinesIter yields result.Result[[]byte]
. There's a collection function that collect such an iterator into result.Result[[][]byte]
. To make this easier to use, add .CollectResults
as a method to the Iterator.
iter.Lines(file).CollectResult().Unwrap()
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe.
Additional context
I'd like the same for LinesString, however lines string is simply a MapIter. In order to achieve this you'll first need to make LinesString its own iterator.
Is your feature request related to a problem? Please describe.
Filter
ing an iterator is achieved by using the iter
package's Filter
function. This can lead to deeply nested code that can be difficult to read. The issue belongs to a series of issues that remedy that problem. See #55 for more details.
Describe the solution you'd like
Each iterator should allow Filter
ing via a method rather than the function iter.Filter
.
For example, this test:
func ExampleFilter() {
filtered := iter.Filter[int](iter.Lift([]int{0, 1, 0, 2}), filters.IsZero[int]).Collect()
fmt.Println(filtered)
// Output: [0 0]
}
Could instead read like:
func ExampleFilter() {
filtered := iter.Lift([]int{0, 1, 0, 2}).Filter(filters.IsZero[int]).Collect()
fmt.Println(filtered)
// Output: [0 0]
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No - I'd like to offer this to first-time contributors ideally.
Checklist
.FIlter(filter)
on each iteratorFilter
is already comprehensively tested elsewhere).Example...
tests or README references to Filter
to use the method.See #57 for an example of where this was implemented for Collect
.
Is your feature request related to a problem? Please describe.
It's not clear to me how a a result should be marshalled into JSON when it holds an error value (since error is represented by an interface). Type information regarding the error would be lost.
However, it seems reasonable to me to support Unmarshal of plain values into result.Result[T] since they will always be unmarshalled into result.Ok
variants.
Describe the solution you'd like
Support unmarshalling of values into result.Result[T]
. For example the JSON value 42
should unmarshall into:
result.Ok(42)
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe.
Additional context
Do not implement marshalling, only unmarshalling.
What happened?
Type inference rules have gotten much better since 1.18, so now you can:
func main() {
// All even natural numbers (2, 4, 6, 8...)
isEven := func(n int) bool { return n%2 == 0 }
evens := iter.Filter(iter.Drop(iter.Count(), 1), isEven)
for i := 0; i < 5; i++ {
fmt.Println(evens.Next().Unwrap())
}
file, _ := os.Open(`main.go`)
// All non-empty lines from a file
lines := iter.Exclude(iter.LinesString(file), filters.IsZero)
for line := lines.Next(); line.IsSome(); line = lines.Next() {
fmt.Println(line.Unwrap())
}
// String representations of numbers
numbers := iter.Map(iter.Count(), strconv.Itoa)
for i := 0; i < 5; i++ {
fmt.Println(numbers.Next().Unwrap())
}
}
Which outputs
2
4
6
8
10
Ok(package main)
Ok(import ()
Ok( "fmt")
Ok( "os")
Ok( "strconv")
Ok( "github.com/BooleanCat/go-functional/iter")
Ok( "github.com/BooleanCat/go-functional/iter/filters")
Ok())
Ok(func main() {)
Ok( // All even natural numbers (2, 4, 6, 8...))
Ok( isEven := func(n int) bool { return n%2 == 0 })
Ok( evens := iter.Filter(iter.Drop(iter.Count(), 1), isEven))
Ok( for i := 0; i < 5; i++ {)
Ok( fmt.Println(evens.Next().Unwrap()))
Ok( })
Ok( file, _ := os.Open(`main.go`))
Ok( // All non-empty lines from a file)
Ok( lines := iter.Exclude(iter.LinesString(file), filters.IsZero))
Ok( for line := lines.Next(); line.IsSome(); line = lines.Next() {)
Ok( fmt.Println(line.Unwrap()))
Ok( })
Ok( // String representations of numbers)
Ok( numbers := iter.Map(iter.Count(), strconv.Itoa))
Ok( for i := 0; i < 5; i++ {)
Ok( fmt.Println(numbers.Next().Unwrap()))
Ok( })
Ok(})
0
1
2
3
4
Though it's worth noting that lines seems to require extra indirection.
What happened?
Provide a description of the issue.
What did you expect to happen?
Explain what you would have expected to happen instead.
Which version of go-functional were you using?
Provide the version number (such as v0.3.0
).
To Reproduce
Provide a code snippet or steps to reproduce the issue.
Do you intend to fix this issue yourself?
Yes or no. This is so that the maintainers know to leave you time to make a
contribution rather than just fixing it themselves.
Additional context
Add any other context about the problem here.
What happened?
Sometimes go-functional fails a report card lint (misspell has been an example). I only learn about this after I ship a new release.
What did you expect to happen?
I'd like linting to fail in CI if go-functional scores anything less than 100% on the report card linters.
Which version of go-functional were you using?
v0.15.0
To Reproduce
You can see lint errors on the report card (if there are any currently).
Do you intend to fix this issue yourself?
No.
Additional context
I suspect these are probably optional linters in golangci-lint
and it's just a case of configuring a yaml file in the repo. If that is the case, run all default linters + linters run in the report card. Adding additional linters is out of scope but I would consider a separate PR with solid reasoning for using other linters.
Is your feature request related to a problem? Please describe.
No.
Describe the solution you'd like
go-functional should be featured on https://github.com/avelino/awesome-go to spread awareness.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Yes.
Is your feature request related to a problem? Please describe.
It's not possible to chain Map iterators because of limitations with Go's type system (you cannot define new type parameters on methods). So this is not possible:
func (iter *BaseIter[T]) Transform[U any](func(T) U) *MapIter[T, U] {
...
}
Describe the solution you'd like
I'd like a more limited version of the Map iterator where the return type is the same as the input type.
Provide code snippets to show how this new feature might be used.
The following should be possible and will allow chaining on simpler Map
operations.
func (iter *BaseIter[T]) Transform(func(T) T) *TransformIter[T] {
...
}
evens := iter.Count().Transform(double).Take(5).Collect()
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe, be a good one for first time contributors to pick up.
TransformIter[T]
Hi,
I stumbled upon your project via Twitter and while I read your TODOs in your README,
this echoed with me since I'm writing a go library as well.
I also searched for simple ways, to include example code in the README,
which is automatically checked by the compiler and I would like to avoid manual copy&paste actions.
May I share my solution?
I hope this saves you some research time, as I found this very helpful for my own library 'lib-bpmn-engine'.
๐ for you and your project.
PS: not an issue, this can be closed.
I see you've recently rewritten the package to support go generics. Having this kinds of wrappers is really useful ๐๐ป
You went sort of the pythonic way with passing iterators into functions. However most other languages have a chainable iterator API that is more convenient to use (js map/filter/... on arrays, java streams, c++20 ranges, rust iterators). Have you considered something smilar?
Given that Go has no inheritance (for java streams) nor trait implementations for traits (for rust iters), building a convenient chainable API is somewhat challenging. Avoiding code duplication would require one more level of abstraction - always hiding specific iterators behind an iterator wrapper.
What happened?
This test failed unexpectedly: https://github.com/BooleanCat/go-functional/actions/runs/5985534714/job/16237724514 (TestLiftHashMapKeysCloseEarly
).
What did you expect to happen?
The test should be deterministic.
Which version of go-functional were you using?
HEAD
@ ece50cdf941d64d8384d982a9e1c4ee62a757605
To Reproduce
go test -run TestLiftHashMapKeysCloseEarly ./iter -count=100000
Do you intend to fix this issue yourself?
Yes.
Is your feature request related to a problem? Please describe.
Printing a Pair
of values should be reconisably a 2-length tuple in a simple representation.
Describe the solution you'd like
Tuples should print like so:
foo := iter.Pair[string, int]("apple", 42)
fmt.Printf("%s\n", foo) // (apple, 42)
This will involve implementing the fmt.Stringer
interface for the type.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No.
Is your feature request related to a problem? Please describe.
A common way to do transformation pipelines currently is using channels. It would be useful to be able to plug into those.
Describe the solution you'd like
An iterator that plugs consumes a channel. The iterator is exhausted when the channel is closed.
Provide code snippets to show how this new feature might be used.
func ExampleFromChannel() {
ch := make(chan int, 2)
go func() {
ch <- 1
ch <- 2
close(ch)
}()
fmt.Println(iter.Collect[int](iter.FromChannel[int](ch)))
// Output: [1 2]
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No.
Additional context
N/A.
Is your feature request related to a problem? Please describe.
There ought to be a way to "do something" with items yielded from iterators without collecting the values. ForEach
supports providing a callback to operate over each member.
Describe the solution you'd like
words := iter.Lift([]string{"some", "words", "please"})
iter.ForEach(words, func(word string) {
fmt.Println(word)
})
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Maybe.
Is your feature request related to a problem? Please describe.
Exclude
ing an iterator is achieved by using the iter
package's Exclude
function. This can lead to deeply nested code that can be difficult to read. The issue belongs to a series of issues that remedy that problem. See #55 for more details.
Describe the solution you'd like
Each iterator should allow Exclude
ing via a method rather than the function iter.Exclude
.
For example, this test:
func ExampleExclude() {
filtered := iter.Exclude[int](iter.Lift([]int{0, 1, 0, 2}), filters.IsZero[int]).Collect()
fmt.Println(filtered)
// Output: [1, 2]
}
Could instead read like:
func ExampleFilter() {
filtered := iter.Lift([]int{0, 1, 0, 2}).Exclude(filters.IsZero[int]).Collect()
fmt.Println(filtered)
// Output: [1 2]
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No - I'd like to offer this to first-time contributors ideally.
Checklist
.Exclude(filter)
on each BaseIterExclude
is already comprehensively tested elsewhere).Example...
tests or README references to Exclude
to use the method.See #57 for an example of where this was implemented for Collect
.
What happened?
When browsing the reference documentation, the Option and Result packages do not have any examples visible.
What did you expect to happen?
I expect to see examples for each function and receiver in both the Option and Result packages' reference documentation.
Which version of go-functional were you using?
v0.4.0
To Reproduce
Visit the reference documentation and observe the missing examples.
Do you intend to fix this issue yourself?
Not at the moment.
Additional context
There are example tests in the packages' source, but for some reason it isn't rendered in the reference documentation.
Is your feature request related to a problem? Please describe.
It is a feature that I liked a lot from the IBM/fp-go library, but that library is very confusing to use and has hardly any documentation.
Describe the solution you'd like
Create a function that takes an initial value t0 and successively applies N functions where the input of a function is the return value of the previous function.
Provide code snippets to show how this new feature might be used.
// example implementation
func Flow2[F1 ~func(T0) T1, F2 ~func(T1) T2, T0, T1, T2 any](f1 F1, f2 F2) func(T0) T2 {
return func(t0 T0) T2 {
return f2(f1(t0))
}
}
var (
toStr = func(value int) string { return fmt.Sprint(value) }
length = func(value string) int { return len(value) }
)
func main() {
// usage
myFun := Flow2(toStr, length)
// first convert int to string, then get the length of the string
fmt.Println(myFun(123456)) // 6
}
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
Yes
Additional context
My English is quite bad, so I could not do the documentation of the feature, but I could use a translator to leave notes for whoever is going to do the final documentation.
Is your feature request related to a problem? Please describe.
It'd be great to get a trusted linter such as golangci-lint
running over the code as a step in the check job of the test workflow.
Describe the solution you'd like
Each time a PR is raised, merge should be blocked on golangci-lint passing.
Provide code snippets to show how this new feature might be used.
N/A.
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
No.
Additional context
I'm not sure if the default configuration of the linter is good enough or if we should enable or disable particular lints. I'll leave it to whoever works on this to figure that out and suggest something in a PR.
If there are issues found by the linter and they are not particularly arduous then please fix them in separate commits in the same PR or provide justifcation why we should disable that linter.
Is your feature request related to a problem? Please describe.
It's possible users would like to use an iterator more than once. Be using tee
as inspiration we can have that behaviour in go-functional.
Describe the solution you'd like
evens := iter.Count().Filter(isEven).Take(5)
iters := iter.Tee(evens)
iters.One.Take(2).Collect() // [0 2]
iters.Two.Take(2).Collect() // [0 2]
Does this incur a breaking change?
No.
Do you intend to build this feature yourself?
If no one else picks it up.
Additional context
Since the iterators that are generated by tee
may be consumed at different rates, the tee
struct will need to remember a portion of the results from underlying iterator (the lag between the faster and slower iterators). A naive solution would just remember the entire underlying iterator, a better solution would use something like a double ended queue.
Thread safety is out of scope unless you think it should be in scope and can covince me.
The README should provide a brief overview of go-functional and leave the details to the auto-generated docs. The following topics should be covered in the README.
Is your feature request related to a problem? Please describe.
It's a feature request, a lot of std libs of functional programming languages have this built in.
Describe the solution you'd like
A robust implementation of the option.Map
Provide code snippets to show how this new feature might be used.
Given the following function
func x (int) string {
if x == 0 {
return "zero"
}
return "non-zero"
}
We should be able to pass function x
to option.Map
option.Map[int, string](x)
and get back a closure y
func y (o option.Option[int]) option.Option[string] {
if o.IsNone() {
return option.None[string]()
}
return option.Some[string](x(o.Unwrap())
}
Effectively Map
allows a function to work with option types, it's pretty useful when we want functions to more easily
work with functions that return an Option
variant
Does this incur a breaking change?
No, it does not.
Do you intend to build this feature yourself?
Yes, it should be pretty simple.
I think that having an iterator over a channel would be very convenient, as it would allow to build delayed pipelines.
Maybe even not only over one channel, but over multiple. The reflect package has a dynamic select to listen to multiple channels.
Another idea would be a function for consuming an iterator and sending all its values to a channel.
This way we could describe a pipeline that reads from a channel, does some mapping/filtering and writes to another. All imperatively ๐ฅณ
I'm eager to implement it. What do you think of it?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.