digitalmars.D.learn - Array indexing & typedef
- Charles Hixson (12/12) Jun 19 2005 Does:
- Jarrett Billingsley (7/12) Jun 19 2005 Yes. Any time you put _any_ kind of type inside the brackets, it's an A...
- Charles Hixson (8/27) Jun 20 2005 Thanks for the info.
- Regan Heath (15/37) Jun 20 2005 I dont understand what you want. It seems like you're saying you want a ...
- Charles Hixson (26/71) Jun 21 2005 Sort of right. I'm translating a program from Ada (learning 2
- Regan Heath (16/73) Jun 21 2005 Yeah, that is basically what I figured you wanted. I agree it would be
- Charles Hixson (17/102) Jun 22 2005 They won't even "really" do the job...though I guess they could,
- Regan Heath (4/97) Jun 22 2005 Just for fun if you post the container here I'll try and turn it into a ...
- Charles Hixson (106/207) Jun 23 2005 OK, here it is. Note that I had to define append rather than
- Regan Heath (8/111) Jun 23 2005 It's opIndex, not optIndex, that's why it wasn't working.
- Charles Hixson (11/31) Jun 23 2005 Well the original code was single spaced, tab delimited @ 3
- Derek Parnell (129/132) Jun 23 2005 Should be "op" rather than "opt". However the opCatAssign() will not wor...
- Charles Hixson (9/22) Jun 24 2005 Thanks much for the analysis. At least that tells me:
- Derek Parnell (16/23) Jun 24 2005 No I don't. It seems a sensible idea to a mere mortal like myself but
- Mike Parker (14/17) Jun 24 2005 What's so kludgy? I don't see any difference between:
- Derek Parnell (10/34) Jun 24 2005 I understand your point of view. To me "~" means "concat 2 things
- Mike Parker (12/16) Jun 24 2005 Not entirely the same argument. When you see an operator, your mind is
- Regan Heath (9/9) Jun 23 2005 After a brief look I'm not quite sure where to start.
- Charles Hixson (33/45) Jun 23 2005 O, there are predicates, and rules, and various indexes...I'm not
- Chris Sauls (3/8) Jun 22 2005 Couldn't you just use a static array? Or am I missing something?
- Derek Parnell (15/24) Jun 22 2005 Static or Dynamic, it doesn't matter.
- Chris Sauls (3/8) Jun 22 2005 Okay, I get it now... odd, but I guess its like another kind of contract...
- Derek Parnell (20/50) Jun 20 2005 Maybe a struct might be useful ...
- Charles Hixson (9/60) Jun 21 2005 But doesn't that still give you a hash table / sparse array?
- Derek Parnell (10/69) Jun 21 2005 Sorry, I misunderstood.
- Charles Hixson (23/91) Jun 22 2005 Yeah. But the syntax of how to do it is the problem. I think I
Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType? If so, is there a valid way of specifying that one wants an array of items which is indexed by a specialized type of integer short of defining a new class? If not, what's the approved way to define an associative array with an index of ints? I'm certain that this must have come up before, but I haven't been able to find it.
Jun 19 2005
"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 19 2005
Jarrett Billingsley wrote:"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 20 2005
On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 20 2005
Regan Heath wrote:On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Sort of right. I'm translating a program from Ada (learning 2 languages at once). In Ada if one defines a type and then defines an array type, say: Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order to translate the program...but it does add a layer of error checking at compile time that I think useful...*!*IF*!* I can add it without too much work. (OTOH, Ada doesn't have built in hash tables...and I've been scratching my head around how to replace tree searches that aren't well documented [now where is this "out" variable used...and WHY??].) OTOH, replacing GoalRange with an enumeration is a bit ... strange. There will probably be less than a few hundred goals...but they will come and go. (It's a backwards chaining "Expert System Shell"...of the old and "simple" variety.) The two languages are VERY different, and the right way to do things frequently changes GROSSLY when I translate it. (At one point I nearly gave up and said.."I'll just do a literal translation!", but really, that's the wrong approach. I wouldn't be doing this at all if I weren't trying to learn from the process.) OTOH, a sparse array / hash table is definitely NOT what I want where I'm just looking to enforce type safety. (But I sure do want it at other times!)Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 21 2005
On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Regan Heath wrote:Yeah, that is basically what I figured you wanted. I agree it would be useful.On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Sort of right. I'm translating a program from Ada (learning 2 languages at once). In Ada if one defines a type and then defines an array type, say: Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order to translate the program...but it does add a layer of error checking at compile time that I think useful...Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."*!*IF*!* I can add it without too much work. (OTOH, Ada doesn't have built in hash tables...and I've been scratching my head around how to replace tree searches that aren't well documented [now where is this "out" variable used...and WHY??].)I'm sorry I can't help with Ada. I've never used it.OTOH, replacing GoalRange with an enumeration is a bit ... strange.Yeah, but it's the closest built in basic type to a 'range' that D has I reckon. I D got ranges I'd imagine them built onto the enum syntax eg. enum myInt : int { 0,...,100 } enum myInt : int { 0 ... 100 } or something similar. There have been a number of requests for a range type in D, I can't remember Walter's position (or even if he gave one). I suspect at this stage 'ranges', while useful, are not high on the list of things to do.OTOH, a sparse array / hash table is definitely NOT what I want where I'm just looking to enforce type safety. (But I sure do want it at other times!)Sure, they're kind of overkill really for this problem. Tho, they'd do the job, right? Regan
Jun 21 2005
Regan Heath wrote:On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:They won't even "really" do the job...though I guess they could, as long as you could distinguish null from out-of-range. But hash tables aren't intended for stepping through, and arrays are. You could force them to do the job...but that would be worse than writing a new container class (which looks to be relatively minor), and would probably be much more inefficient. (Done right, all the overhead [over an array of integers] should be at compile time.) Still, this really IS minor. I can skip the layer of error checking, and use alias instead of typedef...or I can write the container classes (which might be good practice anyway). But I'd need to write it several times, because I'm NOT ready to start dealing with templates yet. (For some reason, that's the feature of D that makes less sense to me than any of the others. I far prefer the way that Eiffel uses generics [or did 5 years ago] to handle the same problem.)Regan Heath wrote:Yeah, that is basically what I figured you wanted. I agree it would be useful.On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Sort of right. I'm translating a program from Ada (learning 2 languages at once). In Ada if one defines a type and then defines an array type, say: Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order to translate the program...but it does add a layer of error checking at compile time that I think useful...Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."*!*IF*!* I can add it without too much work. (OTOH, Ada doesn't have built in hash tables...and I've been scratching my head around how to replace tree searches that aren't well documented [now where is this "out" variable used...and WHY??].)I'm sorry I can't help with Ada. I've never used it.OTOH, replacing GoalRange with an enumeration is a bit ... strange.Yeah, but it's the closest built in basic type to a 'range' that D has I reckon. I D got ranges I'd imagine them built onto the enum syntax eg. enum myInt : int { 0,...,100 } enum myInt : int { 0 ... 100 } or something similar. There have been a number of requests for a range type in D, I can't remember Walter's position (or even if he gave one). I suspect at this stage 'ranges', while useful, are not high on the list of things to do.OTOH, a sparse array / hash table is definitely NOT what I want where I'm just looking to enforce type safety. (But I sure do want it at other times!)Sure, they're kind of overkill really for this problem. Tho, they'd do the job, right? Regan
Jun 22 2005
On Wed, 22 Jun 2005 08:21:06 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Regan Heath wrote:Just for fun if you post the container here I'll try and turn it into a template class.On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:They won't even "really" do the job...though I guess they could, as long as you could distinguish null from out-of-range. But hash tables aren't intended for stepping through, and arrays are. You could force them to do the job...but that would be worse than writing a new container class (which looks to be relatively minor), and would probably be much more inefficient. (Done right, all the overhead [over an array of integers] should be at compile time.) Still, this really IS minor. I can skip the layer of error checking, and use alias instead of typedef...or I can write the container classes (which might be good practice anyway). But I'd need to write it several times, because I'm NOT ready to start dealing with templates yet. (For some reason, that's the feature of D that makes less sense to me than any of the others. I far prefer the way that Eiffel uses generics [or did 5 years ago] to handle the same problem.)Regan Heath wrote:Yeah, that is basically what I figured you wanted. I agree it would be useful.On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Sort of right. I'm translating a program from Ada (learning 2 languages at once). In Ada if one defines a type and then defines an array type, say: Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order to translate the program...but it does add a layer of error checking at compile time that I think useful...Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."*!*IF*!* I can add it without too much work. (OTOH, Ada doesn't have built in hash tables...and I've been scratching my head around how to replace tree searches that aren't well documented [now where is this "out" variable used...and WHY??].)I'm sorry I can't help with Ada. I've never used it.OTOH, replacing GoalRange with an enumeration is a bit ... strange.Yeah, but it's the closest built in basic type to a 'range' that D has I reckon. I D got ranges I'd imagine them built onto the enum syntax eg. enum myInt : int { 0,...,100 } enum myInt : int { 0 ... 100 } or something similar. There have been a number of requests for a range type in D, I can't remember Walter's position (or even if he gave one). I suspect at this stage 'ranges', while useful, are not high on the list of things to do.OTOH, a sparse array / hash table is definitely NOT what I want where I'm just looking to enforce type safety. (But I sure do want it at other times!)Sure, they're kind of overkill really for this problem. Tho, they'd do the job, right? Regan
Jun 22 2005
Regan Heath wrote:On Wed, 22 Jun 2005 08:21:06 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:OK, here it is. Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access. There seem to be type problems that I don't understand. (Sample use at the end.) I haven't tested the code yet beyond getting it to compile, but it's hardly a complete application. typedef uint SymbolId; typedef uint IndexId; typedef char[] Token; class Symbols { protected class Symbol { Token token; SymbolId symbolId; bit arithme; bit defined; float value; IndexId indexId; this (Token t) { token = t; symbolId = cast(SymbolId)symbols.length; } } SymbolId nxtSymbolId = 0; Symbol[] symbols; /* note that the symbNdx hash table can be rebuilt as needed * from the symbols array. Thus it need not be saved. */ SymbolId[Token] symbNdx; invariant { // does nxtSymbolId have any other use? If so, why? assert (nxtSymbolId == symbols.length); // Make sure the index is kept current assert (symbols.length == symbNdx.length); } bit search(Symbol symbol) { return search(symbol.token); } public //this () { super(); } this () { } bit search(SymbolId symbolId) { if (symbolId >= symbols.length) return false; if (symbols[symbolId] !is null) assert(symbols[symbolId].symbolId == symbolId); return (symbols[symbolId] !is null); } bit search(Token token) { return search(symbNdx[token]); } this(char[] name) { } Token optIndex(SymbolId symbolId) { if (symbolId >= symbols.length) return null; return symbols[symbolId].token; } SymbolId optIndex(Token token) { assert (token !is null); return symbNdx[token]; } void optCatAssign(Token token) in { assert (token !is null); } body { Symbol symb; if (search (token) ) { // do we really want to allow symbols to be redefined? throw new SymbolException ("attempt to redefine existing symbol"); } else { nxtSymbolId += 1; symbNdx[token] = cast(SymbolId)symbols.length; symbols ~= new Symbol(token); } } void append(Token token) in { assert (token !is null); } body { Symbol symb; if (search (token) ) { // do we really want to allow symbols to be redefined? throw new SymbolException ("attempt to redefine existing symbol"); } else { nxtSymbolId += 1; symbNdx[token] = cast(SymbolId)symbols.length; symbols ~= new Symbol(token); } } } ++++++++++++++++++++++++ in a new file ++++++++++++++++++++++++ import symbol; SymbolId makeSym(inout Symbols symbols, in Token phrase) { symbols.append(phrase); //return symbols[cast(Token)phrase]; return symbols.optIndex(phrase); }Regan Heath wrote:Just for fun if you post the container here I'll try and turn it into a template class.On Tue, 21 Jun 2005 20:28:31 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:They won't even "really" do the job...though I guess they could, as long as you could distinguish null from out-of-range. But hash tables aren't intended for stepping through, and arrays are. You could force them to do the job...but that would be worse than writing a new container class (which looks to be relatively minor), and would probably be much more inefficient. (Done right, all the overhead [over an array of integers] should be at compile time.) Still, this really IS minor. I can skip the layer of error checking, and use alias instead of typedef...or I can write the container classes (which might be good practice anyway). But I'd need to write it several times, because I'm NOT ready to start dealing with templates yet. (For some reason, that's the feature of D that makes less sense to me than any of the others. I far prefer the way that Eiffel uses generics [or did 5 years ago] to handle the same problem.)Regan Heath wrote:Yeah, that is basically what I figured you wanted. I agree it would be useful.On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Sort of right. I'm translating a program from Ada (learning 2 languages at once). In Ada if one defines a type and then defines an array type, say: Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order to translate the program...but it does add a layer of error checking at compile time that I think useful...Jarrett Billingsley wrote:I dont understand what you want. It seems like you're saying you want a normal array i.e. sequentialy indexed items and you want to limit which type can be used to index it to? why? I'd guess you have something like: class Bar{} enum Foo { A,B,C,D,E,F,G } Bar[G] data; and you're trying to get the compiler to limit the indices to the 'data' array to the enumerated type, or similar. Am I on the right track? Regan"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."*!*IF*!* I can add it without too much work. (OTOH, Ada doesn't have built in hash tables...and I've been scratching my head around how to replace tree searches that aren't well documented [now where is this "out" variable used...and WHY??].)I'm sorry I can't help with Ada. I've never used it.OTOH, replacing GoalRange with an enumeration is a bit ... strange.Yeah, but it's the closest built in basic type to a 'range' that D has I reckon. I D got ranges I'd imagine them built onto the enum syntax eg. enum myInt : int { 0,...,100 } enum myInt : int { 0 ... 100 } or something similar. There have been a number of requests for a range type in D, I can't remember Walter's position (or even if he gave one). I suspect at this stage 'ranges', while useful, are not high on the list of things to do.OTOH, a sparse array / hash table is definitely NOT what I want where I'm just looking to enforce type safety. (But I sure do want it at other times!)Sure, they're kind of overkill really for this problem. Tho, they'd do the job, right? Regan
Jun 23 2005
On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:OK, here it is. Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access. There seem to be type problems that I don't understand. (Sample use at the end.)It's opIndex, not optIndex, that's why it wasn't working.I haven't tested the code yet beyond getting it to compile, but it's hardly a complete application.Missing was TokenException (I defined one). I'll see what I come up with, no promises :) Regan p.s. the code below is really weirdly formatted, extra double spaced everywhere.. was that intentional or a result of the NG?typedef uint SymbolId; typedef uint IndexId; typedef char[] Token; class Symbols { protected class Symbol { Token token; SymbolId symbolId; bit arithme; bit defined; float value; IndexId indexId; this (Token t) { token = t; symbolId = cast(SymbolId)symbols.length; } } SymbolId nxtSymbolId = 0; Symbol[] symbols; /* note that the symbNdx hash table can be rebuilt as needed * from the symbols array. Thus it need not be saved. */ SymbolId[Token] symbNdx; invariant { // does nxtSymbolId have any other use? If so, why? assert (nxtSymbolId == symbols.length); // Make sure the index is kept current assert (symbols.length == symbNdx.length); } bit search(Symbol symbol) { return search(symbol.token); } public //this () { super(); } this () { } bit search(SymbolId symbolId) { if (symbolId >= symbols.length) return false; if (symbols[symbolId] !is null) assert(symbols[symbolId].symbolId == symbolId); return (symbols[symbolId] !is null); } bit search(Token token) { return search(symbNdx[token]); } this(char[] name) { } Token optIndex(SymbolId symbolId) { if (symbolId >= symbols.length) return null; return symbols[symbolId].token; } SymbolId optIndex(Token token) { assert (token !is null); return symbNdx[token]; } void optCatAssign(Token token) in { assert (token !is null); } body { Symbol symb; if (search (token) ) { // do we really want to allow symbols to be redefined? throw new SymbolException ("attempt to redefine existing symbol"); } else { nxtSymbolId += 1; symbNdx[token] = cast(SymbolId)symbols.length; symbols ~= new Symbol(token); } } void append(Token token) in { assert (token !is null); } body { Symbol symb; if (search (token) ) { // do we really want to allow symbols to be redefined? throw new SymbolException ("attempt to redefine existing symbol"); } else { nxtSymbolId += 1; symbNdx[token] = cast(SymbolId)symbols.length; symbols ~= new Symbol(token); } } } ++++++++++++++++++++++++ in a new file ++++++++++++++++++++++++ import symbol; SymbolId makeSym(inout Symbols symbols, in Token phrase) { symbols.append(phrase); //return symbols[cast(Token)phrase]; return symbols.optIndex(phrase); }
Jun 23 2005
Regan Heath wrote:On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson <charleshixsn earthlink.net> wrote:Well the original code was single spaced, tab delimited 3 spaces = one tab. (I pasted that into the email, and then did a global replace of tabs with 3 spaces...not good, but the starts of lines should be OK.) My guess was that most of the lines were too long, and the messaging processes split the lines somewhere along the path. (TokenException doesn't do anything special except say "This is a token exception with the following message: xxxxx" ... only of course, not literally that. Nearly anything you defined it as should work adequately.)OK, here it is. Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access. There seem to be type problems that I don't understand. (Sample use at the end.)It's opIndex, not optIndex, that's why it wasn't working.I haven't tested the code yet beyond getting it to compile, but it's hardly a complete application.Missing was TokenException (I defined one). I'll see what I come up with, no promises :) Regan p.s. the code below is really weirdly formatted, extra double spaced everywhere.. was that intentional or a result of the NG?
Jun 23 2005
On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson wrote: [snip]OK, here it is. Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access.Should be "op" rather than "opt". However the opCatAssign() will not work until Walter allows us to concatenate things that are not arrays. If you define opCatAssign() and then use "x ~= y" where 'y' is not an array or an element of 'x', the compiler complains. Anyhow, here is the result of my playing around with your code. I added opIndex(int) to make using symbols[int] easier, and a Count() method. <code for file symbol.d> typedef uint SymbolId; typedef uint IndexId; typedef char[] Token; class SymbolException { char[] m_msg; this(char[] msg) { m_msg = msg.dup; } } class Symbols { protected: struct Symbol { Token token; SymbolId symbolId; bit arithme; bit defined; float value; IndexId indexId; void Init(Token t) { token = t; symbolId = nxtSymbolId; } } static SymbolId nxtSymbolId = 0; Symbol[] lSymbolList; /* note that the symbNdx hash table can be rebuilt as needed from the symbols array. Thus it need not be saved. */ SymbolId[Token] symbNdx; void AddSymbol(Token pToken) { nxtSymbolId += 1; symbNdx[pToken] = nxtSymbolId; lSymbolList.length = lSymbolList.length + 1; lSymbolList[$-1].Init(pToken); } invariant { // Make sure the index is kept current assert (lSymbolList.length == symbNdx.length); } bit search(Symbol symbol) { return search(symbol.token); } public: this () { } bool search(SymbolId pSymbolId) { if (pSymbolId >= nxtSymbolId) return false; if (pSymbolId >= lSymbolList.length) return false; assert(lSymbolList[pSymbolId].symbolId == pSymbolId); return true; } bool search(Token token) { return (token in symbNdx) is null ? false : true; } Token opIndex(SymbolId symbolId) { if (symbolId >= lSymbolList.length) return null; return lSymbolList[symbolId].token; } SymbolId opIndex(Token token) { assert (token !is null); return symbNdx[token]; } Token opIndex(int pIdx) { assert(pIdx >= 0 && pIdx < lSymbolList.length); return lSymbolList[pIdx].token; } SymbolId append(Token token) in { assert (token !is null); } body { Symbol symb; if (search (token) ) { // do we really want to allow symbols to be redefined? throw new SymbolException("attempt to redefine existing symbol"); } AddSymbol(token); return nxtSymbolId; } int Count() { return lSymbolList.length; } } </code> <code for test.d> import std.stdio; import symbol; void main() { Symbols lBase = new Symbols; lBase.append(cast(Token)"if"); lBase.append(cast(Token)"static"); lBase.append(cast(Token)"static if"); for(int i = 0; i < lBase.Count; i++) { writefln("Symbol id %d: '%s'", i, lBase[i]); } }</code> -- Derek Melbourne, Australia 24/06/2005 11:18:46 AM
Jun 23 2005
Derek Parnell wrote:On Thu, 23 Jun 2005 17:00:25 -0700, Charles Hixson wrote: [snip]Thanks much for the analysis. At least that tells me: 1) How to fix MY mistake and 2) Why the thing that wasn't my mistake didn't work. I do hope that SOME better way to append to a container class soon becomes available. opCatAssign seemed the most reasonable, but if not that, then some other. Otherwise user container classes will remain...kludgy. (You don't happen to know if allowing this is planned for the future, do you?)OK, here it is. Note that I had to define append rather than using optCatAssign, and I have to call optIndex as a function rather than using [] access.Should be "op" rather than "opt". However the opCatAssign() will not work until Walter allows us to concatenate things that are not arrays. If you define opCatAssign() and then use "x ~= y" where 'y' is not an array or an element of 'x', the compiler complains. [snip]
Jun 24 2005
On Fri, 24 Jun 2005 00:00:19 -0700, Charles Hixson wrote:Derek Parnell wrote:... the opCatAssign() will not work until Walter allows us to concatenate things that are not arrays. If you define opCatAssign() and then use "x ~= y" where 'y' is not an array or an element of 'x', the compiler complains.... (You don't happen to know if allowing this is planned for the future, do you?)No I don't. It seems a sensible idea to a mere mortal like myself but Walter doesn't always see things the same way that I do ;-) In my opinion, the general case of ... <classinstance> ~= <expression> should call <classinstance>.opCatAssign( <expression> ) if there is a matching member defined. This should also apply to structs as well. My rationale is that it if such a member is defined then the class (or struct) knows what to do with the <expression> so the compiler should just let it do its thing. I hope that this is just an oversight and will be fixed very soon. -- Derek Melbourne, Australia 24/06/2005 5:12:01 PM
Jun 24 2005
Charles Hixson wrote:other. Otherwise user container classes will remain...kludgy. (You don't happen to know if allowing this is planned for the future, do you?)What's so kludgy? I don't see any difference between: x ~= y and x.append(y); Less typing with the operator, particularly for chaining, but the same result either way. I prefer the latter, actually. To me the ~ operator in D means 'concat 2 arrays'. Once you start allowing it to be overloaded, it could mean anything. Then you wind up with cryptic code where you constantly have to look up the overide to make sure it really is appending/concatting and not doing something funky. It's like when people use the * operator with two vectors to carry out a dot product. Always throws me off. I would be happy if Walter did away with operator overloading altogether, but that's just wishful thinking :)
Jun 24 2005
On Fri, 24 Jun 2005 16:45:49 +0900, Mike Parker wrote:Charles Hixson wrote:I understand your point of view. To me "~" means "concat 2 things together".other. Otherwise user container classes will remain...kludgy. (You don't happen to know if allowing this is planned for the future, do you?)What's so kludgy? I don't see any difference between: x ~= y and x.append(y); Less typing with the operator, particularly for chaining, but the same result either way. I prefer the latter, actually. To me the ~ operator in D means 'concat 2 arrays'.Once you start allowing it to be overloaded, it could mean anything. Then you wind up with cryptic code where you constantly have to look up the overide to make sure it really is appending/concatting and not doing something funky. It's like when people use the * operator with two vectors to carry out a dot product. Always throws me off. I would be happy if Walter did away with operator overloading altogether, but that's just wishful thinking :)Yes, this is an issue with overloading operators, but on the other hand, how do you know that a function called 'append' is also not doing anything 'funky'? It might not even be appending. Its the same argument really. -- Derek Melbourne, Australia 24/06/2005 6:52:24 PM
Jun 24 2005
Derek Parnell wrote:Yes, this is an issue with overloading operators, but on the other hand, how do you know that a function called 'append' is also not doing anything 'funky'? It might not even be appending. Its the same argument really.Not entirely the same argument. When you see an operator, your mind is trained to recognize it as a specific functions. '+' generally means 'add' and '-' generally means 'subtract'. This is built in to the language do fundamentally never changes. Function names and implementations *do* vary from API to API and generally require that you read the documentation and/or source to completely understand what any given function does. So when I'm skimming source, a '+' operator registers as 'addition' automatically and the eyes move on, but a function named 'add' registers no differently than a function named 'googleyfoobob' - both being functions, they will definitely stand out if I don't already know exactly what they do, particularly when debugging.
Jun 24 2005
After a brief look I'm not quite sure where to start. I see Symbols (the container class) I see Symbol (created to hold a Token, and SymbolId) I see Token (an object) I see SymbolId (ever incrementing, always unique id for a Symbol) I see IndexId (not used?) You said "But I'd need to write it several times", what parts change for the next time? Regan
Jun 23 2005
Regan Heath wrote:After a brief look I'm not quite sure where to start. I see Symbols (the container class) I see Symbol (created to hold a Token, and SymbolId) I see Token (an object) I see SymbolId (ever incrementing, always unique id for a Symbol) I see IndexId (not used?) You said "But I'd need to write it several times", what parts change for the next time? ReganO, there are predicates, and rules, and various indexes...I'm not sure whatall as I'm still translating (and understanding) the original program. Certainly I won't be doing things quite the same way, as the original includes a manually implemented hash table and tree structure, and there are pointers all over the place. (I have a fierce distaste for having to deal with pointers. That's the compiler's job!) It also includes storage management without including garbage collection. I'm certain that parts of what I'm not understanding have to do with that. Etc. As near as I can tell the guy who wrote it was more a professor of Computer Science specializing in AI than a programmer. I feel certain that Ada COULD be done more neatly. (OTOH, without understanding exactly what he's doing in places, this is a bit of a non-humble analysis...but, e.g., he implemented his own variable length strings claiming that Ada didn't provide them. But perhaps they were added with Ada95, and he was writing for Ada 198x.) Anyway understanding the program is one challenge, and translating it into a modern decent language is another. And when I get done I'll have a toy backward chaining Expert System Shell. (I'll probably also change the syntax of the rules...but first I need to understand what he was doing with them originally...and that requires understanding the program. :) I'm finding the combination to be quite an interesting challenge.) P.S.: SymbolId, TokenId, PredicateId, RuleId, etc. are all my idea. The original used pointers in these places, but I want something that I can reasonably store in a database. Id's are permanent, memory locations are transient. This means that it's going to be a bit difficult to forget things, since I won't be able to depend on a garbage collector, but it's worth the price to be able to checkpoint dump a process, and then resume later without worrying about relocation in memory.
Jun 23 2005
Charles Hixson wrote:Type GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order toCouldn't you just use a static array? Or am I missing something? -- Chris Sauls
Jun 22 2005
On Wed, 22 Jun 2005 02:16:15 -0500, Chris Sauls wrote:Charles Hixson wrote:Static or Dynamic, it doesn't matter. It would be used in situations like this ... typedef int WidgetId; typedef int Dimension; class Widget { . . . } Widget[cast(WidgetId)] KnownWidgets; Dimension x,y,z; . . . KnownWidgets[ x ].Hide(); // This should fail as it's index // is a 'Dimension' and not a 'WidgetId' -- Derek Parnell Melbourne, Australia 22/06/2005 7:33:51 PMType GoalRange is Integer range 0...MaxGoal; Type Goals is array (GoalRange) of Goal; then it's a compilation error if you index the array with a variable of any type other than GoalRange. This isn't necessary in order toCouldn't you just use a static array? Or am I missing something?
Jun 22 2005
Derek Parnell wrote:Widget[cast(WidgetId)] KnownWidgets; Dimension x,y,z; . . . KnownWidgets[ x ].Hide(); // This should fail as it's index // is a 'Dimension' and not a 'WidgetId'Okay, I get it now... odd, but I guess its like another kind of contract. -- Chris Sauls
Jun 22 2005
On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson wrote:Jarrett Billingsley wrote:Maybe a struct might be useful ... struct arrtype { int x; } void main() { char[][ arrtype ] c; arrtype a,b; a.x = 1; b.x = 2; c[a] = "one"; c[b] = "two"; } -- Derek Parnell Melbourne, Australia 21/06/2005 8:04:42 AM"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 20 2005
Derek Parnell wrote:On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson wrote:But doesn't that still give you a hash table / sparse array? No, I think what I need to do (if I decide it's worth it) is create a class and implement opIndex, opIndexAssign, and possibly opSlice (two versions). That would (apparently?) allow me to specify the index type required...but that's a bit heavy duty just to implement a bit of type checking...so I'll probably skip that unless I find an easier way, or unless I find another reason to create it as a class.Jarrett Billingsley wrote:Maybe a struct might be useful ... struct arrtype { int x; } void main() { char[][ arrtype ] c; arrtype a,b; a.x = 1; b.x = 2; c[a] = "one"; c[b] = "two"; }"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 21 2005
On Tue, 21 Jun 2005 20:37:44 -0700, Charles Hixson wrote:Derek Parnell wrote:Sorry, I misunderstood. So you want a standard array, that is one in which the index is an offset from the start of the array, but you want to specify that only certain types of integers are allowed as indexes in array references. Sounds like a useful idea; a natural extension of static type checking. -- Derek Melbourne, Australia 22/06/2005 1:52:49 PMOn Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson wrote:But doesn't that still give you a hash table / sparse array? No, I think what I need to do (if I decide it's worth it) is create a class and implement opIndex, opIndexAssign, and possibly opSlice (two versions). That would (apparently?) allow me to specify the index type required...but that's a bit heavy duty just to implement a bit of type checking...so I'll probably skip that unless I find an easier way, or unless I find another reason to create it as a class.Jarrett Billingsley wrote:Maybe a struct might be useful ... struct arrtype { int x; } void main() { char[][ arrtype ] c; arrtype a,b; a.x = 1; b.x = 2; c[a] = "one"; c[b] = "two"; }"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 21 2005
Derek Parnell wrote:On Tue, 21 Jun 2005 20:37:44 -0700, Charles Hixson wrote:Yeah. But the syntax of how to do it is the problem. I think I agree that hash tables are a more important use for the syntax. Up until now I'd been confused about just WHAT would happen if I declared an array with an integer type, possibly partially BECAUSE Ada used it for type checking...which seems to me a straight-forward interpretation of the syntax, just not the most useful one. Hash tables have more general utility, but error checking is also high priority...it would be nice to have BOTH. Unfortunately, just how to do it isn't terribly clear. Possibly range types are the answer. This would require simple syntax to specify open-ended (well, sort of) ranges. Then one could adopt the convention that arrays indexed by a range were normal arrays with a range index. (But then how would one make a hash table over a range?) One obvious answer is to adopt a new keyword in the special limited context of array declarations, thus: typedef short Entry; int[indexed by Entry] checkedItems; This would work, and is clear, but requires the new keyword "indexed by" within the context of an array declaration. This isn't as bad as it might be, as it wouldn't break any existing code...but it does make things more complicated.Derek Parnell wrote:Sorry, I misunderstood. So you want a standard array, that is one in which the index is an offset from the start of the array, but you want to specify that only certain types of integers are allowed as indexes in array references. Sounds like a useful idea; a natural extension of static type checking.On Mon, 20 Jun 2005 13:34:14 -0700, Charles Hixson wrote:But doesn't that still give you a hash table / sparse array? No, I think what I need to do (if I decide it's worth it) is create a class and implement opIndex, opIndexAssign, and possibly opSlice (two versions). That would (apparently?) allow me to specify the index type required...but that's a bit heavy duty just to implement a bit of type checking...so I'll probably skip that unless I find an easier way, or unless I find another reason to create it as a class.Jarrett Billingsley wrote:Maybe a struct might be useful ... struct arrtype { int x; } void main() { char[][ arrtype ] c; arrtype a,b; a.x = 1; b.x = 2; c[a] = "one"; c[b] = "two"; }"Charles Hixson" <charleshixsn earthlink.net> wrote in message news:d950du$2u4c$1 digitaldaemon.com...Thanks for the info. Unfortunately, what I wanted wasn't a sparse array, but an array that required it's indexes to be a particular type... O, well. At other times I want sparse arrays...so that's all to the good. Any suggestions as to how to require indexes to be of a particular type? (All I can think of is building a class, and implementing optAssign, etc.)Does: typedef int MyType; char[MyType] val; result in val being an associative array, rather than an arrays whose indicies are typechecked to be instances of MyType?Yes. Any time you put _any_ kind of type inside the brackets, it's an AA. This works too: char[int] val; val is an AA of chars indexed by ints. I think an AA with an int key is usually called a "sparse array."
Jun 22 2005