2015-10-07 16 views
13

Khi tôi tạo ra một số mảng A và gán nó đến BTạo bản trong Julia với toán tử =

A = [1:10] 
B = A 

tôi có thể sửa đổi A và sự thay đổi phản ánh trong B

A[1] = 42 
# B[1] is now 42 

Nhưng nếu tôi làm điều đó với các biến vô hướng, thay đổi không lan truyền:

a = 1 
b = a 
a = 2 
# b remains being 1 

Tôi thậm chí có thể kết hợp mọi thứ và chuyển đổi véc tơ thành scala r và thay đổi không lan truyền:

A = [1:10] 
B = A 
A = 0 
# B remains being 1,2,...,10 

Nhà điều hành = chính xác là gì? Khi tôi muốn sao chép các biến và sửa đổi các biến cũ bảo toàn tính toàn vẹn của các biến mới, khi nào tôi nên sử dụng b = copy(a) chỉ trên b=a?

+0

Dựa trên dự đoán của bạn về kết quả được phản ánh từ câu hỏi, ngôn ngữ R có thể khiến bạn ngạc nhiên nhất. – colinfang

Trả lời

24

Sự rắc rối bắt nguồn từ này: phânđột biến không phải là những điều tương tự.

Chuyển nhượng. Bài tập giống như x = ... - phần còn lại của số = là số nhận dạng, tức là tên biến. Thay đổi nhiệm vụ mà đối tượng biến x đề cập đến (điều này được gọi là một ràng buộc biến). Nó không biến đổi bất kỳ đối tượng nào cả.

Đột biến. Có hai cách tiêu biểu để biến đổi điều gì đó trong Julia: x.f = ... - những gì còn lại của = là biểu thức truy cập trường; x[i] = ... - phần còn lại của = là biểu thức lập chỉ mục. Hiện tại, đột biến trường là cơ bản - cú pháp đó có thể chỉ có nghĩa là bạn đang đột biến cấu trúc bằng cách thay đổi trường của cấu trúc đó. Điều này có thể thay đổi. Cú pháp đột biến mảng không phải là cơ bản - x[i] = y có nghĩa là setindex!(x, y, i) và bạn có thể thêm phương thức vào setindex! hoặc thay đổi cục bộ chức năng chung nào setindex!. Việc gán mảng thực tế là một hàm dựng sẵn - một hàm được thực hiện trong C (và chúng ta biết cách tạo mã LLVM tương ứng).

Thay đổi đột biến giá trị của đối tượng; nó không thay đổi bất kỳ ràng buộc biến nào. Sau khi thực hiện một trong hai điều trên, biến số x vẫn đề cập đến cùng một đối tượng đã làm trước đó; đối tượng đó có thể có nội dung khác nhau, tuy nhiên. Đặc biệt, nếu đối tượng đó có thể truy cập từ một số phạm vi khác - nói rằng hàm được gọi là một trong những làm đột biến - sau đó giá trị thay đổi sẽ được hiển thị ở đó. Nhưng không có ràng buộc nào đã thay đổi - tất cả các ràng buộc trong tất cả các phạm vi vẫn đề cập đến cùng một đối tượng.

Bạn sẽ lưu ý rằng trong lời giải thích này, tôi chưa bao giờ nói về tính bất biến hoặc bất biến. Đó là bởi vì nó không có gì để làm với bất kỳ điều này - đối tượng có thể thay đổi và bất biến có chính xác cùng ngữ nghĩa khi nói đến nhiệm vụ, chuyển đối số, v.v. Sự khác biệt duy nhất là nếu bạn cố gắng làm x.f = ... khi x không thay đổi, bạn sẽ gặp lỗi.

+0

Cảm ơn bạn đã trả lời đầy đủ. Như tôi đã hiểu bạn, tất cả các hoạt động 'b = a' của tôi là các phép gán, vì vậy trong mọi trường hợp' b' nên tham chiếu đến 'a'. Những gì tôi đang mất tích? – RedPointyJackson

+0

Khi bạn thực hiện 'A [1] = 42' đó là đột biến, chứ không phải gán. – StefanKarpinski

+0

Ok, tôi đã từ bỏ điều đó. Nhưng khi tôi làm 'b = a', nó nên được gán bởi vì nó là một phép toán trong kiểu' x = ... ', đúng không? Vì vậy, bây giờ tôi đã 'b' 'chỉ' để' a', và tất cả các thay đổi trong 'a' nên phản ánh bất cứ khi nào tôi đánh giá b, phải không? – RedPointyJackson

-4

Hành vi này tương tự như Java. A và B là các biến có thể chứa kiểu dữ liệu "đơn giản", chẳng hạn như số nguyên, float, hoặc tham chiếu (còn gọi là con trỏ) đến cấu trúc dữ liệu phức tạp hơn. Ngược lại với Java, Julia xử lý nhiều loại không trừu tượng dưới dạng dữ liệu "đơn giản".

Bạn có thể thử nghiệm với isbits(A) xem biến A của bạn có chứa một giá trị bit hay không hoặc tham chiếu đến một đối tượng dữ liệu khác. Trong trường hợp đầu tiên, B=A sẽ sao chép từng bit từ A sang cấp phát bộ nhớ mới cho B, nếu không, chỉ tham chiếu đến đối tượng mới được sao chép.

Cũng chơi xung quanh với pointer_from_objref(A).

+2

Câu trả lời này gây hiểu lầm tốt nhất: khả năng đột biến so với bất biến là cá trích đỏ. Các giá trị có thể thay đổi và bất biến có ngữ nghĩa giống nhau trong cả hai ngôn ngữ - cả hai đều có ngữ nghĩa tham chiếu. Đó là bởi vì cả Julia lẫn Java đều không có các loại giá trị có thể thay đổi, giống như các cấu trúc của C, vốn có các ngữ nghĩa khác nhau. – StefanKarpinski

Các vấn đề liên quan