+3

Lazy evaluation in Scala

Giới thiệu về Scala

Scala, viết tắt của Scalable Language, là một ngôn ngữ lai lập trình hàm (hidbrid functional programming language), được tạo ra bởi Martin Odersky và ra mắt lần đầu tiên vào năm 2003.

Scala tích hợp một cách nhuần nhuyễn giữa các ngôn ngữ lập trình hướng đối tượng và ngôn ngữ lập trình hàm. Nó được biên dịch để chạy trên các máy ảo Java (Java Virtual Machine). Hiện tại có rất nhiều công ty đang phụ thuộc vào Java trong việc phát triển các ứng dụng quan trọng liên quan tới kinh doanh, đang dần dần chuyển sang sử dụng Scala để đẩy nhanh tốc độ, và tăng khả năng mở rộng (scalable) cũng như độ tin cậy của các sản phẩm.

Sau đây là một số tính chất quan trọng của Scala giúp ngôn ngữ này trở thành một trong những lựa chọn hàng đầu của các lập trình viên.

  • Scala là một ngôn ngữ hướng đối tượng

  • Scala là một ngôn ngữ lập trình hàm

  • Scala là một ngôn ngữ statically typed

    Không giống như những ngôn ngữ static type khác, Scala không cần thiết phải có thông tin về kiểu dữ liệu. Bạn không phải chỉ ra kiểu dữ liệu trong hầu hết các trường.

  • Scala chạy trên JVM

    Scala được biên dịch sang Java Byte Code, được chạy bởi Java Virtual Machine (JVM). Điều này có nghĩa rằng Scala và Java sử dụng chung một runtime platform. Bạn có thể dễ dàng chuyển từ Java sang Scala.

    Trình biên dịch của Scala dịch Scala code sang Java Byte Code - loại mã có thể được thực thi bởi câu lệnh scala. Câu lệnh scala cũng tương tự như câu lệnh java.

  • Scala có thể chạy Java Code

    Scala có khả năng sử dụng tất cả các class của Java SDK và các custom class cũng như những project mã nguồn mở Java.

  • Một số sự khác biệt của Scala khi so sánh với Java

  • Các Web Framework của Scala

    Scala được sử dụng ở mọi nơi và có vai trò quan trọng đối với các tổ chức kinh doanh ứng dụng web. Bạn có thể tham khảo một số Web Framework sau:

Lazy evaluation trong Scala

Laziness là gì trong lập trình

Khi nhìn qua, bạn có thể cảm nhận laziness là một khái niệm có liên quan tới hiệu năng.

Trong lập trình, laziness có nghĩa là trì hoãn quá trình tính toán một giá trị cho tới khi nào cần thiết sử dụng giá trị đó. Và nếu giá trị đó không bao giờ cần thiết được sử dụng, nó sẽ không bao giờ được tính toán.

Laziness cũng giúp tránh được việc tính toán lặp đi lặp lại nhiều lần. Sau khi giá trị của một hàm được tính toán, kết quả được lưu trong một bảng tra cứu được đánh thứ tự (indexing) bằng giá trị của các thông số đó. Trong mỗi lần hàm được gọi, máy tính sẽ kiểm tra xem trong bảng tra cứu đã có giắ tị của hàm hay chưa. Nếu đã có, giá trị đó sẽ được trả về, nếu không hàm sẽ được tính toán và một giá trị khác sẽ được thêm vào bảng tra cứu để sử dụng lại.

Một số lợi ích của lazy evaluation:

  • Tăng hiệu suất bằng cách tránh các tính toán không cần thiết, và các tình trạng lỗi xảy ra trong các tính toán đó.
  • Khả năng xây dựng một cấu trúc dữ liệu vô hạn (potentially infinite data structure)
  • Khả năng định nghĩa một cấu trúc điều khiển theo cách trừu tượng

Lazy evaluation giúp giảm thiểu bộ nhớ sử dụng, do giá trị chỉ được tạo ra khi cần thiết. Tuy nhiên, tồn tại nhiều khó khăn trong việc kết hợp giữa lazy evaluation và các function mang tính chất mệnh lệnh như exception handling hay input/output bởi thứ tự của các lệnh trở nên không đoán trước được. Lazy evaluation cũng có thể gây ra các lỗ hổng bộ nhớ (máy tính gặp sai sót trong việc quản lý cung cấp bộ nhớ).

Khái niệm ngược với Lazy evaluation là Eager evaluation, còn hay được gọi là Strict evaluation. Eager evaluation tính toán giá trị của một biểu thức ngay lập tức, và là phương pháp tính toán được sử dụng trong hầu hết các ngôn ngữ lập trình.

Một số ngôn ngữ lập trình, ví dụ như Haskell sử dụng lazy evaluation một cách mặc định, việc tính toán của các biểu thức phải đợi tới khi chúng được sử dụng.

Một số ngôn ngữ lập trình khác (ví dụ như Scala), mặc định sử dụng eager evaluation nhưng nếu được chỉ định của thể, một biểu thức hoặc một giá trị sẽ được tính theo kiểu lazy evaluation.

Laziness trong Scala

Scala mặc định sử dụng eager evaluation nhưng cho phép sử dụng lazy evaluation nếu như trước định nghĩa của một giá trị ta thêm từ khoá lazy.

Ví dụ: lazy val x = 1 + 1;

Chúng ta hãy cùng tìm hiểu về Lazy evaluation của Scala thông qua đoạn mã sau:

def expr = {
  val x = { print("x"); 1}
  lazy val y = { print("y"); 2}
  def z = { print("z"); 3}
  z + y + x + z + y + x
}
expr

Nếu bạn chạy chương trình này, kết quả in ra sẽ như thế nào.

  1. zyxzyx
  2. xyzz
  3. xzyz
  4. zyzz
  5. Một kết quả khác

laziness.png

Đáp án:

Với hàm expr được định nghĩa như trên, khi bạn thực hiện việc gọi hàm trog câu lệnh dưới cùng. Thứ tự của việc tính toán sẽ diễn ra như sau.

  • Đầu tiên, ba định nghĩa của x, y, z sẽ được đánh giá. Giá trị của x sẽ được tính toán ngay lập tức, kèm theo đó chữ "x" sẽ được in ra.

    Giá trị của y, do được định nghĩa kèm theo từ khoá lazy, việc tính toán giá trị này sẽ bị trì hoãn cho tới khi nó được gọi.

    Ở đây z được định nghĩa là một hàm, do đó giá trị của nó sẽ không được tính toán ngay lập tức.

  • Chúng ta sẽ xem xem câu lệnh z + y + x + z + y + x sẽ cho ra kết quả ra sao

    Đầu tiên, hàm z được gọi ra. Máy tính sẽ tính toán giá trị của z và kèm theo đó in ra chữ "z".

    Tiếp theo, giá trị của y được gọi, lúc này y mới được tính toán, và chữ "y" sẽ được in kèm.

    Sau đó, giá trị của x được gọi, giá trị này đã được tính toán từ trước, do đó việc tính toán sẽ không xảy ra lần hai, không có gì được in ra.

    Tiếp theo, hàm z được gọi, lúc này lại thêm một chữ "z" được in ra.

    Sau cùng, giá trị của y và x lần lượt được gọi ra, do hai giá trị này đã được tính toán từ trước nên máy tính chỉ việc gọi giá trị đã được lưu ra để sử dụng lại, dẫn tới việc không có chữ cái nào được in ra.

  • Như vậy kết quả in ra của đoạn mã trên là xzyz.

Tài liệu tham khảo

  1. Lazy evaluation - Arnaldo Pedro Figueira Figueira
  2. Tutorial point
  3. Understand and implement laziness with examples in Scala, JavaScript, Swift and Racket
  4. Lazy evaluation - Wikipedia

Kết luận

Qua bài viết này, hi vọng bạn đã hiểu thêm về sự khác biệt giữa Lazy evaluation và Eager evaluation. Chúc bạn vận dụng tốt những kiến thức của mình để áp dụng tăng hiệu năng của chương trình. Cảm ơn vì đã đọc bài viết. (thankyou)


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí