Ruby学习笔记之函数

函数


代码块


在Ruby中一个代码块就是把几个Ruby语句打包到一起

如{puts "hello"}和

do

club.enroll(person)

person.socialize

end

block_given?

判断是否已经给出一个快,这样方法可以有两个行为

传递块对象

一个块是一个Proc对象,使用call方法可以调用这个块对象

1.在向方法传递时要用&做作为前缀,这时Ruby会把块默认转换为Proc对象

class ProcExample

def pass_in_block(&action)

@stored_proc = action

end

def use_proc(parameter)

@stored_proc.call(parameter)

end

end

eg = ProcExample.new

eg.pass_in_block { |param| puts "The parameter is #{param}" }

eg.use_proc(99)

2.注意:虽然快对象出现在参数列表中,但是调用的时候并没有显示传递块

3.块对象必须出现在最后

4,在传递块对象的时候要加上&

例如:

def math(a, b)

yield(a, b)

end

def teach_math(a, b, &operation)

puts "Let's do the math:"

puts math(a, b, &operation)

end

teach_math(2, 3) {|x, y| x * y}

arity

得到Proc对象的参数个数

作用


一个语句块可以在函数调用是传递给函数,在函数内部可以用yield调用传递给这个函数的代码块。还可以给yield传递参数,而代码块接受参数的形式如下:

{|person, phrase| puts "#{person} says #{phrase}"}

代码块相当于匿名函数。

load pattern

这个同scala一致

闭包

1.闭包的真正意义是:块中包含了块可以访问的本地的变量,然后传递快时就可以一起传递这些变量。这样,这些本地变量也随着块一起在程序中传递。

def n_times(thing)

lambda {|n| thing * n }

end

2.代码块可以和调用函数以外的数据发生联系

sum = 0

[1, 2, 3, 4].each do |value|

square = value * value

sum += square

end

puts sum

注意:这人的代码块用了 外界的变量sum

如果想要控制sum是快内的变量,那么就要在参数后面设定

[1, 2, 3, 4].each do |value;sum|

square = value * value

sum += square

end

lambda

1.声明lambda时要用lambda函数

2.从Ruby1.9开始可以用另外的方法创建Proc对象

proc1 = ->arg { puts "In proc1 with #{arg}" }

proc2 = ->arg1, arg2 { puts "In proc2 with #{arg1} and #{arg2}" }

proc3 = ->(arg1, arg2) { puts "In proc3 with #{arg1} and #{arg2}" }

proc1.call "ant"

proc2.call "bee", "cat"

proc3.call "dog", "elk"

3.在Ruby1.9中,可以用另外的方法调用Proc对象

1.proc[arg-list]

2.proc.(arg-list)

控制结构

一个块可以用yield调用,也可以把他传递给方法的最后一个参数。前一种方法调用形式如下: ri("ssj") {p "start"},这种情况不能和Ruby的风格兼容(尽管在其他的语言中看起来很自然)。而后一中方法调用形式是:after i { puts i},更加自然。

定义如下:

def after(seconds, &block)

Thread.new do # In a new thread...

sleep(seconds) # First sleep

block.call # Then call the block

end # Return the Thread object right away

end

可以利用这一点来创建控制结构

Proc和lambda的不同


Proc.new和Kernel.proc用来产生块,Kernel.lambda用来产生lambda函数。

return

Proc中的return会在块定义的地方返回,可以不用显式的return来避免这个问题;lambda则仅仅从块中返回,表现的像一个函数。因此在需要传递时,应该常常使用lambda。

as:

def procBuilder(message) # Create and return a proc

Proc.new { puts message; return } # return returns from procBuilder

# but procBuilder has already returned here!

end

def test

puts "entering method"

p = procBuilder("entering proc")

p.call # Prints "entering proc" and raises LocalJumpError!

puts "exiting method" # This line is never executed

end

test

对于lambda,则不同

def lambdaBuilder(message) # Create and return a lambda

lambda { puts message; return } # return returns from the lambda

end

def test

puts "entering method"

l = lambdaBuilder("entering lambda")

l.call # Prints "entering lambda"

puts "exiting method" # This line is executed

end

test

如果块在顶层空间中定义。那么return出现就会引发错误,因为没办法从顶层空间返回。

def double(callable_object)

callable_object.call * 2

end

p = Proc.new { return 10 }

# This fails with a LocalJumpError:

# double(p)

break

1.Proc中,一旦break就会跳出block。并且导致迭代器返回。

2.在lambda中,如果没有任何循环或者迭代,那么break就不会起作用。

参数个数

Proc对于传递的参数个数比较宽松,参数多或者少都可以调用Proc;lambda则不同

定义

def say_goodnight(name)

result = "Good night, " + name

return result

end

注意函数的返回值是最后一个表达式的值,因此可以不用写return语句

简写

1,Ruby中方法在声明和使用时可以去掉圆括号,仅仅以空格代替

2,当映射表是函数的最后一个参数,是这时候可以去掉大括号。而仅仅写其中的内容

3,当参数是可变的时,可以去掉圆括号写成print_sym :a,:b,:c,这样就非常像一个关键字了。

方法名

1.一个普通方法一般是以小写字母开头,一般大写开头的方法用来类型装换

2.返回boolean的值得方法以?结尾

3.一些危险的方法以!结尾,比如会更改对象状态的方法

4.

默认参数

Ruby可以使用默认参数,一般其规则和C++一致,即默认参数字字可以在参数列表的最后出现。但是ruby并不要求一定要这样,必要时可以使用命名参数来简化参数传递。

可变参数

def greeting(*name,age)

puts "hello,#{name.count},you are #{age} years old"

end

不想Scala那样,ruby的可变参数可以出现任何位置,不仅仅是在参数列表的末尾,而且从理论上,在任何地方支持默认参数都是可以的。

1.可变参数只能出现一次

2.在可变参数后面不能有默认参数

3.可变参数在方法中是一个列表

多返回值

def meth_three

100.times do |num|

square = num*num

return num, square if square > 1000

end

end

meth_three # => [32, 1024]

如果不带return则必须用如下形式

def polar(x,y)

theta = Math.atan2(y,x)

r = Math.hypot(x,y)

[r, theta]

end

单例方法


动态添加对象方法

在一个对象上定义方法就可以实现动态向对象添加方法

例如:

o = "message"

def o.print_self

p self

end

o.print_self#"message"

Ruby中所有的属性都是私有的,因此Ruby会把所有的调用都看成方法,因此没办法向对象添加属性,只能添加方法。再进一步:Ruby的对象就像一个对象槽,其中可以像一个Hash那样添加元素

类方法(静态方法)

在对类和模块定义单例方法时,就是类方法

参见: 类方法

undef

def sum(x,y); x+y; end

puts sum(1,2)

undef sum

方法重命名

方法重命名在Ruby中有两个作用

as:alias original_hello hello

1.给一个方法多个名称,那么就可以在合适的地方使用更加合适的名字

2.一旦一个类的实例方法被重命名了,那么原来的命字就可以重新使用。这个在开放类中特别好有用,因为有时开放类中要改变类的实例方法,这时,只要把原来的方法重命名就可以。

as:

def hello # A nice simple method

puts "Hello World" # Suppose we want to augment it...

end

alias original_hello hello # Give the method a backup name

def hello # Now we define a new method with the old name

puts "Your attention please" # That does some stuff

original_hello # Then calls the original method

puts "This has been a test" # Then does some more stuff

end

注意:alias是一个关键字,因此这个调用没有用逗号隔开

Method


创建:

m = 0.method(:succ) # A Method representing the succ method of Fixnum 0

String.instance_method(:reverse) # => UnboundMethod object

调用:

m[],或者m.call

转换成Proc

1.Method.to_proc

2.def square(x); x*x; end

puts (1..10).map(&method(:square))

参见: 方法 (相同)

Unbound Method

未绑定方法不同于绑定方法,他们在调用时必须首先绑定一个对象

创建:

1.unbound_plus = Fixnum.instance_method("+")

2.unbound_plus = Fixnum.public_instance_method("+")

绑定:

plus_2 = unbound_plus.bind(2) # Bind the method to the object 2

调用:绑定后变成Method,因此可以同Method

函数式编程


1.Ruby中函数是一等公民,函数可以相互传递,同时也支持闭包

偏函数

product = lambda {|x, y| x*y } # A function of two arguments

double = lambda {|x| product(2,x) } # Apply one argument

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值