很多所谓的设计模式是语言的导致问题。一个问题既然能用编程解决,就没有模式的存在了,也没有什么再次抽象一说。
我想说两点:
Scala 10 年的时候靠着 actor 火了一两年,顺便把 erlang 的热度也带起来了。但是过了 12 年之后,go 和 docker 相继出来就没影了(相对而言)。 scala 的 play 和 erlang 的 chicagoboss 都是相当有特色的 fullstack framework,也是该死的死,该沉寂的沉寂。
老实说,elixir 我觉得能活跃个一两年,之后还是得回归小圈子,自己默默耍着。至于 crystal,看看每月众筹的进度,能不死就烧香拜佛了
主要还是吸收 ruby 的语法,语言是否优雅还是看个人,不过我觉得 crystal 已经做得足够棒了。
性能方面 benchmarks crystal 一般是跟 java,rust 对打,比 c 慢一点。就是并发不尽人意,等下一个大版本应该会好了。
尝试了一下另一种写法,不知道能不能满足。不过这种代码玩一下好,真要用还真不敢..
module RedisCache
CACHE = {}
def self.redis_cache_method_prefix
4.times.map { 10.times.map { (97 + rand(26)).chr }.join('') }.join('_')
end
def redis_cache &block
mod1 = Module.new(&block)
ims = mod1.instance_methods
mod2 = Module.new do
ims.each do |im|
prefix = RedisCache.redis_cache_method_prefix
class_eval <<-CODE
def #{im}(*args)
key = '#{prefix}_#{self.object_id}_#{im}'
if RedisCache::CACHE[key]
puts RedisCache::CACHE[key]
else
super
RedisCache::CACHE[key] = key
end
end
CODE
end
end
mod1.prepend(mod2)
self.include(mod1)
end
end
class A
extend RedisCache
redis_cache do
def hi
puts 'hello, world'
end
def hi2
end
end
end
A.new.hi #=> hello, world
A.new.hi #=> btafxausko_gnmqyfidcy_kdyvsmyqha_jkxqiwvemz_16998140_hi
% enables Ruby code processing for lines beginning with %
<> omit newline for lines starting with <% and ending in %>
> omit newline for lines ending in %>
- omit blank lines ending in -%>
rails 早期版本会强调这个写法,不过现在貌似也不怎么写了。
如果用 rails 自带的 turbolinks 是需要把 javascript tag 放在 head 里面的,如果不用 turbolinks,我也喜欢放底部,少套一层 domready 回调。
类似 Java/C# 本身也是需要要查找方法的,他们内部维护着一张保持对象内所有函数指针的 vtable,Ruby 也有一张类似的 method_table,通过 rb_method_entry_make
把方法加入到 method_table,每次调用方法 Ruby 会通过 class 和 method_id 查找 method_table,返回 rb_method_entry_t
,没有就直接抛出异常。这个过程是耗时的,而且无论有没有类型系统。
你给的代码思路是后面的优化,有点像是内联函数。(既然要调用,那么不如直接把函数内联到调用点)。但是,你并没有考虑到 oop 和动态语言的特性。按你的例子来看,每个 objects
是有 count
方法,但是 oop 里面一个方法是可能需要搜索继承链的。况且,ruby 没有编译期...
我想起了这个 gem 了 contracts.ruby。另外,性能是由语言性质和 vm 决定的,类型系统能提速很大程度是因为强类型语言一般都是编译型语言造成的错觉。至于类型系统可选,我觉得换个语言可能靠谱点,毕竟不像 ts 之于 js,后端可选择的余地很多。
首先,这样还是无法避免最最常见的类型问题,空指针。第二,缺乏动态性。举个例子,ruby 里面,file, io, stringio 都有个 close 方法,函数需要针对多个类型调用 close,这个时候没有 duck typing 或者结构化类型,就会显得非常的繁琐。
偶尔犯二无所谓,卡了一下午可能有点问题了。不过也有可能是他只用过 mongodb
但是也及其复杂,Scala 那套类型系统算是非常强大了,也非常成功地把他推上太阳系第一复杂语言的宝座。
其实 Javascript 也是通过原型链搜索方法,也是弱类型语言,但运行效率并不差。而关于类型检查的问题,目前 Ruby 的做法是用单元测试,Ruby 是解释型语言不能像 Erlang 一样用 spec
在编译期间检查,但 3.0 可能会参考 go interface 那套。
最后你提到的 C# 的var
能在声明时进行类型推导,但这个除了能少写一个单词真不算优点。
隔壁 cnode 的热度也在降,首页底部回复都是两天前。所以说人到底去哪了
以前 emacs 有个插件,只要少个 end 满屏幕血红色。不知道别的编辑器有没有。
webpack 对于用过 grunt,gulp 的人来说简直是天使..
起一个数据容器 b 挂到应用容器 a。如果需要备份,再起一个临时容器 c,用 volumes-from 把 b 挂到 c,不过这种做法网上一般是用 tar 备份,用 pg_dump 有些曲折。而且 rancher 能不能定时运行新容器是个问题。
也可以用 exec 对运行中的容器 a 操作。
这种持久化容器可以参照 rancher catalog 里面一些应用的 dockerfile,比如 pg
如果单纯想看看惰性求值怎么实现,ar 可能太大了点。可以看看 lazy.js
,这个比较简单
客气了,我也收获到一篇不错的文章:) 另外如果技术上的问题的话发论坛可能更好些。
检查一下 nginx.conf
,看看 server_name
后面漏了分号没。
还在招人么
假如 s2 = 'saaaaaaaaa'
,上面需要 count 10*2 次,下面只要 2*2 次。
md5 是单向加密
Mac 可以用 macgap ,把 meta
改一下就可以了。一键打包成 .app,启动快体积只有 3m。不过还是建议一楼的吧,实在是慢
扫地机器人只能吸地面,买那种小型的手持吸尘器就够用了,有钱上戴森
最开始引我入坑是看到一个非常牛的高中妹子用 Ruby 写抓取 acfun 弹幕的脚本(PAD 播放器的作者,如果是最早期 b 站会员可能知道她是谁)
当时就对这种 do/end 语法感到新奇,不过由于刚入坑 Django(当时貌似是 1.3beta),只学了语言本身,没继续学习 Rails。但是也一直有用 Ruby 写一些有趣的东西。临近毕业时才开始学习 Rails,直到现在用 Rails 工作也有 3 年多了吧..
大学的时候折腾过,还浪费过时间配置过 emacs 浏览器,scala ide(卡得一 b)等等没卵用的插件。毕业后就没时间精力去折腾编辑器了,怎么方便怎么来,而且写前端还是需要鼠标的。
正则可以使用 =~
,多余的类型判断就不要了,比如 gsub
出来的值没必要判断是否是字符串,hash 可以使用 dig
来获取值。不过可能正则没办法保证提取的 json 字符串是否正确。
IO.foreach('test.log') do |line|
if /(kafka:)({.+}(?=",))+/ =~ line
hash = JSON.parse($2.gsub('\\', ''))
hash.dig('media_info', 'format', 'duration')
end
end
一行代码流...
IO.read('test.log').scan(/(?>kafka:)((?:{.+?}(?=",))+)/m).flatten.map { |l| JSON.parse(l.gsub('\\', ''))&.dig('media_info', 'format', 'duration') }
angular1.08 的时候我机智地跑了
react_on_rails 提供了服务器渲染,还是挺感兴趣的,然而并没有做 spa 的打算,还是用 mithril.js 凑合用着
#5 楼 @Insub 如果像 p_id, m_id 这些 param 是有规律的话那好说,举个例子,可以把路径转换成正则表达式,然后按顺序一个个 match,看能不能匹配。但是这样得考虑一下性能。
str = '/publishers/:p_id/magazines/:m_id/photos/:p1_id'.gsub(/:(\w+_id)/, '(?<\1>.*?)')
#=> /publishers/(?<p_id>.*?)/magazines/(?<m_id>.*?)/photos/(?<p_id>.*?)
reg = Regexp.new(str)
reg.match('/publishers/15/magazines/3/photos/2')
#=> #<MatchData "/publishers/15/magazines/3/photos/" p_id:"15" m_id:"3" p1_id:"2">