contains behavior related to flow control

Mimics
Inactive cells
Active cells
Specs
Inactive cells (details)
inspect = "DefaultBehavior FlowControl"
kind = "DefaultBehavior FlowControl"
notice = "DefaultBehavior FlowControl"
Active cells (details)
(+args)

returns result of evaluating first argument

method(+args, 
  if(args length ==(1), 
    args [](0), 
    tuple(*(args))))
break(value nil)

breaks out of the enclosing context. if an argument is supplied, this will be returned as the result of the object breaking out of

cond(...)

takes zero or more arguments. each two arguments are paired, where the first one is the condition part, and the second is the then-part. if there's an uneven number of arguments, that part is the else-part. if no arguments are provided, or no conditions match and there is no else part, cond returns nil.

syntax(
  DefaultBehavior FlowControl cell(:cond) createNestedIfStatements(call arguments))
continue()

breaks out of the enclosing context and continues from that point again.

dip(...)

takes one argument name and one piece of code that will get the receiver as argument and return the result of calling the code

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    code = call arguments [](
        1) 
    
    LexicalBlock createFrom(list(argName, code), call ground) call(self) 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
do(...)

executes the arguments with the receiver as context and ground, and then returns the receiver.

macro(
  call arguments each(evaluateOn(cell("@"))) 
  cell("@"))
ensure([code], +[ensureBlocks])

will execute and return the value of the first argument. after the code has run, all the remaining blocks of code are guaranteed to run in order even if a non-local flow control happens inside the main code. if any code in the ensure blocks generate a new non-local flow control, the rest of the ensure blocks in that specific ensure invocation are not guaranteed to run.

for(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "map", "flatMap") 
  )
for:dict(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "map:dict", "flatMap:dict") 
  )
for:set(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "map:set", "flatMap:set") 
  )
if(condition, [then] nil, [else] nil)

evaluates the first arguments, and then evaluates the second argument if the result was true, otherwise the last argument. returns the result of the call, or the result if it's not true.

ignoreErrors(...)

takes one or two pices of code. runs the first code segment and returns nil if it signals an error. If a second argument of code is given, evaluates this only when an error is encountered and uses the result to return. if everything works as expected, ignoreErrors will just return the result of the first evaluation

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    protectedCode = call arguments [](
        0) 
    
    bind(rescue(Condition Error, fn(c, nil)), 
      protectedCode evaluateOn(call ground, call ground)), 
    argCount ==(
      2), 
    
    protectedCode = call arguments [](
        0) 
    otherwiseCode = call arguments [](
        1) 
    
    bind(rescue(Condition Error, fn(c, otherwiseCode evaluateOn(call ground, call ground))), 
      protectedCode evaluateOn(call ground, call ground)), 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
let([code], +[placesAndValues])

takes zero or more place and value pairs and one code argument, establishes a new lexical scope and binds the places to the values given. if the place is a simple name, it will just be created as a new binding in the lexical scope. if it is a place specification, that place will be temporarily changed - but guaranteed to be changed back after the lexical scope is finished. the let-form returns the final result of the code argument.

loop(+[body])

loops forever - executing it's argument over and over until interrupted in some way.

p:for(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "p:map", "p:flatMap") 
  )
p:for:dict(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "p:map:dict", "p:flatMap:dict") 
  )
p:for:set(...)

nil

syntax(
  DefaultBehavior FlowControl cell(:for) transform(call arguments, "p:map:set", "p:flatMap:set") 
  )
passNil(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    code = call arguments [](
        0) 
    
    currentMessage = code 
    ground = call ground 
    currentReceiver = call ground 
    while(currentMessage, 
      currentReceiver = currentMessage sendTo(currentReceiver, ground) 
      if(currentReceiver nil?, 
        return(nil)) 
      currentMessage = currentMessage next 
      if(currentMessage &&(currentMessage terminator?), 
        currentMessage = currentMessage next 
        currentReceiver = ground) 
      ) 
    currentReceiver 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
rap(...)

takes one or more message chains. Will call these on the receiver, then return the receiver

macro(
  call arguments each(code, 
    code evaluateOn(call ground, self)) 
  self 
  )
return(value nil)

returns from the enclosing method/macro. if an argument is supplied, this will be returned as the result of the method/macro breaking out of.

sap(...)

nil

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      2), 
    
    sapCode = call arguments [](
        0) 
    iterCode = call arguments [](
        1) 
    
    result = sapCode evaluateOn(call ground, self) 
    while(result, 
      iterCode evaluateOn(call ground, result) 
      result = sapCode evaluateOn(call ground, self)) 
    self, 
    argCount ==(
      3), 
    
    sapCode = call arguments [](
        0) 
    argName = call arguments [](
        1) 
    iterCode = call arguments [](
        2) 
    
    destructor = Mixins Enumerable Destructor from(argName) 
    block = LexicalBlock createFrom(destructor argNames +(list(iterCode)), call ground) 
    result = sapCode evaluateOn(call ground, self) 
    while(result, 
      block call(*(destructor unpack(result))) 
      result = sapCode evaluateOn(call ground, self)) 
    self 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
tap(...)

takes one or two arguments that represent code. Will yield the receiver and then return the receiver after executing the given code

macro(
  argCount = call arguments length 
  cond(
    argCount ==(
      1), 
    
    code = call arguments [](
        0) 
    
    code evaluateOn(call ground, self) 
    self, 
    argCount ==(
      2), 
    
    argName = call arguments [](
        0) 
    code = call arguments [](
        1) 
    
    LexicalBlock createFrom(list(argName, code), call ground) call(self) 
    self 
    , 
    error!(Condition Error Invocation NoMatch, message: call message, context: call currentContext)) 
  )
tapping(...)

takes one or more message chains. Will call these on the receiver, then return the receiver

macro(
  call arguments each(code, 
    code evaluateOn(call ground, self)) 
  self 
  )
unless(condition, [then] nil, [else] nil)

evaluates the first arguments, and then evaluates the second argument if the result was false, otherwise the last argument. returns the result of the call, or the result if it's true.

until([condition] nil, +[body])

until the first argument evaluates to something true, loops and evaluates the next argument

while([condition] nil, +[body])

while the first argument evaluates to something true, loops and evaluates the next argument

with(...)

takes any number of keyword arguments, followed by an optional code argument. will first create a new mimic of the receiver, then evaluate all the keyword arguments in order and set cells corresponding to the names of these keyword arguments to the evaluated arguments. if a code argument is supplied, it will be evaluated in the context of the newly created object, using something similar to 'do'. returns the created object.

macro(
  newObject = mimic 
  call arguments each(arg, 
    if(arg keyword?, 
      Reflector other:cell(newObject, arg name asText [](0 ..(0 -(2)))) = arg next evaluateOn(call ground), 
      arg evaluateOn(call ground, newObject))) 
  newObject)