For faster navigation, this Iframe is preloading the Wikiwand page for Ruby.

Ruby

维基百科,自由的百科全书

Ruby
Ruby logo.png
编程范型面向对象指令式函数式
设计者松本行弘
实现者松本行弘等人
发行时间1995年
稳定版本
3.1.2
( 2022年4月12日,​2个月前​(2022-04-12
类型系统动态类型
操作系统跨平台
许可证Ruby许可证[1] / BSD许可证[2] / GNU通用公共许可证第二版[3]
网站www.ruby-lang.org 编辑维基数据链接
主要实现产品
Ruby MRI英语Ruby MRIYARVRubinius英语RubiniusMagLev英语MagLev (software)JRuby
MacRuby英语MacRubyRubyMotion英语RubyMotionHotRuby英语HotRubyIronRuby
mruby
启发语言
Ada[4]C++[4]CLU[5]Dylan[5]Eiffel[4]
Lisp[5]Perl[5]Python[5]Smalltalk[5]
影响语言
ClojureD[6]ElixirFalconFancy英语Fancy (programming language)[7]Groovy
Ioke英语Ioke (programming language)[8]Mirah英语Mirah (programming language)Nu[9]Reia英语Reia (programming language)Potion英语Potion (programming language)

Ruby 是一种面向对象指令式函数式动态通用编程语言。在20世纪90年代中期由日本电脑科学家松本行弘(Matz)设计并开发。

遵守BSD许可证和Ruby License[10][注 1]。它的灵感与特性来自于PerlSmalltalkEiffelAda以及Lisp语言。由Ruby语言本身还发展出了JRubyJava平台)、IronRuby.NET平台)等其他平台的Ruby语言替代品。

历史

Ruby的作者松本行弘
Ruby的作者松本行弘

Ruby的作者--松本行弘于1993年2月24日开始编写Ruby,直至1995年12月才正式公开发布于fj(新闻组)。之所以称为Ruby是取法自Perl,因为Perl的发音与6月的诞生石pearl(珍珠)相同,Ruby选择以7月的诞生石ruby(红宝石)命名。

Ruby相较之下比其他类似的编程语言(如PerlPython)年轻,又因为Ruby是日本人发明的,所以早期的非日文资料和程序都比较贫乏,在网上仍然可以找到早期对Ruby的资料太少之类的批评。约于2000年,Ruby开始进入美国,英文的资料开始发展。

2004年,Rails框架诞生,Ruby更加广为人知,Ruby并于2006年为TIOBE获选为年度编程语言。

Ruby的理念

减少编程时候的不必要的琐碎时间,令编写程序的人高兴,是设计Ruby语言的Matz的一个首要的考虑;其次是良好的界面设计。他强调系统设计必须强调人性化,而不是一味从机器的角度设想[11]

遵循着最小惊讶原则英语Principle of least astonishment,Ruby语言通常非常直观,按照编程人认为它应该的方式运行。

Ruby的作者认为Ruby > (Smalltalk + Perl) / 2[来源请求],表示Ruby是一个语法像Smalltalk一样完全面向对象、脚本执行、又有Perl强大的文字处理功能的编程语言。

Ruby的版本体系

Ruby版本号的构成形式是(MAJOR).(MINOR).(TEENY),均为只有1位的整数;如“1.8.6”、“1.9.3”。

1.9版系统的TEENY不小于1时为稳定版,TEENY为0的版本是开发版。在1.9之前的版本中偶数MINOR代表稳定版,奇数MINOR代表开发版。[12]

Ruby的Hello World程序

下面是一个在标准输出设备上输出Hello World的简单程序:

#!/usr/bin/env ruby
puts "Hello, world!"

或者是在irb交互式命令行的模式下:

>>puts "Hello, world!"
Hello, world!
=> nil

Ruby的特点

变量与函数的命名规则

乍看之下与Perl的命名规则有些类似,不过Perl的命名用来区分标量、数组与映射;而Ruby的命名规则用来表示变量与类别的关系。Ruby的变量有以下几种:

  • 一般小写字母、下划线开头:变量(Variable)。
  • $开头:全局变量(Global variable)。
  • @开头:实例变量(Instance variable)。
  • @@开头:类变量(Class variable)类别变量被共享在整个继承链中
  • 大写字母开头:常量(Constant)。

有些函数则会加一个后缀,用来表示函数的用法,跟变量命名规则不同,函数的命名规则只是习惯,不具强制性,即使你不照规则命名也不影响程序运作

  • =结尾:赋值方法,相当于其他编程语言的set开头的方法,算是一种语法糖
  • !结尾:破坏性方法,调用这个方法会修改本来的对象,这种方法通常有个非破坏性的版本,调用非破坏性的版本会回传一个对象的副本。
  • ?结尾:表示这个函数的回传值是个布尔值。

多种字符串表示法

Ruby提供了多种字符串的表示方法,方便撰写有大量文字资料的程序。除了来自C语言的引号表示法之外,还有来自于Perl的百分号字面量记法,以及方便书写大量内容的Heredoc记法。Ruby可以方便地以#{variable_name}的方式向字符串中插入变量。

a = '\n这是一个单引号的字符串,反斜线和变量插值不会被转义'

b = %q{这是一个不可转义的字符串}

c = "\n这是一个双引号的字符串,反斜线和变量插值会被转义\n#{a}"

d = %Q{\n這是一個常量字串,特殊内容同样会被转义\n}

e = <<BLOCK
这是一个以Heredoc方式书写的常量字符串,可转义,结尾标志不可缩进
BLOCK

f = <<-BLOCK
      这是一个可以缩进的Heredoc字符串
    BLOCK

g = <<~BLOCK
      这是一个可以缩进的Heredoc字符串
      缩进会被自动去掉,在2.3版本中引入
    BLOCK

h = %/\t这是一个可转义的的字符串\n/

动态修改对象、类别

Ruby是动态语言,你可以在程序中修改先前定义过的类别。 也可以在某个类别的实例中定义该实例特有的方法,这叫做原型方法(prototype)。

class MyClass
  def the_method
    "general method"
  end
end

mc = MyClass.new
def mc.the_method
  "special for this instance."
end

mc.the_method

强大的反射机制与元编程

Ruby的反射功能相当惊人,甚至可以自行追踪程序运作,或是取出private变量、拦截方法的调用。 常常与‘可以动态的修改对象’这项特色结合,做为‘元编程’的功能:程序在运行时, 可以由程序员提供的信息,自行生成、修改类别或对象,这项功能大大的提高了撰写代码的效率。 在Rails之中,就大量使用了这种特性。

以下为用Rails使用元编程的示例:

class Project < ActiveRecord::Base
  belongs_to :portfolio
  has_one    :project_manager
  has_many   :milestones
end

在这个例子中,Project类别继承Base类别,Base类别内置的belongs_tohas_onehas_many方法,便会根据参数来修改Project类别的内容,并自行创建其他相关的方法。程序员可以更专心处理程序的运作,而不必为每个类别重复得撰写代码。

丰富灵活的循环表示

# 使用 for,在 1 到 3 取出值 1、2、3 到 outer_i 裡操作。
for outer_i in 1..3 do
  puts "for: #{outer_i * 100}"
end

# 在 1 到 3 的集合裡針對每個值,放到 i 裡操作。
(1..3).each do |i|
  puts "each: #{i * 100}"
end

# 只要符合 outer_i 小於等於 300,則進入迴圈。
outer_i = 100
while outer_i <= 300
  puts "while: #{outer_i}"
  outer_i += 100
end

# 直到 outer_i 大於 300 前,都可以進入迴圈。
outer_i = 100
until outer_i > 300
  puts "until: #{outer_i}"
  outer_i += 100
end

# 無限迴圈,用 break 來打斷迴圈。
outer_i = 100
loop do
  break if outer_i > 300

  puts "loop: #{outer_i}"
  outer_i += 100
end

# 作 3 次迴圈,i 從 0 開始遞增 1。
3.times do |i|
  puts "times: #{(i + 1) * 100}"
end

# 從 1 遞增 1 到 3,值傳入 i 來操作。
1.upto(3) do |i|
  puts "upto: #{i * 100}"
end

# 從 3 遞減 1 到 1,值傳入 i 來操作。
3.downto(1) do |i|
  puts "downto: #{400 - i * 100}"
end

# 從 100 開始以每步 +100 邁向 300。
100.step(300, 100) do |i|
  puts "step: #{i}"
end

其他特色

  • 完全面向对象:任何东西都是对象,没有基础类型
  • 变量是动态类型
  • 任何东西都有值:不管是四则运算、逻辑表达式还是一个语句,都有回传值。
  • 运算符重载
  • 垃圾回收
  • 强类型[13]
  • 变量无需声明
  • Windows上,加载DLL

比较与批评

让人意外之处

  • 在Ruby中,只有falsenil表示false,其它的所有值都表示true(包括00.0""[][14]。这点和C语言的‘用0代表false’不同。
  • Ruby的字符串是可改变的,这与Java固定不变的字符串不同。在Ruby中,常用Symbol对象来表示不可变的字符串。Ruby 2.3提供了默认冻结字符串的选项,在原始码开头添加魔术注释# frozen_string_literal: true可以打开这个选项,当用户试图更改String对象时会抛出运行时异常。同时,松本行弘表示,在Ruby 3中,字符串将是默认不可变的。[15]
  • Ruby的继承功能相当脆弱,尽管Ruby是一个面向对象语言,Ruby内的许多规则,却使得子类有可能不小心就改写了父类的功能,在《The Ruby Programming Language》一书中,建议除非程序员对一个类别相当了解,否则尽可能不要使用继承。

和Perl 6比较

  • CPAN上排名第一名,同时也是Perl 6的开发者的唐凤(Autrijus / Audrey)说:“Ruby就是‘没有到处打广告的Perl 6’”。[16][17]
  • 松本行弘在接受欧莱礼(O'Reilly)访问时,提到“Ruby借用了很多Perl的东西……,Python远比Perl要少……”、“我认为Ruby这个名字作为Perl之后的一门语言的名字真是再恰当不过了。”[18]
  • Perl之父拉里·沃尔(Larry Wall)说:“很多方面上我还是很喜欢Ruby的,这是因为那些部分是从Perl借过去的。:-)”、“我还喜欢Ruby的C<*>一元星号操作符,所以我把它加到Perl 6里面。”[19]

程序示例

此条目包含指南或教学内容。请借由移除或重写指南段落来改善条目,或在讨论页提出讨论。

下面的代码可以在Ruby shell中运行,比如irb交互式命令行,或者保存为文件并运行命令ruby <filename>

  • 一些基本的Ruby代码:
# Everything, including a literal, is an object, so this works:
-199.abs                                                # 199
"ruby is cool".length                                   # 12
"Rick Astley".index("c")                                # 2
"Nice Day Isn't It?".downcase.split(//).sort.uniq.join  # " '?acdeinsty"
  • 一些转换:
puts "What's your favorite number?"
number = gets.chomp
outputnumber = number.to_i + 1
puts outputnumber.to_s + ' is a bigger and better favorite number.'

集合

a = [1,'hi', 3.14, 1, 2, [4, 5]]

p a[2]           # 3.14
p a.[](2)# 3.14
p a.reverse      # [[4, 5], 2, 1, 3.14, 'hi', 1]
p a.flatten.uniq # [1, 'hi', 3.14, 2, 4, 5]
  • 构造和使用关联数组:
hash = { :water => 'wet', :fire => 'hot' }
puts hash[:fire] # Prints:  hot

hash.each_pair do |key, value| # Or:  hash.each do |key, value|
puts "#{key} is #{value}"
end

# Prints:  water is wet
#          fire is hot

hash.delete :water # Deletes :water => 'wet'
hash.delete_if {|k,value| value=='hot'} # Deletes :fire => 'hot'

块和迭代器

  • 有两个语法用于创建块:
{ puts "Hello, World!" } # Note the { braces }
#or
do puts "Hello, World!" end
  • 传参数的块使用闭包Closure
# In an object instance variable (denoted with '@'), remember a block.
def remember(&a_block)
  @block = a_block
end

# Invoke the above method, giving it a block which takes a name.
remember {|name| puts "Hello, #{name}!"}

# When the time is right (for the object) -- call the closure!
@block.call("Jon")
# => "Hello, Jon!"
  • 从方法中返回闭包:
def create_set_and_get(initial_value=0) # Note the default value of 0
  closure_value = initial_value
  return Proc.new {|x| closure_value = x}, Proc.new { puts closure_value }
end

setter, getter = create_set_and_get  # ie. returns two values
setter.call(21)
getter.call # => 21
  • 迭代调用调用时提供的块:
def use_hello
  yield "hello"
end

# Invoke the above method, passing it a block.
use_hello {|string| puts string} # => 'hello'
  • 使用块迭代数组:
array = [1, 'hi', 3.14]
array.each { |item| puts item }
# => 1
# => 'hi'
# => 3.14

array.each_index { |index| puts "#{index}: #{array[index]}" }
# => 0: 1
# => 1: 'hi'
# => 2: 3.14

(3..6).each { |num| puts num }
# => 3
# => 4
# => 5
# => 6

像inject()方法可以接收一个参数和一个块。迭代的注入列表的每一个成员,执行函数时保存总和。这同函数编程语言中的foldl函数相类似,比如:

[1,3,5].inject(10) {|sum, element| sum + element} # => 19

首先块接收到了10(inject的参数)当作变量sum,并且1(数组的第一个元素)当作变量element;这会返回11。11又被当作下一步的sum变量,它加上3得到了14。14又被加上了5,最终返回结果19。

  • 块运行在内置的方法中:
File.open('file.txt', 'w') do |file| # 'w' denotes "write mode".
  file.puts 'Wrote some text.'
end                                  # File is automatically closed here

File.readlines('file.txt').each do |line|
puts line
end
# => Wrote some text.
  • 使用枚举器和块求1到10的平方:
(1..10).collect {|x| x*x} # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

下面的代码定义一个命名为Person的类。含有一个“initialize”方法,用于构选创建一个新对象,它还有两个方法,一个重载了<=>比较运算符(这样Array#sort可以使用age排序)另一个重载了to_s方法(这样Kernel#puts可以格式化输出),attr_reader是Ruby中元数据编程的例子:attr_accessor为实例变量定义了getter和setter方法,attr_reader只是一个getter方法。另外,方法中最后的声明是它的返回值,也允许显式的使用“return”语句。

class Person
  attr_reader :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end
  def <=>(person) # Comparison operator for sorting
    @age <=> person.age
  end
  def to_s
    "#@name (#@age)"
  end
end

group = [
  Person.new("Bob", 33),
  Person.new("Chris", 16),
  Person.new("Ash", 23)
]

puts group.sort.reverse
  • 下面按age倒序输出了三个名字:
Bob(33)
Ash(23)
Chris(16)

各种版本

Matz's Ruby interpreter, 最初也是最常见的Ruby版本, 简称MRI, 用C语言撰写.

JRuby,类似PythonJython,一个可于Java上执行Ruby的语言,支持Java的接口和类别。最新发布版为9.1.6.0(2016-11-09),与Ruby 2.3兼容。它的官方网站为jruby.org

mruby是一个轻量级的Ruby解释器,可以嵌入到其它应用程序中,或者作为库链接到应用中。

参见

注释

  1. ^ Ruby早期遵守GPL协议。

参考文献

  1. ^ COPYING in Ruby official source repository. [2013-10-30]. (原始内容存档于2017-03-20). 
  2. ^ BSDL in Ruby official source repository. [2013-10-30]. (原始内容存档于2022-03-21). 
  3. ^ Contents of /trunk/GPL. [2 May 2015]. (原始内容存档于2022-03-21). 
  4. ^ 4.0 4.1 4.2 Cooper, Peter. Beginning Ruby: From Novice to Professional. Beginning from Novice to Professional 2nd. Berkeley: APress. 2009: 101. ISBN 1-4302-2363-4. To a lesser extent, Python, LISP, Eiffel, Ada, and C++ have also influenced Ruby. 
  5. ^ 5.0 5.1 5.2 5.3 5.4 5.5 Bini, Ola. Practical JRuby on Rails Web 2.0 Projects: Bringing Ruby on Rails to Java. Berkeley: APress. 2007: 3. ISBN 1-59059-881-4. It draws primarily on features from Perl, Smalltalk, Python, Lisp, Dylan, and CLU. 
  6. ^ Intro – D Programming Language 1.0 – Digital Mars. [2013-10-30]. (原始内容存档于2018-12-25). 
  7. ^ Bertels, Christopher. Introduction to Fancy. Rubinius blog. Engine Yard. 23 February 2011 [2011-07-21]. (原始内容存档于2018-12-25). 
  8. ^ Bini, Ola. Ioke. Ioke.org. [2011-07-21]. (原始内容存档于2011-07-21). inspired by Io, Smalltalk, Lisp and Ruby 
  9. ^ Burks, Tim. About Nu™. Programming Nu™. Neon Design Technology, Inc. [2011-07-21]. (原始内容存档于2011-07-24). 
  10. ^ Ruby License. [2004-09-25]. (原始内容存档于2011-08-22). 
  11. ^ The Philosophy of Ruby, A Conversation with Yukihiro Matsumoto, Part I by Bill Venners on 2003-09-29 (Artima Developer,英文). [2007-09-17]. (原始内容存档于2019-07-05). 
  12. ^ [Ruby语言入门东南大学出版社2010年4月第一版P19]
  13. ^ To Ruby From Python. [2010-10-26]. (原始内容存档于2022-02-22). 
  14. ^ To Ruby From Python页面存档备份,存于互联网档案馆),When tested for truth, only false and nil evaluate to a false value. Everything else is true (including 0, 0.0, "", and []).
  15. ^ Immutable String literal in Ruby 3.. [2017-11-27]. (原始内容存档于2022-04-15). 
  16. ^ Perl 6于2019年10月更名为Raku
  17. ^ 存档副本. [2013-10-22]. (原始内容存档于2015-09-24). 
  18. ^ O'Reilly訪問Matz。. [2007-07-20]. (原始内容存档于2009-07-28). 
  19. ^ Larry Wall On Perl, Religion, and……. [2007-07-20]. (原始内容存档于2007-07-29). 
  20. ^ Guido談Python 3000及與Ruby的競爭。. [2007-07-23]. (原始内容存档于2012-11-20). 

外部链接

{{bottomLinkPreText}} {{bottomLinkText}}
Ruby
Listen to this article

This browser is not supported by Wikiwand :(
Wikiwand requires a browser with modern capabilities in order to provide you with the best reading experience.
Please download and use one of the following browsers:

This article was just edited, click to reload
This article has been deleted on Wikipedia (Why?)

Back to homepage

Please click Add in the dialog above
Please click Allow in the top-left corner,
then click Install Now in the dialog
Please click Open in the download dialog,
then click Install
Please click the "Downloads" icon in the Safari toolbar, open the first download in the list,
then click Install
{{::$root.activation.text}}

Install Wikiwand

Install on Chrome Install on Firefox
Don't forget to rate us

Tell your friends about Wikiwand!

Gmail Facebook Twitter Link

Enjoying Wikiwand?

Tell your friends and spread the love:
Share on Gmail Share on Facebook Share on Twitter Share on Buffer

Our magic isn't perfect

You can help our automatic cover photo selection by reporting an unsuitable photo.

This photo is visually disturbing This photo is not a good choice

Thank you for helping!


Your input will affect cover photo selection, along with input from other users.