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