POV-Ray : Newsgroups : povray.off-topic : A tale of two cities Server Time
30 Jul 2024 04:21:07 EDT (-0400)
  A tale of two cities (Message 6 to 15 of 105)  
<<< Previous 5 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Warp
Subject: Re: A tale of two cities
Date: 13 Mar 2012 11:56:43
Message: <4f5f6e3a@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> In common with all known IDEs, hitting the "new project" button creates 
> a project with /way/ more useless boilerplate code than you will ever 
> need.

  Probably because you created a new *Windows* project, rather than a
portabla command-line one.

> The real sticking point was when I started trying to use abstract 
> classes. It seems that you cannot have a variable of an abstract class. 
> (Because creating that variable would require creating an instance of an 
> abstract class, which is illegal.) You can only have a variable that 
> /points to/ such a value. (Because then what it points to can actually 
> be some concrete subclass.)

  Dynamic binding, abstract classes, and even inheritance, are needed
in practice significantly less often than one might think (especially
if one comes from a background where that's basically the only way of
doing anything).

  In quite many cases it's enough to have classes with no dynamic binding
nor inheritance, and which are handled by value (at least if they contain
only moderate amount of data). In the case of a huffman coder, I really
don't understand what do you need abstract classes for. (There *is* such
a thing as over-designing, when talking about OOP.)

  In many cases if you design your program such that you don't need
dynamic binding, your program will often become more efficient in terms
of both speed and memory usage. (Not because dynamic binding would be
inefficient, as it isn't, but because dynamic memory allocation is, and
if we are talking about abstract classes, then dynamic memory allocation
usually goes hand in hand with it.)

  (Inheritance in itsef is not bad in this sense, because C++ does not
force dynamic binding. Base classes can sometimes be used to group common
implementations into a single module, to avoid code repetition. Using an
inherited class is in no way less efficient than one that has no parent
class at all. However, as said, even inheritance is less often necessary
in practice than one might think.)

> I was eventually able to get the program to produce the correct output. 
> However, it uses the dreaded "new" operator. In particular, it does 
> /not/ use the "delete" operator anywhere. In other words, it leaks. I 
> have literally no idea how to fix this. I can't think of any way of 
> doing it that won't result in double-freeing objects. That's mainly 
> because I can't put responsibility for object creation (and hence object 
> destruction) in the logical place. And /that/ is because I don't have 
> some of the necessary technical understanding.

  If you are an experienced, competent c++ programmer, each time you have
to write the dreaded keyword 'new', it should give you a feeling of unease,
and the instinctive desire to think of better alternatives. This even if
you have no problems whatsoever with memory management in this situation
(eg. because you are using a smart pointer). That's because 'new' is not
only a source of leaks, but also it's inefficient.

  There are, of course, situations where 'new' is the only and best
solution. For example, if you are implementing your own dynamic array
(which has something that std::vector does not provide), then there's
no problem. However, the usage of 'new' should in this case be tightly
restricted to happen inside this dynamic array class, strictly controlled
by it. Maximum encapsulation of the memory management is the key.

  If, for some strange reason, you need to allocate individual objects
dynamically with 'new', then you should either use a smart pointer to
handle it (C++11 provides std::unique_ptr and std::shared_ptr for this
purpose), or you should write a class that acts as such (in other words,
which acts kind of like a data container containing one element: The
allocated object.)

  Writing 'new' outside of a class member function (of a class that handles
that allocated memory, of course) is always a risk. Even if you make sure
there's a corresponding 'delete' at the end of the function, your code
will not be exception-safe (because if an exception happens before that
'delete', the allocated object will be leaked; the exception is if you
use a smart pointer such as std::unique_ptr to handle it).

  In practice I don't remember having to write 'new' even once outside
of a class that handles the allocated memory. Smart pointers are fine
and all, but they are seldom needed in practice.

  Now, writing a class that properly manages its dynamically allocated
memory is a non-trivial task of its own.

-- 
                                                          - Warp


Post a reply to this message

From: Invisible
Subject: Re: A tale of two cities
Date: 13 Mar 2012 12:32:04
Message: <4f5f7684$1@news.povray.org>
On 13/03/2012 03:56 PM, Warp wrote:
> Invisible<voi### [at] devnull>  wrote:
>> In common with all known IDEs, hitting the "new project" button creates
>> a project with /way/ more useless boilerplate code than you will ever
>> need.
>
>    Probably because you created a new *Windows* project, rather than a
> portabla command-line one.

Nope. I specifically requested "console application".

>    Dynamic binding, abstract classes, and even inheritance, are needed
> in practice significantly less often than one might think (especially
> if one comes from a background where that's basically the only way of
> doing anything).

Perhaps. Although in a sense, I'm not actually "interested" in building 
a specific application here, I'm interested in figuring out how 
inheritance and so forth actually works in C++.

> In the case of a huffman coder, I really
> don't understand what do you need abstract classes for. (There *is* such
> a thing as over-designing, when talking about OOP.)

The most obvious way to implement this is to physically build a binary 
tree. That requires either inheritance, or else doing something sly with 
unions. (Or even being /really/ dirty and just having one node type, and 
ignoring the unused fields.)

Now for the /encoding/ part itself, I don't actually need a physical 
tree. I have a vague recollection that last time I did this, I ended up 
cheating and just storing a vector of codewords, and manually munging 
that. It's a lot less elegant, but avoids dynamic allocation. (Or 
rather, no it doesn't, but it hides it in STL containers, so you don't 
have to do it manually.)

This application is just supposed to be the "warm up" for my next 
project, which will involve building complex expression trees. I really 
don't see how you can get away with no dynamic binding when each node 
type needs to be processed differently. Unless you go all non-OO and try 
to implement node type dispatch manually...

>    In many cases if you design your program such that you don't need
> dynamic binding, your program will often become more efficient in terms
> of both speed and memory usage.

I guess to some extent it depends on whether your goals are efficiency 
or maintainability. Certainly the code I'm trying to write will probably 
take milliseconds to execute, whichever way I implement it. If I was 
writing something high-performance, I might care about such things.

>    If you are an experienced, competent c++ programmer, each time you have
> to write the dreaded keyword 'new', it should give you a feeling of unease,
> and the instinctive desire to think of better alternatives.

Well, I did try to think of a way around it. But I failed to come up 
with a solution.

>    There are, of course, situations where 'new' is the only and best
> solution. For example, if you are implementing your own dynamic array
> (which has something that std::vector does not provide), then there's
> no problem. However, the usage of 'new' should in this case be tightly
> restricted to happen inside this dynamic array class, strictly controlled
> by it. Maximum encapsulation of the memory management is the key.

The problem is, I want to copy some data, but since I don't know what 
class it belongs to, I have no idea how big it will be. Presumably 
there's some way around that, but damned if I know what it is... Like I 
say, I need to find a more thorough reading resource that explains this 
stuff properly.

>    Now, writing a class that properly manages its dynamically allocated
> memory is a non-trivial task of its own.

Is that not just a case of allocating the memory correctly in the 
constructor, and freeing it properly in the destructor? (I mean, 
assuming nobody tries to copy the object or free its dynamic memory or 
anything like that...)


Post a reply to this message

From: Warp
Subject: Re: A tale of two cities
Date: 13 Mar 2012 13:20:55
Message: <4f5f81f5@news.povray.org>
Invisible <voi### [at] devnull> wrote:
> > In the case of a huffman coder, I really
> > don't understand what do you need abstract classes for. (There *is* such
> > a thing as over-designing, when talking about OOP.)

> The most obvious way to implement this is to physically build a binary 
> tree. That requires either inheritance, or else doing something sly with 
> unions. (Or even being /really/ dirty and just having one node type, and 
> ignoring the unused fields.)

  I don't see why you need different types of objects for such a binary
tree. Each object can be identical to each other in structure. (If in
some nodes some of the fields are unused, so what? It will still be
significantly more efficient than dynamic binding.)

  You don't need to mess with unions unless you really, really need to
make the objects as small as physically possible. However, making them
that small is completely moot if you are going to allocate them
individually anyways (the allocation bookkeeping overhead will nullify
any space saving you could get from shaving off a few bytes using unions.)
It would only make a significant difference if you used arrays of
objects as your tree data structure, rather than allocating objects
individually, and there were tons and tons of elements.

> Now for the /encoding/ part itself, I don't actually need a physical 
> tree. I have a vague recollection that last time I did this, I ended up 
> cheating and just storing a vector of codewords, and manually munging 
> that. It's a lot less elegant, but avoids dynamic allocation. (Or 
> rather, no it doesn't, but it hides it in STL containers, so you don't 
> have to do it manually.)

  Using an array of objects (rather than individually allocated objects)
doesn't completely avoid memory allocation, but it minimizes their amount,
which is often very significant. (In other words, if your program makes
20 allocations instead of a million, it will have a significant impact
on the speed of the program.)

> This application is just supposed to be the "warm up" for my next 
> project, which will involve building complex expression trees. I really 
> don't see how you can get away with no dynamic binding when each node 
> type needs to be processed differently. Unless you go all non-OO and try 
> to implement node type dispatch manually...

  If you really must have nodes of differing types, then it will become
complicated from the point of view of memory management. Lack of garbage
collection can be a b**** sometimes. (Not that it's impossible; it just
requires a lot of care and strict coding practices to get it right. This
is something you usually want to avoid altogether, if possible.)

  Of course your nodes could simply be (smart) pointers of a base class
type, but then you will be making twice as many allocations (because for
each node you will be allocating the node itself, which is a smart pointer,
*and* the object that the node is pointing to), which is even worse from
an efficiency point of view. It becomes simpler like this, but don't expect
extreme speed. (Haskell probably would beat C++ in this situation.)

  It's sometimes quite a bummer, but when writing efficient C++ you have
to always think "how many memory allocations will this perform?" (even,
and especially, when using STL data containers). The less individual
memory allocations are done, the better. (But of course that's not the
only thing that affects speed, but it's the one major thing not related
to the algorithm itself that does.)

  I have to grant that languages like Java are better at this because
there you don't have to worry about how many allocations are performed
(as JVM's have a significantly faster memory allocation than the C/C++
runtime.)

> >    In many cases if you design your program such that you don't need
> > dynamic binding, your program will often become more efficient in terms
> > of both speed and memory usage.

> I guess to some extent it depends on whether your goals are efficiency 
> or maintainability.

  Avoiding dynamic binding does not automatically mean that your program
becomes more complicated and harder to maintain. In fact, it can sometimes
mean the opposite. Sometimes your programs actually become *simpler* and
much easier to understand. Full OOP (beyond simple encapsulation using
classes) is not always the universal panacea for clarity and maintainability.
(Of course this depends on each individual case.)

> Certainly the code I'm trying to write will probably 
> take milliseconds to execute, whichever way I implement it. If I was 
> writing something high-performance, I might care about such things.

  But even then you have to think which design is easiest in terms of
memory management. The less you have to manage memory manually, the
better. Your program becomes safer and simpler.

> The problem is, I want to copy some data, but since I don't know what 
> class it belongs to, I have no idea how big it will be.

  I didn't understand your problem from that description alone.

> >    Now, writing a class that properly manages its dynamically allocated
> > memory is a non-trivial task of its own.

> Is that not just a case of allocating the memory correctly in the 
> constructor, and freeing it properly in the destructor? (I mean, 
> assuming nobody tries to copy the object or free its dynamic memory or 
> anything like that...)

  The simplest design is to delete the allocated memory in the destructor
(it doesn't really matter where inside the class the memory is allocated
as long as the pointer is kept as 0 when there's nothing allocated) and
then disabling the copy constructor and assignment operators. (In C++98
this is done by declaring them private and not implementing them. In C++11
you can explicitly express this with a keyword.)

  Often this is enough. However, sometimes you would want to be able
to copy and assign objects of that class type around. That's where the
non-triviality kicks in.

  The first problem is: How should the object be copied? There are many
possibilities:

- Perform a deep copy. Every time the object is copied or assigned, all
of the data it's managing is copied. This is the easiest way of managing
copying, but it can be pretty inefficient with large amounts of data (and
because each time you make a copy you need an additional 'new').

- Make the class act as a reference to the managed data, in which case each
copy *shares* the managed data. In this case you need to use reference
counting to know when to delete the data. You also have to design your
program taking into account that the object is acting as a reference to
the data, not as the data itself. (This can work pretty well if your
data object is considered immutable.)

- Perform lazy copying. In other words, copying/assigning the object does
not yet deep-copy the data. Only when the data is modified it will be
copied if it was being shared between more than one object. This makes
copying and assigning more efficient, but accessors less.

- The data is *moved* from the original to the copy. This is very efficient
(because you don't need reference counting or anything else) but can be
quite limiting (because you are not actually copying anything, just moving
the data from one object to another).

  The second problem is that implementing these is not completely trivial
and requires attention to detail and knowing the traps.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: A tale of two cities
Date: 13 Mar 2012 13:31:25
Message: <4f5f846c@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
>   The first problem is: How should the object be copied? There are many
> possibilities:

  If you are wondering which solution the STL data containers use,
it's usually just a simple deep-copy whenever the container is copied
or assigned. (While this is implementation-defined, you can assume that
the vast majority, if not all, of the STL implementations out there use
deep copying.) You should take this into account when using the STL.
(In other words, never needlessly copy/assign a large data container.)

  As said, deep-copying is the easiest/simplest solution in terms of
memory management, but you have to be careful to not be copying them
around without a good reason.

-- 
                                                          - Warp


Post a reply to this message

From: nemesis
Subject: Re: A tale of two cities
Date: 13 Mar 2012 15:27:43
Message: <4f5f9faf$1@news.povray.org>
Invisible escreveu:
> On 13/03/2012 10:11 AM, Invisible wrote:
> I eventually gave up with NetBeans. It's just too cripplingly slow. (I 
> did not have this problem with VS.) If I type something and have to wait 
> /4 seconds/ for anything to appear on the screen, that's too slow, IMHO.

ah, children from the 90's...

> Seriously. Once I got to a handful of files, amounting to a grand total 
> of 6KB of Java source, performance became unacceptably poor.

That's not my (ackowledged little) experience.  And surely not of most 
people working on some hairy shared projects.

> In all, I was spending /far/ too much time fighting the IDE and not 
> enough time actually coding stuff.

cool, now you'll be just fighting a wholesomely stupid language.

*oh, I felt so Darrenish now*

> Some of you may remember that logic simulator I built in Haskell a while 
> back. If I recall, I challenged Warp to implement it in C++, and he 
> couldn't even figure out how the heck it works.

Perhaps you should have told him what the code is supposed to do rather 
than expect someone to figure out what some haskell code is doing.

Here's a challenge for you.  What do these haskell snippets are supposed 
to do?

snippet 1:

((.)$(.))

snippet 2:

f >>= a . b . c =<< g


and for a bonus, guess what this one does:

import System.Environment

foo n = 0 % (0 # (1,0,1)) where
  i%ds
   | i >= n = []
   | True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
   where k = i+10; j = min n k
         (h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
               | True = splitAt 10 ds
  j # s | n>a || r+n>=d = k # t
      | True = show q : k # (n*10,(a-(q*d))*10,d)
   where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
  j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)

main = putStr.foo.read.head =<< getArgs


no googling, huh? ;)


> Yes, Java /still/ sucks. :-P

Yes and that is a feature by design.

What doesn't suck is the JVM and the tens of thousands of useful libs 
that run atop it.  It's the only truly cross-platform performant VM out 
there.  Think about it, libs you don't actually need to recompile on 
your machine.

And if you don't like java, you can just choose from many languages 
running atop it and leveraging from said libs:  Scala, Jython, JRuby, 
even quite a few Scheme implementations... any haskell work on this front?

BTW, Ant is yet another example of XML-madness:  it's basically a 
verbose XML makefile for java.

-- 
a game sig: http://tinyurl.com/d3rxz9


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: A tale of two cities
Date: 13 Mar 2012 15:40:42
Message: <4f5fa2ba@news.povray.org>
On 13/03/2012 19:27, nemesis wrote:
> Invisible escreveu:
>> On 13/03/2012 10:11 AM, Invisible wrote:
>> I eventually gave up with NetBeans. It's just too cripplingly slow. (I
>> did not have this problem with VS.) If I type something and have to
>> wait /4 seconds/ for anything to appear on the screen, that's too
>> slow, IMHO.
>
> ah, children from the 90's...

I wish. :-P

Seriously. Visual Studio manages to be responsive enough, and not eat 
half my RAM. NetBeans can't. IMHO, that makes NetBeans inferior.

>> Seriously. Once I got to a handful of files, amounting to a grand
>> total of 6KB of Java source, performance became unacceptably poor.
>
> That's not my (ackowledged little) experience. And surely not of most
> people working on some hairy shared projects.

I can only say what I saw, not what other people see.

>> In all, I was spending /far/ too much time fighting the IDE and not
>> enough time actually coding stuff.
>
> cool, now you'll be just fighting a wholesomely stupid language.

That's the one. ;-)

>> Some of you may remember that logic simulator I built in Haskell a
>> while back. If I recall, I challenged Warp to implement it in C++, and
>> he couldn't even figure out how the heck it works.
>
> Perhaps you should have told him what the code is supposed to do rather
> than expect someone to figure out what some haskell code is doing.

Well, I did try to explain it in words, but sometimes source code is 
more exact.

> Here's a challenge for you. What do these haskell snippets are supposed
> to do?
>
> snippet 1:
>
> ((.)$(.))

ASCII art? ;-)

In fact, the "$" is necessary. Either way, this takes a 3-argument 
function, the first argument to the function, a function that transforms 
some type into the type of the second argument, and a suitable argument 
to transform. Or, in symbols,

(x -> y -> z) -> x -> (j -> y) -> y -> z

> snippet 2:
>
> f >>= a . b . c =<< g

Without knowing what the variables are bound to, this cannot be 
answered. It would be like saying "what does Foo(Bar(5)) do?"

> and for a bonus, guess what this one does:
>
> import System.Environment
>
> foo n = 0 % (0 # (1,0,1)) where
> i%ds
> | i >= n = []
> | True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
> where k = i+10; j = min n k
> (h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
> | True = splitAt 10 ds
> j # s | n>a || r+n>=d = k # t
> | True = show q : k # (n*10,(a-(q*d))*10,d)
> where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
> j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)
>
> main = putStr.foo.read.head =<< getArgs

That's not even parsable. (Indentation is significant, remember?)

> no googling, huh? ;)

All I need is Hoogle. :-P

>> Yes, Java /still/ sucks. :-P
>
> Yes and that is a feature by design.

O RLY?

> What doesn't suck is the JVM and the tens of thousands of useful libs
> that run atop it. It's the only truly cross-platform performant VM out
> there. Think about it, libs you don't actually need to recompile on your
> machine.

Ha! If only... They don't say "write once, test everywhere" for nothing. ;-)

> And if you don't like java, you can just choose from many languages
> running atop it and leveraging from said libs: Scala, Jython, JRuby,
> even quite a few Scheme implementations... any haskell work on this front?

Darren claims they committed to a feature freeze too soon. I don't know 
about the low-level details of the JVM. But I gather that, say, adding 
Java generics required lots of ugly hacks so it didn't break compatibility.

I hear there are other languages that target the JVM. Presumably you 
still can't use any of the existing libraries though. (Not that any of 
them are much good.)

Oh, Haskell? Yeah, I gather a few people have tried to target the JVM 
with it. Nothing production-grade currently exists, however.

> BTW, Ant is yet another example of XML-madness: it's basically a verbose
> XML makefile for java.

Oh well. At least you don't need tab characters. :-P


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: A tale of two cities
Date: 13 Mar 2012 15:41:30
Message: <4f5fa2ea$1@news.povray.org>
>> The most obvious way to implement this is to physically build a binary
>> tree. That requires either inheritance, or else doing something sly with
>> unions. (Or even being /really/ dirty and just having one node type, and
>> ignoring the unused fields.)
>
>    I don't see why you need different types of objects for such a binary
> tree. Each object can be identical to each other in structure. (If in
> some nodes some of the fields are unused, so what? It will still be
> significantly more efficient than dynamic binding.)

So 16 bytes of space overhead per node is worth it if you can avoid one 
indirect jump instruction? That seems like an odd trade-off from an 
efficiency point of view. (Program complexity is another matter...)

>    You don't need to mess with unions unless you really, really need to
> make the objects as small as physically possible.

Granted. That's why I wasn't going to try to do that.

>> Now for the /encoding/ part itself, I don't actually need a physical
>> tree. I have a vague recollection that last time I did this, I ended up
>> cheating and just storing a vector of codewords, and manually munging
>> that. It's a lot less elegant, but avoids dynamic allocation. (Or
>> rather, no it doesn't, but it hides it in STL containers, so you don't
>> have to do it manually.)
>
>    Using an array of objects (rather than individually allocated objects)
> doesn't completely avoid memory allocation, but it minimizes their amount,
> which is often very significant. (In other words, if your program makes
> 20 allocations instead of a million, it will have a significant impact
> on the speed of the program.)

Mmm, I hadn't even thought of using an /array/. I suppose the upper 
bound on the tree size is statically known, so why not?

>    If you really must have nodes of differing types, then it will become
> complicated from the point of view of memory management. Lack of garbage
> collection can be a b**** sometimes.

Ah well, that's why all large-scale applications are developed in C++, 
right? Because it doesn't force you to have garbage collection.

>    It's sometimes quite a bummer, but when writing efficient C++ you have
> to always think "how many memory allocations will this perform?"

Right. So what you're saying is that it's not dynamic binding /itself/ 
which is slow, but rather the dynamic allocations which necessarily go 
with it. (?)

>    Avoiding dynamic binding does not automatically mean that your program
> becomes more complicated and harder to maintain. In fact, it can sometimes
> mean the opposite. Sometimes your programs actually become *simpler* and
> much easier to understand. Full OOP (beyond simple encapsulation using
> classes) is not always the universal panacea for clarity and maintainability.
> (Of course this depends on each individual case.)

I usually find the OOP approach to be a good one. (Not always, of 
course.) Whether that's the type of code I write or what, I don't know.

Out of curiosity, if /you/ were writing a piece of code that's supposed 
to take a text string, parse it as an expression, and then execute the 
resulting expression, how would you implement that? The most obvious way 
is to make every valid kind of expression be a different class, and have 
an abstract base class with an "execute this" method, which gets 
implemented differently for each type of expression. But this 
necessarily involves dynamic binding and dynamic allocation, which you 
seem to make out is the Ultimate Evil to be avoided at all costs. So how 
would you do it?

(The obvious alternative is to design a single type that contains every 
field that any expression type will ever need, and write a giant switch 
statement to analyse each node to figure out how to execute it - which 
is exactly what OOP was designed to get rid of.)

>    But even then you have to think which design is easiest in terms of
> memory management. The less you have to manage memory manually, the
> better. Your program becomes safer and simpler.

Not manually managing memory certainly /is/ simpler than manually 
managing memory. No arguments there! ;-)

>> The problem is, I want to copy some data, but since I don't know what
>> class it belongs to, I have no idea how big it will be.
>
>    I didn't understand your problem from that description alone.

OK, well, if there is a single TreeNode class, I could write something like

   TreeNode(TreeNode t0, TreeNode t1)
   {
     child0 = new TreeNode;
     child1 = new TreeNode;
     *child0 = t0;
     *child1 = t1;
   }

If, however, the TreeNode class is abstract, obviously this won't work 
at all. I now need to know what the /actual/ type of t0 is before I can 
allocate sufficient space for it. (I'm also fuzzy on what happens when 
you try to delete a pointer - does it know what the "real" size of the 
object is, or does it use the declared type of the pointer?)

>>>     Now, writing a class that properly manages its dynamically allocated
>>> memory is a non-trivial task of its own.
>
>> Is that not just a case of allocating the memory correctly in the
>> constructor, and freeing it properly in the destructor? (I mean,
>> assuming nobody tries to copy the object or free its dynamic memory or
>> anything like that...)
>
>    The simplest design is to delete the allocated memory in the destructor
> (it doesn't really matter where inside the class the memory is allocated
> as long as the pointer is kept as 0 when there's nothing allocated) and
> then disabling the copy constructor and assignment operators. (In C++98
> this is done by declaring them private and not implementing them. In C++11
> you can explicitly express this with a keyword.)
>
>    Often this is enough. However, sometimes you would want to be able
> to copy and assign objects of that class type around. That's where the
> non-triviality kicks in.

Right. Yeah, I can see how that might get confusing - especially if 
you're trying to minimise actual data copying...


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: A tale of two cities
Date: 13 Mar 2012 15:42:34
Message: <4f5fa32a$1@news.povray.org>
On 13/03/2012 17:31, Warp wrote:
> Warp<war### [at] tagpovrayorg>  wrote:
>>    The first problem is: How should the object be copied? There are many
>> possibilities:
>
>    If you are wondering which solution the STL data containers use,
> it's usually just a simple deep-copy whenever the container is copied
> or assigned.

Just to be picky: I'm presuming that it's a "deep" copy as far as 
copying the container itself. Presumably what happens to the elements 
depends on what their copy constructor implements. (?)


Post a reply to this message

From: nemesis
Subject: Re: A tale of two cities
Date: 13 Mar 2012 15:59:35
Message: <4f5fa727$1@news.povray.org>
Orchid Win7 v1 escreveu:
> On 13/03/2012 19:27, nemesis wrote:
>> ah, children from the 90's...
> 
> I wish. :-P

ok, old fart.

> Seriously. Visual Studio manages to be responsive enough, and not eat 
> half my RAM. NetBeans can't. IMHO, that makes NetBeans inferior.

Windows comes with the .NET libraries used by VS.  It's also a native 
program, rather than one running on a VM.

>> Here's a challenge for you. What do these haskell snippets are supposed
>> to do?
>>
>> snippet 1:
>>
>> ((.)$(.))
> 
> ASCII art? ;-)

actually, I thought it was some perl idiom. :)

if it was a bit more concise, it'd give you a nice pair of boobies:
(.)(.)

> In fact, the "$" is necessary. Either way, this takes a 3-argument 
> function, the first argument to the function, a function that transforms 
> some type into the type of the second argument, and a suitable argument 
> to transform. Or, in symbols,
> 
> (x -> y -> z) -> x -> (j -> y) -> y -> z

haha, you already new that from the haskellwiki. :p

>> snippet 2:
>>
>> f >>= a . b . c =<< g
> 
> Without knowing what the variables are bound to, this cannot be 
> answered. It would be like saying "what does Foo(Bar(5)) do?"

ok, both come from here:

http://www.haskell.org/haskellwiki/Pointfree#The_owl
http://www.haskell.org/haskellwiki/Pointfree#Squish

>> and for a bonus, guess what this one does:
>>
>> import System.Environment
>>
>> foo n = 0 % (0 # (1,0,1)) where
>> i%ds
>> | i >= n = []
>> | True = (concat h ++ "\t:" ++ show j ++ "\n") ++ j%t
>> where k = i+10; j = min n k
>> (h,t) | k > n = (take (n`mod`10) ds ++ replicate (k-n) " ",[])
>> | True = splitAt 10 ds
>> j # s | n>a || r+n>=d = k # t
>> | True = show q : k # (n*10,(a-(q*d))*10,d)
>> where k = j+1; t@(n,a,d)=k&s; (q,r)=(n*3+a)`divMod`d
>> j&(n,a,d) = (n*j,(a+n*2)*y,d*y) where y=(j*2+1)
>>
>> main = putStr.foo.read.head =<< getArgs
> 
> That's not even parsable. (Indentation is significant, remember?)

ah, seems indentation is lost (too bad for haskell).  But nice style on 
giving up.

>>> Yes, Java /still/ sucks. :-P
>>
>> Yes and that is a feature by design.
> 
> O RLY?

Yes, so that your hired slaves can't cut the pulses and get free.

>> What doesn't suck is the JVM and the tens of thousands of useful libs
>> that run atop it. It's the only truly cross-platform performant VM out
>> there. Think about it, libs you don't actually need to recompile on your
>> machine.
> 
> Ha! If only... They don't say "write once, test everywhere" for nothing. 
> ;-)

seems like most of the thousands of open-source java libs are well 
tested already.

> I hear there are other languages that target the JVM. Presumably you 
> still can't use any of the existing libraries though. (Not that any of 
> them are much good.)

yes, you are likely to use java libs.

> Oh, Haskell? Yeah, I gather a few people have tried to target the JVM 
> with it. Nothing production-grade currently exists, however.
> 
>> BTW, Ant is yet another example of XML-madness: it's basically a verbose
>> XML makefile for java.
> 
> Oh well. At least you don't need tab characters. :-P

says the haskell programmer... :p

-- 
a game sig: http://tinyurl.com/d3rxz9


Post a reply to this message

From: Orchid Win7 v1
Subject: Re: A tale of two cities
Date: 13 Mar 2012 16:37:07
Message: <4f5faff3$1@news.povray.org>
>>> ah, children from the 90's...
>>
>> I wish. :-P
>
> ok, old fart.

Thanks for making me feel better. :-P

>> Seriously. Visual Studio manages to be responsive enough, and not eat
>> half my RAM. NetBeans can't. IMHO, that makes NetBeans inferior.
>
> Windows comes with the .NET libraries used by VS. It's also a native
> program, rather than one running on a VM.

You know, people say "oh, Java isn't slow". And then this happens...

Also, about this "Windows comes with the .NET libraries". If that's so, 
then why did I have to wait 20 minutes for it to download .NET when I 
installed it?

>>> snippet 1:
>>>
>>> ((.)$(.))
>>
>> ASCII art? ;-)
>
> actually, I thought it was some perl idiom. :)

The question is, who the heck writes code like that anyway? (Except to 
show off.)

> if it was a bit more concise, it'd give you a nice pair of boobies:

Hey, that's what it looked like in the first place. But rich boobies. ;-)

>> In fact, the "$" is necessary. Either way, this takes a 3-argument
>> function, the first argument to the function, a function that
>> transforms some type into the type of the second argument, and a
>> suitable argument to transform. Or, in symbols,
>>
>> (x -> y -> z) -> x -> (j -> y) -> y -> z
>
> haha, you already new that from the haskellwiki. :p

Erm, no... It's a simple question of type inference. I mean, c'mon, it's 
not exactly a complicated code fragment. It's two function calls.

>> That's not even parsable. (Indentation is significant, remember?)
>
> ah, seems indentation is lost (too bad for haskell). But nice style on
> giving up.

Well, yeah, because even if I could understand it, that wouldn't prove 
anything to anyone.

>>>> Yes, Java /still/ sucks. :-P
>>>
>>> Yes and that is a feature by design.
>>
>> O RLY?
>
> Yes, so that your hired slaves can't cut the pulses and get free.

Wuh?

>> Ha! If only... They don't say "write once, test everywhere" for
>> nothing. ;-)
>
> seems like most of the thousands of open-source java libs are well
> tested already.

Wait - there are open-source Java libs now?

(Last time I looked at Java, all anyone ever used it for was pointless 
Tic-Tac-Toe applets. Nobody ever wrote actual large applications with 
it, just small toy examples.)

>>> BTW, Ant is yet another example of XML-madness: it's basically a verbose
>>> XML makefile for java.
>>
>> Oh well. At least you don't need tab characters. :-P
>
> says the haskell programmer... :p

What? Tab characters are explicitly disallowed in Haskell. :-P


Post a reply to this message

<<< Previous 5 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.