Ergebnis 1 bis 16 von 16

Thema: Erweiterte For-Schleife mit Index - III

  1. #1
    User Halbes Megabyte Themenstarter

    Registriert seit
    28.08.2008
    Fachbeiträge
    575
    Genannt
    0 Post(s)
    Man könnte angesichts der beiden Vorgänger-Beiträge vielleicht denken, dass das das Beste wäre, was man aktuell mit Java hinbekommt. Aber es heißt ja...
    Zum Blog-Eintrag

  2. #2
    User short
    Registriert seit
    26.08.2014
    Ort
    Dresden (ganz in der Nähe)
    Fachbeiträge
    21
    Genannt
    8 Post(s)
    Blog-Einträge
    1
    Bei der Verwendung geht es für dieses Beispiel noch ein wenig kürzer mit 'name' anstatt 'names.get(i)'.

  3. #3
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Danke, das war ein Copy-Paste-Fehler, hab's korrigiert.

  4. #4
    Global Moderator Viertel Gigabyte
    Registriert seit
    05.08.2008
    Fachbeiträge
    4.901
    Genannt
    307 Post(s)
    Besser:
    Java Code:
    1.  
    2. public static <A> void indexed2(Iterable<? extends A> iterable, BiConsumer<? super A, Integer> consumer)
    sonst
    Java Code:
    1.  
    2.         List<Number> numbers = Arrays.asList(1, 2, 3);
    3.         List<? extends Number> extendedNumbers = Arrays.asList(1, 2, 3);
    4.        
    5.         BiConsumer<Number, Integer> consumerA = null;
    6.         BiConsumer<Object, Integer> consumerB = null;
    7.        
    8.         For.indexed(numbers, consumerA);
    9.         //For.indexed(numbers, consumerB); // Geht nicht
    10.  
    11.         //For.indexed(extendedNumbers, consumerA); // Geht nicht
    12.         //For.indexed(extendedNumbers, consumerB); // Geht nicht
    13.        
    14.         // Geht alles:
    15.         For.indexed2(numbers, consumerA);
    16.         For.indexed2(numbers, consumerB);
    17.  
    18.         For.indexed2(extendedNumbers, consumerA);
    19.         For.indexed2(extendedNumbers, consumerB);

    (wird manchmal als "PECS" bezeichnet: Producer extends, Consumer super)

  5. Es bedanken sich:
    nillehammer (25.05.2016)
  6. #5
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Stimmt.

    OT: Ich finde es so doof, dass man in Java die Varianzen nicht wie bei Scala bei der Definition angeben kann, dann gäbe es solche Probleme bei der Benutzung erst gar nicht.

  7. #6
    Global Moderator Viertel Gigabyte
    Registriert seit
    05.08.2008
    Fachbeiträge
    4.901
    Genannt
    307 Post(s)
    Für mich ist das zwar "Varianzen bei der Definition angeben", aber ... demnach meinst du offenbar was anderes....

    EDIT @nillehammer Hähsowas, jetzt hab' ich tatsächlich nachgeschaut: Mir wäre nicht bewußt gewesen, dass es ObjIntConsumer gibt....

  8. #7
    Frequent User Halbes Megabyte
    Registriert seit
    31.07.2013
    Ort
    Hamburg
    Fachbeiträge
    550
    Genannt
    56 Post(s)
    Blog-Einträge
    2
    Zitat Zitat von Marco13 Beitrag anzeigen
    EDIT
    @nillehammer
    Hähsowas, jetzt hab' ich tatsächlich nachgeschaut: Mir wäre nicht bewußt gewesen, dass es ObjIntConsumer gibt....
    Wenn's um Primitives geht, muss ich auch jedes mal in java.util.function nachschauen, was dort so definiert ist. Wir Primitiven werden halt immer stiefmütterlich behandelt

  9. #8
    Global Moderator Viertel Gigabyte Avatar von SlaterB
    Registriert seit
    06.08.2008
    Fachbeiträge
    2.695
    Genannt
    275 Post(s)
    'EDIT @nillehammer ' bezieht sich also auf einen Kommentar im Blog-Eintrag..,
    meine grenzenlose Intelligenz hat es erfasst , allgemein reichlich unkenntlich hier,

    Zitieren schadet dazu nicht, geht natürlich im Blog nicht, aber manuell:
    nillehammer - Gestern 16:29

    Anstatt des Biconsumer<A, Integer> nimm besser einen ObjIntConsumer<? super A>. Dann sparst Du Dir das Autoboxing.

    das Blog-System mit diesen RSS Reader-Themen und dann Kommentaren hier ist reichlich buggy,
    wahrscheinlich besser die Themen hier gleich zu sperren,
    andererseits niemand zu verdenken lieber hier zu posten als in irgendwelchen komischen Blogs unbekannter Sichtbarkeit..
    Hansa wird Meister

  10. #9
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Zitat Zitat von Marco13 Beitrag anzeigen
    Für mich ist das zwar "Varianzen bei der Definition angeben", aber ... demnach meinst du offenbar was anderes....
    In Scala kannst du bei der Klassendefinition Foo[+A] bzw Foo[-A] schreiben. Damit signalisierst du, dass ein Foo[B] auch als ein Foo[A] verwendet werden kann, wenn B eine Sub- bzw. Superklasse von A ist. Siehe Variances - Scala Documentation

  11. #10
    Global Moderator Viertel Gigabyte Avatar von SlaterB
    Registriert seit
    06.08.2008
    Fachbeiträge
    2.695
    Genannt
    275 Post(s)
    wie würde das hier helfen?

    aktueller Stand ist
    public static <A> void indexed(Iterable<? extends A> iterable, ObjIntConsumer<? super A> consumer) {

    ist hier eigentlich das ? super nicht verzichtbar?
    welcher Einsatzzweck ist damit abzudecken?

    für alle vier Beispiele von Marco13 (bzw. die drei die vorher nicht gingen) reicht ja wohl
    public static <A> void indexed(Iterable<? extends A> iterable, ObjIntConsumer<A> consumer) {
    der ObjIntConsumer bzw. vormals BiConsumer ist fest, will Number oder eben Object sehen

    interessant ist, ob man mit Object-ObjIntConsumer eine Number-Liste durchlaufen kann, oder mit beiden eine extends-Liste

    -------

    wie würde nun Variances helfen? wäre das Interface Iterable zu ändern, damit alle Listen/ Collections in Java?
    klingt ein bisschen heftig,
    welche Auswirkungen hätte es?
    Java Code:
    1.         List<String> names = Arrays.asList("Heinz", "Peter", "Marie");
    2.         List<Object> o = names;
    3.         List<? extends Object> o2 = names;
    dass die o-Definition nicht geht ist ja ein Glück, o2 geht auch jetzt schon


    lieber doch nur diese eine Methode so variabel halten?
    wie ließe sich dann diese Methode mit etwas a la Variances anders schreiben?
    Hansa wird Meister

  12. #11
    Frequent User Halbes Megabyte
    Registriert seit
    31.07.2013
    Ort
    Hamburg
    Fachbeiträge
    550
    Genannt
    56 Post(s)
    Blog-Einträge
    2
    Zitat Zitat von SlaterB Beitrag anzeigen
    ist hier eigentlich das ? super nicht verzichtbar?
    welcher Einsatzzweck ist damit abzudecken?
    Meist ja, manchmal nein. Wenn Du bspw. eine List<Student> bearbeitest, müsste ohne "? super" ein ObjIntConsumer<Student> übergeben werden. Übergibst Du hier einen Lambda-Ausdruck, bspw.
    Code:
    (obj, index) -> System.out.println(index + " " + obj);
    dann ist es kein Problem. Obwohl der Lamda-Ausruck eigentlich ein ObjIntConsumer<Object> ist, wird er einfach als ObjIntConsumer<Student> genommen, weil's passt. Das klappt sogar mit Methodenreferenzen (void accept(Object, int) ). Wenn Du allerdings den Lambda-Ausdruck (oder Methodenreferenz) einer Variablen mit explizit deklariertem Typ ObjectIntConsumer<Object> zuweist und dann versuchst, die Variable zu übergeben, dann braucht es "? super".
    Geändert von nillehammer (25.05.2016 um 11:21 Uhr)

  13. #12
    Global Moderator Viertel Gigabyte Avatar von SlaterB
    Registriert seit
    06.08.2008
    Fachbeiträge
    2.695
    Genannt
    275 Post(s)
    das sind ja nun in etwa die Beispiele von Marco13, also schon behandelt,
    wie gesagt geht das doch alles allein mit ? extends?

    interessanterweise allein mit dem ? super auch:
    Java Code:
    1. public class Test2 {
    2.     public static void main(String[] args)   {
    3.         List<Number> numbers = Arrays.asList(1, 2, 3);
    4.         List<? extends Number> extendedNumbers = Arrays.asList(1, 2, 3);
    5.         ObjIntConsumer<Number> consumerA = null;
    6.         ObjIntConsumer<Object> consumerB = null;
    7.        
    8.         For.indexedExtends(numbers, consumerA); // alle 4 gehen
    9.         For.indexedExtends(numbers, consumerB);
    10.         For.indexedExtends(extendedNumbers, consumerA);
    11.         For.indexedExtends(extendedNumbers, consumerB);
    12.        
    13.         For.indexedSuper(numbers, consumerA);  // alle 4 gehen
    14.         For.indexedSuper(numbers, consumerB);
    15.         For.indexedSuper(extendedNumbers, consumerA);
    16.         For.indexedSuper(extendedNumbers, consumerB);  
    17.     }
    18. }
    19.  
    20. class For {
    21.     public static <A>void indexedExtends(Iterable<? extends A> iterable, ObjIntConsumer<A> consumer)  {
    22.         int index = 0;
    23.         for (A a : iterable)   {
    24.             consumer.accept(a, index++);
    25.         }
    26.     }
    27.    
    28.     public static <A>void indexedSuper(Iterable<A> iterable, ObjIntConsumer<? super A> consumer)  {
    29.         int index = 0;
    30.         for (A a : iterable)    {
    31.             consumer.accept(a, index++);
    32.         }
    33.     }
    34. }
    aber die Tooltips zu den gefundenen Typen für die indexedSuper-Variante mit teils ? super ? extends Number sind ja reichlich abenteuerlich, siehe Screenshot

    für die indexedExtends-Variante ist es nüchtern ehrlich korrekt: entweder wird zu Number oder Object aufgelöst, je nachdem wie es passt,
    der ObjIntConsumer steht fest und gibt den Typ vor, Iterable passt sich mit ? extends an, reicht?
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken Erweiterte For-Schleife mit Index - III-screen1.png  
    Geändert von SlaterB (25.05.2016 um 11:38 Uhr)
    Hansa wird Meister

  14. #13
    Global Moderator Viertel Gigabyte
    Registriert seit
    05.08.2008
    Fachbeiträge
    4.901
    Genannt
    307 Post(s)
    Zitat Zitat von Landei Beitrag anzeigen
    In Scala kannst du bei der Klassendefinition Foo[+A] bzw Foo[-A] schreiben. Damit signalisierst du, dass ein Foo[B] auch als ein Foo[A] verwendet werden kann, wenn B eine Sub- bzw. Superklasse von A ist. Siehe Variances - Scala Documentation
    Daran hatte ich mich noch dunkel erinnert. Aber ob diese Varianzen nun auf Klassen- oder Methodenebene festgetacktert werden erscheint mir erstmal nur wie eine Frage nach der Granularität - konzeptuell ("Typtheoretisch") sehe ich keinen so großen Unterschied.

    Zitat Zitat von SlaterB Beitrag anzeigen
    ist hier eigentlich das ? super nicht verzichtbar?
    welcher Einsatzzweck ist damit abzudecken?
    Zitat Zitat von nillehammer Beitrag anzeigen
    Meist ja, manchmal nein. Wenn Du bspw. eine List<Student> bearbeitest, müsste ohne "? super" ein ObjIntConsumer<Student> übergeben werden.
    Es ist verzichtbar. Auch bei dem "Student"-Beispiel würde ohne das ? super der Typ A auf "Student" festgelegt, und die potentielle Freiheit (auch wenn es sie im konkreten Fall nicht gibt) über das extends A abgehandelt. Man hat, etwas verallgemeinert, die Wahl zwischen
    Java Code:
    1.  
    2. static void <A> process(Producer<A> p, Consumer<A> c)
    3. static void <A> process(Producer<A> p, Consumer<? super A> c)
    4. static void <A> process(Producer<? extends A> p, Consumer<A> c)
    5. static void <A> process(Producer<? extends A> p, Consumer<? super A> c)
    Und wenn man den Typ "A" nicht händisch festlegt (mit sowas wie Methods.<SomeType>process(p,c);), dann sind die letzten drei gleichwertig*: In allen Fällen gibt man eine Untere und eine Obere Grenze vor, zwischen der der Compiler den Typ "A" einordnen darf. Der Unterschied ist lediglich, ob diese Grenzen "Inklusiv" oder "Exklusiv" sind.

    *:
    Echt gleichwertig?

    Es gibt zumindest keinen Fall, wo nur EINER der letzten drei hier in Eclipse rot aufleuchtet:
    Java Code:
    1.  
    2. package bytewelt;
    3.  
    4.  
    5. class Producer<T>
    6. {
    7.     T produce()
    8.     {
    9.         return null;
    10.     }
    11. }
    12. class Consumer<T>
    13. {
    14.     void consumer(T t)
    15.     {
    16.        
    17.     }
    18. }
    19.  
    20. public class ProducerConsumerVariances
    21. {
    22.     Producer<Object> po = null;
    23.     Producer<Number> pn = null;
    24.     Producer<Integer> pi = null;
    25.    
    26.     Producer<? extends Object> peo = null;
    27.     Producer<? extends Number> pen = null;
    28.     Producer<? extends Integer> pei = null;
    29.  
    30.     Consumer<Object> co = null;
    31.     Consumer<Number> cn = null;
    32.     Consumer<Integer> ci = null;
    33.    
    34.     Consumer<? super Object> cso = null;
    35.     Consumer<? super Number> csn = null;
    36.     Consumer<? super Integer> csi = null;
    37.    
    38.     void objectProducerObjectConsumer()
    39.     {
    40.         processA(po, co);
    41.         processB(po, co);
    42.         processC(po, co);
    43.         processD(po, co);
    44.     }
    45.     void numberProducerObjectConsumer()
    46.     {
    47.         processA(pn, co);
    48.         processB(pn, co);
    49.         processC(pn, co);
    50.         processD(pn, co);
    51.     }
    52.     void integerProducerObjectConsumer()
    53.     {
    54.         processA(pi, co);
    55.         processB(pi, co);
    56.         processC(pi, co);
    57.         processD(pi, co);
    58.     }
    59.    
    60.     void objectProducerNumberConsumer()
    61.     {
    62.         processA(po, cn);
    63.         processB(po, cn);
    64.         processC(po, cn);
    65.         processD(po, cn);
    66.     }
    67.     void numberProducerNumberConsumer()
    68.     {
    69.         processA(pn, cn);
    70.         processB(pn, cn);
    71.         processC(pn, cn);
    72.         processD(pn, cn);
    73.     }
    74.     void integerProducerNumberConsumer()
    75.     {
    76.         processA(pi, cn);
    77.         processB(pi, cn);
    78.         processC(pi, cn);
    79.         processD(pi, cn);
    80.     }
    81.        
    82.     void objectProducerIntegerConsumer()
    83.     {
    84.         processA(po, ci);
    85.         processB(po, ci);
    86.         processC(po, ci);
    87.         processD(po, ci);
    88.     }
    89.     void numberProducerIntegerConsumer()
    90.     {
    91.         processA(pn, ci);
    92.         processB(pn, ci);
    93.         processC(pn, ci);
    94.         processD(pn, ci);
    95.     }
    96.     void integerProducerIntegerConsumer()
    97.     {
    98.         processA(pi, ci);
    99.         processB(pi, ci);
    100.         processC(pi, ci);
    101.         processD(pi, ci);
    102.     }
    103.        
    104.     void extendsObjectProducerObjectConsumer()
    105.     {
    106.         processA(peo, co);
    107.         processB(peo, co);
    108.         processC(peo, co);
    109.         processD(peo, co);
    110.     }
    111.     void extendsNumberProducerObjectConsumer()
    112.     {
    113.         processA(pen, co);
    114.         processB(pen, co);
    115.         processC(pen, co);
    116.         processD(pen, co);
    117.     }
    118.     void extendsIntegerProducerObjectConsumer()
    119.     {
    120.         processA(pei, co);
    121.         processB(pei, co);
    122.         processC(pei, co);
    123.         processD(pei, co);
    124.     }
    125.  
    126.     void extendsObjectProducerNumberConsumer()
    127.     {
    128.         processA(peo, cn);
    129.         processB(peo, cn);
    130.         processC(peo, cn);
    131.         processD(peo, cn);
    132.     }
    133.     void extendsNumberProducerNumberConsumer()
    134.     {
    135.         processA(pen, cn);
    136.         processB(pen, cn);
    137.         processC(pen, cn);
    138.         processD(pen, cn);
    139.     }
    140.     void extendsIntegerProducerNumberConsumer()
    141.     {
    142.         processA(pei, cn);
    143.         processB(pei, cn);
    144.         processC(pei, cn);
    145.         processD(pei, cn);
    146.     }
    147.  
    148.     void extendsObjectProducerIntegerConsumer()
    149.     {
    150.         processA(peo, ci);
    151.         processB(peo, ci);
    152.         processC(peo, ci);
    153.         processD(peo, ci);
    154.     }
    155.     void extendsNumberProducerIntegerConsumer()
    156.     {
    157.         processA(pen, ci);
    158.         processB(pen, ci);
    159.         processC(pen, ci);
    160.         processD(pen, ci);
    161.     }
    162.     void extendsIntegerProducerIntegerConsumer()
    163.     {
    164.         processA(pei, ci);
    165.         processB(pei, ci);
    166.         processC(pei, ci);
    167.         processD(pei, ci);
    168.     }
    169.    
    170.     void objectProducerSuperObjectConsumer()
    171.     {
    172.         processA(po, cso);
    173.         processB(po, cso);
    174.         processC(po, cso);
    175.         processD(po, cso);
    176.     }
    177.     void numberProducerSuperObjectConsumer()
    178.     {
    179.         processA(pn, cso);
    180.         processB(pn, cso);
    181.         processC(pn, cso);
    182.         processD(pn, cso);
    183.     }
    184.     void integerProducerSuperObjectConsumer()
    185.     {
    186.         processA(pi, cso);
    187.         processB(pi, cso);
    188.         processC(pi, cso);
    189.         processD(pi, cso);
    190.     }
    191.  
    192.     void objectProducerSuperNumberConsumer()
    193.     {
    194.         processA(po, csn);
    195.         processB(po, csn);
    196.         processC(po, csn);
    197.         processD(po, csn);
    198.     }
    199.     void numberProducerSuperNumberConsumer()
    200.     {
    201.         processA(pn, csn);
    202.         processB(pn, csn);
    203.         processC(pn, csn);
    204.         processD(pn, csn);
    205.     }
    206.     void integerProducerSuperNumberConsumer()
    207.     {
    208.         processA(pi, csn);
    209.         processB(pi, csn);
    210.         processC(pi, csn);
    211.         processD(pi, csn);
    212.     }
    213.  
    214.     void objectProducerSuperIntegerConsumer()
    215.     {
    216.         processA(po, csi);
    217.         processB(po, csi);
    218.         processC(po, csi);
    219.         processD(po, csi);
    220.     }
    221.     void numberProducerSuperIntegerConsumer()
    222.     {
    223.         processA(pn, csi);
    224.         processB(pn, csi);
    225.         processC(pn, csi);
    226.         processD(pn, csi);
    227.     }
    228.     void integerProducerSuperIntegerConsumer()
    229.     {
    230.         processA(pi, csi);
    231.         processB(pi, csi);
    232.         processC(pi, csi);
    233.         processD(pi, csi);
    234.     }
    235.    
    236.  
    237.  
    238.     void extendsObjectProducerSuperObjectConsumer()
    239.     {
    240.         processA(peo, cso);
    241.         processB(peo, cso);
    242.         processC(peo, cso);
    243.         processD(peo, cso);
    244.     }
    245.     void extendsNumberProducerSuperObjectConsumer()
    246.     {
    247.         processA(pen, cso);
    248.         processB(pen, cso);
    249.         processC(pen, cso);
    250.         processD(pen, cso);
    251.     }
    252.     void extendsIntegerProducerSuperObjectConsumer()
    253.     {
    254.         processA(pei, cso);
    255.         processB(pei, cso);
    256.         processC(pei, cso);
    257.         processD(pei, cso);
    258.     }
    259.  
    260.     void extendsObjectProducerSuperNumberConsumer()
    261.     {
    262.         processA(peo, csn);
    263.         processB(peo, csn);
    264.         processC(peo, csn);
    265.         processD(peo, csn);
    266.     }
    267.     void extendsNumberProducerSuperNumberConsumer()
    268.     {
    269.         processA(pen, csn);
    270.         processB(pen, csn);
    271.         processC(pen, csn);
    272.         processD(pen, csn);
    273.     }
    274.     void extendsIntegerProducerSuperNumberConsumer()
    275.     {
    276.         processA(pei, csn);
    277.         processB(pei, csn);
    278.         processC(pei, csn);
    279.         processD(pei, csn);
    280.     }
    281.  
    282.     void extendsObjectProducerSuperIntegerConsumer()
    283.     {
    284.         processA(peo, csi);
    285.         processB(peo, csi);
    286.         processC(peo, csi);
    287.         processD(peo, csi);
    288.     }
    289.     void extendsNumberProducerSuperIntegerConsumer()
    290.     {
    291.         processA(pen, csi);
    292.         processB(pen, csi);
    293.         processC(pen, csi);
    294.         processD(pen, csi);
    295.     }
    296.     void extendsIntegerProducerSuperIntegerConsumer()
    297.     {
    298.         processA(pei, csi);
    299.         processB(pei, csi);
    300.         processC(pei, csi);
    301.         processD(pei, csi);
    302.     }
    303.  
    304.  
    305.     public static <T> void processA(Producer<T> p, Consumer<T> c)
    306.     {
    307.         c.consumer(p.produce());
    308.     }
    309.     public static <T> void processB(Producer<? extends T> p, Consumer<T> c)
    310.     {
    311.         c.consumer(p.produce());
    312.     }
    313.     public static <T> void processC(Producer<T> p, Consumer<? super T> c)
    314.     {
    315.         c.consumer(p.produce());
    316.     }
    317.     public static <T> void processD(Producer<? extends T> p, Consumer<? super T> c)
    318.     {
    319.         c.consumer(p.produce());
    320.     }
    321.  
    322. }



    Der Grund, warum ich das ? super trotzdem hinschreiben würde, ist "Konsistenz", "Konsequenz", "Klarheit". Man könnte es formulieren als "Weil das laut PECS** eben so sein sollte", aber ich denke, dass es wirklich hilft, die Intention (bzw. das nicht-Vorhandensein einer speziellen Typanforderung) auszudrücken.

    ** Da der "Producer" in Java eigentlich "Supplier" heißt, müßte das eigentlich "SECS" heißen. Hihihi.

  15. #14
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Zitat Zitat von Marco13 Beitrag anzeigen
    Daran hatte ich mich noch dunkel erinnert. Aber ob diese Varianzen nun auf Klassen- oder Methodenebene festgetacktert werden erscheint mir erstmal nur wie eine Frage nach der Granularität - konzeptuell ("Typtheoretisch") sehe ich keinen so großen Unterschied.
    Der Unterschied ist, ob ich einmal (wie in Scala) bei der Definition sage: "Hier kann X oder eine Unterklasse von X kommen", oder jedesmal (über Wildcards), wenn ich die Klasse benutze.

    Zumal typtheoretisch die Art der Nutzung fast immer feststeht. Wenn z.B. irgendwo einmal Bla extends Comparator<? extends Bla> steht, ist das schlichtweg falsch, es gibt dafür keinen sinnvollen Anwendungsfall. Deshalb ist es sinnvoll, z.B. Comparator ein für allemal als contravariant zu definieren.
    Geändert von Landei (25.05.2016 um 14:25 Uhr)

  16. #15
    Global Moderator Viertel Gigabyte Avatar von SlaterB
    Registriert seit
    06.08.2008
    Fachbeiträge
    2.695
    Genannt
    275 Post(s)
    nochmal gefragt, wo könnte man das hier anwenden, wie würde es weiterhelfen?

    bei der Methodendefinition
    public static <+A> void indexed(Iterable<A> iterable, ObjIntConsumer<A> consumer) {
    ? ist das in Scala möglich oder auch für dort als Wunsch formuliert?

    -----

    der Link Variances - Scala Documentation
    spart ja auch nicht gerade mit Komplexität
    Please note that this is an advanced example which combines the use of polymorphic methods, lower type bounds, and covariant type parameter annotations in a non-trivial fashion. Furthermore we make use of inner classes to chain the stack elements without explicit links.
    für normalsterbliche Leser eher nicht gedacht, oder?

    ganz am Ende wird es erst konkret:
    e.g. it’s possible to push a string on an integer stack. The result will be a stack of type Stack[Any]; so only if the result is used in a context where we expect an integer stack, we actually detect the error. Otherwise we just get a stack with a more general element type.
    so ist das also,
    für Welten mit veränderlichen Objekten ohne neue Variablenzuweisung nach jeder Aktion aber eher nicht gedacht:
    Code:
    Stack[Integer] s = ..
    s.push("string");
    // alle Integer aus s auslesen -> boom
    aber das gibt es ja eben nicht, insofern dort durchaus ok, auch für class List in scala eingesetzt

    dann wäre ja wirklich Iterable<+A> der Gedanke hier für die indexed()-Methode bzw. Iterable-Definition und in indexed() nichts anzugeben?,
    in Java mit zustandsbehafteten Objekten aber natürlich undenkbar

    ----------

    OT:
    Covariance and Contravariance in Scala | Atlassian Blogs
    fand ich gerade noch bei der Suche, sieht zunächst bekömmlicher aus,
    aber dann Abschnittsüberschriften 'A little bit of category theory', 'Function Functors', 'Back to Earth'..

    passend ein Kommentar darunter
    I started reading but it became too confusing after a while.. I even tried re-reading parts but got no luck.
    I think it could be convenient to use examples to explain definitions.
    Thanks anyway!
    warum nur muss alles unsagbar kompliziert gemacht werden, so hat die Sprache ja nie eine Chance..
    Hansa wird Meister

  17. #16
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Zitat Zitat von SlaterB Beitrag anzeigen
    nochmal gefragt, wo könnte man das hier anwenden, wie würde es weiterhelfen?

    bei der Methodendefinition
    public static <+A> void indexed(Iterable<A> iterable, ObjIntConsumer<A> consumer) {
    ? ist das in Scala möglich oder auch für dort als Wunsch formuliert?
    Scala kann das nur auf Klassenebene soweit ich weiß, bei einzelnen Methoden scheint es auch nicht sonderlich nützlich zu sein.

    für Welten mit veränderlichen Objekten ohne neue Variablenzuweisung nach jeder Aktion aber eher nicht gedacht:
    Code:
    Stack[Integer] s = ..
    s.push("string");
    // alle Integer aus s auslesen -> boom
    aber das gibt es ja eben nicht, insofern dort durchaus ok, auch für class List in scala eingesetzt
    Das wäre bei einem unveränderlichen, contravarianten Stack kein Problem. Kleinste gemeinsame Oberklasse von Integer und String wäre Object, dementsprechend wäre das Resultat nach dem push ein Stack[Object] - vollkommen typsicher (wenn auch nicht sehr nützlich in diesem Beispiel). Veränderliche Datenstrukturen sind dagegen meist invariant. Scala würde sich auch querstellen, wenn du versuchen würdest, eine selbige co- oder contravariant zu definieren.
    Geändert von Landei (25.05.2016 um 16:53 Uhr)

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Ähnliche Themen

  1. Erweiterte For-Schleife mit Index
    Von RSS Reader im Forum Neues aus den Byte-Welt-Blogs
    Antworten: 5
    Letzter Beitrag: 10.02.2016, 13:03
  2. Erweiterte For-Schleife mit Index - II
    Von RSS Reader im Forum Neues aus den Byte-Welt-Blogs
    Antworten: 0
    Letzter Beitrag: 09.02.2016, 11:21
  3. Byte-Welt-Blog - Erweiterte For-Schleife mit Index
    Von Landei im Forum Blogs und Berichte
    Antworten: 0
    Letzter Beitrag: 01.11.2015, 05:35
  4. Matrix for Schleife
    Von dibbi1234 im Forum Dotnet-Forum
    Antworten: 18
    Letzter Beitrag: 16.12.2013, 08:46
  5. Antworten: 10
    Letzter Beitrag: 19.11.2013, 11:22

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •