|
View:
New views
10 Messages
—
Rating Filter:
Alert me
|
|
|
Unexpected results when adding & removing fields to empty structs<Apologies if the issues below are just ignorance or stupidity on my part)
<System: Octave 3.2.3 MingW (sourceforge binary), Windows XP SP3> Adding fields to empty structs doesn't seem to work: octave-3.2.3.exe: #1 > aa = struct("field1", {}) aa = { 0x0 struct array containing the fields: field1 } octave-3.2.3.exe: #2 > [aa.field2] = {} aa = { 0x0 struct array containing the fields: field1 } ===> No field2 to be seen in struct aa (This works OK on Matlab r2007a, if that's any reference :-) ) .....while..... octave-3.2.3.exe: #3 > cc = struct("field1", {}) cc = { 0x0 struct array containing the fields: field1 } octave-3.2.3.exe: #4 > [cc(1).field2]= {} cc = { field1 = [](0x0) field2 = {}(0x0) } but now the fields contain (empty) values. Note that field1 has been "extended" with [] rather than {}. I suppose this last example is intended behavior as adding elements to all fields in a struct (extending the "field size") always goes like (at least on my box) struct(size(struct, 2) + 1).a_field = {anything} where field1 was initially empty (zero size) but an (empty) element was added implicitly due to the operation of adding another field. But: octave-3.2.3.exe: #5 > [cc.field3]= {} cc = { field1 = [](0x0) field2 = {}(0x0) field3 = {}(0x0) } octave-3.2.3.exe: #7 > [cc(1).field4]= {} cc = { field1 = [](0x0) field2 = {}(0x0) field3 = {}(0x0) field4 = {}(0x0) } where the layout seems to be mixed up. Furthermore, continuing with cc: octave-3.2.3.exe: #8 > rmfield(cc, "field3") ans = { field1 = [](0x0) field2 = {}(0x0) field4 = {}(0x0) } octave-3.2.3.exe: #9 > rmfield(cc, "field2") ans = { field1 = [](0x0) field3 = {}(0x0) field4 = {}(0x0) } octave-3.2.3.exe: #10 > rmfield(cc, "field3") ans = { field1 = [](0x0) field2 = {}(0x0) field4 = {}(0x0) } where "field3" and "field2" magically but unintendedly reappear. On a related note (empty lines skipped for brevity): octave-3.2.3.exe: #93 > AA = struct() AA = { } octave-3.2.3.exe: #94 > size (AA) ans = 1 1 ## ?? octave-3.2.3.exe: #95 > isempty (AA) ans = 0 ## !! but in line with size(aa) === while ==== octave-3.2.3.exe: #96 > BB = struct("field1", {}) BB = { 0x0 struct array containing the fields: field1 } octave-3.2.3.exe: #97 > size (BB) ans = 0 0 ## !? octave-3.2.3.exe: #98 > isempty (BB) ans = 1 ## ?! again in line with size(bb) The results of size() and isempty() on AA and BB are IMO contrary to expectation. (But... fully Matlab r2007a-compatible!) Is this somehow logical (but beyond my sense for logic) or is it too far pursued Matlab compatibility? Thank you, Philip _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn Thu, Nov 5, 2009 at 11:22 PM, Philip Nienhuis <pr.nienhuis@...> wrote:
> <Apologies if the issues below are just ignorance or stupidity on my part) > > <System: Octave 3.2.3 MingW (sourceforge binary), Windows XP SP3> > > Adding fields to empty structs doesn't seem to work: > > octave-3.2.3.exe: #1 > aa = struct("field1", {}) > aa = > { > 0x0 struct array containing the fields: > > field1 > } > > octave-3.2.3.exe: #2 > [aa.field2] = {} > aa = > { > 0x0 struct array containing the fields: > > field1 > } > > ===> No field2 to be seen in struct aa > (This works OK on Matlab r2007a, if that's any reference :-) ) > [aa.field2] when aa is sempty resolves to an empty cs-list, so there's nothing to assign (excess rhs values are discarded). Apparently Matlab carries out the empty assignments for possible side effects, while Octave simply skips them. For compatibility, here's a patch: > .....while..... > > octave-3.2.3.exe: #3 > cc = struct("field1", {}) > cc = > { > 0x0 struct array containing the fields: > > field1 > } > > octave-3.2.3.exe: #4 > [cc(1).field2]= {} > cc = > { > field1 = [](0x0) > field2 = {}(0x0) > } > > but now the fields contain (empty) values. Note that field1 has been > "extended" with [] rather than {}. > I suppose this last example is intended behavior as adding elements to > all fields in a struct (extending the "field size") always goes like (at > least on my box) > struct(size(struct, 2) + 1).a_field = {anything} > where field1 was initially empty (zero size) but an (empty) element was > added implicitly due to the operation of adding another field. > Yep, that is correct. > But: > > octave-3.2.3.exe: #5 > [cc.field3]= {} > cc = > { > field1 = [](0x0) > field2 = {}(0x0) > field3 = {}(0x0) > } > > octave-3.2.3.exe: #7 > [cc(1).field4]= {} > cc = > { > field1 = [](0x0) > field2 = {}(0x0) > field3 = {}(0x0) > field4 = {}(0x0) > } > > where the layout seems to be mixed up. Another bug. See > Furthermore, continuing with cc: > > octave-3.2.3.exe: #8 > rmfield(cc, "field3") > ans = > { > field1 = [](0x0) > field2 = {}(0x0) > field4 = {}(0x0) > } > > octave-3.2.3.exe: #9 > rmfield(cc, "field2") > ans = > { > field1 = [](0x0) > field3 = {}(0x0) > field4 = {}(0x0) > } > > octave-3.2.3.exe: #10 > rmfield(cc, "field3") > ans = > { > field1 = [](0x0) > field2 = {}(0x0) > field4 = {}(0x0) > } > where "field3" and "field2" magically but unintendedly reappear. > This is a mix-up of the "your ignorance" case and Octave's sometimes too succint documentation. While the docstring for rmfield might give you the impression that rmfield(cc, "field3") removes the field3 from cc, but this is not true. Remember (and this is written in the manual) that Octave functions, be them built-in or user scripts, *never* alter their arguments. There is no passing by reference. When you pass a variable as a function argument, it behaves *as if* a copy was made for all the values (in reality it's a lazy copy). This very simple and natural scheme frees the Matlab language of the object ownership problems seen, for instance, in Python or C#, at the cost of sometimes sacrificing memory efficiency. rmfield does, in fact take a copy of the argument, remove the named field from that copy and return the result, so cc = rmfield (cc, "field3"); is what you want. In the docstrings this is often not emphasized because it's assumed to be a general principle. > > On a related note (empty lines skipped for brevity): > > octave-3.2.3.exe: #93 > AA = struct() > AA = > { > } > octave-3.2.3.exe: #94 > size (AA) > ans = > 1 1 ## ?? > octave-3.2.3.exe: #95 > isempty (AA) > ans = 0 ## !! but in line with size(aa) > > === while ==== > > octave-3.2.3.exe: #96 > BB = struct("field1", {}) > BB = > { > 0x0 struct array containing the fields: > field1 > } > octave-3.2.3.exe: #97 > size (BB) > ans = > 0 0 ## !? > octave-3.2.3.exe: #98 > isempty (BB) > ans = 1 ## ?! again in line with size(bb) > > The results of size() and isempty() on AA and BB are IMO contrary to > expectation. (But... fully Matlab r2007a-compatible!) > > Is this somehow logical (but beyond my sense for logic) or is it too far > pursued Matlab compatibility? > It's logical. isempty simply tests whether any dimension is zero; it doesn't test for the number of fields. Structs with no fields are not much useful anyway, so I'd expect them to be very rare. > > Thank you, > > Philip > _______________________________________________ > Bug-octave mailing list > Bug-octave@... > https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave > -- RNDr. Jaroslav Hajek computing expert & GNU Octave developer Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic url: www.highegg.matfyz.cz _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn Fri, Nov 6, 2009 at 10:31 AM, Jaroslav Hajek <highegg@...> wrote:
> On Thu, Nov 5, 2009 at 11:22 PM, Philip Nienhuis <pr.nienhuis@...> wrote: >> <Apologies if the issues below are just ignorance or stupidity on my part) >> >> <System: Octave 3.2.3 MingW (sourceforge binary), Windows XP SP3> >> >> Adding fields to empty structs doesn't seem to work: >> >> octave-3.2.3.exe: #1 > aa = struct("field1", {}) >> aa = >> { >> 0x0 struct array containing the fields: >> >> field1 >> } >> >> octave-3.2.3.exe: #2 > [aa.field2] = {} >> aa = >> { >> 0x0 struct array containing the fields: >> >> field1 >> } >> >> ===> No field2 to be seen in struct aa >> (This works OK on Matlab r2007a, if that's any reference :-) ) >> > > [aa.field2] when aa is sempty resolves to an empty cs-list, so there's > nothing to assign (excess rhs values are discarded). Apparently Matlab > carries out the empty assignments for possible side effects, while > Octave simply skips them. For compatibility, here's a patch: > >> .....while..... >> >> octave-3.2.3.exe: #3 > cc = struct("field1", {}) >> cc = >> { >> 0x0 struct array containing the fields: >> >> field1 >> } >> >> octave-3.2.3.exe: #4 > [cc(1).field2]= {} >> cc = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> } >> >> but now the fields contain (empty) values. Note that field1 has been >> "extended" with [] rather than {}. >> I suppose this last example is intended behavior as adding elements to >> all fields in a struct (extending the "field size") always goes like (at >> least on my box) >> struct(size(struct, 2) + 1).a_field = {anything} >> where field1 was initially empty (zero size) but an (empty) element was >> added implicitly due to the operation of adding another field. >> > > Yep, that is correct. > >> But: >> >> octave-3.2.3.exe: #5 > [cc.field3]= {} >> cc = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> field3 = {}(0x0) >> } >> >> octave-3.2.3.exe: #7 > [cc(1).field4]= {} >> cc = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> field3 = {}(0x0) >> field4 = {}(0x0) >> } >> >> where the layout seems to be mixed up. > > Another bug. > See > > >> Furthermore, continuing with cc: >> >> octave-3.2.3.exe: #8 > rmfield(cc, "field3") >> ans = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> field4 = {}(0x0) >> } >> >> octave-3.2.3.exe: #9 > rmfield(cc, "field2") >> ans = >> { >> field1 = [](0x0) >> field3 = {}(0x0) >> field4 = {}(0x0) >> } >> >> octave-3.2.3.exe: #10 > rmfield(cc, "field3") >> ans = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> field4 = {}(0x0) >> } >> where "field3" and "field2" magically but unintendedly reappear. >> > > This is a mix-up of the "your ignorance" case and Octave's sometimes > too succint documentation. While the docstring for rmfield might give > you the impression that > rmfield(cc, "field3") > removes the field3 from cc, but this is not true. Remember (and this > is written in the manual) that Octave functions, be them built-in or > user scripts, *never* alter their arguments. There is no passing by > reference. When you pass a variable as a function argument, it behaves > *as if* a copy was made for all the values (in reality it's a lazy > copy). This very simple and natural scheme frees the Matlab language > of the object ownership problems seen, for instance, in Python or C#, > at the cost of sometimes sacrificing memory efficiency. > > rmfield does, in fact take a copy of the argument, remove the named > field from that copy and return the result, so > cc = rmfield (cc, "field3"); > is what you want. In the docstrings this is often not emphasized > because it's assumed to be a general principle. > >> >> On a related note (empty lines skipped for brevity): >> >> octave-3.2.3.exe: #93 > AA = struct() >> AA = >> { >> } >> octave-3.2.3.exe: #94 > size (AA) >> ans = >> 1 1 ## ?? >> octave-3.2.3.exe: #95 > isempty (AA) >> ans = 0 ## !! but in line with size(aa) >> >> === while ==== >> >> octave-3.2.3.exe: #96 > BB = struct("field1", {}) >> BB = >> { >> 0x0 struct array containing the fields: >> field1 >> } >> octave-3.2.3.exe: #97 > size (BB) >> ans = >> 0 0 ## !? >> octave-3.2.3.exe: #98 > isempty (BB) >> ans = 1 ## ?! again in line with size(bb) >> >> The results of size() and isempty() on AA and BB are IMO contrary to >> expectation. (But... fully Matlab r2007a-compatible!) >> >> Is this somehow logical (but beyond my sense for logic) or is it too far >> pursued Matlab compatibility? >> > > It's logical. isempty simply tests whether any dimension is zero; it > doesn't test for the number of fields. Structs with no fields are not > much useful anyway, so I'd expect them to be very rare. > >> >> Thank you, >> >> Philip >> _______________________________________________ >> Bug-octave mailing list >> Bug-octave@... >> https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave >> > > > > -- > RNDr. Jaroslav Hajek > computing expert & GNU Octave developer > Aeronautical Research and Test Institute (VZLU) > Prague, Czech Republic > url: www.highegg.matfyz.cz > Oops, I forgot to hyperlink the patches: http://hg.savannah.gnu.org/hgweb/octave/rev/eead00a7df05 http://hg.savannah.gnu.org/hgweb/octave/rev/ea88eece12f5 regards -- RNDr. Jaroslav Hajek computing expert & GNU Octave developer Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic url: www.highegg.matfyz.cz _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsJaroslav Hajek wrote:
> On Thu, Nov 5, 2009 at 11:22 PM, Philip Nienhuis <pr.nienhuis@...> wrote: >> <Apologies if the issues below are just ignorance or stupidity on my part) >> >> <System: Octave 3.2.3 MingW (sourceforge binary), Windows XP SP3> >> >> Adding fields to empty structs doesn't seem to work: >> >> octave-3.2.3.exe: #1 > aa = struct("field1", {}) >> aa = >> { >> 0x0 struct array containing the fields: >> >> field1 >> } >> >> octave-3.2.3.exe: #2 > [aa.field2] = {} >> aa = >> { >> 0x0 struct array containing the fields: >> >> field1 >> } >> >> ===> No field2 to be seen in struct aa : <snip> : > [aa.field2] when aa is sempty resolves to an empty cs-list, so there's > nothing to assign (excess rhs values are discarded). Apparently Matlab > carries out the empty assignments for possible side effects, while > Octave simply skips them. For compatibility, here's a patch: Thank you. <snip> : >> octave-3.2.3.exe: #9 > rmfield(cc, "field2") >> ans = >> { >> field1 = [](0x0) >> field3 = {}(0x0) >> field4 = {}(0x0) >> } >> >> octave-3.2.3.exe: #10 > rmfield(cc, "field3") >> ans = >> { >> field1 = [](0x0) >> field2 = {}(0x0) >> field4 = {}(0x0) >> } >> where "field3" and "field2" magically but unintendedly reappear. >> > > This is a mix-up of the "your ignorance" case and Octave's sometimes > too succint documentation. While the docstring for rmfield might give > you the impression that > rmfield(cc, "field3") > removes the field3 from cc, but this is not true. Remember (and this > is written in the manual) that Octave functions, be them built-in or > user scripts, *never* alter their arguments. There is no passing by > reference. When you pass a variable as a function argument, it behaves > *as if* a copy was made for all the values (in reality it's a lazy > copy). This very simple and natural scheme frees the Matlab language > of the object ownership problems seen, for instance, in Python or C#, > at the cost of sometimes sacrificing memory efficiency. > > rmfield does, in fact take a copy of the argument, remove the named > field from that copy and return the result, so > cc = rmfield (cc, "field3"); > is what you want. In the docstrings this is often not emphasized > because it's assumed to be a general principle. <blush> Yeah I should have realized this, sorry. I might have been distracted because removing fields from structures works through a function rmfield(), while adding fields only works through assignment [struct(:).newfield] = deal({cells}{:}) which does change the original. Part of my original bug report was motivated by all kind of corner cases with empty structs. To avoid having to repeatedly beware & take care of such cases I've created a script around this for my own use, because invoking something like: new_s = addfield (old_s, "nfield", [optional values]) is IMO a little more obvious than the assignment syntax above + variants for exceptions. BTW if anyone thinks such a script is useful for other octave users I'll happily contribute it (here or for octave-forge) > >> On a related note (empty lines skipped for brevity): >> >> octave-3.2.3.exe: #93 > AA = struct() >> AA = >> { >> } >> octave-3.2.3.exe: #96 > BB = struct("field1", {}) : <snip> >> BB = >> { >> 0x0 struct array containing the fields: >> field1 >> } : <snip> >> The results of size() and isempty() on AA and BB are IMO contrary to >> expectation. (But... fully Matlab r2007a-compatible!) >> >> Is this somehow logical (but beyond my sense for logic) or is it too far >> pursued Matlab compatibility? >> > > It's logical. isempty simply tests whether any dimension is zero; it > doesn't test for the number of fields. Structs with no fields are not > much useful anyway, so I'd expect them to be very rare. (How does size()work in such a case? that one seems to convey the wrong info to isempty) ) Well, it's logical in the sense of "how octave works internally". Still I think it's a bit inconsistent from a user's point of view. A struct with no fields has "no dimensions" to test at all so should be reported "empty" with size 0. IMO, of course :-) Indeed such structs may not be that useful per se, but I can think of automated scripts that could generate them and use them later on; I think from an efficiency perspective such scripts should be saved from having to test for too many corner cases, especially far-fetched ones. To that end, behavior of operations like size() and isempty() should be as consistent as reasonably possible. But assigning extra burden to very-often-used functions for the sake of some rarely encountered cases might not be very sensible either. And -again- Matlab (used preferrably at my employer's office) doesn't do any better in this case. Anyway, thank you for your answer & patches. As I'm not in core octave development I suppose I'll have to wait until a next stable binary :-( (but I'm glad some stuff is solved already). Philip _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn Fri, Nov 6, 2009 at 9:56 PM, Philip Nienhuis <pr.nienhuis@...> wrote:
> Jaroslav Hajek wrote: >> On Thu, Nov 5, 2009 at 11:22 PM, Philip Nienhuis <pr.nienhuis@...> wrote: >>> <Apologies if the issues below are just ignorance or stupidity on my part) >>> >>> <System: Octave 3.2.3 MingW (sourceforge binary), Windows XP SP3> >>> >>> Adding fields to empty structs doesn't seem to work: >>> >>> octave-3.2.3.exe: #1 > aa = struct("field1", {}) > >> aa = > >> { > >> 0x0 struct array containing the fields: > >> > >> field1 > >> } > >> > >> octave-3.2.3.exe: #2 > [aa.field2] = {} > >> aa = > >> { > >> 0x0 struct array containing the fields: > >> > >> field1 > >> } > >> > >> ===> No field2 to be seen in struct aa > : > <snip> > : >> [aa.field2] when aa is sempty resolves to an empty cs-list, so there's >> nothing to assign (excess rhs values are discarded). Apparently Matlab >> carries out the empty assignments for possible side effects, while >> Octave simply skips them. For compatibility, here's a patch: > > Thank you. > > <snip> > : >>> octave-3.2.3.exe: #9 > rmfield(cc, "field2") >>> ans = >>> { >>> field1 = [](0x0) >>> field3 = {}(0x0) >>> field4 = {}(0x0) >>> } >>> >>> octave-3.2.3.exe: #10 > rmfield(cc, "field3") >>> ans = >>> { >>> field1 = [](0x0) >>> field2 = {}(0x0) >>> field4 = {}(0x0) >>> } >>> where "field3" and "field2" magically but unintendedly reappear. >>> >> >> This is a mix-up of the "your ignorance" case and Octave's sometimes >> too succint documentation. While the docstring for rmfield might give >> you the impression that >> rmfield(cc, "field3") >> removes the field3 from cc, but this is not true. Remember (and this >> is written in the manual) that Octave functions, be them built-in or >> user scripts, *never* alter their arguments. There is no passing by >> reference. When you pass a variable as a function argument, it behaves >> *as if* a copy was made for all the values (in reality it's a lazy >> copy). This very simple and natural scheme frees the Matlab language >> of the object ownership problems seen, for instance, in Python or C#, >> at the cost of sometimes sacrificing memory efficiency. >> >> rmfield does, in fact take a copy of the argument, remove the named >> field from that copy and return the result, so >> cc = rmfield (cc, "field3"); >> is what you want. In the docstrings this is often not emphasized >> because it's assumed to be a general principle. > > <blush> Yeah I should have realized this, sorry. > I might have been distracted because removing fields from structures > works through a function rmfield(), while adding fields only works > through assignment > [struct(:).newfield] = deal({cells}{:}) > which does change the original. > Part of my original bug report was motivated by all kind of corner cases > with empty structs. To avoid having to repeatedly beware & take care of > such cases I've created a script around this for my own use, because > invoking something like: > > new_s = addfield (old_s, "nfield", [optional values]) > > is IMO a little more obvious than the assignment syntax above + variants > for exceptions. > How would that differ from setfield? > BTW if anyone thinks such a script is useful for other octave users I'll > happily contribute it (here or for octave-forge) > >> >>> On a related note (empty lines skipped for brevity): >>> >>> octave-3.2.3.exe: #93 > AA = struct() >>> AA = >>> { >>> } >>> octave-3.2.3.exe: #96 > BB = struct("field1", {}) > : > <snip> >>> BB = >>> { >>> 0x0 struct array containing the fields: >>> field1 >>> } > : > <snip> >>> The results of size() and isempty() on AA and BB are IMO contrary to >>> expectation. (But... fully Matlab r2007a-compatible!) >>> >>> Is this somehow logical (but beyond my sense for logic) or is it too far >>> pursued Matlab compatibility? >>> >> >> It's logical. isempty simply tests whether any dimension is zero; it >> doesn't test for the number of fields. Structs with no fields are not >> much useful anyway, so I'd expect them to be very rare. > > (How does size()work in such a case? that one seems to convey the wrong > info to isempty) ) > Well, it's logical in the sense of "how octave works internally". Still > I think it's a bit inconsistent from a user's point of view. A struct > with no fields has "no dimensions" to test at all so should be reported > "empty" with size 0. IMO, of course :-) > No, that is not true. The number of fields is simply an independent property of the structure. You may also think of it as an extra dimension. You can have structs with no fields but arbitrary dimensions. Admittedly, what is really missing is a function to query the number of fields, say, nfields (s). Currently one needs length (fieldnames (s)). > Indeed such structs may not be that useful per se, but I can think of > automated scripts that could generate them and use them later on; I > think from an efficiency perspective such scripts should be saved from > having to test for too many corner cases, especially far-fetched ones. > To that end, behavior of operations like size() and isempty() should be > as consistent as reasonably possible. Agreed. I think right now, it's quite consistent. > But assigning extra burden to very-often-used functions for the sake of > some rarely encountered cases might not be very sensible either. > > And -again- Matlab (used preferrably at my employer's office) doesn't do > any better in this case. > > Anyway, thank you for your answer & patches. > As I'm not in core octave development I suppose I'll have to wait until > a next stable binary :-( (but I'm glad some stuff is solved already). > Surely you don't *have to* wait - you can download the sources right now and build Octave from them. http://hg.savannah.gnu.org/hgweb/octave Honestly, setting up the build with all dependency libs is a non-trivial task (at least if you want full functionality), but once done, you can get new patches included very easily. best regards -- RNDr. Jaroslav Hajek computing expert & GNU Octave developer Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic url: www.highegg.matfyz.cz _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structs(sorry for late response, my provider's email server was down for some days)
Jaroslav Hajek wrote: > On Fri, Nov 6, 2009 at 9:56 PM, Philip Nienhuis <pr.nienhuis@...> wrote: >> Jaroslav Hajek wrote: >>> On Thu, Nov 5, 2009 at 11:22 PM, Philip Nienhuis <pr.nienhuis@...> wrote: >>>> <Apologies if the issues below are just ignorance or stupidity on my part) : <long snip> >>> This is a mix-up of the "your ignorance" case and Octave's sometimes >>> too succint documentation. While the docstring for rmfield might give >>> you the impression that >>> rmfield(cc, "field3") >>> removes the field3 from cc, but this is not true. Remember (and this >>> is written in the manual) that Octave functions, be them built-in or >>> user scripts, *never* alter their arguments. There is no passing by >>> reference. When you pass a variable as a function argument, it behaves >>> *as if* a copy was made for all the values (in reality it's a lazy >>> copy). This very simple and natural scheme frees the Matlab language >>> of the object ownership problems seen, for instance, in Python or C#, >>> at the cost of sometimes sacrificing memory efficiency. >>> >>> rmfield does, in fact take a copy of the argument, remove the named >>> field from that copy and return the result, so >>> cc = rmfield (cc, "field3"); >>> is what you want. In the docstrings this is often not emphasized >>> because it's assumed to be a general principle. >> <blush> Yeah I should have realized this, sorry. >> I might have been distracted because removing fields from structures >> works through a function rmfield(), while adding fields only works >> through assignment >> [struct(:).newfield] = deal({cells}{:}) >> which does change the original. >> Part of my original bug report was motivated by all kind of corner cases >> with empty structs. To avoid having to repeatedly beware & take care of >> such cases I've created a script around this for my own use, because >> invoking something like: >> >> new_s = addfield (old_s, "nfield", [optional values]) >> >> is IMO a little more obvious than the assignment syntax above + variants >> for exceptions. >> > > How would that differ from setfield? * AFAICS & test, setfield() seems intended for assigning a value to individual field elements, but only one element at a time (= per call). Unless of course I again overlooked something. This becomes cumbersome if one wants to add a somewhat larger array to all field elements in a struct. * (A wrapper script around) [s.f] = deal({cell_values}) assigns values to all elements of a field in one swoop and can add fields too. But yes, some fine-grainedness might be lost. * And I think setfield's syntax isn't that obvious either; that is, the help text could be more helpful. A suggestion for an IMO more easily comprehensible example is attached - just fit it in between the function call description and the example. If you'd prefer I can send setfield.m with improved help section. (You're right about sometimes too succinct octave docs. Admittedly only after checking out Matlab's helpdesk it occurred to me how setfield works. Hopefully my little addition may help others to avoid such a surrender.) <snip> >>>> On a related note (empty lines skipped for brevity): >>>> >>>> octave-3.2.3.exe: #93 > AA = struct() >>>> AA = >>>> { >>>> } >>>> octave-3.2.3.exe: #96 > BB = struct("field1", {}) >> : >> <snip> >>>> BB = >>>> { >>>> 0x0 struct array containing the fields: >>>> field1 >>>> } >> : >> <snip> >>>> The results of size() and isempty() on AA and BB are IMO contrary to >>>> expectation. (But... fully Matlab r2007a-compatible!) >>>> >>>> Is this somehow logical (but beyond my sense for logic) or is it too far >>>> pursued Matlab compatibility? >>>> >>> It's logical. isempty simply tests whether any dimension is zero; it >>> doesn't test for the number of fields. Structs with no fields are not >>> much useful anyway, so I'd expect them to be very rare. >> (How does size()work in such a case? that one seems to convey the wrong >> info to isempty) ) ? >> Well, it's logical in the sense of "how octave works internally". Still >> I think it's a bit inconsistent from a user's point of view. A struct >> with no fields has "no dimensions" to test at all so should be reported >> "empty" with size 0. IMO, of course :-) >> > > No, that is not true. The number of fields is simply an independent > property of the structure. You may also think of it as an extra > dimension. You can have structs with no fields but arbitrary > dimensions. Admittedly, what is really missing is a function to query > the number of fields, say, nfields (s). Currently one needs length > (fieldnames (s)). I was thinking more of size(s) yielding misleading info about empty structs - perhaps because size(s) itself gets confused there. Again, matlab does the same so why worry... <snip> >> As I'm not in core octave development I suppose I'll have to wait until >> a next stable binary :-( (but I'm glad some stuff is solved already). >> > > Surely you don't *have to* wait - you can download the sources right > now and build Octave from them. > http://hg.savannah.gnu.org/hgweb/octave > > Honestly, setting up the build with all dependency libs is a > non-trivial task (at least if you want full functionality), but once > done, you can get new patches included very easily. Sure, I've done that for some time several years ago under linux and cygwin. However nowadays I'm mostly confined to Windows so I would need a MingW development setup first, and from what I've read so far that's still a bit too challenging for me. However my first priority is to get octave involved in procedures we'd otherwise do with Matlab. That replacement-attempt doesn't quite go without the odd fairly involved hitch. IOW it's non-trivial either :-) Thanks, Philip _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn Wed, Nov 11, 2009 at 10:43 PM, Philip Nienhuis <pr.nienhuis@...> wrote: (sorry for late response, my provider's email server was down for some days) It seems you're right. Gosh, what a useless function.
Yes, that is the preferred way. You can even bypass deal and just do [s.f] = c{:} where c is a cell array. * And I think setfield's syntax isn't that obvious either; that is, the Sorry, no attachment arrived. (You're right about sometimes too succinct octave docs. Admittedly only <snip> I don't know what you mean. size is not confused in any way - it just returns the correct dimensions. End of story. Number of fields is not a dimension. FWIW, I added a nfields () function to Octave that can be used to get the number of fields. Again, matlab does the same so why worry... Yes, the benefits must outweigh the costs for you. That's up to you to decide. -- RNDr. Jaroslav Hajek computing expert & GNU Octave developer Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic url: www.highegg.matfyz.cz _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsJaroslav Hajek wrote:
> > > On Wed, Nov 11, 2009 at 10:43 PM, Philip Nienhuis <pr.nienhuis@... > <mailto:pr.nienhuis@...>> wrote: : <snip> : > >> invoking something like: > >> > >> new_s = addfield (old_s, "nfield", [optional values]) > >> > >> is IMO a little more obvious than the assignment syntax above + > variants > >> for exceptions. > >> > > > > How would that differ from setfield? > > * AFAICS & test, setfield() seems intended for assigning a value to > individual field elements, but only one element at a time (= per call). > Unless of course I again overlooked something. This becomes cumbersome > if one wants to add a somewhat larger array to all field elements in a > struct. > > It seems you're right. Gosh, what a useless function. But I'll hold my breath, perhaps both ARE useful for corner cases. And, uhm, Matlab compatibility of course (is that a corner case?) > * (A wrapper script around) [s.f] = deal({cell_values}) assigns values > to all elements of a field in one swoop and can add fields too. But yes, > some fine-grainedness might be lost. > > > Yes, that is the preferred way. You can even bypass deal and just do > [s.f] = c{:} > where c is a cell array. ... but I found that doesn't always work. Apart from deal() I sometimes also needed (:) to the left of "=" like in [s(:).f] = deal(c{:}) To find out how to add fields to large structs & fill them simultaneously I experimented a lot; the above syntax is what always seemed to work OK - except for 1x1 and some empty structs. Which provoked my original posting. > * And I think setfield's syntax isn't that obvious either; that is, the > help text could be more helpful. > A suggestion for an IMO more easily comprehensible example is attached - > just fit it in between the function call description and the example. > If you'd prefer I can send setfield.m with improved help section. > > > Sorry, no attachment arrived. Yes. sorry for that. Another try then. I also attached some additional help text for rmfield() (that may also benefit from additional info). As rmfield is built-in, I cannot adapt it myself. Philip ## ## Note: to remove fields in nested structs, specify the substruct at ## both sides of the "=" sign, e.g.: ## @example ## a.b.c = rmfield (a.b.c, "oldfld"); ## @end example ## @example ## pp = struct ("f1", @{"a", 3@}); ## pp = setfield (pp, @{1, 2@}, "f2", (8)); ## pp.f2 ## => ans = [](0x0) ## ans = 8 ## (which adds a field f2 to struct pp and assigns value 8 ## to the second element of pp.f2. The other elements of ## pp.f2 will be filled with empty values) ## @end example ## ## Note: to add fields in nested structs, specify the substruct at ## both sides of the "=" sign, e.g.: ## @example ## a.b.c = setfield (a.b.c, @{2, 3@}, "nwfld", []); ## @end example ## ## A more complicated example: _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn Thu, Nov 12, 2009 at 10:37 PM, Philip Nienhuis <pr.nienhuis@...> wrote: Jaroslav Hajek wrote: Sorry, but such comments (that something sometimes doesn't work) are virtually useless. Show me where it doesn't work and I'll either try to fix that or explain why it is so. To find out how to add fields to large structs & fill them simultaneously I experimented a lot; the above syntax is what always seemed to work OK - except for 1x1 and some empty structs. Which provoked my original posting. example? where it doesn't work?
thanks. -- RNDr. Jaroslav Hajek computing expert & GNU Octave developer Aeronautical Research and Test Institute (VZLU) Prague, Czech Republic url: www.highegg.matfyz.cz _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
|
|
Re: Unexpected results when adding & removing fields to empty structsOn 12-Nov-2009, Philip Nienhuis wrote:
| Jaroslav Hajek wrote: | > | > On Wed, Nov 11, 2009 at 10:43 PM, Philip Nienhuis <pr.nienhuis@... | > <mailto:pr.nienhuis@...>> wrote: | > | > * AFAICS & test, setfield() seems intended for assigning a value to | > individual field elements, but only one element at a time (= per call). | > Unless of course I again overlooked something. This becomes cumbersome | > if one wants to add a somewhat larger array to all field elements in a | > struct. | > | > It seems you're right. Gosh, what a useless function. | | If so, getfield() may also be superfluous. | But I'll hold my breath, perhaps both ARE useful for corner cases. | And, uhm, Matlab compatibility of course (is that a corner case?) Before dynamic field name indexing was implemented in Matlab, setfield and getfield were provided to allow structure fields to be accessed without using eval when the field name is stored in a variable. I don't think they are really needed now, but are provided to avoid breaking existing code that uses them. jwe _______________________________________________ Bug-octave mailing list Bug-octave@... https://www-old.cae.wisc.edu/mailman/listinfo/bug-octave |
| Free embeddable forum powered by Nabble | Forum Help |