Confused on how to use lambda in ruby for select - ruby

I'm working with ruby and I'm just learning lambdas. I have an array of objects and I want to select certain objects from the array based of different conditions like so:
result = array.select{|ar| ar.number > 4}
I want to put the arguments of the select into a lambda expression i.e. I want to put |ar| ar.number > 4 into a lambda expression. I've tried a few things including:
result = array.select{lambda{|g| g.number > 4}}
But this doesn't work.
I've also tried this:
l = lambda {g.number > 4}
result = array.select{|g| l}
and that also doesn't work. Also I need to pass my lambda express to a function so I don't think the first way I did it would have worked. How would I do this?

Enumerable#select takes a block, not a lambda. So, you need to pass it a block.
Thankfully, there is an operator which will convert a lambda or proc (and in fact anything which responds to to_proc) to a block: the unary prefix & operator, which is only valid in argument lists (where it converts a proc to a block) and in parameter lists (where it converts a block to a proc).
So, if you have a lambda l, you can pass it as a block to method foo like so:
foo(&l)
Your second problem is that your lambda doesn't take any arguments, but the block passed to select takes one argument, so you need to create your lambda with one argument:
l = lambda {|el| el.number > 4 }
# I prefer this syntax, though:
l = -> el { el.number > 4 }
Putting all that together, we have:
result = array.select(&l)

To pass a lambda (or a proc) to a method as a block, you have to use the special &syntax:
result = array.select &mylambda
Also, your lambda (or proc) must specify the name for parameters it will receive and use. Thus:
l = lambda { |g| g.number > 4}
result = array.select &l

A clean way to do this is to use Ruby's "stabby" lambda syntax:
l = ->(ar) { ar.number > 4 }
result = array.select(&l)
The more "traditional" way to define a lambda is as such:
l = lambda { |ar| ar.number > 4 }
result = array.select(&l)
Note that you don't strictly need to use a lambda; you could also use a proc*:
p = proc { |ar| ar.number > 4 }
result = array.select(&p)
* The main difference between proc and lambda is that lambda will throw an error when passed too few or too many arguments, while proc will ignore it. Another subtle difference is that the return statement inside a proc will cause execution to return both from the closure and the enclosing method (if any).

Related

How to make a number argument a variable?

How do I make a number argument a variable?
For example:
Snippet 1:
a=1
a_7 = a+6
alphabet = "ABCDEFGHIJKLMNOPQRSTUVQXYZ"
letter_7 = alphabet.slice[a_7..a_7]
Snippet 2:
alphabet = "ABCDEFGHIJKLMNOPQRSTUVQXYZ"
letter_7 = alphabet.slice[7..7]
I would like to make snippet 1 have the same outcome as snippet 2, with a variable as the arguments within slice action. Is there a way to do this?
So your issue come from the fact that you are using the slice method without any arguments. You can not use [] with the slice method. To make this work, you need to change [] to ()
letter_7 = alphabet.slice(7..7)
This will actually return H as the result, because arrays index start at 0, so to get the 7th letter, you will need to slice at index 6.
letter_7 = alphabet.slice(6..6) #=> 'G'
Or, you can just use the [] method on the string itself.
letter_7 = alphabet[6] #=> 'G'
Of course, you can replace the index values with variables, as long as the variables are set to integers.
a = 6
letter_7 = alphabet[a] #=> 'G'

Kotlin asterisk operator before variable name or Spread Operator in Kotlin

I want to know what exactly an asterisk does before a variable name in Kotlin.
I saw this (*args) in a Spring boot Kotlin example:
#SpringBootApplication
open class Application {
#Bean
open fun init(repository: CustomerRepository) = CommandLineRunner {
repository.save(Customer("Jack", "Bauer"))
repository.save(Customer("Chloe", "O'Brian"))
repository.save(Customer("Kim", "Bauer"))
repository.save(Customer("David", "Palmer"))
repository.save(Customer("Michelle", "Dessler"))
}
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
The * operator is known as the Spread Operator in Kotlin.
From the Kotlin Reference...
When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):
It can be applied to an Array before passing it into a function that accepts varargs.
For Example...
If you have a function that accepts a varied number of arguments...
fun sumOfNumbers(vararg numbers: Int): Int {
return numbers.sum()
}
Use the spread operator to pass an array's elements as the arguments:
val numbers = intArrayOf(2, 3, 4)
val sum = sumOfNumbers(*numbers)
println(sum) // Prints '9'
Notes:
The * operator is also the multiplication operator (of course).
The operator can only be used when passing arguments to a function. The result of the operation cannot be stored since it yields no value (it is purely syntactic sugar).
The operator may confuse some C/C++ programmers at first because it looks like a pointer is being de-referenced. It isn't; Kotlin has no notion of pointers.
The operator can be used in-between other arguments when calling a vararg function. This is demonstrated in the example here.
The operator is similar to the apply function in various functional programming languages.
In addition to the answers that were directly towards "what is this thing!?!", you often have the case where you have a List and want to pass it to a function that is expecting a vararg. For this, the conversion is:
someFunc(x, y, *myList.toTypedArray())
Assuming that last parameter of someFunc is vararg of the same type as the elements in the list.
As described in the documentation this is a spread operator:
When we call a vararg-function, we can pass arguments one-by-one, e.g.
asList(1, 2, 3), or, if we already have an array and want to pass its
contents to the function, we use the spread operator (prefix the array
with *):
val a = arrayOf(1, 2, 3)
val list = asList(-1, 0, *a, 4)
In Java you can pass an array as is but an advantage of unpacking an array with spread operator * is that spread operator lets you combine the values from an array and some fixed values in a single call. Java doesn't support this.
If a function which accept a vararg(Variable number of arguments) parameter like:
fun sum(vararg data:Int)
{
// function body here
}
Now to call this method, we can do:
sum(1,2,3,4,5)
But what if we have these value in an array, like:
val array= intArrayOf(1,2,3,4,5)
then, to call this method we have to use spread operator, like:
sum(*array)
Here, *(spread operator) will pass all content of that array.
*array is equivalent to 1,2,3,4,5
But wait a minute, what if we call it like this: sum(array)
it will give us Type Mismatch compile time error:
Type mismatch.
Required:Int
Found:IntArray
The problem is sum function accept a vararg Int parameter(which accept value like: 1,2,3,4,5) and if we pass array, it will be passed as IntArray.

Why variables setted inside Enum.each is not saved?

I'm trying to set a value to a variable inside a function in Enum.each, but at the end of loop, variable is empty and I don't know exactly why this behaviour.
Code:
base = "master"
candidates = ["stream", "pigeons", "maters"]
return = []
Enum.each(candidates, fn candidate ->
cond do
String.length(base) == String.length(candidate) ->
return = return ++ [candidate]
true ->
true
end
end)
IO.inspect return
At this example, return is expected to be ["stream", "maters"], but instead, it is only an empty list: []
My question is why this happens.
When dealing with languages like Elixir, it is better to think in terms of "values" and "names" instead of "variables".
The reason you cannot do what you want is that Elixir has "lexical scoping".
When you assign to a "variable", you create a new value in the inner scope. You never change the "value" of a "name" defined in the outer scope.
(you probably can get what you want with Enum.filter/2, but I'm guessing this is just an illustrative example)
EDIT:
As of today, Elixir will allow you to write something like this:
if condition_that_evals_to_false do
x = 1
else
x = 2
end
IO.inspect x # => 2
```
But this will be deprecated in Elixir 1.3
Any reason why you don't just filter?
Anyways it seems like you're trying to mutate the value of return which is not possible with Elixir.
base = "master"
candidates = ["stream", "pigeon", "maters"]
result = Enum.filter(candidates, fn(candidate) ->
length(candidate) == length(base)
end
IO.inspect result
Edit: I'd also like to add that based on your logic, all of the candidates would be returned
Not sure, since I've never worked with the language, but a couple things spring to mind:
String.length(base) == String.length(candidate) can be equivalent to true, which is already a pattern in your set.
It could also be a scope issue with the return variable. It could be that the local return is hiding the global return. You could check this by outputting return every iteration. Each iteration the return should contain a single entry.
This is a bug. From Elixir's documentation:
Note: due to a bug in the 0.12.x series, cond‘s conditions actually
leak bindings to the surrounding scope. This should be fixed in
0.13.1.
You should use filtering like #{Christopher Yammine} suggested.

Ruby: evaluate string with dynamic binding of variables

I have a database of "formulas" stored as strings. Let's assume for simplicity, that each formula contains 2 variables denoted by a and b, and that the formulas are all wellformed and it is ensured that it consists only of characters from the set ()ab+-*.
At runtime, formulas are fetched from this database, and from another source, numeric values for a and b are fetched, and the formulas are evaluated. The evaluation can be programmed like this:
# This is how it works right now
formula = fetch_formula(....)
a = fetch_left_arg(....)
b = fetch_right_arg(....)
result = eval(formula)
This design works, but I'm not entirely happy with it. It requires that my program names the free variables exactly the same as they are named in the formula, which is ugly.
If my "formula" would not be a string, but a Proc object or Lambda which accepts two parameters, I could do something like
# No explicitly named variables
result = fetch_proc(...).call(fetch_left_arg(....),fetch_right_arg(....))
but unfortunately, the formulas have to be strings.
I tried to experiment in the following way: What if the method, which fetches the formula from the database, would wrap the string into something, which behaves like a block, and where I could pass parameters to it?
# This does not work of course, but maybe you get the idea:
block_string = "|a,b| #{fetch_formula(....)}"
Of course I can't eval such a block_string, but is there something similar which I could use? I know that instance_eval can pass parameters, but what object should I apply it to? So this is perhaps not an option either....
This is very nasty approach, but for simple formulas you’ve mentioned it should work:
▶ formula = 'a + b'
▶ vars = formula.scan(/[a-z]+/).uniq.join(',') # getting vars names
#⇒ "a,b"
▶ pr = eval("proc { |#{vars}| #{formula} }") # preparing proc
▶ pr.call 3, 5
#⇒ 8
Here we rely on the fact, that parameters are passed to the proc in the same order, as they appear in the formula.
If I get your question correctly, it is something that I have done recently, and is fairly easy. Given a string:
s = "{|x, y| x + y}"
You can create a proc by doing:
eval("Proc.new#{s}")
One way to avoid creating the variables in the local scope could be to use a Binding:
bind = binding
formula = fetch_formula(....)
bind.local_variable_set :a, fetch_left_arg(....)
bind.local_variable_set :b, fetch_right_arg(....)
result = bind.eval(formula)
The variables a and b now only exist in the binding, and do not pollute the rest of your code.
You can create a lambda from string, as shown below:
formula = "a + b"
lambda_template = "->(a,b) { %s }"
formula_lambda = eval(lambda_template % formula)
p formula_lambda.call(1,2)
#=> 3

Ruby: Assign output of a function only if it does not return nil

When programming in Ruby I quite often have assignments like the following
test = some_function if some_function
With that assignments I want to assign the output of a function, but if it returns nil I want to keep the content of the variable. I know there are conditional assignments, but neither ||= nor &&= can be used here. The shortest way I found to describe the statement above is
test = (some_function or test)
Is there a better / shorter way to do this?
I don't think there's anything better than the last snippet you showed but note that or is used for flow control, use || instead:
test = some_function || test
It's usually better to assign new values to new names, the resulting code is easier to understand and debug since variables/symbols have the same value throughout the scope:
some_different_and_descriptive_name_here = some_function || test
I'd just add parentheses
(a = b) unless b.nil?
(a = b) if b
being inferior because if b is false then a remains as before
Keep in mind that this evaluates b twice, so if b is a function with side-effects (such as changing variables outside of its scope or printing) it will do that twice; to avoid this you must use
temp = b; (a = temp) unless temp.nil?
(which can, of course, be split into)
temp = b
(a = temp) unless temp.nil?

Resources