New Transformation `..` Operator to Transform Values

Hello Everyone,

I am proposing new transformation operator syntax that can be used in various ways including creating ranges, type conversion, and applying functions:


a = (1..10) # list of numbers from 1 to 10 inclusive

a = (0.0..1.0) # list of numbers from 0 to 1 by 0.1 inclusive.
((1,0.02)..2) #list of numbers from 1 to 2 by 0.02 by using tuple value
(1..(2,0.02)) #list of numbers from 1 to 2 by 0.02 by using tuple value


a_length = a..len # same as len(a) as a piping functionality.

a_map = a..(map, map_function) # same as map(map_function, a)
a_map = a..(lambda _:map(map_function,_)) # same as map(map_function, a)

a_filter = a..(filter, filter_function) # same as filter(filter_function, a)

a=1.0
a_int = a..int # same as int(a)
a_str = a..str # same as str(a)

We can also use another forms of this operator for extended functionalities including (<.., >.., ^..) or (... or ...., ....., ......) to be used as exclusive types of transformations.


a = (1..10) # list of 1 to 10, general

a = (1~..10) # list of 1 to 10
a = (1*..10) # list of 1 to 10
a = (1+..10) # list of 1 to 10
a = (1-..10) # list of 1 to 10
a = (1/..10) # list of 1 to 10
a = (1%..10) # list of 1 to 10

a = (1<..10) # list of 1 to 9
a = (1>..10) # list of 2 to 10
a = (1^..10) # list of 2 to 9

a=[1,2,3]+..[4,5,6] # add 2 matrices 
a=[1,2,3]-..[4,5,6] # subtract 2 matrices 
a=[1,2,3]*..[4,5,6] # multiply 2 matrices 


a = 1
a ..=10 # list of 1 to 10, general
a ~..=10 # list of 1 to 10
a <..=10 # list of 1 to 9
a >..=10 # list of 2 to 10
a ^..=10 # list of 2 to 9

There can particular focus on .. operator for the proposal, and the other operator can be divided into a different topic or proposal as an extension if needed.

a = ((1, True)..(10, False)) # list of 1 to 9 using tuple value
a = ((1, False)..(10, True)) # list of 2 to 10 using tuple value
a = ((1, False)..(10, False)) # list of 2 to 9 using tuple value

If there is a need to seperate the range and pipe functionality, we can use the operator :: or ::: for ranges while .. for pipe functionality.

a=(1::10) # list of values from 1 to 10 # used in arrays for [::] value.
a=(1:::10) # list of values from 1 to 10
a_str=a..str # str(a)

Thank you

I do like Ruby’s range capabilities like 'a'..'zz' and Date.today..(Date.today + 7) and myClassInstance..anotherInstance, but those other usages you showed just look odd/bad. Why would you want to write those instead of the normal way?

1 Like

Thank you for your reply. I think of this operator as a general operator that can have various applications including ranges by just overriding its method __transformation__ and thus allowing different ways for using this operator. Of course this issue can be discussed further and changed as required by development team. It’s just an idea that can be explored further and discussed more.

An idea is FAR more compelling if it starts with a real, concrete use-case, not just “hey, what would happen if we did this?”. Syntax is a big deal. We don’t have syntax for every random little thing that might be convenient. Even when something would have significant value for a subset of Python users, it can take a long time and a lot of debating to get it added (see PEP 465 for one that eventually succeeded).

So, what’s the use-case here? If it’s nothing more than the start of a discussion, this can be moved to Python Help instead.

2 Likes

Thank you for your reply. It can be used as a new syntax that simplifies some coding operations as specified in the examples in the proposal. The proposal is flexible and open for changes as it’s discussed. There is value in this proposal that could add new features for the language, however, the implementation of this proposal is decided by development team and community if seen as a good addition to the language.

This topic is 2 different ideas in 1 big proposal with extensive syntax changes.

It does not answer or cover issues and questions raised in previous discussions about these matters.

a) Function application does not seem to offer anything new. It currently looks like calling the function by writing things in different order.
b) Range Literals: PEP 204 - Range Literals: Getting closure.

Given the size of suggested changes in comparison to accompanying research and analysis, I am moving this to “Help”. It could be useful to discuss these and brainstorm further for those who are interested to join in at this stage.

If OP is willing to make a longer commitment to working on these, I would suggest tackling each a) and b) separately.

1 Like

So this is np.linspace function, but less flexible. Step is 1 out of 3 main components in range/sequence construction and is not mentioned anywhere.

If the intent of function application is to provide composition (which is not shown in examples), then more realistic proposal would be to add functools.pipe. This in combination with functools.partial would cover the functionality without introduction of new syntax.

There is also c) Matrix algebra operators.

Currently, tensor objects re-use __add__, __sub__, __mul__. While these operations with list vectors are easily done with list(map(operator.add, A, B)))

1 Like

@dg-pb
Yes, the first case of ranges for float/double values needs more research and discussion. The initial idea is to infer the step from the size of the decimal places of the given number so for 1.0, it’s 0.1 step, which wouldn’t work for 1.00 for 0.01 step value or 1.0 for 0.2 step value.
Suggestion:

((1,0.02)..2) #list of numbers from 1 to 2 by 0.02 by using tuple value
(1..(2,0.02)) #list of numbers from 1 to 2 by 0.02 by using tuple value

The concepts in the proposal are very related and It’s possible to divide the proposal into sub proposals as required by the development team and community.
Thank you

Figure out what your proposal is. Don’t hide behind vagueness. At the moment, there isn’t enough concrete content here to even discuss; you’ve thrown out this broad set of ideas and you’re hoping that other people will do the work required to turn it into something useful.

@Rosuav
The proposal is clear it’s just open for more discussion as needed. What’s not clear for you so it can be clarified better. The proposal is about a new list of transformation operators starting with .. with the .. being general and then the other variations(+..,>..) are specific. They can be used for type conversion, and creating ranges and also pipe functions.

To me they seem related only by the operator syntax. Apart from that to me they all look completely different judged on applications, implementations and implications.

If you dive into them properly by committing to these for longer time, you will see how many different underlying issues, questions and obstacles each of them has.

In other words, this looks like 1% baked idea. Although such posts are not desirable in “Ideas” section, I would not mind discussing it in “Help” section if these were posted separately.

Currently, the scope is just too wide and ideas are too raw. You need to do a bit of cooking and/or a bit of narrowing for this to be productive discussion.

1 Like

There can particular focus on .. operator for the proposal, and the other operator can be divided into a different topic or proposal as an extension if needed.

a = ((1, True)..(10, False)) # list of 1 to 9 using tuple value
a = ((1, False)..(10, True)) # list of 2 to 10 using tuple value
a = ((1, False)..(10, False)) # list of 2 to 9 using tuple value

But what do they DO? What is the point of them? You’re proposing a new syntax without showing any particular purpose to it - you’ve shown a range syntax (but we’ve already had that proposed and rejected, and you haven’t explained how your proposal is better), and a super generic “this could do anything” concept. There is no purpose to it. There is no coherency. What is your actual proposal?

1 Like

I mentioned them in the main proposal post.

1>..10 is used for generating numbers from 2 to 10 if step is 1 value.
[]+..[] is used for adding matrices.

I’m suggesting to move these extra extension operators to a different proposal as needed, while the focus for the current proposal is .. operator functionality.

IMO, this needs to be convenient and flexible. I.e. step size would be very much preferable to create range objects.

This creation of range/sequence objects is very verbose and would not be convenient at all.

Open/closed is not as important from flexibility POV as one can always just have different starting/ending values. For simplicity and consistency, it might be best just to keep things in line with slice/range closed bound to open bound.

The best that I can think of at the moment is introduction of ternary operator. I am not sure about syntax/naming/etc, but it could look like:

class int:
    def __ternary__(self, other, step=None):
        return range(self, other, step)

print(0:10:)    # range(0, 10)
print(0:10:2)   # range(0, 10, 2)

For int, it would produce ranges, and it could be a good place to start.

Regarding other classes, it should be carefully evaluated what sort of functionality would bring most value. For list, it could be matrix algebra. E.g.:

class new_list(list):
    def __ternary__(self, other, op=operator.add):
        return list(map(op, self, other))

l1 = nes_list([1, 2, 3])
l2 = nes_list([1, 2, 3])
print(l1:l2:mul)    # [2, 4, 6]

But I doubt that this would/should end up in standard library. If the user needs this, it would be possible to implement it easily.

If you want to start by focusing on ranges, I would strongly suggest having a thorough read of PEP 204 - Range Literals: Getting closure - #32 by jbo.

Also, one more question. Are you suggesting this for someone else to do or is it something that you desire to work on yourself?

1 Like

I don’t see where the transformation is happening… When I read ‘transformation operator,’ I was thinking of something like this: Transformation Operator.

Also, please take a look at Python Discuss FAQ.

1 Like

It’s a general transformation not mathematical transformation. For example "1"..int transform string to int value.

it’s an idea that I think it could be a good addition for the language and it’s open for discussion. I’m can certainly help in the implementation as needed.

What I don’t really get.

If

a_length = a..len # same as len(a) as a piping functionality.

then why doesn’t

a = (1..10)

become

10(1)

(or TypeError: 'int' object is not callable)

?

1 Like

The operator checks for the types for operands given if the second operand is a function then it calls that function with the first operand. if the they are numbers, it creates a range list. if any operand is a tuple, it checks the tuple type and size (as used in the main post) and then creates a range list.