2009-07-12 31 views
35

Tôi có một vấn đề đơn giản nhưng bực mình trong Clojure, tôi có một hàm (gọi là hàm đọc) để chỉ ra người dùng muốn làm gì từ đầu vào của mình, sau đó gọi một hàm khác thực hiện điều đó (hãy gọi nó là chức năng hành động). Hàm hành động này gọi hàm đọc khi nó được thực hiện để người dùng có thể thực hiện một tác vụ khác.Thứ tự mã trong Clojure

Bây giờ vấn đề của tôi là nếu tôi đặt mã cho hàm đọc trước mã cho hàm hành động, tôi gặp lỗi trong hàm đọc nói rằng nó không biết hàm hành động là gì (vì mã cho nó là tiếp tục xuống) và nếu tôi làm ngược lại, tôi cũng nhận được một lỗi tương tự rõ ràng, nói rằng chức năng đọc không thể được giải quyết vv

Có cách nào đơn giản để sửa lỗi này?

Mã thực tế:

(defn ajout [botin] 
    (def botin botin) 
    (readCmd botin) 
) 

(defn readCmd [botin] 
    (println "Entrez une commande svp ") 
    (def botin botin) 
    (let [cmd (read-line)] 
    (if (.equals cmd "a") ((println "Ajout 8o") (ajout botin)) 
     (if (.equals cmd "e") ((println "Elim 8o") (eliminer botin)) 
     (if (.equals cmd "i") ((println "Imprim 8o") (imprimer botin)) 
      ((println "Commande invalide, nous vous rapellons que les commandes possibles sont : ") (print-les-cmd) (readCmd)))))) 


) 

như thế này, tôi nhận được một lỗi tại (readCmd Botín) dòng trong hàm ajout nói: Không thể giải quyết biểu tượng: readCmd trong bối cảnh này

Nếu Tôi đặt mã cho hai hàm này theo thứ tự ngược lại, tôi sẽ nhận được thông báo lỗi: Không thể giải quyết biểu tượng: ajout trong ngữ cảnh này

+0

Bạn có thể đăng một mẫu mã đơn giản của những gì không được làm việc. Điều đó sẽ giúp theo dõi vấn đề. – seth

+1

Tất nhiên ---- Mã Bắt đầu ---- (defn thêm [sách] (def đặt trong chức năng book) (readCmd cuốn sách-in-function) ) (defn readCmd [sách] (println "Enter cmd") (def book-in-function book) (cho [cmd (đọc)] (nếu (.equals cmd "add") ((println "Adding") (thêm cuốn sách-in chức năng)) (println "Dont know")) ) ) --- Mã End --- Nếu tôi đặt nó như thế này, tôi nhận được Không thể giải quyết biểu tượng : readCmd trong ngữ cảnh này tại dòng lệnh gọi-đọc trong hàm cộng Nếu tôi đặt hai hàm theo thứ tự ngược lại, tôi nhận được lỗi tương tự nhưng đối với hàm cộng trong hàm read-cmd – JoOb

+1

tôi có đã chỉnh sửa bài đăng gốc sau khi xem nhận xét như thế nào :) – JoOb

Trả lời

11

Ở đầu mã của bạn đặt:

(declare readCmd) 
58

Bạn có thể sử dụng các khai báo chuyển tiếp trong Clojure để bạn có thể gọi các hàm chưa được xác định.

(declare readCmd) 

sẽ hoạt động!

Trong Clojure, thứ tự mà bạn xác định hàm quan trọng, một hàm không thể gọi hàm khác (hoặc bất kỳ thứ gì cho vấn đề đó) chưa được xác định. Đó là lý do tại sao chúng tôi có các tờ khai chuyển tiếp.

+14

Haha, điều này nhắc tôi về C++ – wrongusername

+0

@wrongusername Và trình biên dịch đơn Pascal/Modula-2/Oberon. Thay đổi ça ... [Tuyên bố chuyển tiếp] (http://en.wikipedia.org/wiki/Forward_declaration) –

+3

Đây là một trong những điều tồi tệ nhất khi viết Clojure cho tôi. Tôi thích ngôn ngữ, nhưng có vẻ như điều này thêm bolilerplate không cần thiết. Trình biên dịch chỉ có thể làm điều này một cách ngầm định. – d11wtq

17

Khi những người khác đã trả lời, bạn cần phải (khai báo readCmd) để khắc phục vấn đề trước mắt của bạn.

Tuy nhiên, vẫn còn vấn đề với mã này, vì nó thực sự thực hiện quá trình lặp lại bằng cách sử dụng đệ quy lẫn nhau (readCmd -> ajout -> readCmd -> imprimer -> readCmd -> ...) sẽ tiêu thụ ngăn xếp và bạn sẽ nhận được (on) tràn ngăn xếp. Một cách tốt hơn để tổ chức này, sẽ làm cho readCmd tail đệ quy, và làm cho nó gọi các hành động. Khi một hành động trả về, readCmd đuôi đệ quy gọi chính nó.

Ngoài ra này đoạn mã:

((println "Ajout 8o") (ajout botin)) 

lẽ không phải là những gì bạn muốn làm: nó sẽ gọi println và sẽ cố gắng sử dụng kết quả như một hàm. Thay vào đó, hãy sử dụng "do":

(do (println "Ajout 8o") (ajout botin)) 

Bạn cũng có thể xem xét về trường hợp hoặc điều kiện, chúng sẽ đơn giản hóa các if lồng nhau.

Một điều kỳ lạ về mã của bạn là

(def botin botin) 

những gì nó là thế nào?

2

Có một sợi vào nhóm Clojure google về vấn đề này cung cấp một số cân nhắc thú vị, đặc biệt là về cách sử dụng các khai báo có thể đi lên một số công cụ trong hệ sinh thái:

thread

Tất nhiên, bạn có thể tranh luận rằng các công cụ tốt nên hoạt động với tất cả các cấu trúc của ngôn ngữ :)

IMO, bạn đã quen với phong cách từ dưới lên và chỉ đọc ngược lại. Đó là một câu chuyện khác mà bạn nói nơi bạn xây dựng mọi thứ thay vì phân hủy chúng.

Và tất nhiên, như những người khác đã nói, bạn có thể chuyển tiếp tuyên bố với

(declare my-function) 
Các vấn đề liên quan