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

Robert Klemme 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 `<main>'

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
=> #<struct S a=3300, b=20>
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

···

On Fri, Oct 26, 2012 at 5:44 PM, Igor Pirnovar <lists@ruby-forum.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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.

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

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
=> #<struct S num=5>
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:

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

···

On Sat, Oct 27, 2012 at 9:14 AM, Igor Pirnovar <lists@ruby-forum.com> wrote:
On Tue, Oct 23, 2012 at 7:44 PM, Igor Pirnovar <lists@ruby-forum.com> wrote:

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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

-- Matma Rex

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
=> #<struct S num=5>
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
=> #<struct S num=15>
irb(main):020:0> v1 = s.num
=> 15
irb(main):021:0> s = S.new 0
=> #<struct S num=5>
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

···

On Sat, Oct 27, 2012 at 10:49 PM, Igor Pirnovar <lists@ruby-forum.com> wrote:

Robert Klemme 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!

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

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

···

--
Posted via http://www.ruby-forum.com/.

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.

···

--
Posted via http://www.ruby-forum.com/\.

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

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

···

Am 29.10.2012 13:47, schrieb Igor Pirnovar:

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?

--
<https://github.com/stomar/&gt;

Todd B. wrote in post #1080981:

Okay, I see, thanks.

Okay, you see what? That was one of the worst responses I've ever read
on this forum. It completely missed the big picture. Your example
shows that ruby is a completely screwed up somewhere. You can't have
two constants with the same name, so your class should have overwritten
the Struct.

···

--
Posted via http://www.ruby-forum.com/\.

Bartosz Dziewoński wrote in post #1081236:

Verb isn't grammar. It is a word. Please rethink what you just wrote.

According to Ruby grammar {{ class S; def @var = value; end }} is the
definition of instance method and again according to Ruby grammar
convention its use is defined as {{ S#var = value }}. Here, the
accessor method can be considered a verb or operator. Idiom {{ class S;
end }} is according to Ruby grammar the definition of class 'S'. If for
some word grammar seems inappropriate here, I do not intend to convince
you otherwise. Likewise I never meant to say that verb is grammar, but
it nevertheless represents grammatical conception or term and it is in
this context that I used the word, suggesting otherwise is pretending
ignorance.

You should use class S < Struct.new(:num) here, and then properly call
super. I'm sure you can find examples of what it does online, do try.

As for 'infinite recursion', it is I, who is objecting to this use all
along and pointing out that Struct should be fixed so it would
understand, conform and obey the Ruby instance variable grammar and
rules.

Use of '@' instance variables is sometimes unavoidable and necessary.
Ruby grammar is clear about its use, except when it comes to the
conundrum of mixing Struct with class reopening, and using instance
variables in this context. The examples above clearly demonstrate these
problems.

Regards, igor

···

--
Posted via http://www.ruby-forum.com/\.

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 Rex

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

···

--
Posted via http://www.ruby-forum.com/\.

Admin Tensor wrote in post #1081703:

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

Excellent point

Cheers, igor

···

--
Posted via http://www.ruby-forum.com/\.

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.

···

On Oct 28, 2012, at 12:08 , Admin Tensor <lists@ruby-forum.com> wrote:

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

Todd B. wrote in post #1080981:

Okay, I see, thanks.

Okay, you see what? That was one of the worst responses I've ever read
on this forum. It completely missed the big picture.

No... Yours is. Quit being a constant prick on here.

···

On Oct 24, 2012, at 18:21 , 7stud -- <lists@ruby-forum.com> wrote:

Your example
shows that ruby is a completely screwed up somewhere. You can't have
two constants with the same name, so your class should have overwritten
the Struct.

Ruby is not screwed up, at least not in the ways you say it is. The `class
S` line isn't declaring a new class named S, it's reopening the class
created by Struct.new.

    S = Struct.new(:num)
    class S
      def show_num; puts "Show:#{self.num}"; end
    end

is like

    S = Struct.new(:num) do
      def show_num; puts "Show:#{self.num}"; end
    end

or similar enough to

    class S < Struct.new(:num)
      def show_num; puts "Show:#{self.num}"; end
    end

···

On Wed, Oct 24, 2012 at 9:21 PM, 7stud -- <lists@ruby-forum.com> wrote:

Todd B. wrote in post #1080981:
>
> Okay, I see, thanks.
>

Okay, you see what? That was one of the worst responses I've ever read
on this forum. It completely missed the big picture. Your example
shows that ruby is a completely screwed up somewhere. You can't have
two constants with the same name, so your class should have overwritten
the Struct.

--
-yossef

So the whole discussion can be summed up as: monkey-patching is
dangerous, only do it if you understand the implications.

Let's all play nice now, 'k?

···

On 26 October 2012 09:19, Igor Pirnovar <lists@ruby-forum.com> wrote:

Bartosz Dziewoński wrote in post #1081236:
Use of '@' instance variables is sometimes unavoidable and necessary.
Ruby grammar is clear about its use, except when it comes to the
conundrum of mixing Struct with class reopening, and using instance
variables in this context. The examples above clearly demonstrate these
problems.

--
  Matthew Kerwin, 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

...says the other troll in this thread...

···

On Oct 27, 2012, at 17:32 , 7stud -- <lists@ruby-forum.com> 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 Rex

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

Ryan Davis 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

···

--
Posted via http://www.ruby-forum.com/\.

Yossef Mendelssohn wrote in post #1081055:

Ruby is not screwed up, at least not in the ways you say it is. The
`class
S` line isn't declaring a new class named S, it's reopening the class
created by Struct.new.

Thanks for the explanation.

···

--
Posted via http://www.ruby-forum.com/\.

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!)

···

On 28 October 2012 11:50, Ryan Davis <ryand-ruby@zenspider.com> wrote:

On Oct 27, 2012, at 17:32 , 7stud -- <lists@ruby-forum.com> 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 Rex

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

...says the other troll in this thread...

--
  Matthew Kerwin, 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

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':

···

Am 28.10.2012 21:51, schrieb Igor Pirnovar:

Ryan Davis 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.

-----
$ 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.

--
<https://github.com/stomar/&gt;