Skip to main content

Passing Functions and Lambdas into Functions with Ruby

Ruby's New Style of Lambda Functions


f = ->( m ) { p m }
f.call( 1 )
#=> 1
Which of course means the same thing as:


f = lambda { |n| p n }
f.call(1)
#=> 1

Ruby Proc Objects


p = Proc.new { |n| p n + 2 }
p.call(2)
#=> 4

Using a Function as a Closure in Ruby


def domo( k )
  ->(m) { p m + k }
end

z = domo( 5 )
z.call( 5 )
#=> 10
Function :domo takes a single parameter. Within :domo, we create a lambda that takes a single parameter, and adds that parameter to the value :domo takes in as its parameter. Then, we assign z to be the result of the lambda in :domo with its 'k' parameter loaded with 5.

When z is called, we pass (another) 5 to it. This parameter loads the lambdas n parameter. The lambda executes, essentially adding n(5) + k(5) and yielding the result of 10.

The thing about closures such as this is, we can load the initial value of the lambda to be whatever we want it to be when assigning the function :domo's return value to z. That becomes a fixed value that z will always have. But..., we can call z with whatever value we wish to add z to. For example:


z = domo(6)
z.call(4)
#=> 10
z.call(6)
#=> 12

etc., etc. That's the power of the closure. You could set up a number of such closures with constant values set up, and then operate on those values with whatever numbers you wish to pass in. Each closure represents its own individual processing with its own loaded value.

Passing Functions to Functions in Ruby


def fritter( f, n )
  func = method( f )
  func.call( :n => n )
end

def mac( opts = {} )
  v = opts[ :n ]
  v + 6
end

p fritter( :mac, 6 )
# => 12

Passing one function to another function as a parameter is how Ruby can be used in a functional programming style. The function :fritter takes the function :mac, as well as a number, as parameters.

Inside :fritter, on the first line, the symbol passed in to parameter f is converted to a method object via the :method function. This method object is stored in the variable, func.
Next, on the second line of :fritter, we call the method object, which is the method, :mac, sending it the parameter 6
To pass a function to another function in Ruby, the name of the function is passed. To name a function, a symbol must be used. It is the symbol that represents the functions name. So, the name of the mac function is :mac.

Now, consider the function, :mac. :mac takes a hash as a parameter. Inside the function, the local variable, v is assigned either the value attached to the key :n, or 1 if :n has no value. :mac then returns the sum of its local variable v, and the number 6.

Finally, the function call of :fritter, with the parameters of the :mac function, and the numeral 6 ( note that this 6 id different from the 6 within the body of :mac. So, :fritter is called, and it returns the return value of :mac called itself with a parameter of 6!

Somewhat convoluted? Admittedly, this example is. But its the idea that is important. You can change the functions to solve whatever problem you're working on. Here I wanted to show just the mechanics of passing a function a function.

Passing Lambdas to a Function in Ruby


@even = ->( n ) { n % 2 == 0 }

def fun( e, n )
  e.call( n )
end

def negate( e, n )
  !e.call( n )
end

The lambda here, @even, simply takes an input parameter of n, and tests to see if it is even.
The function, :fun, simply calls the @even lambda with the numeral parameter, n that is passed in.

The function, :negate, literally does the opposite of :fun. It does this in a very simple way: it literally
negates the @even function called with the numerical parameter, n.


fun( @even, 2 )
#=> true
fun( @even, 1 )
#=> false
negate( @even, 2 )
#=> false
negate( @even, 1 )
#=> true

Both of the functions are called, each with an even value, and an odd value. They return the expected boolean results.

Comments

Popular posts from this blog

Install current SBCL on OS X

You must have Command Line Tools installed. If you don't , this tutorial is not for you. Google: installation of XCode and Command Line Tools. Normally, I use brew to install things (when it offers a solution), but in this case the keg version was a couple minor version's off. And, there had been sufficient addition's that motivated me to want the current release. So, building from source was the path of least resistance. First, what not to do : The note's caution against using OS X's Terminal , as their make.sh script pukes a shit-ton of text during the build, and according to them, it can slow the build. I did not experience an issue with this, compared to other builds I've done in the past.   BUT , they also say build can be accomplished with other LISP's installed (you must have a lisp installed prior to building). OMFG , unless you want to wait a month of Sunday's, my experience building with CLISP was slower than the Molasses in January.  D

React Simplicity

This is just a quick intro to React to show how easy it is on a very basic level. React is often compared to Angular, but the two are very different: Angular is more of a framework , whereas React is more of a library . So, with React, we can make Components, and in so doing, we can intersperse plain Javascript to instill behavior. This article is not showing (or using) best practices, or a recommended structure. It's purpose is only to show how easy the basic mechanics of React are. Let's grab the getting started cli from React's page npm install -g create-react-app create-react-app my-app cd my-app npm start After this is done, and you have the project displayed in your browser, let's experiment. A boiler-plate header we can use for each new class can be as simple as: /src/Foo.js import React, { Component } from 'react'; class Foo extends Component { render(){ return(); } } export default Foo; So, all that we need to change to get st

Dead Simple React.js with Meteor

I spent a little time exploring the patterns involved in using React.js with Meteor. It's incredibly easy, it turns out. I'll show some examples here. The setup: meteor add kadira:flow-router npm install react react-dom react-mounter npm install react-addons-pure-render-mixin meteor add react-meteor-data Then of course remove all blaze related meteor packages. Ok, Some basic component patterns: Let's create one that accepts a single argument: Hello.jsx import React from 'react'; export const Hello = ({name}) => ( <div>Hello, {name}</div> ); That's all there is to it. Now, let's see a pattern for a component that takes two arguments. We can see that to add further arguments, we can just tack them on after the first two: TwoArgs.jsx import React from 'react'; export const TwoArgs = ({one, two}) => ( <div> <h2>TwoArgs!</h2> <h3>One is: {one}</h3> <h3>Two is: {two}&