R là ngôn ngữ lập trình đặc thù - Domain Specific Language (DSL) - dành cho thống kê và phân tích dữ liệu. Có 2 đối tượng chính sử dụng R:
R. Đối tượng này thường là những người có kinh nghiệm làm việc với các ngôn ngữ lập trình khác và kiến thức khoa học máy tính (computer science) nhất định.Ngay cả với đối tượng thứ 2 khi mới bắt đầu làm quen với R, cũng cảm thấy băn khoăn vì sự khác biệt của R. Căn nguyên sự dị biệt này, bên cạnh nguồn gốc thống kê và đại số tuyến tính, R thừa kế nhiều di sản của S và gây ra nhiều bối rối cho nhiều người vốn đã quen thuộc với các cú pháp ngôn ngữ khác. Bài viết trình bày 1 số “góc khuất” này của R, xét trên khía cạnh ngôn ngữ lập trình.
<- hay =?Toán tử gán là toán tử cơ bản nhất của tất cả các ngôn ngữ lập trình. Ngoại trừ Assembly, = được sử dụng rộng rãi như 1 toán tử báo hiệu phép gán. Mặc dù R ngày nay vẫn hỗ trợ = như 1 toán tử gán, hầu hết những người phát triển R đều khuyến nghị sử dụng <-. Tại sao lại vậy?
R khởi phát từ S - cũng là 1 ngôn ngữ lập trình thống kê - và vì S sử dụng <- để làm toán tử gán nên R thừa kế di sản này? Mà S được phát triển từ APL - 1 ngôn ngữ lập trình từ năm một nghìn chín trăm sáu mươi tư . Nếu biết rằng người ta sử dụng APL trên máy tính mà bàn phím có hẳn 1 nút <- và vì hình dáng <- có vẻ tượng hình cho phép gán nên nó đã được sử dụng!!! 1 nguồn gốc li kì cho 1 toán tử.
Vậy nên dùng = hay <- khi viết mã nguồn R?
Cho đến tận năm 2001, R vẫn chỉ cho phép dùng = khi truyền tham số của hàm được gọi và điều này gây ra không ít khó khăn cho những lập trình viên chuyển từ các ngôn ngữ khác sang.
foo(bar = "baz")
Năm 2001, = được giới thiệu lần đầu trong R như 1 toán tử gán trong nỗ lực giảm bớt khác biệt với các ngôn ngữ lập trình khác. Ban đầu có những tính năng chưa thể thực hiện với = nhưng lại được hỗ trợ bởi <- do = vẫn chủ yếu được dùng khi truyền tham số cho hàm (mang ý nghĩa khác với phép gán). Lúc đó phép gán với = chỉ được dùng top of the call hoặc dùng kèm với ( và ). Ngược lại, parser của R bị rối và báo lỗi.
May mắn thay, ngày nay, chúng ta có thể dùng = thay <- để thực hiện phép gán trong hầu hết các trường hợp dù đây đó 1 số khác biệt như ví dụ dưới đây:
>quote(y <- 5)
y <- 5
>quote(y = 5)
Error in quote(y = 5) : supplied argument name 'y' does not match 'expr'
<- vẫn là quy chuẩn của S - ngôn ngữ mà R kế thừa - và rất nhiều lập trình viên cây đa cây đề của R chuyển sang từ S. Do đó <- tiếp tục được sử dụng chủ đạo trong R thay vì =. Mọi cuốn sách dùng <-, mọi ví dụ dùng <- và rất nhiều khả năng người dạy R cho bạn cũng dùng <-.
Nếu viết mã nguồn R cho các dự án mang tính cá nhân, người phát triển có thể tuỳ ý dùng toán tử gán (tất nhiên không nên trộn lẫn = hay <-). Trong hầu hết các trường hợp, khi mã nguồn R được chia sẻ với người phát triển khác, <- là một chọn lựa tốt hơn.
. và _Đối với người lập trình chuyên nghiệp, quy chuẩn khi viết code (coding convention) là một chủ đề quan trọng đặc biệt là khi mã nguồn bạn viết được chia sẻ trong 1 môi trường làm việc chung. 1 nhà khoa học máy tính từng nói “70% thời gian của việc lập trình là dành cho việc đặt tên biến và tên hàm cho thật ý nghĩa”. Ngôn ngữ lập trình như C, C++, C# hay Java thường sử dụng kiểu camel case như:
thisIsAVariable
hoặc
ThisIsAVariable
Cách viết này tuy quen thuộc nhưng hơi khó đọc do không có sự ngăn cách giữa các từ. 1 số ngôn ngữ như Python thì lập trình viên hay sử dụng _ để phân cách như:
this_is_a_variable
Riêng chỉ có R cho phép . trong tập các kí tự dùng khi đặt tên biến, tên hàm. 1 thời gian dài R kế thừa S (lại S) dùng _ như 1 toán tử gán và sử dụng . khi đặt tên như:
csv.write
install.packages
Với nhiều ngôn ngữ lập trình . thường mang ý nghĩa đặc biệt (VD: truy xuất đến các attribute trong Java hay C#). Do đó, mặc dù sẽ còn rất lâu R thay đổi cách đặt tên các hàm kinh điển sử dụng ., người lập trình không nên sử dụng . để tránh gây khó hiểu cho các lập trình viên từ các ngôn ngữ khác chuyển qua vốn ngày càng nhiều.
stringAsFactor = TRUE là mặc định?Khi làm việc với dữ liệu, *.csv là định dạng hay sử dụng nhất kéo theo đó là hàm read.csv hoặc read.csv2. Sử dụng với tham số mặc định stringAsFactor = TRUE, thì tất cả các column có kiểu dữ liệu character đều được recode thành factor. Một tìm kiếm đơn giản với Google chorất nhiều bài viết mô tả những lỗi không mong muốn vì quên mất thiết lập này. Ngày nay, cấu hình mặc định này không mang lại sự thoải mái và trong hầu hết các trường hợp, người code thiết lập stringAsFactor = FALSE. Căn nguyên tại sao default là TRUE thay vì FALSE?
Trước đây, khi R chỉ được sử dụng bởi các nhà thống kê để giải quyết các bài toán về xây dựng mô hình thống kê, mã hoá dữ liệu character thành factor là nhu cầu hợp lý và tất yếu. Với tabular data, nếu 1 cột dữ liệu nào đó không phải là dạng số, numeric, gần như chắc chắn nó sẽ được mã hoá lại thành 1 biến phân loại. VD: biến Giới tính, Quốc gia, Khu vực, và những hàm tính toán mô hình như lm hay glm cần xây dựng 1 loạt các biến dummy từ các biến phân loại - factor. Với tư tưởng đó, stringAsFactor = TRUE là thiết lập gần như không phải suy nghĩ hay đắn đo.
Ngày nay, R lấn sân sang nhiều lĩnh vực khác. Đây là điều đáng mừng nhưng đồng thời cũng mở ra nhiều trường hợp vượt ngoài tầm nhìn của những người xây dựng R ban đầu. Hầu hết những người phàn nàn về stringAsFactor = TRUE khi thực hiện các nghiệp vụ không phải là xây dựng mô hình thống kê truyền thống và dẫu có rất nhiều phàn nàn về tham số này, R hoàn toàn không có lỗi.
Có lẽ stringAsFactor = TRUE vẫn là giá trị mặc định trong 1 thời gian dài nữa.
<- thay vì = khi thực hiện phép gán_ thay vì . trong việc đặt tên hàm, biếnstringAsFactor = FALSE