2014-04-16 12 views
18

Mã này là dưới đây:mẫu bất hợp pháp trong bản đồ của Erlang

-module(map_demo). 
-export([count_characters/1]). 

count_characters(Str) -> 
count_characters(Str, #{}). 

count_characters([H|T], #{ H => N } = X) -> 
    count_characters(T, X#{ H := N+1 }); 
count_characters([H|T], X) -> 
    count_characters(T, X#{ H => 1}); 
count_characters([], X) -> 
    X. 

khi biên dịch mã kiểm tra vào vỏ Erlang, nó báo cáo các lỗi sau đây:

1> c(map_demo). 
map_demo.erl:7: illegal pattern 
map_demo.erl:8: variable 'N' is unbound 
map_demo.erl:10: illegal use of variable 'H' in map 
map_demo.erl:7: Warning: variable 'H' is unused 
error 

Tôi mới trong Erlang, và không thể tìm thấy bất cứ điều gì sai trái. Làm thế nào để sửa nó?

+2

Điều gần nhất tôi có thể tìm thấy là đây là "lỗi đã biết". Những người erlang này có nghiêm trọng không? Đây là một lỗi rất lớn trong trường hợp đó! Tôi nghĩ rằng đây là thứ mà bạn đã lấy từ "Lập trình Erlang" của chính Joe Armstrong, và tôi bị sốc với chính cốt lõi rằng điều này không hiệu quả! –

+0

Kể từ Erlang/OTP 18.0 mã này ném lỗi "chỉ" cho dòng 7, 8 vì các biến bị ràng buộc là hợp pháp để sử dụng trong bản đồ: ________________________________________________________________________________ 1> 'K = thecake, # {K => isalie} .' _______________________________________________' # { thecake => isalie} ' –

+0

đang chạy phiên bản 20, và đây là một lỗi? Có lẽ tôi sẽ nghiên cứu thêm một chút trước khi nổi giận, nhưng ... https://stackoverflow.com/questions/44247735/map-pattern-matching-in-erlang-unexpected-error-unbound – alexakarpov

Trả lời

15

Những câu trả lời từ IRC (# erlang @ freenode):

  1. biến như phím trong các trận đấu chưa được hỗ trợ (phát hành 17,0)
  2. Một vấn đề tổng quát hơn ảnh hưởng đến lập luận phù hợp của một chức năng: dòng 7 của H được kết hợp 2 lần; hoặc một lần và được sử dụng để khớp với N rồi. (Sự cố này cũng xuất hiện với các tệp nhị phân)

Điều này cần được giải quyết trong các bản phát hành sắp tới.

Tính đến phiên bản 17 this công trình:

-module(count_chars). 
-export([count_characters/1]). 

count_characters(Str) -> 
     count_characters(Str, #{}). 

%% maps module functions cannot be used as guards (release 17) 
%% or you'll get "illegal guard expression" error 
count_characters([H|T], X) -> 
    case maps:is_key(H,X) of 
     false -> count_characters(T, maps:put(H,1,X)); 
     true -> Count = maps:get(H,X), 
         count_characters(T, maps:update(H,Count+1,X)) 
    end; 
count_characters([], X) -> 
     X. 

Dưới đây là một phiên bản (chỉ thử nghiệm trên 18) đó là hơi tương tự như một trong những cuốn sách:

-module(count_chars). 
-export([count_characters/1]). 

count_characters(Str) -> 
     count_characters(Str, #{}). 

count_characters([H|T], X) -> 
    case maps:is_key(H,X) of 
     false -> count_characters(T, X#{ H => 1 }); 
     true -> #{ H := Count } = X, 
       count_characters(T, X#{ H := Count+1 }) 
    end; 
count_characters([], X) -> 
     X. 
+1

Vì (1) là trường hợp, cách viết mã này chính xác bằng cách sử dụng bản đồ trong 17.0 là gì? – JDong

-1

Vấn đề trong cú pháp phù hợp.

FOF trận đấu sử dụng :=. Ví dụ

test(#{ key := Test }) -> Test.

Và đối với liên quan chủ chốt và giá trị sử dụng =>. Ví dụ: M = #{ keynew => 123 }

+0

Vì vậy, làm thế nào để sửa mã? Tôi vừa thử phương pháp của bạn. Nhưng nó không hoạt động. – geeker

+0

Xin lỗi, tôi đã bỏ qua một khoảnh khắc. Nếu bạn sử dụng bản đồ, khóa không thể biến đổi, cần sử dụng như # {key => Value}. – saa

-1

Tôi đoán bạn đang sử dụng R17 vì tính năng này chỉ khả dụng từ phiên bản này.

nhìn vào một số tài liệu, hiểu biết của tôi là bạn nên viết mã theo cách đó (Tôi không thể kiểm tra nó, tôi vẫn đang sử dụng R15: o)

-module(map_demo). 
-export([count_characters/1]). 

count_characters(Str) -> 
count_characters(Str, #{}). 

count_characters([H|T], #{ H := N } = X) -> 
    count_characters(T, X#{ H := N+1 }); 
count_characters([H|T], X) -> 
    count_characters(T, X#{ H => 1}); 
count_characters([], X) -> 
    X. 
-2

-module (count_chars) .

%% API

-export ([count/1]).

count (Str) -> count_chars (Str, bản đồ: mới()).

count_chars ([H | T], Bản đồ) khi is_map (Bản đồ) ->

N = maps:get(H, Map, 0), 
count_chars(T, maps:put(H, N + 1, Map)); 

count_chars ([], Bản đồ) -> Bản đồ.

+0

Vui lòng giải thích những gì đã thay đổi để làm cho câu trả lời này hoạt động đúng. Chỉ cần cho mã không hỗ trợ trong việc làm rõ những gì đã sai ở nơi đầu tiên. – EWit

2

Quoted from OTP 17.0 Release Notes:

OTP-11.616 == Erts stdlib hipe dialyzer biên dịch typer ==

EEP43: New data type - Maps 

    With Maps you may for instance: 

    -- M0 = #{ a => 1, b => 2}, % create associations 

    -- M1 = M0#{ a := 10 }, % update values 

    -- M2 = M1#{ "hi" => "hello"}, % add new associations 

    -- #{ "hi" := V1, a := V2, b := V3} = M2. % match keys with 
    values 

    For information on how to use Maps please see the Reference 
    Manual. 

    The current implementation is without the following features: 

    -- No variable keys 

    -- No single value access 

    -- No map comprehensions 

    Note that Maps is experimental during OTP 17.0. 

Hiện nay bạn có thể sử dụng maps mô-đun để thực hiện count_characters:

count_characters(Str) -> 
    count_characters(Str, #{}). 

count_characters([H|T], X) -> 
    count_characters(T, maps:put(H, maps:get(H, X, 0) + 1, X)); 
count_characters([], X) -> 
    X. 
1

@EWit, Felipe Mafra:

bản đồ thực hiện những gì nó được cho là phải làm; những gì còn thiếu ở đây là phần giảm:

count(Str) -> M = count_chars(Str, maps:new()), % maps part, bad naming 
    L = maps:to_list(M),      % to be able to sum 
    N = [X || {_,X} <- L],      % strip the numbers 
    lists:sum(N).        % sum them up 

count_chars([H|T], Map) when is_map(Map)-> 
    N = maps:get(H, Map, 0), 
    count_chars(T, maps:put(H, N + 1, Map)); 
count_chars([], Map) -> Map. 
Các vấn đề liên quan