How to make the function accept a block - ruby

I am having a class G and my custom function func which i expect to take a block like this:
class G
def func(&block)
return '1' unless block_given?
# More code
end
end
I think that now when i do
G g = new G
g.func {|t| t}
block_given? should return true but its returning false
I hve tried following variants as well to no resort
g.func do |t|
end
Any help would be appreciated.

It's working fine if you correct some minor syntax errors. Note that there is no type declaration for ruby variables and object instantiation is done through an instance method of class Class instead with keyword (like in Java):
class G
def func(&block)
return '1' unless block_given?
block.call
end
end
g = G.new
g.func { puts 'block was called' }
g.func
# Output:
# irb(main):046:0>g.func { puts 'block was called' }
# block was called
# => nil
# irb(main):047:0>g.func
# => "1"

(Adding my output, although Matt beat me to it.)
> class G
> def func(&block)
> return '1' unless block_given?
> # More code
> end
> end
=> nil
> g = G.new
=> #<G:0x856e444>
> g.func { |t| puts "hi" }
=> nil
> g.func
=> "1"

Related

Ruby - How to associate method with another method

I'm new to Ruby, and expect to use methods inside of method or associate construct_const method with interpret method. Interpret method should simply return the value for this constant
def construct_const(value)
def interpret()
return #value
end
end
e = construct_const(0)
assert_equal(0, e.interpret)
In your posting, you are using value and #value. I guess this is a typo, since you are not refering value anywhere in your example code, so I assume that you wanted to use value in your interpret method, not #value.
You can define a method on the fly for a certain object using define_singleton_method, i.e.
def construct_const(value)
define_singleton_method(:interpret) { value }
end
With this, if you do then a
e.construct_const
the variable e will then have a new method 'interpret` attached to it.
When you define interpret method inside construct_const you get a :interpret symbol as the result of calling construct_const. Because every statement returns a value defining a method returns the method name.
> def interpret()
> return #value
> end
=> :interpret
So each time you call construct_const you define a method and return its name.
Also, you mismatch a local variable value and an instance variable #value.
You can use lambda or proc to return a function, the function will have call method:
def construct_const(value)
-> { value }
end
> e = construct_const(0)
=> #<Proc:0x000055c060a47f60#(irb):12 (lambda)>
> e.call
=> 0
You can define an anonymous class with a method interpret:
def construct_const(value)
my_class = Class.new do
def initialize(value)
#value = value
end
def interpret
#value # Here you can use an instance variable because it's inside of the anonymous class
end
end
my_class.new(value) # Pass a value to initialize a new instance
end
> e = construct_const(0)
=> #<#<Class:0x0000563663366c68>:0x0000563663366b50 #value=0>
> e.interpret
=> 0
A similar solution but with a predefined class:
class Interpreter
def initialize(value)
#value = value
end
def interpret
#value
end
end
def construct_const(value)
Interpreter.new(value)
end
> e = construct_const(0)
=> #<Interpreter:0x0000563663367b68 #value=0>
> e.interpret
=> 0
A solutions with Struct object:
def construct_const(value)
Struct.new(:interpret).new(value)
end
> e = construct_const(0)
=> #<struct interpret=0>
> e.interpret
=> 0
You've probably had better answers already, but as far as I can see, these seem to work (though I don't really know what I'm doing):
def construct_const(value)
mod = Module.new
mod.module_eval do
define_method :interpret do
value
end
end
obj = Object.new
obj.extend(mod)
obj
end
e = construct_const(0)
=> #<Object:0x00000000084a0e90>
e.interpret
=> 0
def construct_const(value)
obj = Object.new
obj.instance_eval do
#value = value
def interpret
#value
end
end
obj
end
e = construct_const(0)
=> #<Object:0x000000000a369098 #value=0>
e.interpret
=> 0

How to implement autovivification for Ruby structs?

Ruby has support for autovivification for hashes by passing a block to Hash.new:
hash = Hash.new { |h, k| h[k] = 42 }
hash[:foo] += 1 # => 43
I'd like to implement autovivification for structs, also. This is the best I can come up with:
Foo = Struct.new(:bar) do
def bar
self[:bar] ||= 42
end
end
foo = Foo.new
foo.bar += 1 # => 43
and of course, this only autovivifies the named accessor (foo.bar), not the [] form (foo[:bar]). Is there a better way to implement autovivification for structs, in particular one that works robustly for both the foo.bar and foo[:bar] forms?
I would go with the following approach:
module StructVivificator
def self.prepended(base)
base.send(:define_method, :default_proc) do |&λ|
instance_variable_set(:#λ, λ)
end
end
def [](name)
super || #λ && #λ.() # or more sophisticated checks
end
end
Foo = Struct.new(:bar) do
prepend StructVivificator
end
foo = Foo.new
foo.default_proc { 42 } # declare a `default_proc` as in Hash
foo[:bar] += 1 # => 43
foo.bar += 1 # => 44
foo.bar above calls foo[:bar] under the hood through method_missing magic, so the only thing to overwrite is a Struct#[] method.
Prepending a module makes it more robust, per-instance and in general more flexible.
The code above is just an example. To copy the behavior of Hash#default_proc one might (credits to #Stefan for comments):
module StructVivificator
def self.prepended(base)
raise 'Sorry, structs only!' unless base < Struct
base.singleton_class.prepend(Module.new do
def new(*args, &λ) # override `new` to accept block
super(*args).tap { #λ = λ }
end
end)
base.send(:define_method, :default_proc=) { |λ| #λ = λ }
base.send(:define_method, :default_proc) { |&λ| λ ? #λ = λ : #λ }
# override accessors (additional advantage: performance/clarity)
base.members.each do |m|
base.send(:define_method, m) { self[m] }
base.send(:define_method, "#{m}=") { |value| self[m] = value }
end
end
def [](name)
super || default_proc && default_proc.(name) # or more sophisticated checks
end
end
Now default_proc lambda will receive a name to decide how to behave in such a case.
Foo = Struct.new(:bar, :baz) do
prepend StructVivificator
end
foo = Foo.new
foo.default_proc = ->(name) { name == :bar ? 42 : 0 }
puts foo.bar # => 42
puts foo[:bar] += 1 # => 43
puts foo.bar += 1 # => 44
puts foo[:baz] += 1 # => 1

Method overriding in Ruby

I have code that looks like this:
module A
def b(a)
a+1
end
end
class B
include A
end
I would like to write a method in the class B that looks sort of like this
class B
def b(a)
if a==2 # are you sure? same result as the old method
3
else
A.b(a)
end
end
end
How do I go about doing this in Ruby?
You want the super function, which invokes the 'previous' definition of the function:
module A
def b(a)
p 'A.b'
end
end
class B
include A
def b(a)
if a == 2
p 'B.b'
else
super(a) # Or even just `super`
end
end
end
b = B.new
b.b(2) # "B.b"
b.b(5) # "A.b"
class B
alias old_b b # one way to memorize the old method b , using super below is also possible
def b(a)
if a==2
'3' # returning a string here, so you can see that it works
else
old_b(a) # or call super here
end
end
end
ruby-1.9.2-p0 > x = B.new
=> #<B:0x00000001029c88>
ruby-1.9.2-p0 >
ruby-1.9.2-p0 > x.b(1)
=> 2
ruby-1.9.2-p0 > x.b(2)
=> "3"
ruby-1.9.2-p0 > x.b(3)
=> 4

Can you eval code in the context of a caller in Ruby?

Essentially I'm wondering if the following can be done in Ruby.
So for example:
def bar(symbol)
# magic code goes here, it outputs "a = 100"
end
def foo
a = 100
bar(:a)
end
You have to pass foo's context to bar:
def foo
a = 100
bar(:a, binding)
end
def bar(sym, b)
puts "#{sym} is #{eval(sym.to_s, b)}"
end
There is no built-in way to get a callers binding in Ruby in 1.8.X or 1.9.X.
You can use https://github.com/banister/binding_of_caller to work around.
In MRI 2.0 you can use RubyVM::DebugInspector, see: https://github.com/banister/binding_of_caller/blob/master/lib/binding_of_caller/mri2.rb
Working sample in MRI 2.0:
require 'debug_inspector'
def bar(symbol)
RubyVM::DebugInspector.open do |inspector|
val = eval(symbol.to_s, inspector.frame_binding(2))
puts "#{symbol}: #{val}"
end
end
def foo
a = 100
bar(:a)
end
foo
# a: 100
Here's a easier syntax hack, using a passed in block binding:
def loginfo &block
what = yield.to_s
evaled = eval(what, block.binding)
Rails.logger.info "#{what} = #{evaled.inspect}"
end
called like this:
x = 1
loginfo{ :x }
will log out:
x = 1
Just FYI, here's a "hacky way".
This is my (re-)implementation of well-known ppp.rb:
#!/usr/bin/ruby
#
# better ppp.rb
#
require 'continuation' if RUBY_VERSION >= '1.9.0'
def ppp(*sym)
cc = nil
ok = false
set_trace_func lambda {|event, file, lineno, id, binding, klass|
if ok
set_trace_func nil
cc.call(binding)
else
ok = event == "return"
end
}
return unless bb = callcc{|c| cc = c; nil }
sym.map{|s| v = eval(s.to_s, bb); puts "#{s.inspect} = #{v}"; v }
end
a = 1
s = "hello"
ppp :a, :s
exit 0
This currently fails with 1.9.[012] due to a bug in ruby's set_trace_func.
Check article out Variable Bindings in Ruby
class Reference
def initialize(var_name, vars)
#getter = eval "lambda { #{var_name} }", vars
#setter = eval "lambda { |v| #{var_name} = v }", vars
end
def value
#getter.call
end
def value=(new_value)
#setter.call(new_value)
end
end
def ref(&block)
Reference.new(block.call, block.binding)
end
def bar(ref)
# magic code goes here, it outputs "a = 100"
p ref.value
end
def foo
a = 100
bar(ref{:a})
end
foo

Class returning an array

I have a class like:
class Configuration
def self.files
##files ||= Array.new
end
end
Now instead of doing this:
irb(main):001:0> Configuration.files
=> [file, file, file]
I would like to be able to do this:
irb(main):001:0> Configuration
=> [file, file, file]
But I can't figure out how, any ideas?
#glenn jackman:
I was thinking of adding extra methods to a 'Configuration' constant that's a hash. So if I had...
Configuration = Hash.new
Configuration[:foo] = 'bar'
I wanted to be able to save this Configuration hash constant to be able to dump to and load from a YAML file I wanted to be able to use...
Configuration.load
Configuration.save
I wanted the Configuration class to look like
class Configuration
def self.save
open('config.yml', 'w') {|f| YAML.dump( self , f)}
end
def self.load
open('config.yml') {|f| YAML.load(f)}
end
end
You could possibly get the effect you are looking for by adding a method to the top level object which implicitly calls Configuration.files, but you can't really make a reference to a class invoke a method on it. You can alias the method to something shorter, but you will need to call something.
irb's top level just calls 'inspect' on the result, so by overriding it you can customize what you see in irb:
$ irb
>> class Configuration
>> def self.files
>> ##files ||= Array.new
>> end
>> def self.inspect
>> ##files.inspect
>> end
>> end
=> nil
>> Configuration.files << 1 << 2 << 3
=> [1, 2, 3]
>> Configuration
=> [1, 2, 3]
You could do something like this:
class Configuration
(class << self; self; end).module_eval do
def files
['foo','bar','baz']
end
def to_s
files
end
end
end
This would define the Configuration.files method and say that the to string conversion would return the result of that method. But I am really not sure why you would want to do this. It seems quite wrong.
wpc#wpc-laptop:~$ irb
irb(main):001:0> 'a'
=> a
irb(main):002:0> def A
irb(main):003:1> end
=> nil
irb(main):004:0> A
NameError: uninitialized constant A
from (irb):4
from :0
irb(main):005:0> class A
irb(main):006:1> end
=> nil
irb(main):007:0> A
=> A
irb(main):008:0> class A
irb(main):009:1> (class ['g']
irb(main):012:3> end
irb(main):013:2> def to_s
irb(main):014:3> g
irb(main):015:3> end
irb(main):016:2> end
irb(main):017:1> end
=> nil
irb(main):018:0> A
=> g
irb(main):019:0> class B
irb(main):020:1> class def to_s
irb(main):022:3> 'g'
irb(main):023:3> end
irb(main):024:2> end
irb(main):025:1> end
=> nil
irb(main):026:0> B
=> g
irb(main):027:0> class B
irb(main):028:1> class def files
irb(main):030:3> ['a','b','c']
irb(main):031:3> end
irb(main):032:2> def to_s
irb(main):033:3> files
irb(main):034:3> end
irb(main):035:2> end
irb(main):036:1> end
=> nil
irb(main):037:0> B
=> abc
The right solution is to using the class' method of to_s, but what it return is only the string; and then you can set the inspect for using. See the follows' detail for help.
class A
class<<self
def to_s
......
end
end
end

Resources