First class environments: Difference between revisions

Added FreeBASIC
(Added Perl Implementation)
(Added FreeBASIC)
 
(44 intermediate revisions by 17 users not shown)
Line 4:
Often this term is used in the context of "first class functions". In an analogous way, a programming language may support "first class environments".
 
The environment is minimally, the set of variables accessableaccessible to a statement being executed. Change the environments and the same statement could produce different results when executed.
 
Often an environment is captured in a [[wp:Closure_(computer_science)|closure]], which encapsulates a function together with an environment. That environment, however, is '''not''' first-class, as it cannot be created, passed etc. independently from the function's code.
Line 10:
Therefore, a first class environment is a set of variable bindings which can be constructed at run-time, passed as a parameter, returned from a subroutine, or assigned into a variable. It is like a closure without code. A statement must be able to be executed within a stored first class environment and act according to the environment variable values stored within.
 
The task: Build a dozen environments, and a single piece of code to be run repeatedly in each of these envionments.
 
;Task:
Each environment contains the bindings for two variables: A value in the [[Hailstone sequence]], and a count which is incremented until the value drops to 1. The initial hailstone values are 1 through 12, and the count in each environment is zero.
Build a dozen environments, and a single piece of code to be run repeatedly in each of these environments.
 
Each environment contains the bindings for two variables:
:*   a value in the [[Hailstone sequence]], and
:*   a count which is incremented until the value drops to 1.
 
 
The initial hailstone values are 1 through 12, and the count in each environment is zero.
 
When the code runs, it calculates the next hailstone step in the current environment (unless the value is already 1) and counts the steps. Then it prints the current value in a tabular form.
 
When all hailstone values dropped to 1, processing stops, and the total number of hailstone steps for each environment is printed.
<br><br>
 
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
Here the 'environment' consists of all the dynamic variables; the static integer variables (A%-Z%) are not affected.
<langsyntaxhighlight lang="bbcbasic"> DIM @environ$(12)
@% = 4 : REM Column width
Line 65 ⟶ 74:
IF LEN(e$) < 216 e$ = STRING$(216, CHR$0)
SYS "RtlMoveMemory", ^@%+108, !^e$, 216
ENDPROC</langsyntaxhighlight>
'''Output:'''
<pre>
Line 93 ⟶ 102:
 
=={{header|Bracmat}}==
<langsyntaxhighlight lang="bracmat">( (environment=(cnt=0) (seq=))
& :?environments
& 13:?seq
Line 126 ⟶ 135:
)
& out$(After !environments)
)</langsyntaxhighlight>
Output:
<pre> Before
Line 176 ⟶ 185:
=={{header|C}}==
Well, this fits the semantics, not sure about the spirit…
<langsyntaxhighlight Clang="c">#include <stdio.h>
 
#define JOBS 12
Line 211 ⟶ 220:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>
Line 236 ⟶ 245:
COUNTS:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
 
=={{header|Clojure}}==
<syntaxhighlight lang="clojure">
(def hailstone-src
"(defn hailstone-step [env]
(let [{:keys[n cnt]} env]
(cond
(= n 1) {:n 1 :cnt cnt}
(even? n) {:n (/ n 2) :cnt (inc cnt)}
:else {:n (inc (* n 3)) :cnt (inc cnt)})))")
 
(defn create-hailstone-table [f-src]
(let [done? (fn [e] (= (:n e) 1))
print-step (fn [envs] (println (map #(format "%4d" (:n %)) envs)))
print-counts (fn [envs] (println "Counts:\n"
(map #(format "%4d" (:cnt %)) envs)))]
(loop [f (eval (read-string f-src))
envs (for [n (range 12)]
{:n (inc n) :cnt 0})]
(if (every? done? envs)
(print-counts envs)
(do
(print-step envs)
(recur f (map f envs)))))))
</syntaxhighlight>
 
{{out}}
<pre>
( 1 2 3 4 5 6 7 8 9 10 11 12)
( 1 1 10 2 16 3 22 4 28 5 34 6)
( 1 1 5 1 8 10 11 2 14 16 17 3)
( 1 1 16 1 4 5 34 1 7 8 52 10)
( 1 1 8 1 2 16 17 1 22 4 26 5)
( 1 1 4 1 1 8 52 1 11 2 13 16)
( 1 1 2 1 1 4 26 1 34 1 40 8)
( 1 1 1 1 1 2 13 1 17 1 20 4)
( 1 1 1 1 1 1 40 1 52 1 10 2)
( 1 1 1 1 1 1 20 1 26 1 5 1)
( 1 1 1 1 1 1 10 1 13 1 16 1)
( 1 1 1 1 1 1 5 1 40 1 8 1)
( 1 1 1 1 1 1 16 1 20 1 4 1)
( 1 1 1 1 1 1 8 1 10 1 2 1)
( 1 1 1 1 1 1 4 1 5 1 1 1)
( 1 1 1 1 1 1 2 1 16 1 1 1)
( 1 1 1 1 1 1 1 1 8 1 1 1)
( 1 1 1 1 1 1 1 1 4 1 1 1)
( 1 1 1 1 1 1 1 1 2 1 1 1)
Counts:
( 0 1 7 2 5 8 16 3 19 6 14 9)
</pre>
 
Line 241 ⟶ 301:
D doesn't have first class environments, this is an approximation.
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.algorithm, std.range, std.array;
 
struct Prop {
Line 268 ⟶ 328:
 
writefln("Counts:\n%(% 4d%)", envs.map!(env => env.cnt));
}</langsyntaxhighlight>
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
Line 291 ⟶ 351:
Counts:
0 1 7 2 5 8 16 3 19 6 14 9</pre>
 
=={{header|EchoLisp}}==
'''(environment-new ((name value) ..) ''' is used to create a new envrionment. '''(eval form env)''' is used to evaluate a form in a specified environment.
<syntaxhighlight lang="scheme">
(define (bump-value)
(when (> value 1)
(set! count (1+ count))
(set! value (if (even? value) (/ value 2) (1+ (* 3 value))))))
(define (env-show name envs )
(write name)
(for ((env envs)) (write (format "%4a" (eval name env))))
(writeln))
 
(define (task (envnum 12))
(define envs (for/list ((i envnum)) (environment-new `((value ,(1+ i)) (count 0)))))
(env-show 'value envs)
(while
(any (curry (lambda ( n env) (!= 1 (eval n env))) 'value) envs)
(for/list ((env envs)) (eval '(bump-value) env))
(env-show 'value envs))
(env-show 'count envs))
</syntaxhighlight>
{{out}}
<pre>
(task)
value 1 2 3 4 5 6 7 8 9 10 11 12
value 1 1 10 2 16 3 22 4 28 5 34 6
value 1 1 5 1 8 10 11 2 14 16 17 3
value 1 1 16 1 4 5 34 1 7 8 52 10
value 1 1 8 1 2 16 17 1 22 4 26 5
value 1 1 4 1 1 8 52 1 11 2 13 16
value 1 1 2 1 1 4 26 1 34 1 40 8
value 1 1 1 1 1 2 13 1 17 1 20 4
value 1 1 1 1 1 1 40 1 52 1 10 2
value 1 1 1 1 1 1 20 1 26 1 5 1
value 1 1 1 1 1 1 10 1 13 1 16 1
value 1 1 1 1 1 1 5 1 40 1 8 1
value 1 1 1 1 1 1 16 1 20 1 4 1
value 1 1 1 1 1 1 8 1 10 1 2 1
value 1 1 1 1 1 1 4 1 5 1 1 1
value 1 1 1 1 1 1 2 1 16 1 1 1
value 1 1 1 1 1 1 1 1 8 1 1 1
value 1 1 1 1 1 1 1 1 4 1 1 1
value 1 1 1 1 1 1 1 1 2 1 1 1
value 1 1 1 1 1 1 1 1 1 1 1 1
count 0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Erlang}}==
Line 301 ⟶ 409:
</pre>
There is a lot of code below to manage the tabular printout. Otherwise the task is simple.
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( first_class_environments ).
 
Line 361 ⟶ 469:
end,
print_loop().
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 381 ⟶ 489:
[{12,9}, {11,14}, {10,6}, {9,19}, {8,3}, {7,16}, {6,8}, {5,5}, {4,2}, {3,7}, {2,1}, {1,0}]
</pre>
 
=={{header|Factor}}==
Factor is a stack language without the need for variable bindings. Values are variables through and through. This simplifies matters somewhat. It means we can use data stacks (sequences) for our first class environments. The <code>with-datastack</code> combinator takes a data stack (sequence) and quotation as input, and inside the quotation, it is as though one is operating on a new data stack populated with values from the sequence. The resultant data stack is then once again stored as a sequence for safe keeping.
<syntaxhighlight lang="factor">USING: assocs continuations formatting io kernel math
math.ranges sequences ;
 
: (next-hailstone) ( count value -- count' value' )
[ 1 + ] [ dup even? [ 2/ ] [ 3 * 1 + ] if ] bi* ;
 
: next-hailstone ( count value -- count' value' )
dup 1 = [ (next-hailstone) ] unless ;
 
: make-environments ( -- seq ) 12 [ 0 ] replicate 12 [1,b] zip ;
 
: step ( seq -- new-seq )
[ [ dup "%4d " printf next-hailstone ] with-datastack ] map
nl ;
 
: done? ( seq -- ? ) [ second 1 = ] all? ;
 
make-environments
[ dup done? ] [ step ] until nl
"Counts:" print
[ [ drop "%4d " printf ] with-datastack drop ] each nl</syntaxhighlight>
{{out}}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
Counts:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|FreeBASIC}}==
{{trans|Wren}}
<syntaxhighlight lang="vbnet">Type E
As Integer _valor, _contar
Public:
Declare Sub Constructor_(value As Integer, count As Integer)
Declare Function Valor() As Integer
Declare Function Contar() As Integer
Declare Sub Hailstone()
End Type
 
Sub E.Constructor_(value As Integer, count As Integer)
This._valor = value
This._contar = count
End Sub
 
Function E.Valor() As Integer
Return This._valor
End Function
 
Function E.Contar() As Integer
Return This._contar
End Function
 
Sub E.Hailstone()
Print Using "####"; This._valor;
If (This._valor = 1) Then Exit Sub
This._contar = This._contar + 1
This._valor = Iif(This._valor Mod 2 = 0, This._valor \ 2, 3 * This._valor + 1)
End Sub
 
 
Dim As Integer jobs = 12
Dim As E envs(jobs)
 
For i As Integer = 0 To jobs - 1
envs(i).Constructor_(i + 1, 0)
Next i
 
Print "Sequences:"
Dim As Integer done = 0
While done = 0
For i As Integer = 0 To jobs - 1
envs(i).Hailstone()
Next i
Print
done = 1
For i As Integer = 0 To jobs - 1
If envs(i).Valor() <> 1 Then
done = 0
Exit For
End If
Next i
Wend
 
Print "Counts:"
For i As Integer = 0 To jobs - 1
Print Using "####"; envs(i).Contar();
Next i
Print
 
Sleep</syntaxhighlight>
{{out}}
<pre>Same as Wren entry.</pre>
 
=={{header|Go}}==
{{trans|C}}
<syntaxhighlight lang="go">package main
 
import "fmt"
 
const jobs = 12
 
type environment struct{ seq, cnt int }
 
var (
env [jobs]environment
seq, cnt *int
)
 
func hail() {
fmt.Printf("% 4d", *seq)
if *seq == 1 {
return
}
(*cnt)++
if *seq&1 != 0 {
*seq = 3*(*seq) + 1
} else {
*seq /= 2
}
}
 
func switchTo(id int) {
seq = &env[id].seq
cnt = &env[id].cnt
}
 
func main() {
for i := 0; i < jobs; i++ {
switchTo(i)
env[i].seq = i + 1
}
 
again:
for i := 0; i < jobs; i++ {
switchTo(i)
hail()
}
fmt.Println()
 
for j := 0; j < jobs; j++ {
switchTo(j)
if *seq != 1 {
goto again
}
}
fmt.Println()
 
fmt.Println("COUNTS:")
for i := 0; i < jobs; i++ {
switchTo(i)
fmt.Printf("% 4d", *cnt)
}
fmt.Println()
}</syntaxhighlight>
 
{{out}}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
COUNTS:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Haskell}}==
 
First let's implement the algorithm of calculating Hailstone series:
<syntaxhighlight lang="haskell">hailstone n
| n == 1 = 1
| even n = n `div` 2
| odd n = 3*n + 1</syntaxhighlight>
 
and a data structure representing the environment
 
<syntaxhighlight lang="haskell">data Environment = Environment { count :: Int, value :: Int }
deriving Eq</syntaxhighlight>
 
In Haskell operations with first class environments could be implemented using several approaches:
 
1. Using any data structure <code>S</code> which is passed by a chain of functions, having type <code>S -> S</code>.
 
2. Using the <code>Reader</code> monad, which emulates access to imutable environment.
 
3. Using the <code>State</code> monad, which emulates access to an environment, that coud be changed.
 
For given task approaches 1 and 3 are suitable.
 
Let's define a collection of environments:
 
<syntaxhighlight lang="haskell">environments = [ Environment 0 n | n <- [1..12] ]</syntaxhighlight>
 
and a <code>process</code>, which changes an environment according to a task.
 
Approach 1.
 
<syntaxhighlight lang="haskell">process (Environment c 1) = Environment c 1
process (Environment c n) = Environment (c+1) (hailstone n)</syntaxhighlight>
 
Approach 3. (needs <code>import Control.Monad.State</code>)
 
<syntaxhighlight lang="haskell">process = execState $ do
n <- gets value
c <- gets count
when (n > 1) $ modify $ \env -> env { count = c + 1 }
modify $ \env -> env { value = hailstone n }</syntaxhighlight>
 
Repetitive batch processing of a collection we implement as following:
 
<syntaxhighlight lang="haskell">fixedPoint f x
| fx == x = [x]
| otherwise = x : fixedPoint f fx
where fx = f x
 
prettyPrint field = putStrLn . foldMap (format.field)
where format n = (if n < 10 then " " else "") ++ show n ++ " "
 
main = do
let result = fixedPoint (map process) environments
mapM_ (prettyPrint value) result
putStrLn (replicate 36 '-')
prettyPrint count (last result)</syntaxhighlight>
 
{{Out}}
<pre>1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
-----------------------------------
0 1 7 2 5 8 16 3 19 6 14 9 </pre>
 
Or in "transposed" way
 
<syntaxhighlight lang="haskell">main = do
let result = map (fixedPoint process) environments
mapM_ (prettyPrint value) result
putStrLn (replicate 36 '-')
putStrLn "Counts: "
prettyPrint (count . last) result</syntaxhighlight>
 
{{Out}}
<pre> 1
2 1
3 10 5 16 8 4 2 1
4 2 1
5 16 8 4 2 1
6 3 10 5 16 8 4 2 1
7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
8 4 2 1
9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
10 5 16 8 4 2 1
11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
12 6 3 10 5 16 8 4 2 1
------------------------------------
Counts:
0 1 7 2 5 8 16 3 19 6 14 9 </pre>
 
=={{header|Icon}} and {{header|Unicon}}==
The simplest way to create an environment with variables isolated from code in Icon/Unicon is to create instances of records or class objects.
<langsyntaxhighlight Iconlang="icon">link printf
 
procedure main()
Line 407 ⟶ 826:
else env.sequence := 3 * env.sequence + 1
}
end</langsyntaxhighlight>
{{libheader|Icon Programming Library}}
[http://www.cs.arizona.edu/icon/library/src/procs/printf.icn printf.icn provides formatting]
Line 439 ⟶ 858:
 
Here is my current interpretation of the task requirements:
<langsyntaxhighlight lang="j">coclass 'hailstone'
 
step=:3 :0
Line 473 ⟶ 892:
old=: state
end.
)</langsyntaxhighlight>
{{out|Example use}}
<langsyntaxhighlight lang="j"> environments=: conew&'hailstone'"0 (1+i.12)
run_hailstone_ environments
1 1 10 2 16 3 22 4 28 5 34 6
Line 496 ⟶ 915:
1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
0 1 7 2 5 8 16 3 19 6 14 9</langsyntaxhighlight>
In essence: run is a static method of the class <code>hailstone</code> which, given a list of objects of the class runs all of them until their hailstone sequence number stops changing. It also displays the hailstone sequence number from each of the objects at each step. Its result is the step count from each object.
 
=={{header|Java}}==
<syntaxhighlight lang="java">
 
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
 
public final class FirstClassEnvironments {
 
public static void main(String[] aArgs) {
code();
}
private static void code() {
do {
for ( int job = 0; job < JOBS; job++ ) {
switchTo(job);
hailstone();
}
System.out.println();
} while ( ! allDone() );
 
System.out.println(System.lineSeparator() + "Counts:");
for ( int job = 0; job < JOBS; job++ ) {
switchTo(job);
System.out.print(String.format("%4d", count));
}
System.out.println();
}
private static boolean allDone() {
for ( int job = 0; job < JOBS; job++ ) {
switchTo(job);
if ( sequence > 1 ) {
return false;
}
}
return true;
}
private static void hailstone() {
System.out.print(String.format("%4d", sequence));
if ( sequence == 1 ) {
return;
}
count += 1;
sequence = ( sequence % 2 == 1 ) ? 3 * sequence + 1 : sequence / 2;
}
private static void switchTo(int aID) {
if ( aID != currentId ) {
environments.get(currentId).seq = sequence;
environments.get(currentId).count = count;
currentId = aID;
}
sequence = environments.get(aID).seq;
count = environments.get(aID).count;
}
private static class Environment {
public Environment(int aSeq, int aCount) {
seq = aSeq; count = aCount;
}
private int seq, count;
}
private static int sequence, count, currentId;
private static List<Environment> environments =
IntStream.rangeClosed(1, 12).mapToObj( i -> new Environment(i, 0 ) ).collect(Collectors.toList());
private static final int JOBS = 12;
 
}
</syntaxhighlight>
{{ out }}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
Counts:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|jq}}==
 
{{works with|jq|1.5}}
 
In the context of jq, a JSON object is an environment in the sense of this article,
because an object, E, serves as an execution environment for a program of the form E | P
where P is a jq program.
 
For the task at hand, the environment can be taken to be an object of the form:
 
{ "value": <HAILSTONE>, "count": <COUNT> }
 
The required jq "code" is simply:
 
if .value > 1 then (.value |= hail) | .count += 1 else . end
 
where the filter "hail", when given an integer, computes the next hailstone value.
 
Let us therefore define a function named "code" accordingly:
<syntaxhighlight lang="jq">def code:
# Given an integer as input, compute the corresponding hailstone value:
def hail: if . % 2 == 0 then ./2|floor else 3*. + 1 end;
if .value > 1 then (.value |= hail) | .count += 1 else . end;
</syntaxhighlight>
 
To generate the n-th environment, it is useful to define a function:
 
def environment: . as $n | { value: $n, count:0 };
 
 
Now the program for creating the 12 environments and applying "code" to them until quiesence can be written as follows:
 
def generate:
[range(1;13) | environment] # create 12 environments
| recurse( if (any(.[] | .value; . != 1)) then map(code) else empty end);
 
 
Finally, to present the results in tabular form, the following helper function will be useful:
 
# Apply a filter to a stream,
# and ALSO emit the last item in the stream filtered through "final"
def filter_and_last(s; filter; final):
[s] as $array
| ($array[] | filter), ($array[-1] | final);
 
 
Putting it all together:
<syntaxhighlight lang="jq">filter_and_last( generate;
map(.value) | @tsv;
"", "Counts:", (map(.count) | @tsv ))</syntaxhighlight>
 
 
{{out}}
 
The following invocation produces the result shown below, assuming the above code is in a file named "program.jq":
 
$ jq -nr -f program.jq
 
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
 
Counts:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Julia}}==
{{trans|C}}
<syntaxhighlight lang="julia">const jobs = 12
 
mutable struct Environment
seq::Int
cnt::Int
Environment() = new(0, 0)
end
 
const env = [Environment() for i in 1:jobs]
const currentjob = [1]
 
seq() = env[currentjob[1]].seq
cnt() = env[currentjob[1]].cnt
seq(n) = (env[currentjob[1]].seq = n)
cnt(n) = (env[currentjob[1]].cnt = n)
 
function hail()
print(lpad(seq(), 4))
if seq() == 1
return
end
cnt(cnt() + 1)
seq(isodd(seq()) ? 3 * seq() + 1 : div(seq(), 2))
end
 
function runtest()
for i in 1:jobs
currentjob[1] = i
env[i].seq = i
end
computing = true
while computing
for i in 1:jobs
currentjob[1] = i
hail()
end
println()
for j in 1:jobs
currentjob[1] = j
if seq() != 1
break
elseif j == jobs
computing = false
end
end
end
println("\nCOUNTS:")
for i in 1:jobs
currentjob[1] = i
print(lpad(cnt(), 4))
end
println()
end
 
runtest()
</syntaxhighlight>{{output}}<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
COUNTS:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Kotlin}}==
This is based on the C entry except that, instead of using object references (Kotlin/JVM doesn't support explicit pointers) to switch between environments, it saves and restores the actual values of the two variables on each job switch. I see no reason why objects shouldn't be used to represent the environments as long as they have no member functions.
<syntaxhighlight lang="scala">// version 1.1.3
 
class Environment(var seq: Int, var count: Int)
 
const val JOBS = 12
val envs = List(JOBS) { Environment(it + 1, 0) }
var seq = 0 // 'seq' for current environment
var count = 0 // 'count' for current environment
var currId = 0 // index of current environment
 
fun switchTo(id: Int) {
if (id != currId) {
envs[currId].seq = seq
envs[currId].count = count
currId = id
}
seq = envs[id].seq
count = envs[id].count
}
 
fun hailstone() {
print("%4d".format(seq))
if (seq == 1) return
count++
seq = if (seq % 2 == 1) 3 * seq + 1 else seq / 2
}
 
val allDone get(): Boolean {
for (a in 0 until JOBS) {
switchTo(a)
if (seq != 1) return false
}
return true
}
 
fun code() {
do {
for (a in 0 until JOBS) {
switchTo(a)
hailstone()
}
println()
}
while (!allDone)
 
println("\nCOUNTS:")
for (a in 0 until JOBS) {
switchTo(a)
print("%4d".format(count))
}
println()
}
fun main(args: Array<String>) {
code()
}</syntaxhighlight>
 
{{out}}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
COUNTS:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Lua}}==
Line 506 ⟶ 1,282:
* Lua 5.2: an upvalue called <code>_ENV</code>
 
<langsyntaxhighlight lang="lua">
local envs = { }
for i = 1, 12 do
Line 540 ⟶ 1,316:
io.write(("% 4d"):format(env.count))
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 566 ⟶ 1,342:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Nim}}==
{{trans|C}}
<syntaxhighlight lang="nim">import strformat
 
const Jobs = 12
 
type Environment = object
sequence: int
count: int
 
var
env: array[Jobs, Environment]
sequence, count: ptr int
 
#---------------------------------------------------------------------------------------------------
 
proc hail() =
stdout.write fmt"{sequence[]: 4d}"
if sequence[] == 1: return
inc count[]
sequence[] = if (sequence[] and 1) != 0: 3 * sequence[] + 1
else: sequence[] div 2
 
#---------------------------------------------------------------------------------------------------
 
proc switchTo(id: int) =
sequence = addr(env[id].sequence)
count = addr(env[id].count)
 
#---------------------------------------------------------------------------------------------------
 
template forAllJobs(statements: untyped): untyped =
for i in 0..<Jobs:
switchTo(i)
statements
 
#———————————————————————————————————————————————————————————————————————————————————————————————————
 
for i in 0..<Jobs:
switchTo(i)
env[i].sequence = i + 1
 
var terminated = false
while not terminated:
 
forAllJobs:
hail()
echo ""
 
terminated = true
forAllJobs:
if sequence[] != 1:
terminated = false
break
 
echo ""
echo "Counts:"
forAllJobs:
stdout.write fmt"{count[]: 4d}"
echo ""</syntaxhighlight>
 
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
 
Counts:
0 1 7 2 5 8 16 3 19 6 14 9</pre>
 
=={{header|Order}}==
Order supports environments as a first-class type, but since all values are immutable, updating a value means using one environment to update the next in a chain (nothing unusual for languages with immutable data structures):
<langsyntaxhighlight lang="c">#include <order/interpreter.h>
#define ORDER_PP_DEF_8hail ORDER_PP_FN( \
Line 612 ⟶ 1,473:
8seq_iota(1, 13))),
8h_loop(8S))
)</langsyntaxhighlight>
{{out}}
<syntaxhighlight lang="text">(1,2,3,4,5,6,7,8,9,10,11,12) (1,1,10,2,16,3,22,4,28,5,34,6) (1,1,5,1,8,10,11,2,14,16,17,3) (1,1,16,1,4,5,34,1,7,8,52,10) (1,1,8,1,2,16,17,1,22,4,26,5) (1,1,4,1,1,8,52,1,11,2,13,16) (1,1,2,1,1,4,26,1,34,1,40,8) (1,1,1,1,1,2,13,1,17,1,20,4) (1,1,1,1,1,1,40,1,52,1,10,2) (1,1,1,1,1,1,20,1,26,1,5,1) (1,1,1,1,1,1,10,1,13,1,16,1) (1,1,1,1,1,1,5,1,40,1,8,1) (1,1,1,1,1,1,16,1,20,1,4,1) (1,1,1,1,1,1,8,1,10,1,2,1) (1,1,1,1,1,1,4,1,5,1,1,1) (1,1,1,1,1,1,2,1,16,1,1,1) (1,1,1,1,1,1,1,1,8,1,1,1) (1,1,1,1,1,1,1,1,4,1,1,1) (1,1,1,1,1,1,1,1,2,1,1,1) Counts:(0,1,7,2,5,8,16,3,19,6,14,9)</langsyntaxhighlight>
The C preprocessor cannot output newlines, so the output is all on one line, but easily parsable.
 
=={{header|PicoLisp}}==
Runtime environments can be controlled with the '[http://software-lab.de/doc/refJ.html#job job]' function:
<lang PicoLisp>(let Envs
(mapcar
'((N) (list (cons 'N N) (cons 'Cnt 0))) # Build environments
(range 1 12) )
(while (find '((E) (job E (> N 1))) Envs) # Until all values are 1:
(for E Envs
(job E # Use environment 'E'
(prin (align 4 N))
(unless (= 1 N)
(inc 'Cnt) # Increment step count
(setq N
(if (bit? 1 N) # Calculate next hailstone value
(inc (* N 3))
(/ N 2) ) ) ) ) )
(prinl) )
(prinl (need 48 '=))
(for E Envs # For each environment 'E'
(job E
(prin (align 4 Cnt)) ) ) # print the step count
(prinl) )</lang>
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
================================================
0 1 7 2 5 8 16 3 19 6 14 9</pre>
 
=={{header|Perl}}==
Line 673 ⟶ 1,489:
Next, repeatedly perform the task, until the required conditions are met, and print the counts.
 
<langsyntaxhighlight lang="perl">
use strict;
use warnings;
Line 714 ⟶ 1,530:
printf "%4s", ${$_->varglob('count')} for @enviornments;
print "\n";
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 740 ⟶ 1,556:
</pre>
 
=={{header|Perl 6Phix}}==
Emulation using edx as an "enviroment index" into static sequences. (You could of course nest the three sequences inside a single "environments" sequence, if you prefer.)<br>
Fairly straightforward. Set up an array of hashes containing the current values and iteration counts then pass each hash in turn with a code reference to a routine to calculate the next iteration.
See also [[Nested_function#Phix]]
 
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang perl6>my $calculator = sub ($n is rw) {
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
return ($n == 1) ?? 1 !! $n %% 2 ?? $n div 2 !! $n * 3 + 1
<span style="color: #008080;">function</span> <span style="color: #000000;">hail</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
};
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
 
<span style="color: #000000;">n</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">2</span>
sub next (%this is rw, &get_next) {
<span style="color: #008080;">else</span>
return %this if %this.<value> == 1;
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
%this.<value>.=&get_next;
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
%this.<count>++;
<span style="color: #008080;">return</span> <span style="color: #000000;">n</span>
return %this;
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
};
 
<span style="color: #004080;">sequence</span> <span style="color: #000000;">hails</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">tagset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">12</span><span style="color: #0000FF;">),</span>
my @hailstones = map { $_ = %(value => $_, count => 0) }, 1 .. 12;
<span style="color: #000000;">counts</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">),</span>
 
<span style="color: #000000;">results</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">columnize</span><span style="color: #0000FF;">({</span><span style="color: #000000;">hails</span><span style="color: #0000FF;">})</span>
while not all( map { $_.<value> }, @hailstones ) == 1 {
say [~] map { $_.<value>.fmt("%4s") }, @hailstones;
<span style="color: #008080;">function</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
@hailstones[$_].=&next($calculator) for ^@hailstones;
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hails</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span>
}
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
 
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
say 'Counts';
<span style="color: #000000;">hails</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span>
 
<span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
say [~] map { $_.<count>.fmt("%4s") }, @hailstones;</lang>
<span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">n</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">done</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">counts</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%4d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">results</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]}):</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"==="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">))})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">counts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
Emulation using edx as a dictionary_id (creating a separate dictionary for each environment):
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">hail</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">/=</span> <span style="color: #000000;">2</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">*</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">n</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"hail"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #000000;">0</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">hail</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"hail"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"count"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"count"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">)+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"results"</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"results"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">))&</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">edx</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">dicts</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">d</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"hail"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">i</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"count"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">setd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"results"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">i</span><span style="color: #0000FF;">},</span><span style="color: #000000;">d</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">dicts</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">d</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">done</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">step</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dicts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">while</span> <span style="color: #008080;">not</span> <span style="color: #000000;">done</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"results"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dicts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #000000;">done</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)?</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%4d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]}):</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">i</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"==="</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">))})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">12</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">count</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">getd</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"count"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">dicts</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%4d"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
{{out}}
(same for both)
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 10 2 16 3 22 4 28 5 34 6
5 1 8 10 11 2 14 16 17 3
16 4 5 34 1 7 8 52 10
8 2 16 17 22 4 26 5
4 1 8 52 11 2 13 16
2 4 26 34 1 40 8
1 2 13 17 20 4
1 40 52 10 2
20 26 5 1
10 13 16
5 40 8
16 20 4
8 10 2
4 5 1
2 16
1 8
4
2
1
=== === === === === === === === === === === ===
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|PicoLisp}}==
Runtime environments can be controlled with the '[http://software-lab.de/doc/refJ.html#job job]' function:
<syntaxhighlight lang="picolisp">(let Envs
(mapcar
'((N) (list (cons 'N N) (cons 'Cnt 0))) # Build environments
(range 1 12) )
(while (find '((E) (job E (> N 1))) Envs) # Until all values are 1:
(for E Envs
(job E # Use environment 'E'
(prin (align 4 N))
(unless (= 1 N)
(inc 'Cnt) # Increment step count
(setq N
(if (bit? 1 N) # Calculate next hailstone value
(inc (* N 3))
(/ N 2) ) ) ) ) )
(prinl) )
(prinl (need 48 '=))
(for E Envs # For each environment 'E'
(job E
(prin (align 4 Cnt)) ) ) # print the step count
(prinl) )</syntaxhighlight>
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
Line 785 ⟶ 1,744:
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
================================================
Counts
0 1 7 2 5 8 16 3 19 6 14 9</pre>
</pre>
 
 
 
=={{header|Python}}==
In Python, name bindings are held in dicts, one for global scope and another for local scope. When [http://docs.python.org/release/3.1.3/library/functions.html#exec exec]'ing code, you are allowed to give your own dictionaries for these scopes. In this example, two names are held in dictionaries that are used as the local scope for the evaluation of source.
<langsyntaxhighlight lang="python">environments = [{'cnt':0, 'seq':i+1} for i in range(12)]
 
code = '''
Line 810 ⟶ 1,766:
for env in environments:
print('% 4d' % env['cnt'], end='')
print()</langsyntaxhighlight>
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
Line 837 ⟶ 1,793:
=={{header|R}}==
 
<langsyntaxhighlight Rlang="r">code <- quote(
if (n == 1) n else {
count <- count + 1;
Line 852 ⟶ 1,808:
 
cat("\nCounts:\n")
eprint(envs, "count")</langsyntaxhighlight>
 
{{out}}
Line 880 ⟶ 1,836:
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 909 ⟶ 1,865:
(displayln (make-string (* 4 12) #\=))
(show-nums (get-var-values 'count))
</syntaxhighlight>
</lang>
 
Output:
Line 937 ⟶ 1,893:
</pre>
 
=={{header|REXXRaku}}==
(formerly Perl 6)
<lang rexx>/*REXX program illustrates first-class environments (using hailstone #s)*/
parse arg #envs .; env_.=; if #envs=='' then #envs=12
 
Set up an array of hashes containing the current values and iteration counts then pass each hash in turn with a code reference to a routine to calculate the next iteration.
/*═════════════════════════════════════initialize (twelve) environments.*/
do init=1 for #envs; env_.init=init; end
 
<syntaxhighlight lang="raku" line>my $calculator = sub ($n is rw) {
/*═════════════════════════════════════process environments until done. */
$n do== forever1 ?? 1 until!! env_.0;$n %% 2 ?? $n div 2 !! $n * 3 + env_.0=1
}
do k=1 for #envs
env_.k=env_.k hailstone(k) /*where the rubber meets the road*/
end /*k*/
end /*forever*/
 
sub next (%this, &get_next) {
/*═════════════════════════════════════show results in tabular form. */
count=0; doreturn lines=-1%this if until%this.<value> _=='' 1; _=
%this.<value> .= &get_next;
do j=1 for #envs
%this.<count>++;
select
%this;
when count== 1 then _=_ right(words(env_.j)-1,3)
}
when lines==-1 then _=_ right(j,3)
when lines== 0 then _=_ right('',3,'─')
otherwise _=_ right(word(env_.j,lines),3)
end /*select*/
end /*j*/
 
my @hailstones = map { %(value => $_, count => 0) }, 1 .. 12;
if count==1 then count=2
 
_=strip(_,'T')
while not all( map { $_.<value> }, @hailstones ) == 1 {
if _=='' then count=count+1
say [~] map { $_.<value>.fmt: '%4s' }, @hailstones;
if count==1 then _=copies(' ═══',#envs)
@hailstones[$_] .= &next($calculator) for ^@hailstones;
if _\=='' then say substr(_,2)
}
end /*lines*/
 
exit /*stick a fork in it, we're done.*/
say "\nCounts\n" ~ [~] map { $_.<count>.fmt: '%4s' }, @hailstones;</syntaxhighlight>
 
/*─────────────────────────────────────HAILSTONE (Collatz) subroutine───*/
hailstone: procedure expose env_.; arg n; _=word(env_.n,words(env_.n))
if _==1 then return ''; env_.0=0; if _//2==0 then return _%2; return _*3+1</lang>
{{out}}
<pre> 1 2 3 4 5 6 7 8 9 10 11 12
<pre>
1 21 10 3 2 4 16 5 3 622 74 28 8 5 9 34 10 11 126
1 1 5 1 8 10 11 2 14 16 17 3
─── ─── ─── ─── ─── ─── ─── ─── ─── ─── ─── ───
1 21 16 3 1 4 5 34 6 1 7 8 952 10 11 12
1 1 10 8 2 1 16 2 3 16 22 17 4 1 28 22 5 4 34 26 6 5
1 1 54 1 81 10 8 11 52 2 1 14 11 16 172 13 3 16
1 1 162 1 1 4 4 5 3426 1 34 7 1 8 40 52 108
1 1 1 8 1 1 2 1613 17 1 17 221 20 4 26 54
1 1 4 1 1 1 81 5240 1 52 11 1 2 10 13 162
1 1 1 2 1 1 1 20 4 26 1 3426 1 40 5 8 1
1 1 1 1 1 1 210 13 1 13 171 16 20 41
1 1 1 1 1 1 40 5 1 5240 1 108 21
1 1 1 1 1 1 16 1 20 1 26 54 1
1 1 1 1 1 1 8 1 10 1 13 2 161
1 1 1 1 1 1 4 1 5 1 40 1 81
1 1 1 1 1 1 2 1 16 1 20 1 41
1 1 1 1 1 1 1 1 8 1 10 1 21
1 1 1 1 1 1 1 1 4 1 5 1 1
1 1 1 1 1 1 1 1 2 1 1 161
Counts
1 8
0 1 7 2 5 8 16 3 19 6 14 49</pre>
 
2
=={{header|REXX}}==
1
The formatting is sensitive to a terminating Collatz sequence and is shown as blanks &nbsp; (that is,
═══ ═══ ═══ ═══ ═══ ═══ ═══ ═══ ═══ ═══ ═══ ═══
<br>once a &nbsp; '''1''' &nbsp; (unity) &nbsp; is found, no more numbers are displayed in that column).
0 1 7 2 5 8 16 3 19 6 14 9
 
Column widths are automatically adjusted for their width &nbsp;(the maximum decimal digits displayed in a column).
 
The '''hailstone''' function (subroutine) could be coded in─line to further comply with the task's requirement that
<br>the solution have a &nbsp; ''single piece of code to be run repeatedly in each of these environments''.
<syntaxhighlight lang="rexx">/*REXX pgm illustrates N 1st─class environments (using numbers from a hailstone seq).*/
parse arg n . /*obtain optional argument from the CL.*/
if n=='' | n=="," then n= 12 /*Was N defined? No, then use default.*/
@.= /*initialize the array @. to nulls.*/
do i=1 for n; @.i= i /* " environments to an index. */
end /*i*/
w= length(n) /*width (so far) for columnar output.*/
 
do forever until @.0; @.0= 1 /* ◄─── process all the environments. */
do k=1 for n; x= hailstone(k) /*obtain next hailstone number in seq. */
w= max(w, length(x)) /*determine the maximum width needed. */
@.k= @.k x /* ◄─── where the rubber meets the road*/
end /*k*/
end /*forever*/
#= 0 /* [↓] display the tabular results. */
do lines=-1 until _=''; _= /*process a line for each environment. */
do j=1 for n /*process each of the environments. */
select /*determine how to process the line. */
when #== 1 then _= _ right(words(@.j) - 1, w) /*environment count.*/
when lines==-1 then _= _ right(j, w) /*the title (header)*/
when lines== 0 then _= _ right('', w, "─") /*the separator line*/
otherwise _= _ right(word(@.j, lines), w)
end /*select*/
end /*j*/
 
if #==1 then #= 2 /*separator line? */
if _='' then #= # + 1 /*Null? Bump the #.*/
if #==1 then _= copies(" "left('', w, "═"), N) /*the foot separator*/
if _\='' then say strip( substr(_, 2), "T") /*display the counts*/
end /*lines*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
hailstone: procedure expose @.; parse arg y; _= word(@.y, words(@.y) )
if _==1 then return ''; @.0= 0; if _//2 then return _*3 + 1; return _%2</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
 
(Shown at three─fourths size.)
<pre style="font-size:75%>
1 2 3 4 5 6 7 8 9 10 11 12
── ── ── ── ── ── ── ── ── ── ── ──
1 2 3 4 5 6 7 8 9 10 11 12
1 10 2 16 3 22 4 28 5 34 6
5 1 8 10 11 2 14 16 17 3
16 4 5 34 1 7 8 52 10
8 2 16 17 22 4 26 5
4 1 8 52 11 2 13 16
2 4 26 34 1 40 8
1 2 13 17 20 4
1 40 52 10 2
20 26 5 1
10 13 16
5 40 8
16 20 4
8 10 2
4 5 1
2 16
1 8
4
2
1
══ ══ ══ ══ ══ ══ ══ ══ ══ ══ ══ ══
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
{{out|output|text=&nbsp; when using the input of: &nbsp; &nbsp; <tt> 60 </tt>}}
 
(Shown at two─thirds size.)
<pre style="font-size:67%;height:195ex">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ──── ────
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
1 10 2 16 3 22 4 28 5 34 6 40 7 46 8 52 9 58 10 64 11 70 12 76 13 82 14 88 15 94 16 100 17 106 18 112 19 118 20 124 21 130 22 136 23 142 24 148 25 154 26 160 27 166 28 172 29 178 30
5 1 8 10 11 2 14 16 17 3 20 22 23 4 26 28 29 5 32 34 35 6 38 40 41 7 44 46 47 8 50 52 53 9 56 58 59 10 62 64 65 11 68 70 71 12 74 76 77 13 80 82 83 14 86 88 89 15
16 4 5 34 1 7 8 52 10 10 11 70 2 13 14 88 16 16 17 106 3 19 20 124 22 22 23 142 4 25 26 160 28 28 29 178 5 31 32 196 34 34 35 214 6 37 38 232 40 40 41 250 7 43 44 268 46
8 2 16 17 22 4 26 5 5 34 35 1 40 7 44 8 8 52 53 10 58 10 62 11 11 70 71 2 76 13 80 14 14 88 89 16 94 16 98 17 17 106 107 3 112 19 116 20 20 124 125 22 130 22 134 23
4 1 8 52 11 2 13 16 16 17 106 20 22 22 4 4 26 160 5 29 5 31 34 34 35 214 1 38 40 40 7 7 44 268 8 47 8 49 52 52 53 322 10 56 58 58 10 10 62 376 11 65 11 67 70
2 4 26 34 1 40 8 8 52 53 10 11 11 2 2 13 80 16 88 16 94 17 17 106 107 19 20 20 22 22 22 134 4 142 4 148 26 26 160 161 5 28 29 29 5 5 31 188 34 196 34 202 35
1 2 13 17 20 4 4 26 160 5 34 34 1 1 40 40 8 44 8 47 52 52 53 322 58 10 10 11 11 11 67 2 71 2 74 13 13 80 484 16 14 88 88 16 16 94 94 17 98 17 101 106
1 40 52 10 2 2 13 80 16 17 17 20 20 4 22 4 142 26 26 160 161 29 5 5 34 34 34 202 1 214 1 37 40 40 40 242 8 7 44 44 8 8 47 47 52 49 52 304 53
20 26 5 1 1 40 40 8 52 52 10 10 2 11 2 71 13 13 80 484 88 16 16 17 17 17 101 107 112 20 20 20 121 4 22 22 22 4 4 142 142 26 148 26 152 160
10 13 16 20 20 4 26 26 5 5 1 34 1 214 40 40 40 242 44 8 8 52 52 52 304 322 56 10 10 10 364 2 11 11 11 2 2 71 71 13 74 13 76 80
5 40 8 10 10 2 13 13 16 16 17 107 20 20 20 121 22 4 4 26 26 26 152 161 28 5 5 5 182 1 34 34 34 1 1 214 214 40 37 40 38 40
16 20 4 5 5 1 40 40 8 8 52 322 10 10 10 364 11 2 2 13 13 13 76 484 14 16 16 16 91 17 17 17 107 107 20 112 20 19 20
8 10 2 16 16 20 20 4 4 26 161 5 5 5 182 34 1 1 40 40 40 38 242 7 8 8 8 274 52 52 52 322 322 10 56 10 58 10
4 5 1 8 8 10 10 2 2 13 484 16 16 16 91 17 20 20 20 19 121 22 4 4 4 137 26 26 26 161 161 5 28 5 29 5
2 16 4 4 5 5 1 1 40 242 8 8 8 274 52 10 10 10 58 364 11 2 2 2 412 13 13 13 484 484 16 14 16 88 16
1 8 2 2 16 16 20 121 4 4 4 137 26 5 5 5 29 182 34 1 1 1 206 40 40 40 242 242 8 7 8 44 8
4 1 1 8 8 10 364 2 2 2 412 13 16 16 16 88 91 17 103 20 20 20 121 121 4 22 4 22 4
2 4 4 5 182 1 1 1 206 40 8 8 8 44 274 52 310 10 10 10 364 364 2 11 2 11 2
1 2 2 16 91 103 20 4 4 4 22 137 26 155 5 5 5 182 182 1 34 1 34 1
1 1 8 274 310 10 2 2 2 11 412 13 466 16 16 16 91 91 17 17
4 137 155 5 1 1 1 34 206 40 233 8 8 8 274 274 52 52
2 412 466 16 17 103 20 700 4 4 4 137 137 26 26
1 206 233 8 52 310 10 350 2 2 2 412 412 13 13
103 700 4 26 155 5 175 1 1 1 206 206 40 40
310 350 2 13 466 16 526 103 103 20 20
155 175 1 40 233 8 263 310 310 10 10
466 526 20 700 4 790 155 155 5 5
233 263 10 350 2 395 466 466 16 16
700 790 5 175 1 1186 233 233 8 8
350 395 16 526 593 700 700 4 4
175 1186 8 263 1780 350 350 2 2
526 593 4 790 890 175 175 1 1
263 1780 2 395 445 526 526
790 890 1 1186 1336 263 263
395 445 593 668 790 790
1186 1336 1780 334 395 395
593 668 890 167 1186 1186
1780 334 445 502 593 593
890 167 1336 251 1780 1780
445 502 668 754 890 890
1336 251 334 377 445 445
668 754 167 1132 1336 1336
334 377 502 566 668 668
167 1132 251 283 334 334
502 566 754 850 167 167
251 283 377 425 502 502
754 850 1132 1276 251 251
377 425 566 638 754 754
1132 1276 283 319 377 377
566 638 850 958 1132 1132
283 319 425 479 566 566
850 958 1276 1438 283 283
425 479 638 719 850 850
1276 1438 319 2158 425 425
638 719 958 1079 1276 1276
319 2158 479 3238 638 638
958 1079 1438 1619 319 319
479 3238 719 4858 958 958
1438 1619 2158 2429 479 479
719 4858 1079 7288 1438 1438
2158 2429 3238 3644 719 719
1079 7288 1619 1822 2158 2158
3238 3644 4858 911 1079 1079
1619 1822 2429 2734 3238 3238
4858 911 7288 1367 1619 1619
2429 2734 3644 4102 4858 4858
7288 1367 1822 2051 2429 2429
3644 4102 911 6154 7288 7288
1822 2051 2734 3077 3644 3644
911 6154 1367 9232 1822 1822
2734 3077 4102 4616 911 911
1367 9232 2051 2308 2734 2734
4102 4616 6154 1154 1367 1367
2051 2308 3077 577 4102 4102
6154 1154 9232 1732 2051 2051
3077 577 4616 866 6154 6154
9232 1732 2308 433 3077 3077
4616 866 1154 1300 9232 9232
2308 433 577 650 4616 4616
1154 1300 1732 325 2308 2308
577 650 866 976 1154 1154
1732 325 433 488 577 577
866 976 1300 244 1732 1732
433 488 650 122 866 866
1300 244 325 61 433 433
650 122 976 184 1300 1300
325 61 488 92 650 650
976 184 244 46 325 325
488 92 122 23 976 976
244 46 61 70 488 488
122 23 184 35 244 244
61 70 92 106 122 122
184 35 46 53 61 61
92 106 23 160 184 184
46 53 70 80 92 92
23 160 35 40 46 46
70 80 106 20 23 23
35 40 53 10 70 70
106 20 160 5 35 35
53 10 80 16 106 106
160 5 40 8 53 53
80 16 20 4 160 160
40 8 10 2 80 80
20 4 5 1 40 40
10 2 16 20 20
5 1 8 10 10
16 4 5 5
8 2 16 16
4 1 8 8
2 4 4
1 2 2
1 1
════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════ ════
0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5 26 13 13 21 21 21 34 8 109 8 29 16 16 16 104 11 24 24 24 11 11 112 112 19 32 19 32 19
</pre>
 
Line 1,004 ⟶ 2,138:
{{trans|PicoLisp}}
The ''object'' is an environment for instance variables. These variables use the <code>@</code> sigil. We create 12 objects, and put <code>@n</code> and <code>@cnt</code> inside these objects. We use <code>Object#instance_eval</code> to switch the current object and bring those instance variables into scope.
<langsyntaxhighlight lang="ruby"># Build environments
envs = (1..12).map do |n|
Object.new.instance_eval {@n = n; @cnt = 0; self}
Line 1,010 ⟶ 2,144:
 
# Until all values are 1:
whileuntil envs.findall? {|e| e.instance_eval {@n} >== 1}
envs.each do |e|
e.instance_eval do # Use environment _e_
printf "%4s", @n
unless 1 ==if @n > 1
@cnt += 1 # Increment step count
@n = if 1 & @n.odd? == 1 # Calculate next hailstone value
@n * 3 + 1
else
Line 1,032 ⟶ 2,166:
end
end
puts</langsyntaxhighlight>
Ruby also provides the ''binding'', an environment for local variables. The problem is that local variables have lexical scope. Ruby needs the lexical scope to parse Ruby code. So, the only way to use a binding is to evaluate a string of Ruby code. We use <code>Kernel#binding</code> to create the bindings, and <code>Kernel#eval</code> to evaluate strings in these bindings. The lines between <code><<-'eos'</code> and <code>eos</code> are multi-line string literals.
<langsyntaxhighlight lang="ruby"># Build environments
envs = (1..12).map do |n|
e = class Object
Line 1,041 ⟶ 2,175:
binding
end
eval(<<-'eos'EOS, e).call(n)
n, cnt = nil, 0
proc {|arg| n = arg}
eosEOS
next e
end
 
# Until all values are 1:
whileuntil envs.findall? {|e| eval('n >== 1', e)}
envs.each do |e|
eval(<<-'eos'EOS, e) # Use environment _e_
printf "%4s", n
unlessif 1n ==> n1
cnt += 1 # Increment step count
n = if 1 & n.odd? == 1 # Calculate next hailstone value
n * 3 + 1
else
Line 1,061 ⟶ 2,195:
end
end
eosEOS
end
puts
Line 1,067 ⟶ 2,201:
puts '=' * 48
envs.each do |e| # For each environment _e_
eval(<<-'eosprintf "%4s", cnt', e) # print the step count
printf "%4s", cnt # print the step count
eos
end
puts</langsyntaxhighlight>
{{out}}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
================================================
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Sidef}}==
{{trans|Raku}}
<syntaxhighlight lang="ruby">func calculator({.is_one} ) { 1 }
func calculator(n {.is_even}) { n / 2 }
func calculator(n ) { 3*n + 1 }
 
func succ(this {_{:value}.is_one}, _) {
return this
}
 
func succ(this, get_next) {
this{:value} = get_next(this{:value})
this{:count}++
return this
}
 
var enviornments = (1..12 -> map {|i| Hash(value => i, count => 0) });
 
while (!enviornments.map{ _{:value} }.all { .is_one }) {
say enviornments.map {|h| "%4s" % h{:value} }.join;
enviornments.range.each { |i|
enviornments[i] = succ(enviornments[i], calculator);
}
}
 
say 'Counts';
say enviornments.map{ |h| "%4s" % h{:count} }.join;</syntaxhighlight>
{{out}}
<pre>
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
Counts
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Tcl}}==
The simplest way to make a first-class environment in Tcl is to use a dictionary; the <code>dict with</code> command (and <code>dict update</code>; not shown here) will expand a dictionary and bind it to variables for the duration of its body script.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
for {set i 1} {$i <= 12} {incr i} {
Line 1,105 ⟶ 2,313:
}
}
puts ""</langsyntaxhighlight>
{{out}}
<pre>
Line 1,129 ⟶ 2,337:
1 1 1 1 1 1 1 1 1 1 1 1
Counts...
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|Wren}}==
{{libheader|Wren-fmt}}
In Wren classes satisfy the definition of first-class objects in that: "they can be constructed at run-time, passed as a parameter, returned from a subroutine, or assigned into a variable."
 
It also appears that they can represent first-class environments in that they can encapsulate a set of variables (the class's fields) and code (the class's methods) which acts on those variables.
 
So that's what we use here. However, to create a dynamic class you have to wrap it in a function which then returns a reference to the class object.
<syntaxhighlight lang="wren">import "./fmt" for Fmt
 
var environment = Fn.new {
class E {
construct new(value, count) {
_value = value
_count = count
}
 
value { _value }
count { _count }
 
hailstone() {
Fmt.write("$4d", _value)
if (_value == 1) return
_count = _count + 1
_value = (_value%2 == 0) ? _value/2 : 3*_value + 1
}
}
return E
}
 
// create and initialize the environments
var jobs = 12
var envs = List.filled(jobs, null)
for (i in 0...jobs) envs[i] = environment.call().new(i+1, 0)
System.print("Sequences:")
var done = false
while (!done) {
for (env in envs) env.hailstone()
System.print()
done = true
for (env in envs) {
if (env.value != 1) {
done = false
break
}
}
}
System.print("Counts:")
for (env in envs) Fmt.write("$4d", env.count)
System.print()</syntaxhighlight>
 
{{out}}
<pre>
Sequences:
1 2 3 4 5 6 7 8 9 10 11 12
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
Counts:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
=={{header|zkl}}==
In zkl, classes wrap state. All instances of a class share code but each instance binds code to itself. In this task, class creation, instead of returning a new class instance, it returns a bound function. Calling this function calculates the next hailstone in the environment the function is bound to. To get the counts from the class/environment, we ask the function for its container and then pull the count.
<syntaxhighlight lang="zkl">class Env{
var n,cnt=0;
fcn init(_n){n=_n; returnClass(self.f)}
fcn f{
if(n!=1){
cnt += 1;
if(n.isEven) n=n/2; else n=n*3+1;
}
n
}
}</syntaxhighlight>
<syntaxhighlight lang="zkl">var es=(1).pump(12,List,Env);
while(1){
ns:=es.run(True);
ns.pump(String,"%4d".fmt).println();
if (not ns.filter('!=(1))) break;
}
println("Counts:");
es.pump(String,fcn(e){"%4d".fmt(e.container.cnt)}).println();</syntaxhighlight>
{{out}}
<pre>
1 1 10 2 16 3 22 4 28 5 34 6
1 1 5 1 8 10 11 2 14 16 17 3
1 1 16 1 4 5 34 1 7 8 52 10
1 1 8 1 2 16 17 1 22 4 26 5
1 1 4 1 1 8 52 1 11 2 13 16
1 1 2 1 1 4 26 1 34 1 40 8
1 1 1 1 1 2 13 1 17 1 20 4
1 1 1 1 1 1 40 1 52 1 10 2
1 1 1 1 1 1 20 1 26 1 5 1
1 1 1 1 1 1 10 1 13 1 16 1
1 1 1 1 1 1 5 1 40 1 8 1
1 1 1 1 1 1 16 1 20 1 4 1
1 1 1 1 1 1 8 1 10 1 2 1
1 1 1 1 1 1 4 1 5 1 1 1
1 1 1 1 1 1 2 1 16 1 1 1
1 1 1 1 1 1 1 1 8 1 1 1
1 1 1 1 1 1 1 1 4 1 1 1
1 1 1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1
Counts:
0 1 7 2 5 8 16 3 19 6 14 9
</pre>
 
{{omit from|Ada|Task could be completed, but would never truly meet definition of first class}}
{{omit from|GoLily|RetractingNo solution.support for Spirit of task not met.eval}}
{{omit from|Maxima}}
2,122

edits