RCR 296: Destructive methods return self

F

Florian Gross

Douglas said:
form.button.tabgroup.last.(
caption = "Foo"
enabled = true
top -= 5
left += 10
onclick = {
puts "Hello World"
}
)

Does this sound sensible?

Could it act like this:

[...]
m = Sample.new

m.{ |self| red = 'read' }

# or:

m.do |self|
red = 'read'
end

puts m.red #=> read

While I'm not sure if I prefer this syntax it would still be acceptable.

The most important part IMHO is to make sure that in that context 'foo =
1' will not be a local variable assignment but rather a setter invocation.

I think I'd still prefer a keyword-based syntax over all this
punctuation, though.
 
A

Aredridel

I like the idea of a safe instance_eval (one that doesnt circumvent
privacy or has access to instance variables), and "apply" is a good
name for that.

+1!

That's the first time I've seen a "with" construct I truly like.

Ari
 
B

Ben Giddings

Malte said:
That's something I encounter often, too. It' especially tiresome when
trying to figure out how undocumented methods work - or when I've
forgotten in which order arguments have to be given (example:
alias_method). Though extensive use of hashes as parameters would be
terribly verbose, it would be very easy to read, because it's easier to
know what is happening - provided that the keys used have got sensible
names.

That happens to me too. That's why I hope that with Ruby 2, Matz makes
it so that every method's parameters are named by default so for:

def send_data(data, to)
# ...
end

you could call it as:

send_data(the_data, "bob")

or

send_data(to: "bob", data: the_data)

This would be especially useful when the function parameters are not
obviously named:

send_data(to: ARGV[1], data: ARGV[3])

If you know the method well and know the order of parameters well, you
could just use them in order. If you want to be explicit about them,
you can use the keyword params.

I think this would be the most useful implementation, but I'm not sure
how easy it is.

Ben
 
B

Ben Giddings

Christian said:
I like the idea of a safe instance_eval (one that doesnt circumvent
privacy or has access to instance variables), and "apply" is a good
name for that.

There's also the idea that everything in the group would be assumed to
be a method call, so that

frame.layer.button[3].apply do
title = "Button title"
size = :max
pack!
show
end

would be equivalent to:

frame.layer.button[3].title = "Button title"
frame.layer.button[3].size = :max
frame.layer.button[3].pack!
frame.layer.button[3].show

In other words, "title" and "size" would be accessor methods, and not
local variables within the scope of the frame.layer.button[3] instance.

Ben
 
G

gabriele renzi

Ben Giddings ha scritto:
That happens to me too. That's why I hope that with Ruby 2, Matz makes
it so that every method's parameters are named by default so for:

I agree with your hope, but notice that matz said more than one times
that this won't happen. I'm not sure about the reasons (He did not
explained them or I simply forgotten he did, probably the latter).
 
D

Daniel Amelang

From what I can tell, the basis for your alternative syntax (**) was
that (*) was not consistent. Florian has already pointed out that it
is, in fact, consistent (the astericks functions as an array
'collector' already), so I think we're back to the single * syntax,
right?

Dan
 
D

Daniel Amelang

Obscure, yes, but it is interesting. The passing _in_ of arguments is
now mirrored in how the return values are received.

Dan
 
B

Bill Kelly

There's no word in the English language for what you do to a dead
thing to make it stop chasing you.

# I suspect any of these ought to work, but we can try them all

%w(mince incinerate cremate vaporize).each do |word|
zombie.send(word) rescue next
end


')'.intern

Bill
 
T

Trans

Florian said:
Let's keep talk about this for a moment.

We'll finally get keyword arguments in Rite and they're already in Ruby
1.9 as well.

But what about keyword return values? How would those look?

I'm not sure how this would work out, but I guess we would need to build
it on the (a, b) = [1, 2] syntax.

Perhaps (result: a, changed: b) = obj.strip! would work.

I think the case of (result: result, changed: changed) would be quite
common so perhaps it would be a good idea to introduce a short-cut.
Maybe :)result, :changed) = rhs.

What do you think about this? I guess I'm getting obscure here, but this
might be an alternative to more complex solutions...

I'm not sure I understand your short-cut. What variables would the
results end up in?


Giveing this more though... the parameters going in will be of the
form,

ameth( arg1: value1, arg2: value2 )

Right? So how would one define keyword return values coming out?

return ( arg1: value1, arg2: value2 )

Perhaps? Then how does one capture these values, which is what you're
asking. Yes? Is the return value a hash now as opposed to an array? Or
is it something different entirely?

Here is the example if based solely on order.

r, c = obj.strip!

But this won't work if an actual hash is being returned. And as things
stand, if an actual hash is being returned something like this has to
be done:

h = obj.strip!
r, c = h[:result], h[:changed]

So how can these two become integrated and consistent?

T.
 
T

Trans

Matt said:
Note that I was just showing something for not using that temporary
variable... not to show how to make it consistent - I have had very
little decent sleep, and this previous seemed like an important email
to write. apologies.

My, my! Infallible even while sleepy! :) Not a problem. Thanks for
sheding some light on this. Your example brings us quite close to an
answer I think.

T.
 
F

Florian Gross

Trans said:
Let's keep talk about this for a moment.

We'll finally get keyword arguments in Rite and they're already in Ruby
1.9 as well.

But what about keyword return values? How would those look?
[...]
Perhaps (result: a, changed: b) = obj.strip! would work.

I think the case of (result: result, changed: changed) would be quite
common so perhaps it would be a good idea to introduce a short-cut.
Maybe :)result, :changed) = rhs.

I'm not sure I understand your short-cut. What variables would the
results end up in?

result and changed. It assigns the keyword return value with that name
to the variable with that name. It might be very rarely needed, though.
I think the uncompressed syntax would be more useful.
return ( arg1: value1, arg2: value2 )

Perhaps? Then how does one capture these values, which is what you're
asking. Yes? Is the return value a hash now as opposed to an array? Or
is it something different entirely?

That looks nice. I think it would return a Hash.

My suggestion for capturing them is to introduce a new variable
assignment syntax:

(x: var1, y: var2) = {x: 1, y: 2}
var1 # => 1
var2 # => 2

This might look odd at first, but I think it makes some kind of sense...
 
T

Trans

Florian said:
result and changed. It assigns the keyword return value with that name
to the variable with that name. It might be very rarely needed,
though.

Ah, Okay. That makes sense. Though you are right it does look a bit
odd, which is why I wasn't sure what you intended. I think as you said
that might be a little too obscure.
I think the uncompressed syntax would be more useful.

I agree.
That looks nice. I think it would return a Hash.

Okay, nice. That keeps things straight forward --no special type of
return object involved.
My suggestion for capturing them is to introduce a new variable
assignment syntax:

(x: var1, y: var2) = {x: 1, y: 2}
var1 # => 1
var2 # => 2

This might look odd at first, but I think it makes some kind of
sense...

Yes, it does make sense. But also true to it seems a bit odd at first.

I wonder, since this can already be done, as Matt pointed out:

h = {x: 1, y: 2}
var1, var2 = *h.values_at:)x, :y)

Could the following simple notation ultimately be workable?

var1, var2 = h[:x,:y]

T.
 
T

Trans

Matt said:
So, why not have an operator -> such that
obj->method(*args, &block)
is equivalent to (and more efficient than)
lambda {
obj.method(*args, &block)
obj
}
and, then you can add in ()'s around for better chaining:
obj->(sort.replace(&blocky)) # Still returns obj

Then, with destructive methods, you can have
obj->sort!->reject!(&no_like)...

I think this makes sense since the `.' operator is well known as the
`member' operator and for objects, gets the appropriate method (as far
as most languages go). -> has the hanging notion of pointers from
c/c++, but it also makes a bit of conceptual sense here in that we're
sort of `piping' obj forward... the direction of forward is always ->
in left to right reading :)

Interesting. So you can dictate the return of 'self' from the outside
with any method you choose irregardless of what it may normally return?


Yet that doesn't seem at all useful for non-destructive methods.
"obj->strip" would be pointless, I think. It would be more useful if
any method could act destructively. As I suggested earlier: "obj!sort".
Perhaps a better notation for this would be your suggestion
"obj->sort". But this is all quite speculative given that matz has
never seemed too keen in pursing generalized in-place modification.

T.
 
T

Trans

Matt said:
But it is useful if you are not self-destructive (ie, you are still
doing side effects, but effecting the world instead of just self).

Ah, fair point.
Matz may be against generalized in-place modifications (so am I - I'm
a haskell kid at heart), but it does get used. When efficiency is
needed, fp is dropped for scripting, and then for more efficient
scripting, and then for C. But what I'm suggesting has nothing to do
with in place scripting, but is really just a sort of with statement,
but I think rather more elegant than the kind that comes with VB, and
is syntactically pleasant.

Right, I realize. Just seemded to me that a "with" statement is
primarily useful with in-place methods. So I thought to take your
suggestion all the way to that point. But you are right, there is a
potential use without destructive methods, albiet less common.
I think that without a stricter type system, having the interpretter
make good use of turning a invocation into a modification might be
harder than you think (maybe even in general impossible - but good
enough in practice) - leaving the details up to us at this particular
level might be a good idea.

Yes, I imagine you are right. I am an unclear as to exactly how this
works. I know some have done such a thing (evil.rb for instance). But I
have also heared the phrase "segmentation fault" in reference to such
things too. There must be complications that I am unaware-of.

T.
 
M

Mathieu Bouchard

Currently I am converting the Fixnum to a number and inserting it inside
the Symbol but that's ugly.

D'oh. Converting Fixnum to a string. Like,

"_#{inletindex}_#{selector}".intern

_____________________________________________________________________
Mathieu Bouchard -=- Montréal QC Canada -=- http://artengine.ca/matju
 
C

Csaba Henk

From what I can tell, the basis for your alternative syntax (**) was
that (*) was not consistent.

You've misunderstood me. ** is not a proposed alternative syntax, it's
the direct consequence of *your* proposal.

Think a bit.

*a = getSomeIntegers # say it gives you [1,4,5]
ary.values_at *a # so it's the same as ary.values_at 1, 4, 5

What does it become if you don't bother to store the result of the
multivalue call in a?

ary.values_at **getSomeIntegers

My proposal was for *relaxing* the iterated stars. I suggested that in such
cases

ary.values_at getSomeIntegers

should behave in the same way as the two-star version, so you don't have
to bother with starstar.
Florian has already pointed out that it
is, in fact, consistent (the astericks functions as an array
'collector' already), so I think we're back to the single * syntax,
right?

That was fine from his part, I'm convinced about consistency. And among
all proposals which popped up in this thread I most like your one.

Csaba
 
C

Csaba Henk

We'll finally get keyword arguments in Rite and they're already in Ruby
1.9 as well.

Are they in current CVS? And how to use them? I didn't find any info
about it.

Csaba
 
F

Florian Gross

Csaba said:
Are they in current CVS? And how to use them? I didn't find any info
about it.

Hm, I'm not sure if the support has already been added to def, but the
following ought to work:

x(name: "Foobar", age: 100)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top