October 31, 2013
On 10/26/13, 17:42, Andrei Alexandrescu wrote:
> unittest
> {
>      Tristate a;
>      assert(a == Tristate.no);

Why not have '0' map to unknown? Seems to more useful, like float.nan and the like.

L.
October 31, 2013
On 10/31/13 2:35 AM, Lionello Lunesu wrote:
> On 10/26/13, 17:42, Andrei Alexandrescu wrote:
>> unittest
>> {
>>      Tristate a;
>>      assert(a == Tristate.no);
>
> Why not have '0' map to unknown? Seems to more useful, like float.nan
> and the like.

So logical operations are closer to the built-in Boolean ones, and conversion from bool is simple. If there's no such advantage, 0 should be the most frequent value (comparisons against 0 are smallest and fastest).

One possibility is to make the initial value unknown by default (which is a great idea).

I'll post shortly an update to Ternary (better name) along with additions to std.allocator.


Andrei

March 26, 2016
On Saturday, 26 October 2013 at 15:41:32 UTC, Andrei Alexandrescu wrote:
> While messing with std.allocator I explored the type below. I ended up not using it, but was surprised that implementing it was quite nontrivial. Should we add it to stdlib?

I can think of many variants of for this. What about

    { yes, // 1 chance
      no, // 0 chance
      likely, // > 1/2 chance
      unlikely, // < 1/2 chance
      unknown // any chance
    }

?

Partial implementation at

https://github.com/nordlow/justd/blob/master/fuzzy.d#L15

:)
March 26, 2016
On Saturday, 26 March 2016 at 22:11:53 UTC, Nordlöw wrote:
> On Saturday, 26 October 2013 at 15:41:32 UTC, Andrei Alexandrescu wrote:
>> While messing with std.allocator I explored the type below. I ended up not using it, but was surprised that implementing it was quite nontrivial. Should we add it to stdlib?
>
> I can think of many variants of for this. What about
>
>     { yes, // 1 chance
>       no, // 0 chance
>       likely, // > 1/2 chance
>       unlikely, // < 1/2 chance
>       unknown // any chance
>     }
>
> ?
>
> Partial implementation at
>
> https://github.com/nordlow/justd/blob/master/fuzzy.d#L15
>
> :)

If we're going down that route, might as well use state tables. With CTFE + templates, you could possibly do something like this:


	immutable State[] StateOrTable = ParseStateTable!q{
	        | yes | no       | likely | unlikely | unknown
	------------------------------------------------------
	yes     | yes | yes      | yes    | yes      | yes
	no      | yes | no       | likely | unlikely | unknown
	likely  | yes | likely   | likely | likely   | likely
	unlikely| yes | unlikely | likely | unlikely | unknown
	unknown | yes | unknown  | likely | unknwon  | unknown
	};

	State opBinary(string op)(State other)
	if(op == "||") {
		return StateOrTable[this.value*NumStates+other.value];
	}

Though I see issues with having a generic n-state value template and also rewriting `a != b` to `!(a == b)`; I suspect that there may be some class of values where the two are not equivalent.
March 27, 2016
On Saturday, 26 March 2016 at 22:39:58 UTC, Alex Parrill wrote:

...
> If we're going down that route, might as well use state tables.
...

For Boolean, Ternary, and N-state logic:

a && b == min(a, b)
a || b == max(a, b)
~a == N-1-a

why to optimize it more?
March 27, 2016
On Sunday, 27 March 2016 at 02:19:56 UTC, crimaniak wrote:
> On Saturday, 26 March 2016 at 22:39:58 UTC, Alex Parrill wrote:
>
> ...
>> If we're going down that route, might as well use state tables.
> ...
>
> For Boolean, Ternary, and N-state logic:
>
> a && b == min(a, b)
> a || b == max(a, b)
> ~a == N-1-a
>
> why to optimize it more?

That's incorrect for the `unknown` value.

Lets say you represented true as 1f, false as 0f, and unknown as NaN...

std.algorithm.max(0, 0f/0f) = 0, but should be NaN
std.math.fmax(1, 0f/0f) = NaN, but should be 1

N-state logic isn't just about probabilities either. According to Wikipedia, Bochvar's three-valued logic has an "internal" state, where any operation with `internal` results in `internal` (similar to NaN). More broadly, the values and operations between them could be whatever the mathematician or developer wants, so a truth table is one of the ways to generally specify an operator.
March 27, 2016
On 03/26/2016 10:36 PM, Alex Parrill wrote:
> N-state logic isn't just about probabilities either. According to
> Wikipedia, Bochvar's three-valued logic has an "internal" state, where
> any operation with `internal` results in `internal` (similar to NaN).
> More broadly, the values and operations between them could be whatever
> the mathematician or developer wants, so a truth table is one of the
> ways to generally specify an operator.

BTW there's a tri-state logic type in std.allocator. Care to take a look at how it might be improved? -- Andrei
March 27, 2016
On Saturday, 26 October 2013 at 21:05:36 UTC, Andrei Alexandrescu wrote:
>
> One challenge in Tristate (or the as-of-yet-unwritten Fourstate) is to define the primitives |, &, ^, and ~ with minimum of operations. For example Tristate still has conditionals in two of them, which I think could be cleverly avoided.

Have you tried to find ideas from LDC's output ?
I've seen impressive LLVM optimization results (and vectorizations) for this sort of stuff.

-Johan
March 28, 2016
On Sunday, 27 March 2016 at 02:36:47 UTC, Alex Parrill wrote:
...
>> a && b == min(a, b)
>> a || b == max(a, b)
>> ~a == N-1-a
>>
>> why to optimize it more?
>
> That's incorrect for the `unknown` value.
>
> Lets say you represented true as 1f, false as 0f, and unknown as NaN...
>
> std.algorithm.max(0, 0f/0f) = 0, but should be NaN
> std.math.fmax(1, 0f/0f) = NaN, but should be 1
>
> N-state logic isn't just about probabilities either. According
 Yes, you right, I mean logic as probability approximation (Godel). But in this case you can't assign arbitrary codes to values. False == 0, unknown == 1 and true == 2 is here.

> to Wikipedia, Bochvar's three-valued logic has an "internal" state, where any operation with `internal` results in `internal` (similar to NaN). More broadly, the values and operations between them could be whatever the mathematician or developer wants, so a truth table is one of the ways to generally specify an operator.
 Fully arbitrary logic needs tables, yes.

March 28, 2016
On Saturday, 26 March 2016 at 22:39:58 UTC, Alex Parrill wrote:
> On Saturday, 26 March 2016 at 22:11:53 UTC, Nordlöw wrote:
>> I can think of many variants of for this. What about
>>
>>     { yes, // 1 chance
>>       no, // 0 chance
>>       likely, // > 1/2 chance
>>       unlikely, // < 1/2 chance
>>       unknown // any chance
>>     }
>>
>> ?
>
> If we're going down that route, might as well use state tables. With CTFE + templates, you could possibly do something like this:
>
>
> 	immutable State[] StateOrTable = ParseStateTable!q{
> 	        | yes | no       | likely | unlikely | unknown
> 	------------------------------------------------------
> 	yes     | yes | yes      | yes    | yes      | yes
> 	no      | yes | no       | likely | unlikely | unknown
> 	likely  | yes | likely   | likely | likely   | likely
> 	unlikely| yes | unlikely | likely | unlikely | unknown
> 	unknown | yes | unknown  | likely | unknwon  | unknown
> 	};

I just hope we don't end up with an abomination like Microsoft's MsoTriState:
https://msdn.microsoft.com/en-us/library/office/ff860737.aspx

(A "tristate boolean" with five values, three of which are "not supported".)