I'm trying to understand why this code is repeating the age and name methods 2 times. When i run the code, it asks for the age and the name, but, it then asks for the name and age again. Im not sure what exactly i've done wrong here? its only meant to ask 1 time.
I tried global variables and it worked but i dont really want to use global variables
require 'date'
def get_age()
puts("Enter your age in years: ")
age = gets.to_i()
return age
end
def get_string()
puts("Enter your name: ")
s = gets.chomp()
return s
end
def print_year_born(get_age)
year_born = Date.today.year - get_age
puts(get_string + "\sYou were born in: " + year_born.to_s)
end
def main()
get_age()
get_string()
print_year_born(get_age)
end
main()
what am i missing?
It's called twice because you call it twice. On line 1 of main, you call get_age() and discard the value it returns. Then on line 3 you call print_year_born(get_age) which invokes get_age again, but this time passes the value returned to print_year_born.
You seem to have some confusion over how methods work. Every time you type get_age, you're calling the method. You don't have to call the methods by themselves on lines 1 and 2, those bare invocations (get_age()/get_string()) are completely redundant. They call the methods but do absolutely nothing with the value they returns.
It's not clear what purpose do you think the first two lines in main serve, but you should remove them:
def main()
get_age() # Wrong: call get_age and ignore return value. Why?
get_string() # Wrong: call get_string and ignore return value. Why?
# Correct: call get_age and use the return value as an argument to print_year_born
print_year_born(get_age)
end
Related
Example: LinkedList printing method.
For this object, you will find a printing method using block, proc, and lambda.
It is not clear to me what the advantages/disadvantages are (if any).
Thank you
What is a LinkedList?
A LinkedList is a node that has a specific value attached to it (which is sometimes called a payload), and a link to another node (or nil if there is no next item).
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
def method_print_values(list_node)
if list_node
print "#{list_node.value} --> "
method_print_values(list_node.next_node)
else
print "nil\n"
return
end
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
#printing the linked list through a method defined within the scope of the class
node3.method_print_values(node3)
#---------------------------- Defining the printing method through a BLOCK
def block_print_value(list_node, &block)
if list_node
yield list_node
block_print_value(list_node.next_node, &block)
else
print "nil\n"
return
end
end
block_print_value(node3) { |list_node| print "#{list_node.value} --> " }
#---------------------------- Defining the printing method through a PROC
def proc_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
proc_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
proc_print_value(node3, Proc.new {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method through a LAMBDA
def lambda_print_value(list_node, callback)
if list_node
callback.call(list_node) #this line invokes the print function defined below
lambda_print_value(list_node.next_node, callback)
else
print "nil\n"
end
end
lambda_print_value(node3, lambda {|list_node| print "#{list_node.value} --> "})
#---------------------------- Defining the printing method outside the class
def print_values(list_node)
if list_node
print "#{list_node.value} --> "
print_values(list_node.next_node)
else
print "nil\n"
return
end
end
print_values(node3)
Examples display how to use different things to do the same. So, there is no principal difference between them in this context:
my_proc = Proc.new { |list_node| print "#{list_node.value} --> " }
node3.block_print_values(node3, &my_proc)
node3.proc_print_value(node3, my_proc)
node3.lambda_print_value(node3, my_proc)
Also, there is possible to define a method by using any of them:
define_method(:my_method, p, &proc { puts p })
my_method 'hello' #=> hello
define_method(:my_method, p, &-> { puts p })
my_method 'hello' #=> hello
But Proc, Lambda, block are not the same. Firstly, need a bit more display how to works magic &. The great article can help with that:
&object is evaluated in the following way:
if object is a block, it converts the block into a simple proc.
if object is a Proc, it converts the object into a block while preserving the lambda? status of the object.
if object is not a Proc, it first calls #to_proc on the object and then converts it into a block.
But this does not show the differences between them. So, now let go to the ruby source:
Proc objects are blocks of code that have been bound to a set of local variables. Once bound, the code may be called in different contexts and still access those variables.
And
+lambda+, +proc+ and Proc.new preserve the tricks of a Proc object given by & argument.
lambda(&lambda {}).lambda? #=> true
proc(&lambda {}).lambda? #=> true
Proc.new(&lambda {}).lambda? #=> true
lambda(&proc {}).lambda? #=> false
proc(&proc {}).lambda? #=> false
Proc.new(&proc {}).lambda? #=> false
Proc created as:
VALUE block = proc_new(klass, FALSE);
rb_obj_call_init(block, argc, argv);
return block;
When lambda:
return proc_new(rb_cProc, TRUE);
Both are Proc. In this case, the difference is just in TRUE or FALSE. TRUE, FALSE - check the number of parameters passed when called.
So, lambda is like more strict Proc:
is_proc = !proc->is_lambda;
Summary of Lambda vs Proc:
Lambdas check the number of arguments, while procs do not.
Return within the proc would exit the method from where it is called.
Return within a lambda would exit it from the lambda and the method would continue executing.
Lambdas are closer to a method.
Blocks: They are called closures in other languages, it is a way of grouping code/statements. In ruby single line blocks are written in {} and multi-line blocks are represented using do..end.
Block is not an object and can not be saved in a variable. Lambda and Proc are both an object.
So, let do small code test based on this answer:
# ruby 2.5.1
user system total real
0.016815 0.000000 0.016815 ( 0.016823)
0.023170 0.000001 0.023171 ( 0.023186)
0.117713 0.000000 0.117713 ( 0.117775)
0.217361 0.000000 0.217361 ( 0.217388)
This shows that using block.call is almost 2x slower than using yield.
Thanks, #engineersmnky, for good references in comments.
Proc is an object wrapper over block. Lambda basically is a proc with different behavior.
AFAIK pure blocks are more rational to use compared to procs.
def f
yield 123
end
Should be faster than
def g(&block)
block.call(123)
end
But proc can be passed on further.
I guess you should find some articles with performance comparison on the toppic
IMO, your block_print_value method is poorly designed/named, which makes it impossible to answer your question directly. From the name of the method, we would expect that the method "prints" something, but the only printing is the border condition, which does a
print "nil\n"
So, while I would strongly vote against using this way to print the tree, it doesn't mean that the whole idea of using a block for the printing problem is bad.
Since your problem looks like a programming assignment, I don't post a whole solution, but give a hint:
Replace your block_print_value by a, say block_visit_value, which does the same like your current method, but doesn't do any printing. Instead, the "else" part could also invoke the block to let it do the printing.
I'm sure that you will see afterwards the advantage of this method. If not, come back here for a discussion.
At a high level, procs are methods that can be stored inside variables like so:
full_name = Proc.new { |first,last| first + " " + last }
I can call this in two ways, using the bracket syntax followed by the arguments I want to pass to it or use the call method to run the proc and pass in arguments inside of parentheses like so:
p full_name.call("Daniel","Cortes")
What I did with the first line above is create a new instance of Proc and assigned it to a variable called full_name. Procs can take a code block as a parameter so I passed it two different arguments, arguments go inside the pipes.
I can also make it print my name five times:
full_name = Proc.new { |first| first * 5 }
The block I was referring to is called a closure in other programming languages. Blocks allow you to group statements together and encapsulate behavior. You can create blocks with curly braces or do...end syntax.
Why use Procs?
The answer is Procs give you more flexibility than methods. With Procs you can store an entire set of processes inside a variable and then call the variable anywhere else in your program.
Similar to Procs, Lambdas allow you to store functions inside a variable and call the method from other parts of the program. So really the same code I had above can be used like so:
full_name = lambda { |first,last| first + " " + last }
p full_name["daniel","cortes"]
So what is the difference between the two?
There are two key differences in addition to syntax. Please note that the differences are subtle, even to the point that you may never even notice them while programming.
The first key difference is that Lambdas count the arguments you pass to them whereas Procs do not. For example:
full_name = lambda { |first,last| first + " " + last }
p full_name.call("Daniel","Cortes")
The code above works, however, if I pass it another argument:
p full_name.call("Daniel","Abram","Cortes")
The application throws an error saying that I am passing in the wrong number of arguments.
However, with Procs it will not throw an error. It simply looks at the first two arguments and ignores anything after that.
Secondly, Lambdas and Procs have different behavior when it comes to returning values from methods, for example:
def my_method
x = lambda { return }
x.call
p "Text within method"
end
If I run this method, it prints out Text within method. However, if we try the same exact implementation with a Proc:
def my_method
x = Proc.new { return }
x.call
p "Text within method"
end
This will return a nil value.
Why did this occur?
When the Proc saw the word return it exited out of the entire method and returned a nil value. However, in the case of the Lambda, it processed the remaining part of the method.
I write a ruby program that prints 3 different values of variable a with different data types:
a = 5
puts a
a = true
puts a
a = 1.325
return a
puts a
In this case, last value didn't print. When i remove return a, program prints a last value, 1.325.
But how?
return controls program flow, calling it will exit the current method and pass the value of a into whatever expression called it.
Usually you would not write a method with an unconditional return and more code afterward, because that code is not reachable. The puts in your example will never be called. Just move it to before the return expression if you want it to run.
*Apologies if the question's wording is confusing. I didn't know exactly how to ask it.
How can I do something like this?
def track_time(function, input)
beg = Time.now
function(input)
end = Time.now
end - beg
end
And then pass it a function and a value for that function to use.
def double(value)
value + value
end
p track_time(double, 5)
The goal is to create something repeatable so I can track how long different functions take to complete.
First you can not use 'end' as a variable name.
As for your question, I agree with Mladen Jablanovićyou that for this use case a block is better, but since you specifically asked about passing a method as a parameter to another method, you can use the 'send' method:
def track_time method, value
begin_time = Time.now
send method, value
end_time = Time.now
end_time - begin_time
end
def double(value)
value + value
end
p trcak_time(:double, 5)
Unfortunately, methods in Ruby are not first-class objects, so they can't be directly passed as arguments. You can pass a name of the method (usually passed as symbol) instead, as other answers suggest.
But the idiomatic way to achieve what you are aiming for are blocks:
def track_time
start = Time.now
yield
finish = Time.now
finish - start
end
track_time do
double(5)
end
#=> 6.127e-06
Remember that end is a reserved word in Ruby (I suspect it was for illustration purposes anyhow).
You could pass in the string/symbol of the function name instead.
def track_time(function, input)
start = Time.now
method(function).call(input)
finish = Time.now
finish - start
end
def double(value)
value + value
end
track_time('double', 5)
=> 6.127e-06
For the sake of simplicity, I've tried to abstract the problem down to its core elements. I've included a small piece of functionality wherein I use Socket to show that I want to pass the block further down into a method which is a black box for all intents and purposes. I'm also passing a constant True for the sake of showing I want to pass arguments as well as a yield block.
With all that being said, if I small have a hierarchy of calls as such:
def foo(use_local_source)
if use_local_source
Socket.unix("/var/run/my.sock") &yield
else
Socket.tcp("my.remote.com",1234) &yield
end
end
foo(True) { |socket|
name = socket.read
puts "Hi #{name}, I'm from foo."
}
How can I pass the implicitly declared block right down through foo and into Socket as if I were calling Socket.tcp(...) { ... } directly.
I know I could set it as an argument, but it doesn't feel idiomatic to Ruby. Is this also untrue and I should pass it as an argument? I've tried combinations of & and *, and I get a range of exception.
def foo(use_local_source)
if use_local_source
yield Socket.unix("/var/run/my.sock")
else
yield Socket.tcp("my.remote.com",1234)
end
end
From the docs for yield:
Yields control back to the context that resumed the fiber, passing along any arguments that were passed to it.
In my journey of a thousand lines of Ruby, I'm having a really hard time with the concept of anonymous functions. Wikipedia says something about there being some nameless soul in the code and it submitting to a higher order, but my understanding ends there.
Or in other words, how would I (when I understand it) explain anonymous functions to my mom?
An anonymous function has these characteristics:
It has no name (hence anonymous)
Is defined inline
Used when you don't want the overhead/formality of a normal function
Is not explicitly referenced more than once, unless passed as an argument to another function
Here's one example of an anonymous function in Ruby (called a block in this case):
my_array.each{ |item| puts item }
Where's the anonymous function in the above? Why, it's the one that receives a single parameter, names it 'item', and then prints it. In JavaScript, the above might be written as...
Array.prototype.each = function(anon){
for (var i=0,len=this.length;i<len;++i) anon(this[i]);
};
myArray.each(function(item){ console.log(item); });
...which both makes it a little bit more clear that a function is being passed as an argument, and also helps one appreciate Ruby's syntax. :)
Here's another anonymous function (back in Ruby):
def count_to(n)
puts "I'm going to count to #{n}"
count = lambda do |i|
if (i>0)
count[i-1]
puts i
end
end
count[n]
puts "I'm done counting!"
end
count_to(3)
#=> I'm going to count to 3
#=> 1
#=> 2
#=> 3
#=> I'm done counting!
Although the example is obviously contrived, it shows how you can create a new function (in this case named count) and assign it to a variable, and use that for recursive calls inside a master method. (Some feel that this is better than creating a second method just for the recursion, or re-using the master method for recursion with very different parameters.)
The function doesn't have a name, the variable does. You could assign it to any number of variables, all with different names.
Returning to the first example, there's even a syntax in Ruby for passing a lambda as the single, blessed block:
print_it = lambda{ |item| puts item }
%w[a b c].each(&print_it)
#=> a
#=> b
#=> c
...but you can also pass a lambda as a normal parameter and call it later, as illustrated here:
module Enumerable
def do_both_to_each( f1, f2 )
each do |item|
f1[item]
f2[item]
end
end
end
print_prefix = lambda{ |i| print "#{i}*#{i} -> " }
print_squared = lambda{ |i| puts i*i }
(1..4).do_both_to_each(print_prefix,print_squared)
#=> 1*1 -> 1
#=> 2*2 -> 4
#=> 3*3 -> 9
#=> 4*4 -> 16
In addiction to previous answers, the anonymous functions are very usefull when you working with closures:
def make_adder n
lambda { |x|
x + n
}
end
t = make_adder 100
puts t.call 1
Or (in Ruby 1.9):
def make_adder_1_9 n
->(x) {
x + n
}
end
t_1_9 = make_adder_1_9 100
puts t_1_9.call 1
Just as Wikipedia says: a function with no name.
It means that you cannot invoke the function in the typical way, by using its name and parameters. Rather the function itself is usually a parameter to another function. A function that operates on functions is called a "higher order function".
Consider this JavaScript(I know you tagged this ruby but...):
window.onload=function(){
//some code here
}
The function will execute when the page loads, but you cannot invoke it by name, because it does not have a name.
What is the point of an anonymous method?
Explanation by Analogy:
When I order my favourite burger (a greasy Big Nac), I don't want to spend 5 minutes filling out a formal order application: name, address, phone number etc. I ain't got time for that. I want to use my mouth: "give me a burger", nice and quick and easy.
Anonymous methods are kinda like the same thing, except when coding:
It's kinda like throwaway method allowing you to code faster
It's the same when coding. If you have to define a function, you have to put it somewhere (else), you have to call it something, and that's a pain, especially if you know you'll never, ever need it again. And when you read the code, you might have to use a complicated IDE to find that method again, and a reference to it. What a pain! You need a throwaway method that you can write directly in your code, where you need it, and just get it done, and move one. Anonymous methods solve this particular problem.
Anonymous functions have the following characteristics:
No name
Inline declaration
Executed directly when declared