Mega Search
23.2 Million


Sign Up

Make a donation  
Functional vs imperative style  
News Group: comp.lang.c++

This is about a class interface design. Let's say I have an Array class 
which is able to encapsulate a N-dimensional array of a dynamic element 
type and has runtime operations for resizing the dimensions, converting 
the element type, etc. 

Should these operations be const member functions returning a new Array 
(functional style) or non-const void member functions modifying the 
object? The actual content is shared and reference-counted behind the 
scenes so just copying an Array object is pretty cheap, so this question 
is more about style, not performance, thus I am mostly leaving out 
optimization issues here.

*Functional style*

class Array {
public:
    Array Reshape(size_t width, size_t height, size_t depth) const;
    template Array Convert() const;
    // ...
};
Array PrepareSomeArray();
void ConsumeArray(Array a);

// usage:
ConsumeArray( PrepareSomeArray().Reshape(10,20,30).Convert());

Advantages:
  - Conscise usage 
  - No side effects (pure functional style)

Drawbacks:
  - Deviates from the std::vector usage (e.g. std::vector::resize()).
  - The caller may forgot to assign the result to a new object and assume 
the modifications happen in place

*Imperative style*

class Array {
public:
    void Reshape(size_t width, size_t height, size_t depth);
    template void Convert();
    // ...
};
Array PrepareSomeArray();
void ConsumeArray(Array a);

// usage example:
Array a = PrepareSomeArray();
a.Reshape(10,20,30);
a.Convert();
ConsumeArray(a);

Advantages:
  - Follows std::vector design

Drawbacks:
  - More verbose usage
  - Code is less robust because of side effects
  - Worse optimization possibilities because unneeded named objects tend 
to remain lying around.

So, any comments or insights? Which style should I aim for? This 
interface is intended for external library users, but at the moment we 
don't have any yet, so cannot ask directly. Which style would *you* 
prefer when given the task to accomplish something by such a library?

Maybe I should provide both styles? They would probably need different 
member function names, are there any naming conventions for these 
different styles?

TIA
Paavo
 

Vote for best question.
Score: 0  # Vote:  0
Date Posted: 27-Aug-2014, at 2:47 AM EST
From: Paavo Helde
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
Melzzzzz  wrote in news:ltnsfr$mv1$1@solani.org:

> On Thu, 28 Aug 2014 13:19:51 -0500
> Paavo Helde  wrote:
> 
>> 
>> I fail to see how refcount changing is bad for thread sharing, but at
>> the same time any other state changing is not.
>> 
> 
> When object is copied across threads user won't expect any surprises.
> Eg changing state would imply COW which has to have some
> synchronization. You know that story about COW strings and why
> are they bad for multi-threaded programs.

This is because in case of std::basic_string COW has to work across 
threads as nobody has told the users they cannot just pass strings over 
to another thread (possibly because the C++ standard did not acknowledge 
the existence of threads at the time...). This causes all the thread 
synchronization pessimizations. In our library, there is a special 
function to be called before passing the object to another thread, which 
ensures the data is not shared.

When COW works in a single thread (and when the class interface is not so 
silly as to expose char& reference from operator[] which will not be used 
for mutation), it is pretty fast and useful.

Cheers
Paavo

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 4:18 PM EST
From: Paavo Helde
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
On Thu, 28 Aug 2014 13:19:51 -0500
Paavo Helde  wrote:

> 
> I fail to see how refcount changing is bad for thread sharing, but at
> the same time any other state changing is not.
> 

When object is copied across threads user won't expect any surprises.
Eg changing state would imply COW which has to have some
synchronization. You know that story about COW strings and why
are they bad for multi-threaded programs.

-- 
press any key to continue or any other to quit...


Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 8:30 PM EST
From: Melzzzzz
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
Melzzzzz  wrote in news:ltlidv$6sa$1@news.albasani.net:

> On Wed, 27 Aug 2014 02:47:57 -0500
> Paavo Helde  wrote:
> 
>> This is about a class interface design. Let's say I have an Array
>> class which is able to encapsulate a N-dimensional array of a dynamic
>> element type and has runtime operations for resizing the dimensions,
>> converting the element type, etc. 
>> 
>> Should these operations be const member functions returning a new
>> Array (functional style) or non-const void member functions modifying
>> the object? The actual content is shared and reference-counted behind
>> the scenes so just copying an Array object is pretty cheap, so this
>> question is more about style, not performance, thus I am mostly
>> leaving out optimization issues here.
> 
> Hm.

Copying an Array object more or less means writing a pointer value in a 
local variable and incrementing the refcount in the actual object. No 
dynamic memory allocation or thread synchronization is involved (pass to 
another thread is a separate explicit operation and ensures first that 
the refcount is 1).

[...]
> I have some experience with Haskell and I can tell that pure functional
> style is performance killer. I always end up writing imperative
> style if I want performance.
> Go for imperative style and make your implementation simpler: get
> rid of reference counting as it is not good for thread sharing.

For some other more lower level interface you might have a point, but 
this is actually a pretty high level C++ interface to a script language 
engine. Value semantics along with the reference counting and COW are 
already there in the script language and the C++ interface ought to have 
the same semantics.

Besides, the goal is to make the usage simple, not the implementation.

> Synchronization problems and ....
> After all OOP is about objects which change states.

I fail to see how refcount changing is bad for thread sharing, but at the 
same time any other state changing is not.

Anyway, I'm currently indeed inclined to go for the imperative style, but 
only because there are several other member functions which seem more 
natural in imperative style (SetPixel(), SetProperty() etc.) and I would 
like to avoid any confusion.

Cheers
Paavo

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 1:19 PM EST
From: Paavo Helde
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
Spike  wrote in news:ltn0ov$u6v$1@dont-email.me:

> On 27/08/2014 09:47, Paavo Helde wrote:
>>
>> Should these operations be const member functions returning a new Array
>> (functional style) or non-const void member functions modifying the
>> object? The actual content is shared and reference-counted behind the
>> scenes so just copying an Array object is pretty cheap, so this question
>> is more about style, not performance, thus I am mostly leaving out
>> optimization issues here.
>>
>> Advantages:
>>    - Conscise usage
>>    - No side effects (pure functional style)
> 
> Maybe I'm missing something, but if the actual content is shared you 
> *have* side effects. So the functional style would be flawed.

No, COW will take care about that. The sharing should in general not be 
noticable for the library user, the objects should normally behave like 
genuine value objects.

Cheers
Paavo



Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 12:15 PM EST
From: Paavo Helde
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
On 27/08/2014 09:47, Paavo Helde wrote:
>
> Should these operations be const member functions returning a new Array
> (functional style) or non-const void member functions modifying the
> object? The actual content is shared and reference-counted behind the
> scenes so just copying an Array object is pretty cheap, so this question
> is more about style, not performance, thus I am mostly leaving out
> optimization issues here.
>
> Advantages:
>    - Conscise usage
>    - No side effects (pure functional style)

Maybe I'm missing something, but if the actual content is shared you 
*have* side effects. So the functional style would be flawed.

S.

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 12:37 PM EST
From: spike
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
On Thu, 28 Aug 2014 09:19:39 +0200
Martijn Lievaart  wrote:

> On Wed, 27 Aug 2014 23:26:23 +0200, Melzzzzz wrote:
> 
> > On Wed, 27 Aug 2014 02:47:57 -0500 Paavo Helde
> >  wrote:
> > 
> (snip)
> >> 
> >> Should these operations be const member functions returning a new
> >> Array (functional style) or non-const void member functions
> >> modifying the object? The actual content is shared and
> >> reference-counted behind the scenes so just copying an Array
> >> object is pretty cheap, so this question is more about style, not
> >> performance, thus I am mostly leaving out optimization issues here.
> > 
> (snip)
> > 
> > I have some experience with Haskell and I can tell that pure
> > functional style is performance killer...
> 
> ... unless the actual content is shared and reference counted behind
> the scenes.

For linked lists and trees that is true. Only updated nodes are copied,
rest are shared. But array update requires copying whole array,
that is why in Haskell mutable arrays (imperative style) are used
whenever one wants performance.

> 
> M4



-- 
press any key to continue or any other to quit...


Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 12:30 PM EST
From: Melzzzzz
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
On Wed, 27 Aug 2014 23:26:23 +0200, Melzzzzz wrote:

> On Wed, 27 Aug 2014 02:47:57 -0500 Paavo Helde 
> wrote:
> 
(snip)
>> 
>> Should these operations be const member functions returning a new Array
>> (functional style) or non-const void member functions modifying the
>> object? The actual content is shared and reference-counted behind the
>> scenes so just copying an Array object is pretty cheap, so this
>> question is more about style, not performance, thus I am mostly leaving
>> out optimization issues here.
> 
(snip)
> 
> I have some experience with Haskell and I can tell that pure functional
> style is performance killer...

.... unless the actual content is shared and reference counted behind the 
scenes.

M4

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 28-Aug-2014, at 9:19 AM EST
From: Martijn Lievaart
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
On Wed, 27 Aug 2014 02:47:57 -0500
Paavo Helde  wrote:

> This is about a class interface design. Let's say I have an Array
> class which is able to encapsulate a N-dimensional array of a dynamic
> element type and has runtime operations for resizing the dimensions,
> converting the element type, etc. 
> 
> Should these operations be const member functions returning a new
> Array (functional style) or non-const void member functions modifying
> the object? The actual content is shared and reference-counted behind
> the scenes so just copying an Array object is pretty cheap, so this
> question is more about style, not performance, thus I am mostly
> leaving out optimization issues here.

Hm.

> 
> *Functional style*
> 
> class Array {
> public:
>     Array Reshape(size_t width, size_t height, size_t depth) const;
>     template Array Convert() const;
>     // ...
> };
> Array PrepareSomeArray();
> void ConsumeArray(Array a);
> 
> // usage:
> ConsumeArray( PrepareSomeArray().Reshape(10,20,30).Convert());
> 
> Advantages:
>   - Conscise usage 
>   - No side effects (pure functional style)
 - you have to make copies of Array on both Reshape and Convert
operations which is more expensive than just mutating operation.
If not, users would be really surprised ;)
Array a = PrepareSomeArray();
Array b = a.Reshape(10,20,30);
// ... work with a
And you *have* side effect, which is maintaining reference count....

> 
> Drawbacks:
>   - Deviates from the std::vector usage (e.g. std::vector::resize()).
>   - The caller may forgot to assign the result to a new object and
> assume the modifications happen in place

- Lot of copies.

> 
> *Imperative style*
> 
> class Array {
> public:
>     void Reshape(size_t width, size_t height, size_t depth);
>     template void Convert();
>     // ...
> };
> Array PrepareSomeArray();
> void ConsumeArray(Array a);
> 
> // usage example:
> Array a = PrepareSomeArray();
> a.Reshape(10,20,30);
> a.Convert();
> ConsumeArray(a);
> 
> Advantages:
>   - Follows std::vector design
> 
> Drawbacks:
>   - More verbose usage
>   - Code is less robust because of side effects
>   - Worse optimization possibilities because unneeded named objects
> tend to remain lying around.
> 
> So, any comments or insights? Which style should I aim for? This 
> interface is intended for external library users, but at the moment
> we don't have any yet, so cannot ask directly. Which style would
> *you* prefer when given the task to accomplish something by such a
> library?
> 
> Maybe I should provide both styles? They would probably need
> different member function names, are there any naming conventions for
> these different styles?

I have some experience with Haskell and I can tell that pure functional
style is performance killer. I always end up writing imperative
style if I want performance.
Go for imperative style and make your implementation simpler: get
rid of reference counting as it is not good for thread sharing.
Synchronization problems and ....
After all OOP is about objects which change states.

> 
> TIA
> Paavo
>  



-- 
press any key to continue or any other to quit...


Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 27-Aug-2014, at 11:26 PM EST
From: Melzzzzz
 
Re: Functional vs imperative style  
News Group: comp.lang.c++
Jorgen Grahn  wrote in 
news:slrnlvscn4.1ks.grahn+nntp@frailea.sa.invalid:

> On Wed, 2014-08-27, Paavo Helde wrote:
> ...
>> So, any comments or insights? Which style should I aim for? This 
>> interface is intended for external library users, but at the moment we 
>> don't have any yet, so cannot ask directly.
> 
> Another non-answer: don't expect the library to turn out really well
> if there are no users.

Right. That's what I'm a bit worried about. At the moment it is a 
proprietary library and the intended users are mostly other departments 
who want to include our data analysis library in their products. 
Currently they are mostly content of using it in a separate executable 
and communicating over disk files or HTTP.

We have some hopes to open-source it at some time-point, which would 
certainly add more users. But this decision is not mine to make.
 
> Can you postpone the interface decisions, working on something else in
> the meantime?  Or trick the users into arriving earlier?

This is a chicken-and-egg problem. This interface has been postponed at 
least from year 2009.

Cheers
Paavo

Vote for best answer.
Score: 0  # Vote:  0
Date Posted: 27-Aug-2014, at 3:50 PM EST
From: Paavo Helde