第一个ruby程序
老实说不是很喜欢去讨论ruby和python的对比,似乎总是把两个语言放在对立的位置上,我觉得没有必要,同样是动态语言,同样是解释型脚本语言,很多特性都是互相影响的,语言本身也在不断进化,我们更应该关注的是编程思想而不是语言本身。
说了一点题外话,之所以要求学ruby,主要就是因为有一本好书想读,就是Paolo Perrotta的《Ruby元编程》,书看了一天,ruby语法学了半天,用irb捣鼓了一晚上,应该说跟python,scala都有很多相近的地方,因为没有接触Lisp,Haskell之类的函数编程语言,因此不好说跟他们怎么样,但是学了python再去学ruby是觉得非常轻松地。
书中星期二中有个问题挑战,就是对DS和Computer类中的函数进行动态生成,好吧,我又犯老毛病了,书看一半,自己先干,在看到define_method方法后用我自己的思路捣鼓了一个解决方案,还没看书中的实例,先把代码弄出来看看,以下就是我的第一个ruby程序:
# 数据源定义,原应为关联数据库,这里只是进行模拟
class DS
parts = 'cpu', 'mouse', 'keyboard' # 临时数组用于批量生成方法
parts.each do |part|
define_method "get_#{part}_info".to_sym do |id| # 生成三种设备的信息函数
"This is #{part} #{id}."
end
define_method "get_#{part}_price".to_sym do |id| # 生成三种设备的价格函数
parts.zip([150, 50, 40]).to_h[part] # 通过zip合并数组转换为哈希结构再索引
end
end
end
# 电脑配件定义
class Computer
def initialize(computer_id, data_source) # 初始化id和数据源
@id = computer_id
@data_source = data_source
end
parts = 'cpu', 'mouse', 'keyboard'
parts.each do |part|
define_method part.to_sym do
info = @data_source.send("get_#{part}_info".to_sym, @id)
price = @data_source.send("get_#{part}_price".to_sym, @id)
result = "#{info} ($#{price})"
return " * #{result}" if price >= 100 # 判断价格是否高于100,加星号显示
result
end
end
end
puts "DS methods: #{DS.instance_methods(false)}"
puts "Computer methods: #{Computer.instance_methods(false)}" ds = DS.new
computer = Computer.new(10, ds)
puts computer.cpu
puts computer.mouse
puts computer.keyboard
然后继续看书,在看到内省的用法的时候觉得比较好,想把我上面的程序修改一下,于是改成了这个样子:
# 电脑配件定义
class Computer
def initialize(computer_id, data_source) # 初始化id和数据源
@id = computer_id
@data_source = data_source
data_source.methods.grep(/^get_(.*)_info$/) {
define_method($1.to_sym) {
info = @data_source.send("get_#{$1}_info", @id)
price = @data_source.send("get_#{$1}_price", @id)
result = "#{info} ($#{price})"
return " * #{result}" if price >= 100 # 判断价格是否高于100,加星号显示
result
}
}
end
end
运行的时候报错了,然后才发现define_method是Class的私有函数,因为属于Class所以不能在实例函数中使用,而因为私有,所以只能隐式调用,如果想这么用只能通过send来进行调用,所以把程序改成了下面这个样子
class Computer
def initialize(computer_id, data_source) # 初始化id和数据源
@id = computer_id
@data_source = data_source
data_source.methods.grep(/^get_(.*)_info$/) {
Computer.send(:define_method, $1) {
info = @data_source.send("get_#{$1}_info", @id)
price = @data_source.send("get_#{$1}_price", @id)
result = "#{info} ($#{price})"
return " * #{result}" if price >= 100 # 判断价格是否高于100,加星号显示
result
}
}
end
end
很不幸,又出问题了,这次出在变量$1未被正确识别,原因是$1是全局变量,而ruby是动态解析的,只有在运行的时候才去获取$1的值,而那个时候它已经编程nil了,因此将全局变量保存为局部变量
# 电脑配件定义
class Computer
def initialize(computer_id, data_source) # 初始化id和数据源
@id = computer_id
@data_source = data_source
data_source.methods.grep(/^get_(.*)_info$/) {
part = $1
Computer.send(:define_method, part) {
info = @data_source.send("get_#{part}_info", @id)
price = @data_source.send("get_#{part}_price", @id)
result = "#{info} ($#{price})"
return " * #{result}" if price >= 100 # 判断价格是否高于100,加星号显示
result
}
}
end
end
其实是有点丑了,不过总要写得跟原文不太一样啦,对于ruby还有不少需要对比和理解,希望看完这本书能好一些
第一个ruby程序的更多相关文章
- 运行第一个ruby程序
0x00 安装 首先需要安装一个ruby的环境,ruby分为win.linux.macOS版本.不用系统安装方法略有差异,不在这进行讲解. 0x01 运行第一个ruby程序 我这里是win环境,打开命 ...
- [Ruby on Rails系列]3、初试Rails:使用Rails开发第一个Web程序
本系列前两部分已经介绍了如何配置Ruby on Rails开发环境,现在终于进入正题啦! Part1.开发前的准备 本次的主要任务是开发第一个Rails程序.需要特别指出的是,本次我选用了一个(Paa ...
- JFinal教程1——小白的第一个JFinal程序
为了使小白能够完全的按步骤创建第一个JFinal应用并运行,笔者将以Java界最流行的Eclipse平台为例,搭建出所有基础教程中喜欢的Hello world应用. 1. JFinal简介 2. 小白 ...
- Python 开篇及第一个Python程序
本节内容 python 简单介绍 python 2.x 或者python 3.x python 安装 第一个python程序 一.python简单介绍 python的创始人为吉多.范罗苏姆(Guido ...
- 为 Ruby 程序员准备的 Go 入门教程
这是我翻译的国外博客,如需转载请注明出处和原文链接 那些在Google的大牛们开发出了一种称为Go的牛叉的语言.乍一看,Ruby和Go有点像远房表亲.其实不然,他们那些互为补充的功能却让他们成为一对完 ...
- DirectX游戏编程(一):创建一个Direct3D程序
一.环境 Visual Studio 2012,DirectX SDK (June 2010) 二.准备 1.环境变量(如没有配置请添加) 变量名:DXSDK_DIR 变量值:D:\Software\ ...
- 第一个python程序
一个python程序的两种执行方式: 1.第一种方式是通过python解释器: cmd->python->进入python解释器->编写python代码->回车. 2.第二种方 ...
- 编写第一个MapReduce程序—— 统计气温
摘要:hadoop安装完成后,像学习其他语言一样,要开始写一个“hello world!” ,看了一些学习资料,模仿写了个程序.对于一个C#程序员来说,写个java程序,并调用hadoop的包,并跑在 ...
- 1.3 第一个C#程序
几乎没一门编程语言的第一个程序都叫“你好,世界”,所以先在visual studio 中创建一个Helloworld程序. 各部分的详细内容: Main方法是程序运行的起点,最重要的代码就写在Main ...
随机推荐
- 单因素特征选择--Univariate Feature Selection
An example showing univariate feature selection. Noisy (non informative) features are added to the i ...
- python socket
#!/usr/bin/env python import sys import time import socket s = socket.fromfd(sys.stdin.fileno(),sock ...
- Eclipse搭建SSH(Struts2+Spring+Hibernate)框架教程
| 版权声明:本文为博主原创文章,未经博主允许不得转载. 前言 确实,刚创博客,对于这个陌生的东西还是有些许淡然.这是我的第一篇博文,希望能给你们有帮助,这就是我最大的乐趣! 好了下面进入正题: SS ...
- C语言实现简单php自定义扩展
1.下载php源码 下载地址:http://cn2.php.net/get/php-5.6.29.tar.gz/from/this/mirror 传到/usr/local/src/下 上传命令:rz ...
- 解决MongoDB磁盘IO问题的三种方法
1.使用组合式的大文档 我们知道MongoDB是一个文档数据库,其每一条记录都是一个JSON格式的文档.比如像下面的例子,每一天会生成一条这样的统计数据: { metric: "conten ...
- 【性能诊断】StackOverflow引发的“网络”及系统稳定性问题
背景描述: 最近一个项目的系统管理员和业务运维人员分别反馈问题: 1.应用系统每个月会有一两次宕机,需要管理员手工重启IIS: 2.财务模块一个功能经常报网络错误“网络异常,请检查网络连接”“Unab ...
- 【SharePoint学习笔记】第4章 SharePoint UI 定制
第4章 SharePoint UI 定制 SharePoint 与 ASP.NET 好的Asp.Net人员很快就能成为好的SharePoint开发人员 Web应用程序 Mi ...
- AngularJS之directive
AngularJS之directive AngularJS是什么就不多舌了,这里简单介绍下directive.内容基本上是读书笔记,所以如果你看过<AngularJS up and runnin ...
- SQL:over partition by与group by 的区别
group by是对检索结果的保留行进行单纯分组,一般总爱和聚合函数一块用例如AVG(),COUNT(),max(),main()等一块用. partition by虽然也具有分组功能,但同时也具有其 ...
- VR定制开发、AR定制开发(长年承接虚拟现实、增强现实应用、VR游戏定制开发,北京公司,可签合同)
Cardboard SDK for Unity的使用 上一篇文章作为系列的开篇,主要是讲了一些虚拟现实的技术和原理,本篇就会带领大家去看一看谷歌的Cardboard SDK for Unity,虽然目 ...