Fonctionnalités semi-uniques du langage de programmation Killer [fermé]

25

Lorsque vous apprenez un nouveau langage de programmation, vous rencontrez parfois une fonctionnalité de langage qui vous donne envie de l'avoir dans vos autres langages de programmation que vous connaissez.

Quelles sont les fonctionnalités de langage qui étaient au moment de l'apprentissage très nouvelles pour vous et que vous souhaiteriez avoir pour vos autres langages de programmation.

Un exemple de ceci est les générateurs en Python ou C #. D'autres exemples peuvent inclure des listes de compréhension en Python, un modèle en C ++ ou LINQ en .NET ou une évaluation paresseuse en Haskell.

Quelles autres fonctionnalités de langage semi-uniques avez-vous rencontrées qui étaient complètement nouvelles et instructives pour vous? Y a-t-il d'autres caractéristiques des anciens langages de programmation qui étaient uniques et qui sont tombées en désuétude?

Brian R. Bondy
la source

Réponses:

25

Pratiquement rien à Haskell

  • Monades. Oui - le gros mot effrayant qui rend les parseurs incroyablement faciles, les E / S, les opérations sur les listes et d'autres choses si faciles (une fois que vous remarquez un modèle commun)
  • Flèches. Idem pour les utilisateurs avancés;)
  • Des trucs standard comme des lambdas, etc.
  • Fonctions de curry
  • Types de données algébriques
  • Correspondance de motifs

Et beaucoup plus.

PS. Oui. Je suis fanboy de Haskell si quelqu'un le demande.

Maciej Piechotka
la source
12
Pour être juste, vous devriez attribuer un crédit ML à la plupart de cette liste.
magnifique
1
Eh bien - sauf les monades et les flèches IIRC. Mais ils sont encore semi- uniques
Maciej Piechotka
Une raison particulière pour downvote?
Maciej Piechotka
2
+1 pour la correspondance des motifs. Je le montre aux autres et ils ne le comprennent pas. Je pense que c'est du génie.
Barry Brown
Obligatoire ( steve-yegge.blogspot.com/2010/12/… ). BTW, je considérerais à peine les lambdas comme uniques, python, C #, javascript, etc. Monades? La plupart des autres langues l'appellent chaînage; le noyau jquery est essentiellement un ensemble massif de monades HTML / DOM et AJAX (Google: jQuery.fn). Le curry est également relativement courant de nos jours.
Evan Plaice
21

Macros Lisp.

Le langage macro Lisp est Lisp, avec quelques fonctionnalités de syntaxe prédéfinies pour des raisons de commodité. En les utilisant, il est possible d'ajouter des fonctionnalités majeures au langage, telles que le choix des styles d'orientation d'objet ou la correspondance déterministe de type Prolog, sans regarder à sa place. Cela rend la setfmacro possible, qui est une macro conceptuellement très puissante: (setf A B)signifie que, lorsque vous évaluez, Avous obtiendrez B, et qui peut être étendu à n'importe quelle limite que vous aimez.

La métaprogrammation de modèles C ++ est capable de choses similaires, mais dans un langage très différent du C ++ normal.

David Thornley
la source
+1 J'espère qu'un jour je pourrai programmer dans un dialecte lisp.
Oliver Weiler
@Helper ... via les modèles C ++ [rire effrayant]
mlvljr
@mlvjr: Tu es effrayant.
David Thornley
En fait, c'est la seule fonctionnalité prête à l'emploi dont vous aurez besoin dans une langue. Avec les macros Lisp, vous pouvez ajouter toutes les autres fonctionnalités possibles ultérieurement.
SK-logic
18

Décorateur de Python.

Il est extrêmement facile de mettre en œuvre la mémorisation ou le timing de la fonction à l'aide du décorateur.

Exemple de temporisateur de fonction.

class FuncTimer(object):
    """ Time how much time a function takes """
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}
        self.start_time = time.time()
    def __call__(self, *args):
        self.memo['return'] = self.fn(*args)
        print("Function '%s' took %u seconds" % (self.fn.__name__, time.time() - self.start_time))
        return self.memo['return']

Maintenant, si vous avez une fonction que vous voulez chronométrer, vous pouvez simplement le faire,

@FuncTimer
def foo():
    # foo's implememtation goes here

Vous verrez quelque chose comme,

La fonction 'foo' a pris 3 secondes.

grokus
la source
Java a des annotations, qui ont un but et une syntaxe similaires, mais fonctionnent très différemment
Casebash
1
+1: Les décorateurs de Python m'ont impressionné plus que presque toutes les autres fonctionnalités du langage. Ils sont très beaux et simples!
Adam Paynter
Peut-être pourriez-vous partager un exemple simple avec nous? Pour être honnête, je ne connais pas Python.
ShdNx
@ShdNx, je viens d'ajouter un exemple.
grokus
1
L'heure de début ne doit-elle pas être calculée dans le cadre de l'appel?
detly
14

Casting void*en C. Vous pouvez tout caster en octets bruts et faire ce que vous voulez avec ces données.

(Oui, de nos jours c'est unique ...)

P Shved
la source
1
L'objet dans les langages .Net est très similaire. Seulement plus de caractères, etc.
Maciej Piechotka
Vous pouvez convertir en objet dans de nombreuses langues. Le problème principal est que de nombreuses langues séparent les primitives et les objets
Casebash
5
@Maciej: même en .NET, vous ne pouvez pas vraiment transtyper des primitives en Object. Vous les mettez en boîte , et c'est une bête assez différente. De plus, c'est toujours totalement différent du casting pour void*...
Dean Harding
1
La conversion Pointeren Pascal et Object Pascal fait la même chose.
Frank Shearar
1
@DeanHarding: Eh bien - en C, vous avez int64_tque vous ne pouvez pas toujours lancer en toute sécurité void *(Désolé pour la fin - 2 ans - réponse).
Maciej Piechotka
12

Rendement en Python

En Python (et je crois en C #), vous pouvez définir un soi-disant générateur qui suspend l'exécution de la fonction à une yieldinstruction, renvoie la valeur et lors des appels suivants, redémarre la fonction là où elle s'était arrêtée (avec l'état préservé entre les appels). C'est idéal pour générer de longues listes de valeurs où vous n'êtes intéressé que par la valeur actuelle de la fonction (ce qui est très courant). Il vous permet de créer des séquences potentiellement infiniment longues tout en n'occupant qu'un espace très limité en mémoire.

Chinmay Kanchi
la source
1
Le rendement est déjà indiqué dans la question.
Trinidad
Cela remonte à BCPL.
Peter Taylor
8

Expressions lambda (fermetures, fonctions imbriquées, méthodes anonymes, peu importe comment vous les appelez).

Je les ai rencontrés pour la première fois en Perl, je les ai immédiatement aimés et je me suis demandé pourquoi d'autres langues ne les avaient pas. De nos jours, je suppose que ce n'est plus si unique; même PHP a réussi à les pirater d'une manière ou d'une autre. Mais ils étaient semi-uniques à l'époque.

Timwi
la source
5
Unique, tant que vous comptez revenir à Lisp, qui est le deuxième langage de programmation le plus ancien. ;-)
Michael H.
-1: Pas semi-unique
Casebash
7

Les ensembles dans Delphi sont très utiles, à peu près juste un tableau booléen nommé. Ils sont très utiles pour enregistrer un formulaire de paramètres avec 32 cases à cocher. Mais ils ont tous les mêmes fonctions de théorie des ensembles (c'est-à-dire la différence, l'intersection, l'union).

Je ne sais pas s'ils sont passés de mode, mais je les utilise tout le temps.

Peter Turner
la source
Bien, mais cela ne serait-il pas facile à implémenter en Java, par exemple: booléen []?
Mark C
Oui, vous pouvez, mais je ne pense pas que ce soit aussi succinct que: TForm = (FF_1500 = 1, FF_CA251 = 5, FF_UB04 = 6, FF_MA10 = 7); TFormSet = ensemble de TForm;
Peter Turner
7

Envoyer

Depuis Erlang. Envoie un message asynchrone à un autre thread.

Expr1 ! Expr2

Recevoir

Depuis Erlang. Reçoit un message d'un autre fil.

receive
    Pattern1 [when GuardSeq1] ->
        Body1;
    ...;
    PatternN [when GuardSeqN] ->
        BodyN
end
Jonas
la source
5

Propriétés C #

/// <summary>
/// Get ID
/// </summary>
public int ID
{
    get; set;
}

contre

(Java)

/**
 * Name of user
 */
private String name;

/**
 * Gets name of user
 * @return Name of user
 */
public String getName() {
    return this.name;
}

/**
 * Sets name of user. 
 * @param name
 */
public void setName(final String name) {
    this.name = name;
}
TheLQ
la source
2
Oui, ils sont meilleurs, mais c'est un mauvais exemple. La différence serait beaucoup plus petite si le getter / setter faisait réellement quelque chose de spécial, et la version C # est moins documentée.
Bart van Heukelom
1
Mon patron est fortement contre les propriétés automatiques de C # et chaque fois que nous avons un argument à ce sujet, aucun de nous n'est capable de voir pourquoi l'autre a raison ou tort. Je les aime juste parce qu'ils rendent le code tellement plus propre et me font gagner beaucoup de temps à long terme.
mbillard
2
Ne permettez tout simplement pas à cela d'encourager les gens à avoir des getters et des setters partout. Seuls les getters et setters qui ont un sens en tant qu'actions sur un objet doivent être utilisés.
David Thornley
3
Elles ne sont pas appelées propriétés C #, elles sont appelées propriétés automatiques
Jaco Pretorius
1
Les propriétés automatiques sont très courantes de nos jours. Python, Objective-C ...
Casebash
5

Les syndicats en C

Je ne peux honnêtement pas dire que je n'ai pas écrit assez de C pour en faire moi-même mais j'ai travaillé avec le code des autres qui le fait.

Lorsqu'il s'agit d'empaqueter des mélanges de données différentes dans des applications qui manipulent des bits / octets bruts tels que la mise en réseau ou le stockage de données binaires. Dans les langues fortement typées, il n'y a tout simplement pas de moyen facile de faire l'équivalent.

Avertissement:

Bien que les unions soient extrêmement utiles dans certains cas, elles ne se trouvent pas dans la plupart des langues de niveau supérieur car elles ne sont pas sécurisées. IE, vous pouvez faire saigner les données au-delà des limites des variables en utilisant les unions (un grand non non dans le monde sûr de type). Un grand pouvoir implique de grandes responsabilités.

Plie d'Evan
la source
2
À mon humble avis pour une bonne raison. La réinterprétation des données est une belle façon de se filmer à pied ( en.wikipedia.org/wiki/Aliasing_(computing) ). Mieux vaut utiliser des conversions explicites à mon humble avis. Les syndicats qui agissent correctement sont les types de données algébriques à mon humble avis.
Maciej Piechotka
@Maciej J'ai ajouté un avertissement nécessaire. Cependant, je ne sais pas si cela explique avec précision les dangers de l'utilisation des syndicats, car je n'ai pas vraiment de connaissances intimes sur leur utilisation. Je sais juste que, là où je les ai vus utiliser, le code était beaucoup plus concis et plus facile à utiliser que l'équivalent du langage de niveau supérieur.
Evan Plaice
Le problème est que C est un «langage de niveau supérieur» (juste un langage de niveau supérieur de bas niveau). Depuis K&R C il obtient beaucoup de règles qui permettent d'utiliser du code portable plus rapide. Le prix à payer est que le compilateur peut assumer diverses choses et certains être confus. La plupart de l' unionutilisation est sûre, certains sont des idiomes bien pris en charge (bien que techniquement incorrects) - voir cellperformance.beyond3d.com/articles/2006/06/… (bien que ce soit plus un problème avec des pointeurs, les syndicats peuvent bien le simuler).
Maciej Piechotka
Delphi a étendu sa recordsyntaxe pour prendre en charge les syndicats:in_addr = record case integer of 0: (S_un_b: SunB); 1: (S_un_w: SunW); 2: (S_addr: u_long); end;
Frank Shearar
5

J'aime vraiment le modificateur sauf dans Ruby . Cela semble si naturel et remplace de nombreux scénarios où votre code semble être très désordonné sans lui.

puts "All good" unless input.nil?

Comment peux tu ne pas aimer cela? :RÉ

Jaco Pretorius
la source
6
Perl l'avait avant Ruby. Je l'aime aussi.
Barry Brown
1
Nemerle a des mots-clés similaires pour unlesset whenqui remplacent les scénarios de branchement les plus courants qui seraient traditionnellement utilisés if/else.
MattDavey
5

syntaxes d'argument fantaisie python

Je ne sais pas à quel point c'est unique, mais en python, vous pouvez faire des trucs sympas comme avoir des paires de mots clés automatiquement transformées en dictionnaire et inversement. Idem pour les listes:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print "-- This parrot wouldn't", action,
    print "if you put", voltage, "volts through it."
    print "-- Lovely plumage, the", type
    print "-- It's", state, "!"


parrot(1000)
parrot(action = 'VOOOOOM', voltage = 1000000)
parrot('a thousand', state = 'pushing up the daisies')
parrot('a million', 'bereft of life', 'jump')

documents python (faites défiler vers le bas pour plus d'informations sur le passage d'arguments)

Gordon Gustafson
la source
1
+1 pour pouvoir passer un paramètre au fond de la liste sans avoir à passer les valeurs de tous les paramètres facultatifs avant lui.
eswald
4

Le préprocesseur C. Vous pouvez même écrire du code commun sur différentes plates-formes avec - moins ou plus - ifdefs.

ern0
la source
2
Il existe de meilleurs préprocesseurs facilement disponibles qui prennent leur propre étape supplémentaire et fonctionnent avec toutes les langues.
David Thornley
Je suis assez content avec ifdef, ifndef et autre.
ern0
3

Catégories Objective-C

Les catégories offrent un moyen simple d'étendre les fonctionnalités d'un objet au moment de l'exécution (pensez à la composition plutôt qu'à l'héritage). L'exemple classique consiste à ajouter un correcteur orthographique à la classe NSString.

@interface NSString (SpellChecker)
- (BOOL) checkSpelling;
@end

Également utile pour les corrections de bogues à faible impact, car l'implémentation d'une méthode d'une catégorie remplacera l'implémentation de ses parents.

aprock
la source
1
Très similaire aux méthodes d'extension en C #
Casebash
2

La méthode d' injection de Ruby combinée avec le symbole # to_proc de Ruby 1.9 permet d'écrire du code incroyablement concis (mais toujours lisible):

par exemple (1..10).inject(:+)

qui additionne les entiers 1 à 10 => 55

Voir des exemples comme celui-ci m'a donné envie d'apprendre Ruby, ce que je viens de commencer à faire.

tcrosley
la source
9
Pour être juste, injecter est la version de Ruby de fold / foldl / foldr à partir de langages comme Lisp, Haskell, etc.
mipadi
Je n'appellerais pas vraiment cela unique.
Daenyth
1
Le titre de la question dit "semi-unique", pas unique. Certes, la concision du code offerte par la combinaison de inject (ou map, etc.) et de Symbol # to_proc va bien au-delà des langages traditionnels comme C, Java et C ++.
tcrosley
Très concis (et j'aime ça), mais je ne suis pas sûr que ce soit différent de quelque chose comme: Enumerable.Range (1, 10) .Aggregate ((s, x) => s + x); de C # ou d'autres langues
FinnNk
1

Le mécanisme de liaison dans JavaFX (RIP). Le mot clé bind vous permet de lier la valeur d'une variable à la valeur d'une expression et de vous débarrasser de tous ces vilains Listener quel que soit le code passe-partout.

Bien que JavaFX ait été un échec à bien des égards, j'ai trouvé de nombreuses fonctionnalités du langage de script assez agréables.

Oliver Weiler
la source
1

Les mixages de chaînes plus l'évaluation de la fonction de temps de compilation en D sont une caractéristique de tueur assez unique. Oui, techniquement, ce sont deux fonctionnalités, mais la vraie puissance vient de leur combinaison. Avec cette combinaison, vous pouvez écrire des fonctions D normales qui génèrent du code sous forme de chaîne au moment de la compilation, puis mélanger ce code dans n'importe quelle étendue et le faire évaluer en tant que code D normal. Le code est entièrement compilé statiquement et s'exécute exactement comme s'il avait été écrit à la main. Cette fonctionnalité est même utilisée pour contourner quelques situations délicates dans la bibliothèque standard.

dsimcha
la source
J'aime aussi le type de retour déduit automatiquement d'une méthode ..
nawfal