Ruby blocks behave unexpectedly when using "do" [duplicate] - ruby

This question already has answers here:
do..end vs curly braces for blocks in Ruby
(14 answers)
Closed 5 years ago.
I was trying to solve a coding puzzle: Take strings, and count the ones that don't include repeated words.
This code works:
def validate(passphrase)
words = passphrase.split
words == words.uniq
end
passphrases = File.readlines("../input/passphrases.txt")
p passphrases.count {|phrase| validate(phrase)}
#=> 337
If I make one minor change with the count block, it counts all of the passphrases instead of just the ones that would return true when passed through the block:
p passphrases.count do |phrase|
validate(phrase)
end
#=>512
What's up with this?

It is due to argument precedence with the do block.
Your first example is equivalent to:
p(passphrases.count {|phrase| validate(phrase)})
The second one with the do block is equivalent to:
p(passphrases.count) do |phrase|
validate(phrase)
end
Where the do is being applied to the p function.
If you want the second case to match the first, wrap the whole block in parenthesis:
p(passphrases.count do |phrase|
validate(phrase)
end)

Related

what is the difference between .capitalize and .capitalize!(or .map & .map!...etc.) and in ruby [duplicate]

This question already has answers here:
What is the purpose of "!" and "?" at the end of method names?
(5 answers)
Closed 6 years ago.
learning how to code with Ruby and was trying learn from test first.
and I stumbled something funny.
I was trying to capitalize every word but
title = 'stuart little'
a = title.split
a.each do |x|
x.capitalize
end
a.join(' ')
This one's result is 'stuart little'
but if I add the ! in capitalize
title = 'stuart little'
a = title.split
a.each do |x|
x.capitalize!
end
a.join(' ')
it ends up with the result I want which is 'Stuart Little'
just .capitalize should work shouldn't it? since I'm just capitalizing the words. and what makes .capitalize! work in this scenario?
When a method has a ! at the end in Ruby, it is commonly referred to as a bang-method. The exclamation point indicates that the method is the dangerous version of another method.
In this case, capitalize! will modify your string, while capitalize will return a new string object. Since you are later calling on your original objects (the strings in a), your code will only work with capitalize!. To make the code work with capitalize, you would have to set that index of the array to the result of the method, e.g. a[index] = x.capitalize
if you really want to learn I like to go to the source
for map for map!. the source would tell you what the difference is
map- Invokes the given block once for each element of self.
and
map! - Invokes the given block once for each element of self,
replacing the element with the value returned by the block.

How do i print a string with repeated names followed by a number - Ruby? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
How do i print a name Ex. John1 and then print after John2, john3, john4, john5 and so one in an infinite number
I started using ruby today and I'm having some trouble figuring this out. I've searched some but can't find anything so how would I do this?
It's to mass produce accounts to the staff of a certain company and I found ruby to be the smartest to write it in and I will never use it again after this
Keep it simple.
puts (1..5).map { |n| "john#{n}" }
john1
john2
john3
john4
john5
The class Range includes the module Enumerable (as does the classes Array, Hash and others). By doing so, instances of Range (such as 1..5) gain the use of all of Enumerable's instance methods. One of Enumerable's instance methods is used here: Enumerable#map.
For printing a simple series like this:
n = 1
loop do
print 'john%d, ' % n
n += 1
end
That will never terminate, which makes it kind of silly. Maybe what you want is a bounded range:
list = (1..10).map do |n|
'john%d' % n
end.join(', ')
puts list
You can adjust the start and end values as necessary.
Perhaps use an enumerator here:
enum = Enumerator.new do |y|
i = 1
loop do
y << "John#{i}"
i += 1
end
end
enum.next #=> "John1"
enum.next #=> "John2"
enum.next #=> "John3"
Then use any one of the methods available to instances of Enumerator. Here we've used Enumerator#next to get the next "John" string.
One simple way is using a for loop. First declare an empty string variable that will hold our contents.
One important thing to consider is the index of the loop. If it's the last item, we do not want to add a separator like ", "
This is where the conditional comes into play. If the index is less than the last, we will add a comma and space, otherwise just the name.
Interpolation is done by wrapping a variable inside #{ and }
str = ""
for i in 1..5
str += i < 5 ? "john#{i}, " : "john#{i}"
end
Returns
"john1, john2, john3, john4, john5"

in ruby, when is a block not a block? [duplicate]

This question already has an answer here:
Ruby block and unparenthesized arguments
(1 answer)
Closed 7 years ago.
Jokes aside, I have a strange situation, I have some code:
def remotes(form,remotes)
personalised_form = form.dup
remotes.each do |ident,remote|
object = yield(ident)
result = remote.call(object)
insert_into_(personalised_form,ident,result)
end
personalised_form
end
And I'm seeing if it works like so:
pp remotes(forms,remotes) do |ident|
case(ident)
when :get_assets
'#Userobject'
end
end
The problem is that ruby seems to think I'm not passing a block to the remotes function.
Why is ruby insisting that I'm not passing a block? (it gives a no block given (yield) (LocalJumpError) specifically).
Thought it's not relevant, remotes is a hash containing key's and Procs, and form is just a specificly structured hash that has the result of the proc inserted into it using the ident to locate the correct insertion point
Ruby thinks you are passing the block to pp method, which simply ignores it. Try:
res = remotes(forms,remotes) do |ident|
case(ident)
when :get_assets
'#Userobject'
end
end
pp res

next and previous for letters and symbols array [duplicate]

This question already has an answer here:
What is the opposite of string.next?
(1 answer)
Closed 9 years ago.
Because
"A".next => "B"
and
"#".next => "$"
How would I find the previous item? So that:
"$".previous => "#"
If you only need it to work on single character strings, you could extend String:
class String
def previous
return (self.ord - 1).chr
end
end
Then:
"$".previous # => "#"
I'm not a big ruby programmer, so I don't know how bad of a practice this is, but it does work if you need it.
Here's one way to do it for individual characters:
('B'.ord-1).chr # => 'A'
('$'.ord-1).chr # => '#'
From What is the opposite of string.next?
prev or something similar is not in the standard API because succ and a hypoethetical prev are surjective. Despite this, "Implement Ruby String Class Prev / Pred / Prev! / Pred! - Opposite Of Next / Succ Methods" is a possible version you could use.
The root problem is that succ is not inversible. This means, once you applied succ, then prev would end up with some ambiguity.
Credits to Bjoern Rennhak.

What does the |variable| syntax mean? [duplicate]

This question already has answers here:
What are those pipe symbols for in Ruby?
(7 answers)
Closed 2 years ago.
What is the | | around profile below called, what does it mean, and why it is after do? I thought do is followed by a loop block or so.
ticks = get_all[0...MAX].map do |profile|
# ...
end
it's like a foreach, so profile will be a different value in each of the functions calls, one function call per element in get_all.
see this:
my_array = [:uno, :dos, :tres]
my_array.each do |item|
puts item
end
They are part of the syntax for defining a block. The way I like to explain it is that the pipes look like a slide and those variables inside the pipes "slide" down into the block of code below them.
Essentially the variables in the pipes are available to the block. In the case of iteration the variable would represent an element in whatever you are iterating over.
I'll use this example to try to explain the concept to you.
friends = ["James", "Bob", "Frank"]
friends.each { |friend| puts friend }
James
Bob
Frank
So here, we have an array of our friends: James, Bob, and Frank.
In order to iterate over them, we call the #each method on the array. The method will start with the first item in my array and call the block on it.
Essentially, the item that I'm currently iterating over is passed to the variable inside of the two pipe characters. You can call it |buddy| and change the block to { |buddy| puts buddy } and it would still do the same thing.
The pipe characters delimit the parameter list of a block definition just like parentheses delimit the parameter list of a method definition. So, in this code snippet:
def foo(bar, baz) end
some_method_that_takes_a_block do |bar, baz| end
The parentheses and the pipes have the exact same purpose.

Resources