Define a primitive data type: Difference between revisions

Content added Content deleted
(→‎{{header|Java}}: Grammar fix, added convenience add and assign methods, simplified checkBounds)
(Whitespace, VB.NET highlighting might be broken? "End" isn't highlighted.)
Line 196: Line 196:
This class relies on implicit conversions to do most int operations; however the combined operations with assignment have to be coded explicitly.
This class relies on implicit conversions to do most int operations; however the combined operations with assignment have to be coded explicitly.


<lang cpp> #include <stdexcept>
<lang cpp>#include <stdexcept>
class tiny_int
{
public:
tiny_int(int i):
value(i)
{
if (value < 1)
throw std::out_of_range("tiny_int: value smaller than 1");
if (value > 10)
throw std::out_of_range("tiny_int: value larger than 10");
}
operator int() const
{
return value;
}
tiny_int& operator+=(int i)
{
// by assigning to *this instead of directly modifying value, the
// constructor is called and thus the check is enforced
*this = value + i;
return *this;
}
tiny_int& operator-=(int i)
{
*this = value - i;
return *this;
}
tiny_int& operator*=(int i)
{
*this = value * i;
return *this;
}
tiny_int& operator/=(int i)
{
*this = value / i;
return *this;
}
tiny_int& operator<<=(int i)
{
*this = value << i;
return *this;
}
tiny_int& operator>>=(int i)
{
*this = value >> i;
return *this;
}
tiny_int& operator&=(int i)
{
*this = value & i;
return *this;
}
tiny_int& operator|=(int i)
{
*this = value | i;
return *this;
}
private:
unsigned char value; // we don't need more space
};</lang>


class tiny_int
{
public:
tiny_int(int i):
value(i)
{
if (value < 1)
throw std::out_of_range("tiny_int: value smaller than 1");
if (value > 10)
throw std::out_of_range("tiny_int: value larger than 10");
}
operator int() const
{
return value;
}
tiny_int& operator+=(int i)
{
// by assigning to *this instead of directly modifying value, the
// constructor is called and thus the check is enforced
*this = value + i;
return *this;
}
tiny_int& operator-=(int i)
{
*this = value - i;
return *this;
}
tiny_int& operator*=(int i)
{
*this = value * i;
return *this;
}
tiny_int& operator/=(int i)
{
*this = value / i;
return *this;
}
tiny_int& operator<<=(int i)
{
*this = value << i;
return *this;
}
tiny_int& operator>>=(int i)
{
*this = value >> i;
return *this;
}
tiny_int& operator&=(int i)
{
*this = value & i;
return *this;
}
tiny_int& operator|=(int i)
{
*this = value | i;
return *this;
}
private:
unsigned char value; // we don't need more space
};</lang>
=={{header|Common Lisp}}==
=={{header|Common Lisp}}==

The built-in integer type specifier provides range parameters. <code>deftype</code> may be used to define an alias for it.
The built-in integer type specifier provides range parameters. <code>deftype</code> may be used to define an alias for it.


Line 293: Line 291:


=={{header|E}}==
=={{header|E}}==
<lang e> def MyNumber := 1..10
<lang e>def MyNumber := 1..10

for i :MyNumber in [0, 5, 10, 15, 20, 25] {
println(i)
}</lang>


for i :MyNumber in [0, 5, 10, 15, 20, 25] {
println(i)
}</lang>
(Note: The region guard, while provided with E, is entirely unprivileged code, and could be argued not to be "primitive".)
(Note: The region guard, while provided with E, is entirely unprivileged code, and could be argued not to be "primitive".)


Line 439: Line 436:
Haskell doesn't have any built-in subrange types. However, it is possible to declare arbitrary types that "behave like" any of the built-in types on the "usual" numeric etc. operations, because these operations are defined by type-classes. So we generalize the task a bit, and first declare a generic container type that supports an additional ''check'' operation. Then, we lift any operation in the base type to the container type, by executing the check after each operation:
Haskell doesn't have any built-in subrange types. However, it is possible to declare arbitrary types that "behave like" any of the built-in types on the "usual" numeric etc. operations, because these operations are defined by type-classes. So we generalize the task a bit, and first declare a generic container type that supports an additional ''check'' operation. Then, we lift any operation in the base type to the container type, by executing the check after each operation:


<lang haskell> {-# OPTIONS -fglasgow-exts #-}
<lang haskell>{-# OPTIONS -fglasgow-exts #-}

data Check a b = Check { unCheck :: b } deriving (Eq, Ord)
data Check a b = Check { unCheck :: b } deriving (Eq, Ord)

class Checked a b where
class Checked a b where
check :: b -> Check a b
check :: b -> Check a b

lift f x = f (unCheck x)
lift f x = f (unCheck x)
liftc f x = check $ f (unCheck x)
liftc f x = check $ f (unCheck x)

lift2 f x y = f (unCheck x) (unCheck y)
lift2 f x y = f (unCheck x) (unCheck y)
lift2c f x y = check $ f (unCheck x) (unCheck y)
lift2c f x y = check $ f (unCheck x) (unCheck y)
lift2p f x y = (check u, check v) where (u,v) = f (unCheck x) (unCheck y)
lift2p f x y = (check u, check v) where (u,v) = f (unCheck x) (unCheck y)

instance Show b => Show (Check a b) where
instance Show b => Show (Check a b) where
show (Check x) = show x
show (Check x) = show x
showsPrec p (Check x) = showsPrec p x
showsPrec p (Check x) = showsPrec p x

instance (Enum b, Checked a b) => Enum (Check a b) where
instance (Enum b, Checked a b) => Enum (Check a b) where
succ = liftc succ
succ = liftc succ
pred = liftc pred
pred = liftc pred
toEnum = check . toEnum
toEnum = check . toEnum
fromEnum = lift fromEnum
fromEnum = lift fromEnum

instance (Num b, Checked a b) => Num (Check a b) where
instance (Num b, Checked a b) => Num (Check a b) where
(+) = lift2c (+)
(+) = lift2c (+)
(-) = lift2c (-)
(-) = lift2c (-)
(*) = lift2c (*)
(*) = lift2c (*)
negate = liftc negate
negate = liftc negate
abs = liftc abs
abs = liftc abs
signum = liftc signum
signum = liftc signum
fromInteger = check . fromInteger
fromInteger = check . fromInteger
instance (Real b, Checked a b) => Real (Check a b) where
toRational = lift toRational
instance (Integral b, Checked a b) => Integral (Check a b) where
quot = lift2c quot
rem = lift2c rem
div = lift2c div
mod = lift2c mod
quotRem = lift2p quotRem
divMod = lift2p divMod
toInteger = lift toInteger</lang>


instance (Real b, Checked a b) => Real (Check a b) where
toRational = lift toRational

instance (Integral b, Checked a b) => Integral (Check a b) where
quot = lift2c quot
rem = lift2c rem
div = lift2c div
mod = lift2c mod
quotRem = lift2p quotRem
divMod = lift2p divMod
toInteger = lift toInteger</lang>
Now we can declare the a subrange 1..10 of integer like this:
Now we can declare the a subrange 1..10 of integer like this:
<lang haskell> newtype TinyInt = TinyInt Int
instance Checked TinyInt Int where
check x | x >= 0 && x <= 10 = Check x
| otherwise = error "Out of range"</lang>


<lang haskell>newtype TinyInt = TinyInt Int

instance Checked TinyInt Int where
check x | x >= 0 && x <= 10 = Check x
| otherwise = error "Out of range"</lang>
In the same way, we could now declare the subtype of the even integers:
In the same way, we could now declare the subtype of the even integers:
<lang haskell>newtype EvenInt = EvenInt Int


<lang haskell> newtype EvenInt = EvenInt Int
instance Checked EvenInt Int where
check x | even x = Check x
| otherwise = error "Not even"</lang>
instance Checked EvenInt Int where
check x | even x = Check x
| otherwise = error "Not even"</lang>


Similarly, we could declare the subtype of floating point numbers with restricted exponent, and so on.
Similarly, we could declare the subtype of floating point numbers with restricted exponent, and so on.

=={{header|Java}}==
=={{header|Java}}==
The closest you can get to defining a primitive type in Java is making a new wrapper class with methods for math operations.
The closest you can get to defining a primitive type in Java is making a new wrapper class with methods for math operations.
Line 585: Line 578:


=={{header|OCaml}}==
=={{header|OCaml}}==
<lang ocaml>
<lang ocaml>exception Out_of_bounds
exception Out_of_bounds


type 'a bounds = { min: 'a; max: 'a }
type 'a bounds = { min: 'a; max: 'a }
Line 612: Line 604:
(mk_bounded res a.bounds)
(mk_bounded res a.bounds)
;;
;;
(** val op : ('a -> 'a -> 'a) -> 'a bounded -> 'a bounded -> 'a bounded *)
(** val op : ('a -> 'a -> 'a) -> 'a bounded -> 'a bounded -> 'a bounded *)</lang>
</lang>


Using in the interactive top level:
Using in the interactive top level:
<lang ocaml>
<lang ocaml># let range = mk_bounds 1 10 ;;
# let range = mk_bounds 1 10 ;;
val range : int bounds = {min = 1; max = 10}
val range : int bounds = {min = 1; max = 10}


Line 630: Line 620:


# op ( + ) a b ;;
# op ( + ) a b ;;
- : int bounded = {value = 7; bounds = {min = 1; max = 10}}
- : int bounded = {value = 7; bounds = {min = 1; max = 10}}</lang>
</lang>


which can be used with floats in the same way:
which can be used with floats in the same way:
<lang ocaml>
<lang ocaml># let rf = mk_bounds 1.0 10.0 ;;
# let rf = mk_bounds 1.0 10.0 ;;
val rf : float bounds = {min = 1.; max = 10.}
val rf : float bounds = {min = 1.; max = 10.}


Line 641: Line 629:
and b = mk_bounded 5.6 rf in
and b = mk_bounded 5.6 rf in
op ( +. ) a b ;;
op ( +. ) a b ;;
- : float bounded = {value = 7.8; bounds = {min = 1.; max = 10.}}
- : float bounded = {value = 7.8; bounds = {min = 1.; max = 10.}}</lang>
</lang>


=={{header|Perl}}==
=={{header|Perl}}==
{{works with|Perl|5}}
{{works with|Perl|5}}
<lang perl> package One_To_Ten;
<lang perl>package One_To_Ten;
use Carp qw(croak);
use Carp qw(croak);
use Tie::Scalar qw();
use Tie::Scalar qw();
use base qw(Tie::StdScalar);
use base qw(Tie::StdScalar);

sub STORE {
sub STORE {
my $self = shift;
my $self = shift;
my $val = int shift;
my $val = int shift;
croak 'out of bounds' if $val < 1 or $val > 10;
croak 'out of bounds' if $val < 1 or $val > 10;
$$self = $val;
$$self = $val;
};
};
package main;
tie my $t, 'One_To_Ten';
$t = 3; # ok
$t = 5.2; # ok, silently coerced to int
$t = -2; # dies, too small
$t = 11; # dies, too big
$t = 'xyzzy';
# dies, too small. string is 0 interpreted numerically</lang>


package main;
tie my $t, 'One_To_Ten';
$t = 3; # ok
$t = 5.2; # ok, silently coerced to int
$t = -2; # dies, too small
$t = 11; # dies, too big
$t = 'xyzzy';
# dies, too small. string is 0 interpreted numerically</lang>
=={{header|Python}}==
=={{header|Python}}==
This doesn't really apply as Python names don't have a type, but something can be done:
This doesn't really apply as Python names don't have a type, but something can be done:
Line 859: Line 845:


=={{header|Toka}}==
=={{header|Toka}}==
needs quotes
<lang toka>needs quotes
{
{
variable update
variable update
[ update @ [ ! ] [ @ ] ifTrueFalse update off ] is action
[ update @ [ ! ] [ @ ] ifTrueFalse update off ] is action
[ dup >r 0 11 r> within [ update on ] [ drop ." Out of bounds\n " ] ifTrueFalse ]
[ dup >r 0 11 r> within [ update on ] [ drop ." Out of bounds\n " ] ifTrueFalse ]
[ ` [ invoke cell-size malloc # ` action compile ` ] invoke is ]
[ ` [ invoke cell-size malloc # ` action compile ` ] invoke is ]
} is value:1-10:
} is value:1-10:
is to
is to
value:1-10: foo
1 to foo
foo .


value:1-10: foo
1 to foo
foo .</lang>
=={{header|Visual Basic .NET}}==
=={{header|Visual Basic .NET}}==


Line 878: Line 863:
Also note that some operators return a Double instead of a new LimitedInt. This was by choice in order to match the behavior of Integers in VB.
Also note that some operators return a Double instead of a new LimitedInt. This was by choice in order to match the behavior of Integers in VB.


<lang vb> Structure LimitedInt
<lang vbnet>Structure LimitedInt
Implements IComparable(Of LimitedInt)
Implements IComparable(Of LimitedInt)
Implements IEquatable(Of LimitedInt)
Implements IEquatable(Of LimitedInt)

Private m_Value As Integer 'treat the default, 0 as being really 1

Public ReadOnly Property Value() As Integer
Get
Return If(m_Value = 0, 1, m_Value)
End Get
End Property

Public Sub New(ByVal value As Integer)
If value < 1 Or value > 10 Then Throw New ArgumentOutOfRangeException("value")
m_Value = value
End Sub

Public Function CompareTo(ByVal other As LimitedInt) As Integer Implements System.IComparable(Of LimitedInt).CompareTo
Return Me.Value - other.Value
End Function
Public Overloads Function Equals(ByVal other As LimitedInt) As Boolean Implements System.IEquatable(Of LimitedInt).Equals
Private m_Value As Integer 'treat the default, 0 as being really 1
Return Me.Value = other.Value
End Function
Public ReadOnly Property Value() As Integer

Get
Public Overrides Function GetHashCode() As Integer
Return If(m_Value = 0, 1, m_Value)
Return Value.GetHashCode
End Get
End Property
End Function

Public Sub New(ByVal value As Integer)
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If TypeOf obj Is LimitedInt Then Return CType(obj, LimitedInt) = Me
If value < 1 Or value > 10 Then Throw New ArgumentOutOfRangeException("value")
End Function
m_Value = value

End Sub
Public Shared Operator =(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Equals(right)
Public Function CompareTo(ByVal other As LimitedInt) As Integer Implements System.IComparable(Of LimitedInt).CompareTo
End Operator
Return Me.Value - other.Value

End Function
Public Shared Operator <>(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return Not (left = right)
Public Overloads Function Equals(ByVal other As LimitedInt) As Boolean Implements System.IEquatable(Of LimitedInt).Equals
End Operator
Return Me.Value = other.Value

End Function
Public Shared Operator +(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value + right.Value
Public Overrides Function GetHashCode() As Integer
Select Case temp
Return Value.GetHashCode
Case 1 To 10 : Return New LimitedInt(temp)
End Function
Case Else : Throw New OverflowException
End Select
Public Overrides Function Equals(ByVal obj As Object) As Boolean
End Operator
If TypeOf obj Is LimitedInt Then Return CType(obj, LimitedInt) = Me

End Function
Public Shared Operator -(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value - right.Value
Public Shared Operator =(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Select Case temp
Return left.Equals(right)
Case 1 To 10 : Return New LimitedInt(temp)
End Operator
Case Else : Throw New OverflowException
End Select
Public Shared Operator <>(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
End Operator
Return Not (left = right)

End Operator
Public Shared Operator *(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value * right.Value
Public Shared Operator +(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Select Case temp
Dim temp As Integer = left.Value + right.Value
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10 : Return New LimitedInt(temp)
Case Else : Throw New OverflowException
End Select
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator /(ByVal left As LimitedInt, ByVal right As LimitedInt) As Double
Return left.Value / right.Value
Public Shared Operator -(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
End Operator
Dim temp As Integer = left.Value - right.Value

Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Public Shared Operator \(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value \ right.Value
Case Else : Throw New OverflowException
End Select
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
End Operator
Case Else : Throw New OverflowException
End Select
Public Shared Operator *(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
End Operator
Dim temp As Integer = left.Value * right.Value

Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Public Shared Operator Mod(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value Mod right.Value
Case Else : Throw New OverflowException
End Select
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
End Operator
Case Else : Throw New OverflowException
End Select
Public Shared Operator /(ByVal left As LimitedInt, ByVal right As LimitedInt) As Double
End Operator
Return left.Value / right.Value

End Operator
Public Shared Operator And(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value And right.Value
Public Shared Operator \(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Select Case temp
Dim temp As Integer = left.Value \ right.Value
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10 : Return New LimitedInt(temp)
Case Else : Throw New OverflowException
End Select
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator Or(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value Or right.Value
Public Shared Operator Mod(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Select Case temp
Dim temp As Integer = left.Value Mod right.Value
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10 : Return New LimitedInt(temp)
Case Else : Throw New OverflowException
End Select
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator Xor(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Dim temp As Integer = left.Value Xor right.Value
Public Shared Operator And(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
Select Case temp
Dim temp As Integer = left.Value And right.Value
Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10 : Return New LimitedInt(temp)
Case Else : Throw New OverflowException
End Select
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator ^(ByVal left As LimitedInt, ByVal right As LimitedInt) As Double
Return left.Value ^ right.Value
Public Shared Operator Or(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
End Operator
Dim temp As Integer = left.Value Or right.Value

Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Public Shared Operator <(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value < right.Value
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator >(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value > right.Value
Public Shared Operator Xor(ByVal left As LimitedInt, ByVal right As LimitedInt) As LimitedInt
End Operator
Dim temp As Integer = left.Value Xor right.Value

Select Case temp
Case 1 To 10 : Return New LimitedInt(temp)
Public Shared Operator <=(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value <= right.Value
Case Else : Throw New OverflowException
End Select
End Operator

End Operator
Public Shared Operator >=(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value >= right.Value
Public Shared Operator ^(ByVal left As LimitedInt, ByVal right As LimitedInt) As Double
End Operator
Return left.Value ^ right.Value

End Operator
Public Shared Widening Operator CType(ByVal left As LimitedInt) As Integer
Return left.Value
Public Shared Operator <(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
End Operator
Return left.Value < right.Value

End Operator
Public Shared Narrowing Operator CType(ByVal left As Integer) As LimitedInt
Return New LimitedInt(left)
Public Shared Operator >(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
End Operator
Return left.Value > right.Value
End Operator
Public Shared Operator <=(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value <= right.Value
End Operator
Public Shared Operator >=(ByVal left As LimitedInt, ByVal right As LimitedInt) As Boolean
Return left.Value >= right.Value
End Operator
Public Shared Widening Operator CType(ByVal left As LimitedInt) As Integer
Return left.Value
End Operator
Public Shared Narrowing Operator CType(ByVal left As Integer) As LimitedInt
Return New LimitedInt(left)
End Operator
End Structure</lang>


End Structure</lang>
{{omit from|JavaScript}}
{{omit from|JavaScript}}
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have user-defined data structures. -->
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have user-defined data structures. -->