Re: (Noob question) Should subclasses be defined in separate modules?
On Friday, 13 January 2023 at 05:17:59 UTC, thebluepandabear wrote: (Sorry if this is a duplicate.) If I have the following code inside of a module: ```D class Obj { private { string name = "Hi"; } } class ObjDerived : Obj { } ``` Is it best practice to define `ObjDerived` inside another module, since `ObjDerived` can still access the members of `Obj` (since `private` is only applied to modules), or does this go against the intended use of the language? As a beginner, I am having an extremely tough time understanding why you would want to place these two classes in the same module or even have this intended behavior of `private`. I am coming from Java/Kotlin which are both strictly OO language and have different ways of encapsulation. The short answer: just think of a module as a way of grouping related objects and functions. If it makes sense to you for `ObjDerived` to have access to the internals of `Obj`, then keep them in the same module. If it doesn't, then put it somewhere else. The long answer: there's no one-size-fits all here. For a short program, a script let's say, just dump everything in one module and be done with it. For a program you're writing for your own use, do whatever you feel comfortable with, even if you plan to open source it. For something you're writing for others to use, like a library, then the first priority is to think about what the public facing API should look like. From that perspective, does `ObDerived` belong in the same module, or is it unrelated enough to go into a different one? If it does fit in the same module, then that can be enough. It is for me. I'd stop there. But some people want to go one step further and ensure that `ObjDerived` can't access the internals of `Obj`. So in that case, you can put them in two separate modules and make a `package.d` file to act as the common module name for both. I think there are good reasons to do that, but most of the time it's just a matter of preference.
(Noob question) Should subclasses be defined in separate modules?
(Sorry if this is a duplicate.) If I have the following code inside of a module: ```D class Obj { private { string name = "Hi"; } } class ObjDerived : Obj { } ``` Is it best practice to define `ObjDerived` inside another module, since `ObjDerived` can still access the members of `Obj` (since `private` is only applied to modules), or does this go against the intended use of the language? As a beginner, I am having an extremely tough time understanding why you would want to place these two classes in the same module or even have this intended behavior of `private`. I am coming from Java/Kotlin which are both strictly OO language and have different ways of encapsulation.
Re: Noob question about structs allocation
On Monday, 15 October 2018 at 04:14:24 UTC, IM wrote: What is the effect of calling destroy? - calling the destructor? - deallocating the memory? - both? It calls the destructor. The GC will deallocate the object's memory later. However, you need to be careful about how you use GC-allocated objects that have destructors. There's currently no built-in way to know when a destructor is called as part of the normal destruction process (a stack-based instance leaving its scope or a manual call to destroy) or when it's called as part of finalization, i.e. when the GC calls it. In D, we use the same destructor for both. I recommend you read these links: http://p0nce.github.io/d-idioms/#The-trouble-with-class-destructors http://p0nce.github.io/d-idioms/#GC-proof-resource-class The focus is on classes, but I think it's more important for structs. Classes are generally going to be used with default GC allocation, meaning their destructors are always finalzers. With a struct, it's not unrealistic to anticipate instances will be allocated on the stack, the non-GC heap, or the GC heap. In that case, the conflation of finalization and destruction is something you have to pay special attention to. If you don't, you can dig yourself an architectural hole that might not even be apparent until you're well and truly into it. Unfortunately, there's currently no direct means in the public API of distinguishing the two cases. The second link above demonstrates a workaround that makes it possible. While less than ideal, it's all we've got at the moment. I've got an unpublished blog post, the next in the GC series at the D blog, on hold right now because of this. I'm hoping we can get something done about it: https://issues.dlang.org/show_bug.cgi?id=17563
Re: Noob question about structs allocation
On Monday, 15 October 2018 at 04:14:24 UTC, IM wrote: What is the effect of calling destroy? - calling the destructor? - deallocating the memory? - both? IIRC, it only calls the destructor, the GC will decide when to deallocate the memory.
Re: Noob question about structs allocation
On Monday, 15 October 2018 at 03:33:04 UTC, Basile B. wrote: On Monday, 15 October 2018 at 03:19:07 UTC, IM wrote: I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have: struct S { int num; } Would allocating an instance on the heap using: S* s = new S; use the GC, or do we have to call destroy() or delete on s ourselves? new is an operator that always allocates using the GC, calling destroy yourself won't hurt either but is not necessary. What is the effect of calling destroy? - calling the destructor? - deallocating the memory? - both?
Re: Noob question about structs allocation
On Monday, 15 October 2018 at 03:19:07 UTC, IM wrote: I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have: struct S { int num; } Would allocating an instance on the heap using: S* s = new S; use the GC, or do we have to call destroy() or delete on s ourselves? new is an operator that always allocates using the GC, calling destroy yourself won't hurt either but is not necessary.
Noob question about structs allocation
I probably used to know the answer to this question, but it's been a long time since I last used D, and I don't remember. Suppose we have: struct S { int num; } Would allocating an instance on the heap using: S* s = new S; use the GC, or do we have to call destroy() or delete on s ourselves?
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 16:35:52 UTC, Eric wrote: There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Consider the following struct: struct Vector4 { @property float x() { return vec[0]; } . . @property void x(float _x) { vec[0] = _x } . . private: float[4] vec; } Here I like to use static array for storing components of vector because I want to use special operations on arrays while taking advantage of auto-vectorization if possible. In this case, it is very convenient to use properties.
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 18:14:29 UTC, Eric wrote: Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; This is basically what I suspected. But why write: @property int getValue() { return(value); } You should use nouns to name properties and verbs to name methods. D has optional parentheses, so you can write x=getValue; So @property is generally not needed except for the case when the method returns a delegate, which in its turn can be implicitly called, so there's an ambiguity, which @property was meant to solve (but AFAIK in the end it didn't). It also serves as a documentation, that the method should be viewed as a property. Initially optional parentheses were meant as an easy implementation of properties, and @property wasn't meant to exist until the ambiguity with the delegate was understood.
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 18:14:29 UTC, Eric wrote: Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; This is basically what I suspected. But why write: @property int getValue() { return(value); } When you could just have a public field: int value; That lets you set and get the value without the parens anyways? thanks, Eric It allows you to add extra logic on read/write, without breaking any user code.
Re: Really nooB question - @property
On 7/21/2014 3:14 AM, Eric wrote: Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; This is basically what I suspected. But why write: @property int getValue() { return(value); } When you could just have a public field: int value; That lets you set and get the value without the parens anyways? thanks, Eric In addition to what others have pointed out, it's useful for read-only values. You don't always want to allow clients to be able to set an objects members. --- This email is free from viruses and malware because avast! Antivirus protection is active. http://www.avast.com
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 16:35:52 UTC, Eric wrote: There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Thx. Eric I wondered the same: http://forum.dlang.org/thread/uskutitmqgdfjeusr...@forum.dlang.org
Re: Really nooB question - @property
On 07/20/2014 11:14 AM, Eric wrote: > >> Use @property when you want a pseudo-variable or something that might >> be conceptually considered a "property" of the object, i.e. to do this: >> >> auto blah = thing.someProperty; >> thing.someProperty = blahblah; > > This is basically what I suspected. But why > write: > > @property int getValue() { return(value); } > > When you could just have a public field: > > int value; > > That lets you set and get the value without the parens anyways? Freely setting a member makes sense only in limited cases where that member does not take any part in any invariant of the object. For example, if a Rectangle class has .length, .width, and .area, it would be an error to set either of them. Additionally, properties enable one to make it look like a type has such a member: struct Rectangle { // ... @property int area() { return length * width; } } Ali
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 16:35:52 UTC, Eric wrote: There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Thx. Eric Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; or struct myArray(T) { T[] arr; @property size_t memSize() { return arr.length * T.sizeof; } } Other than that, don't use it. Ordinary functions can be called without parenthesis anyway. Using those ideas you shouldn't run in to any surprises.
Re: Really nooB question - @property
On Sunday, 20 July 2014 at 17:59:07 UTC, John Colvin wrote: On Sunday, 20 July 2014 at 16:35:52 UTC, Eric wrote: There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Thx. Eric Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; or struct myArray(T) { T[] arr; @property size_t memSize() { return arr.length * T.sizeof; } } Other than that, don't use it. Ordinary functions can be called without parenthesis anyway. Using those ideas you shouldn't run in to any surprises. Oh, but don't expect the compiler to enforce this and please don't use the -property flag, it will only cause you pain.
Re: Really nooB question - @property
Use @property when you want a pseudo-variable or something that might be conceptually considered a "property" of the object, i.e. to do this: auto blah = thing.someProperty; thing.someProperty = blahblah; This is basically what I suspected. But why write: @property int getValue() { return(value); } When you could just have a public field: int value; That lets you set and get the value without the parens anyways? thanks, Eric
Really nooB question - @property
There are a lot of discussions in the forums about how @property should or could be implemented. But I can't seem to find anything that explains why or when I should use @property with the current compiler. Can anyone explain why and when I should use the @property tag? Thx. Eric
Re: noob question
thx sergey my example work correctly now :D
Re: noob question
Thu, 06 Aug 2009 10:56:33 -0400, lllTattoolll wrote: > hi Lars and thx for help. I fix a little the first problem, now I paste a > verion in english whit coment because i´m lost here. > the example is the same only this is in english for your compresion of my > problem. > > -- > code > - > > import std.stdio; > import std.string; > import std.c.stdio; > > void main() > { > > string _name, _lastname, _response; > int _age, _year, _birth; > _year = 2009; > > writef ("Name: "); > _name = readln().chomp; > > writef ("Lastname: "); > _lastname = readln().chomp; > > writefln ("Hello %s ", _name, _lastname ); /* here is my first > problem, dont show me the last name or show me in > two > lines ( this fix whit .chomp ) */ The format string must be "Hello %s %s" to display both operands. Or you can use writeln instead: writeln("Hello ", _name, " ", _lastname); > writefln ("Year of birth: "); > scanf ("%d", & _birth); You use scanf here. Scanf only reads the number, and leaves the symbol in the input stream. When you later call readln() it sees that from the previous question and exits immediately. You better use readln() everywhere: _birth = std.conv.to!int(readln().chomp); > _age = _year - _birth; > > writefln ("Your age is %d? \t YES \t NO", _age ); /* here is my second > problem, can´t into the response and program*/ > _response = readln();/* show me > else line always */ > > if ( chomp(_response) == "yes") > writefln ("thank you %s", _name ); > else > writefln ("Sorry %s you have %d", _name, _age - 1 ); /* this line > always show me because can´t validate _response */ > } The rest seems to work correctly.
Re: noob question
Reply to llltattoolll, writefln ("Your age is %d? \t YES \t NO", _age ); /* here is my second problem, can´t into the response and program*/ _response = readln(); /* show me else line always */ // if all else fails, what are you getting writef(">>%s<<\n", cast(ubyte[])chomp(_response)); // might it be a case error? "YES" vs. "yes"? if ( chomp(_response) == "yes") writefln ("thank you %s", _name ); else writefln ("Sorry %s you have %d", _name, _age - 1 ); /* this line always show me because can´t validate _response */
Re: noob question
hi Lars and thx for help. I fix a little the first problem, now I paste a verion in english whit coment because i´m lost here. the example is the same only this is in english for your compresion of my problem. -- code - import std.stdio; import std.string; import std.c.stdio; void main() { string _name, _lastname, _response; int _age, _year, _birth; _year = 2009; writef ("Name: "); _name = readln().chomp; writef ("Lastname: "); _lastname = readln().chomp; writefln ("Hello %s ", _name, _lastname ); /* here is my first problem, dont show me the last name or show me in two lines ( this fix whit .chomp ) */ writefln ("Year of birth: "); scanf ("%d", & _birth); _age = _year - _birth; writefln ("Your age is %d? \t YES \t NO", _age ); /* here is my second problem, can´t into the response and program*/ _response = readln();/* show me else line always */ if ( chomp(_response) == "yes") writefln ("thank you %s", _name ); else writefln ("Sorry %s you have %d", _name, _age - 1 ); /* this line always show me because can´t validate _response */ } Lars T. Kyllingstad Wrote: > Lars T. Kyllingstad wrote: > > llltattoolll wrote: > >> hi im noob here and try learn D language, i try make this example but > >> when run have 2 problems. > >> > >> 1) when i show name and lastname show me in two lines and i wanna make > >> in the same line. > >> 2) can´t validate option si ( yes ) or no ( no ) and always show the > >> else line. > >> > >> what happend? > >> thx > >> > >> -- > >> code > >> -- > >> import std.stdio; > >> import std.string; > >> import std.c.stdio; > >> > >> > >> > >> void main() > >> { > >> > >> string _nombre, _apellido, _respuesta; > >> int _edad, _año, _nacimiento; > >> _año = 2009; > >> > >> writefln ("Escribe tu nombre: "); > >> _nombre = readln(); > >> > >> writefln ("Escribe tu apellido: "); > >> _apellido = readln(); > >> > >> writefln ("Hola %s ", _nombre ~= _apellido); > >> > >> writefln ("Ingresa el año de tu nacimiento: "); > >> scanf ("%d", & _nacimiento); > >> > >> _edad = _año - _nacimiento; > >> > >> writefln ("Tu edad es %d? \t SI \t NO", _edad); > >> _respuesta = readln(); > >> > >> if ( _respuesta == "si") > >> writeln ("Muchas gracias %s", _nombre ); > >> else > >> writeln ("Lo siento %s entonces tienes %d", _nombre, _edad - 1 ); > >> } > >> > > > > > > Hello, > > > > I think std.stdio.readln() includes the trailing newline. Try this: > > > > if ( chomp(_respuesta) == "si") > > > > The std.string.chomp() function removes trailing CR and LF characters. > > > > -Lars > > > I didn't notice your first question, but the answer is the same. To > solve both problems, you can do this instead: > >... >_nombre = chomp(readln()); >... >_apellido = chomp(readln()); >... > > Also, some people prefer this syntax, which is equivalent: > >_nombre = readln().chomp; >... > > -Lars
Re: noob question
Lars T. Kyllingstad wrote: llltattoolll wrote: hi im noob here and try learn D language, i try make this example but when run have 2 problems. 1) when i show name and lastname show me in two lines and i wanna make in the same line. 2) can´t validate option si ( yes ) or no ( no ) and always show the else line. what happend? thx -- code -- import std.stdio; import std.string; import std.c.stdio; void main() { string _nombre, _apellido, _respuesta; int _edad, _año, _nacimiento; _año = 2009; writefln ("Escribe tu nombre: "); _nombre = readln(); writefln ("Escribe tu apellido: "); _apellido = readln(); writefln ("Hola %s ", _nombre ~= _apellido); writefln ("Ingresa el año de tu nacimiento: "); scanf ("%d", & _nacimiento); _edad = _año - _nacimiento; writefln ("Tu edad es %d? \t SI \t NO", _edad); _respuesta = readln(); if ( _respuesta == "si") writeln ("Muchas gracias %s", _nombre ); else writeln ("Lo siento %s entonces tienes %d", _nombre, _edad - 1 ); } Hello, I think std.stdio.readln() includes the trailing newline. Try this: if ( chomp(_respuesta) == "si") The std.string.chomp() function removes trailing CR and LF characters. -Lars I didn't notice your first question, but the answer is the same. To solve both problems, you can do this instead: ... _nombre = chomp(readln()); ... _apellido = chomp(readln()); ... Also, some people prefer this syntax, which is equivalent: _nombre = readln().chomp; ... -Lars
Re: noob question
llltattoolll wrote: hi im noob here and try learn D language, i try make this example but when run have 2 problems. 1) when i show name and lastname show me in two lines and i wanna make in the same line. 2) can´t validate option si ( yes ) or no ( no ) and always show the else line. what happend? thx -- code -- import std.stdio; import std.string; import std.c.stdio; void main() { string _nombre, _apellido, _respuesta; int _edad, _año, _nacimiento; _año = 2009; writefln ("Escribe tu nombre: "); _nombre = readln(); writefln ("Escribe tu apellido: "); _apellido = readln(); writefln ("Hola %s ", _nombre ~= _apellido); writefln ("Ingresa el año de tu nacimiento: "); scanf ("%d", & _nacimiento); _edad = _año - _nacimiento; writefln ("Tu edad es %d? \t SI \t NO", _edad); _respuesta = readln(); if ( _respuesta == "si") writeln ("Muchas gracias %s", _nombre ); else writeln ("Lo siento %s entonces tienes %d", _nombre, _edad - 1 ); } Hello, I think std.stdio.readln() includes the trailing newline. Try this: if ( chomp(_respuesta) == "si") The std.string.chomp() function removes trailing CR and LF characters. -Lars
noob question
hi im noob here and try learn D language, i try make this example but when run have 2 problems. 1) when i show name and lastname show me in two lines and i wanna make in the same line. 2) can´t validate option si ( yes ) or no ( no ) and always show the else line. what happend? thx -- code -- import std.stdio; import std.string; import std.c.stdio; void main() { string _nombre, _apellido, _respuesta; int _edad, _año, _nacimiento; _año = 2009; writefln ("Escribe tu nombre: "); _nombre = readln(); writefln ("Escribe tu apellido: "); _apellido = readln(); writefln ("Hola %s ", _nombre ~= _apellido); writefln ("Ingresa el año de tu nacimiento: "); scanf ("%d", & _nacimiento); _edad = _año - _nacimiento; writefln ("Tu edad es %d? \t SI \t NO", _edad); _respuesta = readln(); if ( _respuesta == "si") writeln ("Muchas gracias %s", _nombre ); else writeln ("Lo siento %s entonces tienes %d", _nombre, _edad - 1 ); }