Quantcast

Maximum PC

It is currently Sat Dec 20, 2014 6:17 pm

All times are UTC - 8 hours




Post new topic Reply to topic  [ 19 posts ] 
Author Message
 Post subject: Postfix / Prefix operator question (Java or C#)
PostPosted: Sat May 05, 2012 4:41 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
While doing a quick C# review / cram, I've come across some interesting code examples that have surprised me. However, I would have bet BIG money that I would have gotten the following output right. See if you can guess the output _before_ running this code... and if anyone can provide a lucid explanation of what is happening under the covers, I'd appreciate hearing it. (Maybe this is one of the reasons why I like functional programming so much!)

Code:
    public static void main(String[] args) {
       
        int a = 10, b, c;
        b = a++;
        c = ++a;
        System.out.printf("a = %d   b = %d   c = %d\n", a, b, c);
        b = b++;
        c = ++c;
        System.out.printf("a = %d   b = %d   c = %d\n", a, b, c);       
        System.exit(0);       
    }


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Sat May 05, 2012 11:32 pm 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
I was able to determine the output correct without running (verified it with equivalent C++ code). The difference between prefix (++a) and postfix (a++) is that postfix operators increment the value after the line has ran, while prefix operators increment their values before the line is ran.

Spoiler: show
Code:
    public static void main(String[] args) {
       
        int a = 10, b, c;
        b = a++;  // b=10 a=11 because b is assigned a's value (10) before a is incremented to 11
        c = ++a;  // c=12 a=12 because a is incremented to 11 and then c is assigned a's value (12)
        System.out.printf("a = %d   b = %d   c = %d\n", a, b, c);  // a = 12   b = 10   c = 12
        b = b++;  // b=10 because b's old value (10) is fetched, then b is incremented to 11, then b is assigned the value of 10 -- this one tripped me up a bit
        c = ++c;  // c=13 because c is incremented to 11 and then is assigned to c
        System.out.printf("a = %d   b = %d   c = %d\n", a, b, c);  // a = 12   b = 10   c = 13
        System.exit(0);       
    }


Based on the above, the assembly for prefix and postfix operations probably look something like this:
Code:
a = ++b
   b_memory -> b_reg
   b_reg + 1
   b_reg -> b_memory
   b_reg -> a_reg
   a_reg -> a_memory

a = b++
   b_memory -> b_reg
   b_reg -> x_reg
   b_reg + 1
   b_reg -> b_memory
   x_reg -> a_reg
   a_reg -> a_memory


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Mon May 07, 2012 1:42 am 
8086
8086

Joined: Mon May 07, 2012 1:38 am
Posts: 1
I have a doubt ..What is the output for the following statement?????

x=k++ + ++k;


Last edited by smartcat99s on Tue May 08, 2012 6:40 pm, edited 1 time in total.
linkspam


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Mon May 07, 2012 9:20 am 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5533
opusart wrote:
I have a doubt ..What is the output for the following statement?????

x=k++ + ++k;[/url]

According to Wikipedia (because I was rusty on the rules), what you posted can be considered an "undefined" operation, as quoted:
Quote:
Since the increment/decrement operator modifies its operand, use of such an operand more than once within the same expression can produce undefined results. For example, in expressions such as x − ++x, it is not clear in what sequence the subtraction and increment operators should be performed. Situations like this are made even worse when optimizations are applied by the compiler, which could result in the order of execution of the operations to be different than what the programmer intended.

You can read about it at https://en.wikipedia.org/wiki/Increment ... _operators

However, from what I do know about postfix/prefix unary operators, postfix is the very last thing to do, prefix is the very first thing to do. So:

Code:
int k = 1;
int x = 0;
x = k++ + ++k; //k = 3, x = 4 from (2+2) as ++k makes k = 2, x = (2 + 2), then k++ makes k = 3


Remember, computers are literal genies. If you don't know what the above will do right away, then don't do it. It may be more lines of code, it may add another assembly line, but if you want something to be done clearly as you intend, break it down into atomic steps. So if I wanted to increment k, then make x = k + k, then increment k again:

Code:
int k = 1;
int x = 0;
k++;
x = k + k;
k++;


It's very clear what I'm doing.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Mon May 07, 2012 5:41 pm 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
LatiosXT wrote:
opusart wrote:
I have a doubt ..What is the output for the following statement?????

x=k++ + ++k;[/url]

According to Wikipedia (because I was rusty on the rules), what you posted can be considered an "undefined" operation, as quoted:
Quote:
Since the increment/decrement operator modifies its operand, use of such an operand more than once within the same expression can produce undefined results. For example, in expressions such as x − ++x, it is not clear in what sequence the subtraction and increment operators should be performed. Situations like this are made even worse when optimizations are applied by the compiler, which could result in the order of execution of the operations to be different than what the programmer intended.

You can read about it at https://en.wikipedia.org/wiki/Increment ... _operators

However, from what I do know about postfix/prefix unary operators, postfix is the very last thing to do, prefix is the very first thing to do. So:

Code:
int k = 1;
int x = 0;
x = k++ + ++k; //k = 3, x = 4 from (2+2) as ++k makes k = 2, x = (2 + 2), then k++ makes k = 3


According to this Wikipedia article, the prefix and postfix operators are defined in the order of operations for c/c++. So, x = k++ + ++k is defined.

An interesting example:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

I agree with you LatiosXT, in practice code should not be this complicated to read.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Mon May 07, 2012 7:42 pm 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5533
mag wrote:
According to this Wikipedia article, the prefix and postfix operators are defined in the order of operations for c/c++. So, x = k++ + ++k is defined.

Except this is C#/Java, so it may be different. But it may not, since they both derive from C anyway. Either way.

Quote:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

You increment c first, this makes c = 14. So it's 19 + 14 = 33.

Considering this, you should NEVER use an increment/decrement operator in a mathematical operation. It's more so you don't have to write c +=/-= 1.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Mon May 07, 2012 9:10 pm 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
LatiosXT wrote:
mag wrote:
According to this Wikipedia article, the prefix and postfix operators are defined in the order of operations for c/c++. So, x = k++ + ++k is defined.

Except this is C#/Java, so it may be different. But it may not, since they both derive from C anyway. Either way.

http://msdn.microsoft.com/en-us/library/aa691323%28v=vs.71%29.aspx

LatiosXT wrote:
Quote:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

You increment c first, this makes c = 14. So it's 19 + 14 = 33.

Considering this, you should NEVER use an increment/decrement operator in a mathematical operation. It's more so you don't have to write c +=/-= 1.

For some reason I was thinking (c+5) would make c=18, then ++c would make c=19, so 18+19=37. Brain fart.
But wouldn't the parenthesis precede the prefix operator, so it'd be 18+14=32? Replacing "(c+5)" with an "addFive(int)" function does return 32.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 08, 2012 7:12 am 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5533
Aha, see, this is the undefined part then.

If we went by that table Wikepedia posted, then it would make sense that the order of operations is strictly the order that appears in the list. So the increment/decrement operators really have precedence over parenthesis.

If we went with order of operations like in math (such as PEMDAS), then we would have to evaluate (c+5) first, because we encountered that first and it's on the same precedence level as increment/decrement. But your compiler didn't do that.

EDIT: Actually I saw that Wiki listed suffix increment/decrement in the same precedence level as parenthesis, and prefix is after. So yes, (c+5) should've gone first. But still it didn't.

Either way, this seems to prove that an arithmetic operator next to an increment/decrement operator is undefined.

EDIT 2: If the operation were "(c+5) + c++", you get 32. And the parenthesis in the list is a function call... so I'm confused again :D


Last edited by LatiosXT on Tue May 08, 2012 7:26 am, edited 2 times in total.

Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 08, 2012 7:22 am 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
LatiosXT wrote:
EDIT: Actually I saw that Wiki listed suffix increment/decrement in the same precedence level as parenthesis, and prefix is after. So yes, (c+5) should've gone first. But still it didn't.

Either way, this seems to prove that an arithmetic operator next to an increment/decrement operator is undefined.

The parenthesis in that list actually refer to a function call. Parenthesis by themself actually don't appear in that list.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 08, 2012 7:26 am 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5533
So according to Microsoft, my original knowledge of prefix/postfix operators was correct.
Quote:
In the prefix form, the increment or decrement takes place before the value is used in expression evaluation, so the value of the expression is different from the value of the operand. In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand.


Buuuuut, again. Don't use increment/decrement operators in a math expression. That just confuses people.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 22, 2012 7:44 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
Sorry about letting my thread dangle. I had to attend an out of state lawsuit and finish some data analysis for a university. Anyways, I have an answer for the third case that makes sense.

mag wrote:
I was able to determine the output correct without running (verified it with equivalent C++ code). The difference between prefix (++a) and postfix (a++) is that postfix operators increment the value after the line has ran, while prefix operators increment their values before the line is ran.

I don't believe that thinking in terms of "after the line is ran" is helpful since the line of code may contain other operations and/or multiple lines of code.

I think we all agree that the third case that is the only tricky case. In order to get at the root of the problem, I used the Java disassembler, javap, to disassemble the class file. Note that I moved each 'case' into a seperate method to make tracking the bytecode easier. My comments are inlined using ///.

Code:
void case1();
  Code:
   0:   aload_0             ///Loads b onto the stack                 
   1:   aload_0             ///Loads a onto the stack
   2:   dup                 ///Duplicates the top of the stack
                            ///At this point, the stacks looks like this...
                            ///Stack: b a a
                            ///Note, a & b are references, not values

   3:   getfield        #2; //Field a:I  ///Puts the value of a on the stack
   6:   dup_x1              ///Copies the top value below it on the stack
   7:   iconst_1            ///Loads the value 1 onto the stack
                            ///Stack: b a a 10 10 1

   8:   iadd                ///Adds the values, puts the result on the stack
                            ///Stack: b a a 10 11

   9:   putfield        #2; //Field a:I  ///Puts 11 into a's mem ref
   12:  putfield        #3; //Field b:I  ///Puts 10 into b's mem ref
   15:  return

void case3();
  Code:
   0:   aload_0             ///
   1:   aload_0             ///
   2:   dup                 ///
   3:   getfield        #3; //Field b:I
   6:   dup_x1              ///
   7:   iconst_1            ///
   8:   iadd                ///
   9:   putfield        #3; //Field b:I  ///Puts 11 into b's mem ref
   12:  putfield        #3; //Field b:I  ///Puts 10 into b's mem ref
   15:  return


As you can see from the bytecode, case1 and case3 are exactly the same except for line(?) #9. For the first case, the value 11 is placed into the memory reference by a, then the value 10 for b. In the third case, the value 11 is placed into b's memory reference THEN the value 10 is placed into b's memory reference! Pretty surprising... =)


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 22, 2012 8:15 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
mag wrote:
An interesting example:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

How are you arriving at 37? I got 33 when I did this by hand and 32 when I ran it in Java.

Code:
c = (c+5) + ++c;
The prefix operation occurs first... c = 14
(c+5) occurs next...  19
19 + 14 occurs next... 33
33 is assigned to c


This is how Java came up with a value of 32... another interesting result.
Code:
public static void main(java.lang.String[]);
  Code:
   0:   bipush  13       //stack: 13
   2:   istore_1         //stack: empty and var1 = 13
   3:   iload_1          //stack: 13
   4:   iconst_5         //stack: 13 5
   5:   iadd             //stack: 18
   6:   iinc    1, 1     //increment var1 by 1, so var1 = 14
   9:   iload_1          //stack: 18 14
   10:  iadd             //stack: 32
   11:  istore_1         //stack: empty and var1 = 32
   12:  return
}

This ambiguity really makes me appreciate working in functional programming languages! =)

Below is Common Lisp code for how C and Java arrive at their various solutions. The world would be a much better place if C hadn't flourished under cheap Unix machines.
Code:
CL-USER> (setf c 13)  ;Java does the intermediate addition then increments c then performs the final addition
13
CL-USER> (setf c (+ (+ c 5) (incf c)))
32
CL-USER> (setf c 13)   ;C performs the prefix operation then the intermediate addition then the final addition
13
CL-USER> (setf c (+ (incf c) (+ c 5)))
33
CL-USER>

[/code]


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 22, 2012 8:17 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
LatiosXT wrote:
So according to Microsoft, my original knowledge of prefix/postfix operators was correct.
Quote:
In the prefix form, the increment or decrement takes place before the value is used in expression evaluation, so the value of the expression is different from the value of the operand. In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand.


Buuuuut, again. Don't use increment/decrement operators in a math expression. That just confuses people.

Unless you're using a functional programming language, then it only makes PERFECT sense! =)


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Tue May 22, 2012 8:58 pm 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
Gadget wrote:
mag wrote:
An interesting example:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

How are you arriving at 37? I got 33 when I did this by hand and 32 when I ran it in Java.

mag wrote:
LatiosXT wrote:
Quote:
Code:
c = 13;
c = (c+5) + ++c;

When I run it, I get c = 33, but from what I know, I think c should be 37, and I don't see how it could be 33.

You increment c first, this makes c = 14. So it's 19 + 14 = 33.

Considering this, you should NEVER use an increment/decrement operator in a mathematical operation. It's more so you don't have to write c +=/-= 1.

For some reason I was thinking (c+5) would make c=18, then ++c would make c=19, so 18+19=37. Brain fart.
But wouldn't the parenthesis precede the prefix operator, so it'd be 18+14=32? Replacing "(c+5)" with an "addFive(int)" function does return 32.
:wink:

Gadget wrote:
Code:
c = (c+5) + ++c;
The prefix operation occurs first... c = 14
(c+5) occurs next...  19
19 + 14 occurs next... 33
33 is assigned to c


This is how Java came up with a value of 32... another interesting result.
Code:
public static void main(java.lang.String[]);
  Code:
   0:   bipush  13       //stack: 13
   2:   istore_1         //stack: empty and var1 = 13
   3:   iload_1          //stack: 13
   4:   iconst_5         //stack: 13 5
   5:   iadd             //stack: 18
   6:   iinc    1, 1     //increment var1 by 1, so var1 = 14
   9:   iload_1          //stack: 18 14
   10:  iadd             //stack: 32
   11:  istore_1         //stack: empty and var1 = 32
   12:  return
}

The ambiguity here really boils down to whether or not parenthesis are higher on the order of operations than prefix operations. It appears that in Java they are, but in C they are not.

Gadget wrote:
This ambiguity really makes me appreciate working in functional programming languages! =)

Below is Common Lisp code for how C and Java arrive at their various solutions. The world would be a much better place if C hadn't flourished under cheap Unix machines.
Code:
CL-USER> (setf c 13)  ;Java does the intermediate addition then increments c then performs the final addition
13
CL-USER> (setf c (+ (+ c 5) (incf c)))
32
CL-USER> (setf c 13)   ;C performs the prefix operation then the intermediate addition then the final addition
13
CL-USER> (setf c (+ (incf c) (+ c 5)))
33
CL-USER>

[/code]

Is this ambiguity due to a fundamental difference between functional and procedural/OO programming languages, or is it just the effect of a shortcut in Java and C/C++ causing extra complexity that may lead to unexpected results?


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Wed May 23, 2012 10:30 am 
Smithfield
Smithfield

Joined: Sun Jun 18, 2006 7:37 pm
Posts: 5533
As fun as it is to learn such things, again I'm going to iterate that you shouldn't be using increment/decrement operators in an arithmetic operation. I mean, I would freak out if I saw c = ( c + 5 ) + (c = c + 1) in a normal math setting. How are you supposed to solve this?


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Wed May 23, 2012 2:22 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
mag wrote:
Is this ambiguity due to a fundamental difference between functional and procedural/OO programming languages, or is it just the effect of a shortcut in Java and C/C++ causing extra complexity that may lead to unexpected results?

Personally, I believe this illustrates one of the difference between funcational and imperative programming languages. Imperative languages require you to learn substantially more syntatic information, such as operator precedence, than is required in functional programming languages. Also, I wouldn't call either the prefix or postfix operators shortcuts. They're fundamentally the same as any of the other operators, right?

Take CL as an example, the language syntax is incredibly simple. The first term following an open paren is a function call. Any terms proceeding the next closing are arguments to the function. Function calls are evaluated in order from left to right. If a function call has an argument that is itself a function call, the inner function call is evaluated and used as an argument for the outer function call. There is some systatic sugar to make certain common tasks a bit easier, but the only language syntax that you must learn is (fn arg1 arg2 ...). That's it.

To be fair, you also need to know a bit more syntax in order to define a function, which is done using a macro that changes the syntax (but at this point we're comparing large portions of languages).
(defun fn-name (fn-arg1 fn-arg2 ...) (... function body ))

Now an astute student of computer science will notice that the examples from the proceeding post are not technically "pure" functional programming because I'm manipulating the state of a variable. This is true -- I set the variable c to a value and used the incf function to increment it. One of the design goals of Common Lisp was to be a practical programming language for industry developers, not just an interesting academic language like Scheme. Because of this broad goal, CL actually supports several programming styles including imperative, functional, applicative, object-oriented and meta-programming / macros. CL programs are often written in a bottom-up style. First, small functions and macros are written in an imperative style of programming using only local variables. These functions are then used to build up the program. At this higher-level, functional programming and/or object-oriented programming are often employed.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Wed May 23, 2012 3:29 pm 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
LatiosXT wrote:
As fun as it is to learn such things, again I'm going to iterate that you shouldn't be using increment/decrement operators in an arithmetic operation.

Agreed. We should start a thread on composing mathematical functions! =)

LatiosXT wrote:
I mean, I would freak out if I saw c = ( c + 5 ) + (c = c + 1) in a normal math setting. How are you supposed to solve this?

If someone had done this one of my teams, they would be flogged!

I actually got the answer right. Starting with c = 1 the answer is 8 (in Java). While I got the right answer, what I didn't think about are the two assignments that occurs due to the (c = c + 1) term. Fool me twice! The disassembled code looks pretty darn inefficient. Maybe I should look into doing some research on compiler algorithms.

Code:
public static void main(java.lang.String[]);
  Code:
   0:   iconst_1     //stack: 1
   1:   istore_1     //stack: empty and var1 = 1
   2:   iload_1      //stack: 1
   3:   iconst_5     //stack: 1 5
   4:   iadd         //stack: 6
   5:   iload_1      //stack: 6 1
   6:   iconst_1     //stack: 6 1 1
   7:   iadd         //stack: 6 2
   8:   dup          //stack: 6 2 2
   9:   istore_1     //stack: 6 2 and var1 = 2  ... THIS IS THE ASSIGNMENT THAT I MISSED
   10:  iadd         //stack: 8
   11:  istore_1     //stack: var1 = 8
   12:  return
}


The double assignment is a bit more obvious in CL... again, I think it is because of the simpler syntax and explicit use of parens.
Code:
CL-USER> (let ((c 1))
      (setf c (+ (+ c 5) (setf c (+ c 1)))))
8


Out of curiousity, I decided to take a look at the disassembled Lisp code. It is more efficient than the Java code requiring only 9 instructions (vs 13 for Java). I can't really explain why this is the case, especially given the number of man-hours that have gone into Java compiler development, but I will hypothesis that it may be due to the simpler parsing syntax of CL vs Java (ie a recursive descent parser vs a LR parser). I should also emphasize that just because the CL code requires fewer isntructions (and can be compiled directly to ML), it doesn't necessarilly mean that the CL code is faster than the Java code. The JVM might be performing further optimizations that eliminate some of the instructions.
Code:
Disassembly of function FOO
(CONST 0) = 1
(CONST 1) = 5
9 byte-code instructions:
0     (CONST&PUSH 0)                      ; 1
1     (CONST&PUSH 1)                      ; 5
2     (LOAD&PUSH 1)
3     (CALLSR&PUSH 2 53)                  ; +
6     (LOAD&INC&STORE 1)
8     (PUSH)
9     (CALLSR 2 53)                       ; +
12    (VALUES1)
13    (SKIP&RET 2)


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Wed May 23, 2012 10:44 pm 
Team Member Top 50
Team Member Top 50

Joined: Sat Jun 25, 2005 11:04 am
Posts: 1026
Gadget wrote:
mag wrote:
Is this ambiguity due to a fundamental difference between functional and procedural/OO programming languages, or is it just the effect of a shortcut in Java and C/C++ causing extra complexity that may lead to unexpected results?

Personally, I believe this illustrates one of the difference between funcational and imperative programming languages. Imperative languages require you to learn substantially more syntatic information, such as operator precedence, than is required in functional programming languages. Also, I wouldn't call either the prefix or postfix operators shortcuts. They're fundamentally the same as any of the other operators, right?

It seems like it's a difference in cultures, because I don't think there's anything fundamental to imperative languages that makes them have to have substantially more syntax. At the very basic level, there are assignments, mathematical operations, and functions.

I'd agree, I'd say the prefix and postfix operators are syntactic sugar.


Top
  Profile  
 
 Post subject: Re: Postfix / Prefix operator question (Java or C#)
PostPosted: Sat May 26, 2012 12:41 am 
Bitchin' Fast 3D Z8000*
Bitchin' Fast 3D Z8000*
User avatar

Joined: Tue Jun 29, 2004 11:32 pm
Posts: 2555
Location: Somewhere between compilation and linking
mag wrote:
I don't think there's anything fundamental to imperative languages that makes them have to have substantially more syntax.

Perhaps not substantially more syntax, it is pretty hard to quantify this type of thing. As we discussed before, in an imperative programming language (IPL), you need to know the operators, which is a wash because you need to know the functions in a functional programming language (FPL), but the IPL also requires you to be familiar with the operator precedence rules. The real difference is that the grammar in an IPL is almost always larger. For example, why doesn't the following code compile?
Code:
int bar = if (foo) { 1 } else { 2 };  //You have to be familiar with the ternary operator... int bar = (foo) ? 1 : 2;
CL-USER> (setf bar (if foo 1 2))  #Just use the basic syntax... you don't need to know another operator
1
CL-USER> bar  #foo had been set to true...
1

This doesn't compile in Java, C/C++ or any other IPL (AFAIK), but using the if function in an assignment function is perfectly natural in a FPL. I can only use an if condition if it "starts a line", or more explicitly, whenever the grammar says it is OK to use an if condition. I also have to watch out for dangling if clauses and things of that nature (which aren't an issue with an FPL due to the order of function calls being explicitly defined by the user). This may seem like a fairly trivial example, but there have been plenty of occasions when I've been writing code in Java and thought "Lisp sure would have made that easier".

In most IPLs, elements of an array, list and string are accessed using different syntax. In Java, I access the first element of an array with foo[0], but the first element of a list is accessed using foo.get(0), and the first element of a string using charAt(), which returns a char instead of a string with a single element (This requires a substring() call). To find the length of an array, I access the public length member (ie foo.length). The length of a string requires a method call to length() while the list a call to size(). Accessing part of a list, array and string also require different methods (esp for an array). And frankly, Java is much easier to remember than C or C++ (especially when dealing with strings). In CL, these data types are all accessed using the same function calls w/o any variation in syntax.
Code:
CL-USER> (setf foo (list 0 1 2 3 4)
          bar (make-array (length foo) :initial-contents foo)
          baz "01234")
"01234"
CL-USER> (elt foo 0)
0
CL-USER> (elt bar 0)
0
CL-USER> (elt baz 0)
#\0
CL-USER> (length foo)
5
CL-USER> (length bar)
5
CL-USER> (length baz)
#\3
CL-USER> (subseq baz 0 3)
"012"
CL-USER> (subseq bar 0 3)
#(0 1 2)
CL-USER> (subseq foo 0 3)
(0 1 2)

Many IPLs utilize pointers which add another layer of syntax for how to allocate and free memory. Again, there is syntatic sugar for pointer assignments in C/C++. More syntax to memorize.

Typically, IPLs have a number of reserved and/or keywords. I believe Java has 34 keywords and a few reserved words. There are also usually a number of grammar rules concerning naming local variables, global variables and functions. Often this is due to how operators and variables or functions interact. In most IPLs, I can't name a variable a+b even though that may be a perfect description for the variable!
Code:
CL-USER> (setf 1a 1
          b-2 2
          1a+b-2 (+ 1a b-2))
3
CL-USER> (format t "~d ~d ~d~%" 1a b-2 1a+b-2)
1 2 3


In C and C++, there is some interesting syntax related to global variables and variable scoping. The following code will probably test your memory pretty well. C++ also has the oh-so-fun macro system.
Code:
#include<iostream>  //right?  Or is it supposed to be...
#include"iostream"             //???
int x;
void f() {
  int x = 1;
  x = 2;           //which x was just updated?
  ::x = 3;        //and now?
  {
     int x = 4;
     x++;
     ::x++;
  }
}


Another interesting area to contrast is function declarations. This probably the one place where the FPLs have more syntax than the IPLs, because they generally support more language features related to functions (eg parameter declaration, multiple return values, higher order functions, returning functions, etc), but the IPLs still manage to make things more difficult IMO. Take these C++ examples using default parameter values and multiple arguments.
Code:
int f(int x, int y=2, int z = 3);  //This is ok
int g(int x=1, int y=2, int z);  //This is an error

int h(int ...);  //We don't know how many integers will be passed.

For some reason, all parameters without default values must come before parameters with default values. Why? Who knows... just put it in the memory banks. Nope, you don't have to worry about that type of thing in CL. Occasionally you have to write a function that may take any number of arguments (eg the mean() and sum() functions in R). Fine, I just use an ellipsis, right? Well, you need to be able to access those args in the function. How? The <cstdarg> macro to the rescue. That macro is more fun than a migraine... let me tell you.

Several IPLs support operator overloading, which can be convenient, but you must learn additional syntax/grammar rules. Do you know which of the 42 operators can be overloaded in C++. Do you know the three operators that cannot be overloaded? Did you know there were 45 operators?!

In the case of C and C++, you also have header files and the macro system to contend with as well.

mag wrote:
I'd agree, I'd say the prefix and postfix operators are syntactic sugar.

Sure, they are syntactic sugar. However, languages include syntactic sugar because it is something that is done frequently. If anything, you should probably especially familiar with the syntactic sugar in a language because you're going to see it being used all the time. If you actually wrote "int n = n + 1;", you're boss is going to think something is wrong with you! =)


Top
  Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ] 

All times are UTC - 8 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group

© 2014 Future US, Inc. All rights reserved.