lib/object.fy in fancy-0.7.0 vs lib/object.fy in fancy-0.8.0
- old
+ new
@@ -353,21 +353,21 @@
val
}
def if_responds? {
"""
- @return RespondsToProxy for @self
+ @return @Proxies::RespondsToProxy@ for @self
- Returns a @RespondsToProxy@ for @self that forwards any messages
+ Returns a @Proxies::RespondsToProxy@ for @self that forwards any messages
only if @self responds to them.
Example:
# only send 'some_message: if object responds to it:
object if_responds? some_message: some_parameter
"""
- RespondsToProxy new: self
+ Proxies RespondsToProxy new: self
}
def backtick: str {
"""
This is the default implementation for backtick: which gets called when using the backtick syntax.
@@ -464,11 +464,11 @@
self receive_message: msg with_params: params
case 'future ->
val = self receive_message: msg with_params: params
sender completed: val
}
- } catch Exception => e {
+ } catch StandardError => e {
{ sender failed: e } if: sender
die!
e raise!
}
}
@@ -583,19 +583,14 @@
Calls @block with @self while having slots defined in @slotnames
be mutable during execution of @block.
"""
metaclass read_write_slots: slotnames
- val = nil
try {
- val = block call: [self]
+ return block call: [self]
} finally {
- slotnames each: |s| {
- metaclass undefine_method: s
- metaclass undefine_method: "#{s}:"
- }
- return val
+ metaclass remove_slot_accessors_for: slotnames
}
}
private: 'with_mutable_slots:do:
def <=> other {
@@ -625,13 +620,25 @@
# this is the same as:
some_complex_object method_1: arg1
some_complex_object method_2: arg2
some_complex_object method_3: arg3
+
+ If you pass it a block with 1 argument this method behaves exactly like @Object#tap:@
+
+ Example:
+ some_complex_object do: @{
+ method_1: arg1
+ method_2: arg2
+ method_3: arg3
+ }
"""
- block call_with_receiver: self
+ match block arity {
+ case 0 -> block call_with_receiver: self
+ case _ -> block call: [self]
+ }
self
}
def tap: block {
"""
@@ -661,18 +668,21 @@
"""
Thread sleep: seconds
}
- def let: var_name be: value in: block (nil) {
+ def let: var_name be: value in: block (nil) ensuring: ensure_block ({}) {
"""
@var_name @Symbol@ that represents the name of the dynamic variable to be set.
@value Value for the variable.
@block @Block@ in which @var_name will be dynamically bound to @value.
+ @ensure_block @Block@ to be always called, even when @block raised an exception.
@return Returns @value
Dynamically rebinds @var_name as dynamic variable with @value as the value within @block.
+ Exceptions raised within @ensure_block are ignored.
+ Those raised in @block will be reraised up the callstack.
Example:
File write: \"/tmp/output.txt\" with: |f| {
let: '*stdout* be: f in: {
\"hello, world!\" println # writes it to file not STDOUT
@@ -685,19 +695,17 @@
Thread current[var_name]: value
return value
}
oldval = Thread current[var_name]
- retval = nil
try {
Thread current[var_name]: value
- retval = block call
- } catch Exception => e {
- e raise!
+ block call
+ return value
} finally {
+ try { ensure_block call } catch {}
Thread current[var_name]: oldval
- return retval
}
}
def with_output_to: filename do: block {
"""
@@ -718,7 +726,90 @@
"""
File write: filename with: |f| {
let: '*stdout* be: f in: block
}
+ }
+
+ def fancy_methods {
+ """
+ @return @Array@ of all class methods defined in Fancy.
+ """
+
+ methods select: @{ includes?: ":" }
+ }
+
+ def ruby_methods {
+ """
+ @return @Array@ of all class methods defined in Ruby.
+ """
+
+ methods - fancy_methods
+ }
+
+ def >< other {
+ """
+ @other Other @Object@ to create a @MatchAny@ matcher with.
+
+ Shorthand for: `MatchAny new: self with: other`
+ """
+
+ Matchers MatchAny new: self with: other
+ }
+
+ def <> other {
+ """
+ @other Other @Object@ to create a @MatchAll@ matcher with.
+
+ Shorthand for: `MatchAll new: self with: other`
+ """
+
+ Matchers MatchAll new: self with: other
+ }
+
+ def ignoring: exception_classes do: block {
+ """
+ @exception_classes @Fancy::Enumerable@ of @Exception@s to ignore within @block.
+ @block @Block@ to be executed while ignoring (catching but not handling) @Exception@s defined in @exception_classes.
+
+ Example:
+ ignoring: (IOError, ZeroDivisionError) in: {
+ # do something
+ }
+ """
+
+ try {
+ block call
+ } catch (exception_classes to_a join_by: '><) {}
+ }
+
+ def rebind_method: method_name with: rebind_callable within: within_block {
+ """
+ @method_name Name of (singleton) method to rebind for @self.
+ @rebind_callable Name of method or @Block@ to rebind @method_name to.
+ @within_block @Block@ in which @method_name is rebound to @rebind_callable.
+ @return Value of calling @within_block with @self.
+
+ If @within_block takes an argument, it is called with @self.
+
+ Example:
+ class MyRebindableClass {
+ def foo {
+ 42
+ }
+ }
+
+ r = MyRebindableClass new
+ r rebind_method: 'foo with: { 0 } within: @{ foo } # => 0
+ """
+
+ metaclass rebind_instance_method: method_name with: rebind_callable within: within_block receiver: self
+ }
+
+ def _ {
+ """
+ @return @Object@.
+ """
+
+ Object
}
}
\ No newline at end of file