lib/object.fy in fancy-0.3.3 vs lib/object.fy in fancy-0.4.0
- old
+ new
@@ -10,162 +10,229 @@
@return @String concatenation of @String values of @self and @other.
Returns the @String concatenation of @self and @other.
Calls to_s on @self and @other and concatenates the results to a new @String.
"""
+
to_s + (other to_s)
}
def loop: block {
- "Infinitely calls the block (loops)."
- block loop
+ """
+ @block @Block@ to be called endlessly (loop).
+
+ Infinitely calls the block (loops).
+ """
+
+ { true } while_true: block
}
def println {
- "Same as Console println: self. Prints the object on STDOUT, followed by a newline."
+ """
+ Same as:
+ Console println: self
+
+ Prints @self on @STDOUT, followed by a newline.
+ """
+
Console println: to_s
}
def print {
- "Same as Console print: self. Prints the object on STDOUT."
+ """
+ Same as:
+ Console print: self
+
+ Prints @self on STDOUT.
+ """
+
Console print: to_s
}
def != other {
- "Indicates, if two objects are unequal."
+ """
+ @other Other object to compare against.
+ @return @true if @self is not equal to @other, @false otherwise.
+
+ Indicates, if two objects are not equal.
+ """
+
self == other not
}
def if_true: block {
- "Calls the @block if @true? returns @true"
+ """
+ @block @Block@ to be called.
+ @return Value of calling @block with @self.
+
+ Calls the @block (default behaviour).
+ """
+
block call: [self]
}
def if_true: then_block else: else_block {
- "Calls the @then_block if @true? returns @true - otherwise @else_block is called"
+ """
+ @then_block @Block@ to be called.
+ @else_block Does not get called (default behaviour).
+
+ @return Value of calling @then_block with @self.
+
+ Calls the @then_block (default behaviour).
+ """
+
then_block call: [self]
}
def if_false: block {
- "Calls the @block if @false? returns @true@"
+ """
+ @return @nil
+
+ Does nothing (default behaviour).
+ """
nil
}
def if_false: then_block else: else_block {
- "Calls the @then_block if @false? returns @true - otherwise @else_block is called"
- else_block call
- }
+ """
+ @then_block Does not get called (default behaviour).
+ @else_block @Block@ to be called.
+ @return Value of calling @else_block.
- def if_nil: block {
- "Calls the @block if @nil? returns @true@"
- nil
- }
+ Calls @else_block (default behaviour).
+ """
- def if_nil: then_block else: else_block {
- "Calls the @then_block if @nil? returns @true - otherwise @else_block is called"
else_block call
}
+ alias_method: 'if_nil: for: 'if_false:
+ alias_method: 'if_nil:else: for: 'if_false:else:
+
def nil? {
- "Returns @false."
+ """
+ @return @false.
+ """
+
false
}
def false? {
- "Returns @false."
+ """
+ @return @false.
+ """
+
false
}
def true? {
- "Returns @false."
+ """
+ @return @false.
+ """
+
false
}
- def or_take: other {
- "Returns self if it's non-nil, otherwise returns the given object."
-
- if: nil? then: {
- other
- } else: {
- self
- }
- }
-
- def to_num {
- 0
- }
-
def to_a {
+ """
+ @return @Array@ representation of @self.
+ """
+
[self]
}
def to_i {
+ """
+ @return @Fixnum@ representation of @self.
+ """
+
0
}
def to_enum {
+ """
+ @return @FancyEnumerator@ for @self using 'each: for iteration.
+ """
+
FancyEnumerator new: self
}
def to_enum: iterator {
+ """
+ @iterator Message to use for iteration on @self.
+ @return @FancyEnumerator@ for @self using @iterator for iteration.
+ """
+
FancyEnumerator new: self with: iterator
}
def and: other {
"""
+ @other Object or @Block@ (for short-circuit evaluation) to compare @self to.
+ @return @other if both @self and @other are true-ish, @self otherwise.
+
Boolean conjunction.
- Returns @other if @self and @other are true-ish, otherwise @false.
+ If @self and @other are both true-ish (non-nil, non-false), returns @other.
+ If @other is a @Block@, calls it and returns its return value.
"""
if_true: {
{ other = other call } if: (other is_a?: Block)
- return other
+ other
+ } else: {
+ self
}
- return self
}
def or: other {
"""
+ @other Object or @Block@ (for short-circuit evaluation) to compare @self to.
+ @return @self if @self is true-ish, @other otherwise.
+
Boolean disjunction.
- Returns true if either @self or other is true, otherwise nil.
+ If @self is true-ish (non-nil, non-false) returns @self.
+ Otherwise returns @other (if @other is a @Block@, calls it first and returns its return value)
"""
+
if_true: {
- return self
+ self
} else: {
{ other = other call } if: (other is_a?: Block)
- return other
+ other
}
}
- def or: other {
+ def xor: other {
"""
- Boolean disjunction.
- Returns true if either @self or other is true, otherwise nil.
+ @other @Object@ to compare @self against.
+ @return @true if only one of @self and @other is true, @false otherwise.
"""
- unless: self do: {
- { other = other call } if: (other is_a?: Block)
- return other
+
+ if_true: {
+ other not
+ } else: {
+ other not not
}
- return self
}
alias_method: ':&& for: 'and:
alias_method: ':|| for: 'or:
def if: cond then: block {
"""
Same as:
cond if_true: block
"""
+
cond if_true: block
}
def if: cond then: then_block else: else_block {
"""
Same as:
cond if_true: then_block else: else_block
"""
+
cond if_true: then_block else: else_block
}
def while: cond_block do: body_block {
"""
@@ -183,37 +250,84 @@
"""
cond_block until_do: body_block
}
+ def do: body_block while: cond_block {
+ """
+ @body_block @Block@ to be called at least once and as long as @cond_block yields a true-ish value.
+ @cond_block Condition @Block@ used to determine if @body_block@ should be called again.
+ """
+
+ body_block call: [nil]
+ cond_block while_do: body_block
+ }
+
+ def do: body_block until: cond_block {
+ """
+ @body_block @Block@ to be called at least once and as long as @cond_block yields a false-ish value.
+ @cond_block Condition @Block@ used to determine if @body_block@ should be called again.
+ """
+
+ body_block call
+ cond_block until_do: body_block
+ }
+
def unless: cond do: block {
"""
Same as:
cond if_true: { nil } else: block
"""
cond if_true: { nil } else: block
}
+ def unless: cond do: block else: else_block {
+ """
+ Same as:
+ cond if_true: else_block else: block
+ """
+
+ cond if_true: else_block else: block
+ }
+
def method: method_name {
- "Returns the method with a given name for self, if defined."
+ """
+ @return @Method@ with @method_name defined for @self, or @nil.
+ Returns the method with a given name for self, if defined.
+ """
method(message_name: method_name)
}
def documentation {
- "Returns the documentation string for an Object."
- Fancy Documentation for: self . to_s
+ """
+ @return @Fancy::Documentation@ object for @self.
+
+ Returns the @Fancy::Documentation@ object for an Object.
+ """
+
+ Fancy Documentation for: self
}
- def documentation: str {
- "Sets the documentation string for an Object."
- Fancy Documentation for: self is: str
+ def documentation: docstring {
+ """
+ @docstring New docstring for @self.
+
+ Sets the documentation string for an Object.
+ """
+
+ Fancy Documentation for: self is: docstring
}
def identity {
- "The identity method simply returns self."
+ """
+ @return @self.
+
+ The identity method simply returns self.
+ """
+
self
}
def returning: value do: block {
"""
@@ -266,40 +380,232 @@
System pipe: str . read
}
def ? future {
+ """
+ @future Future object to get the value from.
+ @return Result of calling #value on @future.
+
+ Calls #value on @future. Shortcut method.
+ """
+
future value
}
def yield {
+ """
+ Same as Fiber##yield.
+ """
+
Fiber yield
}
def yield: values {
+ """
+ Same as Fiber##yield:
+ """
+
Fiber yield: values
}
- def wait: seconds {
- Fiber yield: [seconds]
- }
-
def next {
- "Skip to the next iteration"
+ """
+ Skip to the next iteration.
+ """
+
Fancy NextIteration new raise!
}
def next: value {
- "Return value for this iteration and skip to the next one"
- (Fancy NextIteration new: value) raise!
+ """
+ @value Value for next iteration.
+
+ Returns @value for current iteration and skip to the next one.
+ """
+
+ Fancy NextIteration new: value . raise!
}
def break {
- "Stop iterating"
+ """
+ Breaks / Stops current iteration.
+ """
+
Fancy BreakIteration new raise!
}
def break: value {
- "Return value from iteration"
- (Fancy BreakIteration new: value) raise!
+ """
+ @value Value to return from iteration.
+
+ Returns @value from iteratioen.
+ """
+
+ Fancy BreakIteration new: value . raise!
}
-}
+
+ def __spawn_actor__ {
+ @__actor__active__ = true
+ Actor spawn: {
+ __actor__loop__
+ }
+ }
+
+ def __actor__loop__ {
+ while: { @__actor__active__ } do: {
+ sender = nil
+ try {
+ type, msg, sender = Actor receive
+ msg, params = msg
+ match type {
+ case 'async ->
+ self receive_message: msg with_params: params
+ case 'future ->
+ val = self receive_message: msg with_params: params
+ sender completed: val
+ }
+ } catch Exception => e {
+ { sender failed: e } if: sender
+ die!
+ e raise!
+ }
+ }
+ }
+
+ def __actor__die!__ {
+ @__actor__active__ = false
+ @__actor__ = nil
+ }
+
+ def __actor__ {
+ @__actor__ = @__actor__ || { __spawn_actor__ }
+ @__actor__
+ }
+
+ protected: [ '__spawn_actor__, '__actor__loop__, '__actor__die!__, '__actor__ ]
+
+ def die! {
+ """
+ Tells an object to let its actor to die (quit running).
+ """
+
+ __actor__die!__
+ }
+
+ def actor {
+ """
+ Returns the Object's actor.
+ If none exists at this moment, a new one will be created
+ and starts running in the background.
+ """
+
+ __actor__
+ }
+
+ def send_future: message with_params: params ([]) {
+ """
+ @message Message to be sent as a @FutureSend@.
+ @params @Array@ of parameters of the @FutureSend@.
+ @return @FutureSend@ object that will hold the return value of @message with @params on @self.
+
+ Creates a @FutureSend@ object (a Future / Promise) that will hold the value of sending @message to @self.
+ """
+
+ FutureSend new: __actor__ receiver: self message: message with_params: params
+ }
+
+ def send_async: message with_params: params ([]) {
+ """
+ @message Message to be sent asynchronously to @self.
+ @params @Array@ of parameters as part of sending @message asynchronously to @self.
+ @return @nil
+
+ Sends @message with @params to @self asynchronously and immediately returns @nil.
+ """
+
+ __actor__ ! ('async, (message, params), nil)
+ nil
+ }
+
+ def synchronized: block {
+ """
+ @block @Block@ to be run only by one Thread at a time.
+
+ Runs a given @Block@ in a synchronized fashion if called by multiple Threads.
+ Uses a @Mutex@ in the background for synchronization (created on demand for each @Object@).
+ """
+
+ @__mutex__ = @__mutex__ || { Mutex new() }
+ @__mutex__ synchronize(&block)
+ }
+
+ def copy_slots: slots from: object {
+ slots each: |s| {
+ set_slot: s value: (object get_slot: s)
+ }
+ }
+
+ def get_slots: slots {
+ """
+ @slots @Array@ of slot names to retrieve from @self.
+ @return @Array@ of slot values of slot names passed in via @slots.
+ """
+
+ slots map: |s| {
+ get_slot: s
+ }
+ }
+
+ def <=> other {
+ """
+ @other Other object to compare against.
+ @return -1 if @self is smaller, 0 if @self is equal or 1 if @self is greater or equal compared to @other.
+ """
+
+ { return -1 } if: (self < other)
+ { return 0 } if: (self == other)
+ return 1 # greater or equal to other
+ }
+
+ def do: block {
+ """
+ @block @Block@ to be called in the context of @self.
+
+ Helper method that calls @block with @self as the receiver.
+ This allows message cascading like code, e.g.:
+
+ some_complex_object do: {
+ method_1: arg1
+ method_2: arg2
+ method_3: arg3
+ }
+
+ # this is the same as:
+ some_complex_object method_1: arg1
+ some_complex_object method_2: arg2
+ some_complex_object method_3: arg3
+ """
+
+ block call_with_receiver: self
+ }
+
+ def slots {
+ """
+ @return @Set@ of slot names that @self has.
+ """
+
+ Set new: $ instance_variables map: |s| {
+ s rest to_sym
+ }
+ }
+
+ def sleep: seconds {
+ """
+ @seconds Amount of seconds to sleep.
+
+ Sets the current Thread (in which self is running) for a given amount to sleep.
+ """
+
+ Thread sleep: seconds
+ }
+}
\ No newline at end of file