Define a primitive data type: Difference between revisions
m
→{{header|PascalABC.NET}}
m (→{{header|Sidef}}: fixed the code) |
|||
(91 intermediate revisions by 31 users not shown) | |||
Line 4:
=={{header|Ada}}==
<
The compiler identifies the range of valid values from the range specification ''1..10'' and automatically builds in bounds checking where it is needed. The compiler is smart enough to omit bounds checking when it is not needed.
<
B : My_Type := A;</
The compiler will omit bounds checking for the assignment of A to B above because both values are of My_Type. A cannot hold a value outside the range of 1..10, therefore the assignment cannot produce an out of bounds result.
Line 17:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386}}
<
INT max bounded = ( LENG max int * max int > long max int | ENTIER sqrt(max int) | max int );
Line 177:
OD;
except bounds error:
SKIP</
Output:
<pre>
Line 191:
===Other libraries or implementation specific extensions===
As of February 2009 no open source libraries to do this task have been located.
=={{header|ATS}}==
{{works with|ATS|Postiats (that is, ATS2)}}
Runtime bounds checking is expensive, so code ''given to the user'' typically has such checks turned off. The user is getting a dangerous version of the program!
Also, the programmer cannot discover violations except by running the program.
Is it not better, if possible, to have ''the compiler'' detect the mistake?
<syntaxhighlight lang="ats">(*
Here is the type:
*)
typedef rosetta_code_primitive_type =
[i : int | 1 <= i; i <= 10] int i
(*
You do not have to insert bounds checking, and the compiler inserts no
bounds checking. You simply *cannot* assign an out-of-range value.
(Proviso: unless you do some serious cheating.)
*)
implement
main0 (argc, argv) =
let
var n : rosetta_code_primitive_type
in
n := 1;
n := 10;
n := 11
end
(*
An attempt to compile this program *will fail* when it typechecks ‘n := 11’:
$ patscc primitive_type-postiats.dats
/path/to/primitive_type-postiats.dats: 282(line=21, offs=3) -- 373(line=27, offs=6): error(3): unsolved constraint: C3NSTRprop(C3TKmain(); S2Eapp(S2Ecst(<=); S2EVar(0->S2Eintinf(11)), S2Eintinf(10)))
/path/to/primitive_type-postiats.dats: 282(line=21, offs=3) -- 373(line=27, offs=6): error(3): unsolved constraint for lvar preservation
typechecking has failed: there are some unsolved constraints: please inspect the above reported error message(s) for information.
exit(ATS): uncaught exception: _2tmp_2ATS_2dPostiats_2src_2pats_error_2esats__FatalErrorExn(1025)
*)</syntaxhighlight>
The compiler’s messages are cryptic, but this problem could be overcome with devoted work on the compiler. (It is, after all, copylefted software and can be forked.)
There is a more serious downside. It is stated in [[#Ada|the Ada section]] that the Ada compiler is smart enough to know when to leave out bounds checks. In contrast, the ATS compiler will ''reject'' the program, unless it ''knows'' it can ‘leave out bounds checks’.
On the other hand, ''if you have no proof'' that a value is within the bounds 1..10, you must avoid attempting the assignment; but you can instead put something like '''if 1 <= k then if k <= 10 then n := k else abort() else abort()'''. In other words, you ''can'' insert a bounds check. It is often done, and there is an '''assertloc''' macro for doing so. The compiler lets you know you need the bounds check, but will not do it for you.
(You can also seriously cheat by using something like '''$UNSAFE.prop_assert''', but that is another topic. I mention it to encourage individual enquiry.)
=={{header|C sharp|C#}}==
Strictly speaking, this task is impossible in C# because a type that behaves like an integer (<code>int</code>, or <code>System.Int32</code>; <code>Integer</code> in VB.NET) must be a struct (in order to have value-type semantics), and, since C# does not allow the definition of a parameterless constructor for a struct (instead generating a default parameterless constructor that sets each of its fields to the default value for the type of the field), an instance of the struct with the forbidden value of zero can be created through that default constructor.
A way to overcome this in the type's public interface, however, is to expose the field exclusively as a property that checks whether its backing field is out of range, and, if so, returns a valid default value.
Through operator overloading, it is possible to declare types in C# with the full complement of operators available on the primitive types. The following structure attempts to mimic the behavior of the <code>int</code> type in C# on .NET Core as much as possible, including interfaces and static members, delegating as much implementation as possible to the <code>Integer</code> type itself.
<syntaxhighlight lang="csharp">using System;
using System.Globalization;
struct LimitedInt : IComparable, IComparable<LimitedInt>, IConvertible, IEquatable<LimitedInt>, IFormattable
{
public static readonly LimitedInt MaxValue = new LimitedInt(MAX_VALUE);
static bool IsValidValue(int value) => value >= MIN_VALUE && value <= MAX_VALUE;
readonly int _value;
public int Value => this._value == 0 ? MIN_VALUE : this._value; // Treat the default, 0, as being the minimum value.
public LimitedInt(int value)
{
if (
throw new ArgumentOutOfRangeException(nameof(value), value, $"Value must be between {MIN_VALUE} and {MAX_VALUE}.");
this._value = value;
}
#region IComparable
public int CompareTo(object obj)
{
if (obj is LimitedInt l) return
throw new ArgumentException("Object must be of type " + nameof(LimitedInt), nameof(obj));
}
#endregion
#region IComparable<LimitedInt>
public int CompareTo(LimitedInt other) => this.Value.CompareTo(other.Value);
#endregion
#region IConvertible
public TypeCode GetTypeCode() => this.Value.GetTypeCode();
bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)this.Value).ToBoolean(provider);
byte IConvertible.ToByte(IFormatProvider provider) => ((IConvertible)this.Value).ToByte(provider);
char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)this.Value).ToChar(provider);
DateTime IConvertible.ToDateTime(IFormatProvider provider) => ((IConvertible)this.Value).ToDateTime(provider);
decimal IConvertible.ToDecimal(IFormatProvider provider) => ((IConvertible)this.Value).ToDecimal(provider);
double IConvertible.ToDouble(IFormatProvider provider) => ((IConvertible)this.Value).ToDouble(provider);
short IConvertible.ToInt16(IFormatProvider provider) => ((IConvertible)this.Value).ToInt16(provider);
int IConvertible.ToInt32(IFormatProvider provider) => ((IConvertible)this.Value).ToInt32(provider);
long IConvertible.ToInt64(IFormatProvider provider) => ((IConvertible)this.Value).ToInt64(provider);
sbyte IConvertible.ToSByte(IFormatProvider provider) => ((IConvertible)this.Value).ToSByte(provider);
float IConvertible.ToSingle(IFormatProvider provider) => ((IConvertible)this.Value).ToSingle(provider);
string IConvertible.ToString(IFormatProvider provider) => this.Value.ToString(provider);
object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)this.Value).ToType(conversionType, provider);
ushort IConvertible.ToUInt16(IFormatProvider provider) => ((IConvertible)this.Value).ToUInt16(provider);
uint IConvertible.ToUInt32(IFormatProvider provider) => ((IConvertible)this.Value).ToUInt32(provider);
ulong IConvertible.ToUInt64(IFormatProvider provider) => ((IConvertible)this.Value).ToUInt64(provider);
#endregion
#region IEquatable<LimitedInt>
public bool Equals(LimitedInt other) => this == other;
#endregion
#region IFormattable
public string ToString(string format, IFormatProvider formatProvider) => this.Value.ToString(format, formatProvider);
#endregion
#region operators
public static bool operator ==(LimitedInt left, LimitedInt right) => left.Value == right.Value;
public static bool operator !=(LimitedInt left, LimitedInt right) => left.Value != right.Value;
public static bool operator <(LimitedInt left, LimitedInt right) => left.Value < right.Value;
public static bool operator >(LimitedInt left, LimitedInt right) => left.Value > right.Value;
public static bool operator <=(LimitedInt left, LimitedInt right) => left.Value <= right.Value;
public static bool operator >=(LimitedInt left, LimitedInt right) => left.Value >= right.Value;
public static LimitedInt operator ++(LimitedInt left) => (LimitedInt)(left.Value + 1);
public static LimitedInt operator --(LimitedInt left) => (LimitedInt)(left.Value - 1);
public static LimitedInt operator +(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value + right.Value);
public static LimitedInt operator -(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value - right.Value);
public static LimitedInt operator *(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value * right.Value);
public static LimitedInt operator /(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value / right.Value);
public static LimitedInt operator %(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value % right.Value);
public static LimitedInt operator &(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value & right.Value);
public static LimitedInt operator |(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value | right.Value);
public static LimitedInt operator ^(LimitedInt left, LimitedInt right) => (LimitedInt)(left.Value ^ right.Value);
public static LimitedInt operator ~(LimitedInt left) => (LimitedInt)~left.Value;
public static LimitedInt operator >>(LimitedInt left, int right) => (LimitedInt)(left.Value >> right);
public static LimitedInt operator <<(LimitedInt left, int right) => (LimitedInt)(left.Value << right);
public static implicit operator int(LimitedInt value) => value.Value;
public static explicit operator LimitedInt(int value)
{
return new LimitedInt(value);
}
#endregion
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
=> this.Value.TryFormat(destination, out charsWritten, format, provider);
public override int GetHashCode() => this.Value.GetHashCode();
public override bool Equals(object obj) => obj is LimitedInt l && this.Equals(l);
public override string ToString() => this.Value.ToString();
#region static methods
public static bool TryParse(ReadOnlySpan<char> s, out int result) => int.TryParse(s, out result);
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out int result) => int.TryParse(s, style, provider, out result);
public static int Parse(string s, IFormatProvider provider) => int.Parse(s, provider);
public static int Parse(string s, NumberStyles style, IFormatProvider provider) => int.Parse(s, style, provider);
public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, ref int result) => int.TryParse(s, style, provider, out result);
public static int Parse(string s) => int.Parse(s);
public static int Parse(string s, NumberStyles style) => int.Parse(s, style);
public static int Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null) => int.Parse(s, style, provider);
public static bool TryParse(string s, ref int result) => int.TryParse(s, out result);
#endregion
}</syntaxhighlight>
=={{header|C++}}==
Line 224 ⟶ 377:
This class relies on implicit conversions to do most int operations; however the combined operations with assignment have to be coded explicitly.
<
class tiny_int
Line 285 ⟶ 438:
private:
unsigned char value; // we don't need more space
};</
=={{header|Clojure}}==
Use proxy on java.lang.Number so it can be used in Clojure's math operations.
<
(if (<= 1 value 10)
(proxy [Number] []
(doubleValue [] value)
(longValue [] value))
(throw (ArithmeticException. "integer overflow"))))</
{{out}}
Line 314 ⟶ 468:
The built-in integer type specifier provides range parameters. <code>deftype</code> may be used to define an alias for it.
<
'(integer 1 10))</
For a bounds check, one may use <code>typep</code> (a predicate) or <code>check-type</code> (signals an error if not of the type).
<
(check-type i one-to-ten)
(case i
Line 331 ⟶ 485:
(8 "eight")
(9 "nine")
(10 "ten")))</
(Note that the above can be written without the separate check-type by using <code>ecase</code> instead of <code>case</code>, which signals an error when no case matches.)
Line 337 ⟶ 491:
To inform the compiler that a variable will be of a certain type, permitting optimizations, use a declaration:
<
(declare (type one-to-ten i))
...)</
Note, however, that the standard does not specify what happens in the event that a declaration is false (though [[SBCL]], for example, does perform type checks on any declaration except when <code>safety</code> is 0); use <code>check-type</code> for portable bounds checks.
Line 345 ⟶ 499:
=={{header|D}}==
<
/++
Line 428 ⟶ 582:
assert(i < 5);
assert(j > i);
}</
=={{header|Delphi}}==
''See [[#Free Pascal|Free Pascal]]''
=={{header|Dyalect}}==
The code below defines a new type <code>TinyInt</code>, provides bounds checking and implementation of all standard arithmetic operators:
<syntaxhighlight lang="dyalect">type TinyInt(Integer value) {
throw @Overflow(value) when value is <1 or >10
} with Lookup, Show
func TinyInt as Integer => this.value
func TinyInt + (other) => TinyInt(this.value + other as Integer)
func TinyInt * (other) => TinyInt(this.value * other as Integer)
func TinyInt - (other) => TinyInt(this.value - other as Integer)
func TinyInt / (other) => TinyInt(this.value / other as Integer)</syntaxhighlight>
Sample usage (interactive session):
<pre>dy>var x = TinyInt(3)
dy>x += 4
TinyInt (7) :: TinyInt
dy>x * 2
Operation overflows</pre>
=={{header|E}}==
<
for i :MyNumber in [0, 5, 10, 15, 20, 25] {
println(i)
}</
(Note: The region guard, while provided with E, is entirely unprivileged code, and could be argued not to be "primitive".)
=={{header|EchoLisp}}==
Types are native objects (Boolean, ..) , or defined by predicates and/or combinations of other types. They are used to check data values or to define functions signatures. The '''types.lib''' library must be loaded.
<syntaxhighlight lang="scheme">
(require 'types)
(require 'math)
;; type defined by a predicate
(define (one-ten? x) (in-interval? x 1 10))
(type One-ten [Integer & one-ten?])
;; OR by an enumeration
(type One-ten [ 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 ])
;; EXPLICIT type checking
;; type-of? returns a Boolean
(type-of? 5 One-ten) → #t
(type-of? 'Albert One-ten) → #f
;; type-check raises an error
(type-check 6 One-ten) → #t
(type-check 88 One-ten)
⛔ error: One-ten : type-check failure : 88 → 'one-ten?'
;; IMPLICIT type checking
;; declare a function signature
(define (f10 x y) (+ x y))
(signature f10 One-ten -> One-ten -> Integer)
(f10 6 7) → 13
(f10 42 666)
❗ error: One-ten : type-check failure : 42 → 'f10:x'
</syntaxhighlight>
=={{header|Elena}}==
ELENA 6.x:
<syntaxhighlight lang="elena">import extensions;
sealed struct TinyInt : BaseNumber
{
int value;
int cast() = value;
constructor(int n)
{
if (n <= 1 || n >= 10)
{
InvalidArgumentException.raise()
};
value := n
}
cast t(string s)
{
value := s.toInt();
if (value <= 1 || value >= 10)
{
InvalidArgumentException.raise()
}
}
TinyInt add(TinyInt t)
= value + (cast int(t));
TinyInt subtract(TinyInt t)
= value - (cast int(t));
TinyInt multiply(TinyInt t)
= value * (cast int(t));
TinyInt divide(TinyInt t)
= value / (cast int(t));
bool equal(TinyInt t)
= value == (cast int(t));
bool less(TinyInt t)
= value == (cast int(t));
string toPrintable()
=> value;
}
public program()
{
TinyInt i := 4t;
TinyInt j := i + i;
console.printLine("4t = ", i);
console.printLine("8t = ", j);
console.write("4t + 8t = ");
try
{
i + j
}
catch(InvalidArgumentException e)
{
console.printLine("A value is out of range")
}
}</syntaxhighlight>
{{out}}
<pre>
4t = 4
8t = 8
4t + 8t = A value is out of range
</pre>
=={{header|Euphoria}}==
In Euphoria types are special functions that may be used in declaring the allowed values for a variable. A type must have exactly one parameter and should return an atom that is either true (non-zero) or false (zero). Types can also be called just like other functions. The types '''object''', '''sequence''', '''atom''' and '''integer''' are predefined.
<
return i >= 1 and i <= 10
end type</
=={{header|Factor}}==
We can accomplish this using a predicate class. A predicate class must be a subclass of an existing class and allows the programmer to write a predicate which determines membership.
<syntaxhighlight lang="factor">PREDICATE: my-int < integer [ 0 > ] [ 11 < ] bi and ;</syntaxhighlight>
This automatically creates the <code>my-int?</code> predicate word which determines whether an object is a <code>my-int</code>.
<syntaxhighlight lang="factor">11 my-int? ! f
10 my-int? ! t
"hello" my-int? ! f</syntaxhighlight>
We can now write methods that specialize on <code>my-int</code>. We will define an increment word, <code>++</code>, which increments <code>integer</code>s by <tt>1</tt> but divides <code>my-int</code>s by <tt>2</tt>.
<syntaxhighlight lang="factor">GENERIC: ++ ( m -- n )
M: integer ++ 1 + ;
M: my-int ++ 2/ ;
10 ++ ! 5
11 ++ ! 12</syntaxhighlight>
=={{header|Forth}}==
{{ works with|ANS/ISO Forth|}}
Forth can be thought of as a clever Assembler for the Forth two stack virtual machine. As such Standard Forth does not type data but it does implicitly "type" words that act on data in that each function normally operates on a prescribed data type. True to the low level nature of Forth, the responsibility to select the correct action word for specific data is given to the programmer. That being said there are some simple ways to add the requested mechanism to your Forth system.
It is worth noting that Forth's penchant for simplicity means we do not need to write new math operators since each operator is atomic and takes arguments from the stack and returns the result to the stack. Therefore we get the desired functionality by only changing the assignment operation. Simplicity has its advantages.
=== Method 1: Safe Integer Store operators===
Forth is a fetch and store based virtual machine. If we create a safe version of store (!) the programmer simply uses this operator rather than the standard store operator.
<syntaxhighlight lang="text">DECIMAL
: CLIP ( n lo hi -- n') ROT MIN MAX ;
: BETWEEN ( n lo hi -- flag) 1+ WITHIN ;
\ programmer chooses CLIPPED or SAFE integer assignment
: CLIP! ( n addr -- ) SWAP 1 10 CLIP SWAP ! ;
: SAFE! ( n addr -- )
OVER 1 10 BETWEEN 0= ABORT" out of range!"
! ;</syntaxhighlight>
Testing
<syntaxhighlight lang="text">VARIABLE X
7 X SAFE! X ? 7 ok
12 X CLIP! X ? 10 ok
99 X SAFE!
:64: out of range!
99 X >>>SAFE!<<<
Backtrace:
$7FAA2B0C throw
$7FAD4698 c(abort")
</syntaxhighlight>
=== Method 2: redefine standard "store" operator as DEFER word ===
Using the code in Method 1, we can re-define the store (!) operator to be switchable.
<syntaxhighlight lang="text">DECIMAL
: FAST! ( n addr -- ) ! ; ( alias the standard version)
DEFER !
\ commands to change the action of '!'
: LIMITS-ON ( -- ) ['] SAFE! IS ! ;
: LIMITS-OFF ( -- ) ['] FAST! IS ! ;
: CLIPPING-ON ( -- ) ['] CLIP! IS ! ; </syntaxhighlight>
Testing
<syntaxhighlight lang="text">VARIABLE Y
LIMITS-OFF ok
1 Y ! Y ? 1 ok
10 Y ! Y ? 10 ok
11 Y ! Y ? 11 ok
0 Y ! Y ? 0 ok
LIMITS-ON ok
1 Y ! Y ? 1 ok
10 Y ! Y ? 10 ok
11 Y ! Y ?
:25: out of range!
11 Y >>>!<<< Y ?
Backtrace:
$7FAA2B0C throw
$7FAD4460 c(abort")
0 Y ! Y ?
:26: out of range!
0 Y >>>!<<< Y ?
Backtrace:
$7FAA2B0C throw
$7FAD4460 c(abort")
</syntaxhighlight>
=== Method 3: Create a safe VALUE assignment operator===
A VALUE defines a numerical data type that returns it's value rather than an address (pointer) like a variable.
We can create a word that assigns a number to a VALUE but tests for out of range errors.
<syntaxhighlight lang="text">: (->) ( n <text> -- )
OVER 1 10 BETWEEN 0= ABORT" out of range!"
>BODY ! ;
: -> ( n -- )
STATE @
IF POSTPONE ['] POSTPONE (->) \ compiling action
ELSE ' (->) \ interpret action
THEN ; IMMEDIATE</syntaxhighlight>
Test
<syntaxhighlight lang="text">0 VALUE Z ok
99 TO Z ok ( normal assignment)
Z . 99 ok
99 -> Z ( safe assignment)
:43: out of range!
99 -> >>>Z<<<
Backtrace:
$7FAA2B0C throw
$7FAD4570 c(abort")
$7FAD45DC (->)</syntaxhighlight>
=={{header|Fortran}}==
Line 448 ⟶ 851:
The module gives an example of how a ''bounded integer'' could be implemented in Fortran (not all the needed interfaces are implemented, and only the one for the + operator are shown). Bounds are checked at run-time.
<
implicit none
Line 549 ⟶ 952:
end function bounded_add_bbb
end module Bounded</
<
use Bounded
implicit none
Line 575 ⟶ 978:
c = c + b ! warning (c=10)
end program BoundedTest</
=={{header|Free Pascal}}==
''See [[#Pascal|Pascal]]''
<syntaxhighlight lang="pascal">type
range = 1..10;
var
n: range;
begin
n := 10;
{$rangeChecks on}
n := n + 10; // will yield a run-time error
end;</syntaxhighlight>
The FPC (Free Pascal compiler) by default does ''not generate'' range checks.
Assigning a value out of range is possible.
Only constant expressions, i. e. expressions that can be evaluated entirely during compile-time, are not accepted, if they are out of range.
The compiler directive <tt>{$rangeChecks on}</tt> will enable insertion of range checks.
If an out of range assignment is attempted, a run-time error occurs.
Note, in <tt>{$mode Delphi}</tt> range checks are only switchable at procedural level, not on a per expression-basis.
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64
Type MyInteger
Private:
Dim i_ As Integer
Public:
Declare Constructor(i_ As Integer)
Declare Property I() As Integer
Declare Operator Cast() As Integer
Declare Operator Cast() As String
End Type
Constructor MyInteger(i_ As Integer)
If i_ < 1 Then
i_ = 1
ElseIf i_ > 10 Then
i_ = 10
End If
This.i_ = i_
End Constructor
Property MyInteger.I() As Integer
Return i_
End Property
Operator MyInteger.Cast() As Integer
Return i_
End Operator
Operator MyInteger.Cast() As String
Return Str(i_)
End Operator
Dim i As MyInteger = 11 ' implicit constructor call; i_ automatically limited to 10
Dim j As MyInteger = 3 ' implicit constructor call; no adjustment needed
Dim k As Integer = 4
Print "i = "; i; " j = " ; j; " k = "; k; " j + 6 ="; j.I + 6; " j + k ="; j + k
Print
Print "Press any key to quit"
Sleep</syntaxhighlight>
{{out}}
<pre>
i = 10 j = 3 k = 4 j + 6 = 9 j + k = 7
</pre>
=={{header|Frink}}==
Frink can set "constraints" on variables that must be enforced at all times. One way is to define a function that returns <CODE>true</CODE> if the constraint is met. This constraint is checked whenever assigning a new value to the variable.
<syntaxhighlight lang="frink">oneToTen[x] := isInteger[x] AND x >= 1 AND x <= 10
var y is oneToTen = 1
while (true)
{
println[y]
y = y + 1
}</syntaxhighlight>
{{out}}
<pre>
1
2
3
4
5
6
7
8
9
10
Error: BasicContext: Cannot set symbol y, ContextFrame threw exception:
Constraint not met: function oneToTen[11] returned false.
In expression:
y = y + 1
</pre>
=={{header|Go}}==
{{trans|Kotlin}}
Creating a type that behaves like an integer but yet is distinct from it can be done in Go subject to the following constraints:
1. An instance of the new type needs to be created via a factory function (Go doesn't have constructors or user defined literals) to ensure it lies between 1 and 10. If an attempt is made to create an instance outside these limits, the value is adjusted so that it is just within them.
2. Go doesn't support operator overloading and so methods need to be defined for the standard operations on integers. As in the case of the Kotlin entry, only the basic arithmetic operations and the increment and decrement operations have been catered for below.
<syntaxhighlight lang="go">package main
import "fmt"
type TinyInt int
func NewTinyInt(i int) TinyInt {
if i < 1 {
i = 1
} else if i > 10 {
i = 10
}
return TinyInt(i)
}
func (t1 TinyInt) Add(t2 TinyInt) TinyInt {
return NewTinyInt(int(t1) + int(t2))
}
func (t1 TinyInt) Sub(t2 TinyInt) TinyInt {
return NewTinyInt(int(t1) - int(t2))
}
func (t1 TinyInt) Mul(t2 TinyInt) TinyInt {
return NewTinyInt(int(t1) * int(t2))
}
func (t1 TinyInt) Div(t2 TinyInt) TinyInt {
return NewTinyInt(int(t1) / int(t2))
}
func (t1 TinyInt) Rem(t2 TinyInt) TinyInt {
return NewTinyInt(int(t1) % int(t2))
}
func (t TinyInt) Inc() TinyInt {
return t.Add(TinyInt(1))
}
func (t TinyInt) Dec() TinyInt {
return t.Sub(TinyInt(1))
}
func main() {
t1 := NewTinyInt(6)
t2 := NewTinyInt(3)
fmt.Println("t1 =", t1)
fmt.Println("t2 =", t2)
fmt.Println("t1 + t2 =", t1.Add(t2))
fmt.Println("t1 - t2 =", t1.Sub(t2))
fmt.Println("t1 * t2 =", t1.Mul(t2))
fmt.Println("t1 / t2 =", t1.Div(t2))
fmt.Println("t1 % t2 =", t1.Rem(t2))
fmt.Println("t1 + 1 =", t1.Inc())
fmt.Println("t1 - 1 =", t1.Dec())
}</syntaxhighlight>
{{out}}
<pre>
t1 = 6
t2 = 3
t1 + t2 = 9
t1 - t2 = 3
t1 * t2 = 10
t1 / t2 = 2
t1 % t2 = 1
t1 + 1 = 7
t1 - 1 = 5
</pre>
=={{header|Haskell}}==
Line 581 ⟶ 1,159:
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:
<
data Check a b = Check { unCheck :: b } deriving (Eq, Ord)
Line 624 ⟶ 1,202:
quotRem = lift2p quotRem
divMod = lift2p divMod
toInteger = lift toInteger</
Now we can declare the a subrange 1..10 of integer like this:
<
instance Checked TinyInt Int where
check x | x >= 0 && x <= 10 = Check x
| otherwise = error "Out of range"</
In the same way, we could now declare the subtype of the even integers:
<
instance Checked EvenInt Int where
check x | even x = Check x
| otherwise = error "Not even"</
Similarly, we could declare the subtype of floating point numbers with restricted exponent, and so on.
=={{header|J}}==
J excels in composition rather than permitting verb overloading. Express a dyadic operation as verb__object1 object2 rather than object1 verb object2 . The example uses the verb ''add'' . The constructor, create, retains j's array data structure opposed to limiting to an atom.
<syntaxhighlight lang="j">
NB. z locale by default on path.
type_z_=: 3!:0
nameClass_z_=: 4!:0
signalError_z_=: 13!:8
NB. create a restricted object from an appropriate integer
create_restrict_ =: monad define
'Domain error: expected integer' assert 1 4 e.~ type y NB. or Boolean
'Domain error: not on [1,10]' assert (0 -.@:e. [: , (0&<*.<&11)) y
value=: y
)
add_restrict_=: monad define
if. 0 = nameClass<'value__y' do.
(value + value__y) conew 0{::coname''
else.
'value unavailable'signalError 21
end.
)
</syntaxhighlight>
<pre>
A=:(>:i.2 3)conew'restrict'
value__A
1 2 3
4 5 6
B =: 2 4 conew 'restrict'
C=: add__B A
value__C
3 4 5
8 9 10
add__C 1 conew'restrict'
|Domain error: not on [1,10]: assert
| 'Domain error: not on [1,10]' assert(0-.@:e.[:,(0&<*.<&11))y
(s:' symbol')conew'restrict'
|Domain error: expected integer: assert
| 'Domain error: expected integer' assert 1 4 e.~type y
</pre>
=={{header|Java}}==
Line 646 ⟶ 1,270:
This example class throws an exception if the value is out of the bounds; it is implemented only in the assignment method "assign" and the addition method "add". The class can be easily extended.
<
{
public BoundedIntOutOfBoundsException(int v, int l, int u) {
Line 716 ⟶ 1,340:
}
}
}</
=={{header|JavaScript}}==
<
n = Math.floor(n);
if(isNaN(n))
Line 742 ⟶ 1,366:
var y = new Num(0); //TypeError
var z = new Num(11); //TypeError
</syntaxhighlight>
=={{header|jq}}==
In the following, we define a new type named "smallint", with arithmetic operations that either return the "smallint" one would expect from ordinary arithmetic, or else return nothing (an empty stream), as opposed to returning null or raising an error. The choice of an empty stream is made to highlight this alternative.
By design, jq's types are constrained to be JSON types, so jq's type system cannot be used to create a new type, but we can create a parallel type system based on JSON objects. We shall do so using the convention that if an object has a key named "type", then the type of the object will be the given value:<
if type == "object" and has("type") then .type else type end;</
<
if type == "object" and has("type") then "\(.type)::\(.value)"
else .
end;</
This definition ensures that jq's basic tests for equality and inequality (== and !=) can be used for the instances of smallint.
Line 760 ⟶ 1,384:
As of this writing, the official release of jq does not support modules, so we will not use jq's new module system here, but it would allow us to place all the smallint functions in a Smallint module.
To generate instances of smallint, we define a function, smallint(i), that will return an instance corresponding to an integer, i, if it is in range. As noted above, it will otherwise return nothing at all (as opposed to null or raising an error):<
| if (i|type) == "number" and i == (i|floor) and i > 0 and i < 11 then {"type": "smallint", "value": i}
else empty
Line 773 ⟶ 1,397:
split("::") | smallint( .[1] | tonumber )
else empty
end ;</
def minus(a;b): smallint(a.value - b.value);
def times(a;b): smallint(a.value * b.value);
def mod(a;b): smallint(a.value % b.value);
def divide(a;b): smallint( (a.value / b.value) | floor );</
add( s(1); s(2)) | pp # "smallint::3"
add( s(6); s(6)) # (nothing)</
=={{header|Julia}}==
Julia has true, machine-optimized user defined primitives, but they are defined as contiguous groups of N bits:
<syntaxhighlight lang="julia">struct LittleInt <: Integer
val::Int8
function LittleInt(n::Real)
1 ≤ n ≤ 10 || throw(ArgumentError("LittleInt number must be in [1, 10]"))
return new(Int8(n))
end
end
Base.show(io::IO, x::LittleInt) = print(io, x.val)
Base.convert(::Type{T}, x::LittleInt) where T<:Number = convert(T, x.val)
Base.promote_rule(::Type{LittleInt}, ::Type{T}) where T<:Number = T
for op in (:+, :*, :÷, :-, :&, :|, :$, :<, :>, :(==))
@eval (Base.$op)(a::LittleInt, b::LittleInt) = LittleInt(($op)(a.val, b.val))
end
# Test
a = LittleInt(3)
b = LittleInt(4.0)
@show a b
@show a + b
@show b - a
@show a * LittleInt(2)
@show b ÷ LittleInt(2)
@show a * b</syntaxhighlight>
{{out}}
<pre>a = 3
b = 4
a + b = 7
b - a = 1
a * LittleInt(2) = 6
b ÷ LittleInt(2) = 2
ERROR: LoadError: ArgumentError: LittleInt number must be in [1, 10]</pre>
=={{header|Kotlin}}==
There are limits to what can be done to create a 'work-alike' primitive type in Kotlin as the language doesn't support either user-defined literals or implicit conversions between types.
However, subject to that, the following code creates a new primitive type called TinyInt whose values lie between 1 and 10 inclusive. Instead of throwing an exception, attempting to create such a type with an out of bounds value results in a value which is within bounds i.e. 1 if the value is less than 1 or 10 if the value is greater than 10.
Rather than attempt to reproduce all functions or operators which the Int type supports, only the basic arithmetic operators and the increment and decrement operators are catered for below:
<syntaxhighlight lang="scala">// version 1.1
class TinyInt(i: Int) {
private val value = makeTiny(i)
operator fun plus (other: TinyInt): TinyInt = TinyInt(this.value + other.value)
operator fun minus(other: TinyInt): TinyInt = TinyInt(this.value - other.value)
operator fun times(other: TinyInt): TinyInt = TinyInt(this.value * other.value)
operator fun div (other: TinyInt): TinyInt = TinyInt(this.value / other.value)
operator fun rem (other: TinyInt): TinyInt = TinyInt(this.value % other.value)
operator fun inc() = TinyInt(this.value + 1)
operator fun dec() = TinyInt(this.value - 1)
private fun makeTiny(i: Int): Int =
when {
i < 1 -> 1
i > 10 -> 10
else -> i
}
override fun toString(): String = value.toString()
}
fun main(args: Array<String>) {
var t1 = TinyInt(6)
var t2 = TinyInt(3)
println("t1 = $t1")
println("t2 = $t2")
println("t1 + t2 = ${t1 + t2}")
println("t1 - t2 = ${t1 - t2}")
println("t1 * t2 = ${t1 * t2}")
println("t1 / t2 = ${t1 / t2}")
println("t1 % t2 = ${t1 % t2}")
println("t1 + 1 = ${++t1}")
println("t2 - 1 = ${--t2}")
}</syntaxhighlight>
{{out}}
<pre>
t1 = 6
t2 = 3
t1 + t2 = 9
t1 - t2 = 3
t1 * t2 = 10
t1 / t2 = 2
t1 % t2 = 1
t1 + 1 = 7
t2 - 1 = 2
</pre>
=={{header|Lasso}}==
<
data private value
Line 810 ⟶ 1,528:
dint(10) + 1 // Error: 11 greater than 10
dint(10) * 2 // Error: 20 greater than 10
</syntaxhighlight>
=={{header|Lua}}==
<syntaxhighlight lang="lua">BI = { -- Bounded Integer
new = function(self, v) return setmetatable({v = self:_limit(v)}, BI_mt) end,
_limit = function(self,v) return math.max(1, math.min(math.floor(v), 10)) end,
}
BI_mt = {
__index = BI,
__call = function(self,v) return self:new(v) end,
__unm = function(self) return BI(-self.v) end,
__add = function(self,other) return BI(self.v+other.v) end,
__sub = function(self,other) return BI(self.v-other.v) end,
__mul = function(self,other) return BI(self.v*other.v) end,
__div = function(self,other) return BI(self.v/other.v) end,
__mod = function(self,other) return BI(self.v%other.v) end,
__pow = function(self,other) return BI(self.v^other.v) end,
__eq = function(self,other) return self.v==other.v end,
__lt = function(self,other) return self.v<other.v end,
__le = function(self,other) return self.v<=other.v end,
__tostring = function(self) return tostring(self.v) end
}
setmetatable(BI, BI_mt)</syntaxhighlight>
Example usage:
<syntaxhighlight lang="lua">zero, one, two, three, four, five = BI(0), BI(1), BI(2), BI(3), BI(4), BI(5)
six, seven, eight, nine, ten, eleven = BI(6), BI(7), BI(8), BI(9), BI(10), BI(11)
print("zero through eleven:\t", zero, one, two, three, four, five, six, seven, eight, nine, ten, eleven)
print("zero less than one?\t", zero < one)
print("eleven greater than ten?", eleven > ten)
print("negative one equals one:", -one)
print("zero plus one equals two:", zero + one)
print("one minus one equals one:", one - one)
print("two minus three equals one:", two - three)
print("three minus two equals one:", three - two)
print("two times three equals six:", two * three)
print("two times three equals six?", two * three == six)
print("three times four equals ten?", three * four == ten)
print("one divided by two equals one:",one / two)
print("five divided by two equals two:", five / two)
print("order of operations (seven):", one + two * three)
print("order of operations (nine):", (one + two) * three)
print("eight mod three equals two:", eight % three)
print("eight mod two equals one:", eight % two)
print("two to the third equals eight:", two ^ three)
print("two to the fourth equals ten:", two ^ four)</syntaxhighlight>
{{out}}
<pre>zero through eleven: 1 1 2 3 4 5 6 7 8 9 10 10
zero less than one? false
eleven greater than ten? false
negative one equals one: 1
zero plus one equals two: 2
one minus one equals one: 1
two minus three equals one: 1
three minus two equals one: 1
two times three equals six: 6
two times three equals six? true
three times four equals ten? true
one divided by two equals one: 1
five divided by two equals two: 2
order of operations (seven): 7
order of operations (nine): 9
eight mod three equals two: 2
eight mod two equals one: 1
two to the third equals eight: 8
two to the fourth equals ten: 10</pre>
=={{header|M2000 Interpreter}}==
We can make a Group to get and return value, a numeric value (if no $ used in name). Here we make operators ++ -- += and -=. To use it as a group in right expression we have to use Group(). Also we need Group() to push as group, at the last statement of CheckThis, where M is a pointer to a named group (K), which is not a movable Group (when module end run, this group erased), so cannot returned from module (if we do that we get a broken reference, which refer to a non exist group).
Class typeA, always return a unnamed group (a movable one) as a copy of an internal group (referred as This in constructor). Here constructor used once and because is in Class: part, can't copied to movable copy. Private variable mval can be visible only from "this" object. Statement .mval++ is same as This.mval++. Properties min and max has only value part, are read only. Min and max are groups also, and we can add anything that a group can have, using a second definition as Group min { }. Also a Property Min make a private variable as [min] so This.[Min] or .[Min] can be read or write inside modules/functions/operators of typeA and those who we insert after. Look at Set {} we place value to .mval using <=. If we use = then we make a local variable in Set not the private variable of group.
Every Module/Function/Operator/Sub/Thread can use stack of values. Rules are simple. Functions/Operators use new stack of values each time we call them in expressions. Module and Function which call using Call, or modules and subs by name use parent stack. Events (call functions) use new stack for each call.
We use stack to push a group (a copy form a pointer M, which points to K), as return value from module.
We can use Currency, Decimal, Double, Single, Long, Integer for primitive data types. When we see type using Type$() we get "Group" (the user object type) but using TypeExp$() (defined in this example) we get group value's type, as Currency here.
<syntaxhighlight lang="m2000 interpreter">
Module CheckDataType {
Module CheckThis {
Class typeA {
Private:
mval as currency
Public:
Property min {value}=-1
Property max {value}=0
Operator "++" {
if .mval=.[max] then Error "Number bigger than Max Value"
.mval++
}
Operator "--" {
if .mval=.[min] then Error "Number lower than Min Value"
.mval--
}
Operator "+=" (x){
if .mval>.[max]+x then Error "Number bigger than Max Value"
.mval+=x
}
Operator "-=" (x) {
if .mval<.[min]-x then Error "Number lower than Min Value"
.mval-=x
}
Value {
=.mval
}
Set (x) {
if x>.[max] then Error "Number bigger than Max Value"
if x<.[min] then Error "Number lower than Min Value"
.mval<=int(x)
}
Class:
Module typeA (.[min], .[max]) {
.mval<=.[min]
}
}
K=typeA(1, 10)
K=5
Def TypeExp$(x)=Type$(x)
Print Type$(K)="Group", TypeExp$(K)="Currency"
K--
Print K
K=K+1
Print K, K.Max, K.Min
K+=4
Print K, K.Max, K.Min
Print -K*4=-36
Try Ok {
K=400
}
If Error or Not Ok then Print Error$
\\ make a new K as K with name Z
Z=Group(K)
Print Z.Max, Z.Min, Z
K++
Z=Group(K)
Print Z=K
K-=5
\\ We make M as pointer to K
M->K
Print Eval(M), K
For M {This++}
Print Eval(M), K
For M {This=8}
Print Eval(M), K
Push Group(M), Group(M)
}
CheckThis
\\ Read Group from stack of values and place a copy in each item in A()
Dim A(4)=Group
\\ We have one more group in stack, so we read it to new variable What
\\ What isn't a pointer to object, is the object (internal is a pointer to objet but isn't usable for M2000)
Read What
What++
Print What.Max=10, What.Min=1, What=9 ' True True True
Print A(2).Max=10, A(2).Min=1, A(2)=8 ' True True True
}
CheckDataType
</syntaxhighlight>
=={{header|MATLAB}}==
Line 817 ⟶ 1,692:
In a folder named "@RingInt"
RingInt.m:
<
properties
Line 904 ⟶ 1,779:
end %classdef
</
Sample Usage:
<
ans =
Line 929 ⟶ 1,804:
ans =
1</
=={{header|Modula-3}}==
In Modula-3, subrange types are automatically subtypes of their base type, so if you define a type called <code>MyInt</code> to be the subrange [1..10] then <code>MyInt</code> is a subtype of <code>INTEGER</code>. If we defined <code>MyChar</code> as the subrange ['A'..'C'] then <code>MyChar</code> would be a subtype of <code>CHAR</code>.
<
<code>MyInt</code> can now be used anywhere an <code>INTEGER</code> can, such as the standard arithmetic functions. Trying to assign a value outside of the range of <code>MyInt</code> will result in a compile time warning, and/or a runtime error.
=={{header|Nim}}==
Subranges are supported by the language and automatically boundchecked:
<syntaxhighlight lang="nim">type
MyInt = range[1..10]
var x: MyInt = 5
x = x + 6 # Runtime error:
x = 12 # Compile-time error:
=={{header|OCaml}}==
<
type 'a bounds = { min: 'a; max: 'a }
Line 967 ⟶ 1,843:
let op f a b =
if a.bounds <> b.bounds then
invalid_arg "different bounds";
let res = f a.value b.value in
check_bounds res a.bounds;
(mk_bounded res a.bounds)
;;
(** val op : ('a -> 'a -> 'a) -> 'a bounded -> 'a bounded -> 'a bounded *)</
Using in the interactive top level:
<
val range : int bounds = {min = 1; max = 10}
Line 989 ⟶ 1,865:
# op ( + ) a b ;;
- : int bounded = {value = 7; bounds = {min = 1; max = 10}}</
which can be used with floats in the same way:
<
val rf : float bounds = {min = 1.; max = 10.}
Line 998 ⟶ 1,874:
and b = mk_bounded 5.6 rf in
op ( +. ) a b ;;
- : float bounded = {value = 7.8; bounds = {min = 1.; max = 10.}}</
=={{header|ooRexx}}==
<
* 21.06.2014 Walter Pachl
* implements a data type tinyint that can have an integer value 1..10
Line 1,050 ⟶ 1,926:
if wordpos(methName, "+ - * / % //")>0 then -- an arithmetic message in hand?
forward message (methName) to (v) array (methArgs[1])
</syntaxhighlight>
'''output'''
<pre>a=1
Line 1,075 ⟶ 1,951:
In this case we are lucky. As a feature of constraint programming we can easily constrain the domain of integers.
<
I
in
I::1#10
I = {Pow 2 4}</
Output:
Line 1,093 ⟶ 1,969:
=={{header|Pascal}}==
<syntaxhighlight lang="pascal">type
naturalTen = 1..10;</syntaxhighlight>
As per ISO 7185, any (attempted) assignment out of range constitutes an error.
However, the processor (usually a compiler) is permitted to leave such an error undetected.
Modern compilers such as [[#Delphi|Delphi]] and [[#Free Pascal|FPC]] give the programmer a choice, which behavior is desired, by providing compiler switches/directives.
=={{header|PascalABC.NET}}==
<syntaxhighlight lang="delphi">
type RangeInt = record
n: integer;
public
constructor(nn: integer);
begin
if nn not in 1..10 then
raise new System.ArgumentOutOfRangeException;
n := nn;
end;
function ToString: string; override := n.ToString;
static function operator implicit (n: integer): RangeInt := new RangeInt(n);
static function operator+(a,b: RangeInt): RangeInt := a.n + b.n;
static function operator-(a,b: RangeInt): RangeInt := a.n - b.n;
static function operator*(a,b: RangeInt): RangeInt := a.n * b.n;
static function operator/(a,b: RangeInt): real := a.n / b.n;
static function operator div(a,b: RangeInt): RangeInt := a.n div b.n;
static function operator mod(a,b: RangeInt): RangeInt := a.n mod b.n;
end;
function RInt(n: integer) := new RangeInt(n);
begin
var b: RangeInt := 3;
Print(a + b, a - b, a div b, a mod b);
Print(a * b); // ArgumentOutOfRangeException exception
</syntaxhighlight>
=={{header|Perl}}==
{{works with|Perl|5}}
<
use Carp qw(croak);
use Tie::Scalar qw();
Line 1,155 ⟶ 2,027:
$t = 11; # dies, too big
$t = 'xyzzy';
# dies, too small. string is 0 interpreted numerically</
=={{header|Phix}}==
{{trans|Euphoria}}
In Phix types are special functions that may be used in declaring the allowed values for a variable. A type must have exactly one parameter and should return true (non-zero) or false (zero). Types can also be called just like other functions. The types '''object''', '''sequence''', '''string''', '''atom''' and '''integer''' are predefined.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">type</span> <span style="color: #000000;">iten</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">1</span> <span style="color: #008080;">and</span> <span style="color: #000000;">i</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">10</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">type</span>
<!--</syntaxhighlight>-->
You can then declare variables of the new type just as you would the builtins
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #004080;">integer</span> <span style="color: #000000;">i</span>
<span style="color: #000000;">iten</span> <span style="color: #000000;">i10</span>
<!--</syntaxhighlight>-->
and typechecking occurs automatically
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #000000;">i</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">11</span> <span style="color: #000080;font-style:italic;">-- fine</span>
<span style="color: #000000;">i10</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">11</span> <span style="color: #000080;font-style:italic;">-- runtime error (desktop/Phix only, not pwa/p2js)</span>
<!--</syntaxhighlight>-->
Note that standard practice is to get a program running and fully tested on desktop/Phix first, ''before'' using pwa/p2js to run it in a browser.
=={{header|PicoLisp}}==
{{trans|Java}}
<
# value lower upper
Line 1,214 ⟶ 2,082:
(set> B 9)
(when (catch 'boundedIntOutOfBounds (+> A (val> B)) NIL)
(prinl @) ) ) )</
Output:
<pre>: (main)
value 12 is out of bounds [1,10]
value 15 is out of bounds [1,10]</pre>
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
[Int][ValidateRange(1,10)]$n = 3 # $n can only accept integers between 1 and 10
</syntaxhighlight>
=={{header|PureBasic}}==
<syntaxhighlight lang="purebasic">If OpenConsole()
Structure Persona
nombre.s{15}
apellido.s{30}
edad.w
List amigos$()
EndStructure
Dim MyFriends.Persona(100)
; Aquí la posición '1' del array MyFriends()
; contendrá una persona y su propia información
MyFriends(1)\nombre = "Carlos"
MyFriends(1)\apellido = "Gzlez."
MyFriends(1)\edad = 47
individuo.Persona
individuo\nombre = "Juan"
individuo\apellido = "Hdez."
individuo\edad = 49
; Ahora, agrega algunos amigos
AddElement(individuo\amigos$())
individuo\amigos$() = "Lucia"
AddElement(individuo\amigos$())
individuo\amigos$() = "Isabel"
ForEach individuo\amigos$()
Debug individuo\amigos$()
Next
;Estructura extendida
Structure Domicilio Extends Persona
calle.s
numero.b
EndStructure
MyFriends.Domicilio\calle = "Grillo"
MyFriends.Domicilio\numero = 20
PrintN(individuo\nombre + " " + individuo\apellido + " " + Str(individuo\edad) + " " + Str(MyFriends.Domicilio\numero))
PrintN(MyFriends(1)\nombre + " " + MyFriends(1)\apellido + " " + Str(MyFriends(1)\edad))
If TypeOf(Persona\edad) = #PB_Word
Debug "Edad ess un 'Word'"
EndIf
superficie.f
If TypeOf(superficie) = #PB_Float
Debug "superficie es un 'Float'"
EndIf
Print(#CRLF$ + #CRLF$ + "--- terminado, pulsa RETURN---"): Input()
CloseConsole()
EndIf</syntaxhighlight>
=={{header|Python}}==
This doesn't really apply as Python names don't have a type, but something can be done:
<
def __init__(self, b):
if 1 <= b <= 10:
Line 1,243 ⟶ 2,178:
>>> type(x)
<class '__main__.num'>
>>></
=={{header|QBasic}}==
{{works with|QBasic}}
<syntaxhighlight lang="qbasic">
TYPE TipoUsuario
nombre AS STRING * 15
apellido AS STRING * 30
edad AS INTEGER
END TYPE
DIM usuario(1 TO 20) AS TipoUsuario
usuario(1).nombre = "Juan"
usuario(1).apellido = "Hdez."
usuario(1).edad = 49
PRINT usuario(1).nombre, usuario(1).apellido, usuario(1).edad
</syntaxhighlight>
=={{header|Racket}}==
Most Racket programmers will use contracts to enforce additional guarantees on values. In the following example, the program exports <tt>x</tt> with a contract that ensures it is a number between 1 and 10.
<
#lang racket
Line 1,257 ⟶ 2,211:
(define x 5)
</syntaxhighlight>
In Typed Racket, it is possible to define a type that only contains the integers from 1 to 10. However, this type is inconvenient to use and is unlikely to be used in practice.
<
#lang typed/racket
Line 1,273 ⟶ 2,227:
(: y 1UpTo10)
(define y 18)
</syntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>subset OneToTen of Int where 1..10;
my OneToTen $n = 5;
$n += 6;</syntaxhighlight>
Here the result 11 fails to smartmatch against the range <code>1..10</code>, so the second assignment throws an exception. You may use any valid smartmatch predicate within a <code>where</code> clause, so the following one-argument closure is also legal:
<syntaxhighlight lang="raku" line>subset Prime of Int where -> $n { $n > 1 and so $n %% none 2 .. $n.sqrt }</syntaxhighlight>
=={{header|Retro}}==
<syntaxhighlight lang="retro">{{
variable update
---reveal---
Line 1,282 ⟶ 2,248:
: to dup 1 10 within [ update on ] [ drop "Out of bounds\n" puts ] if ;
: limited: create 1 , &.limited reclass ;
}}</
This creates a data element that returns a value from 1 to 10. Alteration of the value is possible using '''to'''.
<
1 to foo
foo .s
51 to foo
foo .s
bye</
=={{header|Ruby}}==
Line 1,309 ⟶ 2,275:
and define a method_missing method.
<
include Test::Unit::Assertions
Line 1,394 ⟶ 2,360:
assert_raise(ArgumentError) { c = a + b } # => invalid value '12', must be an integer
assert_raise(ArgumentError) { c = b - a } # => invalid value '-2', must be an integer</
=={{header|Rust}}==
As of version 1.36.0, Rust does not provide special language support for declaring new types which are range-constrained versions of its built-in primitives.
However, it is considered idiomatic to use single-element "tuple structs" (data structures with unnamed fields) to wrap primitive types in containers which impose runtime restrictions on their use without altering their in-memory representation.
The Rust ecosystem refers to this as the "newtype pattern" and an example would be the <code>String</code> type from the standard library, which wraps a <code>Vec<u8></code> to uphold a "contents are valid UTF-8" invariant and expose an alternative set of methods.
This idiom is bolstered by Rust's collection of traits (interfaces) which a type can implement to integrate with existing conversions and operators.
For example, it is common for functions which take paths as input but don't modify them to take <code>AsRef<Path></code>, which allows them to transparently accept any type which has implemented that conversion.
A simple example of implementing the newtype pattern manually would look like this:
<syntaxhighlight lang="rust">use std::convert::TryFrom;
mod test_mod {
use std::convert::TryFrom;
use std::fmt;
// Because the `i8` is not `pub` this cannot be directly constructed
// by code outside this module
#[derive(Copy, Clone, Debug)]
pub struct TwoDigit(i8);
impl TryFrom<i8> for TwoDigit {
type Error = &'static str;
fn try_from(value: i8) -> Result<Self, Self::Error> {
if value < -99 || value > 99 {
Err("Number cannot fit into two decimal digits")
} else {
Ok(TwoDigit(value))
}
}
}
impl Into<i8> for TwoDigit {
fn into(self) -> i8 { self.0 }
}
// This powers `println!`'s `{}` token.
impl fmt::Display for TwoDigit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
}
pub fn main() {
let foo = test_mod::TwoDigit::try_from(50).unwrap();
let bar: i8 = foo.into();
println!("{} == {}", foo, bar);
}</syntaxhighlight>
However, there exist crates such as [https://lib.rs/crates/derive_more derive_more] to automate the parts other than the restricted construction logic based on a simple <code>#[derive(Add, Copy, Clone, Debug, Div, Into, Mul, Sub)]</code> and so on and so forth.
=={{header|Scala}}==
{{libheader|Scala}}<
import TinyInt._
require(int >= lower && int <= upper, "TinyInt out of bounds.")
Line 1,410 ⟶ 2,433:
}
val test = (TinyInt.lower to TinyInt.upper).map(n => TinyInt(n.toByte))</
=={{header|Sidef}}==
<
subset MyIntLimit < Integer { . ~~ (1 .. 10) }
class MyInt(value < MyIntLimit) {
method to_s { value.to_s }
method get_value { value.get_value }
method ==(Number x) { value == x }
method ==(MyInt x) { value == x.value }
method AUTOLOAD(_, name, *args) {
var
results.map{|r| r.kind_of(Number) ? MyInt(r.int) : r}...
}
}
#
##
#
var a = MyInt(2)
a += 7
say a
say a/2
var b = (a - 3)
say b
say a.
a -=
say c # => 9
say c.class # => MyInt
a
say a+b
=={{header|Swift}}==
<syntaxhighlight lang="swift">struct SmallInt {
var value: Int
init(value: Int) {
guard value >= 1 && value <= 10 else {
fatalError("SmallInts must be in the range [1, 10]")
}
self.value = value
}
static func +(_ lhs: SmallInt, _ rhs: SmallInt) -> SmallInt { SmallInt(value: lhs.value + rhs.value) }
static func -(_ lhs: SmallInt, _ rhs: SmallInt) -> SmallInt { SmallInt(value: lhs.value - rhs.value) }
static func *(_ lhs: SmallInt, _ rhs: SmallInt) -> SmallInt { SmallInt(value: lhs.value * rhs.value) }
static func /(_ lhs: SmallInt, _ rhs: SmallInt) -> SmallInt { SmallInt(value: lhs.value / rhs.value) }
}
extension SmallInt: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) { self.init(value: value) }
}
extension SmallInt: CustomStringConvertible {
public var description: String { "\(value)" }
}
let a: SmallInt = 1
let b: SmallInt = 9
let c: SmallInt = 10
let d: SmallInt = 2
print(a + b)
print(c - b)
print(a * c)
print(c / d)
print(a + c)</syntaxhighlight>
{{out}}
<pre>10
1
10
5
Runner/main.swift:17: Fatal error: SmallInts must be in the range [1, 10]
Illegal instruction: 4</pre>
=={{header|Tcl}}==
Tcl does not attach types to values or variables, but it does allow the programmer to create traces on variables that can be used to enforce type-like constraints among other things. Traces are procedures that execute when variables are read, written and/or unset. (Traces are also available for commands and for the execution of a script.) Tcl's compiler does not enforce these constraints; they're strictly runtime entities.
<
variable value_cache
array set value_cache {}
Line 1,497 ⟶ 2,559:
error [format $errMsg $varname $value]
}
}</
So, in an interactive tclsh we can see:
Line 1,523 ⟶ 2,585:
=={{header|Toka}}==
<
{
variable update
Line 1,534 ⟶ 2,596:
value:1-10: foo
1 to foo
foo .</
=={{header|UNIX Shell}}==
Line 1,541 ⟶ 2,603:
* compound variables and
* "discipline functions" which get fired at get/set/unset events
<
function boundedint.set {
nameref var=${.sh.name}
Line 1,556 ⟶ 2,618:
boundedint=-5; echo $boundedint
boundedint=5; echo $boundedint
boundedint=15; echo $boundedint</
{{output}}
<pre>value out of bounds
Line 1,562 ⟶ 2,624:
5
value out of bounds
5</pre>
=={{header|Ursala}}==
Line 1,577 ⟶ 2,639:
corresponding operations on natural numbers with no further bounds
checking required.
<
my_number ::
Line 1,585 ⟶ 2,647:
add = my_number$[the_number: sum+ ~the_number~~]
mul = my_number$[the_number: product+ ~the_number~~]</
test program:
<
total = add(my_number[the_number: 3],my_number[the_number: 4])</
output:
<pre>
Line 1,595 ⟶ 2,657:
</pre>
test program demonstrating bounds checking:
<
total = mul(my_number[the_number: 3],my_number[the_number: 4])</
compile-time diagnostic output:
<pre>
Line 1,603 ⟶ 2,665:
</pre>
Note that restricted types are not idiomatic in Ursala if all we really want is integer arithmetic with run-time bounds checking, which can be done more directly like this.
<
#library+
Line 1,609 ⟶ 2,671:
#import
^|A(~&,//+ nrange(1,10)?</~& <'out of bounds'>!%)*
~&n-=<'sum','difference','product','quotient','remainder'>*~ %QI nat</
This code creates a new library of functions of natural numbers by selecting several of them by name from the standard <code>nat</code> library and putting a wrapper around each one that checks the bounds on the result and throws an exception if necessary. These functions can be used as drop-in replacements for the standard ones.
Line 1,617 ⟶ 2,679:
TinyInt.cls:
<
Public Property Let Value(ByVal vData As Integer)
Line 1,634 ⟶ 2,696:
'vb defaults to 0 for numbers; let's change that...
mvarValue = 1
End Sub</
Usage (in this case, from a form):
<
Private Sub Form_Click()
Line 1,648 ⟶ 2,710:
Randomize Timer
Set x = New TinyInt '"Set = New" REQUIRED
End Sub</
=={{header|Visual Basic .NET}}==
See [[#C#|C#]] for why this task ''technically'' impossible in VB.NET.
Through operator overloading, it is possible to declare types in VB.NET with the full complement of operators available on the primitive types. The following structure attempts to mimic the behavior of the <code>Integer</code> type in VB.NET on .NET Core as much as possible, including interfaces and static members, delegating as much implementation as possible to the <code>Integer</code> type itself.
<
Implements IComparable, IComparable(Of LimitedInt), IConvertible, IEquatable(Of LimitedInt), IFormattable
Private Const MIN_VALUE = 1
Private Const MAX_VALUE = 10
Shared ReadOnly MinValue As New LimitedInt(MIN_VALUE)
Shared ReadOnly MaxValue As New LimitedInt(MAX_VALUE)
Private ReadOnly _value As Integer
' Treat the default, 0, as being the minimum value.
Return If(Me._value = 0, MIN_VALUE, Me._value)
End
If Not IsValidValue(value) Then Throw New ArgumentOutOfRangeException(NameOf(value), value, $"Value must be between {MIN_VALUE} and {MAX_VALUE}.")
Me._value = value
End Sub
#Region "IComparable"
Function CompareTo(obj As Object) As Integer Implements IComparable.CompareTo
If TypeOf obj IsNot LimitedInt Then Throw New ArgumentException("Object must be of type " + NameOf(LimitedInt), NameOf(obj))
Return Me.CompareTo(DirectCast(obj, LimitedInt))
End Function
#End Region
#Region "IComparable(Of LimitedInt)"
Function CompareTo(other As LimitedInt) As Integer Implements IComparable(Of LimitedInt).CompareTo
Return Me.Value.CompareTo(other.Value)
End Function
#End Region
#Region "IConvertible"
Function GetTypeCode() As TypeCode Implements IConvertible.GetTypeCode
Return Me.Value.GetTypeCode()
End Function
Private Function ToBoolean(provider As IFormatProvider) As Boolean Implements IConvertible.ToBoolean
Return DirectCast(Me.Value, IConvertible).ToBoolean(provider)
Private Function ToByte(provider As IFormatProvider) As Byte Implements IConvertible.ToByte
Private Function ToChar(provider As IFormatProvider) As Char Implements IConvertible.ToChar
Private Function ToDateTime(provider As IFormatProvider) As Date Implements IConvertible.ToDateTime
Return
End
Private Function ToDecimal(provider As IFormatProvider) As Decimal Implements IConvertible.ToDecimal
Return DirectCast(Me.Value, IConvertible).ToDecimal(provider)
Private Function ToDouble(provider As IFormatProvider) As Double Implements IConvertible.ToDouble
Private Function ToInt16(provider As IFormatProvider) As Short Implements IConvertible.ToInt16
Private Function ToInt32(provider As IFormatProvider) As Integer Implements IConvertible.ToInt32
Private Function ToInt64(provider As IFormatProvider) As Long Implements IConvertible.ToInt64
Private Function ToSByte(provider As IFormatProvider) As SByte Implements IConvertible.ToSByte
Return
End
Private Function ToSingle(provider As IFormatProvider) As Single Implements IConvertible.ToSingle
Return
End
Private Overloads Function ToString(provider As IFormatProvider) As String Implements IConvertible.ToString
End
Private Function ToType(conversionType As Type, provider As IFormatProvider) As Object Implements IConvertible.ToType
Return
End
Private Function ToUInt16(provider As IFormatProvider) As UShort Implements IConvertible.ToUInt16
Return
End
Private Function ToUInt32(provider As IFormatProvider) As UInteger Implements IConvertible.ToUInt32
Return
End
Private Function ToUInt64(provider As IFormatProvider) As ULong Implements IConvertible.ToUInt64
Return
End
#End Region
#Region "IEquatable(Of LimitedInt)"
Overloads Function Equals(other As LimitedInt) As Boolean Implements IEquatable(Of LimitedInt).Equals
Return Me = other
End Function
#End Region
#Region "IFormattable"
Private Overloads Function ToString(format As String, formatProvider As IFormatProvider) As String Implements IFormattable.ToString
Return Me.Value.ToString(format, formatProvider)
End Function
#End Region
#Region "Operators"
Shared Operator =(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value = right.Value
End Operator
Shared Operator <>(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value <> right.Value
End Operator
Shared Operator <(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value < right.Value
End Operator
Shared Operator >(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value > right.Value
End Operator
Shared Operator <=(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value <= right.Value
End Operator
Shared Operator >=(left As LimitedInt, right As LimitedInt) As Boolean
Return left.Value >= right.Value
End Operator
Shared Operator +(left As LimitedInt) As LimitedInt
Return CType(+left.Value, LimitedInt)
End Operator
Shared Operator -(left As LimitedInt) As LimitedInt
Return CType(-left.Value, LimitedInt)
End Operator
Shared Operator +(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value + right.Value, LimitedInt)
End Operator
Shared Operator -(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value - right.Value, LimitedInt)
End Operator
Shared Operator *(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value * right.Value, LimitedInt)
End Operator
Shared Operator /(left As LimitedInt, right As LimitedInt) As Double
Return left.Value / right.Value
End Operator
Shared Operator \(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value \ right.Value, LimitedInt)
End Operator
Shared Operator ^(left As LimitedInt, right As LimitedInt) As Double
Return left.Value ^ right.Value
End Operator
Shared Operator Mod(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value Mod right.Value, LimitedInt)
End Operator
Shared Operator And(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value And right.Value, LimitedInt)
End Operator
Shared Operator Or(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value Or right.Value, LimitedInt)
End Operator
Shared Operator Xor(left As LimitedInt, right As LimitedInt) As LimitedInt
Return CType(left.Value Xor right.Value, LimitedInt)
End Operator
Shared Operator Not(left As LimitedInt) As LimitedInt
Return CType(Not left.Value, LimitedInt)
End Operator
Shared Operator >>(left As LimitedInt, right As Integer) As LimitedInt
Return CType(left.Value >> right, LimitedInt)
End Operator
Shared Operator <<(left As LimitedInt, right As Integer) As LimitedInt
Return CType(left.Value << right, LimitedInt)
End Operator
Shared Widening Operator CType(value As LimitedInt) As Integer
Return value.Value
End Operator
Shared Narrowing Operator CType(value As Integer) As LimitedInt
If Not IsValidValue(value) Then Throw New OverflowException()
Return New LimitedInt(value)
End Operator
#End Region
'Function TryFormat(destination As Span(Of Char), ByRef charsWritten As Integer, Optional format As ReadOnlySpan(Of Char) = Nothing, Optional provider As IFormatProvider = Nothing) As Boolean
' Return Me.Value.TryFormat(destination, charsWritten, format, provider)
'End Function
Overrides Function GetHashCode() As Integer
Return Me.Value.GetHashCode
End Function
Overrides Function Equals(obj As Object) As Boolean
Return TypeOf obj Is LimitedInt AndAlso Me.Equals(DirectCast(obj, LimitedInt))
End Function
Overrides Function ToString() As String
Return Me.Value.ToString()
End Function
#Region "Shared Methods"
'Shared Function TryParse(s As ReadOnlySpan(Of Char), ByRef result As Integer) As Boolean
' Return Integer.TryParse(s, result)
'End Function
'Shared Function TryParse(s As ReadOnlySpan(Of Char), style As Globalization.NumberStyles, provider As IFormatProvider, ByRef result As Integer) As Boolean
' Return Integer.TryParse(s, style, provider, result)
'End Function
Shared Function Parse(s As String, provider As IFormatProvider) As Integer
Return Integer.Parse(s, provider)
End Function
Shared Function Parse(s As String, style As Globalization.NumberStyles, provider As IFormatProvider) As Integer
Return Integer.Parse(s, style, provider)
End Function
Shared Function TryParse(s As String, style As Globalization.NumberStyles, provider As IFormatProvider, ByRef result As Integer) As Boolean
Return Integer.TryParse(s, style, provider, result)
End Function
Shared Function Parse(s As String) As Integer
Return Integer.Parse(s)
End Function
Shared Function Parse(s As String, style As Globalization.NumberStyles) As Integer
Return Integer.Parse(s, style)
End Function
'Shared Function Parse(s As ReadOnlySpan(Of Char), Optional style As Globalization.NumberStyles = Globalization.NumberStyles.Integer, Optional provider As IFormatProvider = Nothing) As Integer
' Return Integer.Parse(s, style, provider)
'End Function
Shared Function TryParse(s As String, ByRef result As Integer) As Boolean
Return Integer.TryParse(s, result)
End Function
#End Region
End Structure</syntaxhighlight>
=={{header|Visual FoxPro}}==
Visual FoxPro can't define primitives but they can be emulated with custom classes.
<syntaxhighlight lang="vfp">LOCAL o As BoundedInt
o = NEWOBJECT("BoundedInt")
DO WHILE NOT o.lHasError
Line 1,828 ⟶ 3,021:
ENDIF
THIS.lHasError = .T.
ENDDEFINE
=={{header|Wren}}==
To do this in Wren, you need to define a new TinyInt class with a suitable constructor and re-implement all the operators which apply to integers, checking (in the case of those that return an integer) that the result is within bounds and throwing an error if it isn't.
Note that inheriting from the basic types, such as Num, is not allowed.
The following carries out this procedure for a few basic operations and shows examples of their usage including throwing an out of bounds error on the last one.
<syntaxhighlight lang="wren">class TinyInt {
construct new(n) {
if (!(n is Num && n.isInteger && n >= 1 && n <= 10)) {
Fiber.abort("Argument must be an integer between 1 and 10.")
}
_n = n
}
n { _n }
+(other) { TinyInt.new(_n + other.n) }
-(other) { TinyInt.new(_n - other.n) }
*(other) { TinyInt.new(_n * other.n) }
/(other) { TinyInt.new((_n / other.n).truncate) }
==(other) { _n == other.n }
!=(other) { _n != other.n }
toString { _n.toString }
}
var a = TinyInt.new(1)
var b = TinyInt.new(2)
var c = a + b
System.print("%(a) + %(b) = %(c)")
var d = c - a
System.print("%(c) - %(a) = %(d)")
var e = d / d
System.print("%(d) / %(d) = %(e)")
var f = c * c
System.print("%(c) * %(c) = %(f)")
System.print("%(a) != %(b) -> %(a != b)")
System.print("%(a) + %(a) == %(b) -> %((a + a) == b)")
var g = f + b // out of range error here</syntaxhighlight>
{{out}}
<pre>
1 + 2 = 3
3 - 1 = 2
2 / 2 = 1
3 * 3 = 9
1 != 2 -> true
1 + 1 == 2 -> true
Argument must be an integer between 1 and 10.
[./primitive2 line 4] in init new(_)
[./primitive2 line 7] in
[./primitive2 line 11] in +(_)
[./primitive2 line 34] in (script)
</pre>
{{omit from|6502 Assembly}}
{{omit from|68000 Assembly}}
{{omit from|8080 Assembly}}
{{omit from|8086 Assembly}}
{{omit from|ARM Assembly}}
{{omit from|AWK}}
{{omit from|Axe}}
Line 1,838 ⟶ 3,092:
{{omit from|Déjà Vu}}
{{omit from|Erlang|The only way for Erlang would be to do like Java, i.e. cheat}}
{{omit from|Inform 7}}
{{omit from|J}}
Line 1,845 ⟶ 3,098:
{{omit from|Maxima}}
{{omit from|PARI/GP}}
{{omit from|SAS}}
{{omit from|Stata}}
{{omit from|TI-83 BASIC}}
{{omit from|TI-89 BASIC|Does not have user-defined data structures.}}
{{omit from|Vim Script}}
{{omit from|Z80 Assembly}}
|