|
hi,
strings can be compared with < or >: "a" < "b"; but integer arrays can not? ({ 97 }) < ({ 98 }); Compiler Error: 1: Too few arguments to `< (got 2). Compiler Error: 1: Expected: object | mixed. Compiler Error: 1: Function type: Compiler Error: 1: Got : function(string ... : int(0..1)) | function(int | float ... : int(0..1)) | function(program | type(mixed), program | type(mixed), program | type(mixed) ... : int(0..1)) | !function(!(object | mixed) ... : mixed) & function(mixed ... : int(0..1)). the errormessage seems to hint at this being a case not handled or missed or a bug rather than by design. could the code that does the string comparison be reused for arrays too? greetings, martin. -- cooperative communication with sTeam - caudium, pike, roxen and unix services: debugging, programming, training, linux sysadmin, web development -- pike programmer working in china community.gotpike.org foresight developer (open-steam|caudium).org foresightlinux.org unix sysadmin iaeste.at realss.com Martin Bähr http://www.iaeste.at/~mbaehr/ is.schon.org |
|
Martin Bähr <[hidden email]> wrote:
> strings can be compared with < or >: > "a" < "b"; > > but integer arrays can not? No, they can't. I think it's best to not try to define some kind of recursive comparison operation for such data types. It'd rarely be useful, and it could obscure bugs. Also, extra complexity is required to handle stuff like circular links in the arrays. Maybe add functions to Array.pmod to do that instead, e.g. Array.compare, Array.less, and so on? > ({ 97 }) < ({ 98 }); > Compiler Error: 1: Too few arguments to `< (got 2). > Compiler Error: 1: Expected: object | mixed. > Compiler Error: 1: Function type: > Compiler Error: 1: Got : function(string ... : int(0..1)) | function(int | float ... : int(0..1)) | function(program | type(mixed), program | type(mixed), program | type(mixed) ... : int(0..1)) | !function(!(object | mixed) ... : mixed) & function(mixed ... : int(0..1)). > > the errormessage seems to hint at this being a case not handled or > missed or a bug rather than by design. I think the error message is the problem there. I noticed the same "Too few arguments" when I tried to do ({1,2,3}) & (<1,2>) yesterday, and it doesn't make sense. Hopefully Grubba can fix it. And btw, the remaining lines don't help either. It'd be great if we could get rid of those humongous types in these kinds of errors. If it's hard to do something better, I think just a limit that simply skips printing the type if it's too long would help - those messages are scary.. |
|
On Wed, 30 Nov 2011, Martin Stjernholm wrote:
> Martin Bähr <[hidden email]> wrote: > >> strings can be compared with < or >: >> "a" < "b"; >> >> but integer arrays can not? > > No, they can't. I think it's best to not try to define some kind of > recursive comparison operation for such data types. It'd rarely be > useful, and it could obscure bugs. Also, extra complexity is required to > handle stuff like circular links in the arrays. >> ({ 97 }) < ({ 98 }); >> Compiler Error: 1: Too few arguments to `< (got 2). >> Compiler Error: 1: Expected: object | mixed. >> Compiler Error: 1: Function type: >> Compiler Error: 1: Got : function(string ... : int(0..1)) | function(int | float ... : int(0..1)) | function(program | type(mixed), program | type(mixed), program | type(mixed) ... : int(0..1)) | !function(!(object | mixed) ... : mixed) & function(mixed ... : int(0..1)). >> >> the errormessage seems to hint at this being a case not handled or >> missed or a bug rather than by design. > > I think the error message is the problem there. I noticed the same "Too > few arguments" when I tried to do ({1,2,3}) & (<1,2>) yesterday, and it > doesn't make sense. Hopefully Grubba can fix it. a valid operation for some obscure object o. Hmm... I guess it could be possible to improve the message by detecting the problem when the type is currified for the last argument, rather than when there are no more arguments left. The question is then what the error message should be, since in these cases there are multiple single-operation ways to resolve the error. Maybe all posible minimal resolutions should be listed? Bad argument 1 to `&. Got: array(int(1..3)). Expected: multiset|object|mixed. Or Bad argument 2 to `&. Got: multiset(int(1..2)) Expected: array|object|mixed. Or Too few arguments to `&. Expected: object|mixed. To be able to generate the complete message above would require a second pass (or making the current currifier even more complicated) after having determined that there are bad arguments. > And btw, the remaining lines don't help either. It'd be great if we > could get rid of those humongous types in these kinds of errors. If it's > hard to do something better, I think just a limit that simply skips > printing the type if it's too long would help - those messages are > scary.. Maybe so. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
Couln't we drop "|mixed"? It does add anything of value to the message
besides more text that I can see. |
|
In reply to this post by Henrik Grubbström-2
Henrik Grubbström <[hidden email]> wrote:
>> I think the error message is the problem there. I noticed the same "Too >> few arguments" when I tried to do ({1,2,3}) & (<1,2>) yesterday, and it >> doesn't make sense. Hopefully Grubba can fix it. > > The reason for the message is that it `&(({1,2,3}),(<1,2>), o) is > possibly a valid operation for some obscure object o. That object would contain a ``&(mixed,mixed) or something then? Has it actually searched for and found a candidate class with such an lfun when it prints this message? > The question is then what the error message should be, since in these > cases there are multiple single-operation ways to resolve the error. > > Maybe all posible minimal resolutions should be listed? > > Bad argument 1 to `&. > Got: array(int(1..3)). > Expected: multiset|object|mixed. > Or > Bad argument 2 to `&. > Got: multiset(int(1..2)) > Expected: array|object|mixed. > Or > Too few arguments to `&. > Expected: object|mixed. > > To be able to generate the complete message above would require a > second pass (or making the current currifier even more complicated) > after having determined that there are bad arguments. Well, I guess another hypothetical solution would be that the expression is lacking a preceding object that sports a `&(array,multiset), then? I don't think it helps to try to list all possible errors. Most programmers would expect an error on the first conflicting argument when it's currified from the left, i.e. the second message among your three alternatives, so I vote for that one and nothing else. One always has to draw ones own conclusions from the error message anyway, and correct the actual problem whereever it may be. We cannot hope to identify the real cause - it may not even be on that line but rather in a faulty declaration somewhere further back, or that the operator was supposed to be something else, or that it's a comment that's lacking the /* */ around it, or... So I think the goal should be to make as obvious and as short messages as possible. |
|
In reply to this post by Martin Stjernholm
On Wed, Nov 30, 2011 at 08:29:31PM +0100, Martin Stjernholm wrote:
> Maybe add functions to Array.pmod to do that instead, e.g. > Array.compare, Array.less, and so on? but once those exist, couldn't < and > use those when they encounter arrays? i mean it wouldn't be much different than operator overloading... in any case though i'd start with Array.compare which takes a comparison function as argument: int(0..1) Array.compare(array a, array b, function c, void|int non_recursive, mixed ... args) args are passed as extra arguments to c. in recursive mode, c is applied only to terminals, in nonrecursive mode it is applied to any element. greetings, martin. -- cooperative communication with sTeam - caudium, pike, roxen and unix services: debugging, programming, training, linux sysadmin, web development -- pike programmer working in china community.gotpike.org foresight developer (open-steam|caudium).org foresightlinux.org unix sysadmin iaeste.at realss.com Martin Bähr http://www.iaeste.at/~mbaehr/ is.schon.org |
|
In reply to this post by Martin Stjernholm
On Wed, 30 Nov 2011, Martin Stjernholm wrote:
> Henrik Grubbström <[hidden email]> wrote: > >>> I think the error message is the problem there. I noticed the same "Too >>> few arguments" when I tried to do ({1,2,3}) & (<1,2>) yesterday, and it >>> doesn't make sense. Hopefully Grubba can fix it. >> >> The reason for the message is that it `&(({1,2,3}),(<1,2>), o) is >> possibly a valid operation for some obscure object o. > > That object would contain a ``&(mixed,mixed) or something then? Has it > actually searched for and found a candidate class with such an lfun when > it prints this message? the type-checker currently usually doesn't know about lfuns. >> The question is then what the error message should be, since in these >> cases there are multiple single-operation ways to resolve the error. >> >> Maybe all posible minimal resolutions should be listed? >> >> Bad argument 1 to `&. >> Got: array(int(1..3)). >> Expected: multiset|object|mixed. >> Or >> Bad argument 2 to `&. >> Got: multiset(int(1..2)) >> Expected: array|object|mixed. >> Or >> Too few arguments to `&. >> Expected: object|mixed. >> >> To be able to generate the complete message above would require a >> second pass (or making the current currifier even more complicated) >> after having determined that there are bad arguments. > > Well, I guess another hypothetical solution would be that the expression > is lacking a preceding object that sports a `&(array,multiset), then? > I don't think it helps to try to list all possible errors. Most > programmers would expect an error on the first conflicting argument when > it's currified from the left, i.e. the second message among your three > alternatives, so I vote for that one and nothing else. Noted. The problem is when you have large number of arguments and it's one of the first that causes the problem. eg: array a = ({}); multiset m = (<>); a = `&(a,m,a,a,a,a,a,a,a,a); Here you would typically want to know about argument 2 being a mapping, and not about argument 10 not being an object. We could of course decide that nobody is ever going to want to implement an object implementing lfun::`& or lfun::``& accepting a mix of arguments that predef::`& wouldn't accept. That would just be a simple (for some value of "simple" :-)) change of the type of predef::`&. This is actually a solution I'd accept, since I believe that operator overloading should attempt to keep the normal semantics for the operators. > One always has to draw ones own conclusions from the error message > anyway, and correct the actual problem whereever it may be. We cannot > hope to identify the real cause - it may not even be on that line but > rather in a faulty declaration somewhere further back, or that the > operator was supposed to be something else, or that it's a comment > that's lacking the /* */ around it, or... True. > So I think the goal should be to make as obvious and as short messages > as possible. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
On Thu, 1 Dec 2011, Henrik Grubbström wrote:
> We could of course decide that nobody is ever going to want to implement an > object implementing lfun::`& or lfun::``& accepting a mix of arguments that > predef::`& wouldn't accept. That would just be a simple (for some value of > "simple" :-)) change of the type of predef::`&. This is actually a solution > I'd accept, since I believe that operator overloading should attempt to keep > the normal semantics for the operators. I just tried the above approach with the type for predef::`+. Before: > (<1,2,3>) + ({ "foo" }); Compiler Error: 1: Too few arguments to `+ (got 2). Compiler Error: 1: Expected: object | mixed. Compiler Error: 1: Function type: Compiler Error: 1: Got : scope(0,function((0=multiset), (1=multiset) ... : 0 | 1) | function((0=mapping), (1=mapping) ... : 0 | 1) | function((0=array), (1=array) ... : 0 | 1) | function(int, int ... : int) | !function(!string ... : mixed) & function(string | int | float, string | int | float ... : string) | !function(!float ... : mixed) & function(int | float, int | float ... : float) | !function(!(object | mixed) ... : mixed) & function(mixed ... : mixed)). After: > (<1,2,3>) + ({ "foo" }); Compiler Error: 1: Bad argument 2 to `+. Compiler Error: 1: Expected: multiset | object. Compiler Error: 1: Got : array(string(0..255)). The type did get somewhat more complicated though: > typeof(`+); (1) Result: scope(0,function(int, int ... : int) | function((0=multiset), (1=multiset) ... : 0 | 1) | function((0=mapping), (1=mapping) ... : 0 | 1) | function((0=array), (1=array) ... : 0 | 1) | !function(!float ... : mixed) & function(int | float, int | float ... : float) | !function(!(object | mixed) ... : mixed) & (function(object | string | int | float, object | string | int | float ... : mixed) | function(multiset | object, multiset | object ... : mixed) | function(mapping | object, mapping | object ... : mixed) | function(array | object, array | object ... : mixed)) | !function(!string ... : mixed) & function(string | int | float, string | int | float ... : string)) The main change is that I changed !function(!(object | mixed) ... : mixed) & function(mixed ... : mixed) to !function(!(object | mixed) ... : mixed) & (function(object | string | int | float, object | string | int | float ... : mixed) | function(multiset | object, multiset | object ... : mixed) | function(mapping | object, mapping | object ... : mixed) | function(array | object, array | object ... : mixed)) which is a somewhat more complicated type, but not too bad... The change also had the side-effect that strict_types started to complain about addition of mixed, which is probably correct to do, since the arguments might be incompatible. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
In reply to this post by Martin Bähr
Martin Bähr <[hidden email]> wrote:
>> Maybe add functions to Array.pmod to do that instead, e.g. >> Array.compare, Array.less, and so on? > > but once those exist, couldn't < and > use those when they encounter > arrays? i mean it wouldn't be much different than operator > overloading... Different enough. It'd miss the point, which is that < and > should not be clever on ordinary arrays (imo). > in any case though i'd start with Array.compare which takes a comparison > function as argument: > > int(0..1) Array.compare(array a, array b, function c, void|int non_recursive, mixed ... args) > > args are passed as extra arguments to c. If you generalize the comparison function itself like that, then I suggest something like recursive_compare that'd work on mappings as well. Maybe even objects, but that could open up some tricky issues. > in recursive mode, c is applied only to terminals, in nonrecursive mode > it is applied to any element. I'm not so sure about the usefulness in combining those two modes into the same function. Besides, that nonrecursive mode would be very little more than a simple loop. |
|
In reply to this post by Henrik Grubbström-2
Henrik Grubbström <[hidden email]> wrote:
>>> The reason for the message is that it `&(({1,2,3}),(<1,2>), o) is >>> possibly a valid operation for some obscure object o. >> >> That object would contain a ``&(mixed,mixed) or something then? /.../ > > /.../ Also note that the type-checker currently usually doesn't know > about lfuns. I'm confused. If it doesn't know about lfuns, do you mean that the reason for the message is something else than that the hypothetical object would have a ``&? Or do you mean that it doesn't regard the types of the actual involved lfuns (if any)? >> Well, I guess another hypothetical solution would be that the expression >> is lacking a preceding object that sports a `&(array,multiset), then? > > Sporting a ``&(array, multiset), but yes. No, I really meant a hypothetical object preceding the operands that would have a forward acting `&, not a backward acting ``&. >> I don't think it helps to try to list all possible errors. Most >> programmers would expect an error on the first conflicting argument when >> it's currified from the left, i.e. the second message among your three >> alternatives, so I vote for that one and nothing else. > > Noted. > > The problem is when you have large number of arguments and it's one of > the first that causes the problem. eg: > > array a = ({}); multiset m = (<>); > a = `&(a,m,a,a,a,a,a,a,a,a); > > Here you would typically want to know about argument 2 being a > mapping, and not about argument 10 not being an object. Yes, and complaining on the first conflicting argument when it's currified from the left would accomplish exactly that, wouldn't it? Or am I missing something now? > We could of course decide that nobody is ever going to want to > implement an object implementing lfun::`& or lfun::``& accepting a mix > of arguments that predef::`& wouldn't accept. That would just be a > simple (for some value of "simple" :-)) change of the type of > predef::`&. This is actually a solution I'd accept, since I believe > that operator overloading should attempt to keep the normal semantics > for the operators. I agree completely. Iow, the type checker can compare without any special regard for lfuns, and for hypothetical extra objects with them, right? /.../ > The main change is that I changed > > !function(!(object | mixed) ... : mixed) & function(mixed ... : mixed) > > to > > !function(!(object | mixed) ... : mixed) & > (function(object | string | int | float, > object | string | int | float ... : mixed) | > function(multiset | object, multiset | object ... : mixed) | > function(mapping | object, mapping | object ... : mixed) | > function(array | object, array | object ... : mixed)) Does this mean that the problem is always to be solved by more complicated/narrower types rather than a simpler type matcher that disregards hypothetical extra objects? I can see why the latter type improves the type check, and maybe also understand a little that it makes the reported "Got:" type less clumsy. But it seems to me that avoiding those "Too few arguments" errors should be accomplished in the type checker so that it works even when types aren't improved. |
|
On Wed, 7 Dec 2011, Martin Stjernholm wrote:
> Henrik Grubbström <[hidden email]> wrote: > >>>> The reason for the message is that it `&(({1,2,3}),(<1,2>), o) is >>>> possibly a valid operation for some obscure object o. >>> >>> That object would contain a ``&(mixed,mixed) or something then? /.../ >> >> /.../ Also note that the type-checker currently usually doesn't know >> about lfuns. > > I'm confused. If it doesn't know about lfuns, do you mean that the > reason for the message is something else than that the hypothetical > object would have a ``&? Or do you mean that it doesn't regard the types > of the actual involved lfuns (if any)? provided to predef::`&() et al has the required lfuns. The only checking of the actual lfuns is done at run-time. I guess we could extend the compile-time type-checker to support checking for lfuns as well, but right now it doesn't. >>> Well, I guess another hypothetical solution would be that the expression >>> is lacking a preceding object that sports a `&(array,multiset), then? >> >> Sporting a ``&(array, multiset), but yes. > > No, I really meant a hypothetical object preceding the operands that > would have a forward acting `&, not a backward acting ``&. Yes, of course (shows how often I use operator-overloading, I guess...). >> The problem is when you have large number of arguments and it's one of >> the first that causes the problem. eg: >> >> array a = ({}); multiset m = (<>); >> a = `&(a,m,a,a,a,a,a,a,a,a); >> >> Here you would typically want to know about argument 2 being a >> mapping, and not about argument 10 not being an object. > > Yes, and complaining on the first conflicting argument when it's > currified from the left would accomplish exactly that, wouldn't it? Or > am I missing something now? otherwise the type-checker can't know during currifying whether an obscure object supporting a mix of arrays and multisets will show up later in the argument list. >> We could of course decide that nobody is ever going to want to >> implement an object implementing lfun::`& or lfun::``& accepting a mix >> of arguments that predef::`& wouldn't accept. That would just be a >> simple (for some value of "simple" :-)) change of the type of >> predef::`&. This is actually a solution I'd accept, since I believe >> that operator overloading should attempt to keep the normal semantics >> for the operators. > > I agree completely. Iow, the type checker can compare without any > special regard for lfuns, and for hypothetical extra objects with them, > right? objects or the same basic types as without overloading as well? ie an lfun::``&(multiset ... m) would be assumed to return either multisets or objects, but not eg ints or arrays. This could probably be implemented with a rather easy type change (compared to the one further below), eg for predef::`+(): !function(!(object|mixed) ... : mixed) & function(object|mixed ... : object) | function(int|object, int|object ... : int) | function(array|object, array|object ... array) | ... > /.../ >> The main change is that I changed >> >> !function(!(object | mixed) ... : mixed) & function(mixed ... : mixed) >> >> to >> >> !function(!(object | mixed) ... : mixed) & >> (function(object | string | int | float, >> object | string | int | float ... : mixed) | >> function(multiset | object, multiset | object ... : mixed) | >> function(mapping | object, mapping | object ... : mixed) | >> function(array | object, array | object ... : mixed)) > > Does this mean that the problem is always to be solved by more > complicated/narrower types rather than a simpler type matcher that > disregards hypothetical extra objects? above as well. Without you'd just get a complaint that the last argument should be an object|mixed rather than a missing object|mixed. > I can see why the latter type improves the type check, and maybe also > understand a little that it makes the reported "Got:" type less clumsy. > But it seems to me that avoiding those "Too few arguments" errors should > be accomplished in the type checker so that it works even when types > aren't improved. I agree that the type-checker should probably be improved to special-case the last argument as well, but I believe the main problem is limited to the main operator efuns, so I'm not sure if such a change would help anywhere else. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
On Wed, 7 Dec 2011, Henrik Grubbström wrote:
> On Wed, 7 Dec 2011, Martin Stjernholm wrote: > >> Henrik Grubbström <[hidden email]> wrote: >> >>> The problem is when you have large number of arguments and it's one of >>> the first that causes the problem. eg: >>> >>> array a = ({}); multiset m = (<>); >>> a = `&(a,m,a,a,a,a,a,a,a,a); >>> >>> Here you would typically want to know about argument 2 being a >>> mapping, and not about argument 10 not being an object. >> >> Yes, and complaining on the first conflicting argument when it's >> currified from the left would accomplish exactly that, wouldn't it? Or >> am I missing something now? > > Only if we restrict the allowed types for lfun::``&() et al, since > otherwise the type-checker can't know during currifying whether an > obscure object supporting a mix of arrays and multisets will show > up later in the argument list. checker for function calls in Pike 7.9. As expected, you get the following compile-errors for the test-cases: > array a = ({}); multiset m = (<>); > a = a & m; Compiler Error: 1: Bad argument 2 to `&. Compiler Error: 1: Expected: array | mapping | object. Compiler Error: 1: Got : multiset. > a = `&(a,m,a,a,a,a,a,a,a,a); Compiler Error: 1: Bad argument 10 to `&. Compiler Error: 1: Expected: mapping. Compiler Error: 1: Got : array. Compiler Error: 1: Bad type in assignment. Compiler Error: 1: Expected: array. Compiler Error: 1: Got : mapping. > I agree that the type-checker should probably be improved to special-case the > last argument as well, but I believe the main problem is limited to the main > operator efuns, so I'm not sure if such a change would help anywhere else. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
On Fri, 9 Dec 2011, Henrik Grubbström wrote:
> On Wed, 7 Dec 2011, Henrik Grubbström wrote: > >> On Wed, 7 Dec 2011, Martin Stjernholm wrote: >> >>> Yes, and complaining on the first conflicting argument when it's >>> currified from the left would accomplish exactly that, wouldn't it? Or >>> am I missing something now? >> >> Only if we restrict the allowed types for lfun::``&() et al, since >> otherwise the type-checker can't know during currifying whether an >> obscure object supporting a mix of arrays and multisets will show >> up later in the argument list. > > I've now enabled the special-casing of the last argument in the type checker > for function calls in Pike 7.9. obscure types. eg: | > function(int,int:int)|function(string:string) q; | > q(); | Compiler Error: 1: Too few arguments to q (got 0). | Compiler Error: 1: Expected: string. | Compiler Error: 1: Function type: | Compiler Error: 1: Got : function(string : string) | function(int, int : int). The old checker would ask for "string|int", which I guess is more what you would expect. The reason it only mentions "string" is that a single string argument would be sufficient, while for "int" more than one argument is needed. Changing the behaviour here to the old one should be simple. | > q(17); | Compiler Error: 1: Bad argument 1 to q. | Compiler Error: 1: Expected: string. | Compiler Error: 1: Got : int(17..17). Here the old checker would instead ask for a second argument. | > q(17,"foo"); | Compiler Error: 1: Bad argument 2 to q. | Compiler Error: 1: Expected: int. | Compiler Error: 1: Got : string(0..255). This one is the same for both the old and the new type-checker. -- Henrik Grubbström [hidden email] Roxen Internet Software AB |
|
On Sat, Dec 10, 2011 at 04:17:32PM +0100, Henrik Grubbström wrote:
> >I've now enabled the special-casing of the last argument in the type > >checker for function calls in Pike 7.9. nice :-) > | > q(17); > | Compiler Error: 1: Bad argument 1 to q. > | Compiler Error: 1: Expected: string. > | Compiler Error: 1: Got : int(17..17). > Here the old checker would instead ask for a second argument. shouldn't it ask for both? either the number of arguments is wrong, or the type is wrong. greetings, martin. -- cooperative communication with sTeam - caudium, pike, roxen and unix services: debugging, programming, training, linux sysadmin, web development -- pike programmer working in china community.gotpike.org foresight developer (open-steam|caudium).org foresightlinux.org unix sysadmin iaeste.at realss.com Martin Bähr http://www.iaeste.at/~mbaehr/ is.schon.org |
| Powered by Nabble | See how NAML generates this page |
