haskell – Sam & Max http://sametmax.com Du code, du cul Wed, 30 Oct 2019 15:34:04 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Attention au télé-achat http://sametmax.com/attention-au-tele-achat/ http://sametmax.com/attention-au-tele-achat/#comments Thu, 30 Jul 2015 21:54:34 +0000 http://sametmax.com/?p=16712 Dès qu’il y a une tendance, on voit les fanboys sortir leurs dentiers éclatant pour vous faire des démos ventant le produit qui retire toutes les tâches et si vous appelez maintenant il y a 20% de réduction.

Mais tout comme à la télé le magic bullet fait le smoothie en seulement 2 minutes parce que le mec commence la vidéo avec 10 fruits déjà choisis/payés/livrés/lavés/épluchés/découpés, la techno qu’on vous vend a ses travers.

C’est normal. Mais c’est rarement dit.

Ces dernières années, NoSQL, la programmation asynchrone, la programmation fonctionnelle et les projets JS, Node en tête, ont été sur toutes les chaînes : si vous avez pas programmé votre chat avec Mongo + MeteorJS avant 50 ans, vous avez raté votre vie ! Appelez le 5555-5555 et recevez un pins Haskell qui vous créé une copie de votre pull quand vous l’accrochez.

C’est pas qu’il y a une arnaque, c’est juste qu’il y a un truc qu’on appelle la réalité.

Par exemple, aujourd’hui, je tombe sur un projet appelé pymaybe qui implémente le pattern fonctionnel monadique maybe. Je déconne pas, c’est le terme technique.

Je taquine, mais je trouve le projet sincèrement intéressant. Néanmoins la page d’exemple reflète typiquement l’esprit Pierre Bellemare.

Ca commence par un exemple Python soit disant trop long :

def get_user_name():
    current_user = request.user
    if current_user:
        return current_user.name

    return ''

Converti en :

def get_user_name() :
    return maybe(request.user).name.or_else('')

Mais c’est très maladroit, car on résout ici un problème qui n’existe pas. En effet, personne écrivant du Python professionnellement (et qui serait donc intéressé par ce projet) n’écrirait le premier exemple ainsi. Un code de prod serait :

def get_user_name():
    return getattr(request.user, 'name', '')

Ce qui est plus court que les deux snippets ci-dessus, immédiatement reconnu par des pairs, et ne demande pas d’ajouter une dépendance externe à son code.

Le second exemple est plus trompeur encore, et commence par cet extrait :

stores = json.get('stores')
if stores:
    products = stores[0].get('products')
    if products:
        product_name = products[0].get('details', {}).get('name') or 'unknown'

Et avec “coder builder 3000” vous pouvez faire :

product_name = maybe(stores)[0]['products'][0]['details']['name'].or_else('unknown')

Impressionant ! C’est la barre de fer !

Sauf que… Avez-vous remarqué ? Le json.get() est passé à la trappe…

stores = json.get('stores')
product_name = maybe(stores)[0]['products'][0]['details']['name'].or_else('unknown')

Et puis d’où vient maybe() ? Ce n’est pas un builtin… Donc il faut l’importer, comme pour les fruits du mixer qui ne se découpent pas tout seuls.

from pymaybe import maybe
stores = json.get('stores')
product_name = maybe(stores)[0]['products'][0]['details']['name'].or_else('unknown')

Et si vous avez un editeur bien réglé, la 3eme ligne va lever un warning PEP8 : 85 charaters, c’est 5 de trop (sinon on peut écrire tout son script sur une ligne aussi).

from pymaybe import maybe
stores = json.get('stores')
product_name = maybe(stores)[0]['products'][0]['details']['name']
product_name = product_name.or_else('unknown')

Ah, plus qu’une seule ligne d’avantage par rapport à la version originale. Mais une seconde, cette version vous l’écririez ainsi ? Bien entendu que non :

try:
    product_name = json.get('stores')[0]['products'][0]['details']['name']
except (TypeError, KeyError, IndexError):
    product_name = 'unknown'

Ce qui a en prime l’avantage de montrer explicitement les cas dans lequels product_name = 'unknown', plutôt que de devoir savoir ce que fait exactement une lib tierce partie (qui doit en plus être déployée). Et si il y a une erreur en plus qu’il faut gérer ? TypeError ? IoError ? C’est juste une clause de plus. Pour l’autre version, on rajoute 4 lignes.

Attendez, ce n’est pas fini. Il est facile de croire, quand on vient d’un autre langage, que Python est un langage simpliste. Il se traine sa réputation de langage jouet depuis bien longtemps. Erreur classique !

Car Python est très simple à prendre en main, mais possède énormément de profondeur.

__getitem__, anyone ?

(test) >>> class Test:
    def __getitem__(self, value):
        return 1
      ...:     

(test) >>> maybe(Test())[0]
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
 in ()
----> 1 maybe(Test())[0]

/home/sam/.local/share/virtualenvs/test/local/lib/python2.7/site-packages/pymaybe/__init__.pyc in __getitem__(self, key)
    212 
    213     def __getitem__(self, key):
--> 214         return maybe(self.__value.get(key, None))
    215 
    216     def __setitem__(self, key, value):

AttributeError: Test instance has no attribute 'get'

(test) >>> Test()[0]
           1

defaultdict ?

(test) >>> maybe(defaultdict(datetime.utcnow))[0]
           None

(test) >>> defaultdict(datetime.utcnow)[0]
           datetime.datetime(2015, 7, 30, 19, 39, 28, 298488)

Cela signifie-t-il que ce projet ne mérite pas d’être suivi ? Pas du tout, le principe est sympas, ça doit être creusé. Simplement il faut se méfier du mimi, du rara, du miracle.

Si vous relisez les articles sur WAMP et crossbar, vous noterez que je souligne clairement les problèmes de la techno : doc, debugging, syntax twisted… Personne ne demande d’être impartial, mais faut pas non plus vendre la vessie de l’ours avant la lanterne des boeufs.

]]>
http://sametmax.com/attention-au-tele-achat/feed/ 30 16712