1. Standard library praise and challenge
- Posted by jeremy (admin) Sep 11, 2011
- 3471 views
Just some standard library praise. I was recently working with a library retrieved from the archive that was written pre 4.x. I'm not going to mention the library or author. Anyway, I was working on taking advantage of some of the standard library routines instead of the ones written in the library that accomplish the same task. I ran across ltrim, rtrim and trim. Those methods trim whitespace from the left, right or both sides of a sequence. In the standard library we have trim_head, trim_tail and trim which accomplish the same task, except that they will trim anything you want by using an optional second parameter trim(content, what = " \t\r\n") basically. Anyway... the ones written in the library I was working on were pretty simple and looked fine to me at first glance. However, one benchmark I had setup was parsing a 25mb file using the library.
Stock from the archive the library took 21 seconds to complete. Simply removing the local implementations of ltrim, rtrim and trim and using trim_head, trim_tail and trim instead from the standard library parsing time dropped to 16 seconds. That's a 24% increase in performance by a simple search/replace operation using the new standard library.
This is what the new standard libary is all about. A large collection of group maintained/peer audited/performance tested routines. Not only do we get a large number of common functions to use instead of having each programmer reinvent the wheel with each new project, we also get everyone's head wrapped around a single problem and the very best solution possible.
So... this was just a bit of praise about the standard library but also a challenge to Euphoria users. Look at the source for your favorite standard library routines. Do you see a way they can be improved? Do you see a way to make them faster? Do you see a way to make them more robust? If so, create a ticket and let the development team know! 2 eyes are better than 1, 100 eyes are better than 50.
Jeremy
2. Re: Standard library praise and challenge
- Posted by SDPringle Sep 11, 2011
- 3387 views
I have wondered for some time. Why do max and min recurse?
Like max({"Head","Tail"}) will give you 'l' but it seems to me you would want the object with the highest value ("Tail") more often then the highest letter ('l').
There must have been a reason for this.
Shawn
3. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 11, 2011
- 3393 views
I have wondered for some time. Why do max and min recurse?
They do!? Doesn't sound like a common requirement to me. Now that we have optional arguments, it might be better to have recursive behavior controlled by an argument with the default being NOT to recurse.
4. Re: Standard library praise and challenge
- Posted by Insolor Sep 13, 2011
- 3355 views
It would be nice if someone adds these changes to image.e: http://openeuphoria.org/pastey/90.wc
5. Re: Standard library praise and challenge
- Posted by useless Sep 13, 2011
- 3297 views
I have wondered for some time. Why do max and min recurse?
Like max({"Head","Tail"}) will give you 'l' but it seems to me you would want the object with the highest value ("Tail") more often then the highest letter ('l').
I'd say max({"Head","Tail"}) should give you a word, max("HeadTail") should give you a letter.
Likewise, max( { {"2,Tail"} , {"1,Head" } } ) should return a sequence.
There must have been a reason for this.
Shawn
I wouldn't bet on that.
useless
6. Re: Standard library praise and challenge
- Posted by SDPringle Sep 13, 2011
- 3275 views
I am seeing most people describing the functions max and min I wrote myself. I ask you though, what should happen when you pass an empty sequence?
- Undefined results
- Die with an error message
- Return the 'biggest value' or the 'smallest value'.
In the last option, though arguably impossible for real life numbers, the standard library set max({}) to be the smallest representable number, and min({}) the largest representable number. I never liked that behavior either and it is impossible to return the largest representable object. Well, there is a way (in C), but you wouldn't want such a monster to exist.
Shawn Pringle
7. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 13, 2011
- 3284 views
I am seeing most people describing the functions max and min I wrote myself. I ask you though, what should happen when you pass an empty sequence?
- Undefined results
- Die with an error message
- Return the 'biggest value' or the 'smallest value'.
I'm not sure, although that's not really what people are asking about. Let's look at max:
public function max(object a) atom b, c if atom(a) then return a end if b = mathcons:MINF for i = 1 to length(a) do c = max(a[i]) if c > b then b = c end if end for return b end function
I can see what this is getting at. We're in math.e, and the intent is to deal with atoms only. From that perspective it makes sense, although I wonder how often it would really be used for that purpose.
An alternate is to add a more simple, but intuitive, routine, possibly in sequence.e. This other routine would simply do a compare() against each element, starting with the first. I guess the default return would probably be an empty sequence for that routine.
Matt
8. Re: Standard library praise and challenge
- Posted by euphoric (admin) Sep 13, 2011
- 3262 views
I would expect max/min to apply to top-level elements only.
So...
max( { "Head", "Tail" } ) -- "Tail" since it is higher alphabetically max( { 1, 2, 3 } ) -- 3 max( {} ) -- Error condition max( { {1}, {2} } ) -- {2} max( { {1,{1}}, {1,{2}} } ) -- {1,{2}} max( { 1, {1} } ) -- 1? now we're getting somewhere :)
To search deep like the current max() does for the largest atom can be useful but seems to be counter-intuitive. Maybe a max_deep() or something should do this instead so max() can get back its common intent.
9. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 13, 2011
- 3286 views
I am seeing most people describing the functions max and min I wrote myself. I ask you though, what should happen when you pass an empty sequence?
I give you an empty bag and ask you to pull out the largest object. You can't pull out any object so therefore this is an error. The results are defined - you pull nothing out, which is of course neither the biggest nor the smallest, thus we have a problem - also known as an error situation. One way to signal this error is to just give back the bag.
It's clear that math:max() is intended to only work with numbers, but I think we need max/min functions that work with objects too.
public function max(object a) object b,c if atom(a) then return a end if if length(a) = 0 then return a end if b = a[1] for i = 2 to length(a) do c = a[i] if compare(c, b) > 0 then b = c end if end for return b end function
10. Re: Standard library praise and challenge
- Posted by SDPringle Sep 13, 2011
- 3272 views
Also with this recursing property is sum, product and or_all.
Just like max and min, these also recurse so that for any sequence s, sum(s) has the same value as sum(flatten(s)).
11. Re: Standard library praise and challenge
- Posted by bill Sep 14, 2011
- 3254 views
I don't see max or min of null ({}) being an error.
The max is as the min, {} (null).
The max and min of { {}, {'a'} } should be {'a'} as null cannot be less than or greater than another value.
- as in SQL.
12. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3226 views
I don't see max or min of null ({}) being an error.
The empty sequence construct is not null. It is not the same as the NULL concept found in database systems. It is simply a set with no elements, a list with no items, a bag with nothing inside.
Given an empty bag, pick out the largest object.
13. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3211 views
Also with this recursing property is sum, product and or_all.
Just like max and min, these also recurse so that for any sequence s, sum(s) has the same value as sum(flatten(s)).
For maths library, maybe this make sense (I'm not fully convinced of that yet, by the way), but it not always the intuitive result. For example, given a list that contains a mixture of numbers and strings, return the sum of that list. Most spreadsheet programs ignore non-numbers in the summing range, so maybe that's what people expect to happen.
14. Re: Standard library praise and challenge
- Posted by jeremy (admin) Sep 14, 2011
- 3199 views
I don't see max or min of null ({}) being an error.
The empty sequence construct is not null. It is not the same as the NULL concept found in database systems. It is simply a set with no elements, a list with no items, a bag with nothing inside.
Given an empty bag, pick out the largest object.
That's easy, no? From an empty bag the largest object is nothing.
max({}) -- {} min({}) -- {}
Jeremy
15. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3199 views
I don't see max or min of null ({}) being an error.
Same here.
The empty sequence construct is not null. It is not the same as the NULL concept found in database systems. It is simply a set with no elements, a list with no items, a bag with nothing inside.
That's easy, no? From an empty bag the largest object is nothing.
Yep, except for the small hitch that Euphoria has no object or singleton that can unambiguously represent 'nothing' or the NULL concept in general.
max({}) -- {} min({}) -- {}
Jeremy
Like Derek said, the empty sequence is not nothing. But he also said
I give you an empty bag and ask you to pull out the largest object. You can't pull out any object so therefore this is an error. The results are defined - you pull nothing out, which is of course neither the biggest nor the smallest, thus we have a problem - also known as an error situation. One way to signal this error is to just give back the bag.
And I, while wishing to clarify that the empty sequence is not nothing, agree with both Jeremy and Derek on this.
Of course, this is not perfect.
max({{}, {}}) -- returns {} also
But that's close enough for me. If it really matters, I'd just do an "is_empty" check on the original sequence after calling max()/min().
16. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3198 views
It would be nice if someone adds these changes to image.e: http://openeuphoria.org/pastey/90.wc
If no one else beats me to it, I'll review it and probably apply the patch sometime today.
17. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3220 views
It would be nice if someone adds these changes to image.e: http://openeuphoria.org/pastey/90.wc
If no one else beats me to it, I'll review it and probably apply the patch sometime today.
18. Re: Standard library praise and challenge
- Posted by bill Sep 14, 2011
- 3188 views
One can say {} is the empty sequence. True.
However that is not the case when you are comparing atoms. {} has no atom, nothing, NULL. Hence when the sequence is flattened the empty sub-sequences disappear (just as in SQL, NULLs are ignored).
It leaves the problem of what to do with max(NULL) and min(NULL). They should return nothing ({} or NAN). It is odd to call it an error since this would imply that min({{},1}) should also be an error as it is saying:
"which is smaller nothing or 1?"
Note the (inconsistent) treatment of NULL by compare:
include std/math.e 1: ? compare(MINF,MINF) 0 2: ? compare(MINF,min({})) -1 * 3: ? compare(MINF,max({})) 0 ** 4: ? compare(MINF,PINF) -1 5: ? compare(min({}),MINF) 1 * 6: ? compare(min({}),min({}) 0 7: ? compare(min({}),max({})) 1 ** 8: ? compare(min({}),PINF) 0 ** 9: ? compare(max({}),MINF) 0 ** 10: ? compare(max({}),min({})) -1 ** 11: ? compare(max({}),max({})) 0 12: ? compare(max({}),PINF) 0 * 13: ? compare(PINF,MINF) 1 14: ? compare(PINF,min({})) 0 ** 15: ? compare(PINF,max({})) 1 * 16: ? compare(PINF,PINF) 0
19. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3186 views
One can say {} is the empty sequence. True.
However that is not the case when you are comparing atoms.
Which is not the case for the (proposed) max() and min() in std/sequence.e
Note the (inconsistent) treatment of NULL by compare:
This is not inconsistent. The current implementation of max() and min() in std/math.e do not return a value representing NULL - they always return a valid atom.
Should they return NULL? Maybe. Currently, they don't.
20. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3168 views
One can say {} is the empty sequence. True.
However that is not the case when you are comparing atoms. {} has no atom, nothing, NULL. Hence when the sequence is flattened the empty sub-sequences disappear (just as in SQL, NULLs are ignored).
I can see what you're saying but one must not mistake an empty list for NULL. It really is not the same thing in Euphoria. While Euphoria does have a true NULL value, it is only used internally and we do not expose it to the coder. The NOVALUE value is not settable nor does the coder have a way to test for it. Maybe we should make this available for coders to use?
It leaves the problem of what to do with max(NULL) and min(NULL). They should return nothing ({} or NAN). It is odd to call it an error since this would imply that min({{},1}) should also be an error as it is saying:
"which is smaller nothing or 1?"
I see the problem of min({{},1}) differently. To me this is saying, of all the atoms in the argument, which is the smallest. In this case, the answer is 1 because that is the only atom in the argument.
Likewise, min({}) is also saying, of all the atoms in the argument, which is the smallest. In this case, the question is meaningless because there are no atoms in the argument. That is why I'm saying that this situation needs to return a value that means that nothing can be returned.
21. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3193 views
The NOVALUE value is not settable nor does the coder have a way to test for it. Maybe we should make this available for coders to use?
Actually, it can be tested! Use the object type. It might be good to allow euphoria code to explicitly use this. Also, I noticed that we're missing NaN in our math constants.
Matt
22. Re: Standard library praise and challenge
- Posted by bill Sep 14, 2011
- 3180 views
max({}) returns inf, max(1) returns 1
min({}) returns -inf, min(1) returns 1
IE max(atom x) = min(atom x): there is a problem here.
Comparing: min({}) > max({}), max({}) = MINF, min({}) = PINF, MINF < PINF.
This is all nonsense.
To be consistent min({}) and max({}) have to return the same non-value. A consistent mathematical result would be NAN or simply nothing - but one presumes that a function returns something.
By definition NAN: is not equal to NAN and NAN is not not equal to NAN. Like NULLs, NANs cannot be compared.
With sequences there are the possibiliites of an empty sequence (empty string) or NULL. An empty sequence can be compared. A NULL sequence cannot be compared (a sequence without a value assigned is an example).
23. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3188 views
With sequences there are the possibiliites of an empty sequence (empty string) or NULL. An empty sequence can be compared. A NULL sequence cannot be compared (a sequence without a value assigned is an example).
We don't have "NULL sequences", whatever those are. We only have empty sequences.
max({}) returns inf, max(1) returns 1
min({}) returns -inf, min(1) returns 1
IE max(atom x) = min(atom x): there is a problem here.
Comparing: min({}) > max({}), max({}) = MINF, min({}) = PINF, MINF < PINF.
This is all nonsense.
To be consistent min({}) and max({}) have to return the same non-value. A consistent mathematical result would be NAN or simply nothing - but one presumes that a function returns something.
By definition NAN: is not equal to NAN and NAN is not not equal to NAN. Like NULLs, NANs cannot be compared.
This works for me. I can live with math.e's max()/min() returning NaN when given {} as input.
24. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3183 views
To be consistent min({}) and max({}) have to return the same non-value. A consistent mathematical result would be NAN or simply nothing - but one presumes that a function returns something.
By definition NAN: is not equal to NAN and NAN is not not equal to NAN. Like NULLs, NANs cannot be compared.
With sequences there are the possibiliites of an empty sequence (empty string) or NULL. An empty sequence can be compared. A NULL sequence cannot be compared (a sequence without a value assigned is an example).
Exactly! The current implementation is not correct. However, Euphoria doesn't yet have a NaN that we can use. We should implement such a concept, even though it is not quite that easy to do well. If NaN can be an valid value in an expression or parameter, it affects lots of existing code.
25. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3171 views
However, Euphoria doesn't yet have a NaN that we can use. We should implement such a concept, even though it is not quite that easy to do well. If NaN can be an valid value in an expression or parameter, it affects lots of existing code.
I'm a bit confused. We might not have a constant in std/math.e or elsewhere, but we can do it:
constant NaN=-(2*power(10,308)/(3*power(10,308)))
26. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3182 views
However, Euphoria doesn't yet have a NaN that we can use. We should implement such a concept, even though it is not quite that easy to do well. If NaN can be an valid value in an expression or parameter, it affects lots of existing code.
I think the way to do this is to use the architecture appropriate floating point representation of NaN, similar to how we define the infinities, and expose it as a machine func via mathcons.e
Matt
27. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3157 views
-- nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN
It's not working!
$ eui nan.ex -0.6666666667
Matt
28. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3169 views
-- nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN
It's not working!
$ eui nan.ex -0.6666666667
Matt
Hmmm... works for me.
C:\temp>type nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN ? 3 + NaN function tn(object a) return a * 2 end function ? tn(NaN) C:\temp>eui nan.ex nan nan nan C:\temp>eui --version Euphoria Interpreter v4.0.4 development Windows, Using System Memory Revision Date: 2011-08-05 12:12:11, Id: 5095:8351f54dd765 C:\temp>
29. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3162 views
-- nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN
It's not working!
$ eui nan.ex -0.6666666667
Matt
Hmmm... works for me.
Sorry, that was my snarky way of saying that it's not a portable way to get a NaN. We use bigger floating point numbers for 64-bit euphoria, and 10e308 is a lot smaller than 1.19e4932.
Matt
30. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3178 views
-- nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN
It's not working!
$ eui nan.ex -0.6666666667
Matt
It works for me on 32bit. Try this on 64bit.
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
31. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3184 views
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
That gives me -nan.
Matt
32. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3193 views
Sorry, that was my snarky way of saying that it's not a portable way to get a NaN. We use bigger floating point numbers for 64-bit euphoria, and 10e308 is a lot smaller than 1.19e4932.
Matt
If only I was 104 seconds faster!
33. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3191 views
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
That gives me -nan.
Matt
Ok, I'm stumped.
34. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3162 views
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
That gives me -nan.
Matt
Ok, I'm stumped.
The representation of what you created is:
{0,0,0,0,0,0,0,192,255,255}
The sign bit is set, hence the negative. "Positive" NaN is:
{0,0,0,0,0,0,0,192,255,127}
Matt
35. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3169 views
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
That gives me -nan.
Matt
Ok, I'm stumped.
The representation of what you created is:
{0,0,0,0,0,0,0,192,255,255}
The sign bit is set, hence the negative. "Positive" NaN is:
{0,0,0,0,0,0,0,192,255,127}
Matt
I understand the difference, but I'm still clueless on how to create positive NaN. Surely it's not as simple as multiplying by -1 ?
36. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3161 views
I understand the difference, but I'm still clueless on how to create positive NaN. Surely it's not as simple as multiplying by -1 ?
I think you can do stuff like sqrt(-1) (assuming you have exceptions or whatever turned off correctly). The right way is to use whatever the language provides. GCC, for instance, provides a NAN macro (on machines that support NANs in the first place). For recent enough versions, they use __builtin_nanf:
// gcc nan.c -o nan #include <stdio.h> #include <math.h> int main(){ long double ld; double d; d = NAN; ld = NAN; printf("%lg %Lg\n", d, ld ); return 0; }
$ gcc nan.c -o nan && ./nan nan nan
The headers define floats by explicit bytes for older versions of gcc.
Matt
37. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 14, 2011
- 3145 views
I understand the difference, but I'm still clueless on how to create positive NaN. Surely it's not as simple as multiplying by -1 ?
I think you can do stuff like sqrt(-1) (assuming you have exceptions or whatever turned off correctly).
I was looking for a quick series of mathematical functions that'd work as-in in 4.0 and 4.1 that would do the job, to prove a point.
(sqrt(-1) does not work in 4.0, btw).
The right way is to use whatever the language provides.
Agreed. Above all, I was trying to avoid this:
The headers define floats by explicit bytes for older versions of gcc.
Anyways, back to my original point: NaN and Nothing are conceptually separate values. NaN is a floating point number with a specific set of representations that are defined as the value of certain floating point operations (such as sqrt(-1) or fdiv(inf, inf)).
While it may make sense for NaN to be the output of std/math.e's min() and max() and sum() and perhaps even or_all() when they are given an empty sequence as input, NaN does not work the same way as our NOVALUE (or even Python's Nothing object).
38. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3156 views
Anyways, back to my original point: NaN and Nothing are conceptually separate values.
Yes, I totally agree. I just noticed that NaN was missing from our collection of constants.
While it may make sense for NaN to be the output of std/math.e's min() and max() and sum() and perhaps even or_all() when they are given an empty sequence as input, NaN does not work the same way as our NOVALUE (or even Python's Nothing object).
I wouldn't use NaN for that (ideally). I'd prefer to use NOVALUE. I suppose one issue we have with that is the way we currently check for initialized values, which is to say, as little as possible. Allowing NOVALUE to be used explicitly would cause all sorts of new bugs.
OTOH, if you're passing an empty sequence to max/min, then you probably have a bug in your code already.
Matt
39. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 14, 2011
- 3129 views
I understand the difference, but I'm still clueless on how to create positive NaN. Surely it's not as simple as multiplying by -1 ?
Does this work for you guys?
include std/convert.e constant NaN= float64_to_atom({0,0,0,0,0,192,255,127}) ? NaN ? 3 + NaN function tn(object a) return a * 2 end function ? tn(NaN)
40. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 14, 2011
- 3121 views
Does this work for you guys?
include std/convert.e constant NaN= float64_to_atom({0,0,0,0,0,192,255,127}) ? NaN ? 3 + NaN function tn(object a) return a * 2 end function ? tn(NaN)
I get all nans on 4.1 64-bit.
Matt
41. Re: Standard library praise and challenge
- Posted by jeremy (admin) Sep 14, 2011
- 3107 views
Does this work for you guys?
include std/convert.e constant NaN= float64_to_atom({0,0,0,0,0,192,255,127}) ? NaN ? 3 + NaN function tn(object a) return a * 2 end function ? tn(NaN)
I get nan's.
C:\Development\Projects>eui test.ex nan nan nan C:\Development\Projects>eui -v Euphoria Interpreter v4.1.0 development 32-bit Windows, Using System Memory Revision Date: 2011-09-09 18:29:16, Id: 5145:0da3aad80586
42. Re: Standard library praise and challenge
- Posted by petelomax Sep 15, 2011
- 3108 views
-- nan.ex constant NaN=-(2*power(10,308)/(3*power(10,308))) ? NaN
It's not working!
-- nan.ex constant NaN=(2*power(10,9008)/(3*power(10,9008))) ? NaN
That gives me -nan.
Matt
Bit late, but there's no '-' in the second expression. The float64_to_atom is probably faster anyway.
Pete
43. Re: Standard library praise and challenge
- Posted by SDPringle Sep 15, 2011
- 3059 views
It would surprise me that a programmer without enough forethought to check to see if a sequence has no length (or ensure it always has some length) before calling min() or max() will have forethought to check for an error code. In the case where a programmer is not diligent, whatever that error code is for passing {}, be it, the bag({}), NaN, PINF, NINF, or "WTF", will be used in the next calculation as if everything is till okay.
Most recently, I was interested in what the maximum tension on a joint inside of a truss system for choosing the kind of joint one should use. The error value would be used to determine what joint type to use. Logical errors propagate through the code until the program says that the weakest joint is okay to use.
This following is an abbreviation of what I wrote for my private library and I use it myself. If you don't want to check for errors you turn type checking off. max and min assume that s[1] exists. There is no need to return nan, PINF, NINF, or "".
type nonemptysequence(sequence s) return length(s) != 0 end type function max(nonemptysequence s) ... function min(nonemptysequence s) ...
Shawn Pringle
44. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 15, 2011
- 3034 views
It would surprise me that a programmer without enough forethought to check to see if a sequence has no length (or ensure it always has some length) before calling min() or max() will have forethought to check for an error code. In the case where a programmer is not diligent, whatever that error code is for passing {}, be it, the bag({}), NaN, PINF, NINF, or "WTF", will be used in the next calculation as if everything is till okay.
Most recently, I was interested in what the maximum tension on a joint inside of a truss system for choosing the kind of joint one should use. The error value would be used to determine what joint type to use. Logical errors propagate through the code until the program says that the weakest joint is okay to use.
This following is an abbreviation of what I wrote for my private library and I use it myself. If you don't want to check for errors you turn type checking off. max and min assume that s[1] exists. There is no need to return nan, PINF, NINF, or "".
type nonemptysequence(sequence s) return length(s) != 0 end type function max(nonemptysequence s) ... function min(nonemptysequence s) ...
Shawn Pringle
Seconded.
45. Re: Standard library praise and challenge
- Posted by petelomax Sep 16, 2011
- 2998 views
Of course I'm still smarting that max(sequence s) exists at all.
It should be max_sq(sequence s) and max(atom,atom).
Pete
46. Re: Standard library praise and challenge
- Posted by euphoric (admin) Sep 16, 2011
- 2991 views
It should be max_sq(sequence s) and max(atom,atom).
Or even just maxs(sequence s) and max(atom,atom). In line with puts() gets() etc...
47. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 16, 2011
- 2976 views
It should be max_sq(sequence s) and max(atom,atom).
Or even just maxs(sequence s) and max(atom,atom). In line with puts() gets() etc...
Or...
public function max( object a, object b = a ) if atom(a) then if a >= b then return a else return b end if end if b = mathcons:MINF atom c for i = 1 to length(a) do c = max(a[i]) if c > b then b = c end if end for return b end function
Matt
48. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 16, 2011
- 3000 views
It should be max_sq(sequence s) and max(atom,atom).
Or even just maxs(sequence s) and max(atom,atom). In line with puts() gets() etc...
Or...
public function max( object a, object b = a ) if atom(a) then if a >= b then return a else return b end if end if b = mathcons:MINF atom c for i = 1 to length(a) do c = max(a[i]) if c > b then b = c end if end for return b end function
Matt
But then what happens if I do
? max("First", "Second")
49. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 16, 2011
- 2966 views
But then what happens if I do
? max("First", "Second")
Under that, you'd get the max of "First". I would have documented that the function was to be used in the ways that Pete was looking for, which make sense as a math function, to me. Your use appears to be looking for the general object comparison, which I think we were saying should be somewhere else.
Matt
50. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 16, 2011
- 2994 views
Your use appears to be looking for the general object comparison, which I think we were saying should be somewhere else.
We already have smaller_of(object,object) and larger_of(object,object)
51. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 16, 2011
- 2984 views
Your use appears to be looking for the general object comparison, which I think we were saying should be somewhere else.
We already have smaller_of(object,object) and larger_of(object,object)
I thought so! But I couldn't remember those names. I don't spend enough time in the stdlib. I was looking for greatest/greater/bigger.
Matt
52. Re: Standard library praise and challenge
- Posted by useless Sep 17, 2011
- 2986 views
As if it mattered, i believe NULL = NULL. If i have nothing in both paws, then i have the same amount of the same nothing in both paws, ergo the contents of both paws are equal. I understand NULL != zero, but i didn't define what i have nothing of in my paws, if i have "no worms" then i have zero worms, and that's not NULL.
But NaN is not the same, as if x = "blah", y = burb", x is NaN , y is a NaN, but they are different NaNs. If you are not in the right include file to deal with x and y, best you can return is their commonality, in math.e (or whatever) math.compare(x,y) = NaN. But it's not NULL, they are something, but in math.e the comparison may be illogical (or maybe it isn't). Doing this in string.e would give a different answer.
If i asked for the pointer to a function, and you gave me NULL, i believe the function does not exist. But if you give me NaN, then i believe you made an error.
useless, naturally
53. Re: Standard library praise and challenge
- Posted by SDPringle Sep 18, 2011
- 2936 views
There seems to be very divergent opinions on what should happen with max
Mine are:
max(atom) => typecheck error max({}) => typecheck error max({4,32,2}) => 32 max({"Ax",'a'}) => "Ax" max({"Ursula","Susan","Barbara"}) => "Ursula"
Similar results with min. sum and product should work as if you string the members with separators + and * respectively. or_all should work as if you run or_bits(..,or_bits(..., ... ) on the members. The members of a sequence s are defined as s[1], s[2], ... , s[$]. Fortunately, we have namespaces and we can roll our own function definitions.
Shawn Pringle
55. Re: Standard library praise and challenge
- Posted by bill Sep 18, 2011
- 2957 views
Re
type nonemptysequence(sequence s) return length(s) != 0 end type function max(nonemptysequence s) ... function min(nonemptysequence s) ...
no good
nonemptysequence S = { {} } length(S) is 1 max(S) is -inf
56. Re: Standard library praise and challenge
- Posted by bill Sep 18, 2011
- 2920 views
Start with 'a' < {}.
This can only make sense if 'a' and {} are of the same type (object).
We have an order:
MIN_REAL,..,MAX_REAL,{},{MIN_REAL},..,{MAX_REAL},{ {} },..
Max is declared to be max(object a) and returns the maximum atom of the flattened list.
Given this max({}) is an error as is max({}} and max({ {},{} }) even though they are valid lists.
A general form of max() would be max(sequence S) where S is a list of objects (possibly empty).
An empty list would then return an empty list; a non-empty list would return a list containing its maximum element. Min() would work similarly.
Examples:
max({}) ==> {} max({ {} }) ==> { {} } max({ {},{} } ==> { {} } max({"head","tail"} ==> {"tail"} max("head") ==> ('h')
That, I hope covers it.
57. Re: Standard library praise and challenge
- Posted by SDPringle Sep 18, 2011
- 2906 views
I want to clarify that the special cases for max and min that I described here were not meant to be descriptions of the standard library functions max and min. Rather, what functions with these names in my private library return and what they should return according to my philosophy.
The standard library returns some value for max{} and min{}. It flattens its argument. Meaning max({{24,4},{400}}) is the same as max({24,4,400}) in the standard library.
The ones I developed error out when passed an atom or an empty sequence. It doesn't flatten its argument. You can find a maximum or minimum object of a sequence of elements. The arguments may all be strings or matrices.
My max and min were developed separately before I joined this project and the existing max and mins in the standard library were already there when I joined. AFAIK.
Shawn Pringle
58. Re: Standard library praise and challenge
- Posted by bill Sep 18, 2011
- 2884 views
I agree that the library max function is no good.
I could understand someone writing max(flatten(S)) if that is what they wanted to do (why?). I don't understand why the argument to max should be flattened as part of the max function. It makes nonsense of the sort order of object.
I don't have a problem about returning the max of {} or the max of a number because max(3,3) is 3 and max({3}) is 3. I would rather max didn't return an error unless it had to (eg max()).
My function is:
function max(sequence S) -- accepts a (possibly empty) sequence of objects -- returns either an 0 length list or a list containing the maximum item in the list if length(S) < 2 then return S else sequence R = S[1] for i = 2 to length(S) do if S[i] > R[1] then R[1] = S[i] end if end for return R end if end function max({1,2,3,4}) ==> {4} max({ {},{} }) ==> { {} } max({1,2,{0} }) ==> { {0} } max({}) ==> { }
All are exactly what you would expect, except (perhaps) for the last. And, returning the empty list as the max of an empty list is logical and should give no one headaches.
Bill
59. Re: Standard library praise and challenge
- Posted by SDPringle Sep 20, 2011
- 2790 views
I think Bill, Jim, Derek and I are in agreement of what max() and conversely min() should do when the list is not empty. When the list is empty is result is rather academic from my point of view.
Condier though:
- EUPHORIA's routines tend to die rather than give an error code when given bad parameters. Let's be consistent here. In general I prefer to see an error code but there is no way to tell an error code from a result here.
- Certainly, the idea of what a maximum of the empty set is undefined.
- It follows that the interpreter should die in this case.
Consider division by 0. There is no NaN returned. It dies, instead. This is the way the work is designed. Instead of going off into different directions we should try to keep with the same design principles.
Shawn Pringle
60. Re: Standard library praise and challenge
- Posted by euphoric (admin) Sep 20, 2011
- 2762 views
- EUPHORIA's routines tend to die rather than give an error code when given bad parameters. Let's be consistent here. In general I prefer to see an error code but there is no way to tell an error code from a result here.
I think value() provides an error code, so there is a precedent.
result = { [NOT] SUCCESS, 23 } -- one way to do it
I suspect Derek expects an exceptions feature to eventually handle all this, but for now...?
61. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 20, 2011
- 2774 views
- EUPHORIA's routines tend to die rather than give an error code when given bad parameters. Let's be consistent here. In general I prefer to see an error code but there is no way to tell an error code from a result here.
I think value() provides an error code, so there is a precedent.
result = { [NOT] SUCCESS, 23 } -- one way to do it
I suspect Derek expects an exceptions feature to eventually handle all this, but for now...?
I am not in favor of the radical change in the type of return value.
Consider this:
The input to value() could come from anywhere. When value() returned an error code, that signalled a problem but the code could still continue. E.g. if you use value() to get a number but the user types "hello world" instead, you can prompt the user to reenter the number.
This sort of error is recoverable, and can not easily be validated by the calling code (at least, not without duplicating much of the functionality of value() itself).
The sole error with max()/min() can be checked for easily (a simple length check and possibly a type check to make sure it's a sequence) - and as Matt and Shawn and others have pointed out, it's an error that usually signifies a greater problem in the calling code - one that's probably irrecoverable beyond closing all open files, showing the appropriate prompt to the user, and then dying gracefully.
Also, this is a very minor point, but consider anyways:
value() has multiple error codes (well, 2 - failure and eof) whereas we only have the one for max()/min()
62. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 20, 2011
- 2766 views
I think Bill, Jim, Derek and I are in agreement of what max() and conversely min() should do when the list is not empty.
I can't speak for the others but I agree with this statement.
When the list is empty is result is rather academic from my point of view.
Agreed.
Condier though:
- EUPHORIA's routines tend to die rather than give an error code when given bad parameters. Let's be consistent here. In general I prefer to see an error code but there is no way to tell an error code from a result here.
- Certainly, the idea of what a maximum of the empty set is undefined.
- It follows that the interpreter should die in this case.
Consider division by 0. There is no NaN returned. It dies, instead. This is the way the work is designed. Instead of going off into different directions we should try to keep with the same design principles.
Shawn Pringle
Agreed. Even sqrt(-1) dies instead of returning NaN, despite the latter behavior being explicitly allowed by the floating point standard.
I think this is also keeping with the design principle of "Fail Early."
63. Re: Standard library praise and challenge
- Posted by bill Sep 21, 2011
- 2647 views
The only reason why I would object to dying or error on max({}) is:
One is returning the maximum of a list:
An empty list is a valid list,
{} is (potentially) a member of every list.
MAXREAL < {} < {MINREAL} i.e. it has an ordering whereas sqrt(-1) does not.
I think it would be advisable to avoid a situation where max({}) dies or raises an error but max({ {} }) and max({ {},{} }) do not.
Jim: remember I am not returning an atom.
64. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 21, 2011
- 2666 views
Jim: remember I am not returning an atom.
Relevance?
65. Re: Standard library praise and challenge
- Posted by bill Sep 22, 2011
- 2628 views
Objects:
you said:
Agreed. Even sqrt(-1) dies instead of returning NaN, despite the latter behavior being explicitly allowed by the floating point standard. I think this is also keeping with the design principle of "Fail Early."
Sqrt(-1) should not return NaN because i is not anything like a real or a sequence. There cannot be an order for complex numbers unless you define 2 numbers as being equal if the distance from (0,0) (or (0,0,0) ... etc is the same) (metric spaces).
If max({}) fails what of max({ {} }). Are you say max() can only return a number?
Bill
66. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Sep 22, 2011
- 2616 views
If max({}) fails what of max({ {} }). Are you say max() can only return a number?
I think that max()/min() functions only make sense if there is a minimum of two items to compare. And I certainly think the current recursive aspect of the math library functions is a mistake.
Now one might argue that an edge case is when a list has only a single item, in which case that item is returned. But when a list has no items, returning which of those non-existent items is the max/min is meaningless. In such a case, the function should either return ...
- a value that unambiguously indicates that an empty list was passed
- crash
- throw an exception
For now, I prefer the second option; crash the application.
There is no unambiguous value that can be returned with the current Euphoria. We can't use {} or NaN, because both of those might actually be one of the items in a non-empty list.
And of course, Euphoria doesn't have exceptions yet.
If your application has a real case in which an empty list can be validly passed to the function, then you should test for that explicitly as I suspect it would be a rare thing in general.
67. Re: Standard library praise and challenge
- Posted by jimcbrown (admin) Sep 22, 2011
- 2606 views
Objects:
you said:
Agreed. Even sqrt(-1) dies instead of returning NaN, despite the latter behavior being explicitly allowed by the floating point standard. I think this is also keeping with the design principle of "Fail Early."
Sqrt(-1) should not return NaN because i is not anything like a real or a sequence.
You may disagree, but this is specified in the floating point standard. After all, NaN does not specify a real number - it literally stands for Not A Number.
I suppose we could just return {} from sqrt(-1). This is clearly not a number, although the return value could be confused with the result of sqrt({}).
If max({}) fails what of max({ {} }). Are you say max() can only return a number?
Bill
max({ {} }) returns {} but max({}) fails. max({ {}, {} }) returns {}.
68. Re: Standard library praise and challenge
- Posted by mattlewis (admin) Sep 22, 2011
- 2610 views
...stuff...
...different stuff...
Ack. This is why I like to stay away from stdlib development and focus on the interpreter, et.al., where I can deal with less controversial subject matter like goto.
Matt
69. Re: Standard library praise and challenge
- Posted by SDPringle Sep 23, 2011
- 2472 views
...stuff...
...different stuff...
Ack. This is why I like to stay away from stdlib development and focus on the interpreter, et.al., where I can deal with less controversial subject matter like goto.
Matt
Its posts like these that make me wish we had like buttons for the forum. :)
Shawn
70. Re: Standard library praise and challenge
- Posted by Insolor Mar 01, 2012
- 2098 views
Today I looked inside std/sequence.e and have seen this:
public function add_item(object needle, sequence haystack, integer pOrder = 1) if find(needle, haystack) then return haystack end if switch pOrder do case ADD_PREPEND then return prepend(haystack, needle) case ADD_APPEND then return append(haystack, needle) case ADD_SORT_UP then return stdsort:sort(append(haystack, needle)) case ADD_SORT_DOWN then return stdsort:sort(append(haystack, needle), stdsort:DESCENDING) case else error:crash("sequence.e:add_item() invalid Order argument '%d'", pOrder) end switch return haystack end function
Why not to replace this
stdsort:sort(append(haystack, needle))
with some sort of binary insertion function? This approach would be is less reliable (eg. function will not know if the sequence have a proper order, presorting will be up to a user), but it would be much faster on long sequences.
P.S. something like this:
eu:insert(haystack,needle,math:abs(search:binary_search(needle,haystack)))
71. Re: Standard library praise and challenge
- Posted by DerekParnell (admin) Mar 01, 2012
- 2057 views
Why not to replace this
stdsort:sort(append(haystack, needle))
with some sort of binary insertion function?
I wouldn't like to replace the existing functionality but we could certainly add to it. Maybe a new code INSERT_SORTED that would insert the new item into an already sorted list.