Blocks

Block  Object

Blocks are the bread and butter of Atomo. They represent chunks of unevaluated code - sort of like lists of expressions, but with a reference to the context in which they were evaluated.

They are first-class values and can be passed around, evaluated, torn apart, created programmatically, sent between processes, etc.

Example:

{ "hi" print; @ok }
{ a | a + 2 }
{}
Block: expressions  Block
  | expressions is-a?: List

Calls new:in: with its sender as the context.

Example:

> orig = { a = 1; a + 1 }
{ a = 1; a + 1 }
> (Block: orig contents) call
2
Block new: expressions in: context  Block
  | expressions is-a?: List

Returns a new Block with expressions as its contents and context as its context.

Example:

> Block new: ['(1 = 1), '(a + 1)] in: this
{ 1 = 1; a + 1 }
> (Block new: ['(* 7)] in: 6) call
42
b call  any
  | b is-a?: Block

Returns the result of evaluating each expression in b, in order, with a new toplevel object that delegates to the block's context. calling a block does not affect its context (unless it is a block returned by in-context).

Sending call to an empty block raises a @no-expressions error.

Example:

> a = 42
42
> { a = 1; a + 1 } call
2
> a
42
> {} call
ERROR: <error @no-expressions>
b call: (... args)  any
  | b is-a?: Block

Like call, but passes some extra arguments along to b. Any number of arguments may be passed to the block; it can use however many it wants.

Sending call: to an empty block raises a @no-expressions error.

Example:

> { a b | a + b } call: (1, 4)
5
> { a | a + 1 } call: 1
2
> { 1 + 1 } call: 42
2
> {} call: 42
ERROR: <error @no-expressions>

Note that the arguments also do not affect the outer scope:

Example:

> a = 42
42
> { a | a + 1 } call: 10
11
> a
42
v join: b  any
  | b is-a?: Block

Execute b with v delegating-to: b context as its toplevel object (i.e., the block's context is accessible). Returns the result of the block's execution.

Note that v's methods take priority over the block's context.

Example:

> True join: { not }
False
> 1 join: { + 2 }
3
> x = 42
42
> 1 join: { + x }
43

This can be useful for executing a block in the current scope:

Example:

> blk = { x = 1; x + a }
{ x = 1; x + a }
> Object clone do: { a = 42; res = join: blk }
<object (delegates to 1 object)>
  a := 42
  x := 1
  res := 43
v join: b with: (... args)  any
  | b is-a?: Block

Like join:, but with arguments passed to the block.

Note that v's methods take priority over both the arguments and the block's context.

Example:

> 1 join: { a | + a } with: 2
3
> 1 join: { a b | + a * b } with: (2, 3)
7
v do: b  v
  | b is-a?: Block

Like join:, but returns v. Handy for quick object creation.

Example:

> X = Object clone do: { a = 1; b = 2 }
<object (delegates to 1 object)>
  a := 1
  b := 2
v do: b with: (... args)  v
  | b is-a?: Block

Like do:, but with arguments passed to the block.

Example:

> X = Object clone do: { a | x = a; y := a + 1 } with: 1
<object (delegates to 1 object)>
  x := 1
  y := a + 1
> X y
2
b contents  List
  | b is-a?: Block

Returns a list of the expressions contained in b.

Example:

> { a = 1; a + 1 } contents
['(a = 1), '(a + 1)]
b context  Object
  | b is-a?: Block

Returns the context that the b was evaluated in.

Example:

> a = 1
1
> {} context a
1
b arguments  List
  | b is-a?: Block

Returns a list of the block's arguments, which are Patterns.

Example:

> { a (x . _) 0 | a + x } arguments
[<pattern a>, <pattern (x . _)>, <pattern 0>]
b in-context  is-a?: Block
  | b is-a?: Block

Returns an object that delegates to the original block, b, but has its own call and call: methods defined. These overrides evaluate the block in its original scope, as opposed to lexically, via join: and join:with:.

Example:

> a = 42
42
> { a = 1; a } call
1
> a
42
> { a = 1; a } in-context call
1
> a
1
start to: end by: diff do: b  @ok
  | start is-a?: Integer
  | end is-a?: Integer
  | diff is-a?: Integer
  | b is-a?: Block

Calls b with each integer in the range from start to end inclusive, by adding diff to the current number.

Example:

> 0 to: 5 by: 2 do: { n | ("Counting up... " .. n show) print }
Counting up... 0
Counting up... 2
Counting up... 4
@ok
> 5 to: 0 by: -1 do: { n | ("Counting down... " .. n show) print }
Counting down... 5
Counting down... 4
Counting down... 3
Counting down... 2
Counting down... 1
Counting down... 0
@ok
n times: b  @ok
  | n is-a?: Integer
  | b is-a?: Block

Alias for 1 up-to: n do: b in-context.

Example:

> 5 times: { "Odelay!" print }
Odelay!
Odelay!
Odelay!
Odelay!
Odelay!
@ok
start up-to: end do: b  @ok
  | start is-a?: Integer
  | end is-a?: Integer
  | b is-a?: Block

Alias for start to: end by: 1 do: b.

start down-to: end do: b  @ok
  | start is-a?: Integer
  | end is-a?: Integer
  | b is-a?: Block

Alias for start to: end by: -1 do: b.

b repeat  none
  | b is-a?: Block

Repeatedly sends call to b in-context. Never returns.

b repeat: n  List
  | b is-a?: Block
  | n is-a?: Integer

Returns a list containing the results of n calls of b in-context.

Example:

> with-input-from: "doc/main/lists.atomo" do: { { read-line } repeat: 3 }
ERROR: <error @(file-not-found: "doc/main/lists.atomo")>

Here we're reading 3 lines of text from the file "doc/main/lists.atomo" (the source for the documentation you're reading).