Hàm chỉ trả về tham số không thay đổi, vô dụng?


15

Tôi chỉ tìm thấy chức năng này trong dự án tôi đang làm việc tại:

  -- Just returns the text unchanged.
  -- Note: <text> may be nil, function must return nil in that case!
  function Widget:wtr(text)
      return text
  end

Quá buồn, lập trình viên không còn làm việc trong công ty nữa. Tại sao người ta sẽ tạo ra một hàm không làm gì, nhưng trả về tham số mà nó được gọi với?

Có sử dụng chức năng như vậy, không được chỉ định cho ví dụ này, nhưng tổng thể trong mọi trường hợp?

Do

function aFunction(parameter)
    return parameter
end

Kết thúc ở

aFunction(parameter) == parameter

Tại sao tôi lại viết một cái gì đó như

aFunction(parameter) == whatIWantToCheck

thay vì

parameter == whatIWantToCheck

?



13
@gnat Làm thế nào trên trái đất là một bản sao?
Kilian Foth

13
Huh? Hàm này trả về tham số của nó - chuỗi liên quan đến việc trả về this.
Kilian Foth

11
@gnat Câu hỏi là tại sao một người nào đó sẽ viết một hàm không làm gì ngoài việc trả về chính nó. Có, bạn có thể trả về một số đối tượng hoặc giá trị nhất định để cho phép chuỗi phương thức, nhưng đó không phải là câu hỏi của anh ấy. Câu hỏi của anh ấy là tại sao một người nào đó sẽ viết một cái gì đó như int getParam(int param) { //DO NOTHING return param; } Từ phối cảnh phương thức, đó là một cuộc gọi hoàn toàn không cần thiết và không cần thiết vì bạn có thể rời khỏi chức năng của OP khỏi chuỗi phương thức và nó sẽ không tạo ra sự khác biệt nào.
ZeroStatic

4
Điều này có thể không chính đáng và không áp dụng cho lua, nhưng có một trường hợp sử dụng hợp lệ cho điều này trong PHP - trong các phiên bản cũ hơn, new Foo()->method();không phải là cú pháp hợp lệ và các cấu trúc như function with($what) { return $what; }; with(new Foo())->method();được sử dụng như một cách giải quyết.
DCoder

Câu trả lời:


57

Câu hỏi của bạn giống như hỏi những gì tốt của số 0 nếu bất cứ khi nào bạn thêm nó vào một cái gì đó bạn sẽ nhận lại cùng một giá trị. Một chức năng nhận dạng giống như số không cho các chức năng. Bản thân nó vô dụng, nhưng đôi khi hữu ích như là một phần của biểu thức sử dụng các hàm bậc cao hơn, trong đó bạn có thể lấy một hàm làm tham số hoặc trả về kết quả. Đó là lý do tại sao hầu hết các ngôn ngữ lập trình chức năng có một idhoặc identitytrong thư viện tiêu chuẩn của họ.

Nói cách khác, nó làm cho một chức năng mặc định tiện dụng. Giống như bạn có thể muốn đặt offset = 0làm số nguyên mặc định, mặc dù điều đó làm cho phần bù không làm gì, nó có thể có ích để có thể đặt filterFunction = identitylàm hàm mặc định, mặc dù điều đó làm cho bộ lọc không làm gì cả.


Không phải hàm lọc sẽ trả về giá trị boolean? Trong trường hợp này, hàm lọc "không" sẽ là hàm trả về giá trị true.
Kirill Rakhman

1
@cypressious Một chức năng bản đồ, sau đó.
sapi

6
Hoặc để gắn nó theo một khái niệm thiết kế: Mẫu đối tượng Null , phiên bản chức năng
blgt

@cypressious, điều đó sẽ cho một vị đó được thông qua như là một cuộc tranh cãi vào một filterchức năng bậc cao. Hàm thứ tự đầu tiên filtercó loại [a] -> [a],
Karl Bielefeldt

Ví dụ: trong C # tôi thường sử dụng.OrderBy(x => x)
CodeInChaos

27

Chắc chắn rồi. Hãy tưởng tượng một API bên ngoài cho phép bạn truy xuất những thứ từ một nơi nào đó mà bạn thực sự cần, nhưng bạn phải chỉ định tiêu chí lọc và bộ định dạng đầu ra cho mọi truy vấn, ngay cả khi bạn muốn tất cả các kết quả và muốn nhận chúng chính xác như được lưu trữ.

Sau đó, bạn phải phát minh ra một chức năng "chấp nhận mọi thứ" tầm thường và một chức năng "trả lại không thay đổi" tầm thường để lấy dữ liệu. wtrchính xác là một định dạng giả tầm thường như vậy. Nếu bạn sử dụng API đó rất nhiều, sẽ rất hữu ích khi có chức năng trợ giúp giả này nằm xung quanh thay vì phải tạo một hàm ẩn danh bất cứ khi nào bạn truy vấn điều gì đó. (Bạn có thể cân nhắc việc gọi nó identityhơn là wtrđể nó ngay lập tức xóa nó không làm gì cả.)


Tôi chưa thực sự hiểu ý nghĩa, nhưng đó chính xác là kịch bản. Tôi có thể hiểu sau một thời gian, làm việc trong dự án này trong khi giữ câu trả lời của bạn trong tâm trí, tôi nghĩ. atm nó có vẻ vô dụng đối với tôi, ... nếu tôi có rawdata, tại sao tôi lại muốn một chức năng cung cấp cho tôi rawdata một lần nữa, ...
Sempie

3
@Sempie Một lần nữa, nếu API yêu cầu chức năng định dạng, cách duy nhất để có được văn bản chưa được thay đổi là nếu chức năng không làm gì với văn bản.
Doval

3
Nói cách khác: Nếu bạn có một hàm yêu cầu các đối số bộ lọc / định dạng được truyền và bạn hoàn toàn không thể sử dụng nulllàm đối số, bạn sử dụng hàm lọc trống lọc 'không có gì' để khiến chương trình ngừng phàn nàn.
ZeroStatic

3
@Sempie Bạn đã làm việc với SQL, phải không? Bạn biết làm thế nào bạn có thể bao gồm hoặc không bao gồm một WHEREđiều khoản? Đó là một vấn đề lỏng lẻo của cú pháp. Về cơ bản sự vắng mặt của một WHEREmệnh đề hoàn toàn giống như khi bạn có một WHEREmệnh đề chỉ đi trước và cho phép mọi thứ. Thực tế là các nhà thiết kế của SQL cho phép bạn không chỉ định một WHEREmệnh đề, thay vì buộc bạn đặt nó xuống, ngay cả khi nó chấp nhận mọi thứ, là đường cú pháp ít nhiều và họ chỉ cung cấp cho bạn tùy chọn đó để thuận tiện đơn giản. ..
Panzercrisis

5
Có thể đáng lưu ý rằng trong nhiều trường hợp, nhanh hơn và sạch hơn để có mã gọi một cách vô điều kiện một phương thức ảo hoặc ủy nhiệm mà có thể hoặc không thể làm điều gì đó hữu ích, hơn là để mã xác định liệu cuộc gọi có cần thiết hay không và bỏ qua nó nếu không.
supercat

15

Không phải đó chỉ là một đa hình sao?

Từ kinh nghiệm của tôi với Qt tr()wtr()các phương pháp được cho là sẽ được sử dụng (ở đó, trong Qt ) trong việc bản địa hóa Widgetvăn bản của.

Vì vậy, bằng cách trả về văn bản không thay đổi, phương thức này chỉ nói : Widget does no localization (translation of the text) by default. Override this function to enable your own logic.


1
đã không nhận ra đây là một điều QT - đây rõ ràng là câu trả lời.
Corley Brigman

8

Một trường hợp rất phổ biến cho điều này là 'chức năng được thêm vào sau'. Vì vậy, lập trình viên nghĩ rằng có thể có một số thay đổi cho chức năng đó sau này. Vì bạn truy cập nó dưới dạng hàm chứ không phải là tham số, bạn có thể dễ dàng thay đổi toàn cầu. Hãy nói rằng bạn có một chỉ mục với:

function getIndex(index)
    return index
end

và vì chỉ số của bạn bắt đầu từ 0 nên mọi thứ đều ổn. Sau này bạn thay đổi một thành phần ở nơi khác, thành phần này cần bạn dịch chỉ mục của bạn để bắt đầu từ 1. Bạn sẽ phải thêm hàng trăm chỉ mục + 1 ở mọi nơi trong mã của mình. Nhưng với một phương pháp như thế này, chỉ cần nói:

 function getIndex(index)
    return index+1
end

và bạn tốt thôi. Các chức năng như thế này có thể nhanh chóng dẫn đến kỹ thuật quá mức nhưng tại một số điểm chúng có rất nhiều ý nghĩa!


2
Có, mặc dù đáng lưu ý rằng chuỗi doct của chức năng được đăng bởi OP không cho thấy đây là mục đích của chức năng trong trường hợp của anh ta.
Đánh dấu Amery

6

Các hàm còn sơ khai như thế này là phổ biến trong các tình huống thừa kế kiểu. Lớp cơ sở có thể không làm gì hữu ích, nhưng các lớp dẫn xuất có thể làm nhiều việc khác nhau với các đầu vào. Khai báo hàm sơ khai trong lớp cơ sở cho phép tất cả các lớp dẫn xuất một hàm của tên đó và các lớp dẫn xuất riêng lẻ ghi đè lên nó bằng một cái gì đó phức tạp và hữu ích hơn.


5

Một kịch bản bổ sung tương tự như việc sử dụng các thuộc tính python và C #, nhưng trong các ngôn ngữ không có tính năng này.

Nói chung, bạn có thể tuyên bố một cái gì đó chỉ là một thành viên của lớp; giả sử, 'tên' là một chuỗi. Điều này có nghĩa là bạn truy cập nó như thế này:

someobject.name

Sau đó, bạn quyết định rằng tên thực sự cần phải phụ thuộc vào những gì trong đối tượng. Vì vậy, nó thực sự nên là một chức năng. Giáo sư! Ngay cả khi không có đối số, điều đó có nghĩa là tất cả mã truy cập bây giờ phải được đổi thành

someobject.name()

Nhưng nếu bạn có nhiều phiên bản của cuộc gọi này, khả năng không có gì sai với điều đó là khá thấp - ở đâu đó thay đổi này sẽ không được thực hiện, chương trình sẽ bị sập khi bạn đến điểm đó, v.v.

Các thuộc tính trong C # / Python cho phép bạn thay thế một hàm trong những gì từng là một thuộc tính, trong khi vẫn cho phép nó được truy cập như một thuộc tính tức là không có thay đổi. Bạn thậm chí không phải có kế hoạch trước.

Nếu ngôn ngữ của bạn không có điều đó, bạn phải lên kế hoạch trước, nhưng bạn vẫn có thể hỗ trợ nó theo cách mọi người đã làm trước đây bằng cách biến nó thành chức năng ngay từ đầu mà không làm gì cả. Ban đầu, nó sẽ không làm bất cứ điều gì thú vị, và có vẻ như nó nên được gỡ bỏ, và nhiều chức năng của loại này không bao giờ thay đổi. Nhưng sau này, nếu bạn nhận ra rằng thực sự bất cứ khi nào bạn gọi Widget.wtrbạn cần loại bỏ một số ký tự đặc biệt, thì đó không phải là vấn đề lớn - đó đã là một chức năng, bạn chỉ cần thêm nó vào và bạn đã hoàn thành.

TL; DR Đây có thể chỉ là một lập trình viên khôn ngoan lên kế hoạch trước cho những thay đổi trong tương lai.


3
Điều đó sẽ có ý nghĩa nếu phương pháp này phụ thuộc vào bất cứ điều gì khác, nhưng nó không. Nó không phải là một thuộc tính, getter / setter hoặc một trường. Đó là một phương pháp hiện không làm gì cả. Chỉ có cách anh ấy lên kế hoạch cho những thay đổi trong tương lai là nếu logic của phương pháp này sẽ phải thay đổi.
Matthew Steeples

1
Nó không phải ... điều đó có nghĩa là ngay bây giờ, tôi không xử lý dữ liệu này, nhưng sau này, nếu tôi muốn xử lý nó, mọi người dùng dữ liệu đó đều được xử lý dữ liệu miễn phí. Ví dụ ngu ngốc: Giả sử bạn in chuỗi lên màn hình và bạn thường làm như vậy print data. Sau đó, bạn nhận ra tất cả các chuỗi phải viết hoa - bạn phải đi tìm mọi bản in trong chương trình của mình và đổi thành print data.upper(). Nhưng nếu bạn có def cdata(data): return datavà mọi nơi nói print cdata(data), thì bạn chỉ cần thay đổi def cdata(data): return data.upper()và đó là thay đổi duy nhất.
Corley Brigman

Tôi thấy những gì bạn có ý nghĩa ở đó. Điều đó có ý nghĩa hơn
Matthew Steeples

2

Nó không vô dụng, thực sự nó có thể cực kỳ hữu ích, bởi vì nó làm cho mã của bạn thống nhất và linh hoạt hơn.

Ví dụ, giả sử bạn có danh sách người và danh sách thả xuống để người dùng chọn nếu chúng tôi muốn xem "tất cả" hoặc chỉ những người là "nam" hoặc "nữ".

Bạn có thể xử lý "tất cả" như một trường hợp đặc biệt, trong trường hợp đó bạn sẽ cần thêm nếu và để kiểm tra rõ ràng trường hợp này hoặc bạn có thể có chức năng lọc chỉ trả về tham số của nó (ví dụ: cho phép mọi thứ vượt qua), được chỉ định để được sử dụng cho trường hợp "tất cả".


4
Điều đó không phù hợp với kịch bản. Tôi có nghĩa là một hàm trả về các tham số của anh ta và, trong mọi trường hợp, không làm gì khác.
Sempie

@Sempie: Đó là những gì anh ấy nói. Nếu bạn có một Filterlớp hoặc giao diện với MaleFiltervà các FemaleFilterlớp con và mã của bạn yêu cầu một số bộ lọc, một bộ lọc không có gì (trả về tham số của nó không thay đổi) là cách bạn xử lý All. Các chức năng không bao giờ làm bất cứ điều gì, nhưng có thể được thay thế cho một trong đó.
Magus

@Magus, nhưng trong kịch bản của bạn, hàm này là một loại giữ chỗ nào đó, sẽ được thay thế sau đó hoặc chỉ tồn tại vì hàm cũ đã lỗi thời nhưng chương trình cần thông qua này. Dù sao, nó không phải là một bàn giao. Hàm không cung cấp tham số không thay đổi cho hàm khác, như bộ lọc có thể làm, nhưng trả lại cho hàm gọi.
Sempie

@Sempie Không, đó không phải là một nơi thay thế mà nó không được sử dụng như một sự vượt qua tạm thời. Đó là một khái niệm mã hóa (và toán học) hữu ích, chức năng "danh tính". Và, vâng, nó vẫn là một bàn giao, cho dù nó trả nó về "chức năng khác" hay cho chức năng gọi. Điều quan trọng là chức năng "nhận dạng" có thể là một trong nhiều chức năng có thể được gọi bởi chức năng gọi và được sử dụng để tránh nếu và đặc biệt khi hàm được gọi không cần làm gì cả.
Hejazzman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.