22、PHP 与 Ruby 控制结构和函数的对比

PHP 与 Ruby 控制结构和函数的对比

1. 控制结构对比

在编程中,控制结构是实现程序逻辑的重要部分。PHP 和 Ruby 在控制结构上有相似之处,但也存在一些显著的差异。

1.1 if 语句
  • PHP :使用 if {} 来定义条件语句,括号围绕被评估的表达式是必需的。
$value = 10;
if ($value > 5) {
    print "value is \n";
    print "greater than 5\n";
}
  • Ruby :使用 if/end 语法,括号围绕被评估的表达式是可选的。
value = 10
if value > 5
    puts 'value is '
    puts 'greater than 5'
end

还可以使用 if unless 语句修饰符来编写单行条件语句。

$value = 10;
if ($value > 5)
    print "value is greater than 5\n";
if (! $value > 5)
    print "value is NOT greater than 5\n";
value = 10
puts 'value is greater than 5' if value > 5
puts 'value is NOT greater than 5' unless value > 5
1.2 else 和 elseif/elsif
  • else :在 Ruby 中使用 else 与 PHP 类似,三元运算符在两种语言中的工作方式相同。
$value = 10;
if ($value > 5) {
    print 'value is greater than 5';
} else {
    print 'value is NOT greater than 5';
}
$color = $value == 1 ? 'red' : 'blue';
value = 10
if value > 5
    puts 'value is greater than 5'
else
    puts 'value is NOT greater than 5'
end
color = value == 1 ? 'red' : 'blue'
  • elseif/elsif :PHP 的 elseif 关键字在 Ruby 中变为 elsif 。在 Ruby 中,如果想将语句与条件表达式放在同一行,可以使用冒号 : then 关键字。
$value = 7;
if ($value > 8) {
    print 'value is greater than 8';
} elseif ($value > 5) {
    print 'value is greater than 5'
} else {
    print 'value is NOT greater than 5';
}
value = 7
if value > 8
    puts 'value is greater than 8'
elsif value > 5
    puts 'value is greater than 5'
else
    puts 'value is NOT greater than 5'
end
# variation using ":"
if value > 8:
    puts 'value is greater than 8'
elsif value > 5: puts 'value is greater than 5'
else
    puts 'value is NOT greater than 5'
end
# variation using "then"
if value > 8
    then puts 'value is greater than 8'
elsif value > 5 then puts 'value is greater than 5'
else
    puts 'value is NOT greater than 5'
end
1.3 循环结构
  • while 循环 :Ruby 使用 while/end 风格的语法来定义 while 循环的开始和结束。
$page = 1;
while ($page < 5) {
    print "$page\n";
    $page++;
}
page = 1
while page < 5
    puts page
    page += 1
end

Ruby 还添加了 while until 语句修饰符,以便可以在一行代码中编写简单的 while 语句。

$page = 1;
while ($page < 5)
    $page++;
$page = 1;
while (! $page >= 5)
    $page++;
page = 1
page += 1 while page < 5
page = 1
page += 1 until page >= 5
  • do while 循环 :Ruby 不支持 do/while ,但有一个等效的语法,使用 while until 语句修饰符在 begin/end 块表达式上。
$page = 1;
do {
    print "$page\n";
    $page++;
} while ($page < 10);
page = 1
begin
    puts page
    page += 1
end while page < 10
  • for 循环 :Ruby 在循环方面与 PHP 采取了不同的方法。Ruby 中没有 for 结构,大多数循环方法利用整数对象上的迭代器方法。可以使用 times upto 方法编写带有增量器的循环。
for ($i = 0; $i < 5; $i++) {
    print "$i ";
}
5.times do |i|
    print "#{i} "
end
0.upto(4) do |i|
    print "#{i} "
end

可以使用 downto 方法创建带有减量器的循环。

for ($i = 4; $i >= 0; $i--) {
    print "$i ";
}
4.downto(0) do |i|
    print "#{i} "
end

要创建增量或减量时的间隔不是 1 的循环,可以使用 Ruby 的 step 方法。

for ($i = 0; $i < 5; $i += 2) {
    print "$i ";
}
0.step(5, 2) do |i|
    print "#{i} "
end
  • foreach 循环 :在 Ruby 中,数组的 foreach 结构可以通过两种迭代器方法之一来完成。只需要遍历数组中的值时使用 each 方法。
$colors = array('blue', 'orange', 'red');
foreach ($colors as $color) {
    print "$color ";
}
colors = ['blue', 'orange', 'red']
colors.each do |color|
    print "#{color} "
end

当还需要数组的数字索引时,可以使用 each_with_index 方法。

foreach ($colors as $key => $color) {
    print "$key=$color ";
}
colors.each_with_index do |color, i|
    print "#{i}=#{color} "
end

当在哈希上使用 each 方法时,它将当前元素的键和值都传递给块。

$person = array('name' => 'Joe', 'eyes' => 'blue');
foreach ($person as $key => $value) {
    print "$key=$value ";
}
person = {:name => 'Joe', :eyes => 'blue'}
person.each do |key, value|
    print "#{key}=#{value} "
end
1.4 其他控制结构
  • break 语句 :在 PHP 和 Ruby 中,使用 break 语句停止执行,但 break 的参数在两种语言中的工作方式不同。PHP 使用参数来确定要跳出多少个封闭语句,而 Ruby 将其视为语句的返回值。
$i = 0;
while (true) {
    if ($i == 5) break;
    print "$i ";
    $i++;
}
$i = 1;
while ($i < 100) {
    while ($i < 10) {
        if ($i == 5) break 2;
        $i++;
    }
    $i++;
}
print $i;
i = 0
while true
    break if i == 5
    puts "#{i} "
    i += 1
end
i = 1
result = while i < 100
    break "test" if i == 5
    i += 1
end
puts result
  • continue/next 语句 :PHP 的 continue 关键字在 Ruby 中被 next 取代。与 PHP 不同,Ruby 不允许使用额外的参数来指定跳过多少个循环。
$i = 0;
while ($i <= 10) {
    $i++;
    if ($i%2 == 1) continue;
    print "$i ";
}
i = 0
while i <= 10
    i += 1
    next if i%2 == 1
    puts "#{i} "
end
  • switch 语句 :Ruby 实现了 case 表达式来替代 PHP 的 switch case 表达式一旦找到匹配的值就不会继续评估语句,因此不需要 break 语句来停止执行。
switch (1) {
    case 0:
        print "equals 0\n";
    case 1:
        print "equals 1\n";
    case 2:
        print "equals 2\n";
}
$color = 'blue';
switch ($color) {
    case 'red':
    case 'yellow':
        $type = "Warm";
        break;
    case 'blue':
    case 'green':
        $type = "Cool";
        break;
    default:
        $type = "Invalid";
}
print "$type color\n";
case 1
when 0: puts "equals 0"
when 1: puts "equals 1"
when 2: puts "equals 2"
end
color = 'blue'
case color
when 'red', 'yellow':
    type = "Warm"
when 'blue', 'green':
    type = "Cool"
else
    type = "Invalid"
end
puts "#{type} color"
type = case color
when 'red', 'yellow': "Warm"
when 'blue', 'green': "Cool"
else
    "Invalid"
end
puts "#{type} color"
1.5 require 和 include
  • PHP require_once 用于加载外部文件一次, require 可以多次加载。
require_once 'lib/sample_file.php';
require_once 'lib/sample_file.php';
require 'lib/sample_file.php';
require 'lib/sample_file.php';
  • Ruby require 方法与 PHP 的 require_once 类似,加载外部文件一次, .rb 扩展名是可选的。 load 方法可以多次加载外部文件,需要指定文件扩展名。
require 'lib/sample_file'
require 'lib/sample_file'
load 'lib/sample_file.rb'
load 'lib/sample_file.rb'
2. 高级结构 - 块和函数

除了基本的控制结构,PHP 和 Ruby 在高级结构上也有不同的特点。

2.1 块(Blocks)

块是 Ruby 中特有的功能,用于将一段代码封装并传递给方法。可以使用花括号 {} do/end 风格的语法来传递块。

# 单行块
['a', 'b', 'c'].each {|letter| puts letter }
# 多行块
['a', 'b', 'c'].each do |letter|
    puts letter
    puts letter.upcase
end

块的一个实际用途是执行事务操作。使用 yield 关键字来执行传递进来的块。

def dinner
    puts "prepare meal"
    yield
    puts "wash dishes"
end
dinner { puts "eat lasagna" }

还可以向 yield 关键字传递参数,这些参数将被传递到块中使用。

def variations(name)
    yield("upcase", name.upcase)
    yield("downcase", name.downcase)
    yield("capitalize", name.capitalize)
end
variations('joe') {|name, value| puts "#{name} = #{value}" }

可以通过调用 block_given? 来检查是否有块传递给方法。

def my_method
    if block_given?
        puts "block passed in"
    else
        puts "no block"
    end
end
my_method
my_method {}

也可以将代码块传递给方法并使用 call 直接在方法中执行。

def my_method(arg1, &arg2)
    arg2.call('block argument')
end
my_method('test') {|arg1| puts "Some data with #{arg1}" }
2.2 函数(Functions)

在 Ruby 中,实际上没有像 PHP 那样的函数概念。在 Ruby 中,每个函数实际上是定义在类或对象上的方法。任何在全局作用域中定义的方法实际上是 Object 类的方法。

def my_global_method
    puts "I'm available everywhere!"
end
o = Object.new
o.my_global_method
class Car; end
c = Car.new
c.my_global_method

定义和调用方法在 Ruby 中不需要使用括号,当方法没有参数时,括号通常会被省略。

def drink_water
    puts "Gulp, Gulp"
end
drink_water
def drink_beverage(type, size)
    puts "Gulping down #{size} of #{type}"
end
drink_beverage "Gatorade", "gallon jug"
drink_beverage("Gatorade", "gallon jug")

用户定义的方法使用 def/end 语法,与 PHP 的 {} 不同。Ruby 中的方法名是区分大小写的。

function myFunction($arg1, $arg2, $arg3) {
    return "return value \n";
}
print myFunction('a', 'b', 'c');
print mYfunCtion('a', 'b', 'c');
def my_function(arg1, arg2, arg3)
    "return value"
end
puts my_function('a', 'b', 'c')
puts mY_funCtion('a', 'b', 'c')

Ruby 方法名可以以问号 ? 、感叹号 ! 或等号 = 结尾。问号通常用于返回布尔值的方法,等号用于作为左值属性赋值的方法,感叹号通常表示该方法会对接收对象进行破坏性操作。

class User
    def admin=(admin)
        @admin = admin
    end
    def admin?
        @admin || false
    end
end
joe = User.new
joe.admin = true
puts joe.admin?
foo = [2, 1, 3]
p foo.sort
p foo
p foo.sort!
p foo

Ruby 允许嵌套方法,与 PHP 中的嵌套函数类似,它们在外部方法执行之前是不可调用的。

function myFunction() {
    function myInnerFunction() {
        print "inner value\n";
    }
}
myFunction();
myInnerFunction();
def my_function
    def my_inner_function
        print "inner value"
    end
end
my_function
my_inner_function
2.3 函数参数
  • 默认值 :与 PHP 类似,可以通过在方法定义中为参数赋值来使用默认值。但 Ruby 可以将任何数据类型作为默认值,而 PHP 不能将新对象作为默认值。
function myFunction($arg1='default', $arg2=array('a', 'b')) {
    print "$arg1 $arg2[0]\n";
}
myFunction();
def my_function(arg1='default', arg2=['a', 'b'], arg3=Object.new)
    puts "#{arg1} #{arg2[0]}"
end
my_function
  • 哈希参数 :哈希可以在不使用花括号的情况下传递给方法,这种语法模拟了命名参数,在 Rails 中经常使用以提高代码的可读性。
def format(text, options = {})
    text.reverse! if options[:reverse]
    text.upcase! if options[:upcase]
    text
end
puts format('Live not on evil.', :reverse => true, :upcase => true)
  • 块参数 :可以使用单行花括号块或多行 do/end 风格的块将可选块传递给方法。在方法定义中使用 & 前缀的最终参数来引用块。
def checker(value, &block)
    value << block.call if block
    value
end
puts checker('test')
puts checker('test') { " with a block" }
  • 可变参数 :Ruby 有一个很好的处理可变参数的方法,使用 * 前缀的数组参数来收集所有剩余的元素。
function myFunction() {
    $argNum = func_num_args();
    $args = func_get_args();
    $first = array_shift($args);
    $second = array_shift($args);
    print "($argNum) total, first: $first\n";
}
myFunction('red', 'green', 'blue');
def my_function(*args)
    arg_num = args.size
    first = args.shift
    second = args.shift
    puts "(#{arg_num}) total, first: #{first}"
end
my_function('red', 'green', 'blue')

还可以要求指定数量的参数,并使用 * 运算符收集其余的参数。

function anotherFunction($first, $second) {
    $args = func_get_args();
    $third = $args[2];
    print "first: $first, third: $third\n";
}
anotherFunction('red', 'green', 'blue');
def another_function(first, second, *more)
    third = more.first
    puts "first: #{first}, third: #{third}"
end
another_function('red', 'green', 'blue')
2.4 返回值

与 PHP 一样,Ruby 使用 return 关键字从方法返回值。但与 PHP 不同的是,Ruby 会隐式返回任何方法中最后一个被评估的表达式。通常在不需要时不使用 return 关键字是 Ruby 的常见约定。

function sayHi($name) {
    return "hello, $name\n";
}
print sayHi('Joe');
def say_hi(name)
    "hello, #{name}"
end
puts say_hi('Joe')

可以从方法返回任何值,并且通常返回一个数组,然后将其拆分为多个变量。Ruby 不需要使用 list 等函数来分配变量,可以简单地使用逗号分隔的名称列表。

function myColors() {
    return array('red', 'green', 'blue');
}
list($color1, $color2, $color3) = myColors();
print "$color1\n";
def my_colors
    %w{red green blue}
end
color1, color2, color3 = my_colors
puts color1
2.5 可变函数

存储方法名的变量可以像在 PHP 中一样用于调用该方法。在 Ruby 中,我们将方法名和参数数组传递给 send 方法来调用它。

function myFunction($arg1) {
    print "$arg1 in my function!\n";
}
$a = 'myFunction';
$a('value');
def my_method(arg1)
    puts "#{arg1} in my method!"
end
a = "my_method"
send(a, ["value"])
2.6 内置函数

PHP 有广泛的内置函数,都存在于全局作用域中,而 Ruby 采取了不同的方法。Ruby 方法围绕它们修改的对象构建,这意味着我们处理的每个数据类型都有其自己的方法。

$colors = array('blue', 'red');
$reversed = array_reverse($colors);
var_export($reversed);
colors = [:blue, :red]
reversed = colors.reverse
p reversed

这种差异很重要,因为它允许我们将功能从全局命名空间中逻辑分离,使得记忆函数更加容易,因为不需要使用任意前缀来分组相关函数。

通过对 PHP 和 Ruby 的控制结构和函数的对比,我们可以看到两种语言在实现相同功能时的不同方式。开发者可以根据项目的需求和个人的编程习惯来选择使用哪种语言。

PHP 与 Ruby 控制结构和函数的对比

3. 总结与对比表格

为了更清晰地展示 PHP 和 Ruby 在控制结构和函数方面的差异,下面通过表格进行总结:
| 类别 | PHP | Ruby |
| — | — | — |
| if 语句 | 使用 if {} ,括号围绕表达式必需 | 使用 if/end ,括号可选,有 if unless 修饰符用于单行条件 |
| else 和 elseif/elsif | else elseif 常规使用 | else 类似, elseif 变为 elsif ,可使用 : then 放同一行 |
| while 循环 | 常规 while 语法 | while/end 风格,有 while until 修饰符用于单行循环 |
| do while 循环 | 支持 do/while | 无 do/while ,用 begin/end 结合 while until 替代 |
| for 循环 | 有 for 结构 | 无 for ,用 times upto downto step 等迭代器方法 |
| foreach 循环 | foreach 遍历数组或关联数组 | 用 each each_with_index 遍历数组, each 遍历哈希 |
| break 语句 | 参数确定跳出封闭语句数量 | 参数作为语句返回值 |
| continue/next 语句 | continue 可带参数指定跳过循环数 | next 无额外参数指定跳过循环功能 |
| switch 语句 | switch break 停止执行 | case 表达式找到匹配值后自动停止,无需 break |
| require 和 include | require_once 加载一次, require 可多次加载 | require 类似 require_once .rb 扩展名可选; load 可多次加载,需扩展名 |
| 块(Blocks) | 无 | 可使用 {} do/end 传递代码块,用 yield 执行,可检查块是否传递 |
| 函数定义 | 使用 function {} | 使用 def/end ,方法名区分大小写 |
| 函数参数 | 可设默认值,不能将新对象作默认值 | 可设默认值,任何数据类型可作默认值,有哈希参数、块参数、可变参数处理方式 |
| 返回值 | 用 return 返回值 | 用 return 返回值,也会隐式返回最后表达式,常不使用 return |
| 可变函数 | 变量存储函数名直接调用 | 变量存储方法名,用 send 方法调用 |
| 内置函数 | 大量内置函数在全局作用域 | 方法围绕对象构建,各数据类型有自己方法 |

4. 流程图展示

下面通过 mermaid 流程图展示 Ruby 中一个常见的循环操作流程,以 times 方法为例:

graph TD;
    A[开始] --> B[定义循环次数 n];
    B --> C[初始化计数器 i = 0];
    C --> D{i < n};
    D -- 是 --> E[执行块内代码];
    E --> F[i = i + 1];
    F --> D;
    D -- 否 --> G[结束];

这个流程图展示了 Ruby 中 n.times do |i| ... end 循环的执行过程。首先定义循环次数 n ,然后初始化计数器 i 为 0,每次循环检查 i 是否小于 n ,如果是则执行块内代码并将 i 加 1,直到 i 不小于 n 时结束循环。

5. 实际应用建议

在实际开发中,选择 PHP 还是 Ruby 可以根据以下因素考虑:
- 项目类型
- 如果是 Web 开发,尤其是快速搭建网站和应用,PHP 有丰富的 Web 开发框架如 Laravel、CodeIgniter 等,社区资源丰富,开发效率高。
- 如果是开发复杂的 Web 应用、微服务或者对代码简洁性和灵活性要求较高,Ruby on Rails 是一个很好的选择,它遵循“约定优于配置”的原则,能快速开发出高质量的应用。
- 团队技术栈 :如果团队成员对 PHP 比较熟悉,那么使用 PHP 进行开发可以减少学习成本,提高开发效率。反之,如果团队有 Ruby 开发经验,Ruby 可能更合适。
- 性能要求 :PHP 在性能上有一定优势,尤其是在处理高并发和大规模数据时。而 Ruby 在性能方面相对较弱,但通过一些优化手段和工具也能满足大多数应用的需求。

6. 总结

通过对 PHP 和 Ruby 的控制结构和函数的详细对比,我们深入了解了这两种语言在实现相同功能时的不同方式。PHP 具有广泛的内置函数和成熟的 Web 开发生态,适合快速开发和处理大规模数据。Ruby 则以其简洁、灵活的语法和强大的块功能,在构建复杂应用和提高开发效率方面表现出色,尤其是 Ruby on Rails 框架的使用。

开发者在选择使用哪种语言时,应综合考虑项目需求、团队技术栈、性能要求等因素,充分发挥每种语言的优势,以实现最佳的开发效果。同时,了解两种语言的差异也有助于开发者在不同的项目场景中灵活切换和运用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值