Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
5
Task/Associative-array-Creation/00-META.yaml
Normal file
5
Task/Associative-array-Creation/00-META.yaml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category:
|
||||
- Data Structures
|
||||
from: http://rosettacode.org/wiki/Associative_array/Creation
|
||||
note: Basic language learning
|
||||
12
Task/Associative-array-Creation/00-TASK.txt
Normal file
12
Task/Associative-array-Creation/00-TASK.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
;Task:
|
||||
The goal is to create an [[associative array]] (also known as a dictionary, map, or hash).
|
||||
|
||||
|
||||
Related tasks:
|
||||
* [[Associative arrays/Iteration]]
|
||||
* [[Hash from two arrays]]
|
||||
|
||||
|
||||
{{Template:See also lists}}
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
V dict = [‘key1’ = 1, ‘key2’ = 2]
|
||||
V value2 = dict[‘key2’]
|
||||
|
|
@ -0,0 +1 @@
|
|||
{ "one" : 1, "two" : "bad" }
|
||||
|
|
@ -0,0 +1 @@
|
|||
m:new "one" 1 m:! "two" "bad" m:!
|
||||
|
|
@ -0,0 +1,395 @@
|
|||
/* ARM assembly AARCH64 Raspberry PI 3B or android 64 bits */
|
||||
/* program hashmap64.s */
|
||||
|
||||
/*******************************************/
|
||||
/* Constantes file */
|
||||
/*******************************************/
|
||||
/* for this file see task include a file in language AArch64 assembly*/
|
||||
.include "../includeConstantesARM64.inc"
|
||||
.equ MAXI, 10
|
||||
.equ HEAPSIZE,20000
|
||||
.equ LIMIT, 10 // key characters number for compute hash
|
||||
.equ COEFF, 80 // filling rate 80 = 80%
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/* Structures */
|
||||
/********************************************/
|
||||
/* structure hashMap */
|
||||
.struct 0
|
||||
hash_count: // stored values counter
|
||||
.struct hash_count + 8
|
||||
hash_key: // key
|
||||
.struct hash_key + (8 * MAXI)
|
||||
hash_data: // data
|
||||
.struct hash_data + (8 * MAXI)
|
||||
hash_fin:
|
||||
/*********************************/
|
||||
/* Initialized data */
|
||||
/*********************************/
|
||||
.data
|
||||
szMessFin: .asciz "End program.\n"
|
||||
szCarriageReturn: .asciz "\n"
|
||||
szMessNoP: .asciz "Key not found !!!\n"
|
||||
szKey1: .asciz "one"
|
||||
szData1: .asciz "Ceret"
|
||||
szKey2: .asciz "two"
|
||||
szData2: .asciz "Maureillas"
|
||||
szKey3: .asciz "three"
|
||||
szData3: .asciz "Le Perthus"
|
||||
szKey4: .asciz "four"
|
||||
szData4: .asciz "Le Boulou"
|
||||
|
||||
.align 4
|
||||
iptZoneHeap: .quad sZoneHeap // start heap address
|
||||
iptZoneHeapEnd: .quad sZoneHeap + HEAPSIZE // end heap address
|
||||
/*********************************/
|
||||
/* UnInitialized data */
|
||||
/*********************************/
|
||||
.bss
|
||||
tbHashMap1: .skip hash_fin // hashmap
|
||||
sZoneHeap: .skip HEAPSIZE // heap
|
||||
/*********************************/
|
||||
/* code section */
|
||||
/*********************************/
|
||||
.text
|
||||
.global main
|
||||
main: // entry of program
|
||||
|
||||
ldr x0,qAdrtbHashMap1
|
||||
bl hashInit // init hashmap
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey1 // store key one
|
||||
ldr x2,qAdrszData1
|
||||
bl hashInsert
|
||||
cmp x0,#0 // error ?
|
||||
bne 100f
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey2 // store key two
|
||||
ldr x2,qAdrszData2
|
||||
bl hashInsert
|
||||
cmp x0,#0
|
||||
bne 100f
|
||||
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey3 // store key three
|
||||
ldr x2,qAdrszData3
|
||||
bl hashInsert
|
||||
cmp x0,#0
|
||||
bne 100f
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey4 // store key four
|
||||
ldr x2,qAdrszData4
|
||||
bl hashInsert
|
||||
cmp x0,#0
|
||||
bne 100f
|
||||
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey2 // remove key two
|
||||
bl hashRemoveKey
|
||||
cmp x0,#0
|
||||
bne 100f
|
||||
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey1 // search key one
|
||||
bl searchKey
|
||||
cmp x0,#-1
|
||||
beq 1f
|
||||
bl affichageMess
|
||||
ldr x0,qAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 2f
|
||||
1:
|
||||
ldr x0,qAdrszMessNoP
|
||||
bl affichageMess
|
||||
2:
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey2 // search key two
|
||||
bl searchKey
|
||||
cmp x0,#-1
|
||||
beq 3f
|
||||
bl affichageMess
|
||||
ldr x0,qAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 4f
|
||||
3:
|
||||
ldr x0,qAdrszMessNoP
|
||||
bl affichageMess
|
||||
4:
|
||||
ldr x0,qAdrtbHashMap1
|
||||
ldr x1,qAdrszKey4 // search key four
|
||||
bl searchKey
|
||||
cmp x0,#-1
|
||||
beq 5f
|
||||
bl affichageMess
|
||||
ldr x0,qAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 6f
|
||||
5:
|
||||
ldr x0,qAdrszMessNoP
|
||||
bl affichageMess
|
||||
6:
|
||||
ldr x0,qAdrszMessFin
|
||||
bl affichageMess
|
||||
|
||||
100: // standard end of the program
|
||||
mov x0, #0 // return code
|
||||
mov x8, #EXIT // request to exit program
|
||||
svc #0 // perform the system call
|
||||
|
||||
qAdrszCarriageReturn: .quad szCarriageReturn
|
||||
qAdrszMessFin: .quad szMessFin
|
||||
qAdrtbHashMap1: .quad tbHashMap1
|
||||
qAdrszKey1: .quad szKey1
|
||||
qAdrszData1: .quad szData1
|
||||
qAdrszKey2: .quad szKey2
|
||||
qAdrszData2: .quad szData2
|
||||
qAdrszKey3: .quad szKey3
|
||||
qAdrszData3: .quad szData3
|
||||
qAdrszKey4: .quad szKey4
|
||||
qAdrszData4: .quad szData4
|
||||
qAdrszMessNoP: .quad szMessNoP
|
||||
/***************************************************/
|
||||
/* init hashMap */
|
||||
/***************************************************/
|
||||
// x0 contains address to hashMap
|
||||
hashInit:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
mov x1,#0
|
||||
mov x2,#0
|
||||
str x2,[x0,#hash_count] // init counter
|
||||
add x0,x0,#hash_key // start zone key/value
|
||||
1:
|
||||
lsl x3,x1,#3
|
||||
add x3,x3,x0
|
||||
str x2,[x3,#hash_key]
|
||||
str x2,[x3,#hash_data]
|
||||
add x1,x1,#1
|
||||
cmp x1,#MAXI
|
||||
blt 1b
|
||||
100:
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
/***************************************************/
|
||||
/* insert key/datas */
|
||||
/***************************************************/
|
||||
// x0 contains address to hashMap
|
||||
// x1 contains address to key
|
||||
// x2 contains address to datas
|
||||
hashInsert:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
stp x4,x5,[sp,-16]! // save registres
|
||||
stp x6,x7,[sp,-16]! // save registres
|
||||
mov x6,x0 // save address
|
||||
bl hashIndex // search void key or identical key
|
||||
cmp x0,#0 // error ?
|
||||
blt 100f
|
||||
|
||||
ldr x3,qAdriptZoneHeap
|
||||
ldr x3,[x3]
|
||||
ldr x7,qAdriptZoneHeapEnd
|
||||
ldr x7,[x7]
|
||||
sub x7,x7,#50
|
||||
lsl x0,x0,#3 // 8 bytes
|
||||
add x5,x6,#hash_key // start zone key/value
|
||||
ldr x4,[x5,x0]
|
||||
cmp x4,#0 // key already stored ?
|
||||
bne 1f
|
||||
ldr x4,[x6,#hash_count] // no -> increment counter
|
||||
add x4,x4,#1
|
||||
cmp x4,#(MAXI * COEFF / 100)
|
||||
bge 98f
|
||||
str x4,[x6,#hash_count]
|
||||
1:
|
||||
str x3,[x5,x0] // store heap key address in hashmap
|
||||
mov x4,#0
|
||||
2: // copy key loop in heap
|
||||
ldrb w5,[x1,x4]
|
||||
strb w5,[x3,x4]
|
||||
cmp w5,#0
|
||||
add x4,x4,#1
|
||||
bne 2b
|
||||
add x3,x3,x4
|
||||
cmp x3,x7
|
||||
bge 99f
|
||||
add x1,x6,#hash_data
|
||||
str x3,[x1,x0] // store heap data address in hashmap
|
||||
mov x4,#0
|
||||
3: // copy data loop in heap
|
||||
ldrb w5,[x2,x4]
|
||||
strb w5,[x3,x4]
|
||||
cmp w5,#0
|
||||
add x4,x4,#1
|
||||
bne 3b
|
||||
add x3,x3,x4
|
||||
cmp x3,x7
|
||||
bge 99f
|
||||
ldr x0,qAdriptZoneHeap
|
||||
str x3,[x0] // new heap address
|
||||
|
||||
mov x0,#0 // insertion OK
|
||||
b 100f
|
||||
98: // error hashmap
|
||||
adr x0,szMessErrInd
|
||||
bl affichageMess
|
||||
mov x0,#-1
|
||||
b 100f
|
||||
99: // error heap
|
||||
adr x0,szMessErrHeap
|
||||
bl affichageMess
|
||||
mov x0,#-1
|
||||
100:
|
||||
ldp x6,x7,[sp],16 // restaur des 2 registres
|
||||
ldp x4,x5,[sp],16 // restaur des 2 registres
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
szMessErrInd: .asciz "Error : HashMap size Filling rate Maxi !!\n"
|
||||
szMessErrHeap: .asciz "Error : Heap size Maxi !!\n"
|
||||
.align 4
|
||||
qAdriptZoneHeap: .quad iptZoneHeap
|
||||
qAdriptZoneHeapEnd: .quad iptZoneHeapEnd
|
||||
/***************************************************/
|
||||
/* search void index in hashmap */
|
||||
/***************************************************/
|
||||
// x0 contains hashMap address
|
||||
// x1 contains key address
|
||||
hashIndex:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
stp x4,x5,[sp,-16]! // save registres
|
||||
add x4,x0,#hash_key
|
||||
mov x2,#0 // index
|
||||
mov x3,#0 // characters sum
|
||||
1: // loop to compute characters sum
|
||||
ldrb w0,[x1,x2]
|
||||
cmp w0,#0 // string end ?
|
||||
beq 2f
|
||||
add x3,x3,x0 // add to sum
|
||||
add x2,x2,#1
|
||||
cmp x2,#LIMIT
|
||||
blt 1b
|
||||
2:
|
||||
mov x5,x1 // save key address
|
||||
mov x0,x3
|
||||
mov x1,#MAXI
|
||||
udiv x2,x0,x1
|
||||
msub x3,x2,x1,x0 // compute remainder -> x3
|
||||
mov x1,x5 // key address
|
||||
|
||||
3:
|
||||
ldr x0,[x4,x3,lsl #3] // loak key for computed index
|
||||
cmp x0,#0 // void key ?
|
||||
beq 4f
|
||||
bl comparStrings // identical key ?
|
||||
cmp x0,#0
|
||||
beq 4f // yes
|
||||
add x3,x3,#1 // no search next void key
|
||||
cmp x3,#MAXI // maxi ?
|
||||
csel x3,xzr,x3,ge // restart to index 0
|
||||
b 3b
|
||||
4:
|
||||
mov x0,x3 // return index void array or key equal
|
||||
100:
|
||||
ldp x4,x5,[sp],16 // restaur des 2 registres
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
|
||||
/***************************************************/
|
||||
/* search key in hashmap */
|
||||
/***************************************************/
|
||||
// x0 contains hash map address
|
||||
// x1 contains key address
|
||||
searchKey:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
mov x2,x0
|
||||
bl hashIndex
|
||||
lsl x0,x0,#3
|
||||
add x1,x0,#hash_key
|
||||
ldr x1,[x2,x1]
|
||||
cmp x1,#0
|
||||
beq 2f
|
||||
add x1,x0,#hash_data
|
||||
ldr x0,[x2,x1]
|
||||
b 100f
|
||||
2:
|
||||
mov x0,#-1
|
||||
100:
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
/***************************************************/
|
||||
/* remove key in hashmap */
|
||||
/***************************************************/
|
||||
// x0 contains hash map address
|
||||
// x1 contains key address
|
||||
hashRemoveKey:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
mov x2,x0
|
||||
bl hashIndex
|
||||
lsl x0,x0,#3
|
||||
add x1,x0,#hash_key
|
||||
ldr x3,[x2,x1]
|
||||
cmp x3,#0
|
||||
beq 2f
|
||||
str xzr,[x2,x1] // raz key address
|
||||
add x1,x0,#hash_data
|
||||
str xzr,[x2,x1] // raz datas address
|
||||
mov x0,0
|
||||
b 100f
|
||||
2:
|
||||
adr x0,szMessErrRemove
|
||||
bl affichageMess
|
||||
mov x0,#-1
|
||||
100:
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
szMessErrRemove: .asciz "\033[31mError remove key !!\033[0m\n"
|
||||
.align 4
|
||||
/************************************/
|
||||
/* Strings case sensitive comparisons */
|
||||
/************************************/
|
||||
/* x0 et x1 contains the address of strings */
|
||||
/* return 0 in x0 if equals */
|
||||
/* return -1 if string x0 < string x1 */
|
||||
/* return 1 if string x0 > string x1 */
|
||||
comparStrings:
|
||||
stp x1,lr,[sp,-16]! // save registres
|
||||
stp x2,x3,[sp,-16]! // save registres
|
||||
stp x4,x5,[sp,-16]! // save registres
|
||||
mov x2,#0 // characters counter
|
||||
1:
|
||||
ldrb w3,[x0,x2] // byte string 1
|
||||
ldrb w4,[x1,x2] // byte string 2
|
||||
cmp w3,w4
|
||||
blt 2f
|
||||
bgt 3f
|
||||
cmp w3,#0 // 0 end string ?
|
||||
beq 4f
|
||||
add x2,x2,#1 // else add 1 in counter
|
||||
b 1b // and loop
|
||||
2:
|
||||
mov x0,#-1 // smaller
|
||||
b 100f
|
||||
3:
|
||||
mov x0,#1 // greather
|
||||
b 100f
|
||||
4:
|
||||
mov x0,#0 // equals
|
||||
100:
|
||||
ldp x4,x5,[sp],16 // restaur des 2 registres
|
||||
ldp x2,x3,[sp],16 // restaur des 2 registres
|
||||
ldp x1,lr,[sp],16 // restaur des 2 registres
|
||||
ret
|
||||
/********************************************************/
|
||||
/* File Include fonctions */
|
||||
/********************************************************/
|
||||
/* for this file see task include a file in language AArch64 assembly */
|
||||
.include "../includeARM64.inc"
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
main:(
|
||||
|
||||
MODE COLOR = BITS;
|
||||
FORMAT color repr = $"16r"16r6d$;
|
||||
|
||||
# This is an associative array which maps strings to ints #
|
||||
MODE ITEM = STRUCT(STRING key, COLOR value);
|
||||
REF[]ITEM color map items := LOC[0]ITEM;
|
||||
|
||||
PROC color map find = (STRING color)REF COLOR:(
|
||||
REF COLOR out;
|
||||
# linear search! #
|
||||
FOR index FROM LWB key OF color map items TO UPB key OF color map items DO
|
||||
IF color = key OF color map items[index] THEN
|
||||
out := value OF color map items[index]; GO TO found
|
||||
FI
|
||||
OD;
|
||||
NIL EXIT
|
||||
found:
|
||||
out
|
||||
);
|
||||
|
||||
PROC color map = (STRING color)REF COLOR:(
|
||||
REF COLOR out = color map find(color);
|
||||
IF out :=: REF COLOR(NIL) THEN # extend color map array #
|
||||
HEAP[UPB key OF color map items + 1]ITEM color map append;
|
||||
color map append[:UPB key OF color map items] := color map items;
|
||||
color map items := color map append;
|
||||
value OF (color map items[UPB value OF color map items] := (color, 16r000000)) # black #
|
||||
ELSE
|
||||
out
|
||||
FI
|
||||
);
|
||||
|
||||
# First, populate it with some values #
|
||||
color map("red") := 16rff0000;
|
||||
color map("green") := 16r00ff00;
|
||||
color map("blue") := 16r0000ff;
|
||||
color map("my favourite color") := 16r00ffff;
|
||||
|
||||
# then, get some values out #
|
||||
COLOR color := color map("green"); # color gets 16r00ff00 #
|
||||
color := color map("black"); # accessing unassigned values assigns them to 16r0 #
|
||||
|
||||
# get some value out without accidentally inserting new ones #
|
||||
REF COLOR value = color map find("green");
|
||||
IF value :=: REF COLOR(NIL) THEN
|
||||
put(stand error, ("color not found!", new line))
|
||||
ELSE
|
||||
printf(($"green: "f(color repr)l$, value))
|
||||
FI;
|
||||
|
||||
# Now I changed my mind about my favourite color, so change it #
|
||||
color map("my favourite color") := 16r337733;
|
||||
|
||||
# print out all defined colors #
|
||||
FOR index FROM LWB color map items TO UPB color map items DO
|
||||
ITEM item = color map items[index];
|
||||
putf(stand error, ($"color map("""g""") = "f(color repr)l$, item))
|
||||
OD;
|
||||
|
||||
FORMAT fmt;
|
||||
FORMAT comma sep = $"("n(UPB color map items-1)(f(fmt)", ")f(fmt)")"$;
|
||||
|
||||
fmt := $""""g""""$;
|
||||
printf(($g$,"keys: ", comma sep, key OF color map items, $l$));
|
||||
fmt := color repr;
|
||||
printf(($g$,"values: ", comma sep, value OF color map items, $l$))
|
||||
|
||||
)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
⍝ Create a namespace ("hash")
|
||||
X←⎕NS ⍬
|
||||
|
||||
⍝ Assign some names
|
||||
X.this←'that'
|
||||
X.foo←88
|
||||
|
||||
⍝ Access the names
|
||||
X.this
|
||||
that
|
||||
|
||||
⍝ Or do it the array way
|
||||
X.(foo this)
|
||||
88 that
|
||||
|
||||
⍝ Namespaces are first class objects
|
||||
sales ← ⎕NS ⍬
|
||||
sales.(prices quantities) ← (100 98.4 103.4 110.16) (10 12 8 10)
|
||||
sales.(revenue ← prices +.× quantities)
|
||||
sales.revenue
|
||||
4109.6
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
⍝ Assign some names
|
||||
X.this←'that'
|
||||
X.foo←88
|
||||
|
||||
⍝ Access the names
|
||||
X.this
|
||||
that
|
||||
|
||||
⍝ ..or access via 'array index' syntax
|
||||
X['this']
|
||||
that
|
||||
|
||||
⍝ Or do it the array way
|
||||
X.(foo)
|
||||
88
|
||||
|
||||
⍝ GNU APL does not support multiple assoc. array indices however
|
||||
X.(foo this)
|
||||
VALUE ERROR
|
||||
X.(foo this)
|
||||
^
|
||||
|
||||
(sales.prices sales.quantities) ← (100 98.4 103.4 110.16) (10 12 8 10)
|
||||
sales.revenue ← sales.prices +.× sales.quantities
|
||||
sales.revenue
|
||||
4109.6
|
||||
|
|
@ -0,0 +1,371 @@
|
|||
/* ARM assembly Raspberry PI or android 32 bits */
|
||||
/* program hashmap.s */
|
||||
|
||||
/* */
|
||||
|
||||
/* REMARK 1 : this program use routines in a include file
|
||||
see task Include a file language arm assembly
|
||||
for the routine affichageMess conversion10
|
||||
see at end of this program the instruction include */
|
||||
/* for constantes see task include a file in arm assembly */
|
||||
/************************************/
|
||||
/* Constantes */
|
||||
/************************************/
|
||||
.include "../constantes.inc"
|
||||
.equ MAXI, 10 @ size hashmap
|
||||
.equ HEAPSIZE,20000
|
||||
.equ LIMIT, 10 @ key characters number for compute index
|
||||
.equ COEFF, 80 @ filling rate 80 = 80%
|
||||
|
||||
|
||||
/*******************************************/
|
||||
/* Structures */
|
||||
/********************************************/
|
||||
/* structure hashMap */
|
||||
.struct 0
|
||||
hash_count: // stored values counter
|
||||
.struct hash_count + 4
|
||||
hash_key: // key
|
||||
.struct hash_key + (4 * MAXI)
|
||||
hash_data: // data
|
||||
.struct hash_data + (4 * MAXI)
|
||||
hash_fin:
|
||||
/*********************************/
|
||||
/* Initialized data */
|
||||
/*********************************/
|
||||
.data
|
||||
szMessFin: .asciz "End program.\n"
|
||||
szCarriageReturn: .asciz "\n"
|
||||
szMessNoP: .asciz "Key not found !!!\n"
|
||||
szKey1: .asciz "one"
|
||||
szData1: .asciz "Ceret"
|
||||
szKey2: .asciz "two"
|
||||
szData2: .asciz "Maureillas"
|
||||
szKey3: .asciz "three"
|
||||
szData3: .asciz "Le Perthus"
|
||||
szKey4: .asciz "four"
|
||||
szData4: .asciz "Le Boulou"
|
||||
|
||||
.align 4
|
||||
iptZoneHeap: .int sZoneHeap // start heap address
|
||||
iptZoneHeapEnd: .int sZoneHeap + HEAPSIZE // end heap address
|
||||
/*********************************/
|
||||
/* UnInitialized data */
|
||||
/*********************************/
|
||||
.bss
|
||||
//sZoneConv: .skip 24
|
||||
tbHashMap1: .skip hash_fin @ hashmap
|
||||
sZoneHeap: .skip HEAPSIZE @ heap
|
||||
/*********************************/
|
||||
/* code section */
|
||||
/*********************************/
|
||||
.text
|
||||
.global main
|
||||
main: @ entry of program
|
||||
|
||||
ldr r0,iAdrtbHashMap1
|
||||
bl hashInit @ init hashmap
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey1 @ store key one
|
||||
ldr r2,iAdrszData1
|
||||
bl hashInsert
|
||||
cmp r0,#0 @ error ?
|
||||
bne 100f
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey2 @ store key two
|
||||
ldr r2,iAdrszData2
|
||||
bl hashInsert
|
||||
cmp r0,#0
|
||||
bne 100f
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey3 @ store key three
|
||||
ldr r2,iAdrszData3
|
||||
bl hashInsert
|
||||
cmp r0,#0
|
||||
bne 100f
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey4 @ store key four
|
||||
ldr r2,iAdrszData4
|
||||
bl hashInsert
|
||||
cmp r0,#0
|
||||
bne 100f
|
||||
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey2 @ remove key two
|
||||
bl hashRemoveKey
|
||||
cmp r0,#0
|
||||
bne 100f
|
||||
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey1 @ search key
|
||||
bl searchKey
|
||||
cmp r0,#-1
|
||||
beq 1f
|
||||
bl affichageMess
|
||||
ldr r0,iAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 2f
|
||||
1:
|
||||
ldr r0,iAdrszMessNoP
|
||||
bl affichageMess
|
||||
2:
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey2
|
||||
bl searchKey
|
||||
cmp r0,#-1
|
||||
beq 3f
|
||||
bl affichageMess
|
||||
ldr r0,iAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 4f
|
||||
3:
|
||||
ldr r0,iAdrszMessNoP
|
||||
bl affichageMess
|
||||
4:
|
||||
ldr r0,iAdrtbHashMap1
|
||||
ldr r1,iAdrszKey4
|
||||
bl searchKey
|
||||
cmp r0,#-1
|
||||
beq 5f
|
||||
bl affichageMess
|
||||
ldr r0,iAdrszCarriageReturn
|
||||
bl affichageMess
|
||||
b 6f
|
||||
5:
|
||||
ldr r0,iAdrszMessNoP
|
||||
bl affichageMess
|
||||
6:
|
||||
ldr r0,iAdrszMessFin
|
||||
bl affichageMess
|
||||
|
||||
100: @ standard end of the program
|
||||
mov r0, #0 @ return code
|
||||
mov r7, #EXIT @ request to exit program
|
||||
svc #0 @ perform the system call
|
||||
|
||||
iAdrszCarriageReturn: .int szCarriageReturn
|
||||
iAdrszMessFin: .int szMessFin
|
||||
iAdrtbHashMap1: .int tbHashMap1
|
||||
iAdrszKey1: .int szKey1
|
||||
iAdrszData1: .int szData1
|
||||
iAdrszKey2: .int szKey2
|
||||
iAdrszData2: .int szData2
|
||||
iAdrszKey3: .int szKey3
|
||||
iAdrszData3: .int szData3
|
||||
iAdrszKey4: .int szKey4
|
||||
iAdrszData4: .int szData4
|
||||
iAdrszMessNoP: .int szMessNoP
|
||||
/***************************************************/
|
||||
/* init hashMap */
|
||||
/***************************************************/
|
||||
// r0 contains address to hashMap
|
||||
hashInit:
|
||||
push {r1-r3,lr} @ save registers
|
||||
mov r1,#0
|
||||
mov r2,#0
|
||||
str r2,[r0,#hash_count] @ init counter
|
||||
add r0,r0,#hash_key @ start zone key/value
|
||||
1:
|
||||
lsl r3,r1,#3
|
||||
add r3,r3,r0
|
||||
str r2,[r3,#hash_key]
|
||||
str r2,[r3,#hash_data]
|
||||
add r1,r1,#1
|
||||
cmp r1,#MAXI
|
||||
blt 1b
|
||||
100:
|
||||
pop {r1-r3,pc} @ restaur registers
|
||||
/***************************************************/
|
||||
/* insert key/datas */
|
||||
/***************************************************/
|
||||
// r0 contains address to hashMap
|
||||
// r1 contains address to key
|
||||
// r2 contains address to datas
|
||||
hashInsert:
|
||||
push {r1-r8,lr} @ save registers
|
||||
mov r6,r0 @ save address
|
||||
bl hashIndex @ search void key or identical key
|
||||
cmp r0,#0 @ error ?
|
||||
blt 100f
|
||||
|
||||
ldr r3,iAdriptZoneHeap
|
||||
ldr r3,[r3]
|
||||
ldr r8,iAdriptZoneHeapEnd
|
||||
ldr r8,[r8]
|
||||
sub r8,r8,#50
|
||||
lsl r0,r0,#2 @ 4 bytes
|
||||
add r7,r6,#hash_key @ start zone key/value
|
||||
ldr r4,[r7,r0]
|
||||
cmp r4,#0 @ key already stored ?
|
||||
bne 1f
|
||||
ldr r4,[r6,#hash_count] @ no -> increment counter
|
||||
add r4,r4,#1
|
||||
cmp r4,#(MAXI * COEFF / 100)
|
||||
bge 98f
|
||||
str r4,[r6,#hash_count]
|
||||
1:
|
||||
str r3,[r7,r0]
|
||||
mov r4,#0
|
||||
2: @ copy key loop in heap
|
||||
ldrb r5,[r1,r4]
|
||||
strb r5,[r3,r4]
|
||||
cmp r5,#0
|
||||
add r4,r4,#1
|
||||
bne 2b
|
||||
add r3,r3,r4
|
||||
cmp r3,r8
|
||||
bge 99f
|
||||
add r7,r6,#hash_data
|
||||
str r3,[r7,r0]
|
||||
mov r4,#0
|
||||
3: @ copy data loop in heap
|
||||
ldrb r5,[r2,r4]
|
||||
strb r5,[r3,r4]
|
||||
cmp r5,#0
|
||||
add r4,r4,#1
|
||||
bne 3b
|
||||
add r3,r3,r4
|
||||
cmp r3,r8
|
||||
bge 99f
|
||||
ldr r0,iAdriptZoneHeap
|
||||
str r3,[r0] @ new heap address
|
||||
|
||||
mov r0,#0 @ insertion OK
|
||||
b 100f
|
||||
98: @ error hashmap
|
||||
adr r0,szMessErrInd
|
||||
bl affichageMess
|
||||
mov r0,#-1
|
||||
b 100f
|
||||
99: @ error heap
|
||||
adr r0,szMessErrHeap
|
||||
bl affichageMess
|
||||
mov r0,#-1
|
||||
100:
|
||||
pop {r1-r8,lr} @ restaur registers
|
||||
bx lr @ return
|
||||
szMessErrInd: .asciz "Error : HashMap size Filling rate Maxi !!\n"
|
||||
szMessErrHeap: .asciz "Error : Heap size Maxi !!\n"
|
||||
.align 4
|
||||
iAdriptZoneHeap: .int iptZoneHeap
|
||||
iAdriptZoneHeapEnd: .int iptZoneHeapEnd
|
||||
/***************************************************/
|
||||
/* search void index in hashmap */
|
||||
/***************************************************/
|
||||
// r0 contains hashMap address
|
||||
// r1 contains key address
|
||||
hashIndex:
|
||||
push {r1-r4,lr} @ save registers
|
||||
add r4,r0,#hash_key
|
||||
mov r2,#0 @ index
|
||||
mov r3,#0 @ characters sum
|
||||
1: @ loop to compute characters sum
|
||||
ldrb r0,[r1,r2]
|
||||
cmp r0,#0 @ string end ?
|
||||
beq 2f
|
||||
add r3,r3,r0 @ add to sum
|
||||
add r2,r2,#1
|
||||
cmp r2,#LIMIT
|
||||
blt 1b
|
||||
2:
|
||||
mov r5,r1 @ save key address
|
||||
mov r0,r3
|
||||
mov r1,#MAXI
|
||||
bl division @ compute remainder -> r3
|
||||
mov r1,r5 @ key address
|
||||
|
||||
3:
|
||||
ldr r0,[r4,r3,lsl #2] @ loak key for computed index
|
||||
cmp r0,#0 @ void key ?
|
||||
beq 4f
|
||||
bl comparStrings @ identical key ?
|
||||
cmp r0,#0
|
||||
beq 4f @ yes
|
||||
add r3,r3,#1 @ no search next void key
|
||||
cmp r3,#MAXI @ maxi ?
|
||||
movge r3,#0 @ restart to index 0
|
||||
b 3b
|
||||
4:
|
||||
mov r0,r3 @ return index void array or key equal
|
||||
100:
|
||||
pop {r1-r4,pc} @ restaur registers
|
||||
|
||||
/***************************************************/
|
||||
/* search key in hashmap */
|
||||
/***************************************************/
|
||||
// r0 contains hash map address
|
||||
// r1 contains key address
|
||||
searchKey:
|
||||
push {r1-r2,lr} @ save registers
|
||||
mov r2,r0
|
||||
bl hashIndex
|
||||
lsl r0,r0,#2
|
||||
add r1,r0,#hash_key
|
||||
ldr r1,[r2,r1]
|
||||
cmp r1,#0
|
||||
moveq r0,#-1
|
||||
beq 100f
|
||||
add r1,r0,#hash_data
|
||||
ldr r0,[r2,r1]
|
||||
100:
|
||||
pop {r1-r2,pc} @ restaur registers
|
||||
/***************************************************/
|
||||
/* remove key in hashmap */
|
||||
/***************************************************/
|
||||
// r0 contains hash map address
|
||||
// r1 contains key address
|
||||
hashRemoveKey: @ INFO: hashRemoveKey
|
||||
push {r1-r3,lr} @ save registers
|
||||
mov r2,r0
|
||||
bl hashIndex
|
||||
lsl r0,r0,#2
|
||||
add r1,r0,#hash_key
|
||||
ldr r3,[r2,r1]
|
||||
cmp r3,#0
|
||||
beq 2f
|
||||
add r3,r2,r1
|
||||
mov r1,#0 @ raz key address
|
||||
str r1,[r3]
|
||||
add r1,r0,#hash_data
|
||||
add r3,r2,r1
|
||||
mov r1,#0
|
||||
str r1,[r3] @ raz datas address
|
||||
mov r0,#0
|
||||
b 100f
|
||||
2:
|
||||
adr r0,szMessErrRemove
|
||||
bl affichageMess
|
||||
mov r0,#-1
|
||||
100:
|
||||
pop {r1-r3,pc} @ restaur registers
|
||||
szMessErrRemove: .asciz "\033[31mError remove key !!\033[0m\n"
|
||||
.align 4
|
||||
/************************************/
|
||||
/* Strings case sensitive comparisons */
|
||||
/************************************/
|
||||
/* r0 et r1 contains the address of strings */
|
||||
/* return 0 in r0 if equals */
|
||||
/* return -1 if string r0 < string r1 */
|
||||
/* return 1 if string r0 > string r1 */
|
||||
comparStrings:
|
||||
push {r1-r4} @ save des registres
|
||||
mov r2,#0 @ characters counter
|
||||
1:
|
||||
ldrb r3,[r0,r2] @ byte string 1
|
||||
ldrb r4,[r1,r2] @ byte string 2
|
||||
cmp r3,r4
|
||||
movlt r0,#-1 @ smaller
|
||||
movgt r0,#1 @ greather
|
||||
bne 100f @ not equals
|
||||
cmp r3,#0 @ 0 end string ?
|
||||
moveq r0,#0 @ equals
|
||||
beq 100f @ end string
|
||||
add r2,r2,#1 @ else add 1 in counter
|
||||
b 1b @ and loop
|
||||
100:
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
/***************************************************/
|
||||
/* ROUTINES INCLUDE */
|
||||
/***************************************************/
|
||||
.include "../affichage.inc"
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
(*------------------------------------------------------------------*)
|
||||
|
||||
#define ATS_DYNLOADFLAG 0
|
||||
|
||||
#include "share/atspre_staload.hats"
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* Interface *)
|
||||
|
||||
(* You can put the interface in a .sats file. You will have to remove
|
||||
the word "extern". *)
|
||||
|
||||
typedef alist_t (key_t : t@ype+,
|
||||
data_t : t@ype+,
|
||||
size : int) =
|
||||
list (@(key_t, data_t), size)
|
||||
typedef alist_t (key_t : t@ype+,
|
||||
data_t : t@ype+) =
|
||||
[size : int]
|
||||
alist_t (key_t, data_t, size)
|
||||
|
||||
extern prfun
|
||||
lemma_alist_t_param :
|
||||
{size : int} {key_t : t@ype} {data_t : t@ype}
|
||||
alist_t (key_t, data_t, size) -<prf> [0 <= size] void
|
||||
|
||||
extern fun {key_t : t@ype} (* Implement key equality with this. *)
|
||||
alist_t$key_eq : (key_t, key_t) -<> bool
|
||||
|
||||
(* alist_t_nil: create an empty association list. *)
|
||||
extern fun
|
||||
alist_t_nil :
|
||||
{key_t : t@ype} {data_t : t@ype}
|
||||
() -<> alist_t (key_t, data_t, 0)
|
||||
|
||||
(* alist_t_set: add an association, deleting old associations with an
|
||||
equal key. *)
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
alist_t_set {size : int}
|
||||
(alst : alist_t (key_t, data_t, size),
|
||||
key : key_t,
|
||||
data : data_t) :<>
|
||||
[sz : int | 1 <= sz]
|
||||
alist_t (key_t, data_t, sz)
|
||||
|
||||
(* alist_t_get: find an association and return its data, if
|
||||
present. *)
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
alist_t_get {size : int}
|
||||
(alst : alist_t (key_t, data_t, size),
|
||||
key : key_t) :<>
|
||||
Option data_t
|
||||
|
||||
(* alist_t_delete: delete all associations with key. *)
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
alist_t_delete {size : int}
|
||||
(alst : alist_t (key_t, data_t, size),
|
||||
key : key_t ) :<>
|
||||
[sz : int | 0 <= sz]
|
||||
alist_t (key_t, data_t, sz)
|
||||
|
||||
(* alist_t_make_pairs_generator: make a closure that returns
|
||||
the association pairs, one by one. This is a form of iterator.
|
||||
Analogous generators can be made for the keys or data values
|
||||
alone. *)
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
alist_t_make_pairs_generator
|
||||
{size : int}
|
||||
(alst : alist_t (key_t, data_t, size)) :<!wrt>
|
||||
() -<cloref,!refwrt> Option @(key_t, data_t)
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* Implementation *)
|
||||
|
||||
#define NIL list_nil ()
|
||||
#define :: list_cons
|
||||
|
||||
primplement
|
||||
lemma_alist_t_param alst =
|
||||
lemma_list_param alst
|
||||
|
||||
implement
|
||||
alist_t_nil () =
|
||||
NIL
|
||||
|
||||
implement {key_t} {data_t}
|
||||
alist_t_set (alst, key, data) =
|
||||
@(key, data) :: alist_t_delete (alst, key)
|
||||
|
||||
implement {key_t} {data_t}
|
||||
alist_t_get (alst, key) =
|
||||
let
|
||||
fun
|
||||
loop {n : nat}
|
||||
.<n>. (* <-- proof of termination *)
|
||||
(lst : alist_t (key_t, data_t, n)) :<>
|
||||
Option data_t =
|
||||
case+ lst of
|
||||
| NIL => None ()
|
||||
| head :: tail =>
|
||||
if alist_t$key_eq (key, head.0) then
|
||||
Some (head.1)
|
||||
else
|
||||
loop tail
|
||||
|
||||
prval _ = lemma_alist_t_param alst
|
||||
in
|
||||
loop alst
|
||||
end
|
||||
|
||||
implement {key_t} {data_t}
|
||||
alist_t_delete (alst, key) =
|
||||
let
|
||||
fun
|
||||
delete {n : nat}
|
||||
.<n>. (* <-- proof of termination *)
|
||||
(lst : alist_t (key_t, data_t, n)) :<>
|
||||
[m : nat] alist_t (key_t, data_t, m) =
|
||||
(* This implementation is *not* tail recursive, but has the
|
||||
minor advantage of preserving the order of entries without
|
||||
doing a lot of work. *)
|
||||
case+ lst of
|
||||
| NIL => lst
|
||||
| head :: tail =>
|
||||
if alist_t$key_eq (key, head.0) then
|
||||
delete tail
|
||||
else
|
||||
head :: delete tail
|
||||
|
||||
prval _ = lemma_alist_t_param alst
|
||||
in
|
||||
delete alst
|
||||
end
|
||||
|
||||
implement {key_t} {data_t}
|
||||
alist_t_make_pairs_generator alst =
|
||||
let
|
||||
typedef alist_t = [sz : int] alist_t (key_t, data_t, sz)
|
||||
|
||||
val alst_ref = ref alst
|
||||
|
||||
(* Cast the ref to a pointer so it can be enclosed in the
|
||||
closure. *)
|
||||
val alst_ptr = $UNSAFE.castvwtp0{ptr} alst_ref
|
||||
in
|
||||
lam () =>
|
||||
let
|
||||
val alst_ref = $UNSAFE.castvwtp0{ref alist_t} alst_ptr
|
||||
in
|
||||
case+ !alst_ref of
|
||||
| NIL => None ()
|
||||
| head :: tail =>
|
||||
begin
|
||||
!alst_ref := tail;
|
||||
(* For a keys generator, change the following line to
|
||||
"Some (head.0)"; for a data values generator, change
|
||||
it to "Some (head.1)". *)
|
||||
Some head
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* Demonstration program *)
|
||||
|
||||
implement
|
||||
alist_t$key_eq<string> (s, t) =
|
||||
s = t
|
||||
|
||||
typedef s2i_alist_t = alist_t (string, int)
|
||||
|
||||
fn
|
||||
s2i_alist_t_set (map : s2i_alist_t,
|
||||
key : string,
|
||||
data : int) :<> s2i_alist_t =
|
||||
alist_t_set<string><int> (map, key, data)
|
||||
|
||||
fn
|
||||
s2i_alist_t_set_ref (map : &s2i_alist_t >> _,
|
||||
key : string,
|
||||
data : int) :<!wrt> void =
|
||||
(* Update a reference to a persistent alist. *)
|
||||
map := s2i_alist_t_set (map, key, data)
|
||||
|
||||
fn
|
||||
s2i_alist_t_get (map : s2i_alist_t,
|
||||
key : string) :<> Option int =
|
||||
alist_t_get<string><int> (map, key)
|
||||
|
||||
extern fun {} (* {} = a template without template parameters *)
|
||||
s2i_alist_t_get_dflt$dflt :<> () -> int
|
||||
fn {} (* {} = a template without template parameters *)
|
||||
s2i_alist_t_get_dflt (map : s2i_alist_t,
|
||||
key : string) : int =
|
||||
case+ s2i_alist_t_get (map, key) of
|
||||
| Some x => x
|
||||
| None () => s2i_alist_t_get_dflt$dflt<> ()
|
||||
|
||||
overload [] with s2i_alist_t_set_ref
|
||||
overload [] with s2i_alist_t_get_dflt
|
||||
|
||||
implement
|
||||
main0 () =
|
||||
let
|
||||
implement s2i_alist_t_get_dflt$dflt<> () = 0
|
||||
var map = alist_t_nil ()
|
||||
var gen : () -<cloref1> @(string, int)
|
||||
var pair : Option @(string, int)
|
||||
in
|
||||
map["one"] := 1;
|
||||
map["two"] := 2;
|
||||
map["three"] := 3;
|
||||
println! ("map[\"one\"] = ", map["one"]);
|
||||
println! ("map[\"two\"] = ", map["two"]);
|
||||
println! ("map[\"three\"] = ", map["three"]);
|
||||
println! ("map[\"four\"] = ", map["four"]);
|
||||
gen := alist_t_make_pairs_generator<string><int> map;
|
||||
for (pair := gen (); option_is_some pair; pair := gen ())
|
||||
println! (pair)
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
|
@ -0,0 +1,579 @@
|
|||
(*------------------------------------------------------------------*)
|
||||
|
||||
#define ATS_DYNLOADFLAG 0
|
||||
|
||||
#include "share/atspre_staload.hats"
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* String hashing using XXH3_64bits from the xxHash suite. *)
|
||||
|
||||
#define ATS_EXTERN_PREFIX "hashmaps_postiats_"
|
||||
|
||||
%{^ /* Embedded C code. */
|
||||
|
||||
#include <xxhash.h>
|
||||
|
||||
ATSinline() atstype_uint64
|
||||
hashmaps_postiats_mem_hash (atstype_ptr data, atstype_size len)
|
||||
{
|
||||
return (atstype_uint64) XXH3_64bits (data, len);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
extern fn mem_hash : (ptr, size_t) -<> uint64 = "mac#%"
|
||||
|
||||
fn
|
||||
string_hash (s : string) :<> uint64 =
|
||||
let
|
||||
val len = string_length s
|
||||
in
|
||||
mem_hash ($UNSAFE.cast{ptr} s, len)
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* A trimmed down version of the AVL trees from the AVL Tree task. *)
|
||||
|
||||
datatype bal_t =
|
||||
| bal_minus1
|
||||
| bal_zero
|
||||
| bal_plus1
|
||||
|
||||
datatype avl_t (key_t : t@ype+,
|
||||
data_t : t@ype+,
|
||||
size : int) =
|
||||
| avl_t_nil (key_t, data_t, 0)
|
||||
| {size_L, size_R : nat}
|
||||
avl_t_cons (key_t, data_t, size_L + size_R + 1) of
|
||||
(key_t, data_t, bal_t,
|
||||
avl_t (key_t, data_t, size_L),
|
||||
avl_t (key_t, data_t, size_R))
|
||||
typedef avl_t (key_t : t@ype+,
|
||||
data_t : t@ype+) =
|
||||
[size : int] avl_t (key_t, data_t, size)
|
||||
|
||||
extern fun {key_t : t@ype}
|
||||
avl_t$compare (u : key_t, v : key_t) :<> int
|
||||
|
||||
#define NIL avl_t_nil ()
|
||||
#define CONS avl_t_cons
|
||||
#define LNIL list_nil ()
|
||||
#define :: list_cons
|
||||
#define F false
|
||||
#define T true
|
||||
|
||||
typedef fixbal_t = bool
|
||||
|
||||
prfn
|
||||
lemma_avl_t_param {key_t : t@ype} {data_t : t@ype} {size : int}
|
||||
(avl : avl_t (key_t, data_t, size)) :<prf>
|
||||
[0 <= size] void =
|
||||
case+ avl of NIL => () | CONS _ => ()
|
||||
|
||||
fn {}
|
||||
minus_neg_bal (bal : bal_t) :<> bal_t =
|
||||
case+ bal of
|
||||
| bal_minus1 () => bal_plus1
|
||||
| _ => bal_zero ()
|
||||
|
||||
fn {}
|
||||
minus_pos_bal (bal : bal_t) :<> bal_t =
|
||||
case+ bal of
|
||||
| bal_plus1 () => bal_minus1
|
||||
| _ => bal_zero ()
|
||||
|
||||
fn
|
||||
avl_t_is_empty {key_t : t@ype} {data_t : t@ype} {size : int}
|
||||
(avl : avl_t (key_t, data_t, size)) :<>
|
||||
[b : bool | b == (size == 0)] bool b =
|
||||
case+ avl of
|
||||
| NIL => T
|
||||
| CONS _ => F
|
||||
|
||||
fn
|
||||
avl_t_isnot_empty {key_t : t@ype} {data_t : t@ype} {size : int}
|
||||
(avl : avl_t (key_t, data_t, size)) :<>
|
||||
[b : bool | b == (size <> 0)] bool b =
|
||||
~avl_t_is_empty avl
|
||||
|
||||
fn {key_t : t@ype} {data_t : t@ype}
|
||||
avl_t_search_ref {size : int}
|
||||
(avl : avl_t (key_t, data_t, size),
|
||||
key : key_t,
|
||||
data : &data_t? >> opt (data_t, found),
|
||||
found : &bool? >> bool found) :<!wrt>
|
||||
#[found : bool] void =
|
||||
let
|
||||
fun
|
||||
search (p : avl_t (key_t, data_t),
|
||||
data : &data_t? >> opt (data_t, found),
|
||||
found : &bool? >> bool found) :<!wrt,!ntm>
|
||||
#[found : bool] void =
|
||||
case+ p of
|
||||
| NIL =>
|
||||
{
|
||||
prval _ = opt_none {data_t} data
|
||||
val _ = found := F
|
||||
}
|
||||
| CONS (k, d, _, left, right) =>
|
||||
begin
|
||||
case+ avl_t$compare<key_t> (key, k) of
|
||||
| cmp when cmp < 0 => search (left, data, found)
|
||||
| cmp when cmp > 0 => search (right, data, found)
|
||||
| _ =>
|
||||
{
|
||||
val _ = data := d
|
||||
prval _ = opt_some {data_t} data
|
||||
val _ = found := T
|
||||
}
|
||||
end
|
||||
in
|
||||
$effmask_ntm search (avl, data, found)
|
||||
end
|
||||
|
||||
fn {key_t : t@ype} {data_t : t@ype}
|
||||
avl_t_search_opt {size : int}
|
||||
(avl : avl_t (key_t, data_t, size),
|
||||
key : key_t) :<>
|
||||
Option (data_t) =
|
||||
let
|
||||
var data : data_t?
|
||||
var found : bool?
|
||||
val _ = $effmask_wrt avl_t_search_ref (avl, key, data, found)
|
||||
in
|
||||
if found then
|
||||
let
|
||||
prval _ = opt_unsome data
|
||||
in
|
||||
Some {data_t} data
|
||||
end
|
||||
else
|
||||
let
|
||||
prval _ = opt_unnone data
|
||||
in
|
||||
None {data_t} ()
|
||||
end
|
||||
end
|
||||
|
||||
fn {key_t : t@ype} {data_t : t@ype}
|
||||
avl_t_insert_or_replace {size : int}
|
||||
(avl : avl_t (key_t, data_t, size),
|
||||
key : key_t,
|
||||
data : data_t) :<>
|
||||
[sz : pos] (avl_t (key_t, data_t, sz), bool) =
|
||||
let
|
||||
fun
|
||||
search {size : nat}
|
||||
(p : avl_t (key_t, data_t, size),
|
||||
fixbal : fixbal_t,
|
||||
found : bool) :<!ntm>
|
||||
[sz : pos]
|
||||
(avl_t (key_t, data_t, sz), fixbal_t, bool) =
|
||||
case+ p of
|
||||
| NIL => (CONS (key, data, bal_zero, NIL, NIL), T, F)
|
||||
| CONS (k, d, bal, left, right) =>
|
||||
case+ avl_t$compare<key_t> (key, k) of
|
||||
| cmp when cmp < 0 =>
|
||||
let
|
||||
val (p1, fixbal, found) = search (left, fixbal, found)
|
||||
in
|
||||
case+ (fixbal, bal) of
|
||||
| (F, _) => (CONS (k, d, bal, p1, right), F, found)
|
||||
| (T, bal_plus1 ()) =>
|
||||
(CONS (k, d, bal_zero (), p1, right), F, found)
|
||||
| (T, bal_zero ()) =>
|
||||
(CONS (k, d, bal_minus1 (), p1, right), fixbal, found)
|
||||
| (T, bal_minus1 ()) =>
|
||||
let
|
||||
val+ CONS (k1, d1, bal1, left1, right1) = p1
|
||||
in
|
||||
case+ bal1 of
|
||||
| bal_minus1 () =>
|
||||
let
|
||||
val q = CONS (k, d, bal_zero (), right1, right)
|
||||
val q1 = CONS (k1, d1, bal_zero (), left1, q)
|
||||
in
|
||||
(q1, F, found)
|
||||
end
|
||||
| _ =>
|
||||
let
|
||||
val p2 = right1
|
||||
val- CONS (k2, d2, bal2, left2, right2) = p2
|
||||
val q = CONS (k, d, minus_neg_bal bal2,
|
||||
right2, right)
|
||||
val q1 = CONS (k1, d1, minus_pos_bal bal2,
|
||||
left1, left2)
|
||||
val q2 = CONS (k2, d2, bal_zero (), q1, q)
|
||||
in
|
||||
(q2, F, found)
|
||||
end
|
||||
end
|
||||
end
|
||||
| cmp when cmp > 0 =>
|
||||
let
|
||||
val (p1, fixbal, found) = search (right, fixbal, found)
|
||||
in
|
||||
case+ (fixbal, bal) of
|
||||
| (F, _) => (CONS (k, d, bal, left, p1), F, found)
|
||||
| (T, bal_minus1 ()) =>
|
||||
(CONS (k, d, bal_zero (), left, p1), F, found)
|
||||
| (T, bal_zero ()) =>
|
||||
(CONS (k, d, bal_plus1 (), left, p1), fixbal, found)
|
||||
| (T, bal_plus1 ()) =>
|
||||
let
|
||||
val+ CONS (k1, d1, bal1, left1, right1) = p1
|
||||
in
|
||||
case+ bal1 of
|
||||
| bal_plus1 () =>
|
||||
let
|
||||
val q = CONS (k, d, bal_zero (), left, left1)
|
||||
val q1 = CONS (k1, d1, bal_zero (), q, right1)
|
||||
in
|
||||
(q1, F, found)
|
||||
end
|
||||
| _ =>
|
||||
let
|
||||
val p2 = left1
|
||||
val- CONS (k2, d2, bal2, left2, right2) = p2
|
||||
val q = CONS (k, d, minus_pos_bal bal2,
|
||||
left, left2)
|
||||
val q1 = CONS (k1, d1, minus_neg_bal bal2,
|
||||
right2, right1)
|
||||
val q2 = CONS (k2, d2, bal_zero (), q, q1)
|
||||
in
|
||||
(q2, F, found)
|
||||
end
|
||||
end
|
||||
end
|
||||
| _ => (CONS (key, data, bal, left, right), F, T)
|
||||
in
|
||||
if avl_t_is_empty avl then
|
||||
(CONS (key, data, bal_zero, NIL, NIL), F)
|
||||
else
|
||||
let
|
||||
prval _ = lemma_avl_t_param avl
|
||||
val (avl, _, found) = $effmask_ntm search (avl, F, F)
|
||||
in
|
||||
(avl, found)
|
||||
end
|
||||
end
|
||||
|
||||
fn {key_t : t@ype} {data_t : t@ype}
|
||||
avl_t_insert {size : int}
|
||||
(avl : avl_t (key_t, data_t, size),
|
||||
key : key_t,
|
||||
data : data_t) :<>
|
||||
[sz : pos] avl_t (key_t, data_t, sz) =
|
||||
(avl_t_insert_or_replace<key_t><data_t> (avl, key, data)).0
|
||||
|
||||
fun {key_t : t@ype} {data_t : t@ype}
|
||||
push_all_the_way_left (stack : List (avl_t (key_t, data_t)),
|
||||
p : avl_t (key_t, data_t)) :
|
||||
List0 (avl_t (key_t, data_t)) =
|
||||
let
|
||||
prval _ = lemma_list_param stack
|
||||
in
|
||||
case+ p of
|
||||
| NIL => stack
|
||||
| CONS (_, _, _, left, _) =>
|
||||
push_all_the_way_left (p :: stack, left)
|
||||
end
|
||||
|
||||
fun {key_t : t@ype} {data_t : t@ype}
|
||||
update_generator_stack (stack : List (avl_t (key_t, data_t)),
|
||||
right : avl_t (key_t, data_t)) :
|
||||
List0 (avl_t (key_t, data_t)) =
|
||||
let
|
||||
prval _ = lemma_list_param stack
|
||||
in
|
||||
if avl_t_is_empty right then
|
||||
stack
|
||||
else
|
||||
push_all_the_way_left<key_t><data_t> (stack, right)
|
||||
end
|
||||
|
||||
fn {key_t : t@ype} {data_t : t@ype}
|
||||
avl_t_make_data_generator {size : int}
|
||||
(avl : avl_t (key_t, data_t, size)) :
|
||||
() -<cloref1> Option data_t =
|
||||
let
|
||||
typedef avl_t = avl_t (key_t, data_t)
|
||||
|
||||
val stack = push_all_the_way_left<key_t><data_t> (LNIL, avl)
|
||||
val stack_ref = ref stack
|
||||
|
||||
(* Cast stack_ref to its (otherwise untyped) pointer, so it can be
|
||||
enclosed within ‘generate’. *)
|
||||
val p_stack_ref = $UNSAFE.castvwtp0{ptr} stack_ref
|
||||
|
||||
fun
|
||||
generate () :<cloref1> Option data_t =
|
||||
let
|
||||
(* Restore the type information for stack_ref. *)
|
||||
val stack_ref =
|
||||
$UNSAFE.castvwtp0{ref (List avl_t)} p_stack_ref
|
||||
|
||||
var stack : List0 avl_t = !stack_ref
|
||||
var retval : Option data_t
|
||||
in
|
||||
begin
|
||||
case+ stack of
|
||||
| LNIL => retval := None ()
|
||||
| p :: tail =>
|
||||
let
|
||||
val- CONS (_, d, _, left, right) = p
|
||||
in
|
||||
retval := Some d;
|
||||
stack :=
|
||||
update_generator_stack<key_t><data_t> (tail, right)
|
||||
end
|
||||
end;
|
||||
!stack_ref := stack;
|
||||
retval
|
||||
end
|
||||
in
|
||||
generate
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* Hashmaps implemented with AVL trees and association lists. *)
|
||||
|
||||
(* The interface - - - - - - - - - - - - - - - - - - - - - - - - - *)
|
||||
|
||||
typedef hashmap_t (key_t : t@ype+,
|
||||
data_t : t@ype+) =
|
||||
avl_t (uint64, List1 @(key_t, data_t))
|
||||
|
||||
(* For simplicity, let us support only 64-bit hashes. *)
|
||||
extern fun {key_t : t@ype} (* Implement a hash function with this. *)
|
||||
hashmap_t$hashfunc : key_t -<> uint64
|
||||
|
||||
extern fun {key_t : t@ype} (* Implement key equality with this. *)
|
||||
hashmap_t$key_eq : (key_t, key_t) -<> bool
|
||||
|
||||
extern fun
|
||||
hashmap_t_nil :
|
||||
{key_t : t@ype} {data_t : t@ype}
|
||||
() -<> hashmap_t (key_t, data_t)
|
||||
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
hashmap_t_set (map : hashmap_t (key_t, data_t),
|
||||
key : key_t,
|
||||
data : data_t) :<>
|
||||
hashmap_t (key_t, data_t)
|
||||
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
hashmap_t_get (map : hashmap_t (key_t, data_t),
|
||||
key : key_t) :<>
|
||||
Option data_t
|
||||
|
||||
(*
|
||||
Notes:
|
||||
* Generators for hashmap_t produce their output in unspecified
|
||||
order.
|
||||
* Generators for keys and data values can be made by analogy to
|
||||
the following generator for pairs, or can be written in terms
|
||||
of the generator for pairs. (The former approach seems better;
|
||||
it might copy less data.)
|
||||
*)
|
||||
extern fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
hashmap_t_make_pairs_generator (map : hashmap_t (key_t, data_t)) :
|
||||
() -<cloref1> Option @(key_t, data_t)
|
||||
|
||||
(* The implementation - - - - - - - - - - - - - - - - - - - - - - - *)
|
||||
|
||||
implement
|
||||
avl_t$compare<uint64> (u, v) =
|
||||
if u < v then
|
||||
~1
|
||||
else if v < u then
|
||||
1
|
||||
else
|
||||
0
|
||||
|
||||
implement
|
||||
hashmap_t_nil () =
|
||||
avl_t_nil ()
|
||||
|
||||
fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
remove_association {n : nat} .<n>.
|
||||
(lst : list (@(key_t, data_t), n),
|
||||
key : key_t) :<>
|
||||
List0 @(key_t, data_t) =
|
||||
(* This implementation uses linear stack space, and so presumes the
|
||||
list is not extremely long. It preserves the order of the list,
|
||||
although doing so is not necessary for persistence. (You might
|
||||
wish to think about that, taking into account that the
|
||||
order of traversal through a hashmap usually is considered
|
||||
"unspecified".) *)
|
||||
case+ lst of
|
||||
| list_nil () => lst
|
||||
| list_cons (head, tail) =>
|
||||
if hashmap_t$key_eq<key_t> (key, head.0) then
|
||||
tail (* Assume there is only one match. *)
|
||||
else
|
||||
list_cons (head, remove_association (tail, key))
|
||||
|
||||
fun {key_t : t@ype}
|
||||
{data_t : t@ype}
|
||||
find_association {n : nat} .<n>.
|
||||
(lst : list (@(key_t, data_t), n),
|
||||
key : key_t) :<>
|
||||
List0 @(key_t, data_t) =
|
||||
(* This implementation is tail recursive. It will not build up the
|
||||
stack. *)
|
||||
case+ lst of
|
||||
| list_nil () => lst
|
||||
| list_cons (head, tail) =>
|
||||
if hashmap_t$key_eq<key_t> (key, head.0) then
|
||||
lst
|
||||
else
|
||||
find_association (tail, key)
|
||||
|
||||
implement {key_t} {data_t}
|
||||
hashmap_t_set (map, key, data) =
|
||||
let
|
||||
typedef lst_t = List1 @(key_t, data_t) (* Association list. *)
|
||||
val hash = hashmap_t$hashfunc<key_t> key
|
||||
val lst_opt = avl_t_search_opt<uint64><lst_t> (map, hash)
|
||||
val lst =
|
||||
begin
|
||||
case+ lst_opt of
|
||||
| Some lst =>
|
||||
(* There is already an association list for this hash value.
|
||||
Remove any association already in it. *)
|
||||
remove_association<key_t><data_t> (lst, key)
|
||||
| None () =>
|
||||
(* Start a new association list. *)
|
||||
list_nil ()
|
||||
end : List0 @(key_t, data_t)
|
||||
val lst = list_cons (@(key, data), lst)
|
||||
in
|
||||
avl_t_insert<uint64><lst_t> (map, hash, lst)
|
||||
end
|
||||
|
||||
implement {key_t} {data_t}
|
||||
hashmap_t_get (map, key) =
|
||||
let
|
||||
typedef lst_t = List1 @(key_t, data_t) (* Association list. *)
|
||||
val hash = hashmap_t$hashfunc<key_t> key
|
||||
val lst_opt = avl_t_search_opt<uint64><lst_t> (map, hash)
|
||||
in
|
||||
case+ lst_opt of
|
||||
| None () => None{data_t} ()
|
||||
| Some lst =>
|
||||
begin
|
||||
case+ find_association<key_t><data_t> (lst, key) of
|
||||
| list_nil () => None{data_t} ()
|
||||
| list_cons (@(_, data), _) => Some{data_t} data
|
||||
end
|
||||
end
|
||||
|
||||
implement {key_t} {data_t}
|
||||
hashmap_t_make_pairs_generator (map) =
|
||||
let
|
||||
typedef pair_t = @(key_t, data_t)
|
||||
typedef lst_t = List1 pair_t
|
||||
typedef lst_t_0 = List0 pair_t
|
||||
|
||||
val avl_gen = avl_t_make_data_generator<uint64><lst_t> (map)
|
||||
|
||||
val current_alist_ref : ref lst_t_0 = ref (list_nil ())
|
||||
val current_alist_ptr =
|
||||
$UNSAFE.castvwtp0{ptr} current_alist_ref
|
||||
in
|
||||
lam () =>
|
||||
let
|
||||
val current_alist_ref =
|
||||
$UNSAFE.castvwtp0{ref lst_t_0} current_alist_ptr
|
||||
in
|
||||
case+ !current_alist_ref of
|
||||
| list_nil () =>
|
||||
begin
|
||||
case+ avl_gen () of
|
||||
| None () => None ()
|
||||
| Some lst =>
|
||||
begin
|
||||
case+ lst of
|
||||
| list_cons (head, tail) =>
|
||||
begin
|
||||
!current_alist_ref := tail;
|
||||
Some head
|
||||
end
|
||||
end
|
||||
end
|
||||
| list_cons (head, tail) =>
|
||||
begin
|
||||
!current_alist_ref := tail;
|
||||
Some head
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
implement
|
||||
hashmap_t$hashfunc<string> (s) =
|
||||
string_hash s
|
||||
|
||||
implement
|
||||
hashmap_t$key_eq<string> (s, t) =
|
||||
s = t
|
||||
|
||||
typedef s2i_hashmap_t = hashmap_t (string, int)
|
||||
|
||||
fn
|
||||
s2i_hashmap_t_set (map : s2i_hashmap_t,
|
||||
key : string,
|
||||
data : int) :<> s2i_hashmap_t =
|
||||
hashmap_t_set<string><int> (map, key, data)
|
||||
|
||||
fn
|
||||
s2i_hashmap_t_set_ref (map : &s2i_hashmap_t >> _,
|
||||
key : string,
|
||||
data : int) :<!wrt> void =
|
||||
(* Update a reference to a persistent hashmap. *)
|
||||
map := s2i_hashmap_t_set (map, key, data)
|
||||
|
||||
fn
|
||||
s2i_hashmap_t_get (map : s2i_hashmap_t,
|
||||
key : string) :<> Option int =
|
||||
hashmap_t_get<string><int> (map, key)
|
||||
|
||||
extern fun {} (* {} = a template without template parameters *)
|
||||
s2i_hashmap_t_get_dflt$dflt :<> () -> int
|
||||
fn {} (* {} = a template without template parameters *)
|
||||
s2i_hashmap_t_get_dflt (map : s2i_hashmap_t,
|
||||
key : string) : int =
|
||||
case+ s2i_hashmap_t_get (map, key) of
|
||||
| Some x => x
|
||||
| None () => s2i_hashmap_t_get_dflt$dflt<> ()
|
||||
|
||||
overload [] with s2i_hashmap_t_set_ref
|
||||
overload [] with s2i_hashmap_t_get_dflt
|
||||
|
||||
implement
|
||||
main0 () =
|
||||
let
|
||||
implement s2i_hashmap_t_get_dflt$dflt<> () = 0
|
||||
var map = hashmap_t_nil ()
|
||||
var gen : () -<cloref1> @(string, int)
|
||||
var pair : Option @(string, int)
|
||||
in
|
||||
map["one"] := 1;
|
||||
map["two"] := 2;
|
||||
map["three"] := 3;
|
||||
println! ("map[\"one\"] = ", map["one"]);
|
||||
println! ("map[\"two\"] = ", map["two"]);
|
||||
println! ("map[\"three\"] = ", map["three"]);
|
||||
println! ("map[\"four\"] = ", map["four"]);
|
||||
gen := hashmap_t_make_pairs_generator<string><int> map;
|
||||
for (pair := gen (); option_is_some pair; pair := gen ())
|
||||
println! (pair)
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
BEGIN {
|
||||
a["red"] = 0xff0000
|
||||
a["green"] = 0x00ff00
|
||||
a["blue"] = 0x0000ff
|
||||
for (i in a) {
|
||||
printf "%8s %06x\n", i, a[i]
|
||||
}
|
||||
# deleting a key/value
|
||||
delete a["red"]
|
||||
for (i in a) {
|
||||
print i
|
||||
}
|
||||
# check if a key exists
|
||||
print ( "red" in a ) # print 0
|
||||
print ( "blue" in a ) # print 1
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
var map:Object = {key1: "value1", key2: "value2"};
|
||||
trace(map['key1']); // outputs "value1"
|
||||
|
||||
// Dot notation can also be used
|
||||
trace(map.key2); // outputs "value2"
|
||||
|
||||
// More keys and values can then be added
|
||||
map['key3'] = "value3";
|
||||
trace(map['key3']); // outputs "value3"
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
with Ada.Containers.Ordered_Maps;
|
||||
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
|
||||
with Ada.Text_IO;
|
||||
|
||||
procedure Associative_Array is
|
||||
|
||||
-- Instantiate the generic package Ada.Containers.Ordered_Maps
|
||||
|
||||
package Associative_Int is new Ada.Containers.Ordered_Maps(Unbounded_String, Integer);
|
||||
use Associative_Int;
|
||||
|
||||
Color_Map : Map;
|
||||
Color_Cursor : Cursor;
|
||||
Success : Boolean;
|
||||
Value : Integer;
|
||||
begin
|
||||
|
||||
-- Add values to the ordered map
|
||||
|
||||
Color_Map.Insert(To_Unbounded_String("Red"), 10, Color_Cursor, Success);
|
||||
Color_Map.Insert(To_Unbounded_String("Blue"), 20, Color_Cursor, Success);
|
||||
Color_Map.Insert(To_Unbounded_String("Yellow"), 5, Color_Cursor, Success);
|
||||
|
||||
-- retrieve values from the ordered map and print the value and key
|
||||
-- to the screen
|
||||
|
||||
Value := Color_Map.Element(To_Unbounded_String("Red"));
|
||||
Ada.Text_Io.Put_Line("Red:" & Integer'Image(Value));
|
||||
Value := Color_Map.Element(To_Unbounded_String("Blue"));
|
||||
Ada.Text_IO.Put_Line("Blue:" & Integer'Image(Value));
|
||||
Value := Color_Map.Element(To_Unbounded_String("Yellow"));
|
||||
Ada.Text_IO.Put_Line("Yellow:" & Integer'Image(Value));
|
||||
end Associative_Array;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
var names = {} // empty map
|
||||
names["foo"] = "bar"
|
||||
names[3] = 4
|
||||
|
||||
// initialized map
|
||||
var names2 = {"foo": bar, 3:4}
|
||||
|
||||
// lookup map
|
||||
var name = names["foo"]
|
||||
if (typeof(name) == "none") {
|
||||
println ("not found")
|
||||
} else {
|
||||
println (name)
|
||||
}
|
||||
|
||||
// remove from map
|
||||
delete names["foo"]
|
||||
|
|
@ -0,0 +1 @@
|
|||
record r;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
r_put(r, "A", 33); # an integer value
|
||||
r_put(r, "C", 2.5); # a real value
|
||||
r_put(r, "B", "associative"); # a string value
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Cannot / Do not need to instantiate the algorithm implementation (e.g, HashMap).
|
||||
Map<String, String> strMap = new Map<String, String>();
|
||||
strMap.put('a', 'aval');
|
||||
strMap.put('b', 'bval');
|
||||
|
||||
System.assert( strMap.containsKey('a') );
|
||||
System.assertEquals( 'bval', strMap.get('b') );
|
||||
// String keys are case-sensitive
|
||||
System.assert( !strMap.containsKey('A') );
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
Map<String, String> strMap = new Map<String, String>{
|
||||
'a' => 'aval',
|
||||
'b' => 'bval'
|
||||
};
|
||||
|
||||
System.assert( strMap.containsKey('a') );
|
||||
System.assertEquals( 'bval', strMap.get('b') );
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
; create a dictionary
|
||||
d: #[
|
||||
name: "john"
|
||||
surname: "doe"
|
||||
age: 34
|
||||
]
|
||||
|
||||
print d
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
associative_array := {key1: "value 1", "Key with spaces and non-alphanumeric characters !*+": 23}
|
||||
MsgBox % associative_array.key1
|
||||
. "`n" associative_array["Key with spaces and non-alphanumeric characters !*+"]
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
arrayX1 = first
|
||||
arrayX2 = second
|
||||
arrayX3 = foo
|
||||
arrayX4 = bar
|
||||
Loop, 4
|
||||
Msgbox % arrayX%A_Index%
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
; Associative arrays in AutoIt.
|
||||
; All the required functions are below the examples.
|
||||
|
||||
; Initialize an error handler to deal with any COM errors..
|
||||
global $oMyError = ObjEvent("AutoIt.Error", "AAError")
|
||||
|
||||
; first example, simple.
|
||||
global $simple
|
||||
|
||||
; Initialize your array ...
|
||||
AAInit($simple)
|
||||
|
||||
AAAdd($simple, "Appple", "fruit")
|
||||
AAAdd($simple, "Dog", "animal")
|
||||
AAAdd($simple, "Silicon", "tetravalent metalloid semiconductor")
|
||||
|
||||
ConsoleWrite("It is well-known that Silicon is a " & AAGetItem($simple, "Silicon") & "." & @CRLF)
|
||||
ConsoleWrite(@CRLF)
|
||||
|
||||
|
||||
; A more interesting example..
|
||||
|
||||
$ini_path = "AA_Test.ini"
|
||||
; Put this prefs section in your ini file..
|
||||
; [test]
|
||||
; foo=foo value
|
||||
; foo2=foo2 value
|
||||
; bar=bar value
|
||||
; bar2=bar2 value
|
||||
|
||||
|
||||
global $associative_array
|
||||
AAInit($associative_array)
|
||||
|
||||
; We are going to convert this 2D array into a cute associative array where we
|
||||
; can access the values by simply using their respective key names..
|
||||
$test_array = IniReadSection($ini_path, "test")
|
||||
|
||||
for $z = 1 to 2 ; do it twice, to show that the items are *really* there!
|
||||
for $i = 1 to $test_array[0][0]
|
||||
$key_name = $test_array[$i][0]
|
||||
ConsoleWrite("Adding '" & $key_name & "'.." & @CRLF)
|
||||
; key already exists in "$associative_array", use the pre-determined value..
|
||||
if AAExists($associative_array, $key_name) then
|
||||
$this_value = AAGetItem($associative_array, $key_name)
|
||||
ConsoleWrite("key_name ALREADY EXISTS! : =>" & $key_name & "<=" & @CRLF)
|
||||
else
|
||||
$this_value = $test_array[$i][1]
|
||||
; store left=right value pair in AA
|
||||
if $this_value then
|
||||
AAAdd($associative_array, $key_name, $this_value)
|
||||
endif
|
||||
endif
|
||||
next
|
||||
next
|
||||
|
||||
ConsoleWrite(@CRLF & "Array Count: =>" & AACount($associative_array) & "<=" & @CRLF)
|
||||
AAList($associative_array)
|
||||
|
||||
ConsoleWrite(@CRLF & "Removing 'foo'..")
|
||||
AARemove($associative_array, "foo")
|
||||
|
||||
ConsoleWrite(@CRLF & "Array Count: =>" & AACount($associative_array) & "<=" & @CRLF)
|
||||
AAList($associative_array)
|
||||
|
||||
|
||||
AAWipe($associative_array)
|
||||
|
||||
|
||||
; end
|
||||
|
||||
|
||||
|
||||
func AAInit(ByRef $dict_obj)
|
||||
$dict_obj = ObjCreate("Scripting.Dictionary")
|
||||
endfunc
|
||||
|
||||
; Adds a key and item pair to a Dictionary object..
|
||||
func AAAdd(ByRef $dict_obj, $key, $val)
|
||||
$dict_obj.Add($key, $val)
|
||||
If @error Then return SetError(1, 1, -1)
|
||||
endfunc
|
||||
|
||||
; Removes a key and item pair from a Dictionary object..
|
||||
func AARemove(ByRef $dict_obj, $key)
|
||||
$dict_obj.Remove($key)
|
||||
If @error Then return SetError(1, 1, -1)
|
||||
endfunc
|
||||
|
||||
; Returns true if a specified key exists in the associative array, false if not..
|
||||
func AAExists(ByRef $dict_obj, $key)
|
||||
return $dict_obj.Exists($key)
|
||||
endfunc
|
||||
|
||||
; Returns a value for a specified key name in the associative array..
|
||||
func AAGetItem(ByRef $dict_obj, $key)
|
||||
return $dict_obj.Item($key)
|
||||
endfunc
|
||||
|
||||
; Returns the total number of keys in the array..
|
||||
func AACount(ByRef $dict_obj)
|
||||
return $dict_obj.Count
|
||||
endfunc
|
||||
|
||||
; List all the "Key" > "Item" pairs in the array..
|
||||
func AAList(ByRef $dict_obj)
|
||||
ConsoleWrite("AAList: =>" & @CRLF)
|
||||
local $k = $dict_obj.Keys ; Get the keys
|
||||
; local $a = $dict_obj.Items ; Get the items (for reference)
|
||||
for $i = 0 to AACount($dict_obj) -1 ; Iterate the array
|
||||
ConsoleWrite($k[$i] & " ==> " & AAGetItem($dict_obj, $k[$i]) & @CRLF)
|
||||
next
|
||||
endfunc
|
||||
|
||||
; Wipe the array, obviously.
|
||||
func AAWipe(ByRef $dict_obj)
|
||||
$dict_obj.RemoveAll()
|
||||
endfunc
|
||||
|
||||
; Oh oh!
|
||||
func AAError()
|
||||
Local $err = $oMyError.number
|
||||
If $err = 0 Then $err = -1
|
||||
SetError($err) ; to check for after this function returns
|
||||
endfunc
|
||||
|
||||
;; End AA Functions.
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
global values$, keys$
|
||||
dim values$[1]
|
||||
dim keys$[1]
|
||||
|
||||
call updateKey("a","apple")
|
||||
call updateKey("b","banana")
|
||||
call updateKey("c","cucumber")
|
||||
|
||||
gosub show
|
||||
|
||||
print "I like to eat a " + getValue$("c") + " on my salad."
|
||||
|
||||
call deleteKey("b")
|
||||
call updateKey("c","carrot")
|
||||
call updateKey("e","endive")
|
||||
gosub show
|
||||
|
||||
end
|
||||
|
||||
show:
|
||||
for t = 0 to countKeys()-1
|
||||
print getKeyByIndex$(t) + " " + getValueByIndex$(t)
|
||||
next t
|
||||
print
|
||||
return
|
||||
|
||||
subroutine updateKey(key$, value$)
|
||||
# update or add an item
|
||||
i=findKey(key$)
|
||||
if i=-1 then
|
||||
i = freeKey()
|
||||
keys$[i] = key$
|
||||
end if
|
||||
values$[i] = value$
|
||||
end subroutine
|
||||
|
||||
subroutine deleteKey(key$)
|
||||
# delete by clearing the key
|
||||
i=findKey(key$)
|
||||
if i<>-1 then
|
||||
keys$[i] = ""
|
||||
end if
|
||||
end subroutine
|
||||
|
||||
function freeKey()
|
||||
# find index of a free element in the array
|
||||
for n = 0 to keys$[?]-1
|
||||
if keys$[n]="" then return n
|
||||
next n
|
||||
redim keys$[n+1]
|
||||
redim values$[n+1]
|
||||
return n
|
||||
end function
|
||||
|
||||
function findKey(key$)
|
||||
# return index or -1 if not found
|
||||
for n = 0 to keys$[?]-1
|
||||
if key$=keys$[n] then return n
|
||||
next n
|
||||
return -1
|
||||
end function
|
||||
|
||||
function getValue$(key$)
|
||||
# return a value by the key or "" if not existing
|
||||
i=findKey(key$)
|
||||
if i=-1 then
|
||||
return ""
|
||||
end if
|
||||
return values$[i]
|
||||
end function
|
||||
|
||||
function countKeys()
|
||||
# return number of items
|
||||
# remember to skip the empty keys (deleted ones)
|
||||
k = 0
|
||||
for n = 0 to keys$[?] -1
|
||||
if keys$[n]<>"" then k++
|
||||
next n
|
||||
return k
|
||||
end function
|
||||
|
||||
function getValueByIndex$(i)
|
||||
# get a value by the index
|
||||
# remember to skip the empty keys (deleted ones)
|
||||
k = 0
|
||||
for n = 0 to keys$[?] -1
|
||||
if keys$[n]<>"" then
|
||||
if k=i then return values$[k]
|
||||
k++
|
||||
endif
|
||||
next n
|
||||
return ""
|
||||
end function
|
||||
|
||||
function getKeyByIndex$(i)
|
||||
# get a key by the index
|
||||
# remember to skip the empty keys (deleted ones)
|
||||
k = 0
|
||||
for n = 0 to keys$[?] -1
|
||||
if keys$[n]<>"" then
|
||||
if k=i then return keys$[k]
|
||||
k++
|
||||
endif
|
||||
next n
|
||||
return ""
|
||||
end function
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
REM Store some values with their keys:
|
||||
PROCputdict(mydict$, "FF0000", "red")
|
||||
PROCputdict(mydict$, "00FF00", "green")
|
||||
PROCputdict(mydict$, "0000FF", "blue")
|
||||
|
||||
REM Retrieve some values using their keys:
|
||||
PRINT FNgetdict(mydict$, "green")
|
||||
PRINT FNgetdict(mydict$, "red")
|
||||
END
|
||||
|
||||
DEF PROCputdict(RETURN dict$, value$, key$)
|
||||
IF dict$ = "" dict$ = CHR$(0)
|
||||
dict$ += key$ + CHR$(1) + value$ + CHR$(0)
|
||||
ENDPROC
|
||||
|
||||
DEF FNgetdict(dict$, key$)
|
||||
LOCAL I%, J%
|
||||
I% = INSTR(dict$, CHR$(0) + key$ + CHR$(1))
|
||||
IF I% = 0 THEN = "" ELSE I% += LEN(key$) + 2
|
||||
J% = INSTR(dict$, CHR$(0), I%)
|
||||
= MID$(dict$, I%, J% - I%)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
DECLARE associative ASSOC STRING
|
||||
|
||||
associative("abc") = "first three"
|
||||
associative("xyz") = "last three"
|
||||
|
||||
PRINT associative("xyz")
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(("foo" 13)
|
||||
("bar" 42)
|
||||
("baz" 77)) ls2map !
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
::assocarrays.cmd
|
||||
@echo off
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
set array.dog=1
|
||||
set array.cat=2
|
||||
set array.wolf=3
|
||||
set array.cow=4
|
||||
for %%i in (dog cat wolf cow) do call :showit array.%%i !array.%%i!
|
||||
set c=-27
|
||||
call :mkarray sicko flu 5 measles 6 mumps 7 bromodrosis 8
|
||||
for %%i in (flu measles mumps bromodrosis) do call :showit "sicko^&%%i" !sicko^&%%i!
|
||||
endlocal
|
||||
goto :eof
|
||||
|
||||
:mkarray
|
||||
set %1^&%2=%3
|
||||
shift /2
|
||||
shift /2
|
||||
if "%2" neq "" goto :mkarray
|
||||
goto :eof
|
||||
|
||||
:showit
|
||||
echo %1 = %2
|
||||
goto :eof
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
new$hash:?myhash
|
||||
& (myhash..insert)$(title."Some title")
|
||||
& (myhash..insert)$(formula.a+b+x^7)
|
||||
& (myhash..insert)$(fruit.apples oranges kiwis)
|
||||
& (myhash..insert)$(meat.)
|
||||
& (myhash..insert)$(fruit.melons bananas)
|
||||
& out$(myhash..find)$fruit
|
||||
& (myhash..remove)$formula
|
||||
& (myhash..insert)$(formula.x^2+y^2)
|
||||
& out$(myhash..find)$formula;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
h = [:] #Empty hash
|
||||
|
||||
h[:a] = 1 #Assign value
|
||||
h[:b] = [1 2 3] #Assign another value
|
||||
|
||||
h2 = [a: 1, b: [1 2 3], 10 : "ten"] #Initialized hash
|
||||
|
||||
h2[:b][2] #Returns 3
|
||||
|
|
@ -0,0 +1 @@
|
|||
#include <map>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#include <map>
|
||||
#include <iostreams>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Create the map.
|
||||
std::map<int, double> exampleMap;
|
||||
|
||||
// Choose our key
|
||||
int myKey = 7;
|
||||
|
||||
// Choose our value
|
||||
double myValue = 3.14;
|
||||
|
||||
// Assign a value to the map with the specified key.
|
||||
exampleMap[myKey] = myValue;
|
||||
|
||||
// Retrieve the value
|
||||
double myRetrievedValue = exampleMap[myKey];
|
||||
|
||||
// Display our retrieved value.
|
||||
std::cout << myRetrievedValue << std::endl;
|
||||
|
||||
// main() must return 0 on success.
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
std::map<A, B> exampleMap
|
||||
|
|
@ -0,0 +1 @@
|
|||
std::map<int, double> exampleMap
|
||||
|
|
@ -0,0 +1 @@
|
|||
exampleMap[7] = 3.14
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
int myKey = 7;
|
||||
double myValue = 3.14;
|
||||
exampleMap[myKey] = myValue;
|
||||
|
|
@ -0,0 +1 @@
|
|||
exampleMap.insert(std::pair<int, double>(7,3.14));
|
||||
|
|
@ -0,0 +1 @@
|
|||
exampleMap.insert(std::make_pair(7,3.14));
|
||||
|
|
@ -0,0 +1 @@
|
|||
myValue = exampleMap[myKey]
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
double myValue = 0.0;
|
||||
std::map<int, double>::iterator myIterator = exampleMap.find(myKey);
|
||||
if(exampleMap.end() != myIterator)
|
||||
{
|
||||
// Return the value for that key.
|
||||
myValue = myIterator->second;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
System.Collections.HashTable map = new System.Collections.HashTable();
|
||||
map["key1"] = "foo";
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Dictionary<string, string> map = new Dictionary<string,string>();
|
||||
map[ "key1" ] = "foo";
|
||||
|
|
@ -0,0 +1 @@
|
|||
var map = new Dictionary<string, string> {{"key1", "foo"}};
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import ceylon.collection {
|
||||
|
||||
ArrayList,
|
||||
HashMap,
|
||||
naturalOrderTreeMap
|
||||
}
|
||||
|
||||
shared void run() {
|
||||
|
||||
// the easiest way is to use the map function to create
|
||||
// an immutable map
|
||||
value myMap = map {
|
||||
"foo" -> 5,
|
||||
"bar" -> 10,
|
||||
"baz" -> 15,
|
||||
"foo" -> 6 // by default the first "foo" will remain
|
||||
};
|
||||
|
||||
// or you can use the HashMap constructor to create
|
||||
// a mutable one
|
||||
value myOtherMap = HashMap {
|
||||
"foo"->"bar"
|
||||
};
|
||||
myOtherMap.put("baz", "baxx");
|
||||
|
||||
// there's also a sorted red/black tree map
|
||||
value myTreeMap = naturalOrderTreeMap {
|
||||
1 -> "won",
|
||||
2 -> "too",
|
||||
4 -> "fore"
|
||||
};
|
||||
for(num->homophone in myTreeMap) {
|
||||
print("``num`` is ``homophone``");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// arr is an array of string to int. any type can be used in both places.
|
||||
var keys: domain(string);
|
||||
var arr: [keys] int;
|
||||
|
||||
// keys can be added to a domain using +, new values will be initialized to the default value (0 for int)
|
||||
keys += "foo";
|
||||
keys += "bar";
|
||||
keys += "baz";
|
||||
|
||||
// array access via [] or ()
|
||||
arr["foo"] = 1;
|
||||
arr["bar"] = 4;
|
||||
arr("baz") = 6;
|
||||
|
||||
// write auto-formats domains and arrays
|
||||
writeln("Keys: ", keys);
|
||||
writeln("Values: ", arr);
|
||||
|
||||
// keys can be deleted using -
|
||||
keys -= "bar";
|
||||
|
||||
writeln("Keys: ", keys);
|
||||
writeln("Values: ", arr);
|
||||
|
||||
// chapel also supports array literals
|
||||
var arr2 = [ "John" => 3, "Pete" => 14 ];
|
||||
|
||||
writeln("arr2 keys: ", arr2.domain);
|
||||
writeln("arr2 values: ", arr2);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{:key "value"
|
||||
:key2 "value2"
|
||||
:key3 "value3"}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<cfset myHash = structNew()>
|
||||
<cfset myHash.key1 = "foo">
|
||||
<cfset myHash["key2"] = "bar">
|
||||
<cfset myHash.put("key3","java-style")>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
;; default :test is #'eql, which is suitable for numbers only,
|
||||
;; or for implementation identity for other types!
|
||||
;; Use #'equalp if you want case-insensitive keying on strings.
|
||||
|
||||
(setf my-hash (make-hash-table :test #'equal))
|
||||
(setf (gethash "H2O" my-hash) "Water")
|
||||
(setf (gethash "HCl" my-hash) "Hydrochloric Acid")
|
||||
(setf (gethash "CO" my-hash) "Carbon Monoxide")
|
||||
|
||||
;; That was actually a hash table, an associative array or
|
||||
;; alist is written like this:
|
||||
(defparameter *legs* '((cow . 4) (flamingo . 2) (centipede . 100)))
|
||||
;; you can use assoc to do lookups and cons new elements onto it to make it longer.
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
DEFINITION Collections;
|
||||
|
||||
IMPORT Boxes;
|
||||
|
||||
CONST
|
||||
notFound = -1;
|
||||
|
||||
TYPE
|
||||
Hash = POINTER TO RECORD
|
||||
cap-, size-: INTEGER;
|
||||
(h: Hash) ContainsKey (k: Boxes.Object): BOOLEAN, NEW;
|
||||
(h: Hash) Get (k: Boxes.Object): Boxes.Object, NEW;
|
||||
(h: Hash) IsEmpty (): BOOLEAN, NEW;
|
||||
(h: Hash) Put (k, v: Boxes.Object): Boxes.Object, NEW;
|
||||
(h: Hash) Remove (k: Boxes.Object): Boxes.Object, NEW;
|
||||
(h: Hash) Reset, NEW
|
||||
END;
|
||||
|
||||
HashMap = POINTER TO RECORD
|
||||
cap-, size-: INTEGER;
|
||||
(hm: HashMap) ContainsKey (k: Boxes.Object): BOOLEAN, NEW;
|
||||
(hm: HashMap) ContainsValue (v: Boxes.Object): BOOLEAN, NEW;
|
||||
(hm: HashMap) Get (k: Boxes.Object): Boxes.Object, NEW;
|
||||
(hm: HashMap) IsEmpty (): BOOLEAN, NEW;
|
||||
(hm: HashMap) Keys (): POINTER TO ARRAY OF Boxes.Object, NEW;
|
||||
(hm: HashMap) Put (k, v: Boxes.Object): Boxes.Object, NEW;
|
||||
(hm: HashMap) Remove (k: Boxes.Object): Boxes.Object, NEW;
|
||||
(hm: HashMap) Reset, NEW;
|
||||
(hm: HashMap) Values (): POINTER TO ARRAY OF Boxes.Object, NEW
|
||||
END;
|
||||
|
||||
LinkedList = POINTER TO RECORD
|
||||
first-, last-: Node;
|
||||
size-: INTEGER;
|
||||
(ll: LinkedList) Add (item: Boxes.Object), NEW;
|
||||
(ll: LinkedList) Append (item: Boxes.Object), NEW;
|
||||
(ll: LinkedList) AsString (): POINTER TO ARRAY OF CHAR, NEW;
|
||||
(ll: LinkedList) Contains (item: Boxes.Object): BOOLEAN, NEW;
|
||||
(ll: LinkedList) Get (at: INTEGER): Boxes.Object, NEW;
|
||||
(ll: LinkedList) IndexOf (item: Boxes.Object): INTEGER, NEW;
|
||||
(ll: LinkedList) Insert (at: INTEGER; item: Boxes.Object), NEW;
|
||||
(ll: LinkedList) IsEmpty (): BOOLEAN, NEW;
|
||||
(ll: LinkedList) Remove (item: Boxes.Object), NEW;
|
||||
(ll: LinkedList) RemoveAt (at: INTEGER), NEW;
|
||||
(ll: LinkedList) Reset, NEW;
|
||||
(ll: LinkedList) Set (at: INTEGER; item: Boxes.Object), NEW
|
||||
END;
|
||||
|
||||
Vector = POINTER TO RECORD
|
||||
size-, cap-: LONGINT;
|
||||
(v: Vector) Add (item: Boxes.Object), NEW;
|
||||
(v: Vector) AddAt (item: Boxes.Object; i: INTEGER), NEW;
|
||||
(v: Vector) Contains (o: Boxes.Object): BOOLEAN, NEW;
|
||||
(v: Vector) Get (i: LONGINT): Boxes.Object, NEW;
|
||||
(v: Vector) IndexOf (o: Boxes.Object): LONGINT, NEW;
|
||||
(v: Vector) Remove (o: Boxes.Object), NEW;
|
||||
(v: Vector) RemoveIndex (i: LONGINT): Boxes.Object, NEW;
|
||||
(v: Vector) Set (i: LONGINT; o: Boxes.Object): Boxes.Object, NEW;
|
||||
(v: Vector) Trim, NEW
|
||||
END;
|
||||
|
||||
PROCEDURE NewHash (cap: INTEGER): Hash;
|
||||
PROCEDURE NewHashMap (cap: INTEGER): HashMap;
|
||||
PROCEDURE NewLinkedList (): LinkedList;
|
||||
PROCEDURE NewVector (cap: INTEGER): Vector;
|
||||
|
||||
END Collections.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
MODULE BbtAssociativeArrays;
|
||||
IMPORT StdLog, Collections, Boxes;
|
||||
|
||||
PROCEDURE Do*;
|
||||
VAR
|
||||
hm : Collections.HashMap;
|
||||
o : Boxes.Object;
|
||||
keys, values: POINTER TO ARRAY OF Boxes.Object;
|
||||
i: INTEGER;
|
||||
|
||||
BEGIN
|
||||
hm := Collections.NewHashMap(1009);
|
||||
o := hm.Put(Boxes.NewString("first"),Boxes.NewInteger(1));
|
||||
o := hm.Put(Boxes.NewString("second"),Boxes.NewInteger(2));
|
||||
o := hm.Put(Boxes.NewString("third"),Boxes.NewInteger(3));
|
||||
o := hm.Put(Boxes.NewString("one"),Boxes.NewInteger(1));
|
||||
|
||||
StdLog.String("size: ");StdLog.Int(hm.size);StdLog.Ln;
|
||||
|
||||
END Do;
|
||||
|
||||
END BbtAssociativeArrays.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
hash1 = {"foo" => "bar"}
|
||||
|
||||
# hash literals that don't perfectly match the intended hash type must be given an explicit type specification
|
||||
# the following would fail without `of String => String|Int32`
|
||||
hash2 : Hash(String, String|Int32) = {"foo" => "bar"} of String => String|Int32
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
void main() {
|
||||
auto hash = ["foo":42, "bar":100];
|
||||
assert("foo" in hash);
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
m = { => } # empty ordered map, future inserted keys will be ordered
|
||||
h = { -> } # empty hash map, future inserted keys will not be ordered
|
||||
|
||||
m = { 'foo' => 42, 'bar' => 100 } # with ordered keys
|
||||
h = { 'foo' -> 42, 'bar' -> 100 } # with unordered keys
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
main() {
|
||||
var rosettaCode = { // Type is inferred to be Map<String, String>
|
||||
'task': 'Associative Array Creation'
|
||||
};
|
||||
|
||||
rosettaCode['language'] = 'Dart';
|
||||
|
||||
// The update function can be used to update a key using a callback
|
||||
rosettaCode.update( 'is fun', // Key to update
|
||||
(value) => "i don't know", // New value to use if key is present
|
||||
ifAbsent: () => 'yes!' // Value to use if key is absent
|
||||
);
|
||||
|
||||
assert( rosettaCode.toString() == '{task: Associative Array Creation, language: Dart, is fun: yes!}');
|
||||
|
||||
// If we type the Map with dynamic keys and values, it is like a JavaScript object
|
||||
Map<dynamic, dynamic> jsObject = {
|
||||
'key': 'value',
|
||||
1: 2,
|
||||
1.5: [ 'more', 'stuff' ],
|
||||
#doStuff: () => print('doing stuff!') // #doStuff is a symbol, only one instance of this exists in the program. Would be :doStuff in Ruby
|
||||
};
|
||||
|
||||
print( jsObject['key'] );
|
||||
print( jsObject[1] );
|
||||
|
||||
for ( var value in jsObject[1.5] )
|
||||
print('item: $value');
|
||||
|
||||
jsObject[ #doStuff ](); // Calling the function
|
||||
|
||||
print('\nKey types:');
|
||||
jsObject.keys.forEach( (key) => print( key.runtimeType ) );
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
program AssociativeArrayCreation;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
uses Generics.Collections;
|
||||
|
||||
var
|
||||
lDictionary: TDictionary<string, Integer>;
|
||||
begin
|
||||
lDictionary := TDictionary<string, Integer>.Create;
|
||||
try
|
||||
lDictionary.Add('foo', 5);
|
||||
lDictionary.Add('bar', 10);
|
||||
lDictionary.Add('baz', 15);
|
||||
lDictionary.AddOrSetValue('foo', 6); // replaces value if it exists
|
||||
finally
|
||||
lDictionary.Free;
|
||||
end;
|
||||
end.
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
use_namespace(rosettacode)_me();
|
||||
|
||||
add_dict(tanzanianBanknoteObverseDipiction)_keys(500,1000,2000,5000,10000)_values(Karume,Nyerere,lion,black rhinoceros,elephant);
|
||||
|
||||
reset_ns[];
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
use_namespace(rosettacode)_me();
|
||||
|
||||
add_hash(tanzanianBanknoteReverseDipiction)_values(
|
||||
University of Dar es Salaam\, Central Hall Building,
|
||||
Ikulu\, Dar es Salaam,
|
||||
Ngome Kongwe\, Zanzibar,
|
||||
Geita Cyanid Leaching Plant,
|
||||
Bank of Tanzania Headquarters\, Dar es Salaam
|
||||
);
|
||||
|
||||
reset_ns[];
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
var t = (x: 1, y: 2, z: 3)
|
||||
print(t.Keys().ToArray())
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
[].asMap() # immutable, empty
|
||||
["one" => 1, "two" => 2] # immutable, 2 mappings
|
||||
[].asMap().diverge() # mutable, empty
|
||||
["one" => 2].diverge(String, float64) # mutable, initial contents,
|
||||
# typed (coerces to float)
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
Map empty = Map(int, text) # creates an empty map
|
||||
writeLine(empty)
|
||||
var longFruit = Map(int, text).of(1, "banana") # creates a map with the pair 1 => "banana"
|
||||
longFruit[2] = "melon" # associates a key of 2 with "melon"
|
||||
longFruit.insert(3, "avocado")
|
||||
writeLine(longFruit) # prints the map
|
||||
var shortFruit = int%text[4 => "kiwi", 5 => "apple"] # map creation using arrow notation
|
||||
writeLine(shortFruit[5]) # retrieves the value with a key of 5 and prints it out
|
||||
writeLine(shortFruit.length) # prints the number of entries
|
||||
writeLine(shortFruit) # prints the map
|
||||
writeLine(text%text["Italy" => "Rome", "France" => "Paris", "Germany" => "Berlin", "Spain" => "Madrid"])
|
||||
|
|
@ -0,0 +1 @@
|
|||
associative$[][] = [ [ 1 "associative" ] [ 2 "arrays" ] ]
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
proc indexAssoc index . array[][] item .
|
||||
for i = 1 to len array[][]
|
||||
if array[i][1] = index
|
||||
item = array[i][2]
|
||||
break 2
|
||||
.
|
||||
.
|
||||
item = number "nan"
|
||||
.
|
||||
proc indexStrAssoc index$ . array$[][] item$ .
|
||||
for i = 1 to len array$[][]
|
||||
if array$[i][1] = index$
|
||||
item$ = array$[i][2]
|
||||
break 2
|
||||
.
|
||||
.
|
||||
item$ = ""
|
||||
.
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
(lib 'hash) ;; needs hash.lib
|
||||
(define H (make-hash)) ;; new hash table
|
||||
;; keys may be symbols, numbers, strings ..
|
||||
;; values may be any lisp object
|
||||
(hash-set H 'simon 'antoniette)
|
||||
→ antoniette
|
||||
(hash-set H 'antoinette 'albert)
|
||||
→ albert
|
||||
(hash-set H "Elvis" 42)
|
||||
→ 42
|
||||
(hash-ref H 'Elvis)
|
||||
→ #f ;; not found. Elvis is not "Elvis"
|
||||
(hash-ref H "Elvis")
|
||||
→ 42
|
||||
(hash-ref H 'simon)
|
||||
→ antoniette
|
||||
(hash-count H)
|
||||
→ 3
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Map<String, Int> map = new HashMap();
|
||||
map["foo"] = 5; // or: map.put("foo", 5)
|
||||
map["bar"] = 10;
|
||||
map["baz"] = 15;
|
||||
map["foo"] = 6; // replaces previous value of 5
|
||||
|
|
@ -0,0 +1 @@
|
|||
Map<String, Int> map = ["foo"=6, "bar"=10, "baz"=15];
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
Int? mightBeNull = map["foo"];
|
||||
Int neverNull = map.getOrDefault("foo", 0);
|
||||
if (Int n := map.get("foo")) {
|
||||
// if "foo" is in the map, then the variable "n" is set to its value
|
||||
} else {
|
||||
// if "foo" is not in the map, then the variable "n" is not defined
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
for (String key : map) {
|
||||
// the variable "key" is defined here
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
for (Int value : map.values) {
|
||||
// the variable "value" is defined here
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
for ((String key, Int value) : map) {
|
||||
// the variables "key" and "value" are defined here
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import system'collections;
|
||||
|
||||
public program()
|
||||
{
|
||||
// 1. Create
|
||||
var map := Dictionary.new();
|
||||
map["key"] := "foox";
|
||||
map["key"] := "foo";
|
||||
map["key2"]:= "foo2";
|
||||
map["key3"]:= "foo3";
|
||||
map["key4"]:= "foo4";
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import system'collections;
|
||||
|
||||
public program()
|
||||
{
|
||||
// 1. Create
|
||||
auto map := new Map<string,string>();
|
||||
map["key"] := "foox";
|
||||
map["key"] := "foo";
|
||||
map["key2"]:= "foo2";
|
||||
map["key3"]:= "foo3";
|
||||
map["key4"]:= "foo4";
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
%{}
|
||||
|
|
@ -0,0 +1 @@
|
|||
%{"one" => :two, 3 => "four"}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
%{a: 1, b: 2}
|
||||
# equivalent to
|
||||
%{:a => 1, :b => 2}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
defmodule RC do
|
||||
def test_create do
|
||||
IO.puts "< create Map.new >"
|
||||
m = Map.new #=> creates an empty Map
|
||||
m1 = Map.put(m,:foo,1)
|
||||
m2 = Map.put(m1,:bar,2)
|
||||
print_vals(m2)
|
||||
print_vals(%{m2 | foo: 3})
|
||||
end
|
||||
|
||||
defp print_vals(m) do
|
||||
IO.inspect m
|
||||
Enum.each(m, fn {k,v} -> IO.puts "#{inspect k} => #{v}" end)
|
||||
end
|
||||
end
|
||||
|
||||
RC.test_create
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
(setq my-table (make-hash-table))
|
||||
(puthash 'key 'value my-table)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
(setq my-table (make-hash-table :test 'equal))
|
||||
(puthash "key" 123 my-table)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
-module(assoc).
|
||||
-compile([export_all]).
|
||||
|
||||
test_create() ->
|
||||
D = dict:new(),
|
||||
D1 = dict:store(foo,1,D),
|
||||
D2 = dict:store(bar,2,D1),
|
||||
print_vals(D2),
|
||||
print_vals(dict:store(foo,3,D2)).
|
||||
|
||||
print_vals(D) ->
|
||||
lists:foreach(fun (K) ->
|
||||
io:format("~p: ~b~n",[K,dict:fetch(K,D)])
|
||||
end, dict:fetch_keys(D)).
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
let dic = System.Collections.Generic.Dictionary<string,string>() ;;
|
||||
dic.Add("key","val") ;
|
||||
dic.["key"] <- "new val" ;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
let d = [("key","val");("other key","other val")] |> Map.ofList
|
||||
let newd = d.Add("new key","new val")
|
||||
|
||||
let takeVal (d:Map<string,string>) =
|
||||
match d.TryFind("key") with
|
||||
| Some(v) -> printfn "%s" v
|
||||
| None -> printfn "not found"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
H{ { "one" 1 } { "two" 2 } }
|
||||
{ [ "one" swap at . ]
|
||||
[ 2 swap value-at . ]
|
||||
[ "three" swap at . ]
|
||||
[ [ 3 "three" ] dip set-at ]
|
||||
[ "three" swap at . ] } cleave
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
class Main
|
||||
{
|
||||
public static Void main ()
|
||||
{
|
||||
// create a map which maps Ints to Strs, with given key-value pairs
|
||||
Int:Str map := [1:"alpha", 2:"beta", 3:"gamma"]
|
||||
|
||||
// create an empty map
|
||||
Map map2 := [:]
|
||||
// now add some numbers mapped to their doubles
|
||||
10.times |Int i|
|
||||
{
|
||||
map2[i] = 2*i
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
: get ( key len table -- data ) \ 0 if not present
|
||||
search-wordlist if
|
||||
>body @
|
||||
else 0 then ;
|
||||
|
||||
: put ( data key len table -- )
|
||||
>r 2dup r@ search-wordlist if
|
||||
r> drop nip nip
|
||||
>body !
|
||||
else
|
||||
r> get-current >r set-current \ switch definition word lists
|
||||
nextname create ,
|
||||
r> set-current
|
||||
then ;
|
||||
wordlist constant bar
|
||||
5 s" alpha" bar put
|
||||
9 s" beta" bar put
|
||||
2 s" gamma" bar put
|
||||
s" alpha" bar get . \ 5
|
||||
8 s" Alpha" bar put \ Forth dictionaries are normally case-insensitive
|
||||
s" alpha" bar get . \ 8
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
include ffl/hct.fs
|
||||
|
||||
\ Create a hash table 'table' in the dictionary with a starting size of 10
|
||||
|
||||
10 hct-create htable
|
||||
|
||||
\ Insert entries
|
||||
|
||||
5 s" foo" htable hct-insert
|
||||
10 s" bar" htable hct-insert
|
||||
15 s" baz" htable hct-insert
|
||||
|
||||
\ Get entry from the table
|
||||
|
||||
s" bar" htable hct-get [IF]
|
||||
.( Value:) . cr
|
||||
[ELSE]
|
||||
.( Entry not present.) cr
|
||||
[THEN]
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
include lib/hash.4th
|
||||
include lib/hashkey.4th
|
||||
|
||||
\ Create a hash table 'table' with a starting size of 10
|
||||
|
||||
['] fnv1a is hash \ set hash method
|
||||
10 constant /htable \ determine the size
|
||||
/htable array htable \ allocate the table
|
||||
latest /htable hashtable \ turn it into a hashtable
|
||||
|
||||
\ Insert entries
|
||||
|
||||
5 s" foo" htable put
|
||||
10 s" bar" htable put
|
||||
15 s" baz" htable put
|
||||
|
||||
\ Get entry from the table
|
||||
|
||||
s" bar" htable get error? if
|
||||
.( Entry not present.) cr drop
|
||||
else
|
||||
.( Value: ) . cr
|
||||
then
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
program AssociativeArrayCreation;
|
||||
{$IFDEF FPC}{$MODE DELPHI}{$ENDIF}
|
||||
{$IFDEF WINDOWS}{$APPTYPE CONSOLE}{$ENDIF}
|
||||
uses Generics.Collections;
|
||||
var
|
||||
lDictionary: TDictionary<string, Integer>;
|
||||
begin
|
||||
lDictionary := TDictionary<string, Integer>.Create;
|
||||
try
|
||||
lDictionary.Add('foo', 5);
|
||||
lDictionary.Add('bar', 10);
|
||||
lDictionary.Add('baz', 15);
|
||||
lDictionary.AddOrSetValue('foo', 6); // replaces value if it exists
|
||||
finally
|
||||
lDictionary.Free;
|
||||
end;
|
||||
end.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
program AssociativeArrayCreation;
|
||||
{$IFDEF WINDOWS}{$APPTYPE CONSOLE}{$ENDIF}
|
||||
{$MODE DELPHI}
|
||||
uses fgl;
|
||||
|
||||
var
|
||||
lDictionary: TFPGMap<string, Integer>;
|
||||
begin
|
||||
lDictionary := TFPGMap<string, Integer>.Create;
|
||||
try
|
||||
lDictionary.Add('foo', 5);
|
||||
lDictionary.Add('bar', 10);
|
||||
lDictionary.Add('baz', 15);
|
||||
finally
|
||||
lDictionary.Free;
|
||||
end;
|
||||
end.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#define max(a, b) Iif(a>b,a,b)
|
||||
|
||||
enum datatype
|
||||
'for this demonstration we'll allow these five data types
|
||||
BOOL
|
||||
STRNG
|
||||
BYYTE
|
||||
INTEG
|
||||
FLOAT
|
||||
end enum
|
||||
|
||||
union value
|
||||
bool as boolean
|
||||
strng as string*32
|
||||
byyte as byte
|
||||
integ as integer
|
||||
float as double
|
||||
end union
|
||||
|
||||
type dicitem
|
||||
'one part of the dictionary entry, either the key or the value
|
||||
datatype as datatype 'need to keep track of what kind of data it is
|
||||
value as value
|
||||
end type
|
||||
|
||||
type dicentry
|
||||
'a dic entry has two things, a key and a value
|
||||
key as dicitem
|
||||
value as dicitem
|
||||
end type
|
||||
|
||||
sub add_dicentry( Dic() as dicentry, entry as dicentry )
|
||||
redim preserve Dic(0 to max(ubound(Dic)+1,0))
|
||||
Dic(ubound(Dic)) = entry
|
||||
return
|
||||
end sub
|
||||
|
||||
redim as dicentry Dictionary(-1) 'initialise a dictionary with no entries as yet
|
||||
|
||||
dim as dicentry thing1, thing2
|
||||
|
||||
'generate some test dictionary entries
|
||||
with thing1
|
||||
with .key
|
||||
.datatype = STRNG
|
||||
.value.strng = "Cat"
|
||||
end with
|
||||
with .value
|
||||
.datatype = STRNG
|
||||
.value.strng = "Mittens"
|
||||
end with
|
||||
end with
|
||||
|
||||
with thing2
|
||||
with .key
|
||||
.datatype = integ
|
||||
.value.integ = 32767
|
||||
end with
|
||||
with .value
|
||||
.datatype = float
|
||||
.value.float = 2.718281828
|
||||
end with
|
||||
end with
|
||||
|
||||
add_dicentry( Dictionary(), thing1 )
|
||||
add_dicentry( Dictionary(), thing2 )
|
||||
|
||||
print Dictionary(0).value.value.strng
|
||||
print Dictionary(1).key.value.integ
|
||||
|
|
@ -0,0 +1 @@
|
|||
let associative_array = {key1=1,key2=2}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
void local fn DoIt
|
||||
CFDictionaryRef dict1 = fn DictionaryWithObjects( @"Alpha", @"A", @"Bravo", @"B", @"Charlie", @"C", @"Delta", @"D", NULL )
|
||||
|
||||
CFDictionaryRef dict2 = @{@"A":@"Alpha", @"B":@"Bravo", @"C":@"Charlie", @"D":@"Delta"}
|
||||
|
||||
CFMutableDictionaryRef dict3 = fn MutableDictionaryWithCapacity(0)
|
||||
MutableDictionarySetObjectForKey( dict3, @"Alpha", @"A" )
|
||||
MutableDictionarySetObjectForKey( dict3, @"Bravo", @"B" )
|
||||
MutableDictionarySetObjectForKey( dict3, @"Charlie", @"C" )
|
||||
MutableDictionarySetObjectForKey( dict3, @"Delta", @"D" )
|
||||
|
||||
CFMutableDictionaryRef dict4 = fn MutableDictionaryWithDictionary( @{@"A":@"Alpha", @"B":@"Bravo", @"C":@"Charlie", @"D":@"Delta"} )
|
||||
|
||||
print fn DictionaryObjectForKey( dict1, @"A" )
|
||||
print dict1[@"B"]
|
||||
print dict2[@"C"]
|
||||
print dict3[@"D"]
|
||||
print dict4
|
||||
end fn
|
||||
|
||||
fn DoIt
|
||||
|
||||
HandleEvents
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
// declare a nil map variable, for maps from string to int
|
||||
var x map[string]int
|
||||
|
||||
// make an empty map
|
||||
x = make(map[string]int)
|
||||
|
||||
// make an empty map with an initial capacity
|
||||
x = make(map[string]int, 42)
|
||||
|
||||
// set a value
|
||||
x["foo"] = 3
|
||||
|
||||
// getting values
|
||||
y1 := x["bar"] // zero value returned if no map entry exists for the key
|
||||
y2, ok := x["bar"] // ok is a boolean, true if key exists in the map
|
||||
|
||||
// removing keys
|
||||
delete(x, "foo")
|
||||
|
||||
// make a map with a literal
|
||||
x = map[string]int{
|
||||
"foo": 2, "bar": 42, "baz": -1,
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// empty map
|
||||
var emptyMap = new HashMap<String, Integer>()
|
||||
|
||||
// map initialization
|
||||
var map = {"Scott"->50, "Carson"->40, "Luca"->30, "Kyle"->38}
|
||||
|
||||
// map key/value assignment
|
||||
map["Scott"] = 51
|
||||
|
||||
// get a value
|
||||
var x = map["Scott"]
|
||||
|
||||
// remove an entry
|
||||
map.remove("Scott")
|
||||
|
||||
// loop and maps
|
||||
for(entry in map.entrySet()) {
|
||||
print("Key: ${entry.Key}, Value: ${entry.Value}")
|
||||
}
|
||||
|
||||
// functional iteration
|
||||
map.eachKey(\ k ->print(map[k]))
|
||||
map.eachValue(\ v ->print(v))
|
||||
map.eachKeyAndValue(\ k, v -> print("Key: ${v}, Value: ${v}"))
|
||||
var filtered = map.filterByValues(\ v ->v < 50)
|
||||
|
||||
// any object can be treated as an associative array
|
||||
class Person {
|
||||
var name: String
|
||||
var age: int
|
||||
}
|
||||
// access properties on Person dynamically via associative array syntax
|
||||
var scott = new Person()
|
||||
scott["name"] = "Scott"
|
||||
scott["age"] = 29
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
map = [:]
|
||||
map[7] = 7
|
||||
map['foo'] = 'foovalue'
|
||||
map.put('bar', 'barvalue')
|
||||
map.moo = 'moovalue'
|
||||
|
||||
assert 7 == map[7]
|
||||
assert 'foovalue' == map.foo
|
||||
assert 'barvalue' == map['bar']
|
||||
assert 'moovalue' == map.get('moo')
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
map = [7:7, foo:'foovalue', bar:'barvalue', moo:'moovalue']
|
||||
|
||||
assert 7 == map[7]
|
||||
assert 'foovalue' == map.foo
|
||||
assert 'barvalue' == map['bar']
|
||||
assert 'moovalue' == map.get('moo')
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
arr := { => }
|
||||
arr[ 10 ] := "Val_10"
|
||||
arr[ "foo" ] := "foovalue"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
arr := hb_Hash( 10, "Val_10", "foo", "foovalue" )
|
||||
// or
|
||||
arr := { 10 => "Val_10", "foo" => "foovalue" }
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import Data.Map
|
||||
|
||||
dict = fromList [("key1","val1"), ("key2","val2")]
|
||||
|
||||
ans = Data.Map.lookup "key2" dict -- evaluates to Just "val2"
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
dict = [("key1","val1"), ("key2","val2")]
|
||||
|
||||
ans = lookup "key2" dict -- evaluates to Just "val2"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
let d dict 2 # Initial estimated size
|
||||
let d["test"] "test" # Strings can be used as index
|
||||
let d[123] 123 # Integers can also be used as index
|
||||
|
||||
println d["test"]
|
||||
println d[123]
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue