[#3741] Re: Why it's quiet -- standard distribution issues — Aleksi Niemel<aleksi.niemela@...>
I think it's the feature of the mailing list archive to create a threads of
[#3756] RE: XMP on comments — Aleksi Niemel<aleksi.niemela@...>
> require "xmp"
[#3766] modulo and remainder — Dave Thomas <Dave@...>
[#3776] Kernel.rand — Aleksi Niemel<aleksi.niemela@...>
How about defining:
[#3781] Widening out discussions — Dave Thomas <Dave@...>
[#3795] Re: Array.uniq! returning nil — Aleksi Niemel<aleksi.niemela@...>
> As matz said in [ruby-talk:3785] and Dave said in [ruby-talk:1229],
Hi, Aleksi,
[#3823] Re: Array.pick — Aleksi Niemel<aleksi.niemela@...>
> > Just a general comment--a brief statement of purpose and using
[#3827] JRuby? — Aleksi Niemel<aleksi.niemela@...>
Is there or will there be Ruby equivalent of JPython?
[#3882] Re: Array.uniq! returning nil — Aleksi Niemel<aleksi.niemela@...>
> |look too strange, confusing, or cryptic. Maybe just @, $, %, &.
Hi,
[#3918] A question about variable names... — Dave Thomas <Dave@...>
[#3935] If your company uses Pallets, Skids, Boxes, Lumber, etc. — pallets2@...
[#3956] Tk PhotoImage options — andy@... (Andrew Hunt)
Hi all,
[#3971] Thread and File do not work together — "Michael Neumann" <neumann@...>
following example do not work correctly with my ruby
[#3986] Re: Principle of least effort -- another Ruby virtue. — Andrew Hunt <andy@...>
> Principle of Least Effort.
Hi,
[#4005] Re: Pluggable functions and blocks — Aleksi Niemel<aleksi.niemela@...>
Aleksi makes a question:
[#4008] Ruby installation instructions for Windows — Aleksi Niemel<aleksi.niemela@...>
I had to write these instructions for my friends. I thought it might be nice
[#4043] What are you using Ruby for? — Dave Thomas <Dave@...>
On 15 Jul 2000 22:08:50 -0500,
Hi,
[#4057] Re: What are you using Ruby for? — Aleksi Niemel<aleksi.niemela@...>
Johann:
[#4082] Re: What are you using Ruby for? — Aleksi Niemel<aleksi.niemela@...>
[#4091] 'each' and 'in' — hal9000@...
I just recently realized why the default
[#4107] Re: 'each' and 'in' -- special char problem? — schneik@...
[#4114] Method signature - a question for the group — Dave Thomas <Dave@...>
[#4139] Facilitating Ruby self-propagation with the rig-it autopolymorph application. — Conrad Schneiker <schneik@...>
Hi,
[#4158] Getting Tk to work on Windows — "Michael Neumann" <neumann@...>
Hi....
[#4178] Partly converted English Ruby/Tk widget demo working. — Conrad Schneiker <schneik@...>
Hi,
[#4234] @ variables not updated within method? — Hugh Sasse Staff Elec Eng <hgs@...>
Hugh Sasse Staff Elec Eng <hgs@dmu.ac.uk> writes:
On 27 Jul 2000, Dave Thomas wrote:
[#4267] Ruby.next, Perl6, Python 3000, Tcl++, etc. -- Any opportunities for common implementation code? — "Conrad Schneiker" <schneiker@...>
Hi,
"Conrad Schneiker" wrote:
[ruby-talk:03949] Pluggable functions and blocks
Quite longish, but try to bear with me. There's a lot of questions too. They
are just hidden inside the mass of text :).
This question might too easy, but it's not apparently to me. I try to make
it as easy as possible for user to use pluggable functions (which means to
code without eval in any form, without class or module wrappers etc.). I'd
like to have these little snippets of code in other 'configuration' files,
but first I try to use pluggable functions in one file.
I'm not very picky about naming convention here. I talk about function
instead of method, even while all the code are really in methods or in
blocks, because the nature of the problem is just to have piece of code and
use it elsewhere. There should be nothing (visible) extra.
So here goes my simple example:
class Foo
def Foo.foo
puts "foo"
end
def do_foo( foo = proc {Foo.foo} )
foo.call
end
end
def my_foo
puts "bar"
end
Foo.new.do_foo
Foo.new.do_foo( proc {my_foo} ) # I'd like to say do_foo( my_foo )
This seems to work, outputting 'foo\nbar\n' as expected. It's tedious
anyway, and tediousness will turn into error-prone code later. The main
problem is to have explicit proc wrappings over functions.
When the logic is a little bit complex we will hit the first problem:
class Foo
def initialize(bool=true)
@bool = bool
end
def Foo.foo(bool)
if bool
return "foo"
else
return "no foo this time"
end
end
def do_foo( foo = proc {Foo.foo} )
puts foo.call(@bool)
end
end
def my_foo(bool)
if bool
return "bar"
else
return "no bar either"
end
end
Foo.new.do_foo
Foo.new(false).do_foo
Foo.new.do_foo( proc {my_foo} )
Foo.new(false).do_foo( proc {my_foo} )
This won't work anymore. The reason is that when we add an argument to
pluggable function we have to change each proc-wrappings. So then I came up
with a "clever" solution which yet another time post-pones the real fix of
the problem.
class Foo
def initialize(bool=true)
@bool = bool
end
def Foo.foo(bool)
if bool
return "foo"
else
return "no foo this time"
end
end
def do_foo( foo = proc {|*args| Foo.foo(*args)} )
puts foo.call(@bool)
end
end
def my_foo(bool)
if bool
return "bar"
else
return "no bar either"
end
end
Foo.new.do_foo
Foo.new(false).do_foo
Foo.new.do_foo( proc {|*args| my_foo(*args)} )
Foo.new(false).do_foo( proc {|*args| my_foo(*args)} )
Here just I'm probably stupid, but I can't make this work. This outputs:
foo
pluggable_func_4.rb:12:in `foo': wrong # of arguments(0 for 1)
(ArgumentError)
from pluggable_func_4.rb:12:in `do_foo'
from pluggable_func_4.rb:26:in `call'
from pluggable_func_4.rb:13:in `do_foo'
from pluggable_func_4.rb:26
Anyway if I'd be able to continue my story I'd point out few points:
Wrapping my_foo immediately to proc object by saying
my_foo = proc do |bool|
if bool
return "bar"
else
return "no bar either"
end
end
leads to:
pluggable_func_5.rb:19: return appeared outside of method
pluggable_func_5.rb:21: return appeared outside of method
and making a factory:
class Foo
def initialize(bool=true)
@bool = bool
end
def Foo.foo(bool)
if bool
return "foo"
else
return "no foo this time"
end
end
def do_foo( foo = proc {|bool| Foo.foo(bool)} )
puts foo.call(@bool)
end
end
def my_foo
return proc {
|bool|
if bool
return "bar"
else
return "no bar either"
end
}
end
Foo.new.do_foo
Foo.new(false).do_foo
Foo.new.do_foo( my_foo )
Foo.new(false).do_foo( my_foo )
leads to:
foo
no foo this time
pluggable_func_6.rb:21:in `call': return from proc-closure
(LocalJumpError)
from pluggable_func_6.rb:13:in `do_foo'
from pluggable_func_6.rb:31
because you can't return from block from multiple locations. The return
value is the evaluated value of the last expression.
In a nut shell:
** Turning 'def'-style code into proc leads to partial rewrite;
you can't return as freely as in 'def'
** Turning 'def'-style code into 'proc' may lead to
runtime errors instead of compile time errors
This means that proc and definitions are inherently different (more than
additional binding to variables). I wonder why this is so. Or maybe I should
rephrase and ask something different. Why there is no hierarcy for methods
(as a example of the interface, by no means the real thing)
class Method # abstract
def call
end
end
class ClassMethod < Method
@klass, @method
def initialize( klass, method )
end
end
class InstanceMethod < Method
@instance, @method
def initialize( instance, method )
end
end
class Block < Method
@block_binding
def initialize( proc = nil, &block)
end
end
then one could say
def use_pluggable_function( func )
puts func.call()
end
and don't care whether we happen to have a class method, a method for
particular instance (so the real call will be 'instance.method_name(args)'),
or a block.
I'm sure there's a good reason for this. Most likely one just don't need
them, you're able to code without such helper objects, or they're
implemented already in different (or same) form.
Finally, this all has lead me to think why we have blocks in the first
place. I try to handle them as a special case of syntax to write code neatly
(like 'for' is special case for 'each'; actually a little bit more special
than just syntax). In reality they turn out to be more than a subroutine
associated with external variable binding. How or for what, I don't know. I
don't know what's so special with them.
I like the idea of a method associated with a block, used powerfully in
standard library, but don't know why it ends there. If I think the
associated block as a optional argument (which it is, to quite big extent) I
don't know why we can't associate more blocks. I don't know how often this
is useful, but example cases might be
array.sort do primary_criteria end, do secondary_criteria end
or
set_callbacks_for_gui_object enter_cb, action_cb, leave_cb
Maybe I'm seeing things in too Perlish way but I think the way it handles
closures (or callback or "blocks") was easy. Writing "set_callbacks(
&callback, $cb_ref );" feels quite natural to me.
It's time for me to use more Ruby, so I appreciate if some one enlightens
me.
- Aleksi