2010-09-06 21 views
9

Gần đây tôi đã cho Scala một cơ hội thứ hai, và bắt đầu với dự án tôi luôn thực hiện (bằng ngôn ngữ chức năng hoặc giả): một lý do tự động cho logic mệnh đề (và sau này là logic vị ngữ).Scala - Prefix Unary Operators

Bây giờ, tôi đã cố gắng để có được những ký hiệu của logic mệnh đề bằng ngôn ngữ riêng của mình như khá càng tốt, và tôi đã nhận được điều này đến nay - với một chuyển đổi ngầm (String -> Atom):

("A" and "B") implies "C" 

Các hàm "và" và "ngụ ý" (và "hoặc" và "tương đương") là các phương thức đơn giản gọi hàm tạo lớp có liên quan. Tuy nhiên, khi thực hiện "không", tôi gặp khó khăn với một trong hai ký hiệu sau:

("A" and "B").not 
Not("A" and "B") 

Có cách nào để lừa Scala vào chấp nhận mong muốn:

not("A" and "B") 

Ưu tiên sử dụng mà không cần đổi tên lớp "Không" để "không", bởi vì tôi có thể muốn gọi nó là "¬" hoặc cái gì khác, trong tương lai.

Trả lời

4

Kể từ tháng 2 năm 2014, tôi nghĩ cách sạch nhất để xác định tiền tố not hoạt động trên biểu thức, trong khi tránh tất cả các loại bổ sung/gói, sẽ khai báo chức năng trực tiếp trong phạm vi gói. các hàm, lớp, kiểu khác của bạn vv: Điều này được thực hiện bằng cách định nghĩa một đối tượng gói (Scala không cho phép bạn chỉ đặt các hàm ở cấp cơ sở của tệp .scala (tôi rất muốn tìm hiểu tại sao) Bước chân của Java?)).

package org.my.logiclib 

implicit class Atom(s: String) { ... } 
class MyType1 
class MyType2 

object `package` { 
    def not(expr: Expr) = ... 
} 

theo cách này, làm import org.my.logiclib._ sẽ nhập mọi thứ, bao gồm not().

Trên đây là giống như

package org.my 

package logiclib { 
    implicit class Atom ... 
    ... 

    def not(expr: Expr) = ... 
} 
14

Bạn có thể xác định not như một phương thức trên một đối tượng singleton, như thế này:

object Logic { 
    def not(x:Expr) = Not(x) 
} 
import Logic._ 
not("A" and "B") 

(Trong trường hợp Expr được coi là lớp cha chung của And, Or, NotAtom)

Sửa : Dưới đây là ví dụ về cách sử dụng điều này chỉ với một lần nhập:

object Logic { 
    abstract class Expr { 
    def and(e: Expr) = Conjunction(this, e) 
    def or(e: Expr) = Disjunction(this, e) 
    def implies(e: Expr) = Implication(this, e) 
    } 
    case class Conjunction(e1: Expr, e2: Expr) extends Expr 
    case class Disjunction(e1: Expr, e2: Expr) extends Expr 
    case class Implication(e1: Expr, e2: Expr) extends Expr 
    case class Negation(e: Expr) extends Expr 
    case class Atom(name: String) extends Expr 

    def not(e: Expr) = Negation(e) 
    implicit def string2atom(str: String) = Atom(str) 
} 

// use site 
import Logic._ 
not("A" and "B") implies (not("A") or not("B")) 
+0

Cảm ơn, tôi không biết tôi có thể sử dụng "hàng nhập khẩu tĩnh" trong Scala - điều này sẽ để lại cho tôi với một khẩu bắt buộc trên mỗi trang, tuy nhiên, đó - cùng với chuyển đổi tiềm ẩn sẽ có nhiều mã bổ sung cho mỗi lần sử dụng. – wen

+2

@Dennetik: Nếu bạn chỉ cần đặt mọi thứ vào đối tượng Logic, 'import Logic._' là tất cả những gì bạn cần để sử dụng các lớp của bạn. – sepp2k

+1

Đã không nghĩ về điều đó, tôi vẫn phải làm quen với sự tự do của Scala, so với Java ... – wen

19

Tôi nhận thấy trên this answer cho một câu hỏi khác có vẻ như người ta có thể đặt tiền tố tên nhà điều hành với unary_ để đạt được những gì bạn đang cố gắng làm. (Xem unary_!.)

Chỉnh sửa: this article xác nhận cú pháp.

+1

Điều đó không hoạt động với tên nhà điều hành tùy chỉnh. I E. bạn không thể xác định 'unary_not' để nhận tiền tố" not "-operator. – sepp2k

+16

Cụ thể 'prefix_' chỉ hoạt động với'! ',' ~ ',' + 'Và' -'. – sepp2k

+1

@ sepp2k: Cảm ơn, đã không nhận ra điều này phụ thuộc. Hạn chế này có vẻ hơi xấu hổ (và hoàn toàn tùy ý). –

8

Tại sao Not thay vì not? Không có gì ngăn bạn làm việc này:

object not { 
    def apply(expr: T) = ... 
} 

Và sau đó sử dụng not("A" and "B").

+0

tại sao tất cả mọi người luôn tìm cách đưa xung quanh các hàm trực tiếp vào các gói bằng cách sử dụng các đối tượng gói ... –

+1

@ErikAllik Bởi vì trong năm 2010 không có các đối tượng gói. –

+0

Điểm tốt! Không nhận ra điều đó — Cảm ơn :) P.S. Tuy nhiên, bạn sẽ sử dụng một ngày hôm nay để xác định 'không (expr: T)'? –