Is there a way to change the closure of a python function?

2016-09-27 Thread Peng Yu
Hi, In many other functional language, one can change the closure of a
function. Is it possible in python?

http://ynniv.com/blog/2007/08/closures-in-python.html

-- 
Regards,
Peng
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Peter Otten
Peng Yu wrote:

> Hi, In many other functional language, one can change the closure of a
> function. 

Which are those languages, and how do they work? And is Python actually a 
"functional language"?

> Is it possible in python?

I'm not sure what you mean. Something like 

>>> def f(x):
... def g(y):
... return x + y
... def h(newx):
... nonlocal x
... x = newx
... return g, h
... 
>>> a, b = f(10)
>>> a(42)
52
>>> b(20)
>>> a(42)
62

?
 
> http://ynniv.com/blog/2007/08/closures-in-python.html

A short explanation would have been better than that link.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread jmp

On 09/27/2016 04:01 PM, Peng Yu wrote:

Hi, In many other functional language, one can change the closure of a
function. Is it possible in python?

http://ynniv.com/blog/2007/08/closures-in-python.html



If I understood correctly your link:

(untested)
def func(x):
return x+func.y

func.y = 10
func(5) => 15
func.y = 100
func(5) => 105

implements a closure of a function.


jm

Note: function are objects, and can have attributes, however I rarely 
see usage of these, there could be good reasons for that.




--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Ian Kelly
On Tue, Sep 27, 2016 at 8:41 AM, jmp  wrote:
> On 09/27/2016 04:01 PM, Peng Yu wrote:
>>
>> Hi, In many other functional language, one can change the closure of a
>> function. Is it possible in python?
>>
>> http://ynniv.com/blog/2007/08/closures-in-python.html
>>
>
> If I understood correctly your link:
>
> (untested)
> def func(x):
> return x+func.y
>
> func.y = 10
> func(5) => 15
> func.y = 100
> func(5) => 105
>
> implements a closure of a function.

That is not a closure. A closure is a construct of lexical scoping.
This is an example of a closure:

def f(x):
def g():
return x
return g

We say that the variables of f are "closed" over the function g. An
example of use:

py> g1 = f(42)
py> g2 = f(64)
py> g1()
42
py> g2()
64

Note that each closure has its own value of x.

The link suggests that object methods in Python are closures because
of the self argument, but I disagree with that; closures are
constructs of lexical scoping.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Chris Angelico
On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu  wrote:
> Hi, In many other functional language, one can change the closure of a
> function. Is it possible in python?
>
> http://ynniv.com/blog/2007/08/closures-in-python.html
>

>From the blog post:

"""In some languages, the variable bindings contained in a closure
behave just like any other variables. Alas, in python they are
read-only."""

This is not true, at least as of Python 3.

def makeInc(x):
  def inc(y, moreinc=0):
 # x is "closed" in the definition of inc
 nonlocal x
 x += moreinc
 return y + x
  return inc

The 'nonlocal' keyword is like 'global', applying only to assignments
(the blog post already mentions the possibility of mutating an object
rather than reassigning it), and permitting assignment into a broader
scope than the function's locals. You can also have multiple closures
in the same context, and changes made by one of them will affect the
others.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Terry Reedy

On 9/27/2016 11:01 AM, Chris Angelico wrote:

On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu  wrote:

Hi, In many other functional language, one can change the closure of a
function. Is it possible in python?

http://ynniv.com/blog/2007/08/closures-in-python.html



From the blog post:

"""In some languages, the variable bindings contained in a closure
behave just like any other variables. Alas, in python they are
read-only."""

This is not true, at least as of Python 3.

def makeInc(x):
  def inc(y, moreinc=0):
 # x is "closed" in the definition of inc
 nonlocal x
 x += moreinc
 return y + x
  return inc


The value of the cell variable is writable from within the body of the 
closure function if declared nonlocal, but not otherwise, and not from 
without.  The latter may be what Peng meant by 'change' and the blogger 
by 'read-only'.


def makeInc(x):
  def inc(y, moreinc=0):
 # x is "closed" in the definition of inc
 nonlocal x
 x += moreinc
 return y + x
  return inc

f = makeInc(23)
fclose = f.__closure__  # a tuple of 'cells'
fcell = fclose[0]

print(dir(fcell))
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
# '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
# '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__',
# '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
# '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
# Note: no mutation method

print('cell content = ', fcell.cell_contents)
# cell content = 23

fcell.cell_contents = 32
### results in
Traceback (most recent call last):
  File "F:\Python\mypy\tem.py", line 14, in 
fcell.cell_contents = 32
AttributeError: attribute 'cell_contents' of 'cell' objects is not writable
# unless one does so from within the closure body with 'nonlocal' 
declaration.  I presume there is a special byte code for this.



--
Terry Jan Reedy

--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Chris Angelico
On Wed, Sep 28, 2016 at 7:19 AM, Terry Reedy  wrote:
> The value of the cell variable is writable from within the body of the
> closure function if declared nonlocal, but not otherwise, and not from
> without.  The latter may be what Peng meant by 'change' and the blogger by
> 'read-only'.
>

Not from entirely without, but it's possible for two functions to
share a cell. I don't know the mechanics of how nonlocal assignment
works, but ultimately, it's updating the cell that both closures see,
so it's going to affect the other function too.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Ian Kelly
On Tue, Sep 27, 2016 at 3:19 PM, Terry Reedy  wrote:
> On 9/27/2016 11:01 AM, Chris Angelico wrote:
>>
>> On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu  wrote:
>>>
>>> Hi, In many other functional language, one can change the closure of a
>>> function. Is it possible in python?
>>>
>>> http://ynniv.com/blog/2007/08/closures-in-python.html
>>>
>>
>> From the blog post:
>>
>> """In some languages, the variable bindings contained in a closure
>> behave just like any other variables. Alas, in python they are
>> read-only."""
>>
>> This is not true, at least as of Python 3.
>>
>> def makeInc(x):
>>   def inc(y, moreinc=0):
>>  # x is "closed" in the definition of inc
>>  nonlocal x
>>  x += moreinc
>>  return y + x
>>   return inc
>
>
> The value of the cell variable is writable from within the body of the
> closure function if declared nonlocal, but not otherwise, and not from
> without.  The latter may be what Peng meant by 'change' and the blogger by
> 'read-only'.
>
> def makeInc(x):
>   def inc(y, moreinc=0):
>  # x is "closed" in the definition of inc
>  nonlocal x
>  x += moreinc
>  return y + x
>   return inc
>
> f = makeInc(23)
> fclose = f.__closure__  # a tuple of 'cells'
> fcell = fclose[0]
>
> print(dir(fcell))
> # ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__',
> # '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
> # '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__',
> # '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
> # '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
> # Note: no mutation method
>
> print('cell content = ', fcell.cell_contents)
> # cell content = 23
>
> fcell.cell_contents = 32
> ### results in
> Traceback (most recent call last):
>   File "F:\Python\mypy\tem.py", line 14, in 
> fcell.cell_contents = 32
> AttributeError: attribute 'cell_contents' of 'cell' objects is not writable
> # unless one does so from within the closure body with 'nonlocal'
> declaration.  I presume there is a special byte code for this.

You could, however, put a mutable object in the cell variable and then
modify it from without. E.g.:

def makeInc(x):
  x = [x]
  def inc(y, moreinc=0):
x[0] += moreinc
return y + x[0]
  return inc

f = makeInc(23)
fcell = f.__closure__[0]
fcell.cell_contents
# [23]
fcell.cell_contents[0] = 42
f(0)
# 42
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Lawrence D’Oliveiro
On Wednesday, September 28, 2016 at 3:35:58 AM UTC+13, Peter Otten wrote:
> is Python actually a "functional language"?

Yes .
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Lawrence D’Oliveiro
On Wednesday, September 28, 2016 at 4:01:36 AM UTC+13, Chris Angelico wrote:
> You can also have multiple closures in the same context, and changes made by
> one of them will affect the others.

This is the point where it’s probably easier to wrap them all together into 
methods of a common class.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Peng Yu
On Tue, Sep 27, 2016 at 10:01 AM, Chris Angelico  wrote:
> On Wed, Sep 28, 2016 at 12:01 AM, Peng Yu  wrote:
>> Hi, In many other functional language, one can change the closure of a
>> function. Is it possible in python?
>>
>> http://ynniv.com/blog/2007/08/closures-in-python.html
>>
>
> From the blog post:
>
> """In some languages, the variable bindings contained in a closure
> behave just like any other variables. Alas, in python they are
> read-only."""
>
> This is not true, at least as of Python 3.

So in Python 2, this is true?

> def makeInc(x):
>   def inc(y, moreinc=0):
>  # x is "closed" in the definition of inc
>  nonlocal x
>  x += moreinc
>  return y + x
>   return inc
>
> The 'nonlocal' keyword is like 'global', applying only to assignments
> (the blog post already mentions the possibility of mutating an object
> rather than reassigning it), and permitting assignment into a broader
> scope than the function's locals. You can also have multiple closures
> in the same context, and changes made by one of them will affect the
> others.
>
> ChrisA
> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Regards,
Peng
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Jussi Piitulainen
Chris Angelico writes:

> On Wed, Sep 28, 2016 at 7:19 AM, Terry Reedy wrote:
>> The value of the cell variable is writable from within the body of the
>> closure function if declared nonlocal, but not otherwise, and not from
>> without.  The latter may be what Peng meant by 'change' and the blogger by
>> 'read-only'.
>>
>
> Not from entirely without, but it's possible for two functions to
> share a cell. I don't know the mechanics of how nonlocal assignment
> works, but ultimately, it's updating the cell that both closures see,
> so it's going to affect the other function too.

Standard example:

def make():
def inquire():
return balance
def deposit(amount):
nonlocal balance
balance += amount
def withdraw(amount):
nonlocal balance
balance -= amount
balance = 0
return inquire, deposit, withdraw

inq1, put1, get1 = make()
inq2, put2, get2 = make()

put1(30) ; get1(10) ; put1(40)
put2(500) ; put2(500) ; put2(500)

assert inq1() == 60
assert inq2() == 1500
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Gregory Ewing

Lawrence D’Oliveiro wrote:

On Wednesday, September 28, 2016 at 3:35:58 AM UTC+13, Peter Otten wrote:


is Python actually a "functional language"?


Yes .


No, not according to what the term "functional language"
usually means.

Languages described as "functional" usually incorporate
all or most of the following characteristics:

* No side effects (new variable bindings may be created, but
  existing ones cannot be changed; no mutable data structures).

* Lazy evaluation by default.

* Syntactic support for currying.

* Syntactic support for case-analysis-style definition of
  functions, by matching the arguments against a series of
  patterns.

* A standard library geared towards a programming style
  that makes heavy use of higher-order functions.

Python has none of these features. It's possible to use a
subset of Python in a functional way, but it goes against the
grain, and without all the above support from the ecosystem
it's clumsier than it would be in a real functional language.

Some parts of Python, such as list comprehensions, have a
functional flavour, but Python is predominantly an imperative
language.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Gregory Ewing

Peng Yu wrote:

On Tue, Sep 27, 2016 at 10:01 AM, Chris Angelico  wrote:


"""In some languages, the variable bindings contained in a closure
behave just like any other variables. Alas, in python they are
read-only."""

This is not true, at least as of Python 3.


So in Python 2, this is true?


Python 2 doesn't have "nonlocal", so a nested function can't
rebind variables in an intermediate scope (between local and
module-level).

Of course, anything is changeable if you resort to sufficient
amounts of hackery. In this case I believe the hacking level
required involves ctypes.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-27 Thread Chris Angelico
On Wed, Sep 28, 2016 at 3:27 PM, Gregory Ewing
 wrote:
> Lawrence D’Oliveiro wrote:
>>
>> On Wednesday, September 28, 2016 at 3:35:58 AM UTC+13, Peter Otten wrote:
>>
>>> is Python actually a "functional language"?
>>
>>
>> Yes
>> .
>
>
> No, not according to what the term "functional language"
> usually means.
>
> Languages described as "functional" usually incorporate
> all or most of the following characteristics:
>
> * No side effects (new variable bindings may be created, but
>   existing ones cannot be changed; no mutable data structures).

If that's adhered to 100%, the language is useless for any operation
that cannot be handled as a "result at end of calculation" function.
You can't produce intermediate output. You can't even produce
debugging output (at least, not from within the program - you'd need
an external debugger). You certainly can't have a long-running program
that handles multiple requests (eg a web server). That kind of rule is
fine for mathematical systems, and it's fine for certain specific
sub-parts of larger programs, but IMO it's utterly impractical for an
entire programming language.

> * Lazy evaluation by default.

Given that you said "usually means", sure, but only because most
functional programming is abysmal (or impossible - calculating the
squares of all positive integers, then subscripting it) unless
optimized like that.

> * Syntactic support for currying.

Is that really such a big deal? What's the true difference between
syntactic support and stdlib support?

> * Syntactic support for case-analysis-style definition of
>   functions, by matching the arguments against a series of
>   patterns.

Again, why such a big deal? Unless you're deliberately defining
"functional language" as "clone of Haskell" or something, there's no
particular reason for this to be a requirement.

> * A standard library geared towards a programming style
>   that makes heavy use of higher-order functions.

This I would agree with.

> Python has none of these features. It's possible to use a
> subset of Python in a functional way, but it goes against the
> grain, and without all the above support from the ecosystem
> it's clumsier than it would be in a real functional language.
>
> Some parts of Python, such as list comprehensions, have a
> functional flavour, but Python is predominantly an imperative
> language.

Python is predominantly a *practical* language. Since purely
functional programming is fundamentally impractical, Python doesn't
force us into it. You want to work functionally? No problem. Pretend
that "def" is a declaration, make all your functions pure, and either
finish with a single "print(main())" or do your actual work at the
REPL. No problem. Want to make event-driven code? Hide an event loop
(maybe a GUI one, maybe asyncio, whatever) in your main routine, and
do everything through that. Want to use Smalltalk-style "message
passing"? Fits nicely into classes and methods. Want a simple batch
scripting style? Ignore functions and classes, and write your code
flush left. Python doesn't force you into any of these models, ergo
Python isn't a functional language, nor an event-driven language, etc,
etc. It's a general-purpose language.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread ast


"jmp"  a écrit dans le message de 
news:mailman.31.1474987306.2302.python-l...@python.org...

On 09/27/2016 04:01 PM, Peng Yu wrote:




Note: function are objects, and can have attributes, however I rarely see usage of these, there 
could be good reasons for that.




It could be use to implement a cache for example.

def fact1(n):

   if not hasattr(fact1, '_cache'):
   fact1._cache = {0:1}

   if n not in fact1._cache:
   fact1._cache[n] = n * fact1(n-1)

   return fact1._cache[n] 


--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread dieter
Peng Yu  writes:
> Hi, In many other functional language, one can change the closure of a
> function. Is it possible in python?

I do not think so: the corresponding attributes/types ("__closure__", "cell")
are explicitely designed to be read only.

However, I never missed closure changebility. Should I really need it
(in an extreme rare case), I would bind the corresponding variable
to an object which could be modified at will.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Peter Otten
Lawrence D’Oliveiro wrote:

> On Wednesday, September 28, 2016 at 3:35:58 AM UTC+13, Peter Otten wrote:
>> is Python actually a "functional language"?
> 
> Yes

[snip]

No. To replace the mostly irrelevant link with something addressing my 
question:





-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Gregory Ewing

Chris Angelico wrote:


 wrote:


* No side effects (new variable bindings may be created, but
 existing ones cannot be changed; no mutable data structures).


If that's adhered to 100%, the language is useless for any operation
that cannot be handled as a "result at end of calculation" function.


Surprisingly, that turns out not to be true. Modern
functional programming has developed some very elegant
techniques for expressing state-changing operations in
a functional way, using things they call monads.

Essentially you write the whole program in continuation-
passing style, with a state object being passed down an
infinite chain of function calls.

None of the functions ever return, so there's no
danger of an "old" state being seen again after the state
has changed. This allows in-place mutations to be
performed as optimisations; it also allows I/O to be
handled in a functional way.


You can't produce intermediate output. You can't even produce
debugging output (at least, not from within the program - you'd need
an external debugger). You certainly can't have a long-running program
that handles multiple requests (eg a web server).


Well, people seem to be writing web servers in functional
languages anyway, judging by the results of googling for
"haskell web server". :-)


* Syntactic support for currying.


Is that really such a big deal?


It is when higher-order functions are such a fundamental
part of the ecosystem that you can hardly take a breath
without needing to curry something.


Unless you're deliberately defining
"functional language" as "clone of Haskell" or something, there's no
particular reason for this to be a requirement.


It's not *my* definition, I'm just pointing out what
the term "functional language" means to the people
who design and use such languages. It means a lot more
than just "a language that has functions". If that's
your definition, then almost any language designed
in the last few decades is a functional language, and
the term is next to meaningless.


Python is predominantly a *practical* language. Since purely
functional programming is fundamentally impractical, Python doesn't
force us into it.


The point is that a true functional language (as
opposed to just "a language that has functions") *does*
force you into it. Lack of side effects is considered
an important part of that paradigm, because it allows
programs to be reasoned about in a mathematical way.
If that's not enforced, the point of the whole thing
is lost.

The fact that Python *doesn't* force you into it means
that Python is not a functional language in that sense.

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Chris Angelico
On Wed, Sep 28, 2016 at 6:52 PM, Gregory Ewing
 wrote:
> Chris Angelico wrote:
>>
>>
>>  wrote:
>>
>>> * No side effects (new variable bindings may be created, but
>>>  existing ones cannot be changed; no mutable data structures).
>>
>>
>> If that's adhered to 100%, the language is useless for any operation
>> that cannot be handled as a "result at end of calculation" function.
>
>
> Surprisingly, that turns out not to be true. Modern
> functional programming has developed some very elegant
> techniques for expressing state-changing operations in
> a functional way, using things they call monads.
>
> Essentially you write the whole program in continuation-
> passing style, with a state object being passed down an
> infinite chain of function calls.
>
> None of the functions ever return, so there's no
> danger of an "old" state being seen again after the state
> has changed. This allows in-place mutations to be
> performed as optimisations; it also allows I/O to be
> handled in a functional way.

If monads allow mutations or side effects, they are by definition not
pure functions, and violate your bullet point. Languages like Haskell
have them not because they are an intrinsic part of functional
programming languages, but because they are an intrinsic part of
practical/useful programming languages.

>> You can't produce intermediate output. You can't even produce
>> debugging output (at least, not from within the program - you'd need
>> an external debugger). You certainly can't have a long-running program
>> that handles multiple requests (eg a web server).
>
>
> Well, people seem to be writing web servers in functional
> languages anyway, judging by the results of googling for
> "haskell web server". :-)

Again, Haskell has such features in order to make it useful, not
because they're part of the definition of "functional programming".

>> Unless you're deliberately defining
>> "functional language" as "clone of Haskell" or something, there's no
>> particular reason for this to be a requirement.
>
>
> It's not *my* definition, I'm just pointing out what
> the term "functional language" means to the people
> who design and use such languages. It means a lot more
> than just "a language that has functions". If that's
> your definition, then almost any language designed
> in the last few decades is a functional language, and
> the term is next to meaningless.

Of course it's more than "a language that has functions"; but I'd say
that a more useful comparison would be "languages that require
functional idioms exclusively" vs "languages that support functional
idioms" vs "languages with no functional programming support". Python
is squarely in the second camp, with features like list
comprehensions, map/reduce, etc, but never forcing you to use them. (C
would be one I'd put into the third camp - I don't think it'd be at
all practical to try to use any sort of functional programming idiom
in C. But I might be wrong.)

>> Python is predominantly a *practical* language. Since purely
>> functional programming is fundamentally impractical, Python doesn't
>> force us into it.
>
>
> The point is that a true functional language (as
> opposed to just "a language that has functions") *does*
> force you into it. Lack of side effects is considered
> an important part of that paradigm, because it allows
> programs to be reasoned about in a mathematical way.
> If that's not enforced, the point of the whole thing
> is lost.
>
> The fact that Python *doesn't* force you into it means
> that Python is not a functional language in that sense.

Right. But my point is that *no* truly useful general-purpose language
actually enforces all of this. A language with absolutely no side
effects etc is a great way to represent algebra (algebra is all about
a search for truth that existed from the beginning - if you discover
half way through that x is 7, then x must have actually been 7 when
the program started, only you didn't know it yet), but it's a terrible
way to do any sort of I/O, and it's rather impractical for really
long-running calculations, being that much harder to debug. The
languages most commonly referred to as "functional languages" are
merely *closer to* a pure no-side-effect language - they encourage
functional styles more strongly than Python does.

I strongly support the use of pure functions in places where that
makes sense. They're much easier to reason about, write unit tests
for, etc, etc, than are functions with side effects. But most
practical programming work is made easier, not harder, by permitting
side effects.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Lawrence D’Oliveiro
On Wednesday, September 28, 2016 at 9:53:05 PM UTC+13, Gregory Ewing wrote:
> Essentially you write the whole program in continuation-
> passing style, with a state object being passed down an
> infinite chain of function calls.

Procedural programming under another name...
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steven D'Aprano
On Wednesday 28 September 2016 15:27, Gregory Ewing wrote:

> * No side effects (new variable bindings may be created, but
>existing ones cannot be changed; no mutable data structures).

As I understand it, for some advanced functional languages like Haskell, that 
is only true as far as the interface of the language (the API) is concerned. 
Implementation-wise, the language may in fact use a mutable data structure, 
provided it is provable that only one piece of code is accessing it at the 
relevant times.

The analogy with Python is the string concatenation optimization. Officially, 
writing:

a + b + c + d + e


in Python has to create and destory the temporary, intermediate strings:

(a+b)

(a+b+c)

(a+b+c+d)

before the final concatenation is performed. But, provided there is only one 
reference to the initial string a, and if certain other conditions related to 
memory management also hold, then this can be optimized as an in-place 
concatenation without having to create new strings, even though strings are 
actually considered immutable and growing them in place is forbidden.


My understanding is that smart functional languages like Haskell do that sort 
of thing a lot, which avoids them being painfully slow.





-- 
Steven
git gets easier once you get the basic idea that branches are homeomorphic 
endofunctors mapping submanifolds of a Hilbert space.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steve D'Aprano
On Wed, 28 Sep 2016 08:03 pm, Lawrence D’Oliveiro wrote:

> On Wednesday, September 28, 2016 at 9:53:05 PM UTC+13, Gregory Ewing
> wrote:
>> Essentially you write the whole program in continuation-
>> passing style, with a state object being passed down an
>> infinite chain of function calls.
> 
> Procedural programming under another name...

Only in the sense that procedural programming is unstructured programming
under another name. What is a procedure call but a disguised GOSUB, and
what is GOSUB but a pair of GOTOs?




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Jussi Piitulainen
Steve D'Aprano writes:

> On Wed, 28 Sep 2016 08:03 pm, Lawrence D’Oliveiro wrote:
>
>> On Wednesday, September 28, 2016 at 9:53:05 PM UTC+13, Gregory Ewing
>> wrote:
>>> Essentially you write the whole program in continuation-
>>> passing style, with a state object being passed down an
>>> infinite chain of function calls.
>> 
>> Procedural programming under another name...
>
> Only in the sense that procedural programming is unstructured programming
> under another name. What is a procedure call but a disguised GOSUB, and
> what is GOSUB but a pair of GOTOs?

Continuation-passing style is only GOTOs. Instead of returning to the
caller, procedures pass control to the continuation, together with the
values that the continuation is expecting from the procedure.

I guess you can think of it as a way to disguise a GOSUB.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread alister
On Wed, 28 Sep 2016 21:48:20 +1000, Steve D'Aprano wrote:

> On Wed, 28 Sep 2016 08:03 pm, Lawrence D’Oliveiro wrote:
> 
>> On Wednesday, September 28, 2016 at 9:53:05 PM UTC+13, Gregory Ewing
>> wrote:
>>> Essentially you write the whole program in continuation-
>>> passing style, with a state object being passed down an infinite chain
>>> of function calls.
>> 
>> Procedural programming under another name...
> 
> Only in the sense that procedural programming is unstructured
> programming under another name. What is a procedure call but a disguised
> GOSUB, and what is GOSUB but a pair of GOTOs?

by this analysis isn't any function call the same?

are not loops just stylised  conditional gotos?




-- 
We only support a 28000 bps connection.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Paul Moore
On Wednesday, 28 September 2016 10:19:01 UTC+1, Chris Angelico  wrote:
> If monads allow mutations or side effects, they are by definition not
> pure functions, and violate your bullet point. Languages like Haskell
> have them not because they are an intrinsic part of functional
> programming languages, but because they are an intrinsic part of
> practical/useful programming languages.

Monads don't "allow" mutations or side effects. However, they allow you to 
express the *process* of making mutations or side effects in an abstract manner.

What "allows side effects" in languages like Haskell is the fact that the 
runtime behaviour of the language is not defined as "calculating the value of 
the main function" but rather as "making the process that the main functon 
defines as an abstract monad actually happen".

That's a completely informal and personal interpretation of what's going on, 
and Haskell users might not agree with it[1]. But for me the key point in 
working out what Haskell was doing was when I realised that their execution 
model wasn't the naive "evaluate the main function" model that I'd understood 
from when I first learned about functional programming.

Paul

[1] One of the problems with modern functional programming is that they 
typically have major problems explaining their interpretation of what's going 
on, with the result that they generally lose their audience long before they 
manage to explain the actually useful things that come from their way of 
thinking.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steve D'Aprano
On Wed, 28 Sep 2016 11:05 pm, Jussi Piitulainen wrote:

> Steve D'Aprano writes:
> 
>> On Wed, 28 Sep 2016 08:03 pm, Lawrence D’Oliveiro wrote:
>>
>>> On Wednesday, September 28, 2016 at 9:53:05 PM UTC+13, Gregory Ewing
>>> wrote:
 Essentially you write the whole program in continuation-
 passing style, with a state object being passed down an
 infinite chain of function calls.
>>> 
>>> Procedural programming under another name...
>>
>> Only in the sense that procedural programming is unstructured programming
>> under another name. What is a procedure call but a disguised GOSUB, and
>> what is GOSUB but a pair of GOTOs?
> 
> Continuation-passing style is only GOTOs. Instead of returning to the
> caller, procedures pass control to the continuation, together with the
> values that the continuation is expecting from the procedure.
> 
> I guess you can think of it as a way to disguise a GOSUB.


Really, if you think about it, both functional and procedural programming
are exactly the same as programming in assembly language. Returning a value
from a function pushes that value onto the function call stack, which is
really just a disguised assembly MOV command.



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Random832
On Wed, Sep 28, 2016, at 11:41, Paul Moore wrote:
> What "allows side effects" in languages like Haskell is the fact that the
> runtime behaviour of the language is not defined as "calculating the
> value of the main function" but rather as "making the process that the
> main functon defines as an abstract monad actually happen".

Well, from another point of view, the output (that is, the set of
changes to files, among other things, that is defined by the
monad-thingy) is *part of* the value of the main function. And the state
of the universe prior to running it is part of the input is part of the
arguments.
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Chris Angelico
On Thu, Sep 29, 2016 at 2:33 AM, Steve D'Aprano
 wrote:
 Procedural programming under another name...
>>>
>>> Only in the sense that procedural programming is unstructured programming
>>> under another name. What is a procedure call but a disguised GOSUB, and
>>> what is GOSUB but a pair of GOTOs?
>>
>> Continuation-passing style is only GOTOs. Instead of returning to the
>> caller, procedures pass control to the continuation, together with the
>> values that the continuation is expecting from the procedure.
>>
>> I guess you can think of it as a way to disguise a GOSUB.
>
>
> Really, if you think about it, both functional and procedural programming
> are exactly the same as programming in assembly language. Returning a value
> from a function pushes that value onto the function call stack, which is
> really just a disguised assembly MOV command.

http://xkcd.com/435/

Also relevant to this conversation:

https://xkcd.com/1270/

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Chris Angelico
On Thu, Sep 29, 2016 at 2:43 AM, Random832  wrote:
> On Wed, Sep 28, 2016, at 11:41, Paul Moore wrote:
>> What "allows side effects" in languages like Haskell is the fact that the
>> runtime behaviour of the language is not defined as "calculating the
>> value of the main function" but rather as "making the process that the
>> main functon defines as an abstract monad actually happen".
>
> Well, from another point of view, the output (that is, the set of
> changes to files, among other things, that is defined by the
> monad-thingy) is *part of* the value of the main function. And the state
> of the universe prior to running it is part of the input is part of the
> arguments.

That's exactly how a function works in an imperative language, and
it's exactly what the FP advocates detest: opaque state. So is the
difference between "function" and "monad" in Haskell the same as "pure
function" and "function" in other contexts?

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steve D'Aprano
On Thu, 29 Sep 2016 03:46 am, Chris Angelico wrote:

> That's exactly how a function works in an imperative language, and
> it's exactly what the FP advocates detest: opaque state. So is the
> difference between "function" and "monad" in Haskell the same as "pure
> function" and "function" in other contexts?

Honestly Chris, what's hard to understand about this? Monads are burritos.

http://blog.plover.com/prog/burritos.html



-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steve D'Aprano
On Wed, 28 Sep 2016 07:18 pm, Chris Angelico wrote:

> On Wed, Sep 28, 2016 at 6:52 PM, Gregory Ewing
>  wrote:
>> Chris Angelico wrote:
>>>
>>>
>>>  wrote:
>>>
 * No side effects (new variable bindings may be created, but
  existing ones cannot be changed; no mutable data structures).
>>>
>>>
>>> If that's adhered to 100%, the language is useless for any operation
>>> that cannot be handled as a "result at end of calculation" function.

They're useless for that too, because you, the caller, cannot see the result
of the calculation. Printing is a side-effect.

Technically you can view the program state through a debugger, but that's
exposing implementation details and besides its not very practical.

But really, this is nit-picking. It is a little like arguing that no
programming languages are actually Turing complete, since no language has
an infinite amount of memory available. Of course a programming language
needs to have *some* way of doing IO, be that print, writing to files, or
flicking the lights on and off in Morse Code, but the challenge is to wall
that off in such a way that it doesn't affect the desirable (to functional
programmers at least) "no side-effects" property.

However, there's no universally agreed upon definition of "side-effect".
Some people might disagree that printing to stdout is a side-effect in the
sense that matters, namely changes to *program* state. Changes to the rest
of the universe are fine.

Some will say that local state (local variables within a function) is okay
so long as that's just an implementation detail. Others insist that even
functions' internal implementation must be pure. After all, a function is
itself a program. If we believe that programs are easier to reason about if
they have no global mutable state (no global variables), then wrapping that
program in "define function"/"end function" tags shouldn't change that.

Others will point out that "no side-effects" is a leaky abstraction, and
like all such abstractions, it leaks. Your functional program will use
memory, the CPU will get warmer, etc.

http://www.johndcook.com/blog/2010/05/18/pure-functions-have-side-effects/

John Cook suggests that functional programming gets harder and harder to do
right (both for the compiler and for the programmer) as you asymptotically
approach 100% pure, and suggests the heuristic that (say) 85% pure is the
sweet spot: functional in the small, object oriented in the large.

http://www.johndcook.com/blog/2009/03/23/functional-in-the-small-oo-in-the-large/


I agree. I find that applying functional techniques to individual methods
makes my classes much better:

- local variables are fine;
- global variables are not;
- global constants are okay;
- mutating the state of the instance should be kept to the absolute minimum;
- and only done from a few mutator methods, not from arbitrary methods;
- attributes should *usually* be passed as arguments to methods, not 
  treated as part of the environment.


That last one is probably the most controversial. Let me explain.


Suppose I have a class with state and at least two methods:


class Robot:
def __init__(self):
self.position = (0, 0)
def move(self, x, y):
self.position[0] += x
self.position[1] += y
def report(self):
# Robot, where are you?
print("I'm at %r" % self.position)


So far so good. But what if we want to make the report() method a bit more
fancy? Maybe we want to spruce it up a bit, and allow subclasses to
customize how they actually report (print, show a dialog box, write to a
log file, whatever you like):

def report(self):
self.format()
self.display_report() 

def display_report(self):
print("I'm at %r" % self.formatted_position)
   
def format(self):
self.formatted_position = (
"x coordinate %f" % self.position[0],
"y coordinate %f" % self.position[1]
)

Now you have this weird dependency where format() communicates with report()
by side-effect, and you cannot test format() or display_report() except by
modifying the position of the Robot.

I see so much OO code written like this, and it is bad, evil, wrong, it
sucks and I don't like it! Just a little bit of functional technique makes
all the difference:

def report(self):
self.display_report(self.format(self.position)) 

def display_report(self, report):
print("I'm at %r" % report)
   
def format(self, position):
return ("x coordinate %f" % position[0],
"y coordinate %f" % position[1]
)

Its easier to understand them (less mystery state in the environment),
easier to test, and easier to convince yourself that the code is correct.



[...]
> If monads allow mutations or side effects, they are by definition not
> pure functions, and violate your bullet point. Languages like Haskell
> have them not because they are an intrinsic part of functio

Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Chris Angelico
On Thu, Sep 29, 2016 at 1:53 PM, Steve D'Aprano
 wrote:
> John Cook suggests that functional programming gets harder and harder to do
> right (both for the compiler and for the programmer) as you asymptotically
> approach 100% pure, and suggests the heuristic that (say) 85% pure is the
> sweet spot: functional in the small, object oriented in the large.
>
> http://www.johndcook.com/blog/2009/03/23/functional-in-the-small-oo-in-the-large/
>
>
> I agree. I find that applying functional techniques to individual methods
> makes my classes much better:
>
> - local variables are fine;
> - global variables are not;
> - global constants are okay;
> - mutating the state of the instance should be kept to the absolute minimum;
> - and only done from a few mutator methods, not from arbitrary methods;
> - attributes should *usually* be passed as arguments to methods, not
>   treated as part of the environment.

I would agree with you. "Functional programming" is not an alternative
to imperative or object-oriented programming; it's a style, it's a set
of rules, that make small functions infinitely easier to reason about,
test, and debug. My points about practicality basically boil down to
the same thing as you were saying - 100% pure is infinitely hard.

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Gregory Ewing

Paul Moore wrote:

What "allows side effects" in languages like Haskell is the fact that the
runtime behaviour of the language is not defined as "calculating the value of
the main function" but rather as "making the process that the main functon
defines as an abstract monad actually happen".


That's an interesting way of looking at it. To put it
another way, what matters isn't just the final result,
but *how* the final result is arrived at.

In the case where the main function never returns,
the "final result" doesn't even exist, and all you
have left is the process.

Philosophical question: Is a function that never
returns actually a function?

--
Greg
--
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-28 Thread Steven D'Aprano
On Thursday 29 September 2016 16:13, Gregory Ewing wrote:

> Philosophical question: Is a function that never
> returns actually a function?

Mathematically, all functions return, instantly. Or rather, mathematics occurs 
in an abstract environment where there is no time. Everything happens 
simultaneously. So even infinite sums or products can be calculated instantly 
-- if they converge.

So, yes, even functions that never return are functions. You just need to 
collapse all of infinite time into a single instant.


-- 
Steven
git gets easier once you get the basic idea that branches are homeomorphic 
endofunctors mapping submanifolds of a Hilbert space.

-- 
https://mail.python.org/mailman/listinfo/python-list


Re: Is there a way to change the closure of a python function?

2016-09-29 Thread Lawrence D’Oliveiro
On Thursday, September 29, 2016 at 7:13:15 PM UTC+13, Gregory Ewing wrote:
> Philosophical question: Is a function that never
> returns actually a function?

Denotational semantics calls that value “bottom”.
-- 
https://mail.python.org/mailman/listinfo/python-list