iT邦幫忙

2025 iThome 鐵人賽

DAY 26
0

還記得我們在新手村裡學會這幾句話嗎:

  1. 程式主要可以分成邏輯(流程)資料
  2. 函式是把**邏輯(流程)**包起來的自動販賣機

而隨著愈來愈多人寫程式,在歷史發展中,有些高手開始發現一些不太妙的事:

(下面這些話,要用電影旁白的語氣讀,配上遠遠的大風景慢鏡頭… 🌊 )

在那些古老的日子裡(半世紀前),程式是一大團不加以區分的程式碼及資料。控制的流可能自任意處開始,也可能在任何地方結束。不管在哪都可以隨便存取資料…

然而人們發現了一件難堪的事:「寫下的程式,不僅僅會被執行,也可能會被拿來修改。」而那些四處奔竄的控制流,自我修改的程式碼及被隨意存取的資料,執行起來還算美好,之後想修改時就相當駭人了。

於是人們踏上了那條漫長而曲折,尋找計算模型的道路,希望讓此處的修改,不至引起彼方非預料中的錯誤。

-- Kent Beck, Kent Beck 的實作模式

人們對於怎麼修改有各式各樣的意見,於是開始出現了幾種不一樣的程式世界觀,我們把這些不同的世界觀稱為範式 (paradigm)

比較知名的有三派:

  1. 指令式編程(Imperative Programming):
    這派認為程式應該就是對機器下命令,一步步告訴電腦要做什麼。

  2. 物件導向編程 (Object oriented Programming, OOP):
    這派認為程式應該先定義資料的樣子,再把可以這樣動的邏輯綁在這種資料上。這樣就可以像現實世界一樣來設計程式,說「車子都能前進、剎車跟加油」,所以「汽車」、「巴士」跟「坦克」都能這樣做。

  3. 函數式編程 (Functional Programming, FP)
    這派認為程式跟數學非常類似,可以像工廠的輸送帶,往一關關的機器(販賣機)運送那樣,每一步都把資料轉換成下一階段的樣子。因此可以用比較抽象的方式,來看待邏輯運作的方式。

而現代新的程式語言,常常是混合幾種不同的範式,依你的喜好來使用。

各個程式語言適合的範式

語言 物件導向 (OOP) 函數式 (FP) 指令式 (Imperative) 主要範式
Python ⭐️⭐️ ⭐️ ⭐️⭐️⭐️ 多範式,偏指令式
JavaScript ⭐️ ⭐️⭐️ ⭐️⭐️ 多範式,FP 特色愈來愈多
Elixir 0️⃣ ⭐️⭐️⭐️ ⭐️ 純函數式
Ruby ⭐️⭐️⭐️ ⭐️ ⭐️⭐️ 物件導向為主
Kotlin ⭐️⭐️⭐️ ⭐️⭐️ ⭐️⭐️ 多範式,OOP+FP
Swift ⭐️⭐️ ⭐️⭐️ ⭐️⭐️ 多範式,OOP+FP

同一件事的不同做法

我們在線上玩具商店買了一些玩具,這個玩具商店有這些規則:

  1. 一樣的東西超過兩個打 9 折
  2. 布偶類商品不管幾個都是打 9 折
  3. 最後總價超過 1000 元的話,再打 8 折

接著我們就用不同的範式及語言來示範這個購物車算錢的程式

1. 指令式: Python

def calc_total(items):
    total = 0
    for item in items:
        if item['quantity'] > 2 or item['category'] == '布偶' 
	      discount = 0.9
        else 
          discount = 1.0

        total += item['price'] * item['quantity'] * discount
    return total * 0.8 if total > 1000 else total

# 使用範例
items = [
    {'price': 100, 'quantity': 3, 'category': '玩具車'},
    {'price': 200, 'quantity': 1, 'category': '布偶'},
]
print(calc_total(items))  # 270 + 180 = 450

2. 物件導向:Ruby

class Item
  def initialize(price, quantity, category)
    @price, @quantity, @category = price, quantity, category
  end
  
  def subtotal
    @price * @quantity * (@quantity > 2 || @category == '布偶' ? 0.9 : 1.0)
  end
end

class Cart
  def initialize(items) = @items = items
  def total = (s = @items.sum(&:subtotal)) > 1000 ? s * 0.8 : s
end

# 使用範例
items = [
  Item.new(100, 3, '玩具車'),
  Item.new(200, 1, '布偶')
]
puts Cart.new(items).total  # 450.0

3. 函數式: Elixir

defmodule Cart do
  def total(items) do
    items
    |> Enum.map(&item_subtotal/1)
    |> Enum.sum()
    |> apply_bulk_discount()
  end

  defp item_subtotal(%{price: p, quantity: q, category: c}) do
    p * q * item_discount(q, c)
  end

  defp item_discount(q, c) when q > 2 or c == "布偶", do: 0.9
  defp item_discount(_, _), do: 1.0

  defp apply_bulk_discount(subtotal) when subtotal > 1000, do: subtotal * 0.8
  defp apply_bulk_discount(subtotal), do: subtotal
end

# 使用範例
items = [
  %{price: 100, quantity: 3, category: "玩具車"},
  %{price: 200, quantity: 1, category: "布偶"}
]
IO.puts Cart.total(items)  # 450.0

對於程式初學者,還是建議在 Python 跟 JavaScript 中選一個來開始,畢竟 AI 最熟悉的程式語言就是這兩種。但是在已經習慣怎麼寫出軟體功能後,會建議偶爾學習一下其它範式的程式語言。這樣可以用更寬廣的眼界思考事物,讓你的能力與觀點進化到更高的層次。


營火前的小複習

  • 不同的程式語言,對於怎麼組合複雜程式的觀點不太一樣
  • 這些「怎樣讓複雜的程式有條理,好維護跟擴展」的程式世界觀,叫做範式 (paradigm)
  • 比較主流的範式有「指令式 (imperative)」、「物件導向(Object oriented)」及「函數式(Functional)」
  • 有些程式語言可以用不同的範式寫出相同的功能。

地圖


上一篇
Ch 24. 做很少事,但是大家都要會的語言
系列文
Just enough code with AI: 給新手們的程式設計世界觀26
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言