2009-09-27 13 views
68

Gdzie mogę znaleźć listę "magicznych" funkcji Scali, takich jak apply, unapply, update, += itp.?Lista "magicznych" funkcji Scala

Dzięki funkcji Magic-mam na myśli funkcje, które są używane przez niektóre składniowej cukru kompilatora, na przykład

o.update(x,y) <=> o(x) = y 

google dla niektórych kombinacji scalamagic i synonimów functions, ale nie mogę znaleźć byle co.

Nie interesuje mnie użycie magicznych funkcji w bibliotece standardowej, ale w których istnieją funkcje magiczne.

Odpowiedz

71

O ile wiem:

pobierające/ustawiaczy związane:

apply 
update 
identifier_= 

dopasowanie Wzór:

unapply 
unapplySeq 

For-listowe:

map 
flatMap 
filter 
withFilter 
foreach 

prefiksem operatora:

unary_+ 
unary_- 
unary_! 
unary_~ 

Poza tym, każda niejawne z A do B. Scala również konwertować A <op>= B do A = A <op> B, w pierwszym przypadku operator nie określono „OP” nie alfanumeryczne i <op>= nie !=, ==, <= lub >=.

I nie sądzę, żeby istniało jedno miejsce, w którym wymieniono wszystkie cukry syntaktyczne Scali.

+2

Możesz chcieć dodać unary_! itp. operatorzy, którzy znaleźli się w jednym z pozostałych postów, ponieważ wygląda to na najbardziej wyczerpującą odpowiedź na to pytanie :) – Calum

+1

... i zrobiliście to, dzięki! – Calum

+1

Co to jest 'identifier_ ='? Nigdy tego nie widziałem. –

3

Są one zdefiniowane w specyfikacji języka Scala. O ile mi wiadomo, istnieją tylko trzy "magiczne" funkcje, o których wspomniałeś.

Scalas Getter i Setter może również odnosić się do swojej „magii”:

scala> class Magic { 
|  private var x :Int = _ 
|  override def toString = "Magic(%d)".format(x) 
|  def member = x 
|  def member_=(m :Int){ x = m } 
| } 

defined class Magic 

scala> val m = new Magic 

m: Magic = Magic(0) 

scala> m.member 

res14: Int = 0 

scala> m.member = 100 

scala> m 

res15: Magic = Magic(100) 

scala> m.member += 99 

scala> m 

res17: Magic = Magic(199) 
+0

Jeśli można kopać dla mnie dowody dla tego roszczenia, będziesz odpowiadając na moje pytanie ;-) Przypuszczałem, że to będzie w specyfikacji, ale znalezienie ich nie jest zabawną robotą. –

+2

Scala Język Specyfikacja: 6,15 Zadania ... Jeśli x jest funkcja bez parametrów określony w jakiegoś szablonu, a tym samym szablonie zawiera x_ = function seter jako członka, następnie przypisanie x = e jest interpretowany jako inwokacji x _ = (e) tej funkcji ustawiającej . Analogicznie, przypisanie f .x = e do funkcji bez parametrów x to interpretowane jako wywołanie f .x _ = (e). Przypisanie f (args) = e z aplikacją funkcji po lewej stronie operatora "=" interpretowane jest jako f .update (args, e), tj. Wywołanie funkcji aktualizacji zdefiniowanej przez f. – Eastsun

+0

I ment, dowód, że już nie ma. –

15

Oprócz update i apply, istnieje również szereg operatorów jednoargumentowych który (wierzę) kwalifikuje się jako magiczne:

  • unary_+
  • unary_-
  • unary_!
  • unary_~

Dodajmy do tego regularne operatorzy infix/sufiksu (który może być prawie wszystko) i masz sobie pełny pakiet.

Naprawdę powinieneś rzucić okiem na specyfikację języka Scala. Jest to jedyne autorytatywne źródło tych materiałów. Nie jest to trudne do odczytania (o ile dobrze ci radzi z gramatykami bezkontekstowymi) i bardzo łatwe do przeszukiwania. Jedyne, czego nie określa dobrze, to obsługa XML.

10

Przepraszam, jeśli to nie jest dokładnie odpowiedź na twoje pytanie, ale moim ulubionym momentem WTF do tej pory jest @ jako operator przydziału w dopasowaniu wzorca. Dzięki miękkiej kopii "Programowania w Scali" dowiedziałem się, co to było dość szybko.

Za pomocą @ możemy powiązać dowolną część wzoru ze zmienną, a jeśli dopasowanie wzorca się powiedzie, zmienna przechwyci wartość pod-wzoru. Oto przykład z Programowanie w Scala (rozdział 15.2 - Zmienna Binding):

expr match { 
    case UnOp("abs", e @ UnOp("abs", _)) => e 
    case _ => 
} 

Jeśli uda cały mecz wzór, to część, która odpowiadała UnOp ("ABS", _) część jest udostępniany jako jako zmienna e.

I here „s co programowania Scala mówi o tym.

+0

Czy możesz podzielić się z nami tym, co robi operator @? –

+0

Tak, właśnie zredagowałem moją odpowiedź :-) – Yardena

2

będę również dodać _* dla dopasowywania wzoru na dowolną liczbę parametrów jak

case x: A(_*) 

I operator asocjatywności reguły od Odersky łyżka-Venners książki:

Zależność operatora od Scala jest określona przez jego ostatni znak . Jak wspomniano w < ...>, każda metoda, która kończy się w znaku ":" jest wywoływana na jego prawym operandzie, przekazując w lewym operandzie . Metody, które kończą się na jakikolwiek inny znak, są inne. Są wywoływane na lewym operandzie, przechodząc w prawym operandzie . Tak więc * b daje a. * (B), ale a ::: b daje b.:::(a).


Może powinniśmy również wspomnieć składniowej desugaring z do wyrażenia które można znaleźć here


oraz (oczywiście!), alternatywną składnię dla par

a -> b //converted to (a, b), where a and b are instances 

(jako poprawnie po inted się, ten jest po prostu niejawna konwersja odbywa się za pośrednictwem biblioteki, więc to chyba nie kwalifikuje, ale uważam, że jest to wspólny układanka dla początkujących)


+1

IIRC '->' jest po prostu funkcją biblioteczną. –

2

Chciałbym dodać, że istnieje również "magiczna" cecha - scala.Dynamic:

Cecha znacznika, która umożliwia dynamiczne wywoływanie.Instancje x tej cechy umożliwiają wywoływanie metod x.meth(args) dla dowolnych nazw metod meth i list argumentów o nazwach args, a także o dostępach do pól x.field dla dowolnych nazw pól field.

Jeśli połączenie nie jest natywnie obsługiwany przez x (czyli jeśli typ sprawdzania nie), to przepisany zgodnie z następującymi zasadami:

foo.method("blah")  ~~> foo.applyDynamic("method")("blah") 
foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah")) 
foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2)) 
foo.field   ~~> foo.selectDynamic("field") 
foo.varia = 10  ~~> foo.updateDynamic("varia")(10) 
foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13) 
foo.arr(10)   ~~> foo.applyDynamic("arr")(10) 

Jak Scala 2.10, określające bezpośrednie lub pośrednie podklasy tej cechy jest możliwe tylko wtedy, gdy włączona jest dynamika cech językowych.

Więc można zrobić rzeczy jak

import scala.language.dynamics 

object Dyn extends Dynamic { 
    def applyDynamic(name: String)(a1: Int, a2: String) { 
    println("Invoked " + name + " on (" + a1 + "," + a2 + ")"); 
    } 
} 

Dyn.foo(3, "x"); 
Dyn.bar(3, "y"); 
+0

Link nie działa. Czy możesz aktualizować? – Jus12