1. Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 07, 2014
- 4686 views
Currently this is illegal ...
sequence x x = append(1,2)
We get the error message ...
first argument of append must be a sequenceWould it be a bad thing to remove this restriction such that when appending to an atom, Euphoria would automatically build a new sequence? This would be similar to how concatenation works.
sequence x x = 1 & 2 -- No error. Creates {1,2}
In my current code, I ran across this case and had to code an explicit test to get around it. This is 'ugly' and makes the code a bit slower and larger.
function F(object A, object B) sequence x if atom(A) then x = append({A}, B) else x = append(A, B) end if return x end function
2. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 07, 2014
- 4660 views
Currently this is illegal ...
sequence x x = append(1,2)
We get the error message ...
first argument of append must be a sequenceWould it be a bad thing to remove this restriction such that when appending to an atom, Euphoria would automatically build a new sequence? This would be similar to how concatenation works.
Agreed. Let's do this.
3. Re: Discuss changing the behaviour of append()
- Posted by ghaberek (admin) Jun 07, 2014
- 4654 views
This seems like an innocuous and intuitive change. You have my vote.
-Greg
4. Re: Discuss changing the behaviour of append()
- Posted by ArthurCrump Jun 07, 2014
- 4614 views
A similar unnecessary restriction applies to prepend
Arthur
5. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 07, 2014
- 4591 views
Would it be a bad thing to remove this restriction such that when appending to an atom, Euphoria would automatically build a new sequence? This would be similar to how concatenation works.
Simple answer: not such a good idea.
The function append is:
fn(seq, obj) -> seq
The proposed change would require that append be
fn(obj, obj) -> seqwhich makes the test part of append whether you want it or not.
It would seem that append is wanted most often when the first parameter is a sequence....
As to the code being 'ugly' ..
function F(object A, object B) sequence x if atom(A) then x = append({A}, B) else x = append(A, B) end if return x end function
try
function F(object A, object B) if atom(A) then A = {A] end if return append(A, B) end function
or, ditching the function
sequence x if atom(A) then x = append({A},B) else x = append(A,B) end if
6. Re: Discuss changing the behaviour of append()
- Posted by PeteE Jun 07, 2014
- 4560 views
The proposed change would require that append be
fn(obj, obj) -> seqwhich makes the test part of append whether you want it or not.
The test is already part of append, and it triggers the error message "first argument of append must be a sequence". Instead of the error, the proposed change will convert the atom to a sequence first and proceed.
I like it.
7. Re: Discuss changing the behaviour of append()
- Posted by PeteE Jun 07, 2014
- 4564 views
oops, double post
8. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 08, 2014
- 4556 views
Well - that is interesting,
You pass a sequence to append,
Append checks that it got a sequence.
Double work.
It seems to me that append is entitled to crash if you pass in an atom. That it actually checks before dying...
Leaving aside the convenience of append(1,2) as opposed to {1,2} or 1 & 2.
Isn't it true that if you don't know X is a sequence you shouldn't be appending to it?
Isn't this what types are about?
Isn't this to say that it is up to the caller to ensure that the parameters are of the correct type.
and
It is not up to the called function to validate its parameters.
9. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 08, 2014
- 4561 views
Well - that is interesting,
You pass a sequence to append,
Append checks that it got a sequence.
Double work.
IIUC this is only the case using the interpreter. The translator does not seem to check.
It seems to me that append is entitled to crash if you pass in an atom. That it actually checks before dying...
Well, in general having a human readable error message is quite helpful. But for this to happen (and this generally doesn't happen with the translator btw), something needs to check somewhere.
Leaving aside the convenience of append(1,2) as opposed to {1,2} or 1 & 2.
Isn't it true that if you don't know X is a sequence you shouldn't be appending to it?
Isn't this what types are about?
Isn't this to say that it is up to the caller to ensure that the parameters are of the correct type.
and
It is not up to the called function to validate its parameters.
Agreed, the language itself should do that validation. Which is what actually happens.
10. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 08, 2014
- 4554 views
Jim,
If it is the case the translator doesn't check then it would make sense not to change append's behaviour.
Append is surely used > 99.9% in situations where a sequence is passed as parameter.
To account for the < 0.1% of cases where an atom is passed by changing the function does not make sense.
Every use of the function takes an (admittedly small) hit to allow an atom to be passed as if it were a sequence. There are probably more than a few functions which could benefit from this and a few more which could benefit from allowing sequences to be passed as atoms.
Probably a lot of these implicit conversions are stupid or unsafe.
In the long run it's your language and you can do with it as you like.
11. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 08, 2014
- 4570 views
I believe among new users or infrequent users, if a user passes an atom as a first argument to append, it is probably because they are accidentally reversing the order of the parameters and not because they want to treat atoms as length-one sequences that contain that atom.
12. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 08, 2014
- 4524 views
Every use of the function takes an (admittedly small) hit to allow an atom to be passed as if it were a sequence. There are probably more than a few functions which could benefit from this and a few more which could benefit from allowing sequences to be passed as atoms.
If it is the case the translator doesn't check then it would make sense not to change append's behaviour.
Why? If it's for performance reasons then I'd disagree - usability comes first.
Append is surely used > 99.9% in situations where a sequence is passed as parameter.
Right now it's 100% (not including errors).
To account for the < 0.1% of cases where an atom is passed by changing the function does not make sense.
Sure it does! At least, I think there had better be a good reason if we're going to exclude a minority.
Probably a lot of these implicit conversions are stupid or unsafe.
I don't follow.
In the long run it's your language and you can do with it as you like.
Well, not mine personally. It's a community and a group decision. But, well, yeah...
13. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 08, 2014
- 4535 views
I believe among new users or infrequent users, if a user passes an atom as a first argument to append, it is probably because they are accidentally reversing the order of the parameters and not because they want to treat atoms as length-one sequences that contain that atom.
Um, wow.
That's a pretty good argument.
It's better to fail early than introduce a logic error which may not be caught until much much later.
If you are right, then users could be confused as to why append is starting to act like prepend.
That said, I still think this is unlikely to happen. It'd be inconsistent with the order of parameters in the basic math operators (e.g. subtraction and division) and concatenation.
14. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 08, 2014
- 4538 views
Isn't it true that if you don't know X is a sequence you shouldn't be appending to it?
The situation that I needed it was when I was working with elements of a sequence. In other words, I was working with objects and I don't know if they are sequences or atoms unless I specifically check for it.
Ok, let's change the approach. If Euphoria didn't have an append function, and one was being proposed, why would the first parameter necessarily have to be a sequence? In terms of functionality, the difference between append and concatenate, is that append joins the second parameter as ONE object to the first parameter, and concatenate joins the second parameter as a set of zero or more objects to the first parameter. Why must append have a sequence as the first parameter and concatenate doesn't?
15. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 08, 2014
- 4513 views
I believe among new users or infrequent users, if a user passes an atom as a first argument to append, it is probably because they are accidentally reversing the order of the parameters and not because they want to treat atoms as length-one sequences that contain that atom.
I was just going to say something similar, in particular str=prepend(ch,str) has been nicely caught for me a few times, but to be honest if I know I'm adding an atom, I'll use &, and if I'm adding a sequence, the extra type check helps not one tiny bit.
However, I would like to suggest appenda() [and prependa], see what people have to say about that. Or maybe appendany()/prependany() if you prefer.
Pete
Edit: "Why must append have a sequence as the first parameter and concatenate doesn't?"
That certainly hits the nail on the head. Apart from "trying to be helpful but not really managing it", I got no answer to that.
16. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 08, 2014
- 4515 views
I believe among new users or infrequent users, if a user passes an atom as a first argument to append, it is probably because they are accidentally reversing the order of the parameters and not because they want to treat atoms as length-one sequences that contain that atom.
Sometimes, one just has to learn the API. For example, ...
-- Ensure that the output has a new-line added. puts(NEWLINE, STDOUT)
Oops! Parameters are the wrong way around.
17. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 09, 2014
- 4523 views
Derek,
I was aware of the (inconsistent?) behaviour of one element sequences. You can have append do what you want by calling append as:
append(S[1..1], 2) -- coercing S[1] to a sequence
Some clarification.
sequence S = {0,1,2,3} ? length(S[1..0]) -- 0 ? sequence(S[1..0]) -- true ? atom(S[1..0]) -- false ? length(S[1..1]) -- 1 ? sequence(S[1..1]) -- true (slice coerces sequence type) ? atom(S[1..1]) -- false ? length(S[1]) -- 1 (odd!) ? sequence(S[1]) -- false (odd!) ? atom(S[1]) -- true ? append(S[1..1],2) -- {0,2} ? append(S[1],2) -- error
18. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 09, 2014
- 4502 views
You can have append do what you want by calling append as:
append(S[1..1], 2) -- coercing S[1] to a sequence
While more 'elegant', it does have a performance aspect that I was also hoping to avoid.
19. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 09, 2014
- 4463 views
I think the basic problem is that S[i] is not (fully) a sequence.
Every slice is a sequence,
S[i] has a length so it is a sequence,
Yet it can type as an atom.
It seems what you need here is an operator which 'converts' an atom to a sequence.
S[i] & {} -- would work as well as S[i..i] -- but they are fixes
but perhaps we need an explicit operator which minimises the cost of the operation.
I really don't think putting the burden on append is appropriate as you would need to do the same with other functions (prepend ..)
and
append has the right to expect a sequence as parameter
(otherwise why specify types at all?)
20. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 09, 2014
- 4474 views
S[i] has a length so it is a sequence,
Yet it can type as an atom.
Not so. length() simply returns 1 if the object is not a sequence. This change was made for the same reason we are discussing changing append()/prepend() - so to not fix them as well would be to leave the language in an inconsistent state.
21. Re: Discuss changing the behaviour of append()
- Posted by ryanj Jun 09, 2014
- 4454 views
Currently this is illegal ...
sequence x x = append(1,2)
sequence x x = 1 & 2 -- No error. Creates {1,2}
Why not just use & then? What's the advantage of append(), anyway? I don't think i ever use it.
22. Re: Discuss changing the behaviour of append()
- Posted by ArthurCrump Jun 09, 2014
- 4433 views
Why not just use & then? What's the advantage of append(), anyway? I don't think i ever use it.
a = {1,2} & {3,4} -- and b = append({1,2},{3,4})
give different results:
a is {1,2,3,4}
b is {1,2,{3,4}}
Arthur
23. Re: Discuss changing the behaviour of append()
- Posted by ArthurCrump Jun 09, 2014
- 4445 views
A similar unnecessary restriction applies to prepend
Arthur
To suggest the same for prepend was not such a good idea.
There is unlikely to be any confusion appending a new object to an atom, but prepend has its operands in reverse order so that
x = prepend(1,2)
would give x={2,1} if it was allowed.
That could be confusing
Arthur
24. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 09, 2014
- 4452 views
Why not just use & then? What's the advantage of append(), anyway? I don't think i ever use it.
a = {1,2} & {3,4} -- and b = append({1,2},{3,4})
give different results:
a is {1,2,3,4}
b is {1,2,{3,4}}
Arthur
But you can easily simulate the behavior of append like this:
a = {1,2} & {{3,4}} -- and b = append({1,2},{3,4})
It's a good way to make up for the lack of an append= operator:
a &= {{3,4}} -- and b = append(b,{3,4})
25. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 10, 2014
- 4390 views
A similar unnecessary restriction applies to prepend
Arthur
To suggest the same for prepend was not such a good idea.
There is unlikely to be any confusion appending a new object to an atom,
flw
but prepend has its operands in reverse order
Erm, let's just agree that the arguments to prepend are in the same order as append, but of course the result is (sort of) the other way round
so that
x = prepend(1,2)
would give x={2,1} if it was allowed.
That could be confusing
Hmm. You lost me there. Why exactly is that any more confusing than
x = prepend({1},2)
giving x={2,1}?
Pete
26. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 10, 2014
- 4387 views
I think I've just realised where this is all going.
Given that length(atom) now returns 1, and I never thought I'd say this, but, it is only logical that atom[1] becomes valid.
Bit of a shocker, I agree, but there it is.
Pete
27. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 10, 2014
- 4396 views
I think the basic problem is that S[i] is not (fully) a sequence.
Every slice is a sequence,
S[i] has a length so it is a sequence,
Yet it can type as an atom.
It seems what you need here is an operator which 'converts' an atom to a sequence.
S[i] & {} -- would work as well as S[i..i] -- but they are fixes
Unfortunately, this is NOT the issue. I'll restate the problem using different words.
Given an object X, I want to create a sequence by adding another object Y, such that the last item in the newly created sequence is Y, and all the other items in X are unaltered.
Examples ...
X = 4 Y = {8,9} --Result is {4, {8,9}} X = {4} Y = {8,9} --Result is {4, {8,9}} X = {4,5} Y = {8,9} --Result is {4, 5, {8,9}} X = {} Y = {8,9} --Result is {{8,9}}
In all but the first case, the append() function will suffice. But with the first case I need to convert X to a sequence first. That is what I'm hoping to avoid doing; the 'manually' conversion. Instead I'd like Euphoria to do it automatically.
The only suggestion so far that works in each of the case above is the 'concatenate a sequence' trick, but that has a performance hit of creating a temporary sequence and then disposing of it after the operation has completed. Something I'd also like to avoid.
object X, Y X = 4 Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4} Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4,5} Y = {8,9} X &= {Y} --Result is {4, 5, {8,9}} X = {} Y = {8,9} X &= {Y} --Result is {{8,9}}
So, if the change is made to Euphoria's append()/prepend() functions to do this, programs that now currently fail in this situation will no longer fail. Is that okay?
28. Re: Discuss changing the behaviour of append()
- Posted by mattlewis (admin) Jun 10, 2014
- 4363 views
object X, Y X = 4 Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4} Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4,5} Y = {8,9} X &= {Y} --Result is {4, 5, {8,9}} X = {} Y = {8,9} X &= {Y} --Result is {{8,9}}
So, if the change is made to Euphoria's append()/prepend() functions to do this, programs that now currently fail in this situation will no longer fail. Is that okay?
This seems like a positive change.
Matt
29. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 10, 2014
- 4315 views
object X, Y X = 4 Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4} Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4,5} Y = {8,9} X &= {Y} --Result is {4, 5, {8,9}} X = {} Y = {8,9} X &= {Y} --Result is {{8,9}}
So, if the change is made to Euphoria's append()/prepend() functions to do this, programs that now currently fail in this situation will no longer fail. Is that okay?
These append()/prepend() are for operations with sequences (in pure 20 years old EU).
So, if you do not have some sequence to operate with, just do not use append()/prepend().
Use & and be happy :)
Regards
kinz
30. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 10, 2014
- 4336 views
(Edit)
Nevermind -- I see my error.
31. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 10, 2014
- 4357 views
object X, Y X = 4 Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4} Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4,5} Y = {8,9} X &= {Y} --Result is {4, 5, {8,9}} X = {} Y = {8,9} X &= {Y} --Result is {{8,9}}
So, if the change is made to Euphoria's append()/prepend() functions to do this, programs that now currently fail in this situation will no longer fail. Is that okay?
This seems like a positive change.
Matt
Maybe I'm not following very closely and misunderstanding. How in the first case would you concatenate to make a single-level sequence?
object X, Y X = 4 Y = {8,9} -- what operation do I need to form {4, 8, 9}? X = {4, 5} Y = {8,9} -- what operation do I need to form {4, 5, 8, 9}? X = "foo" Y = "bar" -- what operation do I need to form "foobar"?
It's like this:
object X, Y X = 4 Y = {8,9} X &= Y --Result is {4, 8, 9} X = 4 Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4} Y = {8,9} X &= Y --Result is {4, 8, 9} X = {4} Y = {8,9} X &= {Y} --Result is {4, {8,9}} X = {4,5} Y = {8,9} X &= Y --Result is {4, 5, 8, 9} X = {4,5} Y = {8,9} X &= {Y} --Result is {4, 5, {8,9}} X = "foo" Y = "bar" X &= Y --Result is "foobar" X = "foo" Y = "bar" X &= {Y} --Result is NOT "foobar"
Basically, if you combine the concatenation operator with the new sequence operation, you've got a more expensive version of append.
32. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 10, 2014
- 4319 views
I had to re-read the discussion. I thought that Derek was proposing a change to the '&' operator. I missed the extra set of braces.
33. Re: Discuss changing the behaviour of append()
- Posted by mindwalker Jun 10, 2014
- 4312 views
I don't have any horses in this race, but that has never stopped me from cheering.
Basically Derek states he has a need in some code he is writing to append an object to another object and that the append function currently is designed as a sequence operator requiring a sequence as the first parameter (from "4.1.4.9 Other Operations on Sequences" in the manual).
Currently this is illegal ...
sequence x x = append(1,2)
We get the error message ...
first argument of append must be a sequence
Then he states.
... I ... had to code an explicit test to get around it. This is 'ugly' and makes the code a bit slower and larger.
function F(object A, object B) sequence x if atom(A) then x = append({A}, B) else x = append(A, B) end if return x end function
His suggestion is to replace the append sequence function with an append object function which is essentially the F function that he discribed as "This is 'ugly' and makes the code a bit slower and larger". This of course saddles all OpenEuphoria programmers with this 'ugly', slower, larger functionality leaving his code no better off (except the code is hidden in the language now).
When I don't have any horses in a race I sometimes switch which horse I am cheering for (I cheer the underdog if there appears to be any chance).
In my opinion, one of the strengths of the Euphoria language is not having overloaded functions or multiple functions that all do the same basic thing but take different data types as parameters.
Viewed from that perspective, Derek's function becomes the appropriate append function which will work for all data types.
But the question is will this change break someone's program. Could someone have depended on the append function to detect when the first parameter is an atom and to stop the program in that case.
I guess that depends on when/how the error is currently detected. Can one call append(obj1, obj2) and when obj1 has a sequence assigned to it the function works and when an atom is assigned it fails? Or does the processor realize (say in a first pass) that obj1 is defined as an object variable not a sequence and throws the error irregardless of what is ultimately assigned to the variable?
In the second scenario changing horses will have no ill affects since the error detection would have resulted in the programmer changing obj1 into a sequence variable in order to get the program to run.
But in the first scenario it is possible someone's code will be affected if they choose to migrate their program to using the newest version of OpenEuphoria. When a large program written several years ago gets update to a newer version of a language, the initial assumptions and dependancies aren't always remembered (may not even be the same programmer). So this makes this kind of a change possibly serious. If some programmer was foolish enough to depend on the append function to detect corrupt data, the down stream data could become further corrupted when the program starts "working" instead of aborting.
Of course other languages handle this by producing thousands of pages of release notes with a one liner buried somewhere in the middle that reads something like: The append function has been modified (see manual for details).
34. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 10, 2014
- 4302 views
Can one call append(obj1, obj2) and when obj1 has a sequence assigned to it the function works and when an atom is assigned it fails?
Yes. To further clarify, OpenEuphoria compiles append(1,2) cleanly but fails at run-time.
But the question is will this change break someone's program. Could someone have depended on the append function to detect when the first parameter is an atom and to stop the program in that case.
The proposed change cannot break a working program. Theoretically it might make some bugs ever-so-slightly harder to detect, however when appending a sequence it is no help whatsoever, which means it isn't a sensible thing to rely on to help debug programs anyway, at least for the "got yer arguments back-to-front" problems.
Pete
35. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 10, 2014
- 4276 views
Here is my first draft at documenting the proposed changes.
_tom
Sequence Manipulations
The length function "counts top level items and returns the count as a length value." Nested items are not part of the top level count. (Counting is as good as measuring a length. To get the width of a road count the number of steps you take to get across.)
? length( {} ) --> 0 ? length( 4 ) --> 1 ? length( {4,5,"hello"} ) --> 3
Length | Example | Note |
---|---|---|
0 | {} | No items to count; length zero |
1 | a | One potential item, an atom; length one |
1 | {x} | One item, an object; length one |
3 | {x,x,x} | Three items; length three |
You can argue that an atom (a number or character) has no length. It is convenient to recognize that an atom adds one to the length of a sequence after a prepend, append, or concatenation.
You can not use length to distinguish an atom from a sequence.
There are various ways to increase the length of an object:
- The coarse-grained functions (prepend, append) increase length by exactly one.
- The fine-grained operator (&) increases length by the length of the object added.
In a few cases a function or the concatenation operator can be used to produce identical results. However, there are significant differences most of the time.
Number and text data behave the same way.
Length Increasing Functions
The prepend function "adds one entire object to the head of the target object." The append function "adds one entire object to the tail of the target object."
Coarse-grained means "the entire object is added as one item."
It is idiomatic in Euphoria to write these functions so the first argument is the target and the second argument is what gets added.
To change a target variable you have to explicitly assign the new value to it:
x = prepend(x, new_item ) x = append(x, new_item )
Coarse-Grained | Prepend | Append | ||
---|---|---|---|---|
Target | Argument Entire Object |
To Head | To Tail | |
atom 5 |
{} |
? prepend(5, {}) --> {{}, 5} |
? append(5, {}) --> {5, {}} |
|
6 |
? prepend(5, 6) --> {6, 5} |
? append(5, 6) --> {5, 6} |
||
{6} |
? prepend(5,{6} ) --> {{6}, 5} |
? append(5, {6}) --> {5, {6}} |
||
{6,7} |
? prepend(5, {6,7}) --> {{6,7}, 5} |
? append(5, {6,7}) --> {5, {6,7}} |
||
sequence {4,5} |
{} |
? prepend({4,5}, {}) --> {{}, 4,5} |
? append({4,5}, {}) --> {4,5, {}} |
|
6 |
? prepend({4,5}, 6) --> {6, 4,5} |
? append({4,5}, 6) --> {4,5, 6} |
||
{6} |
? prepend({4,5},{6}) --> {{6}, 4,5} |
? append({4.5}, {6}) --> {4,5, {6}} |
||
{6,7} |
? prepend({4,5}, {6,7}) --> {{6,7}, 4,5} |
? append({4,5}, {6,7}) --> {4,5, {6,7}} |
Length Increasing Operator &
The concatenation operator & "increases the length of the target object by the length of the object added."
Fine-grained means "all items are added."
Fine-Grained | Concatenate | Concatenate | ||
---|---|---|---|---|
Target | Argument All Items |
To Head | To Tail | |
atom 5 |
{} |
? {} & 5 --> 5 |
? 5 & {} --> 5 |
|
6 |
? 6 & 5 --> {6,5} |
? 5 & 6 --> {5,6} |
||
{6} |
? {6} & 5 --> {6,5} |
? 5 & {6} --> {5,6} |
||
{6,7} |
? {6,7} & 5 --> {6,7,5} |
? 5 & {6,7} --> {5,6,7} |
||
sequence {4,5} |
{} |
? {} & {4,5} --> {4,5} |
? {4,5} & {} --> {4,5} |
|
6 |
? 6 & {4,5} --> {6,4,5} |
? {4,5} & 6 --> {4,5,6} |
||
{6} |
? {6} & {4,5} --> {6,4,5} |
? {4,5} & {6} --> {4,5,6} |
||
{6,7} |
? {6,7} & {4,5} --> {6,7,4,5} |
? {4,5} & {6,7} --> {4,5,6,7} |
Idiomatic Concatenation
You can combine the concatenation & operator with the assignment = statement.
object x=5, y=6 x &= y ? x --> {5,6} x &= y -- short form x = x & y -- long form
One use for the &= shortcut is to make concatenation & behave like an append function:
object x, y x &= {y}
Target | Argument | Result | ||
---|---|---|---|---|
x | y | Concatenation | Append |
x --> |
x &= {y} |
x = append(x,y) |
|||
atom 5 |
{} |
x --> {5,{}} |
||
6 |
x --> {5,6} |
|||
{6} |
x --> {5,{6}} |
|||
{6,7} |
x --> {5,{6,7}} |
|||
sequence {4,5} |
{} |
x --> {4,5,{}} |
||
6 |
x --> {4,5,6} |
|||
{6} |
x --> {4,5,{6}} |
|||
{6,7} |
x --> {4,5,{6,7}} |
Legacy Notes
Early versions (O[ 3.1 and before) of length did not recognize the length of an atom as one.
Early versions (O[ 4.0 and before) of prepend and append would not allow the target to be an atom.
See Also
insert, splice, remove
36. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 11, 2014
- 4239 views
In my current code, I ran across this case and had to code an explicit test to get around it. This is 'ugly' and makes the code a bit slower and larger.
function F(object A, object B) sequence x if atom(A) then x = append({A}, B) else x = append(A, B) end if return x end function
Derek, this case shows that there was some wrong logic in your "current code". So, your code was 'ugly', not your new function F() which corrected your mistake.
And that your subtle logic bug was fixed thanks to old good append() feature.
Or, maybe, you just forgot how append() works?
Regards
kinz
37. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4236 views
Derek, this case shows that there was some wrong logic in your "current code".
And that your subtle logic bug was fixed thanks to old good append() feature.
Okay, what was the wrong logic bug?
So, your code was 'ugly', not your new function F() which corrected your mistake.
It's still slower, as F() has to make the check for a sequence and then append() will that check a second time. Why not consolidate these two into a single check?
Or, maybe, you just forgot how append() works?
Let's remember, length() works on atoms. It's append() (and prepend()) that's inconsistent here.
38. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 11, 2014
- 4231 views
Derek, this case shows that there was some wrong logic in your "current code". So, your code was 'ugly', not your new function F() which corrected your mistake.
And that your subtle logic bug was fixed thanks to old good append() feature.
Or, maybe, you just forgot how append() works?
Seriously !?
No. Your assumptions about my code are once again wrong. Here is the actual function I'm writing...
-- This routine appends to an item at an arbitrary depth. -- Params: -- S The sequence that holds the item which will be appended to. -- I A list of indexes that point to the specific item in S to append to. -- X The object that will be appended to the targeted item. function deep_append(sequence S, sequence I, object X) if length(I) <= 1 then if length(I) = 1 then -- Using concatenation of a sequence here to get around appending to an atom. S[I[1]] &= {X} end if return S end if integer n = I[1] return S[1 .. n - 1] & {deep_append(S[n], I[2 .. $], X)} & S[n + 1 .. $] end function
The above function works as specified, however I'd hoped for better performance.
39. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 11, 2014
- 4170 views
Tom:
I think your documentation is a bit verbose. I like your simple explanation that append() and prepend() return an object whose length is exactly one greater than their first operand, whereas the concatenation operator & returns an object whose length is the sum of the lengths of its two operands.
The "fine grained" and "coarse grained" bits are confusing. Just call & the "concatenation operator". Then give a few (three) examples for each append(), prepend(), and &.
40. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 11, 2014
- 4178 views
Derek, this case shows that there was some wrong logic in your "current code".
And that your subtle logic bug was fixed thanks to old good append() feature.
Okay, what was the wrong logic bug?
jimcbrown, see please 38.Re:...
Do you see the normal append() function call from Derek's new deep_append() function?
Sorry, I do not see...
This is the second Derek's logic bug - he just doesn't demonstrate that his wrong code, and I can say nothing about his first logic bug.
Sophisma or paralogismos.
41. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 11, 2014
- 4186 views
Seriously !?
Yes, seriously, sorry...
There is no the normal append() call in your function now...
That bug was fixed thanks to old good append().
No?
Regards
kinz
42. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4137 views
Derek, this case shows that there was some wrong logic in your "current code".
And that your subtle logic bug was fixed thanks to old good append() feature.
Okay, what was the wrong logic bug?
jimcbrown, see please 38.Re:...
Do you see the normal append() function call from Derek's new deep_append() function?
Sorry, I do not see...
I don't see the call to normal append() from deep_append(), but I also fail to see the logic bug.
That said, the existing code could be made to work with append like so:
-- This routine appends to an item at an arbitrary depth. -- Params: -- S The sequence that holds the item which will be appended to. -- I A list of indexes that point to the specific item in S to append to. -- X The object that will be appended to the targeted item. function deep_append(sequence S, sequence I, object X) if length(I) <= 1 then if length(I) = 1 then if atom(S[I[1]]) then -- append() is also making this check, why do we have to make this check twice??? S[I[1]] &= {X} -- having to make a new sequence also slows down the atom case else S[I[1]] = append(S[I[1]], X) end if end if return S end if integer n = I[1] return S[1 .. n - 1] & {deep_append(S[n], I[2 .. $], X)} & S[n + 1 .. $] end function
Look how much nicer it is when append() can do atoms too!
-- This routine appends to an item at an arbitrary depth. -- Params: -- S The sequence that holds the item which will be appended to. -- I A list of indexes that point to the specific item in S to append to. -- X The object that will be appended to the targeted item. function deep_append(sequence S, sequence I, object X) if length(I) <= 1 then if length(I) = 1 then S[I[1]] = append(S[I[1]], X) end if return S end if integer n = I[1] return S[1 .. n - 1] & {deep_append(S[n], I[2 .. $], X)} & S[n + 1 .. $] end function
[/quote]
This is the second Derek's logic bug -
You've failed to point out a single logic bug, let alone two.
and I can say nothing about his first logic bug.
Because it doesn't exist?
he just doesn't demonstrate that his wrong code,
Sophisma or paralogismos.
I don't see append() working on atoms being a sophismata. After all, append() already works with atoms as the second parameter!
If you really believe Derek's logic bugs fall into the category of sophisma, you should at least be able to articulate the "odd consequences" or ambiguous interpretation of true/false value here.
43. Re: Discuss changing the behaviour of append()
- Posted by mindwalker Jun 11, 2014
- 4105 views
But the question is will this change break someone's program. Could someone have depended on the append function to detect when the first parameter is an atom and to stop the program in that case.
The proposed change cannot break a working program. Theoretically it might make some bugs ever-so-slightly harder to detect, however when appending a sequence it is no help whatsoever, which means it isn't a sensible thing to rely on to help debug programs anyway, at least for the "got yer arguments back-to-front" problems.
Pete
Since append currently works the way I thought I remembered it did, I disagree Pete with your statement. The proposed change could break a working program.
For example a program could be designed to read in a text file, one line at a time, where each line in the file is supposed to start with a sequence followed by 3 atoms. Think customer information followed by an item number, item count and the item price. The program might be intended to add the item number to the end of the sequence and then compute the total charge and add that to the sequence and then store that sequence to a data base as a transaction.
That program make use of an included, company developed, generic file read function designed to read files containing text strings that represent euphoria sequences and text strings that represent individual atoms. That function could return a sequence of objects based on what was read (some sequences and some atoms).
Of course someone using this generic read function would want to verify the returned line items were the right type and order. And a program such as the one I propose might be designed to just stop if the input doesn't follow the right format (the concept of "do no more harm" and let a human figure out how to fix the problem).
So some "slick" programmer may have realized that the first append would abort if the first object in the line wasn't a sequence. So said programmer may have skipped the separate sequence test and depended on the append function working as documented.
Five years of running this program every hour 24x7x365 and only 3 aborts when the input file was corrupted one way or another and the company decides to stop using Euphoria 2.4 and move to the latest and greatest OpenEuphoria.
At this point, the previously working as designed program would be broken. It would no longer be detecting and aborting if the first line item wasn't a sequence. That is unless the programmer migrating this just happens to remember/realize that the append function was providing this sequence check and modifies the program to now do its own check instead.
44. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 11, 2014
- 4127 views
I don't see the call to normal append() from deep_append(), but I also fail to see the logic bug.
Simple logic bug. The code was wrong, not the normal append(). Why append(), if code was wrong?
Do you see my logic now? I say about the discussion logic here.
This is the second Derek's logic bug -
You've failed to point out a single logic bug, let alone two.
See please above once more.
and I can say nothing about his first logic bug.
Because it doesn't exist?
Yes, Derek uses & now. He changed his primary code. He changed the code logic. See please my recomendation in 29.Re:
Use & and be happy :)
Do you see sophisma or paralogismos in discussion now?
45. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4090 views
I don't see the call to normal append() from deep_append(), but I also fail to see the logic bug.
Simple logic bug. The code was wrong, not the normal append(). Why append(), if code was wrong?
Do you see my logic now? I say about the discussion logic here.
Ok, I see the reasoning.
But, I disagree - append() is wrong, not the code.
Yes, Derek uses & now. He changed his primary code. He changed the code logic.
Yes, he was forced to. Because append() is wrong.
See please my recomendation in 29.Re:
Use & and be happy :)
Do you see sophisma or paralogismos in discussion now?
Yes, indeed. You make a good point here.
46. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4074 views
Since append currently works the way I thought I remembered it did, I disagree Pete with your statement. The proposed change could break a working program.
So some "slick" programmer may have realized that the first append would abort if the first object in the line wasn't a sequence. So said programmer may have skipped the separate sequence test and depended on the append function working as documented.
This is a particularly expensive way of doing that test, as you can't catch or trap exceptions like this. The error would abort the entire program. One would need to use multiple processes and have a master program that detected when the subprogram crashed and take appropriate action at that point. And of course, if the subprogram was halfway thru a giant list of records, that time is wasted as it'll have to start again from the begining.
Much simpler to just do the check manually in the first place.
Five years of running this program every hour 24x7x365 and only 3 aborts when the input file was corrupted one way or another and the company decides to stop using Euphoria 2.4 and move to the latest and greatest OpenEuphoria.
At this point, the previously working as designed program would be broken. It would no longer be detecting and aborting if the first line item wasn't a sequence. That is unless the programmer migrating this just happens to remember/realize that the append function was providing this sequence check and modifies the program to now do its own check instead.
So if we used petelomax's suggestion of appenda()/prependa(), then there would be no problem here?
47. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 11, 2014
- 4076 views
Do you see the normal append() function call from Derek's new deep_append() function?
Sorry, I do not see...
This is the second Derek's logic bug - he just doesn't demonstrate that his wrong code, and I can say nothing about his first logic bug.
You sir, are have a very effective trolling skill.
I didn't show you my failing code because I assumed you had the required Euphoria skills to see when the use of append() would cause the issue first described. My mistake.
Can you point out where there are any logic errors in this function or discussion of mine, please.
The code I posted earlier was the working code. My first attempt at this function used the append() function but that failed at times, due to it trying to append to an atom.
Instead of ...
S[I[1]] &= {X}
my original function had
integer n = I[1] S[n] = append(S[n], X)
This fails when the item at S[n] is an atom. I then changed my code to explicitly test for that condition ...
integer n = I[1] if atom(S[n]) then S[n] = append({S[n]}, X) else S[n] = append(S[n], X) end if
At which point I posted my original question. I have now changed my function to use the concatenation operator to get around the shortcoming in append(), but my suggestion about changing the append() function's behaviour still stands.
48. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 11, 2014
- 4135 views
Since append currently works the way I thought I remembered it did, I disagree Pete with your statement. The proposed change could break a working program.
For example a program could be designed to read in a text file, one line at a time, where each line in the file is supposed to start with a sequence followed by 3 atoms. ...
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program. It would be better, IMO, to validate the text file data before using that data. The application then can either fail gracefully or come to some other arrangement.
By the way, data that is generated by an application should be subject to 'logic' testing during the testing/debugging stages of an application's development, and not during live run times.
Thus from my point of view, I see that my suggested change would not break working programs but would break non-working programs
49. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 11, 2014
- 4094 views
So if we used petelomax's suggestion of appenda()/prependa(), then there would be no problem here?
Ugh! No, please.
We would have append()/prepend() when the first argument must only be a sequence and appenda()/prependa() when the first argument can be any object. That arrangement, I predict, would be more confusing and more likely to introduce errors in code, plus people would tend to just use the newer functions anyway.
50. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4083 views
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program. It would be better, IMO, to validate the text file data before using that data. The application then can either fail gracefully or come to some other arrangement.
Agreed.
Thus from my point of view, I see that my suggested change would not break working programs but would break non-working programs
Agreed in full!
By the way, data that is generated by an application should be subject to 'logic' testing during the testing/debugging stages of an application's development, and not during live run times.
This is a sound principle, but in practice it's hard to think of/catch everything. So those 3 times when there was bad data (and the application crashed?) could easily have been from causes that somehow got missed during the original testing/debugging states, or an "impossible situation" that happened anyways. It happens. Hence the reason to keep validity checking code durning live run times.
I think we can all agree that relying on append() to crash your program for validity checking purposes is a silly way to do things.
51. Re: Discuss changing the behaviour of append()
- Posted by mindwalker Jun 11, 2014
- 4044 views
Since append currently works the way I thought I remembered it did, I disagree Pete with your statement. The proposed change could break a working program.
So some "slick" programmer may have realized that the first append would abort if the first object in the line wasn't a sequence. So said programmer may have skipped the separate sequence test and depended on the append function working as documented.
This is a particularly expensive way of doing that test, as you can't catch or trap exceptions like this. The error would abort the entire program. One would need to use multiple processes and have a master program that detected when the subprogram crashed and take appropriate action at that point. And of course, if the subprogram was halfway thru a giant list of records, that time is wasted as it'll have to start again from the begining.
Much simpler to just do the check manually in the first place.
I wasn't arguing the merits of a particular programming choice. There probably are a thousand better ways to do this. I was arguing that the change could break a working program and gave a hypothetical program scenario to illustrate.
Five years of running this program every hour 24x7x365 and only 3 aborts when the input file was corrupted one way or another and the company decides to stop using Euphoria 2.4 and move to the latest and greatest OpenEuphoria.
At this point, the previously working as designed program would be broken. It would no longer be detecting and aborting if the first line item wasn't a sequence. That is unless the programmer migrating this just happens to remember/realize that the append function was providing this sequence check and modifies the program to now do its own check instead.
So if we used petelomax's suggestion of appenda()/prependa(), then there would be no problem here?
Actually for me Pete Lomax's suggestion is the one I would find least favorable. It is a step in the direction C and so many other languages have gone. The language becomes more complicated and harder to learn since there would be a sequence append and then a new objects append. Newbies would be trying to determine when each should be used, not realizing that they could use appenda in all cases and would never really need the old append.
I think in the end I like Derek's suggestion. But it does have the potential to break existing programs in subtle ways. I would suggest that the release notes should make a big deal about this change and maybe even the manual as well, so that anyone migrating from earlier versions has some chance of recognizing the potetial problem.
52. Re: Discuss changing the behaviour of append()
- Posted by mindwalker Jun 11, 2014
- 4054 views
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program. It would be better, IMO, to validate the text file data before using that data. The application then can either fail gracefully or come to some other arrangement.
Agreed.
Thus from my point of view, I see that my suggested change would not break working programs but would break non-working programs
Agreed in full!
By the way, data that is generated by an application should be subject to 'logic' testing during the testing/debugging stages of an application's development, and not during live run times.
This is a sound principle, but in practice it's hard to think of/catch everything. So those 3 times when there was bad data (and the application crashed?) could easily have been from causes that somehow got missed during the original testing/debugging states, or an "impossible situation" that happened anyways. It happens. Hence the reason to keep validity checking code durning live run times.
I think we can all agree that relying on append() to crash your program for validity checking purposes is a silly way to do things.
All of my original post was a hypothetical scenario with hyperbola added to indicate the satifactory performace of the product in meeting the users needs. Three failures in 5 years indicating the source file generation works correctly except during sudden power outages or network failures or such.
That said in the real world people do make these choices; hobby programmers, small businesses where the owner is the programmer, etc. It may be clever of you to label their program as "not working" just because it doesn't meet your better programming standards. But for them it meets the need and didn't require a ton of programming. In fact that is one of the strengths of Euphoria. Someone doesn't need to be a professional programmer with knowledge of all the best programming standards to fashion a program that as far as they are concerned works.
53. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 11, 2014
- 4122 views
All of my original post was a hypothetical scenario with hyperbola added to indicate the satifactory performace of the product in meeting the users needs.
It may be clever of you to label their program as "not working" just because it doesn't meet your better programming standards.
But it's not a good idea to just label it that way. Agreed. This reminds me of Linus Torvald's rule: http://felipec.wordpress.com/2013/10/07/the-linux-way/
Three failures in 5 years indicating the source file generation works correctly except during sudden power outages or network failures or such.
I.e. rare, unexpected cases. Gotcha. (Of course, you can simulate a power outage (pull the power cord out) or a network failure (unplug your hub/switch), but there's probably always something else that'll trip things up .. eventually. You can't think of everything.)
That said in the real world people do make these choices; hobby programmers, small businesses where the owner is the programmer, etc.
Yes, in the real world ppl sometimes take shortcuts. Agreed.
But for them it meets the need and didn't require a ton of programming. In fact that is one of the strengths of Euphoria. Someone doesn't need to be a professional programmer with knowledge of all the best programming standards to fashion a program that as far as they are concerned works.
Agreed. Still, relying on a program to complete crash in an ungraceful way is kind of unusual and must be rare. I agree with you - it should be ok to make the change to append() (as you agreed), but we should document it well (like we did with the change to length()).
54. Re: Discuss changing the behaviour of append()
- Posted by gbonvehi Jun 12, 2014
- 4090 views
Well, I'm joining late, but I think what we have here is performance vs the ability to introduce logical bugs.
As those bugs could still arise, specially if length()'s behavior is already similar to what's proposed, I'd go with performance.
55. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 12, 2014
- 4089 views
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program.
This can (and should) be applied to functions.
A[i] can be a sequence or an atom.\\ append(A[i],x) : sequence : OK\\ atom : How do you want to see it? (atom or sequence)?This is legitimate because A[i] is the i in A[i..i]??
A[i..i] is a sequence
A[i..i-1] ditto
A{i..i-2] is rubbish
At some point here I am losing you.
56. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 12, 2014
- 4083 views
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program.
This can (and should) be applied to functions.
When reasonable to do so. The problem is when one adds in restrictions that serve no purpose.
(There's a second problem, where it's reasonable for a function in the general case to have a certain behavior, but in a specific context it causes a logical error in the data. But we don't seem to be discussing this here.)
A[i] can be a sequence or an atom.\\ append(A[i],x) : sequence : OK\\
So far, so good.
atom : How do you want to see it? (atom or sequence)?
Autopromotion - we already do this from integers to atoms in the delete case. Now we can promote the atom to a sequence (n -> {n}) and then append x to it.
In general though, autopromotion should be done in specific, case-by-case circumstances.
This is legitimate because A[i] is the i in A[i..i]??
Uh, no.
A[i..i] is a sequence
Yes. That's always a 1-element sequence.
A[i..i-1] ditto
Yes. That's the empty sequence.
A{i..i-2] is rubbish
Agreed. That's a syntax error.
At some point here I am losing you.
I followed you up to the bit after the bit about the rubbish.
57. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 12, 2014
- 4075 views
One of the better techniques in designing applications, is to always provide validity checking on data that comes from outside the program, as opposed to data that is generated by the program.
This can (and should) be applied to functions.
I hold a contrary opinion. In the general case, a function should not be required to validate its arguments. I understand that this sounds almost heretical to many, but let me explain.
A function can not know if the values in its arguments originated from outside the program or internally. In a well-behaved program, data coming into the application will be validated prior to it being used, and usually at the point at which it can give the most meaningful error/warning message to the end user. Calling a function with arguments is defined as data usage. Also, in a well-behaved program, data generated by the program will be correct, and this will be proven by appropriate logic testing during the development stage prior to its live release.
I believe that a routine should assume that it is operating inside a well-behaving program. Thus it will not be required to ensure that its arguments, or any shared program data, are valid. The program will have already done that so there's no need to do it again. However, any data that a function creates and makes available to other code, should be validated by that function. This needs only to be done while in development mode.
At this point I need to talk a bit about "what is valid data?" In general terms, its the set of values that a routine can reasonably be expected to operate on.
For example, consider this function to calculate the real 'X' value for a quadratic equation, which is defined as ... aX2 + bX + c = 0 . For any given quadratic equation, the X can have zero, one or two values which solves the equation. Thus the function should return a sequence of 0, 1, or 2 elements.
The formula that the function needs to evaluate is ...
X1 = (-b - sqrt(b2 - 4ac)) / 2a and X2 = (-b + sqrt(b2 - 4ac)) / 2a
The first thing to note is what should the function do if a=0? If it doesn't check then the program will fail with a divide-by-zero error. If it does check, then its also admitting that the calling program is trying to use the function in an illogical manner. By definition, if a=0 then the equation is no longer a quadratic one but a linear one, and this function is only supposed to be used for quadratics.
I maintain that it's the calling program's responsibility to do the checking of a before calling the function, because it knows when is the most efficient time to do that. The function would be nearly always be duplicating or wasting effort if always checked for a=0.
So, one version of this function could be ...
ifdef DEVEL_MODE then include std/error.e procedure fail_if(integer x, sequence t) if x then crash("** FAILURE DETECTED **\n" & t & '\n') end if end procedure end ifdef -- Compares two floating point numbers allowing for a tolerance. function compare_real(atom f, atom g, atom e = 0.000_000_000_000_009) atom r r = f-g if r > e then return 1 elsif r < -e then return -1 else return 0 end if end function ----------------------------------- public function solve_quad_eqn(atom a, atom b, atom c) ----------------------------------- sequence res atom descrim descrim = b * b - 4 * a * c -- Adjust result for limitations in floating point math. if compare_real(descrim, 0) = 0 then descrim = 0 end if if descrim < 0 then res = {} elsif descrim = 0 then res = {-(b / 2 * a)} else descrim = sqrt(descrim) res = - { b - descrim, b + descrim } / (2 * a) end if ifdef DEVEL_MODE then -- Check that results are sane. for i = 1 to length(res) do fail_if(not atom(res[i]), "The results must be real numbers") end for atom temp = compare_real( (b*b), (4*a*c) ) atom vx = -(b / 2 * a) atom vy = -( b*b - 4*a*c) / (4 * a) if length(res) = 0 then fail_if(temp >= 0, "Should have one or two Real results") fail_if(a > 0 and vy <= 0, "Vertex too low") fail_if(a < 0 and vy >= 0, "Vertex too high") elsif length(res) = 1 then fail_if(temp != 0, "Should have zero or two Real results") fail_if(compare_real(vy , 0) != 0, "Vertex Y should be zero") fail_if(compare_real(vx , res[1]) != 0, "Vertex X should be result") elsif length(res) = 2 then fail_if(temp <= 0, "Should have zero or one Real results") fail_if(compare_real(-(b / a), res[1] + res[2]) != 0, "Invalid symetry") fail_if(a > 0 and vy >= 0, "Vertex too high") fail_if(a < 0 and vy <= 0, "Vertex too low") else fail_if(1, "Only a maximum of two results are allowed") end if end ifdef return res end function ifdef UNIT_TESTING then procedure test_solve_quad() for i = -20 to 20 do for j = -4 to 4 do for k = -5 to 5 by 0.3 do if i != 0 then solve_quad_eqn(i/10, j, k) end if end for end for end for end procedure test_solve_quad() end ifdef
So only during development would the results of the function be validated. Once in production, the function is known to be behaving as specified so we no longer have to make sure its results are good; they will be. And we don't check its arguments because the calling program should have already checked those.
At some point here I am losing you.
Yes, that you have.
58. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 12, 2014
- 3969 views
Here is a another draft of possible documentation. After the change to the definition of "length" from Euphoria 3 to 4, these results follow. Everything seems to fit a consistent pattern once you allow for atomatic promotion of an atom to a sequence.
_tom
(Edit, I made an interesting typo: atomatic vs automatic...)
Object Length
The length of an object "is a count of the top-level items it contains."
The length of a sequence is the number of items it contains; if an item is a nested sequence it still counts as one item. The length of an empty sequence is zero; it contains no items.
The length of an atom is one. This is a convenient viewpoint because when an atom is added to a sequence (by inserting or concatenating) the result is an increase in length by one.
It is easy to argue that a number or a character has no defined length. In Euphoria versions before O[ 4 atoms did not have a defined length.
An atom a is not the same as a sequence {a} containing one atom. This distinction is important and is used in many algorithms.
Increasing Length
You can increase the length of an object by adding one or more items. There are two ways to do this: insertion and concatenation.
- An insertion (prepend, insert, append) increases length by exactly one.
- A concatenation ( & ) increases length by the length of the added object.
It is really convenient to promote an atom into a one item sequence automatically when performing an object lengthening.
Concatenation &
The concatenation operator "joins two objects together to make a sequence whose length is equal to the sum of their individual lengths."
Numerical | Text | |
---|---|---|
atom : atom |
? 3 & 4 --> {4,5} |
? 'O' & 'E' --> "OE" |
sequence : sequence |
? {1,2} & {3,4} --> {1,2,3,4} |
? "Open" & "Euphoria" --> "OpenEuphoria" |
Visualizing Concatenation
A way to visualize the process of concatenation is to imagine some intermediate steps:
Concatenating sequences:
? {1,2} & {3,4} --> {1,2 }&{ 3,4} --> {1,2 , 3,4}
When concatenation involves an atom:
? {1,2} & 3 --> {1,2 }& 3 --> {1,2 }&{ 3} -- promotion of atom to sequence required --> {1,2 , 3}
Prepend, Insert, Append
An insertion function (prepend, insert, append) "places an object as an item within a sequence."
The index argument of the insert function places the new item at the index value of the new sequence.
Think of prepend as insertion of an object before the first item of a sequence. Think of append as insertion of an object after the last item in a sequence.
An insertion of a string into a string never produces another string. Use a concatenation if you need the result to be a string.
Numerical | Text | Special Note | |
---|---|---|---|
atom : atom |
? prepend(3,4) --> {4,3} |
? prepend('a','z') --> "za" |
* fails on * considered for |
sequence : atom |
? append({1,2},3) --> {1,2,3} |
? insert("horse", 'a', 3) --> {104,111,97,114,115,101} -- "hoarse" |
|
sequence : sequence |
? prepend({1,2},{3,4}) --> { {3,4}, 1,2} |
? prepend("jay","blue") --> { {98,108,117,101}, -- 106, -- 97, -- 121 } |
Visualizing Insertion
A way to visualize an insertion function is to imagine some intermediate steps:
An append of an atom to a sequence:
? append({1,2},3) --> {1,2, } ^ 3 --? {1,2,3}
An insertion of a character in a string:
? insert("44",'X',2) --> {52, 52} ^ 120 --> {52,120,52} -- "4X4"
Inserting an object into an atom makes no sense unless you allow for an automatic promotion of an atom into a sequence:
? prepend(1, 5) --> prepend( {1}, 5) -- promotion of atom to sequence required --> { 1} ^ 5 --> { 5, 1 }
For version O[ 4 and earlier Euphoria this automatic promotion of an atom to a sequence was not allowed.
59. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 12, 2014
- 3999 views
Ok, I see the reasoning.
But, I disagree - append() is wrong, not the code.
jimcbrown, append() worked as expected in that Derek's original wrong code.
It signalled about Derek's bug.
Same as it worked 20 years in thousands of EU programs, without any claims from users.
Do you know just one claim?
Derek had to use &, not append(). Period.
And he do use & now, and his new function works ok (as he says) and looks good.
If you wanna another append(), it is yours choice and it is totally another story.
Regards
kinz
60. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 12, 2014
- 3945 views
Ok, I see the reasoning.
But, I disagree - append() is wrong, not the code.
If you wanna another append(), it is yours choice and it is totally another story.
No, it's not another story, it's this story. The whole point of this thread is about that!
jimcbrown, append() worked as expected in that Derek's original wrong code.
It signalled about Derek's bug.
I'll rewrite your quotes as follows:
jimcbrown, append() worked as expected in that Derek's original code.
It signalled to Derek about something it couldn't handle.
Now that I've removed the loaded assumptions in your quotes, I'm happy to agree with you.
Derek's original code found a case that append() couldn't handle, and we want to replace append() with another append() that can handle this case.
Same as it worked 20 years in thousands of EU programs, without any claims from users.
Do you know just one claim?
There were probably bigger claims to deal with, like not being able to declare a variable in the middle of a function, or to assign a value to a variable upon declaration.
Derek had to use &, not append(). Period.
This is just flat out wrong. Technically, he could have used append(), even in a 2.4 compatible version of his function. It would have been more work, true, but it could be done.
And he do use & now, and his new function works ok (as he says) and looks good.
He never said that it looks good.
61. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 12, 2014
- 3922 views
Ok, I see the reasoning.
But, I disagree - append() is wrong, not the code.
jimcbrown, append() worked as expected
This reminds me of an argument I had a while ago about PS/2 connections.
You have serial mice, and maybe there were serial keyboards at one point in time too.
Now, like USB, the original serial line cable was designed so you could unplug and replug devices back in. You could unplug your serial mouse from the computer and plug it back in and it'd work again.
Then I was told that PS/2 is actually derived from serial. And yet, with PS/2, if you unplug your mouse or keyboard, you generally have to reboot to get things working again. I wonder why PS/2 actually lost functionality, compared to the older serial protocol.
Anyways, I was told that this was "by design." That's right, PS/2 was designed to lose functionality compared to serial. I don't know if that's actually true or if the person I was holding this conversation with was just pulling my leg, but this brings up a good point I'd like to make.
Just because something works as designed, doesn't mean that everything's perfect - the original design might have been bad (as imvho PS/2 lack of hotplugability is), thus making improvements necessary.
I still have a lot of old PS/2 keyboards around (and even one DIN keyboard), and a few older desktops that still have PS/2 ports on them. But I got a bunch of USB/PS2 converters and connect everything via USB now. Life's just easier that way.
62. Re: Discuss changing the behaviour of append()
- Posted by kinzz Jun 12, 2014
- 3941 views
Can you point out where there are any logic errors in this function or discussion of mine, please.
The code I posted earlier was the working code. My first attempt at this function used the append() function but that failed at times, due to it trying to append to an atom.
Instead of ...
S[I[1]] &= {X}
my original function had
integer n = I[1] S[n] = append(S[n], X)
This fails when the item at S[n] is an atom.
There is nothing amazing that "this fails". Manual reads: Syntax: s2 = append(s1, x)
You had to append to the sequence, not to an atom.
Your logic was erroneous, you thought that S[n] can not be an atom.
But why not ???
If S={1,2,3,4} then S[3]=3
The atom!
That above was about the function logic.
And there is no any reason to tell on append() if your function works after correction with append() and (much better) with &.
This is about the discussion logic.
But if you wanna another append(), it is fully another story.
Regards
kinz
63. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 12, 2014
- 3933 views
Can you point out where there are any logic errors in this function or discussion of mine, please.
The code I posted earlier was the working code. My first attempt at this function used the append() function but that failed at times, due to it trying to append to an atom.
Instead of ...
S[I[1]] &= {X}
my original function had
integer n = I[1] S[n] = append(S[n], X)
This fails when the item at S[n] is an atom.
There is nothing amazing that "this fails". Manual reads: Syntax: s2 = append(s1, x)
You had to append to the sequence, not to an atom.
Your logic was erroneous, you thought that S[n] can not be an atom.
But why not ???
If S={1,2,3,4} then S[3]=3
The atom!
That above was about the function logic.
And there is no any reason to tell on append() if your function works after correction with append() and (much better) with &.
This is about the discussion logic.
But if you wanna another append(), it is fully another story.
Regards
kinz
I started to respond to this, then I realized that it was more-or-less identical to http://openeuphoria.org/forum/m/124582.wc, which I already responded to.
Perhaps we should take a different tack. What is the compelling original reason for append() to have refused to accept atoms as the first parameter in the first place?
64. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 12, 2014
- 3932 views
There is nothing amazing that "this fails".
I believe that English is not your first language, so I'd just like to point out that at no time have I said that I was "amazed" or even surprised by the current behaviour of append().
Manual reads: Syntax: s2 = append(s1, x)
You had to append to the sequence, not to an atom.
Your logic was erroneous, you thought that S[n] can not be an atom.
What does "amaze" me is your attempts to read my mind. I did not think that S[n] can not be an atom. I fully realized that an arbitrary sequence element could be an atom. What actually happened was that I forgot that append() had the restriction about it's first parameter, because it seemed natural to me that append() would work just like the concatenation operator.
if your function works after correction with append() and (much better) with &.
And this is the point I'm making ... the function does not become better (in my opinion) using the concatenation operator.
But if you wanna another append(), it is fully another story.
But I don't want another function that works almost the same as append(). I want append() to work using the same rationale as concatenate does.
So to summarize, you have not understood me or my posts at all. For this, I'm sorry.
65. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 12, 2014
- 3932 views
Derek,
We agree that a function's parameters should be validated before entering the function. This is why I have said:
The real problem is not append but A[i] being an atom.
My point with the various slices is that every slice is a sequence but A[i] is possibly not.
It would seem reasonable (to me at least) that A[i] and A[i..i] ought be interchangeable. Therefore I am inclined to say the difficulty with append is with the (ambiguous) nature of A[i].
I don't think that append shoud be changed as restricting the target type to sequence is a good restriction.
66. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 12, 2014
- 3937 views
Derek,
We agree that a function's parameters should be validated before entering the function. This is why I have said:
The real problem is not append but A[i] being an atom.
My point with the various slices is that every slice is a sequence but A[i] is possibly not.
It would seem reasonable (to me at least) that A[i] and A[i..i] ought be interchangeable.
Therefore I am inclined to say the difficulty with append is with the (ambiguous) nature of A[i].
I don't think that append shoud be changed as restricting the target type to sequence is a good restriction.
append(A[i], x) -- yes append(1,2) -- no
Obviously with call-by-value the function wouldn't know the difference.
I don't know how the caller could differentiate cleanly except with a sequencing operator (an idea which seems to have been rejected)
67. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 13, 2014
- 3925 views
integer n = I[1] return S[1 .. n - 1] & {deep_append(S[n], I[2 .. $], X)} & S[n + 1 .. $] end function
The above function works as specified, however I'd hoped for better performance.
Would this not help?
integer n = I[1] S[N] = deep_append(S[n], I[2 .. $], X) return S end function
Five years of running this program every hour 24x7x365 and only 3 aborts...
At this point, the previously working as designed program would be broken.
As others might have said, I think you meant
the previously broken as designed program would no longer be properly broken.I can (just about) see your point, but I'm not going to lose any sleep over it. As long as things get properly documented, of course.
So if we used petelomax's suggestion of appenda()/prependa(), then there would be no problem here?
Ugh! No, please.
We would have append()/prepend() when the first argument must only be a sequence and appenda()/prependa() when the first argument can be any object. That arrangement, I predict, would be more confusing and more likely to introduce errors in code, plus people would tend to just use the newer functions anyway.
Agreed, that was certainly not one of my better suggestions.
Perhaps we should take a different tack. What is the compelling original reason for append() to have refused to accept atoms as the first parameter in the first place?
Absolutely. When Derek said something similar, it completely changed my mind, and 4 days later I still cannot think of a valid answer to that one.
Pete
68. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 13, 2014
- 3941 views
Would this not help? ...
Damn you Pete ... That's much better, 38% better in fact. And it's Euphoria Performance Tip #1, which is ...
Don't create sequences, especially temporary ones, if you don't have to.
69. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 13, 2014
- 3926 views
Still trying to make sense of this topic. Here is a summary of a few ideas I see in this thread.
- Is change going to happen?
- How do I describe these chagnes?
_tom
From Euphoria 1.0 Documentation from 1993:
Concatenation of Sequences:
The & operator will concatenate two sequences into a longer sequence. e.g. {1, 2, 3} & {4, 5, 6} is {1, 2, 3, 4, 5, 6}. Atoms can also be concatenated: 6.5 & 9 is {6.5, 9}. {1, 2, 3} & 4 is {1, 2, 3, 4}.
Operations on Sequences:
i = length(s) -- length of sequence s = repeat(x, a) -- repeat x a times s2 = append(s1, x) -- append x to end of s1 s2 = prepend(s1, x) -- prepend x at beginning of s1
Twenty years later...OpenEuphoria wants to look like:
Concatenation of Objects:
The & operator will concatenate two objects into a longer sequence. e.g. {1, 2, 3} & {4, 5, 6} is {1, 2, 3, 4, 5, 6}. Atoms can also be concatenated: 6.5 & 9 is {6.5, 9}. {1, 2, 3} & 4 is {1, 2, 3, 4}.
Operations on Objects:
i = length(x) -- length of object s = repeat(x, a) -- repeat x a times s2 = append(x1, x) -- append x to end of x1 s2 = prepend(x1, x) -- prepend x at beginning of x1
- Keep things the way they were
- Extend Euphoria
Keep Things
- change is bad
- some suble changes in program behaviour if append is changed?
- append was optimized for speed; do not sacrifice this speed
- & is a "sequence creation" operator; therefore it makes sense that you can concatenate two atoms
- append is a "sequence modifying" function; therefore it makes sense that you can not start with an atom
Extend Euphoria
- length has already been changed
- a complementary change given that length is now different
- fits the existing pattern that & already has
- promoting an atom a to a sequence {a} is a convenience that is expected because of the flexibility of Euphoria
- usability is more valuable than interpreter speed
- thinking in terms of objects is more powerful than thinking in terms of just sequences
70. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 13, 2014
- 3953 views
I vote for the proposal to change the behavior of append() and prepend(). The impact should be minimal and it is clearer and more intuitive.
I like the original documentation, it's clear and concise. It should still be valid even with the proposed change.
Some things of note:
append(atom1, atom2) would be the same as atom1 & atom2
append(atom1, sequence1) would be the same as append({atom1}, sequence1)
71. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 15, 2014
- 3815 views
I vote for the proposal to change the behavior of append() and prepend(). The impact should be minimal and it is clearer and more intuitive.
I like the original documentation, it's clear and concise. It should still be valid even with the proposed change.
Some things of note:
append(atom1, atom2) would be the same as atom1 & atom2
append(atom1, sequence1) would be the same as append({atom1}, sequence1)
Ok, I've now implemented a prototype implementation at http://scm.openeuphoria.org/hg/euphoria/rev/b49d88483f04
There may be room to improve upon this, but at least it's a starting point. If we still want to do this, that is.
72. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 16, 2014
- 3765 views
Ok, I've now implemented a prototype implementation at http://scm.openeuphoria.org/hg/euphoria/rev/b49d88483f04
3.1 --- a/source/execute.e Tue Jun 10 20:31:17 2014 -0400 3.2 +++ b/source/execute.e Sun Jun 15 18:33:11 2014 -0400 3.3 @@ -2965,7 +2965,11 @@ 3.4 a = Code[pc+1] 3.5 b = Code[pc+2] 3.6 target = Code[pc+3] 3.7 + if atom(val[a]) then 3.8 + val[target] = append({val[a]}, val[b]) 3.9 + else 3.10 val[target] = append(val[a], val[b]) 3.11 + end if 3.12 pc += 4 3.13 end procedureThat should be unnecessary, unless you need execute.e to run on previous versions of OE
Pete
73. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 16, 2014
- 3751 views
That should be unnecessary, unless you need execute.e to run on previous versions of OE
Agreed. The same is true of all the changes to execute.e in this branch. However, this is a prototype branch. The point is that users can check it out and immediately experiement with it.
So, all the changes are made to execute.e with the idea that they should run on the default branch while being able to demonstrate the new functionality.
(Well, that's part of it. The other part is that it's easier to prototype the changes in Eu in execute.e, get some test code running to validate the changes, then redo the changes in C afterwards and make sure that both versions produce the same output from the test code.)
74. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 16, 2014
- 3727 views
Jim, just out of curiosity, did you consider this style of implementation? ...
if atom(val[a]) then val[target] = val[a] & {val[b]} else val[target] = append(val[a], val[b]) end if
75. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 16, 2014
- 3748 views
Jim, just out of curiosity, did you consider this style of implementation? ...
if atom(val[a]) then val[target] = val[a] & {val[b]} else val[target] = append(val[a], val[b]) end if
I didn't. Should I change it to this? Is it better than append({val[a]}, val[b]) ?
76. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 16, 2014
- 3726 views
Lets change the behavior of operator[]:
atom a1 = 5 for i = 1 to length(a1) do ? a1[i] -- prints 5 end for
JUST KIDDING!
Seriously, this continued treatment of atoms as one-member sequences in more and more instances will only add to confusion. Changing behavior of things is low lying fruit. In some cases this will break new users. In EUPHORIA 5 != {5} but the standard library and builtins more and more treat them as if they are the same.
For example: If you do a match_replace with 'a' you will replace 'a' in a word without complaints but if you are purposely replacing one character in a string you ought to use find_replace and this kind of distinction should be taught everywhere for consistency.
When you try to replace a word in a list of words using match_replace, you would get burned. The lazy conversion here causes people to use a function wrong and learn it wrong. The word wont be replaced in the word because it is comparing the word with lists of words. One might argue good programmers would never make this mistake, however.
If you are using a data structure which contains a list of numbers, you are not going initialize the list to one number. If you know what you are doing, you might initialize it to 0 to signal it is not yet setup and later initialize it with a sequence of numbers. Setting this list to a single atom is an accident and changing append such that it hides this kind of problem is a mistake.
Shawn Pringle
77. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 16, 2014
- 3719 views
Seriously, this continued treatment of atoms as one-member sequences in more and more instances will only add to confusion. Changing behavior of things is low lying fruit. In some cases this will break new users. In EUPHORIA 5 != {5} but the standard library and builtins more and more treat them as if they are the same.
I understand your concern, Shawn. I can see why one might come to this conclusion. So please indulge me to explain where I was coming from.
My proposed change is based around function-centric rather than data-centric thinking. Of course an atom is never a sequence. These datatypes are by definition mutually exclusive. However, I was thinking more along the lines of the activity that append()/prepend() is trying to do, the end result of its endeavours. Namely, add a single object to something to form a list. Currently that 'something' must be an existing list, and all I want to do is expand its usefulness to allow 'something' to be any object. The functionality of append()/prepend() would remain identical.
For example: If you do a match_replace with 'a' you will replace 'a' in a word without complaints but if you are purposely replacing one character in a string you ought to use find_replace and this kind of distinction should be taught everywhere for consistency.
This is a good example ... but maybe not of what you were trying to show. To me this is a good example of poor function naming. The difference between 'find' and 'match' in English is extremely subtle and most people would actually use them interchangeably. Maybe its just me, but I've been burned by this a number of times until I finally learned the Euphoria meanings off-by-heart.
Maybe they should have been named like "locate_an_item_and_replace" and "locate_a_tuple_and_replace" ... well you get the picture ...
The find_replace() is problematic on a few levels anyway. Consider ...
result = find_replace('a', "This is a list of characters", "A") --> {'T','h','i','s', ' ', 'i', 's', ' ', {'A'}, ' ', 'l', 'i', 's', 't', ... etc }
find_replace() can be used to find a character and replace it with a word! Probably not was intended. And similarly with match_replace().
When you try to replace a word in a list of words using match_replace, you would get burned. The lazy conversion here causes people to use a function wrong and learn it wrong. The word wont be replaced in the word because it is comparing the word with lists of words. One might argue good programmers would never make this mistake, however.
Hmmm ... not so sure about that.
object word = "abc" object word_list = {"def", "abc", "ghi"} object new_word = "xyz" result = match_replace(word, word_list, new_word)
Of course, if word_list was initialized to "def,abc,ghi" then it would fail. But I'd argue (taking the data-centric view point), that is a list of characters and not a list of words
If you are using a data structure which contains a list of numbers, you are not going initialize the list to one number. If you know what you are doing, you might initialize it to 0 to signal it is not yet setup and later initialize it with a sequence of numbers. Setting this list to a single atom is an accident and changing append such that it hides this kind of problem is a mistake.
Again, a good example. Especially of breaking the good programming design principle of never using a single data item to represent multiple concepts. A better design is to use two variables - one to indicate the state of the list and another for the actual list. But I digress ... ok, given this scenario, we have a program that doesn't check the state of the list before using it. That is to say, the program has a bug in it. Now consider, what if instead of append(), the program was using concatenate when using the list (because it needed to add multiple items rather than just one). In that case, the bug would still remain hidden. So should we consider changing concatenate to only add to sequences? It could be that, until learned, a new Euphoria programmer could assume that 1 & 2 & 3 gives 123 rather than {1,2,3}?
78. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 16, 2014
- 3706 views
While we shouldn't confuse atoms with sequences, there are many times when it makes sense to accept any object. This is one of those cases.
Same with length of an atom being 1 while the length of the empty sequence is 0.
79. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 17, 2014
- 3711 views
Derek, Thank you for taking the time to explain your rationale. As you pointed out everything about a language is learned after all. So, this is not about belief or facts but rather about feelings.
I feel that append should continue to be a function where the first argument is a sequence and the second an object. I have never written a EUPHORIA program and wished that append could accept() a character as the first argument. I sincerely believe you are the only person who has ever wished they could pass an atom to the first argument of this function.
Shawn
80. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 17, 2014
- 3658 views
So, this is not about belief or facts but rather about feelings.
Hmm ... kind of ... the only empirical thing I can come up with, which is actually why I even bothered in the first place, is that if it were built into the append() function (i.e. C code) it would give better performance than using IL code. The built-in is already testing for the first argument's data-type so there's no change there, so the only difference would be that instead of crashing the application, it could efficiently build a new sequence using the first argument.
81. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 18, 2014
- 3609 views
So, this is not about belief or facts but rather about feelings.
Hmm ... kind of ... the only empirical thing I can come up with, which is actually why I even bothered in the first place, is that if it were built into the append() function (i.e. C code) it would give better performance than using IL code. The built-in is already testing for the first argument's data-type so there's no change there, so the only difference would be that instead of crashing the application, it could efficiently build a new sequence using the first argument.
I believe Derek is saying if we don't have this change, map:put with the APPEND argument will have to handle more cases specially in order to behave as intended. I am saying routines have this kind of strictness to data-types to help users. Especially new users who are learning the language. A new user who misuses this builtin currently gets a helpful error. I feel the if in doubt give an error is more in the spirit of EUPHORIA. Instead of garbage in - garbage out. It is garbage in - give a helpful error. Like I said before, it is subjective which is better.
I think there are better ways to improve EUPHORIA's performance.
Maybe we can handle the case specially where a variable is passed to a user defined function and the result of that function is assigned to that variable. It really shouldn't add a reference at all but just leave the reference count alone in this circumstance to avoid unnecessary copying. Another thing, what is the bottle neck that motivates library wrapping developers to create shims for libraries? Is it the cost of the allocate/poke/peek cycle? Is c_func too slow?
Shawn
82. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 18, 2014
- 3603 views
We had a classic at work today:
We had been writing
S14 for Spring FY 13/14
X14 Christmas
A14 Autumn
T14 Tax
All clear and no problems.
Then it was decided that this was not good enough because they did not sort in order.
So this is changed to:
141
142
143
144.
What happened next was unfortunate.
Two appeals at one time, one file containing records for both, the same sub-codes for both, no communication.
We had campaign codes like 143A-MAR-12 and 144A-MAR-12, not exactly distinguishable.
I failed to see that there were 2 campaigns in the list (this was unexpected - like I had never seen this before). As a result all were imported to the database as campaign 144.
During the processing (in Excel) the records within the the sub-groups with an empty column between so the database IDs no longer matched the list IDs. (Two separate files not checked off against each other).
This was not detected: no one checked as this has not happened before.
This story has some relation to efficiency, cutting corners, etc.
I'm thinking
documentation: communication,
clear coding: meaningful names,
typing: one file per campaign.
83. Re: Discuss changing the behaviour of append()
- Posted by euphoric (admin) Jun 18, 2014
- 3633 views
If we look at the term append(), there's no obviousness, innately or on the surface, about what it should accept as parameters. The only thing we can draw from it is that we will get a sequence of items, whereby the needle is added to the end of the haystack. This needle can be sequence or atom, and the haystack can be sequence or atom, so long as the result is a sequence.
If it matters, I'm not against modifying the behavior of append() to accept (object,object).
84. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 20, 2014
- 3539 views
Here is some code to test append:
-- given sequence s = {1,2,3,4,5,6,7,8,9,10} -- want --> {2,4,6,8,10} that is reduce s to all even items --> use a recursive function to do this function isEven(atom x) --common utility function return remainder( x,2 ) = 0 end function --------------------------------------------------------------- -- CASE I function extractEvens1( sequence list ) if equal( list, {}) then return {} elsif isEven( list[1] ) then return append( list[1], extractEvens1( list[2..$ ] ) ) else return extractEvens1( list[2..$] ) end if end function ? extractEvens1( s ) --error --> first argument of append must be a sequence -- CASE II -- respond to classic OE error message -- use & -- (since append can not be used) function extractEvens2( sequence list ) if equal( list, {}) then return {} elsif isEven( list[1] ) then return list[1] & extractEvens2( list[2..$ ] ) else return extractEvens2( list[2..$]) end if end function ? extractEvens2( s ) --> {2,4,6,8,10} --> get the "expected" result -- CASE III -- "change behavior of append" -- grab a slice function extractEvens3( sequence list ) if equal( list, {}) then return {} elsif isEven( list[1] ) then return append( list[1..1] , extractEvens3( list[2..$ ] ) ) else return extractEvens3( list[2..$]) end if end function ? extractEvens3( s ) -- { -- 2, -- { -- 4, -- { -- 6, -- { -- 8, -- {10,{}} -- } -- } -- } --} sequence s3 = extractEvens3(s) include std/sequence.e s3 = stdseq:flatten(s3) ? s3 --> {2,4,6,8,10} -- CASE IV function extractEvens4( sequence list ) if equal( list, {}) then return {} elsif isEven( list[1] ) then if atom( list[1] ) then list[1] = { list[1]} end if return append( list[1] , extractEvens2( list[2..$ ] ) ) else return extractEvens4( list[2..$]) end if end function ? extractEvens4( s ) -- { -- 2, -- {4,6,8,10} -- } -- an odd looking result
- CASE I: classic error message, I did something wrong.
- CASE II: based on classic error message, I fix the program.
- CASE III: try to "fix" append, I get a result in an indirect way.
- CASE IV: try to "fix" append, output is now ugly.
The proposed change to O[ looks like
3.1 --- a/source/execute.e Tue Jun 10 20:31:17 2014 -0400 3.2 +++ b/source/execute.e Sun Jun 15 18:33:11 2014 -0400 3.3 @@ -2965,7 +2965,11 @@ 3.4 a = Code[pc+1] 3.5 b = Code[pc+2] 3.6 target = Code[pc+3] 3.7 + if atom(val[a]) then 3.8 + val[target] = append({val[a]}, val[b]) 3.9 + else 3.10 val[target] = append(val[a], val[b]) 3.11 + end if 3.12 pc += 4 3.13 end procedure
Looks like this is a CASE IV solution
- works for a simple case
- result can be ugly
Explaining CASE I to newcomers to O[ is simple. Explaining CASE IV is difficult; hard to justify a possible ugly result.
_tom
85. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 20, 2014
- 3514 views
-- CASE III elsif isEven( list[1] ) then return append( list[1..1] , extractEvens3( list[2..$ ] ) )
This is non-sensical. This has the effect of creating a new sequence, even if list[1] is already a sequence. It is equivelant to:
elsif isEven( list[1] ) then if atom( list[1] ) then list[1] = { list[1]} else list[1] = { list[1]} end if
-- CASE III sequence s3 = extractEvens3(s) include std/sequence.e s3 = stdseq:flatten(s3) ? s3 --> {2,4,6,8,10}
- CASE III: try to "fix" append, I get a result in an indirect way.
But this indirect way works for case IV as well.
-- CASE IV sequence s4 = extractEvens4(s) include std/sequence.e s4 = stdseq:flatten(s4) ? s4 --> {2,4,6,8,10}
The proposed change to O[ looks like
3.1 --- a/source/execute.e Tue Jun 10 20:31:17 2014 -0400 3.2 +++ b/source/execute.e Sun Jun 15 18:33:11 2014 -0400 3.3 @@ -2965,7 +2965,11 @@ 3.4 a = Code[pc+1] 3.5 b = Code[pc+2] 3.6 target = Code[pc+3] 3.7 + if atom(val[a]) then 3.8 + val[target] = append({val[a]}, val[b]) 3.9 + else 3.10 val[target] = append(val[a], val[b]) 3.11 + end if 3.12 pc += 4 3.13 end procedure
Yes, and (assuming I did it right) the change to the C runtime works identically.
Looks like this is a CASE IV solution
Agreed.
Explaining CASE I to newcomers to O[ is simple.
Explaining how it works is simple. Justifying the reasons behind it is not so easy.
If someone things that explaining away the reason for this behavior is easy, then please explain why, in original instance (i.e. before we have code and have to deal with backwards incompatibilities), should append() only allow the haystack to be a sequence?
Explaining CASE IV is difficult; hard to justify a possible ugly result.
extractEvens() seems to naturally fit better with concatenation, not append, regardless.
86. Re: Discuss changing the behaviour of append()
- Posted by mindwalker Jun 20, 2014
- 3516 views
Explaining CASE I to newcomers to O[ is simple.
Explaining how it works is simple. Justifying the reasons behind it is not so easy.
If someone things that explaining away the reason for this behavior is easy, then please explain why, in original instance (i.e. before we have code and have to deal with backwards incompatibilities), should append() only allow the haystack to be a sequence?
The original append functionality made sense, an atom by definition is autonomous and can't have something appended to it. An analogy, think of an atom as a point. You can't append another point to it because as soon as you do it is no longer a point. It becomes something else entirely, a line perhaps.
That said it was a little short sighted. One big strength of Euphoria is not having to remember to use the sequence append when appending to a sequence and the atom append when creating a sequence by putting a supplied atom into a new sequence and then appending another atom, and the object append when you are working with objects, etc.
So many other languages have this data type differentiation in their functions; either by function overloading or by multiple functions with different names that do the same basic thing but that take different parameter types. This is one reason other languages can be so hard to learn.
87. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 20, 2014
- 3468 views
Whats left is to make sure that append, prepend, and insert are consistent.
I can't figure out a way to "break" the expanded viewpoint for append. As Jim Brown shows, non of the attemps are convincing.
As Mindwalker suggests, it makes more sense than the old way.
_tom
88. Re: Discuss changing the behaviour of append()
- Posted by petelomax Jun 21, 2014
- 3421 views
Here is some code to test append:
FYI (this does not really add anything to the subject being discussed), this is how I would code that (if I had to use recursion):
sequence s = {1,2,3,4,5,6,7,8,9,10} function isEven(atom x) --common utility function return remainder( x,2 ) = 0 end function function extractEvens(sequence source, integer done=0, sequence thusfar={}) done += 1 if done>length(source) then return thusfar end if atom thisone = source[done] if isEven(thisone) then thusfar = append(thusfar,thisone) end if return extractEvens(source, done, thusfar) end function ? extractEvens(s)
89. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 21, 2014
- 3491 views
Just a question:
Assuming that appending/prepending to atoms is on
we have:
? append(1,{}) -- {1,{}} ? append({},1) -- {1} ? prepend(1,{}) -- {{},1} ? prepend({},1) -- {1}
I'm not saying it's wrong but don't you find the difference strange?
90. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 21, 2014
- 3376 views
Just a question:
Assuming that appending/prepending to atoms is on
we have:
? append(1,{}) -- {1,{}} ? append({},1) -- {1} ? prepend(1,{}) -- {{},1} ? prepend({},1) -- {1}
I'm not saying it's wrong but don't you find the difference strange?
No I don't, because the result is identical to when the first argument is a sequence ...
-- Ensuring that the first parameter is a sequence. ? append({1},{}) -- {1,{}} ? append({},1) -- {1} ? prepend({1},{}) -- {{},1} ? prepend({},1) -- {1} -- Performing the 'equivalent' functionality using concatenate ? {1} & {{}} ? {} & {1} ? {{}}& {1} ? {1} & {}
Or putting the operation into English text ...
- Create a list such that the second argument is added, as a single element, to the set of elements in the first argument.
91. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 21, 2014
- 3346 views
Here is some code to test append:
-- given sequence s = {1,2,3,4,5,6,7,8,9,10} -- want --> {2,4,6,8,10} that is reduce s to all even items --> use a recursive function to do this
Tom,
the append() function is not the appropriate functionality to use in this case because it appends the second argument as a single element to the result, and if the extract function is returning a list of things, then using its returned object in this manner is not what is required. The concatenate operator is a better choice for this exercise. To use append(), the extract function would have to return only a single element from the original list each time it was called.
92. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 21, 2014
- 3355 views
Derek,
What I was getting at is this (and we agree this is not about a processing error).
An argument could be made that:
append(1,{}) -- {1,{}} prepend(1,{}) -- {{},1}
ought to be identical as {} is empty. (We assume the return value is a sequence).
i.e. it should not matter if you prepend or append an empty sequence you have added nothing.
Mathmatically this means: {} is the identify under append. which would mean:
{} append A == A append {} -- == equivalence
I certainly could understand people reading things this way.
I know it doesn't fit with the mechanics of Eu.
Appending an empty slice might appear as an error.
93. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 22, 2014
- 3358 views
An argument could be made that:
append(1,{}) -- {1,{}} prepend(1,{}) -- {{},1}
ought to be identical as {} is empty. (We assume the return value is a sequence).
i.e. it should not matter if you prepend or append an empty sequence you have added nothing.
Ahh... I see what you were trying to get across now.
However, "you have added nothing" is not accurate. The append()/prepend() functions add the second argument as a whole to form the new sequence element. An empty list is still a list; it is a something; an object. The append()/prepend() functions do not add the contents of a list to the first argument, but the entire object itself. For example ...
append({1}, {1}) --> gives {1, {1}} and not {1, 1} prepend({1}, {1}) --> gives {{1}, 1} and not {1, 1} --thus-- append({1}, {}) --> gives {1, {}} and not {1} prepend({}, {1}) --> gives {{}, 1} and not {1}
In all cases, append(X,Y) is identical in result to X & {Y} and prepend(X,Y) is identical in result to {Y} & X so that gives ...
object X, Y, Z X = {1} Y = {} Z = append(X, Y) --> gives {1, {}} Z = X & {Y} --> gives {1, {}} Z = prepend(X, Y) --> gives {{}, 1} Z = {Y} & X --> gives {{}, 1}
Mathmatically this means: {} is the identify under append. which would mean:
{} append A == A append {} -- == equivalence
I certainly could understand people reading things this way.
I know it doesn't fit with the mechanics of Eu.
If append(1,{}) were to give {1}, then it must follow that append(1, {2,3}) should give {1,2,3}, and that is not what it is intended to do. Likewise if prepend(1,{}) were to give {1}, then it must follow that prepend(1, {2,3}) should give {2,3,1}, and again, that is not what it is intended to do.
Appending an empty slice might appear as an error.
There is effectively nothing different between an empty slice and an empty sequence.
94. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3351 views
Not wanting this to degenerate.
From the Haskell wikibook:
In earlier parts of the book, we have made a few passing allusions to monoids and the Monoid type class ... Here we'll give them a more detailed look and show what makes them useful. Introduction
A monoid (m, mappend, mempty) is a type m together with an associative operation mappend :: m -> m -> m (also called (<>) in Haskell) that combines two elements and a zero element mempty :: m which is the neutral element of mappend: Before describing them more formally, let's see monoids in action. Examples
As an information introduction, let's take a look at a common pattern:
> (5 + 6) + 10 == 5 + (6 + 10) True > (5 * 6) * 10 == 5 * (6 * 10) True > ("Hello" ++ " ") ++ "world!" == "Hello" ++ (" " ++ "world!") True
This property is called associativity, and it doesn't hold for only those selected values but for all integers under addition, all integers under multiplication, and all lists under concatenation.
Here's another type of pattern:
> 255 + 0 == 255 && 0 + 255 == 255 True > 255 * 1 == 255 && 1 * 255 == 255 True > [1,2,3] ++ [] == [1,2,3] && [] ++ [1,2,3] == [1,2,3] True
Here 0 is the identity element when adding integers,
1 is the identity when multiplying them, and,
[] is the identity when appending two lists.
So:
Integers form a monoid under addition where 0 is the unit: (Integer, (+), 0) Integers form a monoid under multiplication where 1 is the unit: (Integer, (*), 1) Lists form a monoid under concatenation: ([a], (++), []) ...
Take a function that concatenates three lists:
threeConcat :: [a] -> [a] -> [a] -> [a] threeConcat a b c = a b c
We can generalize this function to work with any monoid:
threeConcat' :: Monoid m => m -> m -> m -> m threeConcat' a b c = a <> b <> c
threeConcat' "Hello" " " "world!" -- "Hello world!" threeConcat' (Sum 5) (Sum 6) (Sum 10) -- Sum {getSum = 21}
Other functions like fold :: (Foldable t, Monoid m) => t m -> m from Data.Foldable use properties of monoids to reduce any foldable structure containing monoids into a single monoidal value:
fold ["Hello", " ", "world!"] -- "Hello world!" > fold (Just (Sum 10)) -- Sum {getSum = 10} > fold Nothing :: Sum Integer -- Sum {getSum = 0}
My point is not that Euphoria should be more Haskell-like but that the monoid makes it easy reasoning about functions.
Our append is strange this way. It has no identity.
95. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3347 views
From the Haskell wikibook:
This property is called associativity, and it doesn't hold for only those selected values but for all integers under addition, all integers under multiplication, and all lists under concatenation.
[] is the identity when appending two lists.
Lists form a monoid under concatenation: ([a], (++), [])
Other than one lapse, the term concatenation is used consistently.
Our append ... has no identity.
Agreed.
Our append is strange this way. It has no identity.
Well, I think this is not so strange. Lots of functions lack an identity. f(x) = x + 1 lacks an identity. Logical NOT lacks an identity.
Furthermore, this has nothing to do with the proposed change. Even without it, append lacks an identity. To demonstrate this with the most likely canidate, append({}, {}) does not return {}.
append also lacks associativity. append(1, {}) and append({}, 1) return different things. Again, this is nothing to do with the proposed change - append({1}, {2}) and append({2}, {1}) also return different things. Other mathematical functions, like division or subtraction, also lack associativity.
96. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3331 views
Jim,
So what? What are you trying to prove?
All you are doing is confirming the obvious.
a + b == b + a a + 0 == 0 + a
is what I am talking about.
Are you listening?
97. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3340 views
Jim,
So what? What are you trying to prove?
All you are doing is confirming the obvious.
a + b == b + a a + 0 == 0 + a
is what I am talking about.
Are you listening?
Are you?
append also lacks associativity. append(1, {}) and append({}, 1) return different things. Again, this is nothing to do with the proposed change - append({1}, {2}) and append({2}, {1}) also return different things. Other mathematical functions, like division or subtraction, also lack associativity.
To borrow your example,
a + b = b + a a + 0 = 0 + a
Also see that,
a / b = b / a a / 1 = 1 / a
Oh, wait a minute....
is what I am talking about.
Actually, you contradict yourself. You state,
a + b == b + a a + 0 == 0 + a
is what I am talking about.
as well as
From the Haskell wikibook:
This property is called associativity,
but you also say
Our append is strange this way. It has no identity.
These (lack of associativity and lack of identity) are two different things.
98. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3325 views
So, Jim,
Associativity doesn't require identity?
Is that what you are saying?
Well, no it doesn't - did I say it did?
But "Hello World!" & "" = "Hello World!"
or didn't you notice?
If A append B is not a monoid then|| (OK: you have your own (rather (beautiful??) operator))
But what have you proved to the world?
I think Jim,
that what you have proved is that (mostly, you are talking BS).
99. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3362 views
So, Jim,
Associativity doesn't require identity?
Is that what you are saying?
I didn't say that - but it's true: http://en.wikipedia.org/wiki/Semigroup
Haskell has a list concatenation operator that has both of these properties, as does Euphoria's own concatenation operator. Euphoria's append has neither. I don't find this state of affairs particularly strange - concatenation naturally has these properties, but the function we define as append (which can be simulated by concatenation) does not.
Well, no it doesn't - did I say it did?
Since you contradict yourself, it's very hard to determine what you are saying.
But "Hello World!" & "" = "Hello World!"
or didn't you notice?
You keep comparing append to concatenation. If you are trying to state that append should behavior identically to concatenation, please state so explicitly, not in this roundabout way.
If you disagree that append should behavior identically to concatenation, I'd like to see some examples where you believe they ought to behave differently.
If A append B is not a monoid then|| (OK: you have your own (rather (beautiful??) operator))
Hardly. Appending is basic operation involving any kind of list structure. I can't think of a single programming language that lacks a function or method to implement this functionality. (Maybe Haskell.)
But what have you proved to the world?
I think Jim,
that what you have proved is that (mostly, you are talking BS).
This is implicitly an ad hominen argument and can be dismissed as such.
I'll restart my original argument for clarity: Since there are many mathematical functions which lack both the associativity and identity properties, I do not find it at all strange that Euphoria's append routine lacks these properties as well.
100. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3360 views
[quote jb] gimlet said...
So, Jim,
Associativity doesn't require identity? Is that what you are saying?
I didn't say that - but it's true: http://en.wikipedia.org/wiki/Semigroup
Haskell has a list concatenation operator that has both of these properties, as does Euphoria's own concatenation operator. Euphoria's append has neither. I don't find this state of affairs particularly strange - concatenation naturally has these properties, but the function we define as append (which can be simulated by concatenation) does not. gimlet said...
Well, no it doesn't - did I say it did?
Since you contradict yourself, it's very hard to determine what you are saying. gimlet said...
But "Hello World!" & "" = "Hello World!" or didn't you notice?
You keep comparing append to concatenation. If you are trying to state that append should behavior identically to concatenation, please state so explicitly, not in this roundabout way.
If you disagree that append should behavior identically to concatenation, I'd like to see some examples where you believe they ought to behave differently. gimlet said...
If A append B is not a monoid then|| (OK: you have your own (rather (beautiful??) operator))
Hardly. Appending is basic operation involving any kind of list structure. I can't think of a single programming language that lacks a function or method to implement this functionality. (Maybe Haskell.) gimlet said...
But what have you proved to the world?
I think Jim, that what you have proved is that (mostly, you are talking BS).
This is implicitly an ad hominen argument and can be dismissed as such.
I'll restart my original argument for clarity: Since there are many mathematical functions which lack both the associativity and identity properties, I do not find it at all strange that Euphoria's append routine lacks these properties as well.
I didn't say that - but it's true: http://en.wikipedia.org/wiki/Semigroup
So Jim,
I contradict myself.
But "Hello World!" & "" = "Hello World!" or didn't you notice?
You keep comparing append to concatenation. If you are trying to state that append should behavior identically to concatenation, please state so explicitly, not in this roundabout way.
Jim, you are so sure!
1 Why should append be different? Append is supposed to be fast and (&) slow. So Jim, what are you saying, that I should not expect them to behave similarly? That I must expect a slow program because I asked for correct behaviour?
That because Euphoria's append is not a monoid that I expect all functions to be monoids?
And on the ground that many FUNCTIONS are not monoids you argue... what?
Jim, I am rather of the opinion that you don't know what you are talking about.
So how much maths did you do? To what purpose?
101. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 22, 2014
- 3345 views
Not wanting this to degenerate.
LOL ... how's that working out for you?
My point is ... that the monoid makes it easy reasoning about functions.
In what ways do "the monoid makes it easy reasoning about functions"?
Our append is strange this way. It has no identity.
Oh well ... c'est la vie.
Euphoria's append() works, its useful, and it's used. I've got no problem with the concept behind it. Should I have?
102. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 22, 2014
- 3327 views
(mostly, you are talking BS).
Well ... that escalated quickly!
103. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3377 views
And on the ground that many FUNCTIONS are not monoids you argue...
Jim, I am rather of the opinion that you don't know what you are talking about.
So how much maths did you do?
Again, I get the impression that if you believe that probability is BS then you you didn't go very far.
More ad hominen attacks and now a Loaded Statement ...
This post lacks any new facts or a valid logical argument. I think we've crossed the line into personal attacks here.
Another post like this, and I'm placing you under "extraordinary measures". If you can't play nice, then don't play at all.
104. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3335 views
OK Jim,
And I suppose I have no recourse.
Bye.
I hope the others agree with you.
105. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3329 views
My point is ... that the monoid makes it easy reasoning about functions.
In what ways do "the monoid makes it easy reasoning about functions"?
Our append is strange this way. It has no identity.
Oh well ... c'est la vie.
Euphoria's append() works, its useful, and it's used. I've got no problem with the concept behind it. Should I have?
I think Shawn hit it on the nail when he said ( http://openeuphoria.org/forum/m/124652.wc ) that it wasn't about facts but feelings. Changing append to be monoid (whatever that would look like) is one of these (unlike the original topic, where the change is backed up by facts about performance optimization and code/algorithm simplication by removing edge cases).
106. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3307 views
Jim, Shawn, Derek,
I haven't been making ad hominem attacks.
My criticism of Jim is criticism of his attacks on me.
He thinks that because I said something about monoids I wanted changes.
I had repeatedly said I didn't (and Derek, I have kept my silence except
in the face of Jim's attacks).
Personally, I don't care much any more, as it is clear that Euphoria is not going to be usable for what I want. And no, that is not sour grapes, just the truth. If load_map doesn't work then I need to use GAWK (and these days I can get up to date versions for Windows so I'm happy).
Jim outed me of course.
107. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3330 views
That because Euphoria's append is not a monoid that I expect all functions to be monoids?
1 Why should append be different?
So Jim, what are you saying, that I should not expect them to behave similarly?
Exactly. append and concatenation are two different things, two different functions. The same way that f(x) = x + 1 and g(x, y) = x + y are two different functions. They simply do different things and therefore do not behavior similarily.
That I must expect a slow program because I asked for correct behaviour?
The fact that concatenation is slower (in the general case only) is irrelevant. Even if it were faster than append, the two functions still are two different functions. (Incidently, when concatenating an atom and a sequence, concatenation is implemented by calling either append or prepend (in the later case swapping the arguments), depending on the order of the arguments. So concatenation is not always slower.)
And on the ground that many FUNCTIONS are not monoids you argue... what?
That append is not strange, as you originally posed:
I'm not saying it's wrong but don't you find the difference strange?
OK Jim,
And I suppose I have no recourse.
Bye.
I'd like to say good riddance, but I have a feeling that this wouldn't be the case: http://openeuphoria.org/forum/m/118296.wc http://openeuphoria.org/wiki/view/forum-msg-id-124160-edit.wc
108. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3340 views
Jim, Shawn, Derek,
I haven't been making ad hominem attacks.
Denial won't help you.
He thinks that because I said something about monoids I wanted changes.
I had repeatedly said I didn't
I never stated this. I did call a "proposed change" making append gain the properties of associtivity and identity, but this was just to emphasis that today, without Derek's idea of allowing atoms in the first argument of append, append still lacks those properties. It always did.
If load_map doesn't work
I asked you before what about load_map() was broken: http://openeuphoria.org/forum/m/124614.wc
You didn't answer then, which now makes me think that it's because you can't.
Jim outed me of course.
I have no recollection of this. I admit that I'm not sorry to see you go, but, wait, you are still here!
109. Re: Discuss changing the behaviour of append()
- Posted by gimlet Jun 22, 2014
- 3353 views
So you don't remember:
You went out of your way to ...
gimlet said...
Yet you then tell me what I already know (and don't understand).
I think it's better to be a little repetitive to establish common ground and make sure all sides are discussing the same topic, than to make assumptions about what the other side knows and doesn't know. gimlet said...
This may not be couth:
Agreed. Quoting a post that is entirely unrelated to what you are saying and then double posting both are not couth. gimlet said...
every time I say 'I don't understand this' or, 'I don't think this is right' I am assumed to stupid.
This is a real pain: you are saying I am stupid.
I can't recall anyone saying this. Still, by your use of the generic 'you', you seem to think that everyone is saying so. If you believe that everybody thinks this about you, regarding such an intimate state about yourself, then - regardless of what everybody is truly thinking - perhaps there is some truth to the matter.
I mean, you should know if you are stupid or not, right?
I previously said that one shouldn't be afraid to ask questions here, and that's still true. Unfounded accusations, however, are not welcome. gimlet said...
Because you make up your mind instantly you miss important things.
If this is the case for "everybody", then maybe it's you who is missing something.
For example, to quote myself, from
http://openeuphoria.org/forum/m/124133.wc jimcbrown said...
please demonstrate a use case where it is necessary to preserve carriage returns.
Still waiting on an answer for that.
I also said, jimcbrown said...
Even so, we might want to add a with-statement option to control this behavior,
but, I'm not sure if it's worth the effort if there's no known use case for it. I'm willing to compromise but I'm going to need a little more first. gimlet said...
So what use are you to me?
What use are you to me? What use are you to the rest of the community? No one is getting paid for this. If this isn't fun for us, then why should anyone have long pointless debates with you about irrelevant details? gimlet said...
Bill
I thought this was your final message: http://openeuphoria.org/forum/m/118296.wc
And what is that?
110. Re: Discuss changing the behaviour of append()
- Posted by jimcbrown (admin) Jun 22, 2014
- 3352 views
So you don't remember:
You went out of your way to ...
I think it's better to be a little repetitive to establish common ground and make sure all sides are discussing the same topic, than to make assumptions about what the other side knows and doesn't know.
So this is in reference to a post on a different thread, where I stated:
Anyways, this load_map() argument is becoming quite repetitive. Unless you (or anyone else) has any new evidence, I think we should just agree to disagree and drop the subject.
at http://openeuphoria.org/forum/m/124693.wc
Yes, it's constructive to be a little repetitive to make sure both sides are talking about the same thing, but once that's been established, it's still possible to become too repetitive, rehashing the same arguments over and over, post after post.
Bill
I thought this was your final message: http://openeuphoria.org/forum/m/118296.wc
And what is that?
I thought it'd be self-evident.
111. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 24, 2014
- 3278 views
Just a question:
Assuming that appending/prepending to atoms is on
we have:
? append(1,{}) -- {1,{}} ? append({},1) -- {1} ? prepend(1,{}) -- {{},1} ? prepend({},1) -- {1}
I'm not saying it's wrong but don't you find the difference strange?
Thanks to Gimlet, the documentation has hopefully been improved:
I think you can choose to view this as strange or as not strange. From there you can design two forks of Euphoria.
Consider append and prepend to be special cases of the insert function.
The proposed changes to O[ are going to put emphasis on object behavior and blur some previous atom-sequence distinctions. While a != {a} remains true, the new behavior tolerates the idea that a becomes {a} when it is convenient in a prepend, insert, or append.
TARGET is an atom, like 1, is promoted to { 1 ,$} using prepend, insert, append prepend append V V { a ,$ } -- all sequences can be written using the ,$ end marker ^ ^ 1 2 -- insert index value -- 1 is like prepend -- 2 is like append when inserting a empty sequence into an "promoted" atom the results are { {}, 1} {1, {} }
TARGET is an empty sequence, like {}, can be written as {$} prepend append V V { $ } -- an empty sequence can be written using the $ end marker ^ ^ 1 2 -- insert index value -- 1 is like prepend -- 2 is like append when inserting an atom into an empty sequence the results are { 1 } { 1 }
The length function is now oddly named. It could have been named item_count (items, count, size, topsize, ... ?)
- on its own {} has a zero item count, but inside a sequence it is itself one item
- length( { } ) or length( "" ) is zero, this does not mean a null sequence, but a sequence with no item count
- length( a ) is one, this does not mean a number has "length", but that one atom is one item
- length( {a} ) = length( a ) means there is one item count in each example
Concatenation combines objects into one. The total item count is equal to the sum of the individual item counts.
Insert, prepend, or append extends the item count by exactly one.
The results of an insertion follow a consistent pattern; from that basis the results are not strange.
If the results seem "strange" is it because an empty sequence can be both paradoxically "length zero and one item"? Note that quantum physics copes with ideas like this.
Another consideration is that syntax is not mathematics. Sometimes syntax is based on mathematics (consider lisp, haskel), sometimes syntax just looks like mathematics (consider the assignment operator = which is better represented by :=), and sometimes syntax just happens when a language is designed.
You must always believe in the documentation, the basis of all truth, and disregard all previous knowledge; documentation in progress see above. (If you are not in a humorous mood, ignore the previous sentence.)
_tom
112. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 24, 2014
- 3154 views
Give me documentation that is right and code that is poorly written and you have bugs in the code. Give me documentation that is wrong and code that is well written and you have bugs in the code because documentation is the promise and the code is the execution of that promise.
Shawn
113. Re: Discuss changing the behaviour of append()
- Posted by _tom (admin) Jun 24, 2014
- 3171 views
Give me documentation that is right and code that is poorly written and you have bugs in the code. Give me documentation that is wrong and code that is well written and you have bugs in the code because documentation is the promise and the code is the execution of that promise.
Shawn
So, how close am I getting to understandable documentation that tells the truth?
I welcome bits and pieces of documentation (let them be rough, let them be just ideas). A community project is not a one person job.
_tom
114. Re: Discuss changing the behaviour of append()
- Posted by SDPringle Jun 24, 2014
- 3151 views
Please don't refer to 'quantum physics' in the documentation. Let's avoid referring to something so counterintuitive in a document that describes something so simple and intuitive. Please don't use smilies in the documentation.
115. Re: Discuss changing the behaviour of append()
- Posted by jaygade Jun 24, 2014
- 3144 views
I think it's a mistake to refer to it as a promotion of an atom to a sequence.
<built-in> function append(object target, object x)
Adds object x as the last item in target.
Returns:
A sequence whose first elements are those of target and whose last element is x.
Comments:
The length of the resulting sequence will be length(target) + 1, no matter what x is.
If x is an atom this is equivalent to result = target & x. If x is a sequence it is not equivalent. If target is an atom then it becomes the first element of the new sequence.
Then add in some of the new examples, but probably no more than 3 to 4. It might be useful to unify the examples given between this post, the & operator, and prepend.
116. Re: Discuss changing the behaviour of append()
- Posted by DerekParnell (admin) Jun 24, 2014
- 3128 views
Consider append and prepend to be special cases of the insert function.
Interesting point of view ... and probably a useful one too in some circumstances. I've mainly regarded append/prepend as special cases of concatenate.
The proposed changes to O[ are going to put emphasis on object behavior and blur some previous atom-sequence distinctions. While a != {a} remains true, the new behavior tolerates the idea that a becomes {a} when it is convenient in a prepend, insert, or append.
Well ... except that "a becomes {a}" never actually happens. An atom does not become a sequence during those operations. Its more that these operations will work on objects rather than just atoms or sequences.
TARGET is an atom, like 1, is promoted to { 1 ,$} using prepend, insert, append
I'm not sure the term TARGET is correct, maybe RESULT? Also, I'm not sure if anything is promoted either.
Also, the $ symbol, in this context, is used as a LIST construction device and has nothing whatsoever to do with sequences.
The length function is now oddly named. It could have been named item_count (items, count, size, topsize, ... ?)
- on its own {} has a zero item count, but inside a sequence it is itself one item
- length( { } ) or length( "" ) is zero, this does not mean a null sequence, but a sequence with no item count
- length( a ) is one, this does not mean a number has "length", but that one atom is one item
- length( {a} ) = length( a ) means there is one item count in each example
Yes, but I guess we are stuck with it now. Evolution, eh?!
If the results seem "strange" is it because an empty sequence can be both paradoxically "length zero and one item"? Note that quantum physics copes with ideas like this.
There is no paradox here. An empty cup is still one thing and contains nothing. A sequence is just a container. It can be empty (length = 0) while still having an existence (is an object).
Another consideration is that syntax is not mathematics. Sometimes syntax is based on mathematics (consider lisp, haskel), sometimes syntax just looks like mathematics (consider the assignment operator = which is better represented by :=), and sometimes syntax just happens when a language is designed.
I like this explanation.