I just noticed that the default constructors for FXVec* do not initialize their elements. This also affects anything that uses FXVec* default constructors under the covers such as the FXExtent* default constructors. It would be nice if the docs were explicit on this "point". :-) Perhaps this is the expected behavior in C++ given the various ways that the C++ default constructor can be invoked, but in Ruby I was expecting the no-argument constructor to initialize the instance to [0.0, 0.0]... $ cat defctor.rb #!/usr/bin/env ruby require ''rubygems'' require ''fox16'' include Fox 500.times do |i| v = FXVec2d.new next if v[0] == 0.0 && v[1] == 0.0 p [i, v] break end puts ''done'' $ ruby defctor.rb [222, [6.76425275721251e-320, 4.70741886267958e-284]] $ fox-config --version 1.6.34 $ gem list -l fxruby | grep fxruby fxruby (1.6.18) Sorry if this is old news, Dave P.S. Ruby users can get an "always initialized" default constructor by using this "monkey patch"... class Fox::FXVec2d alias :fox_initialize :initialize def initialize(*args) args = [0.0, 0.0] if args.empty? fox_initialize(*args) end end
On Jan 25, 2009, at 23:17 , David MacMahon wrote:> I just noticed that the default constructors for FXVec* do not > initialize their elements. This also affects anything that uses > FXVec* default constructors under the covers such as the FXExtent* > default constructors.Another thing to note, which I think is an fxruby and/or swig issue, is that the FXExtent* methods #lower, #upper, and #[] return a new object for each call, but all these different objects are backed by the same underlying C++ object. This can lead to weird/undesirable behavior... $ irb -r fox16 irb(main):001:0> include Fox => Object irb(main):002:0> e1=FXExtentd.new(0,1,0,1) => #<Fox::FXExtentd:0x4d09ef0> irb(main):003:0> l1=e1.lower => [0.0, 0.0] irb(main):004:0> l2=e1.lower => [0.0, 0.0] irb(main):005:0> l1.eql?(l2) => false irb(main):006:0> l1.equal?(l2) => false irb(main):007:0> l1 == l2 => true irb(main):008:0> h={} => {} irb(main):009:0> h[e1.lower]=1 => 1 irb(main):010:0> h[e1.lower] => nil irb(main):011:0> l2.x = 9 => 9 irb(main):012:0> l1 => [9.0, 0.0] irb(main):013:0> e1.lower => [9.0, 0.0] It is a little disconcerting to see the state of object_id A change when object_id B is altered. If the "new-object-returned-on-every-call" behavior is due to how swig maps public members, could that mapping be persuaded to return the same object on each call? If not, could the object_id method be overridden to return the address of the underlying C++ object or does Ruby and/or swig already use #object_id as a pointer to some other "wrapper" structure? If not, it would be nice to have a method that tests whether two objects are backed by the same memory if #object_id cannot be used for that purpose. I think the moral of the story (for now?) is don''t use #eql? or #equal? to compare the return values from these methods, which also means don''t use them as hash indexes. Thanks, Dave
On Monday 26 January 2009, David MacMahon wrote:> I just noticed that the default constructors for FXVec* do not > initialize their elements. This also affects anything that uses > FXVec* default constructors under the covers such as the FXExtent* > default constructors.This is in the interest of speed; one often makes [very large] arrays of these things, and initializing them would be time-consuming.> It would be nice if the docs were explicit on this "point". :-)I''ll update the doc-comments.> Perhaps this is the expected behavior in C++ given the various ways > that the C++ default constructor can be invoked, but in Ruby I was > expecting the no-argument constructor to initialize the instance to > [0.0, 0.0]...There is no rule that says it need to be initialized or not in C++; it all depends on what the developer wants. In this case, they''re intended to behave very much like the regular "plain old data" types, which are also only initialized if you explicitly do so. Speed is the reason why this was done. - Jeroen
David MacMahon
2009-Jan-26 18:10 UTC
[fxruby-users] [Foxgui-users] FXVec* default constructors
On Jan 26, 2009, at 7:41 , Jeroen van der Zijp wrote:> On Monday 26 January 2009, David MacMahon wrote: >> I just noticed that the default constructors for FXVec* do not >> initialize their elements. > > This is in the interest of speed; one often makes [very large] arrays > of these things, and initializing them would be time-consuming.Makes sense.> >> It would be nice if the docs were explicit on this "point". :-) > > I''ll update the doc-comments.Thanks!> There is no rule that says it need to be initialized or not in C++; > it all > depends on what the developer wants.Agreed. I''m sorry if my post sounded too whiny about this. It was intended as a documentation request rather than a complaint. Thanks for Fox! Dave
On Mon, Jan 26, 2009 at 2:37 AM, David MacMahon <davidm at astro.berkeley.edu> wrote:> Another thing to note, which I think is an fxruby and/or swig issue, is that > the FXExtent* methods #lower, #upper, and #[] return a new object for each > call, but all these different objects are backed by the same underlying C++ > object. This can lead to weird/undesirable behavior...Yes, that''s a problem. I''ll see what I can do about modifying those methods (FXExtentd#lower, upper, and []) so that they always return a reference to the same Ruby object. P.S. Also made a fix for the uninitialized values for the FXVec classes. Thanks for pointing that out!