You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We can implement based in the link above, it was inspired by Clojure implementation that has some cool features like early termination using Reduced sentinel!
In fact almost everything there can be translated to returns using typing, specially the transducers parts!
I've written the transducers for map and filter:
E Actual:
E main:14: error: Argument 1 has incompatible type "Callable[[Callable[[_AccType, Any], _AccType]], Callable[[_AccType, Any], _AccType]]"; expected "Callable[[Any, str], Any]" (diff)
E main:14: error: Cannot infer function type argument (diff)
Well, after some tests I can't find a great solution design 😞
The user most provide a function, and this function can be different (map != filter)
My idea now is to provide .from_(map, filter) method to initialize the instance, but I think it is not worth it!
For each transducer function we will need to add an initialization method.
Do you have any suggestion @sobolevn?? If not, I'll continue with the normal solution
Sure, but think in our Result container where we have .from_value(...), .from_failure(...). It's the same concept but will we have more than two from_*:
Oh, wait. I think I cannot do that, the idea behind transducers is to remove the rule from the process. Transducers don't care about the user input or output.
If the users make Transformations[List[str], int] they will be putting this rule again! 🤔
error: Argument "reducing_function" to "transduce" has incompatible type "Callable[[List[int], int], List[int]]"; expected "Callable[[List[<nothing>], int], List[<nothing>]]"
No, this is pretty annoying bug in how mypy works, the thing is: [] is sometimes List[never] and sometimes List[any].
Right now it is not working this way 😞
I'm continuing this issue and after a lot of thoughts I end up deciding that transducers is a cool thing but we don't need them in Python in the same way that's implemented in Clojure! The thing is, Python has generators which chained result in the same behavior of the transducer, instead of creating a lot of intermediate iterable they process each element from the start to the end!
But I do think it's useful for us to provide a better tooling for generators like we have on Clojure transducers! So my idea is to implement that tolling now!
Activity
thepabloaguilar commentedon Apr 25, 2021
https://ramdajs.com/docs/#expand
thepabloaguilar commentedon Apr 25, 2021
https://github.com/cognitect-labs/transducers-python
thepabloaguilar commentedon Apr 25, 2021
We can implement based in the link above, it was inspired by Clojure implementation that has some cool features like early termination using
Reducedsentinel!In fact almost everything there can be translated to returns using typing, specially the transducers parts!
I've written the transducers for map and filter:
P.S.: The types in my code are wrong yet 'cause transducers should work with any kind of input and there I'm fixing
List[_T]sobolevn commentedon Apr 25, 2021
Great stuff!
thepabloaguilar commentedon Apr 26, 2021
Maybe is because I'm so tired now after many hours in front of a computer, but I can't figure out how to solve the problem I'm getting.
Transducer map implementation:
Every type seems correct:
functionshould be the function we normally pass to a map, like,lambda item: str(item)reducingis the function to reduce/next step, like,lambda acc, value: acc + valueBut when I try to make a composition I got a error, but it should work!
Test case:
Test output:
Like,
Anyshouldn't be there.Other test cases works fine:
thepabloaguilar commentedon Apr 26, 2021
I'd love to know if you have any tips @sobolevn!!
thepabloaguilar commentedon Apr 26, 2021
Btw, the actual implementation is working normally:
thepabloaguilar commentedon Apr 26, 2021
Ok, I think the composition I've made is wrong! I'll see tomorow
thepabloaguilar commentedon Apr 26, 2021
@sobolevn I remember a discussion from #451, what will be a great name for this feature?
Options:
thepabloaguilar commentedon Apr 27, 2021
Well, my composition was wrong and my thought too hahaha
The types are working correctly with the composition:
thepabloaguilar commentedon Apr 27, 2021
@sobolevn You can see the progress in this draft PR (yet) or in a very preview documentation here
thepabloaguilar commentedon Apr 27, 2021
I have a suggestion, in the actual implementation way the user need to build "everything" by hand like:
My ideia is to incapsulate in a class:
Using a class makes clear to the users that they are receiving a transformation instead of a random function!
sobolevn commentedon Apr 27, 2021
Yeah, why not!
thepabloaguilar commentedon Apr 28, 2021
Well, after some tests I can't find a great solution design 😞
The user most provide a function, and this function can be different (map != filter)
My idea now is to provide
.from_(map, filter)method to initialize the instance, but I think it is not worth it!For each transducer function we will need to add an initialization method.
Do you have any suggestion @sobolevn?? If not, I'll continue with the normal solution
sobolevn commentedon Apr 28, 2021
Sorry, I don't understand. Can you please show me the code?
thepabloaguilar commentedon Apr 28, 2021
Sure, but think in our Result container where we have
.from_value(...),.from_failure(...). It's the same concept but will we have more than twofrom_*:thepabloaguilar commentedon Apr 28, 2021
Oh, wait. I think I cannot do that, the idea behind transducers is to remove the rule from the process.
Transducersdon't care about the user input or output.If the users make
Transformations[List[str], int]they will be putting this rule again! 🤔thepabloaguilar commentedon May 2, 2021
This is what I will do, continue with the first approach and then I can think about improvements!
thepabloaguilar commentedon May 8, 2021
@sobolevn I need your help a little, I'm planning to finish the implementation this weekend!
We have the
transducefunction right here:Sometimes I just want to pass an empty list to the initial value, like:
And I receive this error from mypy:
To fix this issue I need to type hint that list:
Do you know a way to avoid that??
sobolevn commentedon May 8, 2021
No, this is pretty annoying bug in how mypy works, the thing is:
[]is sometimesList[never]and sometimesList[any].Right now it is not working this way 😞
thepabloaguilar commentedon May 9, 2021
Sad 😭 😭
So, I'll continue as is!
thepabloaguilar commentedon Aug 30, 2022
I'm continuing this issue and after a lot of thoughts I end up deciding that
transducersis a cool thing but we don't need them in Python in the same way that's implemented in Clojure! The thing is, Python has generators which chained result in the same behavior of the transducer, instead of creating a lot of intermediate iterable they process each element from the start to the end!But I do think it's useful for us to provide a better tooling for generators like we have on Clojure transducers! So my idea is to implement that tolling now!
WDYT @sobolevn??
sobolevn commentedon Aug 30, 2022
The idea sounds interesting! Please, feel free to send a prototype.