Jump to content

Define a primitive data type: Difference between revisions

Whitespace, VB.NET highlighting might be broken? "End" isn't highlighted.
(→‎{{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:
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>
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}}==
 
The built-in integer type specifier provides range parameters. <code>deftype</code> may be used to define an alias for it.
 
Line 293 ⟶ 291:
 
=={{header|E}}==
<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".)
 
Line 439 ⟶ 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:
 
<lang haskell> {-# OPTIONS -fglasgow-exts #-}
 
data Check a b = Check { unCheck :: b } deriving (Eq, Ord)
 
class Checked a b where
check :: b -> Check a b
 
lift f x = f (unCheck x)
liftc f x = check $ f (unCheck x)
 
lift2 f x y = 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)
 
instance Show b => Show (Check a b) where
show (Check x) = show x
showsPrec p (Check x) = showsPrec p x
 
instance (Enum b, Checked a b) => Enum (Check a b) where
succ = liftc succ
pred = liftc pred
toEnum = check . toEnum
fromEnum = lift fromEnum
 
instance (Num b, Checked a b) => Num (Check a b) where
(+) = lift2c (+)
(-) = lift2c (-)
(*) = lift2c (*)
negate = liftc negate
abs = liftc abs
signum = liftc signum
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:
<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:
<lang haskell>newtype EvenInt = EvenInt Int
 
<lang instance haskell> newtypeChecked EvenInt =Int EvenInt Intwhere
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.
 
=={{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.
Line 585 ⟶ 578:
 
=={{header|OCaml}}==
<lang ocaml>exception Out_of_bounds
exception Out_of_bounds
 
type 'a bounds = { min: 'a; max: 'a }
Line 612 ⟶ 604:
(mk_bounded res a.bounds)
;;
(** val op : ('a -> 'a -> 'a) -> 'a bounded -> 'a bounded -> 'a bounded *)</lang>
</lang>
 
Using in the interactive top level:
<lang ocaml># let range = mk_bounds 1 10 ;;
# let range = mk_bounds 1 10 ;;
val range : int bounds = {min = 1; max = 10}
 
Line 630 ⟶ 620:
 
# op ( + ) a b ;;
- : int bounded = {value = 7; bounds = {min = 1; max = 10}}</lang>
</lang>
 
which can be used with floats in the same way:
<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.}
 
Line 641 ⟶ 629:
and b = mk_bounded 5.6 rf in
op ( +. ) a b ;;
- : float bounded = {value = 7.8; bounds = {min = 1.; max = 10.}}</lang>
</lang>
 
=={{header|Perl}}==
{{works with|Perl|5}}
<lang perl> package One_To_Ten;
use Carp qw(croak);
use Tie::Scalar qw();
use base qw(Tie::StdScalar);
 
sub STORE {
my $self = shift;
my $val = int shift;
croak 'out of bounds' if $val < 1 or $val > 10;
$$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}}==
This doesn't really apply as Python names don't have a type, but something can be done:
Line 859 ⟶ 845:
 
=={{header|Toka}}==
<lang toka>needs quotes
{
variable update
[ update @ [ ! ] [ @ ] ifTrueFalse update off ] is action
[ dup >r 0 11 r> within [ update on ] [ drop ." Out of bounds\n " ] ifTrueFalse ]
[ ` [ invoke cell-size malloc # ` action compile ` ] invoke is ]
} is value:1-10:
is to
value:1-10: foo
1 to foo
foo .
 
value:1-10: foo
1 to foo
foo .</lang>
=={{header|Visual Basic .NET}}==
 
Line 878 ⟶ 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.
 
<lang vbvbnet> Structure LimitedInt
Implements IComparable(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 PropertyFunction
 
Public SubOverrides NewFunction Equals(ByVal valueobj As IntegerObject) 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 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10Else : ReturnThrow New LimitedInt(temp)OverflowException
End Select
Case Else : Throw New OverflowException
End SelectOperator
 
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
Public Shared Operator \(ByVal left As CaseLimitedInt, 1ByVal Toright 10As :LimitedInt) Return NewAs LimitedInt(temp)
Dim temp As Integer = left.Value \ right.Value
Case Else : Throw New OverflowException
Select Case End Selecttemp
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
Public Shared Operator Mod(ByVal left As CaseLimitedInt, 1ByVal Toright 10As :LimitedInt) Return NewAs LimitedInt(temp)
Dim temp As Integer = left.Value Mod right.Value
Case Else : Throw New OverflowException
Select Case End Selecttemp
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 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10Else : ReturnThrow New LimitedInt(temp)OverflowException
End Select
Case Else : Throw New OverflowException
End SelectOperator
 
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 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10Else : ReturnThrow New LimitedInt(temp)OverflowException
End Select
Case Else : Throw New OverflowException
End SelectOperator
 
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 1 To 10 : Return New LimitedInt(temp)
Case 1 To 10Else : ReturnThrow New LimitedInt(temp)OverflowException
End Select
Case Else : Throw New OverflowException
End SelectOperator
 
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
Public Shared Operator <(ByVal left As CaseLimitedInt, 1ByVal Toright 10 : Return NewAs LimitedInt(temp) As Boolean
Return left.Value < right.Value
Case Else : Throw New OverflowException
End SelectOperator
 
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
Public Shared Operator <=(ByVal left As CaseLimitedInt, 1ByVal Toright 10 : Return NewAs LimitedInt(temp) As Boolean
Return left.Value <= right.Value
Case Else : Throw New OverflowException
End SelectOperator
 
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|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have user-defined data structures. -->
Anonymous user
Cookies help us deliver our services. By using our services, you agree to our use of cookies.