Topic: standardize pure/const attributes
Author: Xeo <hivemaster@hotmail.de>
Date: Sat, 10 Nov 2012 13:35:19 -0800 (PST)
Raw View
------=_Part_764_30205608.1352583320004
Content-Type: text/plain; charset=ISO-8859-1
On Saturday, November 3, 2012 2:21:13 AM UTC+1, snk_kid wrote:
>
> The benefits would be:
>
> * Guaranteed thread-safe and/or re-entrant code enforced by the compiler.
> * Self-documenting code.
> * Could possibly benefit software transactional memory proposal.
>
Another big benefit is automatic parallelization in, say, std::for_each and
similar range-iterating functions. You currently need to be explicit with
e.g. concurrency::for_each.
--
------=_Part_764_30205608.1352583320004
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
On Saturday, November 3, 2012 2:21:13 AM UTC+1, snk_kid wrote:<blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">The benefits would be:<br><br>* Guaranteed =
thread-safe and/or re-entrant code enforced by the compiler.<br>* Self-docu=
menting code.<br>* Could possibly benefit software transactional memory pro=
posal.<br></blockquote><div><br>Another big benefit is automatic paralleliz=
ation in, say, <span style=3D"color: #000;" class=3D"styled-by-prettify"><c=
ode></code>std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">for_=
each</span><code class=3D"prettyprint"></code> and similar range-iterating =
functions. You currently need to be explicit with e.g. <span style=3D"color=
: #000;" class=3D"styled-by-prettify"><code></code>concurrency</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">for_each</span><code class=3D"p=
rettyprint"></code>.<br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_764_30205608.1352583320004--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sat, 10 Nov 2012 14:01:52 -0800 (PST)
Raw View
------=_Part_1480_17603035.1352584912516
Content-Type: text/plain; charset=ISO-8859-1
On Friday, November 2, 2012 6:21:13 PM UTC-7, snk_kid wrote:
>
> I and I'm sure many others would like to be able to specify, compiler
> enforce and simultaneously document referentially transparent (side-effect
> free) expressions without resorting to "trusted" comments and making a lot
> of assumptions about code.
>
> This could either be a new standardized C++11 attribute (gcc has a
> pure/const pre C++11 attribute), a keyword like override or possibly a
> C++AMP "restrict" style language subset overload.
>
> The benefits would be:
>
> * Guaranteed thread-safe and/or re-entrant code enforced by the compiler.
> * Self-documenting code.
> * Could possibly benefit software transactional memory proposal.
>
> If this was extended on to the class level to specify all member functions
> as "pure" and a constant instance of the class is defined this would be a
> true immutable object with no hidden side-effects. Constant member
> functions do not cut it, they only specify to not modify the state of
> "this" which can be side-stepped by the mutable keyword and do not disallow
> hidden side-effects of global/static variables or executing I/O operations.
>
> I don't think using generalized constant expressions should be the way to
> achieve this as a programmer may not want or can not have the code be
> executed at compile-time.
>
I'm not sure how designating a function to be pure makes it necessarily
thread-safe, since two pure functions can still data-race by talking to the
same object (directly or indirectly). Without some guarantee that the pure
functions can't talk to the same memory at the same time, I'm not sure what
that buys you.
I am sure of one thing: if we want pure functions, and we want syntax and
behavior to work with pure functions (ie: preventing pure functions from
calling non-pure functions, like `const`), they should *not be attributes*.
It should be a language keyword or whatever. Attributes shouldn't be used
as a convenient way to back-door new keywords into the language.
A simple contextual keyword in the cv-qualifier section for a function
declaration/definition would be sufficient.
--
------=_Part_1480_17603035.1352584912516
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<br><br>On Friday, November 2, 2012 6:21:13 PM UTC-7, snk_kid wrote:<blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;">I and I'm sure many others would like=
to be able to specify, compiler enforce and simultaneously document refer=
entially transparent (side-effect free) expressions without resorting to "t=
rusted" comments and making a lot of assumptions about code.<br><br>This co=
uld either be a new standardized C++11 attribute (gcc has a pure/const pre =
C++11 attribute), a keyword like override or possibly a C++AMP "restrict" s=
tyle language subset overload.<br><br>The benefits would be:<br><br>* Guara=
nteed thread-safe and/or re-entrant code enforced by the compiler.<br>* Sel=
f-documenting code.<br>* Could possibly benefit software transactional memo=
ry proposal.<br><br>If this was extended on to the class level to specify a=
ll member functions as "pure" and a constant instance of the class is defin=
ed this would be a true immutable object with no hidden side-effects. Const=
ant member functions do not cut it, they only specify to not modify the sta=
te of "this" which can be side-stepped by the mutable keyword and do not di=
sallow hidden side-effects of global/static variables or executing I/O oper=
ations.<br><br>I don't think using generalized constant expressions should =
be the way to achieve this as a programmer may not want or can not have the=
code be executed at compile-time.<br></blockquote><div><br>I'm not sure ho=
w designating a function to be pure makes it necessarily thread-safe, since=
two pure functions can still data-race by talking to the same object (dire=
ctly or indirectly). Without some guarantee that the pure functions can't t=
alk to the same memory at the same time, I'm not sure what that buys you.<b=
r><br>I am sure of one thing: if we want pure functions, and we want syntax=
and behavior to work with pure functions (ie: preventing pure functions fr=
om calling non-pure functions, like `const`), they should <i>not be attribu=
tes</i>. It should be a language keyword or whatever. Attributes shouldn't =
be used as a convenient way to back-door new keywords into the language.<br=
><br>A simple contextual keyword in the cv-qualifier section for a function=
declaration/definition would be sufficient.<br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1480_17603035.1352584912516--
.
Author: korcan.hussein@googlemail.com
Date: Sun, 11 Nov 2012 04:50:40 -0800 (PST)
Raw View
------=_Part_895_11850337.1352638240505
Content-Type: text/plain; charset=ISO-8859-1
>
> I'm not sure how designating a function to be pure makes it necessarily
> thread-safe, since two pure functions can still data-race by talking to the
> same object (directly or indirectly). Without some guarantee that the pure
> functions can't talk to the same memory at the same time, I'm not sure what
> that buys you.
This is not true, two referentially transparent functions can not by
themselves cause race conditions, they do not and can-not modify shared
state, be it implicit global/static state or mutable reference parameters.
Concurrent calls to these functions would all be concurrent reads, if you
add a concurrent writer and using shared state between these concurrent
reads/writes then you could be in the situation of race conditions if you
don't properly serialize reads/writes. A concurrent writer to shared state
can never be a referentially transparent expression/function.
Pure functions will always be thread-safe, if the context in which you use
them is not thread-safe then that context can not be referentially
transparent and can never be guaranteed to be thread safe not the pure
function in themselves.
If you have function which has been declared as pure and take parameters by
non-const reference or pointer to non-constant type and you try to mutate
value of what is being referenced by those parameter then the compiler
should generate a compile error as this is not a pure (referentially
transparent) function and can never be. Non-const reference or pointer to
non-constant type parameters seem to be pointless in the context of a pure
function so may be they should just be disallowed when a function is
declared is pure.
The usefulness of declaring pure functions in context of
concurrency/parallelism is the fact that you have a compiler enforced and
self-documented function for which you can be sure at a single glance that
using this function is 100% guaranteed thread-safe and re-entrant.
The only extra thing that needs to be thought about is the case of local
mutation as pure variable mutation in a self contained scope (e.g. auto
variables in scope of a function, functions parameters passed-by value) can
be still be considered referentially transparent as there is a trivial
translation from local mutation to purely functional code. Haskell has such
support, which is the ST Monad (not to be confused with the state Monad),
this allows functions to be still referentially transparent from the
outside but allow it's implementation to use local mutable variables and
local mutation for reasons such as efficiency.
I believe D does something similar by having two types of "pure" functions,
one being a stronger form of pure than the other and C++ could do the same.
*Rant-Mode*
C++ Programmers write so many functions which are actually purely
functional without even realizing it and good C++ programmers use the
keyword "const" so much (and most often correctly) I wish we could do
something more extreme and get rid of the redundancy. I would change all
the defaults to be variables are constant and functions are pure by default
and make mutable variables and side-effecting code explicit and localized
but I know no-one would support me in this extreme change to the standard
even though it could be done is such as way to not break existing code.
--
------=_Part_895_11850337.1352638240505
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(=
204, 204, 204); padding-left: 1ex;" class=3D"gmail_quote">I'm not sure how =
designating a function to be pure makes it necessarily=20
thread-safe, since two pure functions can still data-race by talking to=20
the same object (directly or indirectly). Without some guarantee that=20
the pure functions can't talk to the same memory at the same time, I'm=20
not sure what that buys you.</blockquote><div><br>This is not true, two ref=
erentially transparent functions can not by themselves cause race condition=
s, they do not and can-not modify shared state, be it implicit global/stati=
c state or mutable reference parameters. Concurrent calls to these function=
s would all be concurrent reads, if you add a concurrent writer and using s=
hared state between these concurrent reads/writes then you could be in the =
situation of race conditions if you don't properly serialize reads/writes. =
A concurrent writer to shared state can never be a referentially transparen=
t expression/function.<br><br>Pure functions will always be thread-safe, if=
the context in which you use them is not thread-safe then that context can=
not be referentially transparent and can never be guaranteed to be thread =
safe not the pure function in themselves.<br><br>If you have function which=
has been declared as pure and take parameters by non-const reference or po=
inter to non-constant type and you try to mutate value of what is being ref=
erenced by those parameter then the compiler should generate a compile erro=
r as this is not a pure (referentially transparent) function and can never =
be. Non-const reference or pointer to non-constant type parameters seem to =
be pointless in the context of a pure function so may be they should just b=
e disallowed when a function is declared is pure.<br><br>The usefulness of =
declaring pure functions in context of concurrency/parallelism is the fact =
that you have a compiler enforced and self-documented function for which yo=
u can be sure at a single glance that using this function is 100% guarantee=
d thread-safe and re-entrant.<br><br>The only extra thing that needs to be =
thought about is the case of local mutation as pure variable mutation in a =
self contained scope (e.g. auto variables in scope of a function, functions=
parameters passed-by value) can be still be considered referentially trans=
parent as there is a trivial translation from local mutation to purely func=
tional code. Haskell has such support, which is the ST Monad (not to be con=
fused with the state Monad), this allows functions to be still referentiall=
y transparent from the outside but allow it's implementation to use local m=
utable variables and local mutation for reasons such as efficiency.<br><br>=
I believe D does something similar by having two types of "pure" functions,=
one being a stronger form of pure than the other and C++ could do the same=
..<br><br>*Rant-Mode*<br><br>C++ Programmers write so many functions which a=
re actually purely functional without even realizing it and good C++ progra=
mmers use the keyword "const" so much (and most often correctly) I wish we =
could do something more extreme and get rid of the redundancy. I would chan=
ge all the defaults to be variables are constant and functions are pure by =
default and make mutable variables and side-effecting code explicit and loc=
alized but I know no-one would support me in this extreme change to the sta=
ndard even though it could be done is such as way to not break existing cod=
e.<br><br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_895_11850337.1352638240505--
.
Author: korcan.hussein@googlemail.com
Date: Sun, 11 Nov 2012 04:56:42 -0800 (PST)
Raw View
------=_Part_170_17249529.1352638602809
Content-Type: text/plain; charset=ISO-8859-1
>
> I'm not sure how designating a function to be pure makes it necessarily
> thread-safe, since two pure functions can still data-race by talking to the
> same object (directly or indirectly). Without some guarantee that the pure
> functions can't talk to the same memory at the same time, I'm not sure what
> that buys you.
This is not true, two referentially transparent functions can not by
themselves cause race conditions, they do not and can-not modify shared
state, be it implicit global/static state or mutable reference parameters.
Concurrent calls to these functions would all be concurrent reads, if you
add a concurrent writer and using shared state between these concurrent
reads/writes then you could be in the situation of race conditions if you
don't properly serialize reads/writes. A concurrent writer to shared state
can never be a referentially transparent expression/function.
Pure functions will always be thread-safe, if the context in which you use
them is not thread-safe then that context can not be referentially
transparent and can never be guaranteed to be thread safe not the pure
function in themselves.
If you have function which has been declared as pure and take parameters by
non-const reference or pointer to non-constant type and you try to mutate
value of what is being referenced by those parameter then the compiler
should generate a compile error as this is not a pure (referentially
transparent) function and can never be. Non-const reference or pointer to
non-constant type parameters seem to be pointless in the context of a pure
function so may be they should just be disallowed when a function is
declared is pure.
The usefulness of declaring pure functions in context of
concurrency/parallelism is the fact that you have a compiler enforced and
self-documented function for which you can be sure at a single glance that
using this function is 100% guaranteed thread-safe and re-entrant.
The only extra thing that needs to be thought about is the case of local
mutation as pure variable mutation in a self contained scope (e.g. auto
variables in scope of a function, functions parameters passed-by value) can
be still be considered referentially transparent as there is a trivial
translation from local mutation to purely functional code. Haskell has such
support, which are the ST and State Monads, these can allow functions to be
still referentially transparent from the outside but allow it's
implementation to simulate variables (or in the case of ST Monad use real
mutable cells) and local mutation.
I believe D does something similar by having two types of "pure" functions,
one being a stronger form of pure than the other and C++ could do the same.
*Rant-Mode*
C++ Programmers write so many functions which are actually purely
functional without even realizing it and good C++ programmers use the
keyword "const" so much (and most often correctly) I wish we could do
something more extreme and get rid of the redundancy. I would change all
the defaults to be variables are constant and functions are pure by default
and make mutable variables and side-effecting code explicit and localized
but I know no-one would support me in this extreme change to the standard
even though it could be done is such as way to not break existing code.
--
------=_Part_170_17249529.1352638602809
Content-Type: text/html; charset=ISO-8859-1
<blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">I'm not sure how designating a function to be pure makes it necessarily
thread-safe, since two pure functions can still data-race by talking to
the same object (directly or indirectly). Without some guarantee that
the pure functions can't talk to the same memory at the same time, I'm
not sure what that buys you.</blockquote><br>This is not true, two
referentially transparent functions can not by themselves cause race
conditions, they do not and can-not modify shared state, be it implicit
global/static state or mutable reference parameters. Concurrent calls to
these functions would all be concurrent reads, if you add a concurrent
writer and using shared state between these concurrent reads/writes then
you could be in the situation of race conditions if you don't properly
serialize reads/writes. A concurrent writer to shared state can never be
a referentially transparent expression/function.<br><br>Pure functions
will always be thread-safe, if the context in which you use them is not
thread-safe then that context can not be referentially transparent and
can never be guaranteed to be thread safe not the pure function in
themselves.<br><br>If you have function which has been declared as pure
and take parameters by non-const reference or pointer to non-constant
type and you try to mutate value of what is being referenced by those
parameter then the compiler should generate a compile error as this is
not a pure (referentially transparent) function and can never be.
Non-const reference or pointer to non-constant type parameters seem to
be pointless in the context of a pure function so may be they should
just be disallowed when a function is declared is pure.<br><br>The
usefulness of declaring pure functions in context of
concurrency/parallelism is the fact that you have a compiler enforced
and self-documented function for which you can be sure at a single
glance that using this function is 100% guaranteed thread-safe and
re-entrant.<br><br>The only extra thing that needs to be thought about
is the case of local mutation as pure variable mutation in a self
contained scope (e.g. auto variables in scope of a function, functions
parameters passed-by value) can be still be considered referentially
transparent as there is a trivial translation from local mutation to
purely functional code. Haskell has such support, which are the ST and State Monads, these can allow functions to be
still referentially transparent from the outside but allow it's
implementation to simulate variables (or in the case of ST Monad use real mutable cells) and local mutation.<br><br>I believe D does something similar by
having two types of "pure" functions, one being a stronger form of pure
than the other and C++ could do the same.<br><br>*Rant-Mode*<br><br>C++
Programmers write so many functions which are actually purely
functional without even realizing it and good C++ programmers use the
keyword "const" so much (and most often correctly) I wish we could do
something more extreme and get rid of the redundancy. I would change all
the defaults to be variables are constant and functions are pure by
default and make mutable variables and side-effecting code explicit and
localized but I know no-one would support me in this extreme change to
the standard even though it could be done is such as way to not break
existing code.<br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_170_17249529.1352638602809--
.
Author: korcan.hussein@googlemail.com
Date: Sun, 11 Nov 2012 05:29:22 -0800 (PST)
Raw View
------=_Part_411_21313567.1352640562371
Content-Type: text/plain; charset=ISO-8859-1
>
> I'm not sure how designating a function to be pure makes it necessarily
> thread-safe, since two pure functions can still data-race by talking to the
> same object (directly or indirectly). Without some guarantee that the pure
> functions can't talk to the same memory at the same time, I'm not sure what
> that buys you.
This is not true, two referentially transparent functions can not by
themselves cause race conditions, they do not and can-not modify shared
state, be it implicit global/static state or mutable reference parameters.
Concurrent calls to these functions would all be concurrent reads, if you
add a concurrent writer and using shared state between these concurrent
reads/writes then you could be in the situation of race conditions if you
don't properly serialize reads/writes. A concurrent writer to shared state
can never be a referentially transparent expression/function.
Pure functions will always be thread-safe, if the context in which you use
them is not thread-safe then that context can not be referentially
transparent and can never be guaranteed to be thread safe not the pure
function in themselves.
If you have function which has been declared as pure and take parameters by
non-const reference or pointer to non-constant type and you try to mutate
value of what is being referenced by those parameter then the compiler
should generate a compile error as this is not a pure (referentially
transparent) function and can never be. Non-const reference or pointer to
non-constant type parameters seem to be pointless in the context of a pure
function so may be they should just be disallowed when a function is
declared is pure.
The usefulness of declaring pure functions in context of
concurrency/parallelism is the fact that you have a compiler enforced and
self-documented function for which you can be sure at a single glance that
using this function is 100% guaranteed thread-safe and re-entrant.
The only extra thing that needs to be thought about is the case of local
mutation as pure variable mutation in a self contained scope (e.g. auto
variables in scope of a function, functions parameters passed-by value) can
be still be considered referentially transparent as there is a trivial
translation from local mutation to purely functional code. Haskell has such
support, which are the ST and State Monads, these can allow functions to be
still referentially transparent from the outside but allow it's
implementation to simulate variables (or in the case of ST Monad use real
mutable cells) and local mutation.
I believe D does something similar by having two types of "pure" functions,
one being a stronger form of pure than the other and C++ could do the same.
--
------=_Part_411_21313567.1352640562371
Content-Type: text/html; charset=ISO-8859-1
<div class="GB4UH3SBPX"><blockquote style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex" class="gmail_quote">I'm not sure how designating a function to be pure makes it necessarily
thread-safe, since two pure functions can still data-race by talking to
the same object (directly or indirectly). Without some guarantee that
the pure functions can't talk to the same memory at the same time, I'm
not sure what that buys you.</blockquote><br></div>This is not true, two
referentially transparent functions can not by themselves cause race
conditions, they do not and can-not modify shared state, be it implicit
global/static state or mutable reference parameters. Concurrent calls to
these functions would all be concurrent reads, if you add a concurrent
writer and using shared state between these concurrent reads/writes then
you could be in the situation of race conditions if you don't properly
serialize reads/writes. A concurrent writer to shared state can never be
a referentially transparent expression/function.<br><br>Pure functions
will always be thread-safe, if the context in which you use them is not
thread-safe then that context can not be referentially transparent and
can never be guaranteed to be thread safe not the pure function in
themselves.<br><br>If you have function which has been declared as pure
and take parameters by non-const reference or pointer to non-constant
type and you try to mutate value of what is being referenced by those
parameter then the compiler should generate a compile error as this is
not a pure (referentially transparent) function and can never be.
Non-const reference or pointer to non-constant type parameters seem to
be pointless in the context of a pure function so may be they should
just be disallowed when a function is declared is pure.<br><br>The
usefulness of declaring pure functions in context of
concurrency/parallelism is the fact that you have a compiler enforced
and self-documented function for which you can be sure at a single
glance that using this function is 100% guaranteed thread-safe and
re-entrant.<br><br>The only extra thing that needs to be thought about
is the case of local mutation as pure variable mutation in a self
contained scope (e.g. auto variables in scope of a function, functions
parameters passed-by value) can be still be considered referentially
transparent as there is a trivial translation from local mutation to
purely functional code. Haskell has such support, which are the ST and State Monads, these can allow functions to be
still referentially transparent from the outside but allow it's
implementation to simulate variables (or in the case of ST Monad use real mutable cells) and local mutation.<br><br>I believe D does something similar by
having two types of "pure" functions, one being a stronger form of pure
than the other and C++ could do the same.<br><br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_411_21313567.1352640562371--
.
Author: grigorij1981@gmail.com
Date: Sun, 11 Nov 2012 13:55:37 -0800 (PST)
Raw View
------=_Part_1479_2954572.1352670937063
Content-Type: text/plain; charset=ISO-8859-1
I'm thinking about interaction with templates. Many of STL algorithms (e.g.
find, accumulate, max_element) would qualify as pure in the weak sense, if
we were sure that passed iterators and function objects do not change state
of container or global state.
So, we need not just attribute or overrider but facility like noexcept, so
we can enable purity of the function conditionally.
And the last thing - how do we treat function/methods that do not change
global state? Most of iterators do not. They are however not pure, in any
sense. Incrementing iterator changes its state. Still, in my opinion it
should be possible to increment locally declared iterator variable inside
a pure function.
Regards,
Gregory
--
------=_Part_1479_2954572.1352670937063
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>I'm thinking about interaction with templates. Many of STL algorithms =
(e.g. find, accumulate, max_element) would qualify as pure in th=
e weak sense, if we were sure that passed iterators and function objects&nb=
sp;do not change state of container or global state.</div><div> </div>=
<div>So, we need not just attribute or overrider but facility like noexcept=
, so we can enable purity of the function conditionally.</div><div> </=
div><div>And the last thing - how do we treat function/methods that do not =
change global state? Most of iterators do not. They are however not pure, i=
n any sense. Incrementing iterator changes its state. Still, in my&nbs=
p;opinion it should be possible to increment locally declared&nbs=
p;iterator variable inside a pure function.</div><div> </div=
><div>Regards,</div><div>Gregory</div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1479_2954572.1352670937063--
.
Author: korcan.hussein@googlemail.com
Date: Wed, 14 Nov 2012 16:13:12 -0800 (PST)
Raw View
------=_Part_1210_32536091.1352938392314
Content-Type: text/plain; charset=ISO-8859-1
>
> I'm thinking about interaction with templates. Many of STL algorithms
> (e.g. find, accumulate, max_element) would qualify as pure in the weak
> sense, if we were sure that passed iterators and function objects do not
> change state of container or global state.
>
> So, we need not just attribute or overrider but facility like noexcept, so
> we can enable purity of the function conditionally.
>
I think the standard library generic algorithms are an interesting case,
non-mutating algorithms could be considered the weaker form of pure but
still referentially transparent just the support for local mutation of
iterators (which are typically passed by value). The tricky part to
consider is the function/functional object parameters. Should these
algorithms enforce these parameters to by referentially transparent?
sometimes you do want to use impure functions/functional objects passed in.
In the case of Haskell there are typically 2 or more versions of these
types of higher-order functions, for example there are the *map/fold *functions
which are purely functional and the function parameter must be purely
function as well but Haskell also has *mapM/foldM* functions which are
variants of map/fold that takes a monadic action as parameter. In the
latter functions, this forces these functions to be monadic function
themselves and thus are not referentially transparent functions.
You could add some kind of support for specifying that function/functional
object parameters must be pure and for lambda functions you could do
something similar to how C++AMP works with lambdas:
auto itr = find(v.begin(), v.end(), [...](const T& x) restrict(pure) ->
bool { ... });
And the last thing - how do we treat function/methods that do not change
> global state? Most of iterators do not. They are however not pure, in any
> sense. Incrementing iterator changes its state. Still, in my opinion it
> should be possible to increment locally declared iterator variable inside
> a pure function.
>
This would be no different than having a (weakly) pure function taking a
mutable integer by value, as I mentioned earlier this case can still be
considered referentially transparent in some sense (or to some extent) as
local mutation can be converted to purely functional form such as using
multiple let-bindings and/or recursion (with accumulators) if an imperative
loop is used (I'm not suggesting the compiler generate such code but the
point being they can be equivalent).
As I mentioned earlier in Haskell this could be roughly equivalent to using
an ST or State Monad inside a function which has a pure interface on the
outside because for these type of Monads they are escapable in any
expressions once the computation has finished (as opposed to the IO Monad
which can only escape when the program is has finished, the end of the
scope of the main entry point which is in the IO Monad in Haskell). This is
fine and not a back-door in the type-system, these Monads do not allow any
other kind of side-effects to happen just pure variable/state local
mutation.
(Note that you do not have to use ST/State Monad in this way, you can
create functions that are still "inside" the ST/State Monad and those would
be called actions in those Monads.)
However as I mentioned earlier things are a bit different when you talk
about higher-order functions/actions which take non-referentially
transparent functions (side-effecting actions) as parameters.
--
------=_Part_1210_32536091.1352938392314
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>I'm
thinking about interaction with templates. Many of STL algorithms (e.g.
find, accumulate, max_element) would qualify as pure in the wea=
k=20
sense, if we were sure that passed iterators and function objects do n=
ot
change state of container or global state.</div><div> </div><div>So, =
we need not just attribute or overrider but facility like noexcept, so we c=
an enable purity of the function conditionally. <br></div></blockquote><div=
><br>I
think the standard library generic algorithms are an interesting case,=20
non-mutating algorithms could be considered the weaker form of pure but=20
still referentially transparent just the support for local mutation of=20
iterators (which are typically passed by value). The tricky part to=20
consider is the function/functional object parameters. Should these=20
algorithms enforce these parameters to by referentially transparent?=20
sometimes you do want to use impure functions/functional objects passed in.=
<br><br>In the case of Haskell there are typically 2 or more versions of th=
ese types of higher-order functions, for example there are the <b>map/fold =
</b>functions which are purely functional and the function parameter must b=
e purely function as well but Haskell also has <b>mapM/foldM</b> functions =
which are variants of map/fold that takes a monadic action as parameter. In=
the latter functions, this forces these functions to be monadic function t=
hemselves and thus are not referentially transparent functions.<br><br>You
could add some kind of support for specifying that function/functional=20
object parameters must be pure and for lambda functions you could do=20
something similar to how C++AMP works with lambdas:<br><br>auto itr =3D fin=
d(v.begin(), v.end(), [...](const T& x) restrict(pure) -> bool { ...=
});<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div>And
the last thing - how do we treat function/methods that do not change=20
global state? Most of iterators do not. They are however not pure, in=20
any sense. Incrementing iterator changes its state. Still, in=20
my opinion it should be possible to increment locally declar=
ed iterator=20
variable inside a pure function.</div></blockquote><div><br>This =
would be no different than having a (weakly) pure function taking a mutable=
integer by value, as I mentioned earlier this case can still be considered=
referentially transparent in some sense (or to some extent) as local mutat=
ion can be converted to purely functional form such as using multiple let-b=
indings and/or recursion (with accumulators) if an imperative loop is used =
(I'm not suggesting the compiler generate such code but the point being the=
y can be equivalent).<br><br>As I mentioned earlier in Haskell this could b=
e roughly equivalent to using an ST or State Monad inside a function which =
has a pure interface on the outside because for these type of Monads they a=
re escapable in any expressions once the computation has finished (as oppos=
ed to the IO Monad which can only escape when the program is has finished, =
the end of the scope of the main entry point which is in the IO Monad in Ha=
skell). This is fine and not a back-door in the type-system, these Monads d=
o not allow any other kind of side-effects to happen just pure variable/sta=
te local mutation.<br><br>(Note that you do not have to use ST/State Monad =
in this way, you can create functions that are still "inside" the ST/State =
Monad and those would be called actions in those Monads.)<br><br>However as=
I mentioned earlier things are a bit different when you talk about higher-=
order functions/actions which take non-referentially transparent functions =
(side-effecting actions) as parameters.<br><br></div></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1210_32536091.1352938392314--
.
Author: korcan.hussein@googlemail.com
Date: Wed, 14 Nov 2012 16:20:13 -0800 (PST)
Raw View
------=_Part_1275_6125843.1352938813379
Content-Type: text/plain; charset=ISO-8859-1
>
> I'm thinking about interaction with templates. Many of STL algorithms
> (e.g. find, accumulate, max_element) would qualify as pure in the weak
> sense, if we were sure that passed iterators and function objects do not
> change state of container or global state.
>
> So, we need not just attribute or overrider but facility like noexcept, so
> we can enable purity of the function conditionally.
>
I think the standard library generic algorithms are an interesting case,
non-mutating algorithms could be considered the weaker form of pure but
still referentially transparent just the support for local mutation of
iterators (which are typically passed by value). The tricky part to
consider is the function/functional object parameters. Should these
algorithms enforce these parameters to be referentially transparent?
sometimes you do want to use impure functions/functional objects passed in
but most often you don't.
In the case of Haskell there are typically 2 or more versions of these
types of higher-order functions, for example there are the *map/fold *functions
which are purely functional and the function parameter must be purely
functional as well but Haskell also has *mapM/foldM* functions which are
variants of map/fold that take a monadic action as a parameter instead of a
pure function. In the latter case, this forces these functions to be
monadic functions themselves and thus are not referentially transparent
(pure) functions.
You could add some kind of support for specifying that function/functional
object parameters must be pure and for lambda functions you could do
something similar to how C++AMP works with lambdas:
auto itr = find(v.begin(), v.end(), [...](const T& x) restrict(pure) ->
bool { ... });
And the last thing - how do we treat function/methods that do not change
> global state? Most of iterators do not. They are however not pure, in any
> sense. Incrementing iterator changes its state. Still, in my opinion it
> should be possible to increment locally declared iterator variable inside
> a pure function.
>
This would be no much different than having a (weakly) pure function taking
a mutable integers by value, as I mentioned earlier this case can still be
considered referentially transparent in some sense (or to some extent) as
local mutation can be converted to purely functional form such as using
multiple let-bindings and/or recursion (with accumulators) if an imperative
loop is used (I'm not suggesting the compiler generate such code but the
point being they can be equivalent).
As I mentioned earlier in Haskell this could be roughly equivalent to using
an ST or State Monad inside a function which has a pure interface on the
outside because for these type of Monads they are escapable in any
expressions once the computation has finished (as opposed to the IO Monad
which can only escape when the program has finished, the end of the scope
of the main entry point which is in the IO Monad in Haskell). This is fine
and not a back-door in the type-system, these Monads do not allow any other
kind of side-effects to happen just pure variable/state local mutation.
(Note that you do not have to use ST/State Monad in this way, you can
create functions that are still "inside" the ST/State Monad and those would
be called actions in those Monads.)
However as I mentioned earlier things are a bit different when you talk
about higher-order functions/actions which take non-referentially
transparent functions (side-effecting actions) as parameters.
--
------=_Part_1275_6125843.1352938813379
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div>I'm
thinking about interaction with templates. Many of STL algorithms (e.g.
find, accumulate, max_element) would qualify as pure in the wea=
k=20
sense, if we were sure that passed iterators and function objects do n=
ot
change state of container or global state.</div><div> </div><div>So, =
we need not just attribute or overrider but facility like noexcept, so we c=
an enable purity of the function conditionally. <br></div></blockquote><div=
><br>I
think the standard library generic algorithms are an interesting case,=20
non-mutating algorithms could be considered the weaker form of pure but=20
still referentially transparent just the support for local mutation of=20
iterators (which are typically passed by value). The tricky part to=20
consider is the function/functional object parameters. Should these=20
algorithms enforce these parameters to be referentially transparent?=20
sometimes you do want to use impure functions/functional objects passed in =
but most often you don't.<br><br>In
the case of Haskell there are typically 2 or more versions of these=20
types of higher-order functions, for example there are the <b>map/fold </b>=
functions which are purely functional and the function parameter must be pu=
rely functional as well but Haskell also has <b>mapM/foldM</b>
functions which are variants of map/fold that take a monadic action as
a parameter instead of a pure function. In the latter case, this forces th=
ese functions to be=20
monadic functions themselves and thus are not referentially transparent (pu=
re) functions.<br><br>You
could add some kind of support for specifying that function/functional=20
object parameters must be pure and for lambda functions you could do=20
something similar to how C++AMP works with lambdas:<br><br>auto itr =3D fin=
d(v.begin(), v.end(), [...](const T& x) restrict(pure) -> bool { ...=
});<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>A=
nd
the last thing - how do we treat function/methods that do not change=20
global state? Most of iterators do not. They are however not pure, in=20
any sense. Incrementing iterator changes its state. Still, in=20
my opinion it should be possible to increment locally declar=
ed iterator=20
variable inside a pure function.</div></blockquote><br>This would=
=20
be no much different than having a (weakly) pure function taking a mutable=
=20
integers by value, as I mentioned earlier this case can still be=20
considered referentially transparent in some sense (or to some extent)=20
as local mutation can be converted to purely functional form such as=20
using multiple let-bindings and/or recursion (with accumulators) if an=20
imperative loop is used (I'm not suggesting the compiler generate such=20
code but the point being they can be equivalent).<br><br>As I mentioned=20
earlier in Haskell this could be roughly equivalent to using an ST or=20
State Monad inside a function which has a pure interface on the outside=20
because for these type of Monads they are escapable in any expressions=20
once the computation has finished (as opposed to the IO Monad which can=20
only escape when the program has finished, the end of the scope of=20
the main entry point which is in the IO Monad in Haskell). This is fine=20
and not a back-door in the type-system, these Monads do not allow any=20
other kind of side-effects to happen just pure variable/state local=20
mutation.<br><br>(Note that you do not have to use ST/State Monad in=20
this way, you can create functions that are still "inside" the ST/State=20
Monad and those would be called actions in those Monads.)<br><br>However
as I mentioned earlier things are a bit different when you talk about=20
higher-order functions/actions which take non-referentially transparent=20
functions (side-effecting actions) as parameters.<br><br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1275_6125843.1352938813379--
.
Author: grigorij1981@gmail.com
Date: Wed, 14 Nov 2012 18:08:46 -0800 (PST)
Raw View
------=_Part_353_19303902.1352945326805
Content-Type: text/plain; charset=KOI8-U
Content-Transfer-Encoding: quoted-printable
The situation in functional language with explicit effects is a bit=20
different than in C++. If we are to add purity annotations to C++ we need=
=20
some way to prove for a function that its effects are local to its body or=
=20
to the object it operates on or that it is pure in strict sense. In Haskell=
=20
that would be reflected in a type of a function. I fear that in C++ we=20
would need (pseudo-)keywords for each of these notions (or at least for=20
some of them). The situation is worsened by the fact that there are=20
pointers in C++. And such innocent code=20
=20
Node** n =3D ...;
Node* m =3D ...;
*n =3D m;
=20
might actually change global state. So I doubt that compiler would be able=
=20
to prove that code that manipulates (changes) std::list is pure in some=20
form without adding ownership annotations to type system.=20
=FE=C5=D4=D7=C5=D2, 15 =CC=C9=D3=D4=CF=D0=C1=C4=C1 2012 =D2. 02:20:13 UTC+2=
=CB=CF=D2=C9=D3=D4=D5=D7=C1=DE=20
korcan....@googlemail.com =CE=C1=D0=C9=D3=C1=D7:
> In the case of Haskell there are typically 2 or more versions of these=20
>> types of higher-order functions, for example there are the *map/fold *fu=
nctions=20
>> which are purely functional and the function parameter must be purely=20
>> functional as well but Haskell also has *mapM/foldM* functions which are=
=20
>> variants of map/fold that take a monadic action as a parameter instead o=
f a=20
>> pure function. In the latter case, this forces these functions to be=20
>> monadic functions themselves and thus are not referentially transparent=
=20
>> (pure) functions.
>>
>> =20
I thought that map and fold can be expressed in terms of mapM/foldM and=20
vice versa, so multiple functions are just for convenience. =20
=20
--=20
------=_Part_353_19303902.1352945326805
Content-Type: text/html; charset=KOI8-U
Content-Transfer-Encoding: quoted-printable
<div>The situation in functional language with explicit effects is a b=
it different than in C++. If we are to add purity annotations to C++ we nee=
d some way to prove for a function that its effects are loca=
l to its body or to the object it operates on or that it is pure =
in strict sense. In Haskell that would be reflected in a type of a fun=
ction. I fear that in C++ we would need (pseudo-)keywords for each&nbs=
p;of these notions (or at least for some of them). The situation =
is worsened by the fact that there are pointers in C++. And such innocent&n=
bsp;code </div><div> </div><div><font face=3D"courier new,monospace">N=
ode** n =3D <font face=3D"arial,sans-serif">...</font>;</font></div><div><f=
ont face=3D"Courier New">Node* m =3D <font face=3D"arial,sans-serif">...</f=
ont>;</font></div><div><font face=3D"courier new,monospace">*n =3D m;<=
/font></div><div> </div><div>might actually change global state. So I =
doubt that compiler would be able to prove that code th=
at manipulates (changes) std::list is pure in some form without adding=
ownership annotations to type system. </div><div><br>=FE=C5=D4=D7=C5=D2, 1=
5 =CC=C9=D3=D4=CF=D0=C1=C4=C1 2012 =D2. 02:20:13 UTC+2 =CB=CF=D2=C9=D3=D4=
=D5=D7=C1=DE korcan....@googlemail.com =CE=C1=D0=C9=D3=C1=D7:</div><blockqu=
ote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left:=
1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border=
-left-style: solid;"><blockquote class=3D"gmail_quote" style=3D"margin: 0px=
0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); b=
order-left-width: 1px; border-left-style: solid;"><div>In
the case of Haskell there are typically 2 or more versions of these=20
types of higher-order functions, for example there are the <b>map/fold </b>=
functions which are purely functional and the function parameter must be pu=
rely functional as well but Haskell also has <b>mapM/foldM</b>
functions which are variants of map/fold that take a monadic action as
a parameter instead of a pure function. In the latter case, this forces th=
ese functions to be=20
monadic functions themselves and thus are not referentially transparent (pu=
re) functions.<br><br></div></blockquote></blockquote><div> </div><div=
>I thought that map and fold can be expressed in terms of mapM/foldM and vi=
ce versa, so multiple functions are just for convenience. </div>=
<div> <br></div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_353_19303902.1352945326805--
.
Author: korcan.hussein@googlemail.com
Date: Thu, 15 Nov 2012 06:01:07 -0800 (PST)
Raw View
------=_Part_1679_4402078.1352988067638
Content-Type: text/plain; charset=ISO-8859-1
>
> The situation in functional language with explicit effects is a bit
> different than in C++. If we are to add purity annotations to C++ we need
> some way to prove for a function that its effects are local to its body or
> to the object it operates on or that it is pure in strict sense. In Haskell
> that would be reflected in a type of a function. I fear that in C++ we
> would need (pseudo-)keywords for each of these notions (or at least for
> some of them). The situation is worsened by the fact that there are
> pointers in C++. And such innocent code
>
> Node** n = ...;
> Node* m = ...;
> *n = m;
>
> might actually change global state. So I doubt that compiler would be able
> to prove that code that manipulates (changes) std::list is pure in some
> form without adding ownership annotations to type system.
>
I'd say that pointers/references to non-constant types should just be
disallowed in functions parameters and function body with strictly pure.
For weakly pure case disallow them in function parameters but maybe allow
them in the function body with referencing to only local variables
(referencing global/static/data-members should be disallowed).
constant/non-constant pointers/references to constant types is fine.
> In the case of Haskell there are typically 2 or more versions of these
>>> types of higher-order functions, for example there are the *map/fold *functions
>>> which are purely functional and the function parameter must be purely
>>> functional as well but Haskell also has *mapM/foldM* functions which
>>> are variants of map/fold that take a monadic action as a parameter instead
>>> of a pure function. In the latter case, this forces these functions to be
>>> monadic functions themselves and thus are not referentially transparent
>>> (pure) functions.
>>>
>>>
> I thought that map and fold can be expressed in terms of mapM/foldM and
> vice versa, so multiple functions are just for convenience.
>
Ah yes that's true my Haskell is getting a bit rusty now a days, still
there are probably cases where you can not define one terms in terms of the
other but that isn't really the point I'm trying to make.
The question is should function parameters have the ability to specify
purity (and level of purity)? In case of std::find, as of current using an
impure function as a predicate would make std::find impure.
--
------=_Part_1679_4402078.1352988067638
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div>The situation in fun=
ctional language with explicit effects is a bit different than in C++. If w=
e are to add purity annotations to C++ we need some way to prove for a=
function that its effects are local to its body or to the o=
bject it operates on or that it is pure in strict sense. In Haskell th=
at would be reflected in a type of a function. I fear that in C++ we w=
ould need (pseudo-)keywords for each of these notions (or at=
least for some of them). The situation is worsened by the fact that t=
here are pointers in C++. And such innocent code </div><div> </di=
v><div><font face=3D"courier new,monospace">Node** n =3D <font face=3D"aria=
l,sans-serif">...</font>;</font></div><div><font face=3D"Courier New">Node*=
m =3D <font face=3D"arial,sans-serif">...</font>;</font></div><div><font f=
ace=3D"courier new,monospace">*n =3D m;</font></div><div> </div><=
div>might actually change global state. So I doubt that compiler would=
be able to prove that code that manipulates (changes) =
std::list is pure in some form without adding ownership annotations to type=
system. </div></blockquote><div><br>I'd say that pointers/references to no=
n-constant types should just be disallowed in functions parameters and func=
tion body with strictly pure. For weakly pure case disallow them in functio=
n parameters but maybe allow them in the function body with referencing to =
only local variables (referencing global/static/data-members should be disa=
llowed). constant/non-constant pointers/references to constant types is fin=
e.<br> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><blockquote =
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;bo=
rder-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:so=
lid"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;pa=
dding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;bor=
der-left-style:solid"><div>In
the case of Haskell there are typically 2 or more versions of these=20
types of higher-order functions, for example there are the <b>map/fold </b>=
functions which are purely functional and the function parameter must be pu=
rely functional as well but Haskell also has <b>mapM/foldM</b>
functions which are variants of map/fold that take a monadic action as
a parameter instead of a pure function. In the latter case, this forces th=
ese functions to be=20
monadic functions themselves and thus are not referentially transparent (pu=
re) functions.<br><br></div></blockquote></blockquote><div> </div><div=
>I thought that map and fold can be expressed in terms of mapM/foldM and vi=
ce versa, so multiple functions are just for convenience. </div>=
</blockquote><div><br>Ah yes that's true my Haskell is getting a bit rusty =
now a days, still there are probably cases where you can not define one ter=
ms in terms of the other but that isn't really the point I'm trying to make=
..<br><br>The question is should function parameters have the ability to spe=
cify purity (and level of purity)? In case of std::find, as of current usin=
g an impure function as a predicate would make std::find impure.<br><br></d=
iv>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1679_4402078.1352988067638--
.
Author: grigorij1981@gmail.com
Date: Thu, 15 Nov 2012 14:33:03 -0800 (PST)
Raw View
------=_Part_693_10261497.1353018783538
Content-Type: text/plain; charset=KOI8-U
Content-Transfer-Encoding: quoted-printable
=FE=C5=D4=D7=C5=D2, 15 =CC=C9=D3=D4=CF=D0=C1=C4=C1 2012 =D2. 16:01:07 UTC+2=
=CB=CF=D2=C9=D3=D4=D5=D7=C1=DE Korcan Hussein=20
=CE=C1=D0=C9=D3=C1=D7:
>
>
>> I'd say that pointers/references to non-constant types should just be=20
>> disallowed in functions parameters and function body with strictly pure.=
=20
>> For weakly pure case disallow them in function parameters but maybe allo=
w=20
>> them in the function body with referencing to only local variables=20
>> (referencing global/static/data-members should be disallowed).=20
>> constant/non-constant pointers/references to constant types is fine.
>>
> =20
In that case, it would be impossible to classify non-const begin() and=20
end() methods of most containers as weakly pure. While these methods=20
only construct iterators, these iterators usually need access to=20
container's internals stored via pointer.
=20
> =20
>
>
>>>> Ah yes that's true my Haskell is getting a bit rusty now a days, still=
=20
>>>> there are probably cases where you can not define one terms in terms o=
f the=20
>>>> other but that isn't really the point I'm trying to make.
>>>>
>>>> The question is should function parameters have the ability to specify=
=20
>>>> purity (and level of purity)? In case of std::find, as of current usin=
g an=20
>>>> impure function as a predicate would make std::find impure.
>>>>
>>>> =20
We may go two ways:
1) Go for D approach - a simple solution close to constexpr in=20
'expr'essiveness. That means no algorithms and no complex containers in=20
pure methods, and the need of pure functional library for C++.=20
2) Try to push boundaries - try to devise type system where most algorithms=
=20
would be possible to use inside pure functions, maybe with some=20
limitations. That is try to keep C++ style in pure methods. That means=20
need of complex annotations on template functions. And maybe several levels=
=20
of purity and ordering between them. And maybe something else.
=20
If we are willing to go for former solution then we should ask ourselves,=
=20
do we need second constexpr? Do we need double annotations like 'constexpr=
=20
pure' in standard library? Do we need four functional sub-languages (macros=
=20
and C++03 template metaprogramming along with constexpr functions and new=
=20
pure functions) in C++?
=20
If we are willing to go for latter solution then we have to be prepared to=
=20
big changes in type system.
=20
Regards,
Gregory
=20
--=20
------=_Part_693_10261497.1353018783538
Content-Type: text/html; charset=KOI8-U
Content-Transfer-Encoding: quoted-printable
<br>=FE=C5=D4=D7=C5=D2, 15 =CC=C9=D3=D4=CF=D0=C1=C4=C1 2012 =D2. 16:01:07 U=
TC+2 =CB=CF=D2=C9=D3=D4=D5=D7=C1=DE Korcan Hussein =CE=C1=D0=C9=D3=C1=D7:<b=
lockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding=
-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; =
border-left-style: solid;"><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 2=
04); border-left-width: 1px; border-left-style: solid;"><br>I'd say that po=
inters/references to non-constant types should just be disallowed in functi=
ons parameters and function body with strictly pure. For weakly pure case d=
isallow them in function parameters but maybe allow them in the function bo=
dy with referencing to only local variables (referencing global/static/data=
-members should be disallowed). constant/non-constant pointers/references t=
o constant types is fine.<br></blockquote></blockquote><div> </div><di=
v>In that case, it would be impossible to classify non-const=
begin() and end() methods of most containers as weakly pure. Whi=
le these methods only construct iterators, these iterators usually nee=
d access to container's internals stored via pointer.</div><div> </div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padd=
ing-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1p=
x; border-left-style: solid;"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204=
, 204); border-left-width: 1px; border-left-style: solid;"> </blockquo=
te><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; pa=
dding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: =
1px; border-left-style: solid;"><blockquote class=3D"gmail_quote" style=3D"=
margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 2=
04, 204); border-left-width: 1px; border-left-style: solid;"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; =
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-=
style: solid;"><br>Ah yes that's true my Haskell is getting a bit rusty now=
a days, still there are probably cases where you can not define one terms =
in terms of the other but that isn't really the point I'm trying to make.<b=
r><br>The question is should function parameters have the ability to specif=
y purity (and level of purity)? In case of std::find, as of current using a=
n impure function as a predicate would make std::find impure.<br><br></bloc=
kquote></blockquote></blockquote></blockquote><div> </div><div>We may =
go two ways:</div><div>1) Go for D approach - a simple solution close to co=
nstexpr in 'expr'essiveness. That means no algorithms and no complex contai=
ners in pure methods, and the need of pure functional library for C++.=
</div><div>2) Try to push boundaries - try to devise type s=
ystem where most algorithms would be possible to use inside pure functions,=
maybe with some limitations. That is try to keep C++ style =
;in pure methods. That means need of complex annotations on template f=
unctions. And maybe several levels of purity and ordering between them. And=
maybe something else.</div><div> </div><div>If we are willing to go f=
or former solution then we should ask ourselves, do we need second constexp=
r? Do we need double annotations like 'constexpr pure' in standard lib=
rary? Do we need four functional sub-languages (macros and C++03 templ=
ate metaprogramming along with constexpr functions and new pure functions) =
in C++?</div><div> </div><div>If we are willing to go for latter solut=
ion then we have to be prepared to big changes in type system.</div><div>&n=
bsp;</div><div>Regards,</div><div>Gregory</div><div> </div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_693_10261497.1353018783538--
.
Author: Xeo <hivemaster@hotmail.de>
Date: Thu, 15 Nov 2012 15:19:25 -0800 (PST)
Raw View
------=_Part_749_18801939.1353021565931
Content-Type: text/plain; charset=ISO-8859-1
Just my 2cents on the pure thing: If we allow parameters to be specified as
pure, I suggest that it can't be "added" like const can. Example:
int i = 42;
int const& ri1 = i; // works
int pure& ri2 = i; // ill-formed, 'i' not marked 'pure'
int pure& ri3 = ri1; // ill-formed, 'ri1's referenced type not marked 'pure'
int pure j = 42;
int const& rj1 = j; // works, 'pure' can be converted to 'const'
int pure& rj2 = j; // works, 'j' marked 'pure'
int const& rj3 = rj2; // works, same reason as for 'rj1'
This way, you can ensure that the variables can't be modified and/or modify
any state. Of course, you also need a pure for member functions now. These
work similar to const member functions, but even mutable members are constin there.
--
------=_Part_749_18801939.1353021565931
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Just my 2cents on the <span style=3D"color: #000;" class=3D"styled-by-prett=
ify">pure</span><code class=3D"prettyprint"></code> thing: If we allow para=
meters to be specified as <span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><code></code>pure</span><code class=3D"prettyprint"></code>, I sug=
gest that it can't be "added" like <span style=3D"color: #008;" class=3D"st=
yled-by-prettify">const</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><code class=3D"prettyprint"></code>can. Example:<br><b=
r><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250, 250);=
border-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; =
word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">int</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> i </span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #=
066;" class=3D"styled-by-prettify">42</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">cons=
t</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&</sp=
an><span style=3D"color: #000;" class=3D"styled-by-prettify"> ri1 </span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> i</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=
=3D"styled-by-prettify">// works</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">int</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> pure</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> ri2 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"> i</span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #800;" class=3D"styled-by-prettify">// ill-formed, 'i' not marked 'pure'<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">int</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> pure</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> ri3 </span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"> ri1</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-by-pret=
tify">// ill-formed, 'ri1's referenced type not marked 'pure'</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span><span sty=
le=3D"color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> pure j </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" class=
=3D"styled-by-prettify">42</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">;</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify"=
>int</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> rj1 </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> j</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"style=
d-by-prettify">// works, 'pure' can be converted to 'const'</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">int</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> pure</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">&</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> rj2 </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> j</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </=
span><span style=3D"color: #800;" class=3D"styled-by-prettify">// works, 'j=
' marked 'pure'</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br></span><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">const</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"> rj3 </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"> rj2</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"styled-b=
y-prettify">// works, same reason as for 'rj1'</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br></span></div></code></div><br>This =
way, you can ensure that the variables can't be modified and/or modify any =
state. Of course, you also need a <span style=3D"color: #000;" class=3D"sty=
led-by-prettify">pure</span><code class=3D"prettyprint"></code> for member =
functions now. These work similar to <span style=3D"color: #008;" clas=
s=3D"styled-by-prettify"><code></code>const</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> </span><code class=3D"prettyprint"></code=
>member functions, but even <span style=3D"color: #008;" class=3D"styled-by=
-prettify">mutable</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><code class=3D"prettyprint"></code>members are <span style=
=3D"color: #008;" class=3D"styled-by-prettify">const</span><code class=3D"p=
rettyprint"></code> in there.<br>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_749_18801939.1353021565931--
.
Author: Korcan Hussein <korcan.hussein@googlemail.com>
Date: Fri, 16 Nov 2012 02:01:16 -0800 (PST)
Raw View
------=_Part_1056_18837692.1353060076933
Content-Type: text/plain; charset=ISO-8859-1
> In that case, it would be impossible to classify non-const begin() and
> end() methods of most containers as weakly pure. While these methods
> only construct iterators, these iterators usually need access to
> container's internals stored via pointer.
>
I don't see that as a problem and I think that would be the correct
semantics logically for non-mutating algorithms but this maybe a breaking
change if the standard library generic algorithms are changed in this way
without doing something extra to care of the case of non-constant
(references/access) to containers calling begin/end which overload
resolution will always pick the one which returns non-constant iterators.
The recently added cbegin/cend could be a solution in this case but that
would require existing code which doesn't use cbegin/cend using standard
library non-mutating algorithms to be updated.
However it's worth noting that most/all non-mutating algorithms take
iterators which are models of the InputIterator Concept which do not
support writing to (but I don't know if the dereference operator
requirements disallows non-constant reference return types).
> do we need second constexpr?
I don't consider them to be equivalent, constant expressions are about
specifying expressions to be evaluated at compile-time, it's only the
current definition of them that requires a subset of the language which may
change in the future.
> Do we need double annotations like 'constexpr pure' in standard library?
Don't we already have that when using them with constant member functions?
> Do we need four functional sub-languages (macros and C++03 template
> metaprogramming along with constexpr functions and new pure functions) in
> C++?
I know it's not ideal but we may end up with more if C++AMP restrict
keyword is proposed for being added to C++, which is all about specifying
language subsets for various things like using a subset of C++ which can be
converted to compute shaders to run on the GPU in C++AMP.
--
------=_Part_1056_18837692.1353060076933
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div>In that =
case, it would be impossible to classify non-const begin() a=
nd end() methods of most containers as weakly pure. While these m=
ethods only construct iterators, these iterators usually need access t=
o container's internals stored via pointer.</div></blockquote><div><br>I do=
n't see that as a problem and I think that would be the correct semantics l=
ogically for non-mutating algorithms but this maybe a breaking change if th=
e standard library generic algorithms are changed in this way without doing=
something extra to care of the case of non-constant (references/access) to=
containers calling begin/end which overload resolution will always pick th=
e one which returns non-constant iterators. The recently added cbegin/cend =
could be a solution in this case but that would require existing code which=
doesn't use cbegin/cend using standard library non-mutating algorithms to =
be updated.<br><br>However it's worth noting that most/all non-mutating alg=
orithms take iterators which are models of the InputIterator Concept which =
do not support writing to (but I don't know if the dereference operator req=
uirements disallows non-constant reference return types).<br></div><div>&nb=
sp;<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">do we need second=
constexpr?</blockquote><div><br>I don't consider them to be equivalent, co=
nstant expressions are about specifying expressions to be evaluated at comp=
ile-time, it's only the current definition of them that requires a subset o=
f the language which may change in the future.<br> </div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">Do we need double annotations like 'co=
nstexpr pure' in standard library?</blockquote><div><br>Don't we already ha=
ve that when using them with constant member functions?<br> </div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">Do we need four functional su=
b-languages (macros and C++03 template metaprogramming along with constexpr=
functions and new pure functions) in C++?</blockquote><div><br> I kno=
w it's not ideal but we may end up with more if C++AMP restrict keyword is =
proposed for being added to C++, which is all about specifying language sub=
sets for various things like using a subset of C++ which can be converted t=
o compute shaders to run on the GPU in C++AMP.<br></div><div> </div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_1056_18837692.1353060076933--
.
Author: grigorij1981@gmail.com
Date: Sat, 17 Nov 2012 01:56:40 -0800 (PST)
Raw View
------=_Part_44_19913232.1353146200082
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
=D0=9F=CA=BC=D1=8F=D1=82=D0=BD=D0=B8=D1=86=D1=8F, 16 =D0=BB=D0=B8=D1=81=D1=
=82=D0=BE=D0=BF=D0=B0=D0=B4=D0=B0 2012 =D1=80. 12:01:17 UTC+2 =D0=BA=D0=BE=
=D1=80=D0=B8=D1=81=D1=82=D1=83=D0=B2=D0=B0=D1=87 Korcan Hussein=20
=D0=BD=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=B2:
>
> =20
>
>> In that case, it would be impossible to classify non-const begin() and=
=20
>> end() methods of most containers as weakly pure. While these methods=20
>> only construct iterators, these iterators usually need access to=20
>> container's internals stored via pointer.
>>
>
> I don't see that as a problem and I think that would be the correct=20
> semantics logically for non-mutating algorithms but this maybe a breaking=
=20
> change if the standard library generic algorithms are changed in this way=
=20
> without doing something extra to care of the case of non-constant=20
> (references/access) to containers calling begin/end which overload=20
> resolution will always pick the one which returns non-constant iterators.=
=20
> The recently added cbegin/cend could be a solution in this case but that=
=20
> would require existing code which doesn't use cbegin/cend using standard=
=20
> library non-mutating algorithms to be updated.
>
My problem with that approach that in weakly pure functions we're not able=
=20
to use algorithms and containers to do mutation. For example, under such=20
requirements the following code can be considered as weakly pure:
=20
int arr[10];
....
int i =3D 0;
for(; i < 10; ++i)
{
if ( arr[i] =3D=3D a )
break;
}
=20
arr[i] =3D b;
=20
But neither of the following is permitted in pure functions:
1)
std::vector<int> v(10);
=20
std::vector<int>::iterator it =3D v.begin();
for( ;it !=3D v.end(); ++it)
{
if (*it =3D=3D a)
break;
}
*it =3D b;=20
=20
2)
int arr[10];
....
int* p =3D find(arr, arr + 10, a);
*p =3D b;
=20
>
> However it's worth noting that most/all non-mutating algorithms take=20
> iterators which are models of the InputIterator Concept which do not=20
> support writing to (but I don't know if the dereference operator=20
> requirements disallows non-constant reference return types).
>
Input iterator does not support writing but not precludes it. Bidirectional=
=20
and random access iterators are input iterators.
> =20
>
>> do we need second constexpr?
>
>
> I don't consider them to be equivalent, constant expressions are about=20
> specifying expressions to be evaluated at compile-time, it's only the=20
> current definition of them that requires a subset of the language which m=
ay=20
> change in the future.
>
They are not equivalent but close to each other. And the very requirements=
=20
of complile-time computations make constexpr code pure.
=20
> =20
>
>> Do we need double annotations like 'constexpr pure' in standard library?
>
>
> Don't we already have that when using them with constant member functions=
?
>
=20
That does not mean we should make it even worse with triple annotations.=20
=20
> =20
>
>> Do we need four functional sub-languages (macros and C++03 template=20
>> metaprogramming along with constexpr functions and new pure functions) i=
n=20
>> C++?
>
>
> I know it's not ideal but we may end up with more if C++AMP restrict=20
> keyword is proposed for being added to C++, which is all about specifying=
=20
> language subsets for various things like using a subset of C++ which can =
be=20
> converted to compute shaders to run on the GPU in C++AMP.
> =20
>
=20
That's an open question whether we should standardize facilities that=20
support proliferation of sublanguages. C++ is quite complex without them.=
=20
--=20
------=_Part_44_19913232.1353146200082
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
=D0=9F=CA=BC=D1=8F=D1=82=D0=BD=D0=B8=D1=86=D1=8F, 16 =D0=BB=D0=B8=D1=81=D1=
=82=D0=BE=D0=BF=D0=B0=D0=B4=D0=B0 2012 =D1=80. 12:01:17 UTC+2 =D0=BA=D0=BE=
=D1=80=D0=B8=D1=81=D1=82=D1=83=D0=B2=D0=B0=D1=87 Korcan Hussein =D0=BD=D0=
=B0=D0=BF=D0=B8=D1=81=D0=B0=D0=B2:<blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;"><div> =
;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex=
; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wid=
th: 1px; border-left-style: solid;"><div>In that case, it would be imp=
ossible to classify non-const begin() and end() methods of m=
ost containers as weakly pure. While these methods only construct=
iterators, these iterators usually need access to container's internals st=
ored via pointer.</div></blockquote><div><br>I don't see that as a problem =
and I think that would be the correct semantics logically for non-mutating =
algorithms but this maybe a breaking change if the standard library generic=
algorithms are changed in this way without doing something extra to care o=
f the case of non-constant (references/access) to containers calling begin/=
end which overload resolution will always pick the one which returns non-co=
nstant iterators. The recently added cbegin/cend could be a solution in thi=
s case but that would require existing code which doesn't use cbegin/cend u=
sing standard library non-mutating algorithms to be updated.<br></div></blo=
ckquote><div>My problem with that approach that in weak=
ly pure functions we're not able to use algorithms and containers to do mut=
ation. For example, under such requirements the following code can be consi=
dered as weakly pure:</div><div><font face=3D"courier new,monospace"></font=
> </div><div><font face=3D"courier new,monospace">int arr[10];</font><=
/div><div><font face=3D"arial,sans-serif">...</font></div><div><font face=
=3D"Courier New">int i =3D 0;</font></div><div><font face=3D"courier new,mo=
nospace">for(; i < 10; ++i)</font></div><div><font face=3D"Courier New">=
{</font></div><div><font face=3D"courier new,monospace"> if ( arr[i] =
=3D=3D a )</font></div><div><font face=3D"Courier New"> &n=
bsp; break;</font></div><div><font face=3D"Courier New">}</font></div>=
<div><font face=3D"Courier New"></font> </div><div><font face=3D"Couri=
er New">arr[i] =3D b;</font></div><div><font face=3D"Courier New"></font>&n=
bsp;</div><div><font face=3D"arial,sans-serif">But neither of the following=
is permitted in pure functions:</font></div><div>1)</div><div><font face=
=3D"courier new,monospace">std::vector<int> v(10);</font></div><div><=
font face=3D"Courier New"></font> </div><div><font face=3D"Courier New=
">std::vector<int>::iterator it =3D v.begin();</font></div><div><div>=
<font face=3D"courier new,monospace">for( ;it !=3D v.end(); ++it=
)</font></div><div><font face=3D"Courier New">{</font></div><div><font face=
=3D"courier new,monospace"> if (*it =3D=3D a)</font></div><div><font =
face=3D"Courier New"> break;</font></div><div>=
<font face=3D"Courier New">}</font></div><div><font face=3D"Courier New"></=
font><font face=3D"courier new,monospace">*it =3D b;</font> </div></di=
v><div><font face=3D"Courier New"></font> </div><div><font face=3D"ari=
al,sans-serif">2)</font></div><div><font face=3D"Courier New"><div><font fa=
ce=3D"courier new,monospace">int arr[10];</font></div><div><font face=3D"ar=
ial,sans-serif">...</font></div><div><font face=3D"Courier New">int* p =3D =
find(arr, arr + 10, a);</font></div><div><font face=3D"Courier New">*p =3D =
b;</font></div></font><font face=3D"courier new,monospace"></font></div><di=
v> </div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0p=
x 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-l=
eft-width: 1px; border-left-style: solid;"><div><br>However it's worth noti=
ng that most/all non-mutating algorithms take iterators which are models of=
the InputIterator Concept which do not support writing to (but I don't kno=
w if the dereference operator requirements disallows non-constant reference=
return types).<br></div></blockquote><div>Input iterator does not support =
writing but not precludes it. Bidirectional and random access ite=
rators are input iterators.</div><blockquote class=3D"gmail_quote" style=3D=
"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, =
204, 204); border-left-width: 1px; border-left-style: solid;"><div> <b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8e=
x; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wi=
dth: 1px; border-left-style: solid;">do we need second constexpr?</blockquo=
te><div><br>I don't consider them to be equivalent, constant expressions ar=
e about specifying expressions to be evaluated at compile-time, it's only t=
he current definition of them that requires a subset of the language which =
may change in the future.<br></div></blockquote><div>They are not equivalen=
t but close to each other. And the very requirements of complile-time compu=
tations make constexpr code pure.</div><div> </div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; bor=
der-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-sty=
le: solid;"><div> </div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204,=
204); border-left-width: 1px; border-left-style: solid;">Do we need double=
annotations like 'constexpr pure' in standard library?</blockquote><d=
iv><br>Don't we already have that when using them with constant member func=
tions?<br></div></blockquote><div> </div><div>That does not mean =
we should make it even worse with triple annotations. </div><div> =
;</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex=
; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wid=
th: 1px; border-left-style: solid;"><div> </div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-l=
eft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: s=
olid;">Do we need four functional sub-languages (macros and C++03 temp=
late metaprogramming along with constexpr functions and new pure functions)=
in C++?</blockquote><div><br> I know it's not ideal but we may end up=
with more if C++AMP restrict keyword is proposed for being added to C++, w=
hich is all about specifying language subsets for various things like using=
a subset of C++ which can be converted to compute shaders to run on the GP=
U in C++AMP.<br></div><div> </div></blockquote><div> </div><div>T=
hat's an open question whether we should standardize facilities that s=
upport proliferation of sublanguages. C++ is quite complex without them. </=
div>
<p></p>
-- <br />
<br />
<br />
<br />
------=_Part_44_19913232.1353146200082--
.