Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Ned Batchelder
On 1/23/17 1:27 PM, Gerald Britton wrote:
>
>
> On Jan 23, 2017 1:12 PM, "Britton, Gerald"  > wrote:
>
>
>  
>
> You're mixing up value immutability with name immutability. The name
>
> isn't immutable, but:
>
>
> Er...No. I'm not confused at all, unless you define immutability in a
> new way.. you said that the "value bound to long_name is immutable."
> It's not. Your example below proves it. 
>
> An immutable object is one whose state cannot be modified once set.
> That's not happening here.  The state of the object bound to
> long_name, which is a pointer to an instance of you class, changes
> with each line.

In Python, names refer to values.  Values can be immutable. Ints,
strings, and tuples are examples of immutable values. They cannot be
mutated.

In Python, names cannot be immutable. It is always possible to make an
existing name refer to a new value.

--Ned.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Alexandre Brault


On 2017-01-23 12:54 PM, Soni L. wrote:
> On 23/01/17 02:56 PM, Gerald Britton wrote:
>> On Jan 23, 2017 11:07 AM, "Soni L." > > wrote:
>>
>> On 23/01/17 01:52 PM, Gerald Britton wrote:
>>>
>>> [snip]
>>>
>>>  
>>>
>>> >I propose `x .= y` -> `x = x . y`, for any `y`.
>>>
>>>  
>>>
>>> [snip]
>>>
>>>  
>>>
>>> I think you mean "any y that is a member of x"
>>>
>>
>> Since it desugars into `x = x.y`, you can literally use anything
>> for `y`.
>>
>> x .= __call__().whatever().unwrap() * 3
>>
>> is equivalent to
>>
>> x = x.__call__().whatever().unwrap() * 3
>>
>> and
>>
>> x .= 1
>>
>> is equivalent to
>>
>> x = x.1
>>
>> which is equivalent to
>>
>> SyntaxError: invalid syntax
>>
>>
>>>  
>>>
>>> Also, note that this syntax means that x will be rebound to
>>> the result of calling x.y, whatever that is (frequently,
>>> None, for mutating methods)
>>>
>>> In general, you can't count on methods to return references
>>> to their instances, even though it's handy for fluent
>>> coding, so this side effect may be unexpected to some
>>>
>>
>> This is why it's for use with **immutable** objects.
>>
>>
>>>  
>>>
>>> That's a problem with your original example:
>>>
>>>  
>>>
>>> >long_name = mkbuilder()
>>>
>>> >long_name = long_name.seta(a)
>>>
>>> >long_name = long_name.setb(b)
>>>
>>> >y = long_name.build()
>>>
>>>  
>>>
>>> What do the methods seta and setb return?  If they don't
>>> return "self" you've got a problem. I think.
>>>
>>
>> They don't return self. Ever. The value bound to long_name is
>> immutable, like an integer. They return a new instance.
>>
>>
>> Then long_name isn't immutable. It changes with every line. That can
>> lead to nasty bugs if you count on its immutability.
>>
>> Easy to see. Just print long_name after each call.
>
> You're mixing up value immutability with name immutability. The name
> isn't immutable, but:
>
> long_name = mkbuilder()
> x = long_name
> long_name .= seta("a")
> y = long_name
> long_name .= setb("b")
> z = long_name
> print(x)  # a = None, b = None
> print(y)  # a = "a", b = None
> print(z)  # a = "a", b = "b"
> print(x is y)  # False
> print(x is z)  # False
> print(y is z)  # False
> print(long_name is z)  # True
This is a really contrived example that doesn't need a special syntax.
Consider instead:

>>> x = mkbuilder()
>>> y = x.seta('a')
>>> z = y.setb('b')
>>> long_name = z

All your prints work as well, this is much easier to mentally parse
(notwithstanding the unpythonesque builder pattern) and doesn't require
the addition of a new syntax that people more knowledgeable than me have
already explained is not a good idea

--Alex
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.



On 23/01/17 04:27 PM, Gerald Britton wrote:



On Jan 23, 2017 1:12 PM, "Britton, Gerald" > wrote:


On 23/01/17 02:56 PM, Gerald Britton wrote:

>//

>//

>/On Jan 23, 2017 11:07 AM, "Soni L." https://mail.python.org/mailman/listinfo/python-ideas> /

>/2Bpy at gmail.com
>> wrote:/

>//

>//

>//

>/ On 23/01/17 01:52 PM, Gerald Britton wrote:/

>>//

>>//

>>//

>>/ [snip]/

>>//

>>/ >I propose `x .= y` -> `x = x . y`, for any `y`./

>>//

>>/ [snip]/

>>//

>>/ I think you mean "any y that is a member of x"/

>>//

>//

>/ Since it desugars into `x = x.y`, you can literally use
anything/

>/ for `y`./

>//

>/ x .= __call__().whatever().unwrap() * 3/

>//

>/ is equivalent to/

>//

>/ x = x.__call__().whatever().unwrap() * 3/

>//

>/ and/

>//

>/ x .= 1/

>//

>/ is equivalent to/

>//

>/ x = x.1/

>//

>/ which is equivalent to/

>//

>/ SyntaxError: invalid syntax/

>//

>//

>>/ Also, note that this syntax means that x will be rebound to/

>>/ the result of calling x.y, whatever that is (frequently,/

>>/ None, for mutating methods)/

>>//

>>/ In general, you can't count on methods to return references/

>>/ to their instances, even though it's handy for fluent
coding,/

>>/ so this side effect may be unexpected to some/

>>//

>//

>/ This is why it's for use with **immutable** objects./

>//

>//

>>/ That's a problem with your original example:/

>>//

>>/ >long_name = mkbuilder()/

>>//

>>/ >long_name = long_name.seta(a)/

>>//

>>/ >long_name = long_name.setb(b)/

>>//

>>/ >y = long_name.build()/

>>//

>>/ What do the methods seta and setb return?  If they don't/

>>/ return "self" you've got a problem. I think./

>>//

>//

>/ They don't return self. Ever. The value bound to long_name is/

>/ immutable, like an integer. They return a new instance./

>//

>//

>/Then long_name isn't immutable. It changes with every line. That
can /

>/lead to nasty bugs if you count on its immutability./

>//

>/Easy to see. Just print long_name after each call./

You're mixing up value immutability with name immutability. The name

isn't immutable, but:

Er...No. I'm not confused at all, unless you define immutability in a 
new way.. you said that the "value bound to long_name is immutable." 
It's not. Your example below proves it.
An immutable object is one whose state cannot be modified once set. 
That's not happening here.  The state of the object bound to 
long_name, which is a pointer to an instance of you class, changes 
with each line.
Python has pointers now?! The value pointed to by the value bound to 
long_name is immutable. Can you stop being so pedantic? >.<


long_name = mkbuilder()

x = long_name

long_name .= seta("a")

y = long_name

long_name .= setb("b")

z = long_name

print(x)  # a = None, b = None

print(y)  # a = "a", b = None

print(z)  # a = "a", b = "b"

print(x is y)  # False

print(x is z)  # False

print(y is z)  # False

print(long_name is z)  # True

See also:

long_name = 1

x = long_name

long_name += 1

y = long_name

long_name += 1

z = long_name

print(x)  # 1

print(y)  # 2

print(z)  # 3

print(x is y)  # False

print(x is z)  # False

print(y is z)  # False

print(long_name is z)  # True

>//

>//

>//

>>/ FWIW why can't you just write:/

>>//

>>/ x.y/

>>//

>>/ or for your example:/

>>//

>>/ long_name.seta(a)/

>>//

>>/ ?/

>>//

>>//

>//

>/ See the IRC bot builder example, it should be more clear. (It's/

>/ about forking the builder.)/

>//

>//

If you wish to unsubscribe from receiving commercial electronic
messages from TD Bank Group, please click here
 or go to the following web address:
www.td.com/tdoptout  Si vous souhaitez
vous désabonner des messages électroniques de nature commerciale
envoyés par Groupe Banque TD veuillez cliquer ici
 ou vous rendre à l'adresse
www.td.com/tddesab 

NOTICE: Confidential message which may be privileged. Unauthorized
use/disclosure prohibited. If received in error, please go to
www.td.com/legal 

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Gerald Britton
On Jan 23, 2017 1:12 PM, "Britton, Gerald"  wrote:

On 23/01/17 02:56 PM, Gerald Britton wrote:

>

>

>* On Jan 23, 2017 11:07 AM, "Soni L."  *

>* >> wrote:*

>

>

>

>* On 23/01/17 01:52 PM, Gerald Britton wrote:*

>>

>>

>>

>>* [snip]*

>>

>>* >I propose `x .= y` -> `x = x . y`, for any `y`.*

>>

>>* [snip]*

>>

>>* I think you mean "any y that is a member of x"*

>>

>

>* Since it desugars into `x = x.y`, you can literally use anything*

>* for `y`.*

>

>* x .= __call__().whatever().unwrap() * 3*

>

>* is equivalent to*

>

>* x = x.__call__().whatever().unwrap() * 3*

>

>* and*

>

>* x .= 1*

>

>* is equivalent to*

>

>* x = x.1*

>

>* which is equivalent to*

>

>* SyntaxError: invalid syntax*

>

>

>>* Also, note that this syntax means that x will be rebound to*

>>* the result of calling x.y, whatever that is (frequently,*

>>* None, for mutating methods)*

>>

>>* In general, you can't count on methods to return references*

>>* to their instances, even though it's handy for fluent coding,*

>>* so this side effect may be unexpected to some*

>>

>

>* This is why it's for use with **immutable** objects.*

>

>

>>* That's a problem with your original example:*

>>

>>* >long_name = mkbuilder()*

>>

>>* >long_name = long_name.seta(a)*

>>

>>* >long_name = long_name.setb(b)*

>>

>>* >y = long_name.build()*

>>

>>* What do the methods seta and setb return?  If they don't*

>>* return "self" you've got a problem. I think.*

>>

>

>* They don't return self. Ever. The value bound to long_name is*

>* immutable, like an integer. They return a new instance.*

>

>

>* Then long_name isn't immutable. It changes with every line. That can *

>* lead to nasty bugs if you count on its immutability.*

>

>* Easy to see. Just print long_name after each call.*



You're mixing up value immutability with name immutability. The name

isn't immutable, but:


Er...No. I'm not confused at all, unless you define immutability in a new
way.. you said that the "value bound to long_name is immutable." It's not.
Your example below proves it.

An immutable object is one whose state cannot be modified once set. That's
not happening here.  The state of the object bound to long_name, which is a
pointer to an instance of you class, changes with each line.



long_name = mkbuilder()

x = long_name

long_name .= seta("a")

y = long_name

long_name .= setb("b")

z = long_name

print(x)  # a = None, b = None

print(y)  # a = "a", b = None

print(z)  # a = "a", b = "b"

print(x is y)  # False

print(x is z)  # False

print(y is z)  # False

print(long_name is z)  # True



See also:



long_name = 1

x = long_name

long_name += 1

y = long_name

long_name += 1

z = long_name

print(x)  # 1

print(y)  # 2

print(z)  # 3

print(x is y)  # False

print(x is z)  # False

print(y is z)  # False

print(long_name is z)  # True

>

>

>

>>* FWIW why can't you just write:*

>>

>>* x.y*

>>

>>* or for your example:*

>>

>>* long_name.seta(a)*

>>

>>* ?*

>>

>>

>

>* See the IRC bot builder example, it should be more clear. (It's*

>* about forking the builder.)*

>

>





If you wish to unsubscribe from receiving commercial electronic messages
from TD Bank Group, please click here  or go to
the following web address: www.td.com/tdoptout
Si vous souhaitez vous désabonner des messages électroniques de nature
commerciale envoyés par Groupe Banque TD veuillez cliquer ici
 ou vous rendre à l'adresse www.td.com/tddesab


NOTICE: Confidential message which may be privileged. Unauthorized
use/disclosure prohibited. If received in error, please go to
www.td.com/legal for instructions.
AVIS : Message confidentiel dont le contenu peut être privilégié.
Utilisation/divulgation interdites sans permission. Si reçu par erreur,
prière d'aller au www.td.com/francais/avis_juridique pour des instructions.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.



On 23/01/17 02:56 PM, Gerald Britton wrote:



On Jan 23, 2017 11:07 AM, "Soni L." > wrote:




On 23/01/17 01:52 PM, Gerald Britton wrote:




[snip]

>I propose `x .= y` -> `x = x . y`, for any `y`.

[snip]

I think you mean "any y that is a member of x"



Since it desugars into `x = x.y`, you can literally use anything
for `y`.

x .= __call__().whatever().unwrap() * 3

is equivalent to

x = x.__call__().whatever().unwrap() * 3

and

x .= 1

is equivalent to

x = x.1

which is equivalent to

SyntaxError: invalid syntax



Also, note that this syntax means that x will be rebound to
the result of calling x.y, whatever that is (frequently,
None, for mutating methods)

In general, you can't count on methods to return references
to their instances, even though it's handy for fluent coding,
so this side effect may be unexpected to some



This is why it's for use with **immutable** objects.



That's a problem with your original example:

>long_name = mkbuilder()

>long_name = long_name.seta(a)

>long_name = long_name.setb(b)

>y = long_name.build()

What do the methods seta and setb return?  If they don't
return "self" you've got a problem. I think.



They don't return self. Ever. The value bound to long_name is
immutable, like an integer. They return a new instance.


Then long_name isn't immutable. It changes with every line. That can 
lead to nasty bugs if you count on its immutability.


Easy to see. Just print long_name after each call.


You're mixing up value immutability with name immutability. The name 
isn't immutable, but:


long_name = mkbuilder()
x = long_name
long_name .= seta("a")
y = long_name
long_name .= setb("b")
z = long_name
print(x)  # a = None, b = None
print(y)  # a = "a", b = None
print(z)  # a = "a", b = "b"
print(x is y)  # False
print(x is z)  # False
print(y is z)  # False
print(long_name is z)  # True

See also:

long_name = 1
x = long_name
long_name += 1
y = long_name
long_name += 1
z = long_name
print(x)  # 1
print(y)  # 2
print(z)  # 3
print(x is y)  # False
print(x is z)  # False
print(y is z)  # False
print(long_name is z)  # True





FWIW why can't you just write:

x.y

or for your example:

long_name.seta(a)

?




See the IRC bot builder example, it should be more clear. (It's
about forking the builder.)




___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Gerald Britton
On Jan 23, 2017 11:07 AM, "Soni L."  wrote:



On 23/01/17 01:52 PM, Gerald Britton wrote:




[snip]



>I propose `x .= y` -> `x = x . y`, for any `y`.



[snip]



I think you mean "any y that is a member of x"


Since it desugars into `x = x.y`, you can literally use anything for `y`.

x .= __call__().whatever().unwrap() * 3

is equivalent to

x = x.__call__().whatever().unwrap() * 3

and

x .= 1

is equivalent to

x = x.1

which is equivalent to

SyntaxError: invalid syntax




Also, note that this syntax means that x will be rebound to the result of
calling x.y, whatever that is (frequently, None, for mutating methods)

In general, you can't count on methods to return references to their
instances, even though it's handy for fluent coding, so this side effect
may be unexpected to some


This is why it's for use with **immutable** objects.




That's a problem with your original example:



>long_name = mkbuilder()

>long_name = long_name.seta(a)

>long_name = long_name.setb(b)

>y = long_name.build()



What do the methods seta and setb return?  If they don't return "self"
you've got a problem. I think.


They don't return self. Ever. The value bound to long_name is immutable,
like an integer. They return a new instance.


Then long_name isn't immutable. It changes with every line. That can lead
to nasty bugs if you count on its immutability.

Easy to see. Just print long_name after each call.





FWIW why can't you just write:



x.y



or for your example:



long_name.seta(a)



?



See the IRC bot builder example, it should be more clear. (It's about
forking the builder.)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Guido van Rossum
On Mon, Jan 23, 2017 at 8:07 AM, Soni L.  wrote:

>
>
> Since it desugars into `x = x.y`, you can literally use anything for `y`.
>
> x .= __call__().whatever().unwrap() * 3
>
> is equivalent to
>
> x = x.__call__().whatever().unwrap() * 3
>
> and
>
> x .= 1
>
> is equivalent to
>
> x = x.1
>
> which is equivalent to
>
> SyntaxError: invalid syntax
>

And that's exactly the problem. Users would be greatly confused because
what's to the right of `.=` is *not* an expression, it's something more
restricted (in particular it must start with a plain identifier). This
makes the `.=` operator a very different beast from `=`, `+=` and friends.

I assume you think that's fine, but given your cavalier attitude about `x
.= 1` my feeling is that you don't have a lot of experience designing and
implementing language features. That is okay, you are learning it here. But
perhaps you should take the hint from the large number of people here who
have gently tried to explain to you that while this is a good idea, it's
not a great idea, and there's no sufficiently important use case to make up
for the confusion (indicated above) that it will inevitably cause.

-- 
--Guido van Rossum (python.org/~guido)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.



On 23/01/17 01:52 PM, Gerald Britton wrote:




[snip]

>I propose `x .= y` -> `x = x . y`, for any `y`.

[snip]

I think you mean "any y that is a member of x"



Since it desugars into `x = x.y`, you can literally use anything for `y`.

x .= __call__().whatever().unwrap() * 3

is equivalent to

x = x.__call__().whatever().unwrap() * 3

and

x .= 1

is equivalent to

x = x.1

which is equivalent to

SyntaxError: invalid syntax


Also, note that this syntax means that x will be rebound to the
result of calling x.y, whatever that is (frequently, None, for
mutating methods)

In general, you can't count on methods to return references to
their instances, even though it's handy for fluent coding, so this
side effect may be unexpected to some



This is why it's for use with **immutable** objects.


That's a problem with your original example:

>long_name = mkbuilder()

>long_name = long_name.seta(a)

>long_name = long_name.setb(b)

>y = long_name.build()

What do the methods seta and setb return?  If they don't return
"self" you've got a problem. I think.



They don't return self. Ever. The value bound to long_name is immutable, 
like an integer. They return a new instance.



FWIW why can't you just write:

x.y

or for your example:

long_name.seta(a)

?




See the IRC bot builder example, it should be more clear. (It's about 
forking the builder.)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Ethan Furman

On 01/23/2017 05:33 AM, Soni L. wrote:


It's literally sugar for repeating the name and moving the dot to the right.
 I think it's clearer than most other compound operators in that it doesn't
 affect precedence rules.

`x += y`, for any code `y`, is equivalent to `x = x + (y)`, not `x = x + y`.

`x .= y`, for any code `y`, is equivalent to `x = x . y`, not `x = x . (y)`.


This is not an improvement.

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Gerald Britton
[snip]



>I propose `x .= y` -> `x = x . y`, for any `y`.



[snip]



I think you mean "any y that is a member of x"



Also, note that this syntax means that x will be rebound to the result of
calling x.y, whatever that is (frequently, None, for mutating methods)

In general, you can't count on methods to return references to their
instances, even though it's handy for fluent coding, so this side effect
may be unexpected to some



That's a problem with your original example:



>long_name = mkbuilder()

>long_name = long_name.seta(a)

>long_name = long_name.setb(b)

>y = long_name.build()



What do the methods seta and setb return?  If they don't return "self"
you've got a problem. I think.



FWIW why can't you just write:



x.y



or for your example:



long_name.seta(a)



?
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Wes Turner
On Sunday, January 22, 2017, Wes Turner  wrote:

>
>
> On Sunday, January 22, 2017, Soni L.  > wrote:
>
>>
>>
>> On 22/01/17 10:03 PM, Wes Turner wrote:
>>
>>
>>
>> On Sunday, January 22, 2017, Wes Turner  wrote:
>>
>>> Have you looked at pyrsistent for 
>>> immutable/functional/persistent/copy-on-write
>>> data structures in Python?
>>>
>>> https://github.com/tobgu/pyrsistent/
>>>
>>> (freeze() / thaw())
>>>
>>> ... e.g. List and Dict NamedTuple values are not immutable (because
>>> append() and update() still work)
>>>
>>
>> fn.py also has immutables:
>> https://github.com/kachayev/fn.py/blob/master/README.rst#per
>> sistent-data-structures
>>
>>
>> You seem to be thinking of "immutable object builder". Not "the builder
>> itself is immutable and operations on it create new builders".
>>
>
> My mistake.
> Something like @optionable and/or @curried from fn.py in conjunction with
> PClass from pyrsistent may accomplish what you describe?
>

From
http://pyrsistent.readthedocs.io/en/latest/api.html#pyrsistent.PClass.set :

"Set a field in the instance. Returns a new instance with the updated
value. The original instance remains unmodified. Accepts key-value pairs or
single string representing the field name and a value."




>
>>
>>
>>
>>
>>>
>>> On Sunday, January 22, 2017, Soni L.  wrote:
>>>
 I've been thinking of an Immutable Builder pattern and an operator to
 go with it. Since the builder would be immutable, this wouldn't work:

 long_name = mkbuilder()
 long_name.seta(a)
 long_name.setb(b)
 y = long_name.build()

 Instead, you'd need something more like this:

 long_name = mkbuilder()
 long_name = long_name.seta(a)
 long_name = long_name.setb(b)
 y = long_name.build()

 Or we could add an operator to simplify it:

 long_name = mkbuilder()
 long_name .= seta(a)
 long_name .= setb(b)
 y = long_name.build()

 (Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y =
 x.build(). But that doesn't work if you wanna "fork" the builder. Some
 builders, like a builder for network connections of some sort, would work
 best if they were immutable/forkable.)
 ___
 Python-ideas mailing list
 Python-ideas@python.org
 https://mail.python.org/mailman/listinfo/python-ideas
 Code of Conduct: http://python.org/psf/codeofconduct/

>>>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] Immutable Builder" Pattern and Operator

2017-01-23 Thread Paul Moore
On 23 January 2017 at 13:47, Hervé "Kyle" MUTOMBO
 wrote:
> Paul Moore is clearly right when He says that this "a .= 1+1" doesn't make
> sense. It means nothing understandable although in "a .= s(e)" can mean
> something. As a matter of fact "a .= EXPR" is bound to succeed only in a
> very small set of cases.

By responding to a digest you make it very hard to see what you're
replying to. Could you get the messages as individual ones, and reply
quoting the context properly, please?

I'm not sure how to interpret your above comment in the light of your
other comment

> Pleasing to see and somehow elegant. I believe .= is a good idea.

as I'm arguing pretty strongly that .= is *not* a good idea, because
there are all sorts of ill-defined cases that haven't been clearly
explained in a way that matches the rest of Python's grammar and
semantics.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Random832
On Mon, Jan 23, 2017, at 09:12, Soni L. wrote:
> Builders for network connections where you don't wanna start with a 
> fresh builder every time.

Maybe you need a builder builder.

Or, more seriously, a way to differentiate the things in the 'builder'
from the things that are going to be different with each connection, and
pass them separately in the connection's constructor.

Or a clone method.

> It is far more useful only because it's not just a syntax sugar. It's 
> more like a completely new, standalone operator.
> Which, IMO, makes it more confusing.
> 
> I propose `x .= y` -> `x = x . y`, for any `y`.

I think you're underestimating the extent to which the fact that "y"
isn't a real expression will cause confusion.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.



On 23/01/17 11:54 AM, Steven D'Aprano wrote:

On Mon, Jan 23, 2017 at 12:49:19AM -0200, Soni L. wrote:
[...]

You seem to be thinking of "immutable object builder". Not "the builder
itself is immutable and operations on it create new builders".

Why would you make a builder class immutable?


Builders for network connections where you don't wanna start with a 
fresh builder every time.




That's not a rhetorical question -- I'm genuinely surprised that you're
not only using the builder design pattern (there are usually better
solutions in Python) but more so that you're making the builder itself
immutable.

In any case, it seems that this is such a narrow and unusual use-case
that it wouldn't be wise to give it special syntax. Especially when
there are other, potentially far more useful, uses for the .= syntax,
e.g. Julia's syntactic loop fusion:

http://julialang.org/blog/2017/01/moredots



It is far more useful only because it's not just a syntax sugar. It's 
more like a completely new, standalone operator.

Which, IMO, makes it more confusing.

I propose `x .= y` -> `x = x . y`, for any `y`.
You propose `x .= y` -> `operate_on(x).with(lambda: y)`

This feels like you're arguing for loops are more useful than 
multiplication, and thus we shouldn't have multiplication.





___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Steven D'Aprano
On Mon, Jan 23, 2017 at 12:49:19AM -0200, Soni L. wrote:
[...]
> You seem to be thinking of "immutable object builder". Not "the builder 
> itself is immutable and operations on it create new builders".

Why would you make a builder class immutable?

That's not a rhetorical question -- I'm genuinely surprised that you're 
not only using the builder design pattern (there are usually better 
solutions in Python) but more so that you're making the builder itself 
immutable.

In any case, it seems that this is such a narrow and unusual use-case 
that it wouldn't be wise to give it special syntax. Especially when 
there are other, potentially far more useful, uses for the .= syntax, 
e.g. Julia's syntactic loop fusion:

http://julialang.org/blog/2017/01/moredots




-- 
Steve
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Immutable Builder" Pattern and Operator

2017-01-23 Thread Kyle
Paul Moore is clearly right when He says that this "a .= 1+1" doesn't make
sense. It means nothing understandable although in "a .= s(e)" can mean
something. As a matter of fact "a .= EXPR" is bound to succeed only in a
very small set of cases.
On Jan 23, 2017 14:39,  wrote:

Send Python-ideas mailing list submissions to
python-ideas@python.org

To subscribe or unsubscribe via the World Wide Web, visit
https://mail.python.org/mailman/listinfo/python-ideas
or, via email, send a message with subject or body 'help' to
python-ideas-requ...@python.org

You can reach the person managing the list at
python-ideas-ow...@python.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Python-ideas digest..."


Today's Topics:

   1. Re: "Immutable Builder" Pattern and Operator (Paul Moore)
   2. Re: "Immutable Builder" Pattern and Operator (Soni L.)
   3. Re: Python-ideas Digest, Vol 122, Issue 81 (Herv? Kyle MUTOMBO)


--

Message: 1
Date: Mon, 23 Jan 2017 13:26:49 +0000
From: Paul Moore 
To: "Soni L." 
Cc: Python-Ideas 
Subject: Re: [Python-ideas] "Immutable Builder" Pattern and Operator
Message-ID:

Content-Type: text/plain; charset=UTF-8

On 23 January 2017 at 13:05, Soni L.  wrote:
> Yeah but the dotequals operator has many other benefits:
>
> long_name .= __call__  # cast to callable
> long_name .= wrapped  # unwrap
> etc

Those don't seem particularly clear to me.

> And it also looks neat.

Well, we have to agree to differ on that one.

Also, the semantics of the proposed operation are very odd. If I
understand your proposal

a .= b(c)

doesn't evaluate b(c) (It can't, as b is a method of a and doesn't
make sense on its own), but rather combines the LHS and RHS with a dot
- so it's defined in terms of rewriting the input rather than as an
operation on the subexpressions. There's no other operator in Python
that I'm aware of that works like this.

What grammar would you allow for the RHS? So far you've shown

LHS .= METHOD(ARGS)
LHS .= ATTRIBUTE

Clearly,

LHS .= EXPR

makes no sense in general (consider a .= 1+1).

On the other hand, what about

LHS .= ATTRIBUTE[INDEX]

? I'm guessing you'd want that allowed?

Frankly, I don't think the benefits are even close to justifying the
complexity.

Paul


--------------

Message: 2
Date: Mon, 23 Jan 2017 11:33:26 -0200
From: "Soni L." 
To: "M.-A. Lemburg" 
Cc: "python-ideas@python.org" 
Subject: Re: [Python-ideas] "Immutable Builder" Pattern and Operator
Message-ID: 
Content-Type: text/plain; charset=windows-1252; format=flowed

... I need a better email client. *double-checks I got everything right
this time...*

On 23/01/17 11:30 AM, Soni L. wrote:
> Sorry, I replied to this wrong. Not used to this mailing list.
>
> On 23/01/17 11:28 AM, Soni L. wrote:
>>
>>
>> On 23/01/17 11:18 AM, M.-A. Lemburg wrote:
>>> On 23.01.2017 14:05, Soni L. wrote:
>>>>
>>>> On 23/01/17 09:45 AM, Serhiy Storchaka wrote:
>>>>> On 23.01.17 01:30, Soni L. wrote:
>>>>>> On 22/01/17 08:54 PM, Serhiy Storchaka wrote:
>>>>>>> On 23.01.17 00:45, Soni L. wrote:
>>>>>>>> I've been thinking of an Immutable Builder pattern and an operator
>>>>>>>> to go
>>>>>>>> with it. Since the builder would be immutable, this wouldn't work:
>>>>>>>>
>>>>>>>> long_name = mkbuilder()
>>>>>>>> long_name.seta(a)
>>>>>>>> long_name.setb(b)
>>>>>>>> y = long_name.build()
>>>>>>> I think the more pythonic way is:
>>>>>>>
>>>>>>> y = build(a=a, b=b)
>>>>>>>
>>>>>>> A Builder pattern is less used in Python due to the support of
>>>>>>> keyword
>>>>>>> arguments.
>>>>>> I guess you could do something like this, for an IRC bot builder:
>>>>>>
>>>>>> fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net",
>>>>>> port=6697,
>>>>>> ssl=true)
>>>>>> mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
>>>>>>channels=["#bots"]).build()
>>>>>> fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
>>>>>> channeldcc=true)
>>>>>> dccbot = mk

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.
... I need a better email client. *double-checks I got everything right 
this time...*


On 23/01/17 11:30 AM, Soni L. wrote:

Sorry, I replied to this wrong. Not used to this mailing list.

On 23/01/17 11:28 AM, Soni L. wrote:



On 23/01/17 11:18 AM, M.-A. Lemburg wrote:

On 23.01.2017 14:05, Soni L. wrote:


On 23/01/17 09:45 AM, Serhiy Storchaka wrote:

On 23.01.17 01:30, Soni L. wrote:

On 22/01/17 08:54 PM, Serhiy Storchaka wrote:

On 23.01.17 00:45, Soni L. wrote:

I've been thinking of an Immutable Builder pattern and an operator
to go
with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()

I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of 
keyword

arguments.

I guess you could do something like this, for an IRC bot builder:

fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", 
port=6697,

ssl=true)
mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
   channels=["#bots"]).build()
fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
channeldcc=true)
dccbot = mkircbotbuilder(parent=fndccbotbuilder,
channels=["#ctcp-s"]).build()
otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
network="irc.subluminal.net")  # because we want this whole network
otherbot = mkircbotbuilder(parent=otherircbotbuilder,
channels=["#programming"]).build()# to use DCC and channel DCC

But this would be cleaner:

botbuilder =
mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
mainbot = botbuilder.channels(["#bots"]).build()
botbuilder .= dcc(true).channeldcc(true)
dccbot = botbuilder.channels(["#ctcp-s"]).build()
botbuilder .= network("irc.subluminal.net")
otherbot = botbuilder.channels(["#programming"]).build()

In Python you can save common options in a dict and pass them as
var-keyword argument. Or use functools.partial. In any case you don't
need a builder class with the build method and a number of 
configuring

methods. It can be just a function with optional keyword parameters.

A Builder pattern is often used in languages that don't support
passing arguments by keyword and partial functions. Python rarely
needs the purposed class implementing a Builder pattern. Actually a
Builder pattern is built-in in the language as a part of syntax.


Yeah but the dotequals operator has many other benefits:

long_name .= __call__  # cast to callable
long_name .= wrapped  # unwrap
etc

And it also looks neat.

I don't see this an being a particular intuitive way of writing
such rather uncommon constructs.

The syntax is not clear (what if you have an expression on the RHS)
and it doesn't save you much in writing (if long_name is too long
simply rebind it under a shorter name for the purpose of the code
block).


It's literally sugar for repeating the name and moving the dot to the 
right. I think it's clearer than most other compound operators in 
that it doesn't affect precedence rules.


`x += y`, for any code `y`, is equivalent to `x = x + (y)`, not `x = 
x + y`.


`x .= y`, for any code `y`, is equivalent to `x = x . y`, not `x = x 
. (y)`.




Also note that rebinding different objects to the same name
in the same block is often poor style and can easily lead to
hard to track bugs.



Rebinding different objects to the same name in rapid succession is 
fine.



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Paul Moore
On 23 January 2017 at 13:05, Soni L.  wrote:
> Yeah but the dotequals operator has many other benefits:
>
> long_name .= __call__  # cast to callable
> long_name .= wrapped  # unwrap
> etc

Those don't seem particularly clear to me.

> And it also looks neat.

Well, we have to agree to differ on that one.

Also, the semantics of the proposed operation are very odd. If I
understand your proposal

a .= b(c)

doesn't evaluate b(c) (It can't, as b is a method of a and doesn't
make sense on its own), but rather combines the LHS and RHS with a dot
- so it's defined in terms of rewriting the input rather than as an
operation on the subexpressions. There's no other operator in Python
that I'm aware of that works like this.

What grammar would you allow for the RHS? So far you've shown

LHS .= METHOD(ARGS)
LHS .= ATTRIBUTE

Clearly,

LHS .= EXPR

makes no sense in general (consider a .= 1+1).

On the other hand, what about

LHS .= ATTRIBUTE[INDEX]

? I'm guessing you'd want that allowed?

Frankly, I don't think the benefits are even close to justifying the complexity.

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread M.-A. Lemburg
On 23.01.2017 14:05, Soni L. wrote:
> 
> 
> On 23/01/17 09:45 AM, Serhiy Storchaka wrote:
>> On 23.01.17 01:30, Soni L. wrote:
>>> On 22/01/17 08:54 PM, Serhiy Storchaka wrote:
 On 23.01.17 00:45, Soni L. wrote:
> I've been thinking of an Immutable Builder pattern and an operator
> to go
> with it. Since the builder would be immutable, this wouldn't work:
>
> long_name = mkbuilder()
> long_name.seta(a)
> long_name.setb(b)
> y = long_name.build()

 I think the more pythonic way is:

 y = build(a=a, b=b)

 A Builder pattern is less used in Python due to the support of keyword
 arguments.
>>>
>>> I guess you could do something like this, for an IRC bot builder:
>>>
>>> fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697,
>>> ssl=true)
>>> mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
>>>   channels=["#bots"]).build()
>>> fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
>>> channeldcc=true)
>>> dccbot = mkircbotbuilder(parent=fndccbotbuilder,
>>> channels=["#ctcp-s"]).build()
>>> otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
>>> network="irc.subluminal.net")  # because we want this whole network
>>> otherbot = mkircbotbuilder(parent=otherircbotbuilder,
>>> channels=["#programming"]).build()# to use DCC and channel DCC
>>>
>>> But this would be cleaner:
>>>
>>> botbuilder =
>>> mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
>>> mainbot = botbuilder.channels(["#bots"]).build()
>>> botbuilder .= dcc(true).channeldcc(true)
>>> dccbot = botbuilder.channels(["#ctcp-s"]).build()
>>> botbuilder .= network("irc.subluminal.net")
>>> otherbot = botbuilder.channels(["#programming"]).build()
>>
>> In Python you can save common options in a dict and pass them as
>> var-keyword argument. Or use functools.partial. In any case you don't
>> need a builder class with the build method and a number of configuring
>> methods. It can be just a function with optional keyword parameters.
>>
>> A Builder pattern is often used in languages that don't support
>> passing arguments by keyword and partial functions. Python rarely
>> needs the purposed class implementing a Builder pattern. Actually a
>> Builder pattern is built-in in the language as a part of syntax.
>>
> Yeah but the dotequals operator has many other benefits:
> 
> long_name .= __call__  # cast to callable
> long_name .= wrapped  # unwrap
> etc
> 
> And it also looks neat.

I don't see this an being a particular intuitive way of writing
such rather uncommon constructs.

The syntax is not clear (what if you have an expression on the RHS)
and it doesn't save you much in writing (if long_name is too long
simply rebind it under a shorter name for the purpose of the code
block).

Also note that rebinding different objects to the same name
in the same block is often poor style and can easily lead to
hard to track bugs.

-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Jan 23 2017)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...   http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...   http://zope.egenix.com/


::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
   Registered at Amtsgericht Duesseldorf: HRB 46611
   http://www.egenix.com/company/contact/
  http://www.malemburg.com/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Soni L.



On 23/01/17 09:45 AM, Serhiy Storchaka wrote:

On 23.01.17 01:30, Soni L. wrote:

On 22/01/17 08:54 PM, Serhiy Storchaka wrote:

On 23.01.17 00:45, Soni L. wrote:
I've been thinking of an Immutable Builder pattern and an operator 
to go

with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()


I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of keyword
arguments.


I guess you could do something like this, for an IRC bot builder:

fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697,
ssl=true)
mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
  channels=["#bots"]).build()
fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
channeldcc=true)
dccbot = mkircbotbuilder(parent=fndccbotbuilder,
channels=["#ctcp-s"]).build()
otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
network="irc.subluminal.net")  # because we want this whole network
otherbot = mkircbotbuilder(parent=otherircbotbuilder,
channels=["#programming"]).build()# to use DCC and channel DCC

But this would be cleaner:

botbuilder =
mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
mainbot = botbuilder.channels(["#bots"]).build()
botbuilder .= dcc(true).channeldcc(true)
dccbot = botbuilder.channels(["#ctcp-s"]).build()
botbuilder .= network("irc.subluminal.net")
otherbot = botbuilder.channels(["#programming"]).build()


In Python you can save common options in a dict and pass them as 
var-keyword argument. Or use functools.partial. In any case you don't 
need a builder class with the build method and a number of configuring 
methods. It can be just a function with optional keyword parameters.


A Builder pattern is often used in languages that don't support 
passing arguments by keyword and partial functions. Python rarely 
needs the purposed class implementing a Builder pattern. Actually a 
Builder pattern is built-in in the language as a part of syntax.



Yeah but the dotequals operator has many other benefits:

long_name .= __call__  # cast to callable
long_name .= wrapped  # unwrap
etc

And it also looks neat.
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Serhiy Storchaka

On 23.01.17 01:30, Soni L. wrote:

On 22/01/17 08:54 PM, Serhiy Storchaka wrote:

On 23.01.17 00:45, Soni L. wrote:

I've been thinking of an Immutable Builder pattern and an operator to go
with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()


I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of keyword
arguments.


I guess you could do something like this, for an IRC bot builder:

fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697,
ssl=true)
mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
  channels=["#bots"]).build()
fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
channeldcc=true)
dccbot = mkircbotbuilder(parent=fndccbotbuilder,
channels=["#ctcp-s"]).build()
otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
network="irc.subluminal.net")  # because we want this whole network
otherbot = mkircbotbuilder(parent=otherircbotbuilder,
channels=["#programming"]).build()# to use DCC and channel DCC

But this would be cleaner:

botbuilder =
mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
mainbot = botbuilder.channels(["#bots"]).build()
botbuilder .= dcc(true).channeldcc(true)
dccbot = botbuilder.channels(["#ctcp-s"]).build()
botbuilder .= network("irc.subluminal.net")
otherbot = botbuilder.channels(["#programming"]).build()


In Python you can save common options in a dict and pass them as 
var-keyword argument. Or use functools.partial. In any case you don't 
need a builder class with the build method and a number of configuring 
methods. It can be just a function with optional keyword parameters.


A Builder pattern is often used in languages that don't support passing 
arguments by keyword and partial functions. Python rarely needs the 
purposed class implementing a Builder pattern. Actually a Builder 
pattern is built-in in the language as a part of syntax.



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Paul Moore
On 22 January 2017 at 22:45, Soni L.  wrote:
> I've been thinking of an Immutable Builder pattern and an operator to go
> with it. Since the builder would be immutable, this wouldn't work:
>
> long_name = mkbuilder()
> long_name.seta(a)
> long_name.setb(b)
> y = long_name.build()
>
> Instead, you'd need something more like this:
>
> long_name = mkbuilder()
> long_name = long_name.seta(a)
> long_name = long_name.setb(b)
> y = long_name.build()
>
> Or we could add an operator to simplify it:
>
> long_name = mkbuilder()
> long_name .= seta(a)
> long_name .= setb(b)
> y = long_name.build()
>
> (Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y = x.build().
> But that doesn't work if you wanna "fork" the builder. Some builders, like a
> builder for network connections of some sort, would work best if they were
> immutable/forkable.)

I don't think the .= operator adds enough to be worth it. If the
problem you see is the duplication of long_name in those lines (it's
difficult to be sure without a real example) then you can use a
temporary:

b = mkbuilder()
b = b.seta(a)
b = b.setb(b)
long_name = b
y = long_name.build()

For your real example:

On 22 January 2017 at 23:30, Soni L.  wrote:
> fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697,
> ssl=true)
> mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
>   channels=["#bots"]).build()
> fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true,
> channeldcc=true)
> dccbot = mkircbotbuilder(parent=fndccbotbuilder,
> channels=["#ctcp-s"]).build()
> otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder,
> network="irc.subluminal.net")  # because we want this whole network
> otherbot = mkircbotbuilder(parent=otherircbotbuilder,
> channels=["#programming"]).build()# to use DCC and channel DCC
>
> But this would be cleaner:
>
> botbuilder =
> mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)
> mainbot = botbuilder.channels(["#bots"]).build()
> botbuilder .= dcc(true).channeldcc(true)
> dccbot = botbuilder.channels(["#ctcp-s"]).build()
> botbuilder .= network("irc.subluminal.net")
> otherbot = botbuilder.channels(["#programming"]).build()

I don't find the second example appreciably cleaner than the first.
But a bit of reformatting looks better to me:

# First create builders for the bots
fnircbotbuilder = mkircbotbuilder(
network="irc.freenode.net",
port=6697,
ssl=true)
fndccbotbuilder = mkircbotbuilder(
parent=fnircbotbuilder,
dcc=true,
channeldcc=true)
otherircbotbuilder = mkircbotbuilder(
parent=fndccbotbuilder,
network="irc.subluminal.net")

# Now create the actual bots
mainbot = mkircbotbuilder(
parent=fnircbotbuilder,
channels=["#bots"]).build()
dccbot = mkircbotbuilder(
parent=fndccbotbuilder,
channels=["#ctcp-s"]).build()
otherbot = mkircbotbuilder(
parent=otherircbotbuilder,
channels=["#programming"]).build()

And some API redesign (make the builders classes, and the parent
relationship becomes subclassing, and maybe make channels an argument
to build() so that you don't need fresh builders for each of the
actual bots, and you don't even need the "builder" in the name at this
point) makes the whole thing look far cleaner (to me, at least):

class FNIRCBot(IRCBot):
network="irc.freenode.net"
port=6697
ssl=True
class FNDCCBot(FNIRCBot):
dcc=True
channeldcc=True
class OtherIRCBot(IRCBot):
network="irc.subluminal.net"

mainbot = FNIRCBot(channels=["#bots"])
dccbot = FNDCCBot(channels=["#ctcp-s"])
otherbot = OtherIRCBot(channels=["#programming"])

Paul
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-23 Thread Cory Benfield

> On 22 Jan 2017, at 22:45, Soni L.  wrote:
> 
> 

This pattern is present in the cryptography module already with things like 
their x509.CertificateBuilder: 
https://cryptography.io/en/latest/x509/reference/#cryptography.x509.CertificateBuilder
 
.

My 2c, but I find that code perfectly readable and legible. I don’t think a 
dot-equals operator would be needed.

Cory___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Wes Turner
On Sunday, January 22, 2017, Soni L.  wrote:

>
>
> On 22/01/17 10:03 PM, Wes Turner wrote:
>
>
>
> On Sunday, January 22, 2017, Wes Turner  > wrote:
>
>> Have you looked at pyrsistent for 
>> immutable/functional/persistent/copy-on-write
>> data structures in Python?
>>
>> https://github.com/tobgu/pyrsistent/
>>
>> (freeze() / thaw())
>>
>> ... e.g. List and Dict NamedTuple values are not immutable (because
>> append() and update() still work)
>>
>
> fn.py also has immutables:
> https://github.com/kachayev/fn.py/blob/master/README.rst#
> persistent-data-structures
>
>
> You seem to be thinking of "immutable object builder". Not "the builder
> itself is immutable and operations on it create new builders".
>

My mistake.
Something like @optionable and/or @curried from fn.py in conjunction with
PClass from pyrsistent may accomplish what you describe?


>
>
>
>
>>
>> On Sunday, January 22, 2017, Soni L.  wrote:
>>
>>> I've been thinking of an Immutable Builder pattern and an operator to go
>>> with it. Since the builder would be immutable, this wouldn't work:
>>>
>>> long_name = mkbuilder()
>>> long_name.seta(a)
>>> long_name.setb(b)
>>> y = long_name.build()
>>>
>>> Instead, you'd need something more like this:
>>>
>>> long_name = mkbuilder()
>>> long_name = long_name.seta(a)
>>> long_name = long_name.setb(b)
>>> y = long_name.build()
>>>
>>> Or we could add an operator to simplify it:
>>>
>>> long_name = mkbuilder()
>>> long_name .= seta(a)
>>> long_name .= setb(b)
>>> y = long_name.build()
>>>
>>> (Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y =
>>> x.build(). But that doesn't work if you wanna "fork" the builder. Some
>>> builders, like a builder for network connections of some sort, would work
>>> best if they were immutable/forkable.)
>>> ___
>>> Python-ideas mailing list
>>> Python-ideas@python.org
>>> https://mail.python.org/mailman/listinfo/python-ideas
>>> Code of Conduct: http://python.org/psf/codeofconduct/
>>>
>>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Soni L.



On 22/01/17 10:03 PM, Wes Turner wrote:



On Sunday, January 22, 2017, Wes Turner > wrote:


Have you looked at pyrsistent for
immutable/functional/persistent/copy-on-write data structures in
Python?

https://github.com/tobgu/pyrsistent/


(freeze() / thaw())

... e.g. List and Dict NamedTuple values are not immutable
(because append() and update() still work)


fn.py also has immutables:
https://github.com/kachayev/fn.py/blob/master/README.rst#persistent-data-structures


You seem to be thinking of "immutable object builder". Not "the builder 
itself is immutable and operations on it create new builders".




On Sunday, January 22, 2017, Soni L. > wrote:

I've been thinking of an Immutable Builder pattern and an
operator to go with it. Since the builder would be immutable,
this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()

Instead, you'd need something more like this:

long_name = mkbuilder()
long_name = long_name.seta(a)
long_name = long_name.setb(b)
y = long_name.build()

Or we could add an operator to simplify it:

long_name = mkbuilder()
long_name .= seta(a)
long_name .= setb(b)
y = long_name.build()

(Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then
y = x.build(). But that doesn't work if you wanna "fork" the
builder. Some builders, like a builder for network connections
of some sort, would work best if they were immutable/forkable.)
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas

Code of Conduct: http://python.org/psf/codeofconduct/




___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Wes Turner
On Sunday, January 22, 2017, Wes Turner  wrote:

> Have you looked at pyrsistent for 
> immutable/functional/persistent/copy-on-write
> data structures in Python?
>
> https://github.com/tobgu/pyrsistent/
>
> (freeze() / thaw())
>
> ... e.g. List and Dict NamedTuple values are not immutable (because
> append() and update() still work)
>

fn.py also has immutables:
https://github.com/kachayev/fn.py/blob/master/README.rst#persistent-data-structures


>
> On Sunday, January 22, 2017, Soni L.  > wrote:
>
>> I've been thinking of an Immutable Builder pattern and an operator to go
>> with it. Since the builder would be immutable, this wouldn't work:
>>
>> long_name = mkbuilder()
>> long_name.seta(a)
>> long_name.setb(b)
>> y = long_name.build()
>>
>> Instead, you'd need something more like this:
>>
>> long_name = mkbuilder()
>> long_name = long_name.seta(a)
>> long_name = long_name.setb(b)
>> y = long_name.build()
>>
>> Or we could add an operator to simplify it:
>>
>> long_name = mkbuilder()
>> long_name .= seta(a)
>> long_name .= setb(b)
>> y = long_name.build()
>>
>> (Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y =
>> x.build(). But that doesn't work if you wanna "fork" the builder. Some
>> builders, like a builder for network connections of some sort, would work
>> best if they were immutable/forkable.)
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Wes Turner
Have you looked at pyrsistent for
immutable/functional/persistent/copy-on-write data structures in Python?

https://github.com/tobgu/pyrsistent/

(freeze() / thaw())

... e.g. List and Dict NamedTuple values are not immutable (because
append() and update() still work)

On Sunday, January 22, 2017, Soni L.  wrote:

> I've been thinking of an Immutable Builder pattern and an operator to go
> with it. Since the builder would be immutable, this wouldn't work:
>
> long_name = mkbuilder()
> long_name.seta(a)
> long_name.setb(b)
> y = long_name.build()
>
> Instead, you'd need something more like this:
>
> long_name = mkbuilder()
> long_name = long_name.seta(a)
> long_name = long_name.setb(b)
> y = long_name.build()
>
> Or we could add an operator to simplify it:
>
> long_name = mkbuilder()
> long_name .= seta(a)
> long_name .= setb(b)
> y = long_name.build()
>
> (Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y =
> x.build(). But that doesn't work if you wanna "fork" the builder. Some
> builders, like a builder for network connections of some sort, would work
> best if they were immutable/forkable.)
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Ethan Furman

On 01/22/2017 03:30 PM, Soni L. wrote:

On 22/01/17 08:54 PM, Serhiy Storchaka wrote:

On 23.01.17 00:45, Soni L. wrote:



I've been thinking of an Immutable Builder pattern and an operator to go
with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()


I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of keyword 
arguments.


I guess you could do something like this, for an IRC bot builder:

fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697, 
ssl=true)
mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
   channels=["#bots"]).build()
fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true, 
channeldcc=true)
dccbot = mkircbotbuilder(parent=fndccbotbuilder, channels=["#ctcp-s"]).build()
otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder, 
network="irc.subluminal.net")  # because we want this whole network
otherbot = mkircbotbuilder(parent=otherircbotbuilder, 
channels=["#programming"]).build()# to use DCC and channel DCC


The following is just fine:

   fnircbotbuilder = mkircbotbuilder(
network="irc.freenode.net",
port=6697,
ssl=true,
)
mainbot = fnircbotbuilder(channels=["#bots"]).build()

fndccbotbuilder = fnircbotbuilder(dcc=true, channeldcc=true)
dccbot = fndccbotbuilder(channels=["#ctcp-s"]).build()

otherircbotbuilder = fndccbotbuilder(network="irc.subluminal.net")
otherbot = otherircbotbuilder(channels=["#programming"]).build()

--
~Ethan~
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Soni L.

On 22/01/17 08:54 PM, Serhiy Storchaka wrote:

On 23.01.17 00:45, Soni L. wrote:

I've been thinking of an Immutable Builder pattern and an operator to go
with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()


I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of keyword 
arguments.


I guess you could do something like this, for an IRC bot builder:

fnircbotbuilder = mkircbotbuilder(network="irc.freenode.net", port=6697, 
ssl=true)

mainbot = mkircbotbuilder(parent=fnircbotbuilder,  # ???
  channels=["#bots"]).build()
fndccbotbuilder = mkircbotbuilder(parent=fnircbotbuilder, dcc=true, 
channeldcc=true)
dccbot = mkircbotbuilder(parent=fndccbotbuilder, 
channels=["#ctcp-s"]).build()
otherircbotbuilder = mkircbotbuilder(parent=fndccbotbuilder, 
network="irc.subluminal.net")  # because we want this whole network
otherbot = mkircbotbuilder(parent=otherircbotbuilder, 
channels=["#programming"]).build()# to use DCC and channel DCC


But this would be cleaner:

botbuilder = 
mkircbotbuilder().network("irc.freenode.net").port(6697).ssl(true)

mainbot = botbuilder.channels(["#bots"]).build()
botbuilder .= dcc(true).channeldcc(true)
dccbot = botbuilder.channels(["#ctcp-s"]).build()
botbuilder .= network("irc.subluminal.net")
otherbot = botbuilder.channels(["#programming"]).build()

(I mean, "channels" could/should be a per-bot property instead of a 
per-builder property... but that doesn't affect the examples much.)

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Joao S. O. Bueno
This is easy to do in Python, and we already have NamedTuples and
other things.


If you need such a builder anyway, this snippet can work - no need for
special syntax:

https://gist.github.com/jsbueno/b2b5f5c06caa915c451253bb4f171ee9



On 22 January 2017 at 20:54, Serhiy Storchaka  wrote:
> On 23.01.17 00:45, Soni L. wrote:
>>
>> I've been thinking of an Immutable Builder pattern and an operator to go
>> with it. Since the builder would be immutable, this wouldn't work:
>>
>> long_name = mkbuilder()
>> long_name.seta(a)
>> long_name.setb(b)
>> y = long_name.build()
>
>
> I think the more pythonic way is:
>
> y = build(a=a, b=b)
>
> A Builder pattern is less used in Python due to the support of keyword
> arguments.
>
>
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Serhiy Storchaka

On 23.01.17 00:45, Soni L. wrote:

I've been thinking of an Immutable Builder pattern and an operator to go
with it. Since the builder would be immutable, this wouldn't work:

long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()


I think the more pythonic way is:

y = build(a=a, b=b)

A Builder pattern is less used in Python due to the support of keyword 
arguments.



___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] "Immutable Builder" Pattern and Operator

2017-01-22 Thread Soni L.
I've been thinking of an Immutable Builder pattern and an operator to go 
with it. Since the builder would be immutable, this wouldn't work:


long_name = mkbuilder()
long_name.seta(a)
long_name.setb(b)
y = long_name.build()

Instead, you'd need something more like this:

long_name = mkbuilder()
long_name = long_name.seta(a)
long_name = long_name.setb(b)
y = long_name.build()

Or we could add an operator to simplify it:

long_name = mkbuilder()
long_name .= seta(a)
long_name .= setb(b)
y = long_name.build()

(Yes, I'm aware you can x = mkbuilder().seta(a).setb(b), then y = 
x.build(). But that doesn't work if you wanna "fork" the builder. Some 
builders, like a builder for network connections of some sort, would 
work best if they were immutable/forkable.)

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/