Name/symbol/object type clash? What is happening here?

Robert K. wrote in post #1081267:

You are repeating that it is broken but you fail to explain what
exactly is broken. That’s not a basis for discussions.

I thought my statement “I believe, we all can tolerate this glitch” was
clear enough. But if you insist to define what is broken, the reply is:
“Ruby grammar consistency when it comes to mixing classes with Structs”.
Every solution that you come up with introduces more complications and
weird or even unacceptable run-arounds, like your underscore aliasing.
Try using your ‘_initialize’ and then straight ‘initialiye’ and you’ll
create two different behaviours both of whom are wrong. One
instantiating {{ s = S.new(0) }} with @num to 0, and the other adding 5
twice making @num 10, when using {{ self.num = n + 5 }} idiom rather
than {{ @num = n + 5 }}, which Struct does not recognize (this should be
fixed, namely, Struct should honour ‘@ semantics’; resorting to
‘self#var’ is not sufficient in all circumstances).

Struct does not honour Ruby’s variable inheritance and class
initialization grammar with respect to inheritance, i.e.: all subclasses
have a single set of instance variables in the inheritance hierarchy. If
the idiom {{ class A < Struct.new(:num); end }} makes Struct a
superclass of A, then class A and indeed all its subclasses should
inherit @num instance method from Struct. Accessing Struct’s @num via {{
self.num }} works only when you are using straight assignment, however
if you need to invoke any kind of computation, you have to resort to
tricks like aliasing which works only sometimes.

S = Struct.new :num do
alias _initialize initialize

def _initialize(n) #=> @num==0

def initialize(n)  #=> @num==10
  super
  self.num = n + 5
end

alias _num= num=
def num=(n) self._num= n + 5; end

end

s = S.new 0
p s.num #=> 10; ## with: ‘_initialize’ #=>0
s.num = 100
p s.num #=> 105

The trouble with Struct is that there is no way to implement
initialization of instance variables in base class (ie. in Struct) that
require more elaborate initialization skims than straight assignment.
You can accomplish this only with regular classes and their inheritance
hierarchies!

When you have to resort to tricks to accomplish things that are not out
of the ordinary, you better avoid those features when working outside of
your quick and dirty domain or “research lab”, and Struct certainly
qualifies for that!

Cheers, igor

Robert, you continue pretending that you proved my point of view wrong
by always providing only half of the solution, because you simply can
not satisfy both requirements simultaneously. Namely, I require that
both ‘initialize’ method as well as the attribute accessor (i.e.: the
setter) method work correctly in tandem when an expression rather than
the simple assignment is required.

This code of yours simply doesn’t work when using Struct, (nor does it
work when you try to reopen ‘S’ as class, as was initially argued at the
beginning of this thread):

S = Struct.new :a do
def initialize(a); self.a = a + 5; end
alias _a= a=
def a=(n) self._a= n + 5; end
end

s = S.new(0)
p s.a #=> 10 WRONG!!!
s.a = 100
p s.a #=> 105

With the exception of ‘to_s’ method, you see here the equivalent of the
above code snippet of yours, this time using only classes (which BTW
works correctly):

class A
attr_accessor :num
def initialize(n); @num=n; end
def to_s; “#{self.class}: num=#@num”; end
end

class B < A
def initialize(n); super; @num = n + 5; end
def num=(n) @num = n + 5; end
end

a = A.new(0)
p “After: a=A.new(0) … #{a}” #=> … A: num=0
a.num = 100
p “After: a.num=100 … #{a}” #=> … A: num=100

b = B.new(0)
p “After: b=B.new(0) … #{b}” #=> … B: num=5
b.num = 100
p “After: b.num=100 … #{b}” #=> … B: num=105

Once again, Struct does not provide satisfactory solution to both above
stated initialization requirements, because it does not obey Ruby’s ‘@’
instance variable semantics, and due to this now revealed Ruby grammar
inconsistency introduced by Struct, exposes broken blundering like yours
as you try to botch your way out of it, when Ruby compounds double
execution of expressions used in class/Struct initialization process
(see my comment in your code: #=> 10 WRONG!!!).

Regards, igor

On Fri, Oct 26, 2012 at 5:44 PM, Igor P. [email protected]
wrote:

Robert K. wrote in post #1081267:

You are repeating that it is broken but you fail to explain what
exactly is broken. That’s not a basis for discussions.

I thought my statement “I believe, we all can tolerate this glitch” was
clear enough. But if you insist to define what is broken, the reply is:
“Ruby grammar consistency when it comes to mixing classes with Structs”.

This has nothing to do with Ruby’s grammar. I think I know what
you’re up to but the term is simply wrong.

Every solution that you come up with introduces more complications and
weird or even unacceptable run-arounds, like your underscore aliasing.

These are basically introduced because you chose to have a property
setter which modifies the value on the fly - this is also a
questionable approach.

Try using your ‘_initialize’ and then straight ‘initialiye’ and you’ll

?

create two different behaviours both of whom are wrong. One
instantiating {{ s = S.new(0) }} with @num to 0, and the other adding 5
twice making @num 10, when using {{ self.num = n + 5 }} idiom rather
than {{ @num = n + 5 }}, which Struct does not recognize (this should be
fixed, namely, Struct should honour ‘@ semantics’; resorting to
‘self#var’ is not sufficient in all circumstances).

I find that rather foggy. What code are you talking about exactly?

Struct does not honour Ruby’s variable inheritance and class
initialization grammar with respect to inheritance, i.e.: all subclasses
have a single set of instance variables in the inheritance hierarchy.

I do not think the thing that you call “initialization grammar”
exists. Inherit from Hash and Array and you won’t see instance
variables either. Actually, all classes which are implemented in C
(which includes std lib as well as extensions) do have the liberty to
store the state in any way they like. Generally using accessors to
modify state is a safer method. It just happens that in most user
written classes the direct access to instance variables works and
gives expected results.

If
the idiom {{ class A < Struct.new(:num); end }} makes Struct a
superclass of A,

It doesn’t - at least not directly. Struct.new creates a new class
which sits between them.

irb(main):002:0> class A < Struct.new(:num); end
=> nil
irb(main):003:0> A.ancestors
=> [A, #Class:0x8b37678, Struct, Enumerable, Object, Kernel,
BasicObject]

then class A and indeed all its subclasses should
inherit @num instance method from Struct.

First of all @num is not a method. This is an instance variable read
access.

The method does not exist in Struct - and it can’t for obvious reasons.

irb(main):005:0> Struct.instance_method :num
NameError: undefined method num' for class Struct’
from (irb):5:in instance_method' from (irb):5 from /usr/local/bin/irb19:12:in

Instead it’s defined in the anonymous superclass of A:

irb(main):006:0> A.instance_method :num
=> #<UnboundMethod: A(#Class:0x8b37678)#num>
irb(main):007:0> A.instance_method(:num).owner
=> #Class:0x8b37678

I am starting to wonder whether you understand how Struct works.

Accessing Struct’s @num via {{
self.num }} works only when you are using straight assignment, however
if you need to invoke any kind of computation, you have to resort to
tricks like aliasing which works only sometimes.

S = Struct.new :num do
alias _initialize initialize

def _initialize(n) #=> @num==0

def initialize(n)  #=> @num==10

???

  super
  self.num = n + 5
end

alias _num= num=
def num=(n) self._num= n + 5; end

end

s = S.new 0
p s.num #=> 10; ## with: ‘_initialize’ #=>0

It’s obvious that you get wrong values if you create flawed logic.
This is also not what I had suggested.

s.num = 100
p s.num #=> 105

The trouble with Struct is that there is no way to implement
initialization of instance variables in base class (ie. in Struct) that
require more elaborate initialization skims than straight assignment.
You can accomplish this only with regular classes and their inheritance
hierarchies!

That is not true. If you only want to modify values during
initialization you can always do

S = Struct.new :a, :b do
def initialize(a, b)
self.a = a * 33
self.b = b / 10
end
end

irb(main):026:0> x = S.new 100, 200
=> #
irb(main):027:0> x.a
=> 3300
irb(main):028:0> x.b
=> 20

You even can omit the super invocation.

When you have to resort to tricks to accomplish things that are not out
of the ordinary, you better avoid those features when working outside of
your quick and dirty domain or “research lab”, and Struct certainly
qualifies for that!

That’s not a dirty trick - it’s just a slightly inconvenient way to
use Struct because one cannot use #initialize as predefined. Other
than that this is what you would for a regular class as well. But you
still benefit from properly defined #eql?, #hash, #[] etc. You’re
simply not using the default constructor but still gain useful
functionality. Heck, it doesn’t even involve meta programming. For
me this does not qualify as hack or trickery.

Cheers

robert

Robert K. wrote in post #1081589:

s = S.new(0)
p s.a #=> 10 WRONG!!!
s.a = 100
p s.a #=> 105

Igor, that was not my code. Your claim is wrong. I posted this
upthread:

I consider this red herring, and in continuation you actually repeat,
your half-way solution in which ‘initialize’ is using straight
assignment rather than expression ‘n + 5’! You again ignore the
requirement that both ‘initialize’ method and the accessor (setter)
method initialize the variable in identical fashion! It is you who is
not sticking to the facts, and who is drawing attention away from the
real issue, which is the fact, that Struct does not allow you to define
custom accessor getters consistently and even in a broken way when
combined with class reopening strategy and inheritance hierarchies, and
should not be used when these are needed. All my examples very
consistently show both sides of the story!

should be taken out of the language. You are free to use or not use
Struct based on your judgement, but please refrain from claiming that
Struct is useless, harmless or should be removed from the library on
such weak evidence.

These are your conclusions and inaccurate interpretations of what I
actually said. Struct indeed is ill suited for the case which I have
presented, which BTW is not at all weak evidence as you would like the
ignorant to believe!

We are spending way too much time on your interpretations of what and
even how things are discussed here. I clearly defined what is required
and where Struct is breaking away from Ruby language rules. I also
stated that we all can tolerate this glitch. However, it is precisely
because of such attitudes towards questionable practices, as you are
constantly demonstrating here, that it would be best if Struct was
pulled out of Ruby all together or fixed, because the way it is
currently implemented for limited use, I may add, only provides basis
for badmouthing this magnificent language. This is my opinion and I you
certainly have not convinced me that I am wrong.

Take it easy,
igor

On Sat, Oct 27, 2012 at 9:14 AM, Igor P. [email protected]
wrote:

Robert, you continue pretending that you proved my point of view wrong
by always providing only half of the solution, because you simply can
not satisfy both requirements simultaneously. Namely, I require that
both ‘initialize’ method as well as the attribute accessor (i.e.: the
setter) method work correctly in tandem when an expression rather than
the simple assignment is required.

I have understood that but apparently you did not read my posting
properly or tested the code I provided.

s = S.new(0)
p s.a #=> 10 WRONG!!!
s.a = 100
p s.a #=> 105

Igor, that was not my code. Your claim is wrong. I posted this
upthread:

S = Struct.new :num do
alias _initialize initialize
def initialize(n)
super
self.num = n
end

alias _num= num=
def num=(n) self._num= n + 5 end
end

If you try that out you’ll see this:

irb(main):011:0> S.new(0).num
=> 5
irb(main):012:0> x = S.new 0
=> #
irb(main):013:0> x.num
=> 5
irb(main):014:0> x.num = 10
=> 10
irb(main):015:0> x.num
=> 15

However, there’s still a hole

irb(main):016:0> x[:num] = 5
=> 5
irb(main):017:0> x.num
=> 5

This (along with the fact that Ruby will return the reference passed
to an assignment and ignore the return value of the method)
demonstrates that the whole approach of changing the value while
assigning is at least questionable.

Once again, Struct does not provide satisfactory solution to both above
stated initialization requirements,

See upthread.

because it does not obey Ruby’s ‘@’
instance variable semantics, and due to this now revealed Ruby grammar

See above, this has nothing to do with grammar and also it is
completely legal for Ruby classes to not exhibit their state via
instance variables.

“Grammar” in context of programming languages has a very specific
meaning:

inconsistency introduced by Struct, exposes broken blundering like yours
as you try to botch your way out of it, when Ruby compounds double
execution of expressions used in class/Struct initialization process
(see my comment in your code: #=> 10 WRONG!!!).

Please stick to the facts.

These statements of yours brought me into the discussion:

On Tue, Oct 23, 2012 at 7:44 PM, Igor P. [email protected]
wrote:

Due to the problems shown above, perhaps Struct should be taken out of
Ruby paradigm all together.

[…] The use of ‘Struct’ should also be
discouraged, and even worse, mixing Struct with class definitions and
usage is ill advised.

That’s like asking to ban hammers from all hardware stores because
they are badly suited to tighten screws. You are claiming that Struct
is ill suited for a particular use case (which is debatable in itself)
and infer that Struct is generally not useful (or even harmful) and
should be taken out of the language. You are free to use or not use
Struct based on your judgement, but please refrain from claiming that
Struct is useless, harmless or should be removed from the library on
such weak evidence.

Cheers

robert

Bartosz Dziewoński wrote in post #1081604:

Robert, please stop feeding the troll. I’ve received enough e-mails
from this idiotic thread already.

– Matma R.

That’s just pure ignorance, and I might add…a cowardly statement.

Robert, please stop feeding the troll. I’ve received enough e-mails
from this idiotic thread already.

– Matma R.

On Oct 27, 2012, at 17:32 , 7stud – [email protected] wrote:

Bartosz Dziewoński wrote in post #1081604:

Robert, please stop feeding the troll. I’ve received enough e-mails
from this idiotic thread already.

– Matma R.

That’s just pure ignorance, and I might add…a cowardly statement.

…says the other troll in this thread…

On 28 October 2012 11:50, Ryan D. [email protected] wrote:

That’s just pure ignorance, and I might add…a cowardly statement.

…says the other troll in this thread…

Hah, burn.

And for the record, if anyone can show me where/how part of any Ruby
script is “breaking away from Ruby language rules” I will laud your
whatsernames. If you can write a program in spite of the interpreter
and still have it work, then you’re doing magic.

This class may not be idiomatic, but it isn’t illegal:

class Foo
  def initialize n
    @notnum = n
  end
  def num= n
    @notnum = n
  end
  def num
    @notnum
  end
end

Ditto Struct, and Array (where’s the @c_array instance variable?) and
Hash (@map? @members? @…?)

Struct is great for some things (like quickly defining an object that
holds some named values, but not arbitrarily many) but not great for
others (like overriding access to said values). Suck it up. And only
use it when it’s most appropriate in your script. And quit whinging.
Or go write Python. (Hah, burn again!)


Matthew K., B.Sc (CompSci) (Hons)
http://matthew.kerwin.net.au/
ABN: 59-013-727-651

“You’ll never find a programming language that frees
you from the burden of clarifying your ideas.” - xkcd

Robert K. wrote in post #1081662:

Apparently I’m wrong - but where?

I have already told you where:

““Ruby compounds double execution of expressions used in class/Struct
initialization process (see my comment in your code: #=> 10 WRONG!!!).””

Apparently the “#=> 10 WRONG!!!” line you never wrote, of course you did
not, you blocked it out, once you saw that it gives you the wrong
result, hence you preferred your half-way solutions. If you hadn’t,
you’d understood what was happening.

I am glad you finally realized, that even this half-way version to
satisfy my original requirements, reveals how Struct breaks the basic
Ruby class initialization grammar! That is why in situations like this
you can not use it unless you are willing to accept botching into your
coding practices. And by the way, irb is not synchronized with the
interpreter, and does not realizes that Struct is not behaving in
accordance with Ruby class initialization grammar, since it bypasses the
‘@’ instant variable semantics, which is the crux of the matter here.

Cheers, igor

Oh god, are you still fighting over this crap? If this is the biggest
problem Ruby has, Matz must have done something right.

Igor, I tell you, every time you use the word “grammar”, god kills a
kitten. You have no clue what this word means, and apparently you don’t
want to know. You may have legitimate points, but both you and this
7stud guy come off as whiney amateurs who’ve found something they don’t
understand and now try to play the great language critics, even though
they don’t really know how this “grammar” and stuff works.

For me, this discussion is very informative, especially when people
support the facts using the Ruby codes. I myself seldom use Struct, but
who knows, probably someone else combines Struct and Class in his/her
code and in that case I can know what is going on.

Although probably this problem has nothing to do with Matz, I hope we
can have a proper documentation somewhere besides this discussion.

Regards,

Bill

On Sat, Oct 27, 2012 at 10:49 PM, Igor P. [email protected]
wrote:

I consider this red herring, and in continuation you actually repeat,
your half-way solution in which ‘initialize’ is using straight
assignment rather than expression ‘n + 5’! You again ignore the
requirement that both ‘initialize’ method and the accessor (setter)
method initialize the variable in identical fashion!

Can we agree that if I ignore your requirement to initialize the
variable in identical fashion this is what will happen: the value
assigned in the constructor is modified in a different way than the
value assigned via the attribute writer method resulting in different
values of the property from #initialize and from assignment? OK. Now
with my code this is what happens:

irb(main):001:0> S = Struct.new :num do
irb(main):002:1* alias _initialize initialize
irb(main):003:1> def initialize(n)
irb(main):004:2> super
irb(main):005:2> self.num = n
irb(main):006:2> end
irb(main):007:1> alias _num= num=
irb(main):008:1* def num=(n) self._num= n + 5 end
irb(main):009:1> end
=> S
irb(main):010:0> s = S.new 0
=> #
irb(main):011:0> s.num
=> 5
irb(main):012:0> s.num == 0 + 5
=> true
irb(main):013:0> s.num = 10
=> 10
irb(main):014:0> s.num
=> 15
irb(main):015:0> s.num == 10 + 5
=> true
irb(main):016:0> s.num = 0
=> 0
irb(main):017:0> s.num
=> 5
irb(main):018:0> s.num == 0 + 5
=> true
irb(main):019:0> s = S.new 10
=> #
irb(main):020:0> v1 = s.num
=> 15
irb(main):021:0> s = S.new 0
=> #
irb(main):022:0> s.num = 10
=> 10
irb(main):023:0> v2 = s.num
=> 15
irb(main):024:0> v1 == v2
=> true

To me this looks suspiciously like #initialize and assignment apply
the same modification of the value. Apparently I’m wrong - but where?

robert

Jan E. wrote in post #1081692:

Igor, I tell you, every time you use the word “grammar”, god kills a
kitten. You have no clue what this word means, and apparently you don’t
want to know.

Jan, thank you for your insightful comment. I understand that you may
have trouble understanding more anthropomorphic relationship to language
rules in programing languages, but isn’t this just the reflection of how
badly general English speaking community understands what even English
grammar is? The rules of Boolean algebra can be interpreted as the
simplest of grammars. You do not have to be a linguist to understand
that words, variables and objects are operands and that operators may
represent what in grammar represent inflections, conjugations, and other
grammar rules { -ed, -ing, -s, -ly, irregular verbs, auxiliary verbs,
order of words, …} with which the semantics of statements is
controlled.

Regards, igor

Admin T. wrote in post #1081703:

… I hope we can have a proper documentation somewhere besides this
discussion.

Excellent point

Cheers, igor

Ryan D. wrote in post #1081718:

I’ve already shown that the FIRST PARAGRAPH of the doco for Struct is
pretty damn clear about this. Igor simply isn’t encumbered by facts.

Where exactly is this “doco” of yours. I have learned about this stuff
on page 226 paragraph 7.1.12 in Mats and Flanagan’s “The Ruby
Programming Language”, long before some obscure web pages like ours here
have explained anything. Heck, there isn’t even a reference to Structs
in the index there! Similarly in D. Thomase’s ‘PickAxe’ on page 392,
there is nothing really worth mentioning. Only when you cut your teeth
in, and experiment you realize, its limitations and advantages. I sense
way too much hubris here. Ryan, must really hurt when you expose your
blunder:)

Cheers

On Oct 28, 2012, at 12:08 , Admin T. [email protected] wrote:

Although probably this problem has nothing to do with Matz, I hope we
can have a proper documentation somewhere besides this discussion.

I’ve already shown that the FIRST PARAGRAPH of the doco for Struct is
pretty damn clear about this. Igor simply isn’t encumbered by facts.

Am 28.10.2012 21:51, schrieb Igor P.:

Ryan D. wrote in post #1081718:

I’ve already shown that the FIRST PARAGRAPH of the doco for Struct is
pretty damn clear about this. Igor simply isn’t encumbered by facts.

Where exactly is this “doco” of yours.

Ryan may allude to the official Ruby documentation… :slight_smile:

In case you do not know, it can be found at http://www.ruby-doc.org
or accessed via `ri’:


$ ri Struct

= Struct < Object


= Includes:
Enumerable (from ruby site)

(from ruby site)

A Struct is a convenient way to bundle a number of attributes together,
using accessor methods, without having to write an explicit class.

[…]

Notice the “using accessor methods” part. Nobody says that it provides
@num-like instance variables which you can access directly.
(And btw, as was already pointed out by others, the same is also true
for Arrays, Strings, Sets, …)

If your needs are not met by the “convenient way” of Struct, and you
need to do more complicated stuff, you shouldn’t use it.

Period.

Please stop wasting our time.

Finally a reasonable response, thank you very much, also for the link.

BTW:
$ ri Struct
Nothing known about Struct
$

Is there a way to update ri library?

Am 29.10.2012 13:47, schrieb Igor P.:

Finally a reasonable response, thank you very much, also for the link.

BTW:
$ ri Struct
Nothing known about Struct
$

Is there a way to update ri library?

Maybe you use RVM and have not created docs for
the current Ruby version?

I think you can do that with `rvm docs generate’