Ruby Lambda Context

ruby lambda context

the code you are looking for is

temp.instance_eval(&callable)

Ruby assign context to lambda?

Yeah, but be careful with it, this one is really easy to abuse. I would personally be apprehensive of code like this.

class Rule
def get_rule
Proc.new { puts name }
end
end

class Person
attr_accessor :name

def init_rule
@name = "ruby"
instance_eval(&Rule.new.get_rule)
end
end

How do I change the context of lambda?

You're close. If you want the lambda(/block, really) to execute in the context of an instance of C (since hi is an instance method on C), then you'll need to instantiate it and then instance_exec the block on that new instance:

class C
def self.filter_clause param_1, &block
puts new.instance_exec &block
end

def hi
"hello"
end
end

class B
def self.filter(value, lambda)
code = lambda { filter_clause(value, &lambda) }
C.instance_exec(&code)
end

filter(:name, ->{ hi })
end

# => hello

Execute lambda in the context of another object

The issue here is that the receiver of instance_eval is passed to the block as an argument. Procs allow for undeclared arguments, lambdas do not.

pr = proc {|*args| p args; a + 1 }
A.new.instance_eval &pr
[#<A:0x43668596>]
=> 6

If you declare your lambda such that it receives an argument, it works just fine:

> la = ->(recv) { a + 1 }
> A.new.instance_eval &la
=> 6

You could just (and probably want to) use instance_exec instead though:

> la = -> { a + 1 }
> A.new.instance_exec &la
=> 6
> la = ->(add) { a + 1 + add }
> A.new.instance_exec 10, &la
=> 16

Calling a lambda from another lambda. Why does the order matter?

first  = -> { defined? second }
second = -> { 'Ok' }
p first.call

results nil => The variable "second" is not defined in the lambda "first".

first  = -> { binding.receiver }
second = -> { 'Ok' }
p first.call

results main => This means that it uses the current binding of main and thus the variable "second" is defined only in the binding.

first  = -> { binding.local_variable_get(:second).call }
second = -> { 'Ok' }
p first.call

results "Ok". That's why the code also prints "Ok" when I ask for the content of the variable "second" of the binding.

Summary: The variable "second" is not defined in the lambda "first". The variable "second" is only defined in the binding. Therefore, the output of "local_variables" also returns "second" because the information is retrieved from the binding.

I also learned something myself. I hope I could help you!

when calling instance_eval(&lambda) to pass current context got error 'wrong number of arguments'

You are actually correct in your assumption. Self is being passed to the Proc and to the lambda as it is being instance_eval'ed. A major difference between Procs and lambdas is that lambdas check the arity of the block being being passed to them.

So:

 class Rule
def get_rule
lambda { |s| puts s.inspect; puts name; }
end
end

class Person
attr_accessor :name

def init_rule
@name = "ruby"
instance_eval(&Rule.new.get_rule)
end
end

p = Person.new
p.init_rule

#<Person:0x007fd1099f53d0 @name="ruby">
ruby

Here I told the lambda to expect a block with arity 1 and as you see in the argument inspection, the argument is indeed the self instance of Person class.

Getting the event body attributes in Ruby with AWS Lambda

event['body'] is going to return a string, a json string.

You need to parse it with something like this.

body = JSON.parse(event['body'])
my_int = body['message']

Also if you were to do.

puts event.inspect

instead of

puts "#{event['body']}"

you would have been able to see that body returned a string and not an object. I hope that helps and good luck.

Ruby lambda's proc's and 'instance_eval'

From the docs

For procs created using lambda or ->() an error is generated if the
wrong number of parameters are passed to a Proc with multiple
parameters. For procs created using Proc.new or Kernel.proc, extra
parameters are silently discarded.

In your case both lamb and proc called with one parameter

From the docs of instance_eval

When instance_eval is given a block, obj is also passed in as the
block's only argument

instance_eval is method of BasicObject class and can be called within instance. So given block will have access for private methods for example.

class Test
def call
secret_number + 100
end
private
def secret_number
42
end
end

test = Test.new
show_secret = -> (obj) { puts secret_number }

test.instance_eval(&show_secret) # print 42

Without instance self of current context will be passed as an argument. I think instance_eval was designed more for calling it within objects.

From the docs of instance_eval

In order to set the context, the variable self is set to obj while the
code is executing, giving the code access to obj's instance variables
and private methods.



Related Topics



Leave a reply



Submit