Biểu tượng của người Viking ở Julia là gì?


131

Cụ thể: Tôi đang cố gắng sử dụng gói DataFrames của Julia, cụ thể là hàm readtable () với tùy chọn tên, nhưng yêu cầu một vectơ ký hiệu.

  • biểu tượng là gì?
  • Tại sao họ lại chọn điều đó qua một vectơ của chuỗi?

Cho đến nay tôi chỉ tìm thấy một số ít tài liệu tham khảo về biểu tượng từ trong ngôn ngữ Julia. Có vẻ như các biểu tượng được đại diện bởi ": var", nhưng nó không rõ ràng cho tôi biết chúng là gì.

Ngoài ra: tôi có thể chạy

df = readtable( "table.txt", names = [symbol("var1"), symbol("var2")] )

Hai câu hỏi của tôi vẫn còn.


3
Một số cuộc trò chuyện về chủ đề này có thể được tìm thấy ở đây: Groups.google.com/d/msg/julia-users/MS7KW8IU-0o/cQ-yDOs_CQEJ
jverzani

Câu trả lời:


231

Các biểu tượng trong Julia giống như trong Lisp, Scheme hoặc Ruby. Tuy nhiên, theo tôi, câu trả lời cho những câu hỏi liên quan là không thực sự thỏa đáng . Nếu bạn đọc những câu trả lời đó, có vẻ như lý do một biểu tượng khác với một chuỗi là các chuỗi có thể thay đổi trong khi các biểu tượng là bất biến, và các biểu tượng cũng được "thực hiện" - bất kể điều đó có nghĩa là gì. Các chuỗi tình cờ có thể thay đổi trong Ruby và Lisp, nhưng chúng không ở Julia và sự khác biệt đó thực sự là một cá trích đỏ. Thực tế là các biểu tượng được thực hiện - tức là được băm bằng cách triển khai ngôn ngữ để so sánh công bằng nhanh chóng - cũng là một chi tiết triển khai không liên quan. Bạn có thể có một triển khai không biểu tượng thực tập và ngôn ngữ sẽ giống hệt nhau.

Vì vậy, một biểu tượng, thực sự là gì? Câu trả lời nằm ở một điểm chung mà Julia và Lisp có - khả năng biểu diễn mã của ngôn ngữ dưới dạng cấu trúc dữ liệu trong chính ngôn ngữ. Một số người gọi đây là "đồng âm" ( Wikipedia ), nhưng những người khác dường như không nghĩ rằng một mình là đủ để một ngôn ngữ là đồng âm. Nhưng thuật ngữ không thực sự quan trọng. Vấn đề là khi một ngôn ngữ có thể đại diện cho mã của chính nó, nó cần một cách để biểu diễn những thứ như bài tập, lời gọi hàm, những thứ có thể được viết dưới dạng giá trị bằng chữ, v.v. Nó cũng cần một cách để biểu diễn các biến của chính nó. Tức là, bạn cần một cách để thể hiện - dưới dạng dữ liệu - fooở phía bên trái của điều này:

foo == "foo"

Bây giờ chúng ta đang đi vào trọng tâm của vấn đề: sự khác biệt giữa biểu tượng và chuỗi là sự khác biệt giữa fooở phía bên trái của so sánh đó và "foo"ở phía bên phải. Ở bên trái, foolà một định danh và nó ước tính giá trị được liên kết với biến footrong phạm vi hiện tại. Ở bên phải, "foo"là một chuỗi ký tự và nó ước tính giá trị chuỗi "foo". Một biểu tượng trong cả Lisp và Julia là cách bạn biểu diễn một biến dưới dạng dữ liệu. Một chuỗi chỉ đại diện cho chính nó. Bạn có thể thấy sự khác biệt bằng cách áp dụng evalcho họ:

julia> eval(:foo)
ERROR: foo not defined

julia> foo = "hello"
"hello"

julia> eval(:foo)
"hello"

julia> eval("foo")
"foo"

Những gì biểu tượng :foođánh giá phụ thuộc vào cái gì - nếu có gì - biến foobị ràng buộc với, trong khi"foo" luôn chỉ đánh giá là "foo". Nếu bạn muốn xây dựng các biểu thức trong Julia sử dụng các biến, thì bạn đang sử dụng các ký hiệu (cho dù bạn có biết hay không). Ví dụ:

julia> ex = :(foo = "bar")
:(foo = "bar")

julia> dump(ex)
Expr
  head: Symbol =
  args: Array{Any}((2,))
    1: Symbol foo
    2: String "bar"
  typ: Any

Những gì đã bỏ đi cho thấy, trong số những thứ khác, là có một :foođối tượng biểu tượng bên trong đối tượng biểu thức bạn nhận được bằng cách trích dẫn mã foo = "bar". Đây là một ví dụ khác, xây dựng một biểu thức với ký hiệu :foođược lưu trong biến sym:

julia> sym = :foo
:foo

julia> eval(sym)
"hello"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        foo = "bar"
        1 + 2
    end)

julia> eval(ex)
3

julia> foo
"bar"

Nếu bạn cố gắng làm điều này khi symbị ràng buộc với chuỗi"foo" , nó sẽ không hoạt động:

julia> sym = "foo"
"foo"

julia> ex = :($sym = "bar"; 1 + 2)
:(begin
        "foo" = "bar"
        1 + 2
    end)

julia> eval(ex)
ERROR: syntax: invalid assignment location ""foo""

Thật rõ ràng để biết lý do tại sao điều này sẽ không hoạt động - nếu bạn cố gắng gán "foo" = "bar"bằng tay, nó cũng sẽ không hoạt động.

Đây là bản chất của một biểu tượng: một biểu tượng được sử dụng để thể hiện một biến trong siêu lập trình. Tất nhiên, khi bạn có các biểu tượng như một kiểu dữ liệu, việc sử dụng chúng cho các mục khác sẽ trở nên hấp dẫn hơn, như là các khóa băm. Nhưng đó là cách sử dụng ngẫu nhiên, cơ hội của một loại dữ liệu có mục đích chính khác.

Lưu ý rằng tôi đã ngừng nói về Ruby một thời gian trước. Đó là bởi vì Ruby không phải là đồng âm: Ruby không biểu thị các biểu thức của nó dưới dạng các đối tượng Ruby. Vì vậy, loại biểu tượng của Ruby là một loại cơ quan tiền đình - một bản chuyển thể còn sót lại, được thừa hưởng từ Lisp, nhưng không còn được sử dụng cho mục đích ban đầu của nó. Các biểu tượng Ruby đã được chọn đồng thời cho các mục đích khác - làm khóa băm, để kéo các phương thức ra khỏi bảng phương thức - nhưng các biểu tượng trong Ruby không được sử dụng để biểu diễn các biến.

Về lý do tại sao các biểu tượng được sử dụng trong DataFrames chứ không phải là chuỗi, bởi vì đó là một mẫu phổ biến trong DataFrames để liên kết các giá trị cột với các biến bên trong các biểu thức do người dùng cung cấp. Vì vậy, việc các tên cột là biểu tượng là điều tự nhiên, vì các biểu tượng chính xác là những gì bạn sử dụng để biểu diễn các biến dưới dạng dữ liệu. Hiện tại, bạn phải viết df[:foo]để truy cập vào foocột, nhưng trong tương lai, bạn có thể truy cập nó df.foothay thế. Khi điều đó trở nên có thể, chỉ các cột có tên là định danh hợp lệ mới có thể truy cập được bằng cú pháp thuận tiện này.

Xem thêm:


6
Thực tập: Trong khoa học máy tính, thực tập chuỗi là một phương pháp chỉ lưu trữ một bản sao của mỗi giá trị chuỗi riêng biệt, phải là bất biến. Chuỗi thực tập làm cho một số tác vụ xử lý chuỗi hiệu quả hơn về thời gian hoặc không gian với chi phí đòi hỏi nhiều thời gian hơn khi chuỗi được tạo hoặc được thực hiện. vi.wikipedia.org/wiki/String_iterning
xiaodai

Tại một thời điểm bạn viết eval(:foo)và tại một điểm khác eval(sym). Có một sự khác biệt có ý nghĩa giữa eval(:foo)eval(foo)?
Grayscale

Rất nhiều như vậy: eval(:foo)đưa ra giá trị mà biến đó foobị ràng buộc trong khi eval(foo)gọi eval trên giá trị đó. Viết eval(:foo)tương đương với chỉ foo(trong phạm vi toàn cầu) eval(foo)là như vậy eval(eval(:foo)).
StefanKarpinki
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.