Ruby ++, the one element and generators

In algebraic theory, terms such as groups and rings are used to define what
addition and multiplication mean. I’m here trying to use something I learned
and forgot a long time ago, so bear with me, but I think the concepts may
apply here.

In Ruby += has been defined as a combination of assignment and the plus
operation (i.e. addition).

In other languages ++ has been defined as the addition with one.

In algebra, the one element is a particularly important element (along with
zero) because you can generate all values by systematically adding the one
element to the previous result, starting with the zero element.

It appears to me that all the talk about why ++ is not valid due to
anti-shoe-box behaviour is beside the point, because the would also be true
for += :
a = 1
a += 2 # ==> 3
We are not redefining any integers here, we are replacing the reference with
a reference to a new object.

The following makes just as much sense as the above:

a = 1
a++ # ==> 2

The point, is that whatever problems there are with ++ and object
modifications applies equally to += and the next, next! method, and these
problems have been solved. We can’t, however, define ++ without help from
the Ruby interpreter because ++ should be specially interpreted at the same
level as += becuase assignment to self is not possible.
In other words, ++ is an operator that replaces a reference to one object
with a reference to the next object. This operation may or may not be an
inplace operation. Thus we have ++ and ++!.
In fact this is exactly the same as the next and next! methods, thus we just
need the interpreter to go along with these synonyms. Note that integers do
not have a next! operation and float do not have a next method at all - this
makes perfect sense:

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element. Furthermore it is not
within the realms of Ruby to redefine the natural numbers, thus no next!
method.

The ++ operator is really a ‘generator’ in algebraic terms. It should
generate the next element in the set of all elements of a given type, such
as the natural numbers. When a one element is defined, the generator is the
add one operator - it is not necessarily the only generator, but it works.
(stray thought: generators are used on error correcting codes to generate
valid values among all values - a very simple error correcting code would be
to define 0, 4, 8, …, i.e. generator is x += 4. correct(x) = x + 2 mod 4,
thus if someone accidentally added 1 to x, it won’t destroy the
information).

In Ruby we don’t really care about exact algebraic generators. For example
it is nice to have the next string: “helo”.next ==> “help”. This doesn’t
generate all valid strings, yet it is rather useful.

Thus we can piggyback on the “next” method to define our generator - or we
may define our generator as “generator” and define next in terms of the
generator whatever…
The default generator can be define based on the one element, whenever it is
defined. As an example, let us define the one element for Float.
Algebraically it doesn’t make sense, except by doint so we actually define a
new value type - which incidentally happens to be the natural numbers if we
define one as an arbitrary non-zero float value, it just has a different
representation:

We can define a default generator and a default next method for Object:

class Object
def generator
self + one
end
def next
generator
end
end

Or just ignore the generator stuff:

class Object
def next
self + one
end
end

We can define the one element for any class we like:

class Float
def one
1.0
end
end

a = 1.0
a.next # ==> 2.0

No we could equally well write

a++ as a synonym for
a = a.next

and

a++! as a synom for
a.next!

Note that we do not have a default definition of next!, but it may be
referencing an object that does have next! defined, such as a string.

Obviously iterators are obvious candiates for ++:
In the following notice the importnat difference between ++ and ++!
If I had used ++! I would not have been able to reference two values
in the collection at the same time, yet I feel ++ does exactly what I expect
in the following. This suggests there really is a difference between ++ and
++! and both are meaningful in their own terms.

if my_collection.size > 1
begin
c = 0
a = my_collection.first
k = a
++a
while a != my_collection.end
b = a
a++
if a.value > b.value
a.swap_values b
c++
end
end while c > 0
end

def unique x
if not my_collection.exist(x)
return x
end
x = x + "~a"
while my_collection.exist(x)
x++!
next
end

Of course, the above examples could be written with next and next!. In
particular, the ++! would probably be nicer using next! But the ++ operator
makes the operation somewhat cleaner that a = a.next.

Mikkel

[snip]

In algebra, the one element is a particularly important element (along with
zero) because you can generate all values by systematically adding the one
element to the previous result, starting with the zero element.

Their importance is not that 0 is the additive identity, and if we have a
ring, then there is a multiplicative identity 1.

[snip]

It appears to me that all the talk about why ++ is not valid due to
anti-shoe-box behaviour is beside the point, because the would also be true
for += :

The anti-shoe-box explanation, as I understand it, is that assignment (ie.
“=”) is distinctly different from object methods (e.g. +). This explains
why += cannot be a method. Indeed, it is not a method.

The analogy does not say that we cannot have a ‘++’. It only explains
why, if we did, it would not be a method either.

[snip]

The point, is that whatever problems there are with ++ and object
modifications applies equally to += and the next, next! method, and these
problems have been solved.

True. Maybe the difference is that ‘+=’ has an ‘=’, so it looks like a
binding operator. Maybe Matz feels that ‘++’ is just not “The Ruby way”.

[snip]

Note that integers do not have a next! operation and float do not have
a next method at all - this makes perfect sense:

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element.

Please don’t call it “one”. There is a multiplicative identity, it’s
just 1. It just happens that 1 is not an additive generator. Call it
“generator”.

[snip]

a++ as a synonym for
a = a.next
[snip]
a++! as a synom for
a.next!

Perhaps we can make ‘a++’ a synonym for ‘a.next’ (i.e. no inplace change)
and ‘a++!’ a synonym for ‘a.next!’ (i.e. inplace change). Maybe Matz will
like that.

Daniel.

“MikkelFJ” mikkelfj-anti-spam@bigfoot.com wrote in message
news:3de91a9b$0$47402$edfadb0f@dtext01.news.tele.dk…

if my_collection.size > 1
begin
c = 0
a = my_collection.first
k = a
++a
while a != my_collection.end
b = a
a++
if a.value > b.value
a.swap_values b
c++
end
end while c > 0
end

In the above I was a bit loose on the semantics of a++ vs. ++a. These
semantics should be well known - i.e. return the old vs. returning the new
value:

++a <=> return a = a.next
a++ <=> b = a; a = a.next; return b

Clearly this doesn’t make sense for ++! because we are destroying the old
value.
One solution would be to disallow a++!, and only allow ++!a, another
solution would be to to conclude that a is still referencing the same object
so the old value is the same as the new value, thus ++!a <=> a++!
I’d prefer the latter solution, although I can hardly imagine anyone writing
++!a.

Mikkel

Scripsit ille aut illa MikkelFJ mikkelfj-anti-spam@bigfoot.com:
[…]

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element. Furthermore it is not
within the realms of Ruby to redefine the natural numbers, thus no next!
method.
[…]

You are referring to an algebraic ‘group’ (is it called like that in
English?). A ‘group’ doesn’t necessarily have a one element. But a
N and Z_p do have a ‘next’ operation.

Additionally, some other things might be a usable debugging help:
properties of operators that can be defined:

  • commutativity: the parser randomly interprets a+b as a.+(b) and
    b.+(a) if in some debugging mode.

  • associativity: the parser randomly interprets a+b+c as (a+b)+c
    and a+(b+c) if in some debugging mode.

  • distributivity of two operators: the parser randomly expands
    (a+b)c to ac+b*c. I think collecting of terms shouldn’t be done,
    since Ruby is an interpreter and not a computer algebra system.

  • existance of a neutral element: the parser randomly transforms x into
    0+x or 1*x.

  • existance of some inverse element: there are mixins that define a-b and
    a/b as a+(-b) and a*b.inverse().

Maybe there could be similar things for the == and comparison operators.

···


bash$ echo QUIT | nc news.t-online.de nntp
200 T-Online Newsserver bereit [06] (posting ok).
205 All your base are belong to us.

The problem is simple:

Q: Why isn’t “x++” just syntax sugar for “x += 1”?

int x, y, z;

x = 5;
y = x++; // y == 5
x = 5;
z = x += 1; // z == 6

It would confuse and upset C programmers, so best not to put it in.

Remember, the following code could only be intended to mean two things:

x = 5
x++

Either you want “++” to be a method, so you really meant so call the "++"
method of the object 5; or you want “++” to be syntax sugar, which we have
already seen is a bad idea (confusing and counter-intuitive).

However, what does it mean to call 5’s “++” method? Again, there are only
two reasonable things you could mean: either you want the method to return
6, or you want 5 to change it’s value to 6. I thing we would all agree that
the latter is absurd (is anyone arguing that they want 5 == 6 ??), so that
leaves the former. Let’s say we could define it like so:

class Fixnum
def ++
self+1
end
end

x = 5
y = x++ # So y == 6, which is ‘wrong’ from a C standpoint.
x # And x is still 5. Terrible.

···

A: Because in C, for example, “x++” doesn’t mean “x += 1”!

----- Original Message -----
[snip]
In other words, ++ is an operator that replaces a reference to one object
with a reference to the next object. This operation may or may not be an
inplace operation.

It cannot be in-place, because then 5 would equal 6. This is BAD.


In algebraic terms, there is no ‘one’ element for Real numbers

Uh, where did you get that idea? The real number are a field. Check out
your field axioms again. There’s an axiom there just to state the existence
of ‘1’. (This doesn’t seem relevant to your argument or mine… :slight_smile: but I
had to point that out.)


No we could equally well write

a++ as a synonym for
a = a.next

No, we couldn’t! The only reason anyone wants a “++” operator is because
they like it from C/C++/Java/etc. However, if it didn’t work like it does
in other languages, it would be terrible! We’d never hear the end of it!
(Hmm… :slight_smile: ) Like I said, if we can’t implement it exactly like it works
in C, then it’s a bad idea. Surely no one disagrees with this?!

“++” is a relic from a language working too close to the processor
instructions.

Chris

In algebra, the one element is a particularly important element (along with
zero) because you can generate all values by systematically adding the one
element to the previous result, starting with the zero element.
Actually, I believe the “one element” is defined as the neutral element of
the multiplication operation. Actually, at least for fields only the prime
fields are generated using only one (and maybe zero). Even GF(4) cannot be
constructed by using only 1 (because trying so would lead to GF(2) = Z2, the
prime field of GF(4))

In fact this is exactly the same as the next and next! methods, thus we just
need the interpreter to go along with these synonyms. Note that integers do
not have a next! operation and float do not have a next method at all - this
makes perfect sense:

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element. Furthermore it is not
within the realms of Ruby to redefine the natural numbers, thus no next!
method.
As I said above, “one” is defined as the element which satisfies a*1=a for
all a. This “generator” property of the “one element” is better expressed as
the generator property of a sucessor() function. E.g, every positive integer
can be expressed as succ(succ(succ(succ(…succ(1)…)))).
It makes perfect sense for me to define succ and succ! for integers,
but not for reals. But x++ really just defined as x=x+1, and thus makes
sense for integer and float.

The ++ operator is really a ‘generator’ in algebraic terms. It should
generate the next element in the set of all elements of a given type, such
as the natural numbers. When a one element is defined, the generator is the
add one operator - it is not necessarily the only generator, but it works.
No, ++ is not a generator. succ or next is, and this is more consistent
with mathematics than making ++ a generator for N.

greetings, Florian Pflug

···

On Sun, Dec 01, 2002 at 05:19:29AM +0900, MikkelFJ wrote:

In the above I was a bit loose on the semantics of a++ vs. ++a. These
semantics should be well known

Yes they are, but I doubt that Matz would like a ‘++a’. It really doesn’t
fit with the OO model at all. Even ‘a++’ is pushing it. I think that’s
why Matz didn’t include a ‘++’.

Daniel.

You are referring to an algebraic ‘group’ (is it called like that in
English?). A ‘group’ doesn’t necessarily have a one element. But a
N and Z_p do have a ‘next’ operation.

Yes, it’s called a ‘group’ in English. Actually, I figured he was talking
about ‘rings’ though.

  • existance of a neutral element: the parser randomly transforms x into
    0+x or 1*x.

This is called “identity”.

No, we couldn’t! The only reason anyone wants a “++” operator is because
they like it from C/C++/Java/etc. However, if it didn’t work like it does
in other languages, it would be terrible! We’d never hear the end of it!

Good point. To make ‘++’ behave as it does in other languages, we would
have to significatly depart from the Ruby model (which is what makes Ruby
great to begin with)

“++” is a relic from a language working too close to the processor
instructions.

True. The whole reason why ‘++’ was invented in C was that it would
reduce the number of CPU instructions:

In C, ‘a = a + 1’ does this:

1 → Store “1” in a memmory location.

  • → Add 1 to ‘a’ and store the result in another location.
    = → take the contents from this location and put them at the
    location of ‘a’.

But ‘a += 1’ does this:
1 → Store “1” in a memmory location.
+= → Add it to ‘a’ and put it directly in the location of ‘a’,
without the intermediate step.

Whereas ‘a++’ does this:

++ → Increement ‘a’ by 1 and put the result directly in the
location of ‘a’. Without the intermediate location.

Surely, this reason doesn’t apply to Ruby. :slight_smile:

Daniel.

Please don’t call it “one”. There is a multiplicative identity, it’s
just 1. It just happens that 1 is not an additive generator. Call it
“generator”.

OK, it’s just that I’ve watched too much Highlander. C. Lambert was my hero
ever since Subway.

Mikkel

“Rudolf Polzer” AntiATField_adsgohere@durchnull.de wrote in message
news:slrnauia8l.f7j.AntiATField_adsgohere@www42.durchnull.de

Scripsit ille aut illa MikkelFJ mikkelfj-anti-spam@bigfoot.com:
[…]

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element. Furthermore it is not
within the realms of Ruby to redefine the natural numbers, thus no next!
method.
[…]

You are referring to an algebraic ‘group’ (is it called like that in
English?).
It’s called so in the direct Danish translation. I’m not sure this is the
correct Englis term.

A ‘group’ doesn’t necessarily have a one element. But a

N and Z_p do have a ‘next’ operation.

I don’t recall the exact criterias anymore, but it’s clear the Z can’t be
generated by adding one, as you’d have to start at negative infinity.
I think perhaps its helpful to just think it terms of a generator such as
next, as suggested by Daniel Carrera. It still won’t generate all values but
it will generate the next value, which is suffient for our purposes, as we
are not really trying to make an objects state space equivalent to a group
or a similar construct.

Additionally, some other things might be a usable debugging help:
properties of operators that can be defined:

This pin-points some of the problems I have with pure OO approach. I feel
like operations should work on an arbtrary number of objects symmetrically -
I believe this is multimethods? Nonetheless, the Ruby abstraction of the
world is mostly a good one, and if you keep in mind the precise mathematic
definitions suchs as cummutitavity (i.e. order of factors do not matter), it
shouldn’t be a problem in practice - but since you can mix types
arbitrarily, there are no guarantees:
For example 2 + “3” vs. “3” + 2. Do you get error, 5 or “32”.
Strings and integers would have to agree to ensure the expected behavior,
even if + is not commutative for strings and it is for numbers.
Of course, there have yet to be invented a clean solution to type coercion
in any language.

Mikkel

I can’t say I really understand the extensive discussions of ++,
although some of the explanations are sensible to the ignorant (those
in possession of partial knowledge) – such as the shoebox, etc.

I did read something that may be relevant in UML Distilled (2nd Ed.,
9th printing, pages 92-93), although I didn’t fully understand it:

“Reference objects are things like Customer. Here, identity is very
important, because you usually want only one object to designate a
customer in the real world.

Value objects are things like Date [Bignum, Fixnum??]. You often have
multiple value objects representing the same object in the real world.
For example, it is normal to have hundreds of objects that designate
1-Jan-99.

Value objects should be immutable [emphasis added] … . In other
words, you should not be able to take a date object of 1-Jan-99 and
change the same date object to be 2-Jan-99.

In days gone by, the difference between reference objects and value
objects was clearer. Value objects were the built-in values of the
type system. [I don’t understand what this sentence means.] Now you
can extend the type system with your own classes, so this issue
requires more thought. [I don’t understand this sentence either, but it seems to suggest that the discussion of ++ involves ideas that are relevant to all programs, not just to the Ruby application itself.]”

Any thoughts and/or explanations would be appreciated.

“Chris” nemo@hellotree.com wrote in message
news:023301c298b6$6d6f3670$6401a8c0@MELONBALLER…

x = 5
y = x++ # So y == 6, which is ‘wrong’ from a C standpoint.
x # And x is still 5. Terrible.

Nope,

x = 5
y = x++ # y = 6

x = 6

You could also define

x = 5
y = x++ # y = 5

x = 6

To be exactly like C, if you’d like to have both ++x and x++ operators, you
can choose the following path:

x = 5
y = x + x.next # y == 6

x == 6

or

x = 5
y = (tmp = x; x = x.next; tmp) # y == 5

x == 6

But personlly I prefer to just have x++ and avoid the tmp sideeffect at the
cost of not being entirely compatible - I have not strong opinions either
way.


In algebraic terms, there is no ‘one’ element for Real numbers

Uh, where did you get that idea? The real number are a field.

Yes field, that’s the term I was looking for (for real numbers, not the
general generator discussion). I simply forgot how much I had forgotten,
otherwise I would have looked it up. Others have pointed out multiplicative
identity. But the essential point was to have an operation that defines the
next element, and apparently this is the next method, although it would be
cool if it could be more closely releated to algebraic constructs.


No we could equally well write

a++ as a synonym for
a = a.next

No, we couldn’t! The only reason anyone wants a “++” operator is because
they like it from C/C++/Java/etc. However, if it didn’t work like it does
in other languages, it would be terrible! We’d never hear the end of it!

Personally, it would please me if you could justifiably say Ruby is
different from Java :wink:
I think ++ is useful in its own right and people are used to ++ doing all
sorts of things depending on what it is operating on. Notably, ++ is often
defined on C++ lightweight reference objects called iterators, which fits
well with the next paradigm.

(Hmm… :slight_smile: ) Like I said, if we can’t implement it exactly like it
works
in C, then it’s a bad idea. Surely no one disagrees with this?!
I disagree, but I believe I have shown how it could behave exactly as in C
for integers without loosing the general concept of combining next and
assignment.

“++” is a relic from a language working too close to the processor
instructions.

Register arithmetic has many sensible operations. They are not necessarily
bad because they are implemented in hardware. Being contrary, I’ll even
argue C doesn’t go far enough: I’ve long missed a rotate operation in C.
I’ve got applications that would benefit from that because the compiler has
decent opportunity to understand what is going on, that said, I can live
without rotate in Ruby - at least I’ve got Array#shift : class Array; def
rotate; push shift; end; end :wink:

Mikkel

WARNING: rather long.

The problem is simple:

Q: Why isn’t “x++” just syntax sugar for “x += 1”?

A: Because in C, for example, “x++” doesn’t mean “x += 1”!

int x, y, z;

x = 5;
y = x++; // y == 5
x = 5;
z = x += 1; // z == 6

It would confuse and upset C programmers, so best not to put it in.

Remember, the following code could only be intended to mean two things:

x = 5
x++

Either you want “++” to be a method, so you really meant so call the “++”
method of the object 5; or you want “++” to be syntax sugar, which we have
already seen is a bad idea (confusing and counter-intuitive).

I believe there’s yet another (insane) answer:
trying to apply ++ on inmediate objects yields an error, for the
associated Variable object is nil.

I think this leads to hell, but it’s seductive enough to toy with it };^>

WARNING: here follows a rather long Gedankenexperiment, and the
reasoning path is shown almost complete (although I had to edit it a
couple times, in an iterative approach).

If we went along the line of “everything is an object”, variables
themselves could be objects. In an expression matching
RE1 = /[_a-z][_a-zAZ1-9]*#{op}/ (where
op is some kind of operator such as ‘++’), the operator would
correspond to the call of a method of the variable object. The list of
such methods (seen as operators from the point of view of the value being
referenced to, but as methods from that of the variable in use) would be
hard-coded into the interpreter.

This is admitedly confusing, so perhaps the following will render it
clearer:

a = 1 # two objects involved here: inmediate ‘1’
# and a Variable whose value can be represented as :a (it’s
# related to symbols in a way, but a Variable object has also
# some information on the scope of the var (not only the name)
p a == 1 # instance method ‘==’ called on inmediate value object ‘1’
a++ # instance method ‘++’ applied to an anonymous object of class
# Variable, holding a reference to the inmediate value object
# of class Fixnum ‘1’

I will call such ‘instance method of objects of class Variable’
vmethods (stands for variable methods).

When finding some expression matching RE1, the interpreter would have to
decide whether to call a regular method on the object being referred to
by the variable or the vmethod of the latter. A number of operator
look-alike tokens could be chosen to always mean ‘this is a vmethod’.
An obvious candidate would be ‘++’.

Such vmethods could be defined internally, (that is implemented in C in
Ruby’s AST tree walker), but another possibility would be giving a
more complete reflection of the code:

class Variable # all vars will derive from this one
def ++(*args)
old = @referee
@referee = @referee.next # (or += 1 or something)
old
end

@referee is a magical attribute defined by Ruby

this is the new ‘reflective’ thing needed for this code to be

possible (besides the new vmethod semantics)

end

Notice that, given some kind of Number class with Number#puts
the following would happen
a = Number.new(1)
(a++).puts # writes ‘1’
this seems to be what we want for the postfix ‘++’.

Then we might want to overload the ‘++’ vmethod (no longer an operator
if you consider from the Variable point of view), and a natural
extension in Ruby would be

a = getSomeIterator()
class <<< a

we want to add overload instance methods of the singleton class of

the Variable object!!!

that is, create a singleton vmethod

def ++(*args)

this is meant to be an iterator

@referee.pointToNextElement

end
end

So far so good, we have

  • a clean separation between regular instance methods and vmethods
    (normally distinction on a lexical level)
  • a way to overload these vmethods per variable (singleton vmethods)

I can already hear you cry about prefix (no-longer-)operators,
and we’re all wondering the possible use of *args…

The answer is of course… redefining the ‘++’ vmethod of the variable
referring to the top-level object!!!

self   		# -> top-level object, variable of type Object
class Variable
  def pre++
    @referee = @referee.next # or += 1, default implementation
  end
end

class <<< self
  def ++(arg)   # arg is the ref to the rhs Variable object 
	arg.send :pre++
  end
end
a = 1	  	# a refers to object '1'
++a	  	# now points to object '2'
puts(++a) 	# puts '3'

Why did I write the ()'s? Well, we need some way to have Ruby know that
it is to do
puts(++a)
and not
(puts++) a
for the second one would try to call the ‘++’ vmethod of nil (cause no
variable named ‘puts’ exists). We could say that the ‘++’ “in the
middle” always binds to the right variable, but I’ll later give one
reason why we could possibly not want this rule :slight_smile:

So, looking for another solution, the following comes to mind:
I think matz’s last thought on style (and we all trust him on this :slight_smile: is
that parenthesis are a good thing (I think Ruby was beginning to warn
about parenthesis being needed in future versions in some contexts) in
many occasions, and this one seems at first sight one of them.
But then we realize that this is in fact the very same problem we have
with methods vs local variables, and the trick there was to draw the
difference during parsing. Quoting from the Pickaxe

\begin{quote}
When Ruby sees a name such as ``a’’ in an expression, it needs to
determine if it is a local variable reference or a call to a method with
no parameters. To decide which is the case, Ruby uses a heuristic. As
Ruby reads a source file, it keeps track of symbols that have been
assigned to. It assumes that these symbols are variables. When it
subsequently comes across a symbol that might be either a variable or a
method call, it checks to see if it has seen a prior assignment to that
symbol. If so, it treats the symbol as a variable; otherwise it treats
it as a method call. As a somewhat pathological case of this, consider
the following code fragment, submitted by Clemens Hintze.

def a
print “Function ‘a’ called\n”
99
end

for i in 1…2
if i == 2
print “a=”, a, “\n”
else
a = 1
print “a=”, a, “\n”
end
end

Produces:
a=1
Function ‘a’ called
a=99
\end{quote}

This is the very same kind of problem we’re facing here!!!
In ‘puts ++ a’ we don’t know what to bind ‘++’ to. A heuristic as the
former would mean that ‘puts ++ a’ means

  • puts(++a) if there’s been no assignment of the form ‘puts=…’ before

  • puts++(a) if there has been one. Then fail horribly (or not, more on
    that later…) because functions (or rather methods) are not first
    class values in Ruby (so we cannot meaningfully ‘increment one’)
    Yet another easier way (which enforces a particular spacing) is having
    to attach ‘++’ to the variable it’s applied to:
    puts++a # illegal, syntax error
    puts ++ a # illegal, what is is attached to?
    puts++ a # do (puts++)(a)
    The later sentence would normally fail because we cannot ‘increment’ a
    method. But what if [methods were first class values in Ruby]

    class <<< Kernel.puts
    def ‘++’
    # do some magic with @referee
    end
    end

Unless Ruby becomes another FP, the latter is useless (or rather
impossible to use).

But there’s even another new possibility if we have Variable objects:
implementing the ‘()’ “around-fix” vmethod:
class Function
def initialize(val)
@val = val
end
end
b = Function.new(0)
class <<< b
def (*args) # maybe we need something to name this ‘operator()’
# do something, such as…
ret = @val + @args.size
puts “#{@val} + number of args => #{ret}”
ret
end
end
b(“one”, “two”, “three”) # => 3

We then need the quite complex heuristic introduced before, instead of
taking “‘puts++a’ means puts(++a) always” because we might want to be
able to omit the parentheses, mirroring what is happening now in Ruby
(continues the last example)
class <<< b
def ++
@val += 1
end
end
a = 1
b ++ a # => 1
b a # => 2
++b a # => 3
b a # => 3

There’s only one problem left: what happens in
class A
a = 1
++a # calling the ++ vmethod of the ‘Variable’ A
end

Ruby will try to run (check the example about redefining ‘++’ for the top-level
object) the ‘++’ vmethod of the ‘A’ constant. There’s two pbs. there:

  • the vmethod is called on an object of class Variable which happens to
    be referring to a constant. We solve it by changing the name of that
    class to a more sensible name: NameBinding or something

  • that vmethod is not defined!!! Solved if we define

    class Object
    def ++(arg) # arg is the ref to the rhs NameBinding object
    arg.send :pre++
    end
    end

this will work as it’s the only way that vmethod can be used, for in
every other (postfix) context ‘++’ is taken as the vmethod related to
the pertinent NameBinding.

You might wonder where this ‘pre++’ came from… it was in fact already
present in the third example, since I cheated and modified it while
writing these lines :slight_smile: It is a vmethod used to do the prefix ++ thing.

Finally, there’s the issue of other “NameBindings” such as

  • attributes
  • locals inside blocks
    The latter are handler exactly the same way, for the former the parser
    must be wise enough to see that @a++ means (@a)++ and not @(a++).

One last concern: what is the meaning of
a = 1
(a++)++ # a++++ ?

Surprisingly enough, the proposed implementation of NameBinding#++
does the right thing!
(a++)++ # => 1 a == 3
We just have to remember that when given a receiver, the #++ vmethod
is always called on the related variable, not on the “value”. This
relates the #++ distinction issue to the way access restrictions are done
(ie no receiver allowed => use self).

BTW, this will fail:
1++++ # ‘++’ called on NameBinding nil
and it’s what we had always wanted, for changing such an inmutable
object is meaningless.

This thought experiment shows what would happen if things where
evaluated in two different contexts: “value” and “name binding”
(== variable, but not always). So you can relate it to Perl’s contexts,
and dislike it for that reason.

You might also find it to be some kind of “call by name”-like semantics
extended the whole language, and detest it for that reason.

Maybe you can associate it with the complexity of Common Lisp’s macros,
and detest it for that reason.

Or you could think that this is nothing but C++ in disguise, with
references à la Java working like pointers, and operator(), and abhor
it for that reason.

If you actually like it (or thinking about it), you’re really into
nasty things. I am too :slight_smile:

My head hurts slightly now. :stuck_out_tongue:

I’d anyway appreciate comments on why this is foolish.
Were it not, and had nobody else thought of it before (which I doubt),
I’d retain all the credit for myself }}:wink:

···

On Sun, Dec 01, 2002 at 06:22:27AM +0900, Chris wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Not only Guinness - Linux is good for you, too.
– Banzai on IRC

“MikkelFJ” mikkelfj-anti-spam@bigfoot.com wrote in message
news:3de9424e$0$47426$edfadb0f@dtext01.news.tele.dk…

To be exactly like C, if you’d like to have both ++x and x++ operators,
you
can choose the following path:

x = 5
y = x + x.next # y == 6

x == 6

sorry, should read

x = 5
y = (x = x.next) # y == 6

x == 6

the post inc. versions is ok:

x = 5
y = (tmp = x; x = x.next; tmp) # y == 5

x == 6

Mikkel

Scripsit ille aut illa MikkelFJ mikkelfj-anti-spam@bigfoot.com:

Scripsit ille aut illa MikkelFJ mikkelfj-anti-spam@bigfoot.com:
[…]

In algebraic terms, there is no ‘one’ element for Real numbers, while
natural numbers (integers) do have a one element. Furthermore it is not
within the realms of Ruby to redefine the natural numbers, thus no next!
method.
[…]

You are referring to an algebraic ‘group’ (is it called like that in
English?).
It’s called so in the direct Danish translation. I’m not sure this is the
correct Englis term.

A ‘group’ doesn’t necessarily have a one element. But a

N and Z_p do have a ‘next’ operation.

I don’t recall the exact criterias anymore, but it’s clear the Z can’t be
generated by adding one, as you’d have to start at negative infinity.

That’s why I named Z_p. Even Z_n would work (addition modulo n, eg if n
= 6, 4 + 5 = 9, 9 MOD 6 is 3, therefore 4 + 5 = 3 (mod 6)), but if
you are using the normal operations modulo a prime number, you can even
divide:

5/4 = x (mod 7)
5 = 4x (mod 7)
5 = 4x + 7q

Euclidean Algorithm:

7 = 40 + 71
4 = 41 + 70
3 = 4*(-1) + 71
1 = 4
2 + 7*(-1)

Multiply with 5:

5 = 410 + 7(-5)
5 = 4*10 (mod 7)
5/4 = 10 (mod 7)
= 3 (mod 7)

So in Z_7 5 divided by 4 is 3. 34 is 12, the remainder after division
by 7 is 5, so 3
4 = 5 (mod 7).

The problem in Z_p is that there isn’t a lowest element. There is a
multiplicative zero, but there is no first element - Z_p is cyclic, you
can reach every element from every element by just adding 1.

I think perhaps its helpful to just think it terms of a generator such as
next, as suggested by Daniel Carrera. It still won’t generate all values but
it will generate the next value, which is suffient for our purposes, as we
are not really trying to make an objects state space equivalent to a group
or a similar construct.

And that’s the IMHO best reason for ‘++’. In C++ it’s also used for more
than adding one to an integer: it can, for example, iterate over tree
nodes of a .

Additionally, some other things might be a usable debugging help:
properties of operators that can be defined:

This pin-points some of the problems I have with pure OO approach. I feel
like operations should work on an arbtrary number of objects symmetrically -
I believe this is multimethods? Nonetheless, the Ruby abstraction of the
world is mostly a good one, and if you keep in mind the precise mathematic
definitions suchs as cummutitavity (i.e. order of factors do not matter), it
shouldn’t be a problem in practice - but since you can mix types
arbitrarily, there are no guarantees:
For example 2 + “3” vs. “3” + 2. Do you get error, 5 or “32”.

I’d say:

2 + “3”
→ 2.+(“3”)
→ error if Fixnum.+ is declared as a commutative operator
(for the sake of simplicity, commutativity requires equal types)
OR
2.+(“3”) is executed and commutativity is just ignored if types
are inequal, but a warning is issued
→ error, 5 or 23, depending on type coercion rules

Strings and integers would have to agree to ensure the expected behavior,
even if + is not commutative for strings and it is for numbers.

That’s why I wrote it would be better if each type can have its own
operator behaviour.

Of course, there have yet to be invented a clean solution to type coercion
in any language.

Easy: there is none. Both Modula-2’s and Perl’s type system have their
pros and cons. There are people who want the strict system of Modula-2
that doesn’t even let you convert a INTEGER to a FLOAT implicitly (so
you have to write “f / 2.0” instead of “f / 2”) and there are people who
want Perl’s system which is anything but stongly typed.

···

“Rudolf Polzer” AntiATField_adsgohere@durchnull.de wrote:


REPLACE
The ZOO must replace an item that is used by the monkey during
typing activities. The item to be replaced may be TYPEWRITER,
PAPER, RIBBON, CHAIR, TABLE, or MONKEY. RFC2795

[I haven’t really had time to read this in depth. I scanned it.]

This seems like an overly complex solution to a facility that I
personally haven’t seen a really demonstrated need for. IMO, ++ adds
no real value. It could be “nice”, but that nice-ness comes at
changing the way that variables work in Ruby – which is just as
references to objects.

In the three Ruby projects that I’ve done, I have only one where
I’ve done “a += 1” (although it’s all over that one, and I could
probably refactor that code to be much cleaner), and that a += 1
behaviour is for a rather inconsequential purpose (status update).

It would be nicer to be able to do Inc(a) or a++, but the cost – to
the Ruby language, IMO – of doing such a thing isn’t worth the
minor savings of keyboarding.

To me, ++ has a HUGE downside: it’s an assignment masquerading as an
increment. There is nothing for the novice which suggests that a++
is actually assigning as well as incrementing, unlike a += 1.

In C-derived languages, I’ll use a++; in Pascal, I’ll use Inc(a). In
Ruby, however, I’ll tend to use a.each, a.each_with_index, a.times,
or something else – or a += 1 if I absolutely must have a counter
like that.

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.12.01 at 18.45.47

···

On Mon, 2 Dec 2002 05:01:35 +0900, Mauricio Fernández wrote:

WARNING: rather long.

Hmmm…, I don’t think the explanation above is strict. I think the
current C compilers are free to translate ‘a = a + 1’ to ‘a++’. Because
of this, we don’t have to worry whether to write ‘a = a + 1’ or ‘a++’. A
good C compiler will translate either of these into an assembly/machine
equivalent of ‘a++’. You can ask/search comp.lang.c if you like. C is
one of the languages where a lot of things are not strictly defined.

Regards,

Bill

···

Daniel Carrera dcarrera@math.umd.edu wrote:

True. The whole reason why ‘++’ was invented in C was that it would
reduce the number of CPU instructions:

In C, ‘a = a + 1’ does this:

1 → Store “1” in a memmory location.

  • → Add 1 to ‘a’ and store the result in another location.
    = → take the contents from this location and put them at the
    location of ‘a’.

But ‘a += 1’ does this:
1 → Store “1” in a memmory location.
+= → Add it to ‘a’ and put it directly in the location of ‘a’,
without the intermediate step.

Whereas ‘a++’ does this:

++ → Increement ‘a’ by 1 and put the result directly in the
location of ‘a’. Without the intermediate location.

Surely, this reason doesn’t apply to Ruby. :slight_smile:

Daniel.

[snip]

It would be nicer to be able to do Inc(a) or a++, but the cost – to
the Ruby language, IMO – of doing such a thing isn’t worth the
minor savings of keyboarding.

To me, ++ has a HUGE downside: it’s an assignment masquerading as an
increment. There is nothing for the novice which suggests that a++
is actually assigning as well as incrementing, unlike a += 1.

[snip again]

Austin –

This echoes my thoughts on the matter. Well said.

At any rate, it’s all rather a theoretical discussion –
i.e., it is moot, since I don’t expect Matz ever to add
++ to Ruby.

It’s fine to discuss matters of “why” and “what if” – but
IMO, he made right decision nine years ago, I’d be amazed
if he ever reversed it, and that is that.

Hal

···

----- Original Message -----
From: “Austin Ziegler” austin@halostatue.ca
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Sunday, December 01, 2002 5:52 PM
Subject: Re: Ruby ++, the one element and generators

At the time C was first used, compilers were so much dumber.
Nowadays any decent compiler will optimize these cases.

···

On Tue, Dec 03, 2002 at 06:30:22AM +0900, William Djaja Tjokroaminata wrote:

Daniel Carrera dcarrera@math.umd.edu wrote:

True. The whole reason why ‘++’ was invented in C was that it would
reduce the number of CPU instructions:

In C, ‘a = a + 1’ does this:

1 → Store “1” in a memmory location.

  • → Add 1 to ‘a’ and store the result in another location.
    = → take the contents from this location and put them at the
    location of ‘a’.

But ‘a += 1’ does this:
1 → Store “1” in a memmory location.
+= → Add it to ‘a’ and put it directly in the location of ‘a’,
without the intermediate step.

Whereas ‘a++’ does this:

++ → Increement ‘a’ by 1 and put the result directly in the
location of ‘a’. Without the intermediate location.

Surely, this reason doesn’t apply to Ruby. :slight_smile:

Daniel.

Hmmm…, I don’t think the explanation above is strict. I think the
current C compilers are free to translate ‘a = a + 1’ to ‘a++’. Because
of this, we don’t have to worry whether to write ‘a = a + 1’ or ‘a++’. A
good C compiler will translate either of these into an assembly/machine
equivalent of ‘a++’. You can ask/search comp.lang.c if you like. C is
one of the languages where a lot of things are not strictly defined.


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

The bug system is not a release-specific entity. Users of
Debian 1.3.1 use the same bug tracking system as users of hamm.
– James Troup troup@debian.org