2019年1月10日

程式語言─課堂作業

Prolog

  • Prolog(Programming in Logic的縮寫)是一種邏輯編程語言
  • 由法國馬賽大學所設計出來的程式語言。
  • 以符號邏輯為基礎,且具有推理性的程式語言,在人工智慧的領域有很大貢獻。

Prolog練習與整理

  1. 規則與事實(rules and facts)
  2. 邏輯基底程式導向語言(邏輯導向程式語言) (logic-based programming language)
  3. 常數
    1. 整數
    2. 字元
    3. 小寫字母為開頭
  4. 變數
  5. 結構
    • 格式:函數名稱(值1,值2,值3)
    • 值也可以是一個結構
    • 利用結構表示事實
      • 學生fei就讀逢甲大學(fcu)
      • student(fei,school(fcu))
      • 每一個值都可以是結構
      • student(person(fei,girl),school(fcu,taichung))
      • 從上面的式子可以知道student、person、school都是結構
  6. 練習一

    • mother(ruby, tim).           %ruby是tim的媽媽
      father(andy, ruby).         %andy是ruby的爸爸
      parent(X, Y) :- father(X, Y).   %parent(X,Y)條件須滿足father(X,Y)
      parent(X, Y) :- mother(X, Y).     %parent(X,Y)條件須滿足mother(X,Y)

      %grandparent函式輸入X,Z需同時滿足parent(X,Y)和parent(Y,Z) grandparent(X,Z) :- parent(X,Y), parent(Y,Z). ------------------------------------- ?-grandparent(andy,tim) True

  7. 練習二

    • % 速度(車種,數值)
      speed(toyota, 100).
      speed(honda, 105). speed(benz, 120). speed(mazda,110).

      % 花費時間(車種,數值) time(toyota, 21). time(honda, 22). time(benz, 23). time(mazda, 24).

      % 計算距離函式 % 找出X的速度以及花費時間 % 輸出Y為距離 distance(X, Y) :-speed(X, Speed), time(X, Time),Y is Speed * Time. ------------------------------------- ?- distance(toyota, Distance). Distance = 2100

      ?-trace, (distance(toyota, Distance)). Call:distance(toyota, 12130) Call:speed(toyota, 12326) Exit:speed(toyota, 100) Call:time(toyota, 12326) Exit:time(toyota, 21) Call:12130 is 10021 Exit:2100 is 10021 Exit:distance(toyota, 2100) Distance = 2100

  8. 函式庫:list,List Manipulation(列表操作)

    • member(?Elem, ?List)

      • 判斷元素是否在列表內
      • ?- member(a,[a,b,c]). 
        true
        ?- member(list(a,b,c),[t,e,v,list(a,b,c),d]). true

    • length(?List, ?Int)

      • 回傳列表長度
      • 第2個參數
        • 如果是變數,將變數綁定為列表參數
        • 如果是數字,就將該數字與長度比較,相等則True,否則False。
      • ?- length([a,b,c,d],X). 
            X = 4
        ?- length([a,b,c],3). true
        ?- length([a,b,c],4). false
    • reverse(?List1, ?List2)

      • 如果兩個變數都是list,就判斷是否互相倒序
      • 如果一個是變數,一個是list,就將變數綁定為list的倒序
      • ?- reverse([1,2,3,4],L). 
            L = [4,3,2,1] 
        ?- reverse(L,[1,2,3,4]). L = [4, 3,2,1]
        ?- reverse([1,2,3,4],[4,3,2,1]). true

    • append(?List1, ?List2, ?List1AndList2)

      • 如果前兩個是list,第三個為變數,那麼將變數綁定為兩個list合併連接的列表
      • 如果前兩個參數包括變量,第三個是列表,那麼將回溯尋找所有可能的列表組合
        ?- append([1,2,3,4],[5,6,7,8,9],L).
        L = [1, 2, 3, 4, 5, 6, 7, 8, 9]
        % 列出L1,L2所有排列組合
        ?- append(L1,L2,[1,2,3,4,5]).
        L1 = [],
        L2 = [1, 2, 3, 4, 5]
        L1 = [1],
        L2 = [2, 3, 4, 5]
        L1 = [1, 2],
        L2 = [3, 4, 5]
        L1 = [1, 2, 3],
        L2 = [4, 5]
        L1 = [1, 2, 3, 4],
        L2 = [5]
        L1 = [1, 2, 3, 4, 5],
        L2 = []

Prolog Deficiencies心得報告

  1. Prolog對新手來說相當困難,跟C語言等語言的思考模式較不相同。
  2. Prolog比較抽象,編譯器很難加以優化。
  3. Prolog並不直觀,執行效率差。
  4. Prolog是處理符號和非數值運算之程式語言,因此對於數值運算無法解決"

Prolog 期中考題目

% 判斷參數是否為列表內的第一個元素
% 如果不是第一個元素,查看列表其他元素
% 取出第一個元素後,剩下的元素成新的列表
% 依序查看參數是否為列表內的第一個元素
member(E, [E|_]) :- !.
member(E, [_|List]) :- member(E, List).

---------------------
?- member(a, [b,c,a,d]).
true

?- trace, (member(a, [b,c,a,d])).
Call:member(a, [b, c, a, d])    % 因a不等於b,因此查看下一個元素
 Call:member(a, [c, a, d])      % 因a不等於c,因此查看下一個元素
  Call:member(a, [a, d])        % 因a等於a,因此結束呼叫
  Exit:member(a, [a, d])        % 因已找到a,因此結束呼叫
 Exit:member(a, [c, a, d])      % 因已找到a,因此結束呼叫
Exit:member(a, [b, c, a, d])    % 因已找到a,因此結束呼叫
true                            % 因已找到a,故為true

Lisp

  • 舉一個例子,寫一個函數來回傳小於 n 的數字總和,用Lisp和C來比較
    ; Lisp                   / C /
    (defun sum (n)           int sum(int n){
      (let ((s 0))             int i, s = 0;
        (dotimes (i n s)       for(i = 0; i < n; i++)
          (incf s i))))          s += i;
                               return(s);
                             }
                             

Lisp 練習

輸出練習

(write-line "Hello World") ;輸出Hello World
(write (+ 7 9 11));輸出11+7+9=27

使用前綴符號

  • 比如說:a * ( b + c ) / d
  • 在Lisp語言內要寫:(/ (* a (+ b c) ) d)
(write(+ (* (/ 9 5) 60) 32));輸出(60*9/5)+32=140

Lisp期中考

(DEFINE (compose f g)            % 接受 f 和 g 函數.
(LAMBDA (x) (f (g x)))) ,       % 將 f ( g x) 設為一個匿名函數.
((compose CAR CDR) '(a b c)) ,      % 將資料 (a b c) 透過 (compose f g) 轉為 (LAMBDA (c) (a (b c))) .
((DEFINE (adder alist)          % 定義 (adder alist) 為以下的判斷式.
(COND ((NULL?alist) 0)          % alist 若為為空則回傳 0 .
(ELSE (EVAL (CONS  '+ alist))))) ,  % 否則將 alist 的所有內容加總.
                    % (使用cons把 ""+""""alist"" 合併為 ""+ alist"" ,再使用 eval 將 ""+ alist"" 從資料型態轉成函數.)
(adder  '(3 4 5 6 2)) ?         % 判斷 alist 是否為零,若非為零則將 alist 加總,再回傳計算過後的結果.

Erlang

Erlang is a general-purpose concurrent programming language and runtime system. The sequential subset of Erlang is a functional language, with strict evaluation, single assignment, and dynamic typing. ~維基百科

  1. Erlang有許多近似Pure Functional Language的特性
  2. 優點
    • 建構並行(Concurrent)
    • 分散(Distributed)
    • 容錯 (Fault-tolerance)的系統
  3. 缺點
    • 內建函式庫的貧乏
    • 對Unicode支援度低
    • 缺乏良好的IDE及Debug Tool

Java (Exception and Event Handling)

  • 例外(Exception):任何不正常的事件,不論是否有錯誤,都可以通過硬體或軟體檢測到,並且可能需要特殊處理。
  • 異常處理程序(Exception handler):處理異常的程式碼單元。
  • 引發異常(Raising an exception):發生與異常相關的事件時。
  • 禁用異常(Disabling an exception):忽略某些硬體可檢測的異常。
  • 繼續(Continuation):控製程序程式碼或程序之外的程序中的某處可能會終止。
  • 完成(Finalization):無論子程序如何停止,都可以完成一些運行。
  • 內置異常(Built-in exception):不是由使用者做出的異常,而是默認的。

Java提供了豐富的異常處理機制,與C語言相同,Java的異常處理也是包含在try, catch, finally三個塊中的,常見的異常處理方式如下:

try{
    // code 可能會產生異常
} catch(IOException e){
    // IOException輸入輸出異常,當產生異常被偵測之後,catch內的code會被執行
} finally {
    // 無論是否有異常,這裡的code都會執行
}

Throwable繼承架構圖(圖轉載至openhome)
Java的異常處理程序與C ++的異常處理程序具有相同的形式,只是每個catch必須有一個參數,這個參數均應是java.lang.Throwable的子類別。其中,主要分為兩大子類別:

  1. java.lang.Error: 其子類別表示了Java虛擬機的異常
  2. java.lang.Exception: 其子類別表示了程序運行中的異常

Exception的子類還可以分為兩類:

  1. java.lang.RuntimeException: 其子類表示了運行中的異常,該異常可以不被catch,編譯器也能通過。該子類表示的異常,均應該在原始碼中避免,比如數組範圍的超出等等。
  2. 非RuntimeException: 其子類表示了程序中不可避免的異常,如文件不存在的FileNotFoundException異常,該異常必須被catch掉或者是在函數頭處聲明。

finally子句放在完整的try結構之後的處理程序列表的末尾。這個結構的語義如下:

  1. 如果try子句不引發異常,finally子句在try結構之後繼續執行之前被執行。
  2. 如果try子句拋出一個異常,並被後面的處理程序捕獲,finally子句在處理程序完成執行後執行。
  3. 如果try子句拋出一個異常,但是它並沒有被try結構之後的處理程序捕獲,finally子句在異常傳播之前被執行。

如果在程式當中需要拋出異常,應使用throw關鍵字:

if(!file.exists()) {
    throw new FileNotFoundException(""檔案不存在"");
}

如果是方法(method)裡拋出異常,應使用關鍵字throws

public void get() throws Exception{
}

Java (Concurrency)

平行(Parallelism)與併行(Concurrency)的差別如下:

  • 多個任務分配到一個CPU核心,在取得的CPU時間片段中交互執行,稱之為併行(Concurrency)。
  • 一個任務可被分成多個子任務並分配到不同的CPU核心同時執行,稱之為平行(Parallelism)。

平行與併行的講解:

  1. Concurrency:多個任務(tasks)同時處理。而併行的相反則為序列化處理,也就是要等一件任務完成才能開始執行另外一件任務。
  2. Parallelism:一個任務分拆為數個子任務來同時執行。

平行和併行是分別獨立的概念,彼此並沒有依賴關係,有平行不一定有併行,反之亦然。

簡單舉例

(支援Concurrency)你吃飯吃到一半,電話來了,你停了下來接了電話,接完後繼續吃飯,這說明你支持Concurrency。
(支援Parallelism)你吃飯吃到一半,電話來了,你一邊打電話一邊吃飯,這說明你支持Parallelism。
(都不支援)你吃飯吃到一半,電話來了,你一直到吃完了以後才去接,這就說明你不支持Parallelism也不支持Concurrency。
分類:程式語言
標籤: