digitalmars.D - std.mmfile.d observations
- Andrew Fedoniouk (28/28) Apr 04 2005 First:
- Ben Hinkle (16/42) Apr 04 2005 Note std.stream also throws when you try to construct a File or Buffered...
- Andrew Fedoniouk (57/88) Apr 04 2005 And it is bad (IMHO).
- Matthew (2/4) Apr 04 2005 Really? Since when?
- Andrew Fedoniouk (47/51) Apr 05 2005 Sorry, Matthew, I've propagated problem with exceptions in destructors [...
-
Matthew
(11/25)
Apr 05 2005
Ok. Phew!
- Andrew Fedoniouk (5/8) Apr 07 2005 This 'and' in "procedural and OO programming" sounds like
- Matthew (2/8) Apr 07 2005 LOL! Brilliant. I shall be thus known henceforth. :-)
- Ben Hinkle (32/127) Apr 05 2005 If one is running D code without a GC they have more things in Phobos to...
- Andrew Fedoniouk (38/60) Apr 05 2005 I am not against exceptions in general.
- Ben Hinkle (23/42) Apr 05 2005 Actually I'd say try/catch allows you to pinpoint the location that can
- brad domain.invalid (42/42) Apr 05 2005 This might be a completely naive comment - I don't claim to be an OO
- Regan Heath (62/104) Apr 05 2005 I think you have a valid point.
- brad domain.invalid (20/20) Apr 05 2005 One other thing that I forgot to point out in my previous post.
- Regan Heath (19/27) Apr 05 2005 I think whether it's "exceptional" depends on any assumptions or
- Regan Heath (5/10) Apr 04 2005 My impression is that given that void[] is implicitly castable to any
- Andrew Fedoniouk (5/14) Apr 04 2005 void is not anything. It is just nothing.
- Regan Heath (24/40) Apr 04 2005 Not in D, IMO. Plus, consider "void *" how can it be a "pointer to
- Andrew Fedoniouk (11/40) Apr 05 2005 Not exactly. DMD does not allow this:
- Regan Heath (26/75) Apr 05 2005 Sorry, I miss read the question above. I thought you were asking what th...
- Andrew Fedoniouk (3/20) Apr 05 2005 void[0] is what?
- Regan Heath (19/41) Apr 05 2005 :)
- Georg Wrede (14/17) Apr 05 2005 One could think of void as being an address only.
-
Stewart Gordon
(10/17)
Apr 05 2005
First: In current implementation of MmFile (std.mmfile.d) constructor of MmFile throws exceptions if file cannot be opened. I don't think that throwing exceptions in cunstructors is a good idea at all. MmFile, I think, shall have not public constructors. Instead it should have one static method: static MmFile open(pathname, openmode) {...} which does not throw any errors and returns just null if operation cannot be completed. Having implemented MmFile this way user of it will always get valid MmFile object in valid state. This is more deterministic approach I guess. Phylosophically speaking, negative response on any file open operation is not an exception but rather expected situation. So don't need an exception here. IMHO of course. -------------------------------------------------------- Second: These two methods of MmFile are in conflict by their return values. void[] opSlice(size_t i1, size_t i2) ubyte opIndex(size_t i) (And yet I still didn't get an idea what void[] means - vector of nothings? ) Probably it is better to change it to ubyte[] opSlice(size_t i1, size_t i2) for the sake of simplicity? Andrew. http://terrainformatica.com
Apr 04 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d2s9kn$460$1 digitaldaemon.com...First: In current implementation of MmFile (std.mmfile.d) constructor of MmFile throws exceptions if file cannot be opened.Note std.stream also throws when you try to construct a File or BufferedFile and it fails to open or create. Java and .Net also throw.I don't think that throwing exceptions in cunstructors is a good idea at all.I suppose it is nasty if one is subclassing and trying to practice RAII. Is that what you had in mind? Maybe we should just make sure these things are final classes and cut the problems off from the start.MmFile, I think, shall have not public constructors. Instead it should have one static method: static MmFile open(pathname, openmode) {...} which does not throw any errors and returns just null if operation cannot be completed.That isn't too bad, I suppose. Checking for a special return value is a common way to avoid throwing. If anyone tries to use the resulting MmFile on failure they'll get a seg-v, which might be less obvious what happened than an exception thrown from MmFile.Having implemented MmFile this way user of it will always get valid MmFile object in valid state. This is more deterministic approach I guess.How does throwing return an object in an invalid state? It seems just as deterministic to me.Phylosophically speaking, negative response on any file open operation is not an exception but rather expected situation. So don't need an exception here. IMHO of course.Maybe we need "open" and "open_plz" where open_plz is less ... assertive. :-)-------------------------------------------------------- Second: These two methods of MmFile are in conflict by their return values. void[] opSlice(size_t i1, size_t i2) ubyte opIndex(size_t i) (And yet I still didn't get an idea what void[] means - vector of nothings? ) Probably it is better to change it to ubyte[] opSlice(size_t i1, size_t i2) for the sake of simplicity?Seems like a good idea to me.
Apr 04 2005
Below:And it is bad (IMHO). What happens with this allocated and not constructed object? It just becomes "joy of garbage colector" which acceptable in pure GC based sytems ... But use cases of D are not always "GCable".In current implementation of MmFile (std.mmfile.d) constructor of MmFile throws exceptions if file cannot be opened.Note std.stream also throws when you try to construct a File or BufferedFile and it fails to open or create. Java and .Net also throw.Probably I am too deep in C++ where exceptions in constructors are "persons non grata" and, apropos, bad design. But anyway it is better to have valid object or nothing then nobody knows what.I don't think that throwing exceptions in cunstructors is a good idea at all.I suppose it is nasty if one is subclassing and trying to practice RAII. Is that what you had in mind? Maybe we should just make sure these things are final classes and cut the problems off from the start.Semantic of 'open' operation always assumes negative results too: (as access to any other system/external resource) Example: Image loadImage(....) { MmFile f = MmFile.open(....); if( f is null ) return null; .... ---versus current ------------------ Image loadImage(....) { MmFile f = null; try { f = new MmFile(....); } catch( FileException ) { } if( f is null ) return null; .....MmFile, I think, shall have not public constructors. Instead it should have one static method: static MmFile open(pathname, openmode) {...} which does not throw any errors and returns just null if operation cannot be completed.That isn't too bad, I suppose. Checking for a special return value is a common way to avoid throwing. If anyone tries to use the resulting MmFile on failure they'll get a seg-v, which might be less obvious what happened than an exception thrown from MmFile.System first allocates chunk of memory. If exception happens then this memory is just non-determenistic garbage :)Having implemented MmFile this way user of it will always get valid MmFile object in valid state. This is more deterministic approach I guess.How does throwing return an object in an invalid state? It seems just as deterministic to me.:-))) Program in INTERCAL programming language: DO (5) NEXT PLEASE WRITE IN :1 DO (1) NEXT PLEASE DO (4) NEXT DO (1) NEXT DO (4) NEXT (2) DO RESUME .1 (1) PLEASE DO (2) NEXT DO READ OUT :1 DO (3) NEXT PLEASE DO (5) NEXT (3) DO (2) NEXT PLEASE GIVE UP -------------------------- Last statement especially .... touching I would say.Phylosophically speaking, negative response on any file open operation is not an exception but rather expected situation. So don't need an exception here. IMHO of course.Maybe we need "open" and "open_plz" where open_plz is less ... assertive. :-)
Apr 04 2005
Probably I am too deep in C++ where exceptions in constructors are "persons non grata" and, apropos, bad design.Really? Since when? Please offer some sources to substantiate this opinion.
Apr 04 2005
Sorry, Matthew, I've propagated problem with exceptions in destructors [1] onto constructors also. Mea culpa. BTW: MmFile destructor is also generating exceptions. In any case general rule: "you should avoid unnecessary try blocks" [2] sounds reasonable as a general recommendation. IMHO, System resource wrappers should not throw exceptions or at least should allow non exceptional forms of operations. There are too many practical reasons for that. One possible implemetataion: class MmFile { this() {} // constructs empty wrapper, no exceptions this(pathname) { if( !open(pathname) ) throw FileException(...). } // the only way to report problem in ctor is to throw an exception. bool open( pathname) // tries to open physical object, no exception here. bool close( ) // tries to 'close' physical object, no exception here. ~this() { close(); } // no exception here, ignorabimus et ignoramus } But I am personally prefer the form : class MmFile { potected this() {} // protected, not constructable in 'void' state externally static MmFile open( pathname); // factory alike ctor. // tries to open physical object, no exception here. // returns null if MmFile could not be open in requested state. bool close( ) // tries to 'close' physical object, no exception here. ~this() { close(); } // no exception here } The second form does not even try to allocate any object if it cannot be created. If I (consumer of MmFile) need an exception I can always throw them after failed open. I would like to have an option to manage throw or not to throw problem by myself. Andrew Fedoniouk. http://terrainformatica.com Literature: [1] Scott Meyer, More Effective C++. "Item 11: Prevent exceptions from leaving destructors." ( http://www.ishiboo.com/~nirva/c++/eff/MEC/MI11_FR.HTM ) [2] Scott Meyer, More Effective C++. "Item 15: Understand the costs of exception handling"Probably I am too deep in C++ where exceptions in constructors are "persons non grata" and, apropos, bad design.Really? Since when? Please offer some sources to substantiate this opinion.
Apr 05 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d2uorf$2ot6$1 digitaldaemon.com...Ok. Phew! <g> Of course, throwing exceptions from dtors in C++ is an (almost) absolute no-no.Sorry, Matthew, I've propagated problem with exceptions in destructors [1] onto constructors also. Mea culpa.Probably I am too deep in C++ where exceptions in constructors are "persons non grata" and, apropos, bad design.Really? Since when? Please offer some sources to substantiate this opinion.BTW: MmFile destructor is also generating exceptions.Sigh. I don't doubt it. I need to rewrite itIn any case general rule: "you should avoid unnecessary try blocks" [2] sounds reasonable as a general recommendation. IMHO, System resource wrappers should not throw exceptions or at least should allow non exceptional forms of operations.I totally agree. I instinctively go for a two layer approach - vestigial evidence of which can be seen in std.loader - whereby non/little-throwing core functions are used in throwing class layers. I write my C/C++ in this way, and don't see anything fundamentally different in D that it should be otherwise. (Of course, such an approach is open to being criticised as being overly complex. C'est la vie!) In that way, there's full and proper support for both procedural and OO programming, without any bias/disaccommodation to practitioners in either camp.
Apr 05 2005
In that way, there's full and proper support for both procedural and OO programming, without any bias/disaccommodation to practitioners in either camp.This 'and' in "procedural and OO programming" sounds like murmur of Styx river separating these two kingdoms. Where Matthew is like Charon on duty. :) ( No offence ) Literature: [1] http://www.pantheon.org/articles/s/styx_river.html
Apr 07 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d32mf5$1b65$1 digitaldaemon.com...LOL! Brilliant. I shall be thus known henceforth. :-)In that way, there's full and proper support for both procedural and OO programming, without any bias/disaccommodation to practitioners in either camp.This 'and' in "procedural and OO programming" sounds like murmur of Styx river separating these two kingdoms. Where Matthew is like Charon on duty. :) ( No offence )
Apr 07 2005
"Andrew Fedoniouk" <news terrainformatica.com> wrote in message news:d2t7qo$12m7$1 digitaldaemon.com...Below:If one is running D code without a GC they have more things in Phobos to worry about than a leak from an exception. Several parts of the library would have to change APIs to adjust. It would probably be easier to not use phobos at all and start a GC-less API elsewhere.And it is bad (IMHO). What happens with this allocated and not constructed object? It just becomes "joy of garbage colector" which acceptable in pure GC based sytems ... But use cases of D are not always "GCable".In current implementation of MmFile (std.mmfile.d) constructor of MmFile throws exceptions if file cannot be opened.Note std.stream also throws when you try to construct a File or BufferedFile and it fails to open or create. Java and .Net also throw.Some things are more likely to fail than others. When calling new to allocate a new object fails it does not return null - it throws. That makes sense since running out of memory is exceptional. Opening a socket accross a flaky network is more likely to fail so I could see the usefullness in returning null or some special failure flag.Probably I am too deep in C++ where exceptions in constructors are "persons non grata" and, apropos, bad design. But anyway it is better to have valid object or nothing then nobody knows what.I don't think that throwing exceptions in cunstructors is a good idea at all.I suppose it is nasty if one is subclassing and trying to practice RAII. Is that what you had in mind? Maybe we should just make sure these things are final classes and cut the problems off from the start.Semantic of 'open' operation always assumes negative results too: (as access to any other system/external resource)MmFile, I think, shall have not public constructors. Instead it should have one static method: static MmFile open(pathname, openmode) {...} which does not throw any errors and returns just null if operation cannot be completed.That isn't too bad, I suppose. Checking for a special return value is a common way to avoid throwing. If anyone tries to use the resulting MmFile on failure they'll get a seg-v, which might be less obvious what happened than an exception thrown from MmFile.Example: Image loadImage(....) { MmFile f = MmFile.open(....); if( f is null ) return null; .... ---versus current ------------------ Image loadImage(....) { MmFile f = null; try { f = new MmFile(....); } catch( FileException ) { } if( f is null ) return null; .....Yes, and then the loadImage has to check for null etc etc. Exceptions are a way of ensuring that "everyone checks for null" and it makes sure the exception happens at the point of opening the file instead of five routines later when someone tries to access a null reference. If you are concerned about the amount of code required to write a try/catch then you can improve on your version slightly by putting the return in the catch - though again I tend to think allowing the exception to go through loadImage is the right thing to do. Or if we could chain exceptions (see my earlier thread about chaining exceptions) one could write Image loadImage(....) { MmFile f = null; try { f = new MmFile(....); } catch( FileException e) { throw new ImageException("Failed to load",e); } .....Free your mind, not your memory :-) Don't worry about a block or two that become garbage from an exception - it won't happen often enough to be measurable.System first allocates chunk of memory. If exception happens then this memory is just non-determenistic garbage :)Having implemented MmFile this way user of it will always get valid MmFile object in valid state. This is more deterministic approach I guess.How does throwing return an object in an invalid state? It seems just as deterministic to me.Nice. It's like getting a "System panic" message on a Sun box. If the system is panicing, then what should I be doing? yikes.:-))) Program in INTERCAL programming language: DO (5) NEXT PLEASE WRITE IN :1 DO (1) NEXT PLEASE DO (4) NEXT DO (1) NEXT DO (4) NEXT (2) DO RESUME .1 (1) PLEASE DO (2) NEXT DO READ OUT :1 DO (3) NEXT PLEASE DO (5) NEXT (3) DO (2) NEXT PLEASE GIVE UP -------------------------- Last statement especially .... touching I would say.Phylosophically speaking, negative response on any file open operation is not an exception but rather expected situation. So don't need an exception here. IMHO of course.Maybe we need "open" and "open_plz" where open_plz is less ... assertive. :-)
Apr 05 2005
Some things are more likely to fail than others. When calling new to allocate a new object fails it does not return null - it throws. That makes sense since running out of memory is exceptional. Opening a socket accross a flaky network is more likely to fail so I could see the usefullness in returning null or some special failure flag.......Yes, and then the loadImage has to check for null etc etc. Exceptions are a way of ensuring that "everyone checks for null" and it makes sure the exception happens at the point of opening the file instead of five routines later when someone tries to access a null reference. If you are concerned about the amount of code required to write a try/catch then you can improve on your version slightly by putting the return in the catch - though again I tend to think allowing the exception to go through loadImage is the right thing to do. Or if we could chain exceptions (see my earlier thread about chaining exceptions) one could write Image loadImage(....) { MmFile f = null; try { f = new MmFile(....); } catch( FileException e) { throw new ImageException("Failed to load",e); } .....I am not against exceptions in general. They are useful when a) you need them and b) can manage them properly. Real scenario: HTML with images. In this particular case 'no image' case is not an exception - it is rather hihgly expected and normal situation. I just cannot see reasons why I need to pay a price of exception mechanism when I don't need it at all. The design of d.std should be flexible to allow me to work in most effective way. Again, non-existence of external resource (file, service on IP address), etc.is not an exception. Application should be designed the way it accepts existence and non-existence of resources as equally probable outcome of open, acquisition, etc. And yet, only at the place of opening resource you know exactly what to do if it does not exist - e.g. apply default values to members of the class, etc. It is just not fair to throw your undetermination further in the code which has no idea how to handle it. So in real life you will *always* wrap MmFile f = new MmFile (...) into try/catch in the procedure calling it. So why bother about exceptions in this case? E.g. try { Image img = LoadImage(....); } catch( what? ) // everything possible from Phobos? { } There is no throws clause in D so you should dig inside source to determine list of all possible exceptions. Is it good? Andrew. http://terrainformatica.com
Apr 05 2005
And yet, only at the place of opening resource you know exactly what to do if it does not exist - e.g. apply default values to members of the class, etc. It is just not fair to throw your undetermination further in the code which has no idea how to handle it.Actually I'd say try/catch allows you to pinpoint the location that can handle it and give that location enough context to do a good job handling it.So in real life you will *always* wrap MmFile f = new MmFile (...) into try/catch in the procedure calling it. So why bother about exceptions in this case? E.g. try { Image img = LoadImage(....); } catch( what? ) // everything possible from Phobos? { }One puts the try/catch wherever they make sense. Sometimes you just let the exception go up the stack until some function wants to clean up or tell the user or recover etc etc. There is no hard rule that exceptions must be caught immediately. Let me ask a question about your code example: when LoadImage returns null (assuming that's what you would do) how do you tell the user what went wrong? Do you say the file didn't exist or that the file length was wrong or the colorspace wasn't supported? The code that called LoadImage has no clue what went wrong. There would have to be a global state GetLastError (if that wasn't already taken...) that would return the error code or string to say exactly what happened. That is much more fragile than putting that information in an exception that gets passed along up the call stack.There is no throws clause in D so you should dig inside source to determine list of all possible exceptions. Is it good?It is part of the documentation of a function to say what it throws or does on failure. D doesn't have checked exceptions but that doesn't mean users have to guess what exceptions get thrown. Looking at the phobos doc for std.stream I notice readExact does say it throws a ReadException but File.open or File.this only says it errors but doesn't give the class of the exception. I'll make the doc more explicit about what exceptions are thrown by std.stream and send that to Walter. I notice std.mmfile does say it throws FileException for any error.
Apr 05 2005
This might be a completely naive comment - I don't claim to be an OO guru. It has always bugged the heck out of me that C++ constructors must either succeed or throw, presumably this is because you can construct objects on the stack - ie Foo f(blah); - and must have a valid object. In D the only way to construct and object is with the new keyword - ie Foo f = new Foo (blah) - and f is always a reference. Therefore all objects in D are references, and can potentially be null. So - would it be useful for D constructors to support the notion of failing to construct an object without throwing an exception? example (I hope the tabs show up OK) class Failure { this(int i) { if (error_cond) return null; // otherwise setup normally } } for (int i = 0; i < 10; i++) { Failure f = new Failure(i); if (f) add_to_list(f); } compared to catching exceptions for (int i = 0; i < 10; i ++) { try { Failure f = new Failure(i); add_to_list (f); } catch (whatever) { } } Does this work well with inheritance? ie if (!super ()) return null; Thoughts? Brad
Apr 05 2005
On Wed, 06 Apr 2005 10:23:26 +1200, <brad domain.invalid> wrote:This might be a completely naive comment - I don't claim to be an OO guru. It has always bugged the heck out of me that C++ constructors must either succeed or throw, presumably this is because you can construct objects on the stack - ie Foo f(blah); - and must have a valid object. In D the only way to construct and object is with the new keyword - ie Foo f = new Foo (blah) - and f is always a reference. Therefore all objects in D are references, and can potentially be null. So - would it be useful for D constructors to support the notion of failing to construct an object without throwing an exception? example (I hope the tabs show up OK) class Failure { this(int i) { if (error_cond) return null; // otherwise setup normally } } for (int i = 0; i < 10; i++) { Failure f = new Failure(i); if (f) add_to_list(f); } compared to catching exceptions for (int i = 0; i < 10; i ++) { try { Failure f = new Failure(i); add_to_list (f); } catch (whatever) { } } Does this work well with inheritance? ie if (!super ()) return null; Thoughts? BradI think you have a valid point. Being a C programmer I have little experience with exceptions (I have done some C++ and Java and so on), that said I am trying to use them in D, as it is the recommended practice. I agree with Ben's point here: <quote "Ben Hinkle"> Let me ask a question about your code example: when LoadImage returns null (assuming that's what you would do) how do you tell the user what went wrong? Do you say the file didn't exist or that the file length was wrong or the colorspace wasn't supported? The code that called LoadImage has no clue what went wrong. There would have to be a global state GetLastError (if that wasn't already taken...) that would return the error code or string to say exactly what happened. That is much more fragile than putting that information in an exception that gets passed along up the call stack. </quote> But at the same time I agree with Andrew that sometimes having to use try/catch when a simple boolean type of "it worked"/"it failed" indication is all that is desired/required. Maybe this is simply a design problem, and where appropriate one or the other should be done, or both provided, not sure. Can we solve this by providing a template/function to handle isolated try catch single function calls? Something like: template call(?) { bool call(?,out Exception e) try { ? //call the function passing all args etc. return true; } catch(Exception ee) { e = ee; return false; } } allowing us to write: Exception e; if (!call(<function/method>,e)) { ..report exception.. } as to me, that looks nicer and less hassle than the whole try/catch block. Even better might be a built in syntax for handling this eg. if (!call(<function/method>,e)) { //where 'e' is the name of the Exception and is only instantiated/valid in this block //no need to define it earlier as shown in first example above } (Instead of 'call' we could use 'catch') In general I prefer this style of programming as I like to handle errors as they occur and avoid endlessly indenting code in {} blocks, which seems to happen when I use try/catch eg. if () { try { if () { try { } catch() { } } } catch() { } } Thoughts? Regan
Apr 05 2005
One other thing that I forgot to point out in my previous post. Exceptions are ment to handle exceptional circumstances. With the current thinking, a constructor failing for some reason is an exceptional circumstance - is this presumption really true? I don't see the harm in allowing constructors to fail and return NULL, all that happens is that you get a null pointer reference and segfault (BTW, I would like null pointer references to be trapped and excepted, but hey, that's another thread) In my own C++ and D code to handle this kind of case, I usually have an empty constructor, and a worker function that fails or doesn't, so my code looks like Foo f = new Foo(); if (f.open("whatever")) { .... } // c++ only else delete f; Brad
Apr 05 2005
On Wed, 06 Apr 2005 11:19:03 +1200, <brad domain.invalid> wrote:One other thing that I forgot to point out in my previous post. Exceptions are ment to handle exceptional circumstances. With the current thinking, a constructor failing for some reason is an exceptional circumstance - is this presumption really true?I think whether it's "exceptional" depends on any assumptions or expectations the programmer has in each situation where it is used. So the code that throws can't know unless told whether it's expected or unexpected thus exceptional or unexceptional. The problem being that it's hard to communicate assumptions/expectations via code. Using a previous example (and contentious subject), AA's: foo["a"] = 4; //assumes "a" is a key in 'foo', could throw if ("a" in foo) {} //a question, not an assumption, shouldn't throw it gets more difficult to decide here: val = foo["a"]; val = foo.get("a"); Is the programmer assuming it exists, or happy to get 'null' if it doesn't... If the next line uses val without checking for 'null' then you have your answer, as Brad said here:I don't see the harm in allowing constructors to fail and return NULL, allthat happens is that you get a null pointer reference and segfault (BTW,I would like null pointer references to be trapped and excepted, but hey,that's another thread)(I belive "constructors" in the above can be replaced with "methods" and it still applies) Regan (perverting Brad's words/meaning to my own ends).
Apr 05 2005
On Mon, 4 Apr 2005 13:55:52 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:These two methods of MmFile are in conflict by their return values. void[] opSlice(size_t i1, size_t i2) ubyte opIndex(size_t i) (And yet I still didn't get an idea what void[] means - vector of nothings? )My impression is that given that void[] is implicitly castable to any other array type, void[] means "vector of anythings". Regan
Apr 04 2005
void is not anything. It is just nothing. http://dictionary.reference.com/search?q=void See: static void[12] voids; What is voids.sizeof ?These two methods of MmFile are in conflict by their return values. void[] opSlice(size_t i1, size_t i2) ubyte opIndex(size_t i) (And yet I still didn't get an idea what void[] means - vector of nothings? )My impression is that given that void[] is implicitly castable to any other array type, void[] means "vector of anythings".
Apr 04 2005
On Mon, 4 Apr 2005 22:39:24 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Not in D, IMO. Plus, consider "void *" how can it be a "pointer to nothing", it's actually a "pointer to anything" even in C/C++. Perhaps "void" was a bad choice of word.void is not anything. It is just nothing. http://dictionary.reference.com/search?q=voidThese two methods of MmFile are in conflict by their return values. void[] opSlice(size_t i1, size_t i2) ubyte opIndex(size_t i) (And yet I still didn't get an idea what void[] means - vector of nothings? )My impression is that given that void[] is implicitly castable to any other array type, void[] means "vector of anythings".See: static void[12] voids; What is voids.sizeof ?1 Set that way to allow void[] to work. And to allow any type to implicitly cast to void. eg. void foo(void[] a) {} void bar(byte[] a) {} void main() { char[] ca; uint[] ia; long[] la; foo(ca); //ok foo(ia); //ok foo(la); //ok bar(ca); //error bar(ia); //error bar(la); //error } It can be quite useful. Regan
Apr 04 2005
Not exactly. DMD does not allow this: static void[12] voids; - sizeof cannot be determined.void is not anything. It is just nothing. http://dictionary.reference.com/search?q=voidNot in D, IMO. Plus, consider "void *" how can it be a "pointer to nothing", it's actually a "pointer to anything" even in C/C++. Perhaps "void" was a bad choice of word.See: static void[12] voids; What is voids.sizeof ?1Set that way to allow void[] to work. And to allow any type to implicitly cast to void. eg. void foo(void[] a) {} void bar(byte[] a) {} void main() { char[] ca; uint[] ia; long[] la; foo(ca); //ok foo(ia); //ok foo(la); //ok bar(ca); //error bar(ia); //error bar(la); //error } It can be quite useful.I don't think thatlong[] la; foo(la); //okis useful. What void foo(void[] a) {} can do with a[] ? But all OS file functions accepts only bytes - addressible entities having strong physical meaning. But AFAIK there is no way to determine number of bytes in actual void[]. Andrew.
Apr 05 2005
On Tue, 5 Apr 2005 14:03:53 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote:Sorry, I miss read the question above. I thought you were asking what the size of a single void was. It appears that static void[12] voids is illegal. But, as you can see below void[] is not, it has a size (8) as it's an array reference, and it's elements void[0] have a size also (1). import std.stdio; void main() { //static void[12] voids; //error: integral constant must be scalar type, not void void[] voids; voids.length = 1; writefln(voids.sizeof); writefln(voids[0].sizeof); } Output: 8 1Not exactly. DMD does not allow this: static void[12] voids; - sizeof cannot be determined.void is not anything. It is just nothing. http://dictionary.reference.com/search?q=voidNot in D, IMO. Plus, consider "void *" how can it be a "pointer to nothing", it's actually a "pointer to anything" even in C/C++. Perhaps "void" was a bad choice of word.See: static void[12] voids; What is voids.sizeof ?1examine/edit each byte of each "anything" (in this case long) in the array. for any task requiring bytewise access to "anything".Set that way to allow void[] to work. And to allow any type to implicitly cast to void. eg. void foo(void[] a) {} void bar(byte[] a) {} void main() { char[] ca; uint[] ia; long[] la; foo(ca); //ok foo(ia); //ok foo(la); //ok bar(ca); //error bar(ia); //error bar(la); //error } It can be quite useful.I don't think thatlong[] la; foo(la); //okis useful. What void foo(void[] a) {} can do with a[] ?But all OS file functions accepts only bytes - addressible entities having strong physical meaning. But AFAIK there is no way to determine number of bytes in actual void[].void[] stores it's own length in bytes. If you pass long[] as void[] it correctly assigns the length of the void[] to encompass all the long[] data. So, void[] has a length and it is known, in D. Regan
Apr 05 2005
:) "each byte" or "each void" of "anything" ?I don't think thatexamine/edit each byte of each "anything" (in this case long) in the array. for any task requiring bytewise access to "anything".long[] la; foo(la); //okis useful. What void foo(void[] a) {} can do with a[] ?void[0] is what? void[0].sizeof shows that 'void' is in fact "third type of byte" :)But all OS file functions accepts only bytes - addressible entities having strong physical meaning. But AFAIK there is no way to determine number of bytes in actual void[].void[] stores it's own length in bytes. If you pass long[] as void[] it correctly assigns the length of the void[] to encompass all the long[] data. So, void[] has a length and it is known, in D.
Apr 05 2005
On Tue, 5 Apr 2005 16:55:38 -0700, Andrew Fedoniouk <news terrainformatica.com> wrote::) Sorry, badly worded. Each /byte sized/ part of "anything".:) "each byte" or "each void" of "anything" ?I don't think thatexamine/edit each byte of each "anything" (in this case long) in the array. for any task requiring bytewise access to "anything".long[] la; foo(la); //okis useful. What void foo(void[] a) {} can do with a[] ?A /byte sized/ part of "anything".void[0] is what?But all OS file functions accepts only bytes - addressible entities having strong physical meaning. But AFAIK there is no way to determine number of bytes in actual void[].void[] stores it's own length in bytes. If you pass long[] as void[] it correctly assigns the length of the void[] to encompass all the long[] data. So, void[] has a length and it is known, in D.void[0].sizeof shows that 'void' is in fact "third type of byte" :)It's similar to byte in that it's the same size. But I reckon D makes a slight distinction with it's implicit cast behaviour. This is my opinion and it's probably quite controversial: <opinion> A "byte" is a 8 bit long /self contained/ piece of memory, as in it's a complete /thing/ in 8 bits. Whereas a "void" from a void[] is an 8 bit long piece of memory, likely part of a whole /thing/. char, 8 bits, a whole UTF-8 codepoint (not a whole character). byte, 8 bits, a /thing/ which is contained in 8 bits. short, 16 bits, a /thing/ which is contained in 16 bits. int, 32 bits, a /thing/ which is contained in 32 bits. void, 8 bits, an 8 bit long part of "any/thing/". </opinion> Regan
Apr 05 2005
Regan Heath wrote:A "byte" is a 8 bit long /self contained/ piece of memory, as in it's a complete /thing/ in 8 bits. Whereas a "void" from a void[] is an 8 bit long piece of memory, likely part of a whole /thing/.One could think of void as being an address only. And since such don't need / can't know, what we imagine there being, then the size is 1. Actually, the size should be 0 to emphasize this, bat technically that would become cumbersome, since you most often itreate through ranges of voids. With size 0 there would have to be extra measures created in the compiler (and philosophy) to enable this iteration to actually move forward. So, for practical reasons, void is of size 1. Another way of putting it is, we do need occasionally to address memory without knowing/caring about the type of data there is. A byte being the smallest location traditionally addressable by programming languages, it is natural that "this smallest address-difference" is used as the "size of void".
Apr 05 2005
Andrew Fedoniouk wrote: <snip>MmFile, I think, shall have not public constructors. Instead it should have one static method: static MmFile open(pathname, openmode) {...} which does not throw any errors and returns just null if operation cannot be completed.<snip> No. What would be the point of having exceptions if we're going to go out of way not to use them? http://www.digitalmars.com/d/errors.html Stewart. -- My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Apr 05 2005