<commit_before>package nz.sodium;

import java.util.Optional;

/**
 * Represents a value of type A that changes over time. 
 */
public class Cell<A> {
	final Stream<A> str;
	A value;
	A valueUpdate;
	private Listener cleanup;
    Lazy<A> lazyInitValue;  // Used by LazyCell

	/**
	 * A cell with a constant value.
	 */
    public Cell(A value)
    {
    	this.str = new Stream<A>();
    	this.value = value;
    }

    Cell(final Stream<A> str, A initValue)
    {
    	this.str = str;
    	this.value = initValue;
    	Transaction.run(new Handler<Transaction>() {
    		public void run(Transaction trans1) {
	    		Cell.this.cleanup = str.listen(Node.NULL, trans1, new TransactionHandler<A>() {
	    			public void run(Transaction trans2, A a) {
			    		if (Cell.this.valueUpdate == null) {
			    			trans2.last(new Runnable() {
			    				public void run() {
				    				Cell.this.value = Cell.this.valueUpdate;
				    				Cell.this.lazyInitValue = null;
				    				Cell.this.valueUpdate = null;
				    			}
			    			});
			    		}
			    		Cell.this.valueUpdate = a;
			    	}
	    		}, false);
    		}
    	});
    }

    /**
     * @return The value including any updates that have happened in this transaction.
     */
    final A newValue()
    {
    	return valueUpdate == null ? sampleNoTrans() :  valueUpdate;
    }

    /**
     * Sample the cell's current value.
     * <p>
     * It may be used inside the functions passed to primitives that apply them to {@link Stream}s,
     * including {@link Stream#map(Lambda1)} in which case it is equivalent to snapshotting the cell,
     * {@link Stream#snapshot(Cell, Lambda2)}, {@link Stream#filter(Lambda1)} and
     * {@link Stream#merge(Stream, Lambda2)}.
     * It should generally be avoided in favour of {@link listen(Handler)} so you don't
     * miss any updates, but in many circumstances it makes sense.
     */
    public final A sample()
    {
        return Transaction.apply(new Lambda1<Transaction, A>() {
        	public A apply(Transaction trans) {
        		return sampleNoTrans();
        	}
        });
    }

    private static class LazySample<A> {
        LazySample(Cell<A> cell) {
            this.cell = cell;
        }
        Cell<A> cell;
        boolean hasValue;
        A value;
    }

    /**
     * A variant of {@link sample()} that works with {@link CellLoop}s when they haven't been looped yet.
     * It should be used in any code that's general enough that it could be passed a {@link CellLoop}.
     * @see Stream#holdLazy(Lazy) Stream.holdLazy()
     */
    public final Lazy<A> sampleLazy() {
        final Cell<A> me = this;
        return Transaction.apply(new Lambda1<Transaction, Lazy<A>>() {
        	public Lazy<A> apply(Transaction trans) {
        	    return me.sampleLazy(trans);
            }
        });
    }

    final Lazy<A> sampleLazy(Transaction trans) {
        final Cell<A> me = this;
        final LazySample<A> s = new LazySample<A>(me);
        trans.last(new Runnable() {
            public void run() {
                s.value = me.valueUpdate != null ? me.valueUpdate : me.sampleNoTrans();
                s.hasValue = true;
                s.cell = null;
            }
        });
        return new Lazy<A>(new Lambda0<A>() {
            public A apply() {
                if (s.hasValue)
                    return s.value;
                else
                    return s.cell.sample();
            }
        });
    }

    A sampleNoTrans()
    {
        return value;
    }

    final Stream<A> updates(Transaction trans)
    {
        return str;
    }

    final Stream<A> value(Transaction trans1)
    {
    	final StreamWithSend<Unit> sSpark = new StreamWithSend<Unit>();
        trans1.prioritized(sSpark.node, new Handler<Transaction>() {
            public void run(Transaction trans2) {
                sSpark.send(trans2, Unit.UNIT);
            }
        });
    	Stream<A> sInitial = sSpark.<A>snapshot(this);
        return updates(trans1).orElse(sInitial);
    }

    /**
     * Transform the cell's value according to the supplied function, so the returned Cell
     * always reflects the value of the function applied to the input Cell's value.
     * @param f Function to apply to convert the values. It must be <em>referentially transparent</em>.
     */
	public final <B> Cell<B> map(final Lambda1<A,B> f)
	{<commit_msg>Make it so Cell.value() acts a bit more sensibly in the case where there is more than one firing in a given transaction, even though this is semantically not allowed. I am experimenting.<commit_after>package nz.sodium;

import java.util.Optional;

/**
 * Represents a value of type A that changes over time. 
 */
public class Cell<A> {
	final Stream<A> str;
	A value;
	A valueUpdate;
	private Listener cleanup;
    Lazy<A> lazyInitValue;  // Used by LazyCell

	/**
	 * A cell with a constant value.
	 */
    public Cell(A value)
    {
    	this.str = new Stream<A>();
    	this.value = value;
    }

    Cell(final Stream<A> str, A initValue)
    {
    	this.str = str;
    	this.value = initValue;
    	Transaction.run(new Handler<Transaction>() {
    		public void run(Transaction trans1) {
	    		Cell.this.cleanup = str.listen(Node.NULL, trans1, new TransactionHandler<A>() {
	    			public void run(Transaction trans2, A a) {
			    		if (Cell.this.valueUpdate == null) {
			    			trans2.last(new Runnable() {
			    				public void run() {
				    				Cell.this.value = Cell.this.valueUpdate;
				    				Cell.this.lazyInitValue = null;
				    				Cell.this.valueUpdate = null;
				    			}
			    			});
			    		}
			    		Cell.this.valueUpdate = a;
			    	}
	    		}, false);
    		}
    	});
    }

    /**
     * @return The value including any updates that have happened in this transaction.
     */
    final A newValue()
    {
    	return valueUpdate == null ? sampleNoTrans() :  valueUpdate;
    }

    /**
     * Sample the cell's current value.
     * <p>
     * It may be used inside the functions passed to primitives that apply them to {@link Stream}s,
     * including {@link Stream#map(Lambda1)} in which case it is equivalent to snapshotting the cell,
     * {@link Stream#snapshot(Cell, Lambda2)}, {@link Stream#filter(Lambda1)} and
     * {@link Stream#merge(Stream, Lambda2)}.
     * It should generally be avoided in favour of {@link listen(Handler)} so you don't
     * miss any updates, but in many circumstances it makes sense.
     */
    public final A sample()
    {
        return Transaction.apply(new Lambda1<Transaction, A>() {
        	public A apply(Transaction trans) {
        		return sampleNoTrans();
        	}
        });
    }

    private static class LazySample<A> {
        LazySample(Cell<A> cell) {
            this.cell = cell;
        }
        Cell<A> cell;
        boolean hasValue;
        A value;
    }

    /**
     * A variant of {@link sample()} that works with {@link CellLoop}s when they haven't been looped yet.
     * It should be used in any code that's general enough that it could be passed a {@link CellLoop}.
     * @see Stream#holdLazy(Lazy) Stream.holdLazy()
     */
    public final Lazy<A> sampleLazy() {
        final Cell<A> me = this;
        return Transaction.apply(new Lambda1<Transaction, Lazy<A>>() {
        	public Lazy<A> apply(Transaction trans) {
        	    return me.sampleLazy(trans);
            }
        });
    }

    final Lazy<A> sampleLazy(Transaction trans) {
        final Cell<A> me = this;
        final LazySample<A> s = new LazySample<A>(me);
        trans.last(new Runnable() {
            public void run() {
                s.value = me.valueUpdate != null ? me.valueUpdate : me.sampleNoTrans();
                s.hasValue = true;
                s.cell = null;
            }
        });
        return new Lazy<A>(new Lambda0<A>() {
            public A apply() {
                if (s.hasValue)
                    return s.value;
                else
                    return s.cell.sample();
            }
        });
    }

    A sampleNoTrans()
    {
        return value;
    }

    final Stream<A> updates(Transaction trans)
    {
        return str;
    }

    final Stream<A> value(Transaction trans1)
    {
    	final StreamWithSend<Unit> sSpark = new StreamWithSend<Unit>();
        trans1.prioritized(sSpark.node, new Handler<Transaction>() {
            public void run(Transaction trans2) {
                sSpark.send(trans2, Unit.UNIT);
            }
        });
    	Stream<A> sInitial = sSpark.<A>snapshot(this);
        return sInitial.merge(updates(trans1), new Lambda2<A,A,A>() {
            public A apply(A left, A right) { return right; }
        });
    }

    /**
     * Transform the cell's value according to the supplied function, so the returned Cell
     * always reflects the value of the function applied to the input Cell's value.
     * @param f Function to apply to convert the values. It must be <em>referentially transparent</em>.
     */
	public final <B> Cell<B> map(final Lambda1<A,B> f)
	{
{'fraction_non_alphanumeric': 0.10942350332594235, 'fraction_numerical': 0.003880266075388027, 'mean_word_length': 2.0190763052208833, 'pattern_counts': {'":': 0, '<': 74, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5548881', 'n_tokens_mistral': 2855, 'n_tokens_neox': 2681, 'n_words': 802}