수정입니다

Expressions and Assignment Statements 본문

전공/프로그래밍언어론

Expressions and Assignment Statements

nongdamgom 2023. 12. 28. 12:45

Chapter 7. Expressions and Assignment Statements

Introduction

  • Expressions : PL에서 computation을 나타내는 fundamental 수단

--> syntax, semantic 의미를 이해하는 것이 중요

  • expression을 잘 이해하기 위해 operator와 operand의 연산 순서가 중요

--> associativity 와 precedence rule 에 의해 결정

  • Essence of imperative languages is dominant role of assignment statements

--> 할당을 하는것 -> 변수의 값 변경(side effect)이 야기됨

Arithmetic Expressions

  • one of the motivations for the development of the first PL
  • operators, operands, parentheses, function calls 로 구성됨
  • 대부분의 언어에서 binary operator는 infix (a + b)

--> Scheme, LISP, Perl : prefix(+ a b)

  • 대부분의 unary operators 는 prefix

--> C-based 언어에서는 prefix, postfix 둘 다 사용

Arithmetic Expressions : Design Issues

  • Operator precendence rules?
  • Operator associativity rules?
  • Order of operand evaluation?
  • Operand evaluation side effects?
  • Operator overloading? or not?
  • Type mixing in expressions?

Operators

  • unary operator : one operand -> ++1
  • binary operator : two operand -> a+b
  • ternary operator : three operand

Operator Precedence Rule

  • 다른 precedence level의 adjacent operators들의 순서가 평가 됨
  • Typical precedence level
  1. parentheses ()
  2. unary operators
  3. ** (언어에서 지원하면)
  4. *, /
  5. +, -

Operator Associativity Rule

  • 같은 precedence level의 adjacent operators들의 순서가 평가 됨
  • Typical associativity rules
  1. Left to right, except ** which is right to left (c**d**e = cde)
  2. sometimes unary operators associate right to left(in FORTRAN))
  • APL - unique case

--> 모든 operator 들이 동일한 우선순위, 결합규칙에 의해서만 결정(right to left)

Expressions in Ruby and Scheme

  • Ruby (OOP 언어)

--> 모든 arithmetic, relational, assignment operator 뿐만 아니라 indexing, shifts, bit-wise logic operator 도 전부 method로 구현된다.

--> 이 모든 method는 overriden 될 수 있다.

  • Scheme(and Common Lisp)

--> 모든 산술&논리 연산들은 subprogram으로 명시적으로 호출된다

ex) a + b * c --> (+ a (* b c)) ==> operator가 함수로, operand가 parameter로써 작용

Conditional Expressions

  • In C-based L

--> average = (count == 0) ? 0 : sum / count

-->if (count == 0) average = 0; else average = sum/count 와 같다.

Operand Evaluation Order

  1. variable : fetch the valut from memory
  2. constants : fetch from memory or machine language instruction(not require fetch)
  3. parenthesized : 포함된 operand 와 operator 먼저
  4. operand가 function call될 때 , 흥미롭다

Potentials for side effects

  • Functional side effects

--> 함수가 parameter나 global variable에 접근할 때 발생

  • problem with functional side effects
int a = 5; int func1(){ a = 17; return 3; } int main() { a = a + func1(); cout << a; return 0; } // In C++, output : 20
  • a가 먼저 평가되면 output : 8
  • func1()이 먼저 평가되면 output : 20

Functional Side Effects

  • 두가지 해결책 존재
  1. language를 side effects를 허용하지 않게 게정의

--> parameter를 read only로만 쓰고, non-local를 function내에서 사용 x

--> 장점 : it works

--> 단점 : inflexibility

2. language를 애초에 operand 의 순서를 fixed하게 정의

--> 단점 : limits some compiler optimizations

--> Java는 operand가 left-to-rignt 순서로 fixed

public class Main { static int a = 5; static int func1(){ a = 17; return 3; } public static void main(String[] args) { a = a + func1(); System.out.println(a); } } //In Java, output : 8

Referential Transparency

  • If any two expressions that have the same value can substituted for one another anywhere without affecting the action of the program
result1 = (fun(a) + b) / (fun(a) - c); temp = fun(a); result2 =(temp + b) / (temp - c);
  • result1과 result2의 값이 같다면 이를 referential transparency라고 함
  • 만약 side effect가 일어나서 같지 않게되면, referential transparency를 위반했다고 함
  • 장점

--> 의미론적으로 더 이해하기가 쉬워짐

  • 몇몇 pure functional language들은 variable을 갖지 않기 때문에 referentially transparent 함 (not all)

--> 이 function들은 지역변수를 저장하는 state를 가질 수 없음

--> 만약 function이 outside value를 사용하면, 반드시 constant여야함(not variable)

--> 즉 그 function의 값은 parameter에 종속됨.

Overloaded Operators

  • operator을 하나 이상의 목적으로 사용할 때 overloading
  • ex) + 연산자를 int에도 쓰고 float에도 씀
  • C, C++ 에서의 * 의 potential to trouble

--> Loss of compiler error detection(a * b 하려고 했는데 a빼먹어도 오류 감지x)

--> some loss of readability

  • C++, C#, F# allow user-defined overloaded operator

--> 잘 사용하면 readability 향상

--> user가 이상한 operation을 정의할 수 있음(+를 곱셈으로 쓴다든지..)

--> 잘 정의 해도 때로 읽기가 어려울 수 있음

Type Conversions

  • narrowing conversion : ex) float to int
  • widening conversion : ex) int to float

Mixed Mode

  • type이 다른 operand들을 가질 수 있음 ex) 2 + 8.5
  • coercion : imlicit type conversion ex) 2 + 8.5 ==> 2.0 + 8.5

--> 단점 : complier가 type error 를 덜 감지함

  • 대부분의 언어들은 모든 numeric type을 widening conversion을 이용해서 coreced
  • In ML, F# : no coercion (type checking의 reliability를 위해서)

Explicit Type Conversions

  • C-based L에서의 casting

--> C : (int) angle , F# : float(sum) - F# 에서는 함수호출과 비슷한 꼴

Errors in Expressions

  • Inherent limitations of arithmetic. ex) divison by zero
  • Limitations of computer arithmetic. ex) overflow
  • 위의 예시들은 run-time 에서 발생하는 error인데 가끔 그냥 무시하고 씀(exceptions)

Relational and Boolean Expression

  • Relation Expression

--> two operand, one relational operator : 비교 연산자

--> 이 relation의 결과 : boolean

--> symbol 은 언어에 따라 다양(!=, /=, ~=, .NE, <>, #)

  • JavaScript, PHP 은 추가적인 relational operator 사용 (===, !==)

--> ==, != 랑 비슷한데 ===, !==이건 coerce를 허용x

--> ex) "7" == 7 : true, "7" === 7 : false

  • Boolean Expression

--> consist of boolean variable, boolean constant, relational expression(>, <, ==), boolean operators(AND, OR, NOT)

  • C89 는 boolean type이 없다 --> 보통 0 or 1로 많이 표현
  • C 의 특이한 expression : a < b < c

--> 생각되로 평가되지 x ( a<b 먼저 수행 = 0 or 1의 결과 -> 그걸 c랑 비교하는 식으로 됨)

Short Circuit Evaluation

  • 모든 식을 다 수행하기 전에 결과가 결정되는 expression

ex) (13 * a) * (b / 13 - 1)

--> a 가 0 이면 (b / 13 - 1) 이건 계산 할 필요 x

  • non-short-circuit evaluation의 문제
index = 0; while ((index < length) && (LIST[index] != value)) index ++;

--> index == length가 되면 (LIST[index] != value) 얘를 안하고 멈춰야 되는데 short circuit이 없으면 얘를 수행해버려서 indexing 오류가 생김 (보통 index 번호는 length-1까지 있으니까)

  • C, C++, Java

--> boolean operator(&&, ||)에 short circuit 사용

--> BUT, bitwise boolean operator(&, |)에는 non - short circuit

  • Ruby, Perl, ML, F#, Python 은 모든 logic operator가 다 short-circuit 지원
  • boolean 식에 short-circuit으로 인한 side effect 생길 수 있음

--> (a > b) || (b++ / 3) : 이 식에서 b는 a <= b 일 때만 변경됨

Assignment Statements

  • general syntax

<target_var> <assignm_operator> <expression>

  • assignmnet operator

--> Fortran, BASIC, C-based L =

--> Ada :=

  • equality 관계연산자랑 혼동 될 수 있어서, 다른거 사용해야함(C 에서 ==)

Conditional Targets

  • In Perl
if ($flag){ $total = 0 } else{ $subtotal = 0 } // 아래랑 위랑 equivalent ($flag ? $total : $subtotal) = 0

Compound Assignment Operators

  • shorthand method

ex) a = a+b --> a += b

--> ALGOL에서 시작, C-based 언어에 적용됨

Unary Assignment Operators

  • 증가/감소 연산을 assignment랑 결합
sum = ++count // 증가 하고 할당 sum = count++ // 할당 하고 증가 count++ // 증가 -count++ // 증가 시키고 음수화

Assignment as an Expression

  • In C-based L , Perl, JavaScript
while ((ch = getchar()) != EOP){}

--> assignment 후 결과 값을 conditional value로 사용할 수 있음

--> 단점 : 다른 side effect 발생 (이해하기 어려운 식을 만들게 될 수 있음)

Multiple Assignment

  • In Perl, Ruby
//Perl Syntax ($first, $second, $third) = (20, 30, 40) ($first, $second) = ($second, $first)

Mixed - Mode Assignment

  • In Fortran, C, Perl, C++ (less limited case)

--> numeric 끼리는 implicitly 하게 강제변환이 자유롭게 적용

  • In Java, C#

--> only widening assignment coercion만 허용 (ex/ int var = 2.0;)

  • In Ada : no assignment coercion (most limited case)

--> explicit type casting 이용

Summary

  • Expressions
  • Operator precedence and associativity
  • Operator overloading
  • Mixed-type expressions
  • Various forms of assignment

// end of chapter 7