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