-
Notifications
You must be signed in to change notification settings - Fork 49
/
Copy pathcascade.rb
62 lines (50 loc) · 1.27 KB
/
cascade.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# In Smalltalk, you can "cascade" side-effectful calls to the same
# object using the semicolon (;) operator. E.g.:
#
# aStream
# print: x;
# nextPutOn: ' @ ';
# print: y
#
# If I understand it correctly, the semicolon is effectively a
# K-combinator or "Kestrel" (see
# https://github.com/raganwald/homoiconic/blob/master/2008-10-29/kestrel.markdown#readme)
#
# I am jealous. Sure, we have tap, but that's awfully verbose by
# comparison:
x, y = 23, 32
$stdout.tap do |s|
s.print x end.tap do |s|
s.print ' @ ' end.tap do |s|
s.print y
end
# Note: Yes, I could use a single tap for all three calls, but I'm
# trying to exactly mimic the semantics of Smalltalk's ';' operator as
# used in the example above.
puts
# Let's see if we can do better for this simple case of cascading a
# series of commands, while ignoring their return values.
require 'delegate'
module Cascadable
class CascadeProxy < BasicObject
def initialize(object)
@object = object
end
def method_missing(*args, &block)
@object.send(*args, &block)
return self
end
end
def cascade
return CascadeProxy.new(self)
end
alias_method :k, :cascade
end
class Object
include Cascadable
end
$stdout.k.
print(x).
print(' @ ').
print(y)
# Yay!