Swift: le sujet officiel fourre-tout

1246710

Réponses

  • MayerickMayerick Membre
    juin 2014 modifié #92
    De ce que j'ai compris for nombres in 1 .. 5 exclus la borne 5 alors que in 1... 5 inclu les bornes. C'est l'équivalent de 1<5 et 1<=5.
  • Oui c'est exactement ça. J'aime bien ce système de boucle for. ça évite de créer une variable i, de l'incrémenter et tout... Pour ça la syntaxe est plus claire qu'Objective-C.


  • muqaddarmuqaddar Administrateur


    De ce que j'ai compris for nombres in 1 .. 5 exclus la borne 5 alors que in 1... 5 inclu les bornes. C'est l'équivalent de 1<5 et 1<=5.




     


    Oui, c'est pas mal du tout: 1 point de plus inclut la boucle supplémentaire.

  • CéroceCéroce Membre, Modérateur
    juin 2014 modifié #95

    Moi je trouve la syntaxe discutable, comme par exemple, mettre le type du retour d'une fonction à  la fin de la première ligne avec (->) plutôt qu'un début...


    C'est une notation qu'on trouve dans d'autres langages, tels que Haskell.
     

    J'avoue que ça m'a fait bizarre au début mais au final je trouve quand même ça plus logique. Le variables d'entrées au début et les variables de "sorties" à  la fin. Comme en maths.


    Il y a tout de même une logique en langage C. Cette direction correspond à  l'affectation:
    a = b;
    La destination est à  gauche, la source à  droite. D'où la raison de mettre le type de sortie d'une fonction à  gauche en C.
  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #96

    Oui, c'est pas mal du tout: 1 point de plus inclut la boucle supplémentaire.

    Oui et je trouve ça plus logique aussi que la version Ruby qui, comme le souligne zoc, a le comportement inverse :
    $ pry
    [1] pry(main)> (1..3).each { |i| puts i }
    1
    2
    3
    => 1..3
    [2] pry(main)> (1...3).each { |i| puts i }
    1
    2
    => 1...3
    Alors qu'en Swift le point supplémentaire inclut la borne supplémentaire, c'est mieux :
    $ swift
    Welcome to Swift! Type :help for assistance.
    1> for i in 1..3 { println("\(i)") }
    1
    2
    2> for i in 1...3 { println("\(i)") }
    1
    2
    3
  • muqaddarmuqaddar Administrateur

    Et ils réfléchissent déjà  à  la suite:


     


     


    #Swift syntax replacement idea: instead of a..b and a...b use [a...b] [a...]b also enables: a[...]b a[...b] What do you think? @cocoafro

     



     


  • AliGatorAliGator Membre, Modérateur
    Oui dans les vidéos WWDC (genre Modern Frameworks & co) ils parlent des bonnes pratiques pour nommer les API & co... et ils disent à  cette occasion à  plusieurs reprise qu'ils sont preneurs de feedbacks sur Swift, idées d'amélioration des APIs, etc.

    Moi pour l'instant je pense avoir fait le tour de tout ce que swift permettait en théorie, en ayant fini le bouquin Swift Programming Langage, et ça promet du lourd... mais là  où je suis déçu c'est :
    - qu'il n'y a l'air d'y avoir les concepts d'APIs privées (y'a pas de headers, mais y'a pas de @private non plus, comment on fait pour ne pas exposer certaines méthodes internes du coup ?)
    - qu'il n'y a pas l'air d'y avoir le concept de classes abstraites, alors que c'est qqch qu'on sait qui nous manque dans ObjC depuis pas mal de temps aussi.
  • muqaddarmuqaddar Administrateur

    Il est l'heure de déplacer ce sujet du forum actualités vers le forum Swift...


  • Pour ma part je trouve assez pertinente la syntaxe 0..5 pour boucler sur des arrays, et la syntaxe 1...5 pour les boucles qui sont plus liées à  quelque chose de tangible que l'on veut conserver de façon lisible dans le code.


     


     




    Et ils réfléchissent déjà  à  la suite:


    #Swift syntax replacement idea: instead of a..b and a...b use [a...b] [a...]b also enables: a[...]b a[...b] What do you think?




     


    Attention, le compte auteur de ce tweet (@SwiftDevs, que je suis également... pas pour longtemps) n'est pas du tout officiel mais créé par des développeurs qui essaient de surfer sur la vague. Ils essayent à  fond d'exploiter twitter pour rameuter du monde pour créer une communauté, vendre des t-shirts etc. Par exemple, quasiment toute personne qui écrit un tweet avec le tag #swift sera marqué comme favori par ce compte, même si c'est pour dire du mal du langage (ils ne lisent pas les tweets mais essayent juste de créer du lien, ce qui fonctionne un peu dans la masse).


     


    Pour des infos plus pertinentes sur swift, on pourrait suivre les devs d'apple sur twitter (Chris Lattner le premier) mais ils ne disent pas grand chose sur le réseau.


  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #101
    Des petits choses que j'aime bien dans Swich quand même, c'est le fait que les closures et les fonctions ont le même type, ce qui peut paraà®tre anodin, mais permet de faire des choses assez sympa, comme passer directement une fonction ou un opérateur à  une méthode qui prend une closure.

    Par exemple pour calculer le résultat de la multiplication de tous les éléments d'un tableau, il suffit d'écrire ceci :
    [1,3,5,6,8,12].reduce(1,*) // retourne 8640
    On peut donc passer juste "*" comme 2ème paramètre à  "reduce" et ça marche tout seul !

    NB : Y'a pas mal d'erreurs dans les exemples de la vidéo WWDC'14 #403 "Intermediate Swift" qui cause du sujet... il utilise des choses comme "numbers.map { sum += $0 }" ou "numbers.map(println)" en passant donc des closures ou des fonctions qui ne correspondent pas au type "(Int)->(Int)" attendu par "numbers.map"... ce qui forcément ne compile pas !
  • zoczoc Membre


    - qu'il n'y a l'air d'y avoir les concepts d'APIs privées (y'a pas de headers, mais y'a pas de @private non plus, comment on fait pour ne pas exposer certaines méthodes internes du coup ?)




     


    Les modificateurs de visibilité viendront dans une prochaine évolution du langage selon Chris Lattner. Ils n'ont juste pas eu le temps de s'en occuper pour l'instant.

  • AliGatorAliGator Membre, Modérateur
    @zoc Ouais c'est ce que j'ai fini par lire sur les forums officiels d'Apple.

    Entre ça et les crash (du compilo, en général) que j'ai souvent en faisant mumuse avec Playground plus ça va plus je me dis qu'il est un peu tôt encore pour s'amuser avec Swift de manière un peu sérieuse... je vais p'tet attendre un peu qu'il soit stable avant de m'y mettre pour de vrai ^^
  • muqaddarmuqaddar Administrateur

    J'aimerais bien pouvoir faire:



    myArrayOfElements.each { |element| ... }

    en plus de:



    for element in myArrayOfElements { ... }
  • muqaddarmuqaddar Administrateur


    Entre ça et les crash (du compilo, en général) que j'ai souvent en faisant mumuse avec Playground plus ça va plus je me dis qu'il est un peu tôt encore pour s'amuser avec Swift de manière un peu sérieuse... je vais p'tet attendre un peu qu'il soit stable avant de m'y mettre pour de vrai ^^




     


    J'ai commencé à  jouer avec le fichier PlayGround fourni par Apple et ça a tenu 1 minute avant de crasher...

  • muqaddarmuqaddar Administrateur

    Par contre, ils vantent la lisibilité du code, mais ce genre de truc:


     


    func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {}


     


    n'est pas terrible je trouve. On commence à  plus rien y comprendre.


  • muqaddarmuqaddar Administrateur

    Le plus gros point positif c'est le retour possible d'éléments multiples dans une fonction.


  • muqaddarmuqaddar Administrateur

    Pourquoi:


     


    label + String(42)


     


    et non :


     


    label + 42.string


     


    ?


     


    Là , on n'a l'impression de faire un espèce de cast.


     


    J'adore pouvoir faire 42.to_s en ruby !


  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #109

    J'aimerais bien pouvoir faire:

    myArrayOfElements.each { |element| ... }
    en plus de:
    for element in myArrayOfElements { ... }

    Bah rien de plus facile :
    extension Array {
    func each(closure: Element->()) {
    for item in self { closure(item) }
    }
    }

    let myArrayOfElements = [1,2,3]
    myArrayOfElements.each { item in println("Hi \(item)") }
  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #110

    Par contre, ils vantent la lisibilité du code, mais ce genre de truc:
     
    func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {}
     
    n'est pas terrible je trouve. On commence à  plus rien y comprendre.

    Non au contraire moi je trouve ça plutôt clair. Je trouve ça même bien + lisible que son équivalent en Objective-C qui serait :
    -(BOOL)hasAnyMatches:(NSArray*)list condition:((BOOL)(^)(NSNumber*))condition { ... }
    Me dis quand même pas que tu trouves la version Objective-C plus lisible que la version Swift quand même, surtout le bordel syntaxique autour de la déclaration du block en paramètre !!
  • AliGatorAliGator Membre, Modérateur
    Si tu veux continuer la transformation de Swift en Ruby:
    extension Int {
    func times(task: ()->() ) {
    for _ in 0..self { task() }
    }
    }
    3.times { println("Hello") }
  • muqaddarmuqaddar Administrateur


    Bah rien de plus facile :



    extension Array {
    func each(closure: Element->()) {
    for item in self { closure(item) }
    }
    }

    let myArrayOfElements = [1,2,3]
    myArrayOfElements.each { item in println("Hi \(item)") }



     


    Oui, il faut ajouter ses propres extensions...


     




    Non au contraire moi je trouve ça plutôt clair. Je trouve ça même bien + lisible que son équivalent en Objective-C qui serait :



    -(BOOL)hasAnyMatches:(NSArray*)list condition:((BOOL)(^)(NSNumber*))condition { ... }

    Me dis quand même pas que tu trouves la version Objective-C plus lisible que la version Swift quand même, surtout le bordel syntaxique autour de la déclaration du block en paramètre !!

     




     


    Cela se discute, ou alors c'est l'habitude...

  • muqaddarmuqaddar Administrateur


    Si tu veux continuer la transformation de Swift en Ruby:



    extension Int {
    func times(task: ()->() ) {
    for _ in 0..self { task() }
    }
    }
    3.times { println("Hello") }



     


    Je commence à  peine la doc, et je ne comprends pas la syntaxe de ton extension.



  • Non au contraire moi je trouve ça plutôt clair. Je trouve ça même bien + lisible que son équivalent en Objective-C qui serait :



    -(BOOL)hasAnyMatches:(NSArray*)list condition:((BOOL)(^)(NSNumber*))condition { ... }



     


     


    ce n'est pas plutôt l'équivalent de ça ? : 



    -(BOOL)hasAnyMatches:(NSArray*)list condition:(BOOL(*)(NSNumber*))condition
  • samirsamir Membre
    juin 2014 modifié #115


    Je commence à  peine la doc, et je ne comprends pas la syntaxe de ton extension.




     


    Il étend un Int en rajoutant une nouvelle fonction qui s'appelle times.


     


    la fonction times prend en paramètre une autre fonction qui n'a pas de params et pas de retours () ->() ( la fonction task)


    à  l'intérieur la fonction times exécute la fonction prise en params ( task ) le nombre de fois sa valeur ( la valeur de l'Int) .


  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #116

    Je commence à  peine la doc, et je ne comprends pas la syntaxe de ton extension.

    Elle n'a vraiment rien de sorcier :

    1. C'est une extension sur le type "Int"
    2. Elle déclare une nouvelle fonction "times", qui prend en paramètre une closure (une fonction sans paramètre d'entrée ni de sortie, comme un dispatch_block_t en Obj-C quoi)
    3. Cette fonction "times" est très simple : elle boucle N fois (où N = self = l'entier que l'on est en train d'étendre) et à  chaque fois exécute la closure task()

    Tu as donc maintenant une nouvelle méthode "times" sur le type "Int", méthode "times" qui prend en simple paramètre un block (sans paramètre ni retour, lui).

    ---

    En Objective-C, ça donnerait :
    @interface NSNumber (Times)
    -(void)times:(void(^)(void))task __attribute__((nonnull));
    @end

    @implementation NSNumber (Times)
    -(void)times:(void(^)(void))task
    {
    int n = self.intValue;
    for(int i = 0; i<n; ++i)
    {
    task();
    }
    }
    @end

    @5.times(^{
    println("Hello");
    });
    Quand même vachement + lourd ! Et en plus on ne peut faire cette catégorie en ObjC que sur NSNumber, alors qu'en Swift (comme en Ruby) tout est Objet, même les Int, ce qui nous permet de les étendre au même titre que des classes, c'est magique !

    NB: j'ai pas testé le code ObjC, il peut y avoir des erreurs... c'est fou, je sais plus faire d'ObjC maintenant que mon cerveau a basculé en Swift, j'ai même dû relire mon code et ajouter des point-virgules à  la fin des lignes et des parenthèses autour du "for", j'ai déjà  tout oublié ^^
  • AliGatorAliGator Membre, Modérateur

    ce n'est pas plutôt l'équivalent de ça ? : 


    -(BOOL)hasAnyMatches:(NSArray*)list condition:(BOOL(*)(NSNumber*))condition

    Alors oui et non :
    1. Oui car en effet je n'aurais pas dû mettre de parenthèses autour du type de retour BOOL
    2. Non car en ObjC l'équivalent d'une closure est bien un block et non un pointeur de fonction (donc c'est bien "^" et pas "*".

    Tout ça démontre que la syntaxe ObjC elle était quand même vraiment pas user-friendly en particulier pour déclarer des blocks en tant que paramètre de fonctions, et je suis tellement déjà  habitué à  la syntaxe Swift que je ne sais déjà  plus écrire les "blocks en paramètre de fonction" en ObjC tellement c'était tordu ^^
  • AliGatorAliGator Membre, Modérateur
    juin 2014 modifié #118
    Bon bah puisque tu m'as sauvagement supprimé ma réponse pendant que j'étais en train de l'éditer, je suis obligé de la réécrire ici un peu plus bas pour répondre à  ton message + haut...
     

    Pourquoi:

    label + String(42)
    et non :
    label + 42.string
    ?
     
    Là , on n'a l'impression de faire un espèce de cast.

    Bah parce que la syntaxe est claire et explicite. On cherche à  créer une String à  partir d'un Int. Donc on crée une String (à  l'aide du constructeur de la classe String) à  partir d'un Int (en passant un Int en paramètre à  ce constructeur). La syntaxe colle exactement à  ce que tu veux faire
     

    J'adore pouvoir faire 42.to_s en ruby !

    Bah si vraiment tu veux retrouver les mêmes choses qu'en Ruby, tu peux toujours... même si utiliser String(42) est plus logique. Et c'est extrêmement simple d'ailleurs :
    extension Int {
    var to_s: String { return String(self) }
    }

    let str = 42.to_s


    PS : Merci d'utiliser les balises CODE dans tes messages, c'est un peu chiant à  lire/citer sinon ;)
  • muqaddarmuqaddar Administrateur


     Bah si vraiment tu veux retrouver les mêmes choses qu'en Ruby, tu peux toujours... même si utiliser String(42) est plus logique. Et c'est extrêmement simple d'ailleurs :



    extension Int {
    var to_s: String { return String(self) }
    }

    let str = 42.to_s



     


    Oui, là  c'est extrêmement clair en effet.


    Si c'est si simple, je sens que beaucoup de devs vont se pondre des petites extensions...

  • AliGatorAliGator Membre, Modérateur
    On va avoir pléthore de pods à  venir pour tout ça je pense ^^

    Perso, tout comme en Objective-C, je préfère n'utiliser les extensions / catégories que quand c'est justifié / que ça ajoute vraiment qqch que je n'avais pas directement.

    Si c'est pour changer la syntaxe dans l'unique but de permettre une syntaxe alternative (qui ne fait rien gagner d'autre que le rapprochement avec un langage déjà  existant), ce n'est à  mon avis pas une bonne idée, car cela va complexifier la syntaxe de Swift qui est justement orienté pour être un langage à  syntaxe simple (= à  grammaire très légère).

    C'est comme si tu déclarais 3 fonctions différentes qui faisaient la même chose (2 de ces fonctions appelant juste la 3ème), dans l'unique but d'avoir 3 "alias" différents pour la même chose... c'est un peu inutile et augmente la confusion (les utilisateurs vont se dire que puisqu'il y a 3 fonctions différentes c'est sûrement parce qu'il y a de subtiles différences entre les 3 sinon y'en aurait qu'une, etc)
  • muqaddarmuqaddar Administrateur
    juin 2014 modifié #121

    @Samir, @Aligator


     


    Merci pour les précisions, mais j'ai encore des retours sur la syntaxe.



    2. Elle déclare une nouvelle fonction "times", qui prend en paramètre une closure (une fonction sans paramètre d'entrée ni de sortie, comme un dispatch_block_t en Obj-C quoi)

    Tu parles de fonction sans paramètre d'entrée ni de sortie OK... alors pourquoi pas: ?



    func times(func task: ()->() ) {}

    Soit on déclare, soit on ne déclare pas... Evidemment, ça bugue.


     


    On est obligé de mettre les 2 premières parenthèses aussi puisque pas d'argument d'entrée ? Réponse du compilo: oui...

Connectez-vous ou Inscrivez-vous pour répondre.