How to Reference a Lambda from Within Itself Using Ruby

How to make Lambda (or lambda-like object) to call itself with a new parameter it got (Ruby)

Slightly confused, is this what you're trying to achieve? I notice you have variable x, but this isn't referred anywhere (just answer is).

lam = ->(x) do
x = Integer(x)

case x
when 1
x * 5
when 2
x * 10
else
puts 'Please enter 1 or 2'
input = gets.chomp
lam.call(input)
end
end

# 2.2.2 > lam.call(5)
# Please enter 1 or 2
# 3
# Please enter 1 or 2
# 2
# => 20
# 2.2.2 > lam.call(1)
# => 5

In Ruby, how can I reference a lambda defined in a module?

try this:

module GalleryGenerator
def self.add_links_to_descriptions
lambda do |mutable_viewable_content|
mutable_viewable_content.description = add_links_to_sources(mutable_viewable_content.description)
return mutable_viewable_content
end
end
#...
end

and call it with GalleryGenerator.add_links_to_descriptions

returning a method reference wrapped in a lambda

Lambdas (and blocks, and procs) in Ruby are closures; this means that local variables available in the same scope as the lambda is defined are accessible inside the lambda. For example:

foo = 42
l = lambda{ p foo }
l.call()
#=> 42

The above should not be any more surprising than the fact that this code works:

x = 17
[1,2,3].map do |n|
n+x # Whoa, you can use _x_ here?!
end
#=> [18,19,20]

It's slightly more surprising when you do something like this:

def make_adder( x )
->(y){ x+y }
end
add10 = make_adder(10)
z = add10.call(32) #=> 42

Again, the local variable x (the parameter passed to the method) is "closed over" by the lambda, its value preserved for reference whenever the lambda is invoked.

So in your example the lambda is just "capturing" the bark_string variable and returning its value later on. Your method is never invoked a second time.


Note that a closure captures the variable itself, not just the object referred to by the variable:

x = "hello"
y = x # reference the same _object_
l = ->{ x } # close over the _variable_ itself
x = "world" # change the variable to point to a new object

p y, #=> "hello" (same object as the original)
l[] #=> "world" (new object)

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!

can you pass self to lambda in rails?

Disclaimer: First, the question (Can you pass self to lambda?) and the problem you're trying to solve (dynamic styles with paperclip) don't fully match up. I won't answer the original question because it's not entirely related to your problem, and rampion took a valiant stab at it.

I'll instead answer your paperclip question.

In detail it is the has_attached_file method for the paperclip plugin in rails. I want to pass a lambda for the styles hash so that the image styles can be based off of attributes of the object stored in the DB. Is this possible?

Yes, it is possible. In paperclip, the :styles option can take a Proc. When the attachment is initialized, if a Proc was used, the attachment itself is passed to the Proc. The attachment has a reference to the associated ActiveRecord object, so you can use that to determine your dynamic styles.

For example, your has_attached_file declaration might look something like this (assuming a User and avatar scenario where the user can customize the size of their avatar):

class User < ActiveRecord::Base
has_attached_file :avatar, :styles => lambda { |attachment|
user = attachment.instance
dimensions = "#{user.avatar_width}x#{user.avatar_height}#"
{ :custom => dimensions }
}
end

Reference the invoking object in the passed block in Ruby

You can use something similar to Instance eval with delegation pattern, used - for example - in Savon gem:

def batman(task, &block)
@original_self = eval('self', block.binding)
puts "Batman: #{task} - done"
instance_exec('feed cat', &block)
@news << task
end

private

def method_missing(method, *args, &block)
if @original_self
@original_self.send(method, *args, &block)
else
super
end
end

In this approach, when you call method (with implicit receiver) inside block passed into batman method, it's called in the context of SuperHeros instance. If there is no such method available, the call goes (through method_missing) to original block self.

Where and when to use Lambda?

It's true, you don't need anonymous functions (or lambdas, or whatever you want to call them). But there are a lot of things you don't need. You don't need classes—just pass all the instance variables around to ordinary functions. Then

class Foo
attr_accessor :bar, :baz
def frob(x)
bar = baz*x
end
end

would become

def new_Foo(bar,baz)
[bar,baz]
end

def bar(foo)
foo[0]
end
# Other attribute accessors stripped for brevity's sake

def frob(foo,x)
foo[0] = foo[1]*x
end

Similarly, you don't need any loops except for loop...end with if and break. I could go on and on.1 But you want to program with classes in Ruby. You want to be able to use while loops, or maybe even array.each { |x| ... }, and you want to be able to use unless instead of if not.

Just like these features, anonymous functions are there to help you express things elegantly, concisely, and sensibly. Being able to write some_function(lambda { |x,y| x + f(y) }) is much nicer than having to write

def temp(x,y)
x + f(y)
end
some_function temp

It's much bulkier to have to break off the flow of code to write out a deffed function, which then has to be given a useless name, when it's just as clear to write the operation in-line. It's true that there's nowhere you must use a lambda, but there are lots of places I'd much rather use a lambda.

Ruby solves a lot of the lambda-using cases with blocks: all the functions like each, map, and open which can take a block as an argument are basically taking a special-cased anonymous function. array.map { |x| f(x) + g(x) } is the same as array.map(&lambda { |x| f(x) + g(x) }) (where the & just makes the lambda "special" in the same way that the bare block is). Again, you could write out a separate deffed function every time—but why would you want to?

Languages other than Ruby which support that style of programming don't have blocks, but often support a lighter-weight lambda syntax, such as Haskell's \x -> f x + g x, or C#'s x => f(x) + g(x);2. Any time I have a function which needs to take some abstract behavior, such as map, or each, or on_clicked, I'm going to be thankful for the ability to pass in a lambda instead of a named function, because it's just that much easier. Eventually, you stop thinking of them as somehow special—they're about as exciting as literal syntax for arrays instead of empty().append(1).append(2).append(3). Just another useful part of the language.


1: In the degenerate case, you really only need eight instructions: +-<>[].,. <> move an imaginary "pointer" along an array; +- increment and decrement the integer in the current cell; [] perform a loop-while-non-zero; and ., do input and output. In fact, you really only need just one instruction, such as subleq a b c (subtract a from b and jump to c if the result is less than or equal to zero).

2: I've never actually used C#, so if that syntax is wrong, feel free to correct it.

returning a method reference wrapped in a lambda

Lambdas (and blocks, and procs) in Ruby are closures; this means that local variables available in the same scope as the lambda is defined are accessible inside the lambda. For example:

foo = 42
l = lambda{ p foo }
l.call()
#=> 42

The above should not be any more surprising than the fact that this code works:

x = 17
[1,2,3].map do |n|
n+x # Whoa, you can use _x_ here?!
end
#=> [18,19,20]

It's slightly more surprising when you do something like this:

def make_adder( x )
->(y){ x+y }
end
add10 = make_adder(10)
z = add10.call(32) #=> 42

Again, the local variable x (the parameter passed to the method) is "closed over" by the lambda, its value preserved for reference whenever the lambda is invoked.

So in your example the lambda is just "capturing" the bark_string variable and returning its value later on. Your method is never invoked a second time.


Note that a closure captures the variable itself, not just the object referred to by the variable:

x = "hello"
y = x # reference the same _object_
l = ->{ x } # close over the _variable_ itself
x = "world" # change the variable to point to a new object

p y, #=> "hello" (same object as the original)
l[] #=> "world" (new object)

How to return a lambda that is returned by another method in Ruby

n_times is a method requiring one argument, you are calling it as the first argument passed to other, but without an argument. That's the error you are getting. You want to pass method(:n_times) which converts it to a Proc rather than calling it.

Secondly you have counter(thing) inside the other method. This is calling the method called 'counter', rather than using the object called 'counter' which is passed as an argument. You want to change that to counter[thing].

Lastly, you are passing 10 to n_times and calling the resulting lambda with "what", but that evaluates 10 * "what" which is a NoMethodError. You need to reverse those arguments.

All together:

def n_times(thing)
lambda { |n| thing * n }
end

def other(counter, thing)
counter[thing]
end

other(method(:n_times), "what").call(10)
# "whatwhatwhatwhatwhatwhatwhatwhatwhatwhat"


Related Topics



Leave a reply



Submit