Sum data type: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|ALGOL 68}}: One day, I will learn how to spell "OCaml"...)
(→‎{{header|REXX}}: added the REXX computer programming language for this task.)
Line 129: Line 129:


let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</lang>
let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</lang>

=={{header|REXX}}==
The '''REXX''' language is untyped, &nbsp; it is up to the program to decide if it's valid and
how to deal with an invalid structure.
<lang rexx>/*REXX pgm snipette validates a specific type of data structure, an IP v4 address (list)*/
ip= 127 0 0 1
if val_ipv4(ip) then say 'valid IPV4 type: ' ip
else say '***error*** invalid IPV4 type: ' ip
...

exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
val_ipv4: procedure; parse arg $; if words($)\==4 | arg()\==1 then return 0
do j=1 for 4; _=word($, j); #=datatype(_, 'W'); L= length(_)
if verify(_, 0123456789)\==0 | \# | _<0 | _>255 | L>3 then return 0
end /*j*/
return 1 /*returns true (1) if valid, 0 if not. */</lang><br>



=={{header|Rust}}==
=={{header|Rust}}==

Revision as of 20:06, 25 June 2019

Sum data type is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Data Structure
This illustrates a data structure, a means of storing data within a program.

You may see other such structures in the Data Structures category.


Task

Create a sum data type:

A sum data type is a data structure used to hold a value that could take on several different, but fixed, types. Only one of the types can be in use at any one time.

Sum data types are considered an algebraic data type and are also known as tagged union, variant, variant record, choice type, discriminated union, disjoint union or coproduct.

Related task
See also




ALGOL 68

Translation of: OCaml

Algol 68's UNION MODE allows the definition of items which can have different types. <lang algol68>MODE LEAF = INT; MODE NODE = STRUCT( TREE left, TREE right ); MODE TREE = UNION( VOID, LEAF, REF NODE );

TREE t1 = LOC NODE := ( LEAF( 1 ), LOC NODE := ( LEAF( 2 ), LEAF( 3 ) ) );</lang>

Note that assignment/initialisation of UNION items is just of a matter of specifying the assigned/initial value, as above; however to use the value requires a CASE clause, such as in the example below (which would print "node", given the above declarations).

<lang algol68>CASE t1

 IN (REF NODE n): print( ( "node",     newline ) )
  , (    LEAF l): print( ( "leaf ", l, newline ) )
  , (    VOID  ): print( ( "empty",    newline ) )

ESAC</lang>

Go

Go doesn't natively support sum types, though it's not difficult to create one (albeit verbosely) as the following example shows.

Normally, the IPAddr type (and associated types/methods) would be placed in a separate package so its 'v' field couldn't be accessed directly by code outside that package. However here, for convenience, we place it in the 'main' package. <lang go>package main

import (

   "errors"
   "fmt"

)

type (

   IpAddr struct{ v interface{} }
   Ipv4   = [4]uint8
   Ipv6   = string

)

var zero = Ipv4{}

func NewIpAddr(v interface{}) (*IpAddr, error) {

   switch v.(type) {
   case Ipv4, Ipv6:
       return &IpAddr{v}, nil
   default:
       err := errors.New("Type of value must either be Ipv4 or Ipv6.")
       return nil, err
   }

}

func (ip *IpAddr) V4() (Ipv4, error) {

   switch ip.v.(type) {
   case Ipv4:
       return ip.v.(Ipv4), nil
   default:
       err := errors.New("IpAddr instance doesn't currently hold an Ipv4.")
       return zero, err
   }

}

func (ip *IpAddr) SetV4(v Ipv4) {

   ip.v = v

}

func (ip *IpAddr) V6() (Ipv6, error) {

   switch ip.v.(type) {
   case Ipv6:
       return ip.v.(Ipv6), nil
   default:
       err := errors.New("IpAddr instance doesn't currently hold an Ipv6.")
       return "", err
   }

}

func (ip *IpAddr) SetV6(v Ipv6) {

   ip.v = v

}

func check(err error) {

   if err != nil {
       fmt.Println(err)
   }

}

func main() {

   v4 := Ipv4{127, 0, 0, 1}
   ip, _ := NewIpAddr(v4)
   home, _ := ip.V4()
   fmt.Println(home)
   v6 := "::1"
   ip.SetV6(v6)
   loopback, _ := ip.V6()
   fmt.Println(loopback)
   _, err := ip.V4()
   check(err)
   rubbish := 6
   ip, err = NewIpAddr(rubbish)
   check(err)

}</lang>

Output:
[127 0 0 1]
::1
IpAddr instance doesn't currently hold an Ipv4.
Type of value must either be Ipv4 or Ipv6.

OCaml

<lang ocaml>type tree = Empty

         | Leaf of int
         | Node of tree * tree

let t1 = Node (Leaf 1, Node (Leaf 2, Leaf 3))</lang>

REXX

The REXX language is untyped,   it is up to the program to decide if it's valid and how to deal with an invalid structure. <lang rexx>/*REXX pgm snipette validates a specific type of data structure, an IP v4 address (list)*/ ip= 127 0 0 1 if val_ipv4(ip) then say 'valid IPV4 type: ' ip

                else say '***error***  invalid IPV4 type: '    ip

...

exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ val_ipv4: procedure; parse arg $; if words($)\==4 | arg()\==1 then return 0

           do j=1  for 4;   _=word($, j);    #=datatype(_, 'W');    L= length(_)
           if verify(_, 0123456789)\==0  |  \#  | _<0  |  _>255  |  L>3  then return 0
           end   /*j*/
         return 1                               /*returns true (1) if valid, 0 if not. */</lang>


Rust

<lang rust>enum IpAddr {

   V4(u8, u8, u8, u8),
   V6(String),

}

let home = IpAddr::V4(127, 0, 0, 1);

let loopback = IpAddr::V6(String::from("::1"));</lang>

zkl

zkl is untyped - it is up to the container to decide if it wants to deal with a type or not. <lang zkl>ip:=List(127,0,0,1); addrs:=Dictionary("ip",ip);</lang> <lang zkl>class Addr{

  fcn init(addr){
     var ip = addr;
     if(not List.isType(addr)) throw(Exception.TypeError);
  }

} ip:=Addr(List(127,0,0,1)); Addr(127,0,0,1); // TypeError : Invalid type Addr(List("abc")); // doesn't fail, would need more error checking ip.ip=L(192,168,1,1); // this doesn't type check either</lang>