URL: https://linuxfr.org/users/anaseto/journaux/un-print-1-3a-ca-nous-inspire-comment Title: Un print(1 + "3a"), ça nous inspire comment ? Authors: anaseto Date: 2017年04月01日T13:53:44+02:00 License: CC By-SA Tags: Score: 57 Cher Nal, Comme il faut bien un minimum de contenu sérieux aujourd’hui, histoire de faire diversion, je vais te parler de mes recherches sur la problématique `print(1 + "3a")`. Chaque langage/compilateur a sa façon de réagir sur le sujet, sa sensibilité, ses opinions ; des fois c’est juste une question de style, d’autres fois c’est des questions plus profondes qui émergent ! Voici donc les fruits de ces recherches. # Veux‐tu faire un print(1 + "3a"), s’il te plaît ? ## Ceux qui te rejettent à l’exécution parce que Num + String, quoi Ruby 1.8, c’est le point de vue coercition de types : ``` $ ruby18 -e 'puts 1 + "3a"' -e:1:in `+': String can't be coerced into Fixnum (TypeError) from -e:1 ``` Avec Python, on a droit à la perspective de la surcharge d’opérateur : ``` $ python -c 'print(1 + "3a")' Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str' ``` Pour Racket, c’est est une question bureaucratique de contrat non respecté ! ``` $ racket -e '(printf "~s\n" (+ 1 "3a"))' +: contract violation expected: number? given: "3a" argument position: 2nd other arguments...: 1 ``` Guile, avare en paroles, se plaint d’un point de vue typage, tout en pointant le vilain "3a" du doigt cependant : ``` $ guile -c '(display (+ 1 "3a"))' ERROR: In procedure +: ERROR: Wrong type: "3a" ``` Avec Common Lisp (sbcl), on a droit à des hurlements, on a fait une erreur **simple** de typage ! Et les remontrances n’en finissent pas... ``` $ sbcl --noinform --non-interactive --eval '(print (+ 1 "3a"))' Unhandled SIMPLE-TYPE-ERROR: Argument Y is not a NUMBER: "3a" Backtrace for: # 0: ((LAMBDA NIL :IN SB-DEBUG::FUNCALL-WITH-DEBUG-IO-SYNTAX)) 1: (SB-IMPL::CALL-WITH-SANE-IO-SYNTAX #) 2: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #) 3: (PRINT-BACKTRACE :STREAM # :START 0 :FROM :INTERRUPTED-FRAME :COUNT NIL :PRINT-THREAD T :PRINT-FRAME-SOURCE NIL :METHOD-FRAME-STYLE NIL) 4: (SB-DEBUG::DEBUGGER-DISABLED-HOOK # #) 5: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #) 6: (INVOKE-DEBUGGER #) 7: (ERROR SIMPLE-TYPE-ERROR :DATUM "3a" :EXPECTED-TYPE NUMBER :FORMAT-CONTROL "~@" :FORMAT-ARGUMENTS (SB-KERNEL::Y NUMBER "3a")) 8: (SB-KERNEL:TWO-ARG-+ 1 "3a") 9: (+ 1 "3a") 10: (SB-INT:SIMPLE-EVAL-IN-LEXENV (+ 1 "3a") #) 11: (SB-INT:SIMPLE-EVAL-IN-LEXENV (PRINT (+ 1 "3a")) #) 12: (EVAL (PRINT (+ 1 "3a"))) 13: (SB-IMPL::PROCESS-EVAL/LOAD-OPTIONS ((:EVAL . "(print (+ 1 \"3a\"))") (:QUIT))) 14: (SB-IMPL::TOPLEVEL-INIT) 15: ((FLET #:WITHOUT-INTERRUPTS-BODY-83 :IN SAVE-LISP-AND-DIE)) 16: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE)) unhandled condition in --disable-debugger mode, quitting ``` _jq_ nous dit que ce qu’on lui demande est tout simplement impossible : ``` $ echo {} | jq '1 + "3a"' jq: error (at :1): number (1) and string ("3a") cannot be added ``` Pour K (kona), c’est une erreur de type pour `+`, mais on n’en saura pas plus. ``` $ k K Console - Enter \ for help 1 + "3a" type error 1 + "3a" ^ ``` J voit là un problème de domaine et nous rajoute des espaces quelque part là où ça coince : ``` $ jc 1 + '3a' |domain error | 1 +'3a' ``` ## Ceux qui te rejettent à l’exécution, mais parce que « a » dans "3a" Perl 6 voudrait bien essayer de nous faire plaisir, mais avec le « a » après le « 3 », c’est au‐dessus de ces capacités et il nous l’explique avec Unicode à l’appui : ``` $ perl6 -e 'say 1 + "3a"' Cannot convert string to number: trailing characters after number in '3⏏a' (indicated by ⏏) in block at -e line 1 Actually thrown at: in block at -e line 1 ``` TCL ne peut pas non plus, mais fait preuve d’un style plus *stacktrace*, en nous montrant petit à petit le code de la commande englobante : ``` $ cat main.tcl puts [expr 1+{3a}] $ tclsh8.5 main.tcl can't use non-numeric string as operand of "+" while executing "expr 1+{3a}" invoked from within "puts [expr 1+{3a}]" (file "main.tcl" line 1) ``` Lua 5.2 essaie aussi, mais n’y arrive pas. Un peu plus sérieux dans le ton : ``` $ lua52 -e 'print(1 + "3a")' lua52: (command line):1: attempt to perform arithmetic on a string value stack traceback: (command line):1: in main chunk [C]: in ? ``` Avec le Shell, c’est expéditif : ``` $ expr 1 + "3a" expr: non-numeric argument ``` ## Ceux qui essaient de te comprendre Perl 5 sent bien que c’est louche et te le fait savoir, mais se débrouille pour trouver 4 à la fin. ``` $ perl -wE 'say 1 + "3a"' Argument "3a" isn't numeric in addition (+) at -e line 1. 4 ``` AWK (BWK awk), trop fort, arrive à faire le calcul sans problèmes : ``` $ awk 'END{print 1 + "3a"}' /dev/null 4 ``` JavaScript (node), rebelle, fait son original : ``` $ node -e 'console.log(1 + "3a")' 13a ``` C n’essaye pas vraiment de comprendre ce que tu voulais faire, mais ne veut pas trop te mettre la pression non plus : ``` $ cat main.c #include int main(void) { printf("%d", 1 + "3a"); return 0; } $ gcc -Wall main.c main.c: In function 'main': main.c:4: warning: format '%d' expects type 'int', but argument 2 has type 'char *' $ clang -Wall main.c main.c:4:15: warning: format specifies type 'int' but the argument has type 'char *' [-Wformat] printf("%d", 1 + "3a"); ~~ ^~~~~~~~ %s 1 warning generated. $ ./a.out 289409602 ``` ## Ceux qui te rejettent à la compilation Go, ça parle simplement typage, mais il pointe le vilain du doigt : ``` $ cat main.go package main import "fmt" func main() { fmt.Println(1 + "3a") } $ go run main.go # command-line-arguments ./main.go:6: cannot convert "3a" to type int ./main.go:6: invalid operation: 1 + "3a" (mismatched types int and string) ``` Avec OCaml, on parle typage, mais ça parle d’expressions, on sent l’esprit système de typage dans le style : ``` $ cat main.ml let () = print_int (2 + "3a") $ ocaml main.ml File "main.ml", line 1, characters 24-28: Error: This expression has type string but an expression was expected of type int ``` Pour Haskell (à _tryhaskell.org_), c’est une question de manque d’instance pour une *typeclass*, sa façon de parler surcharge d’opérateur : ``` λ print (1 + "3a") No instance for (Num [Char]) arising from a use of ‘+’ In the first argument of ‘print’, namely ‘(1 + "3a")’ In the expression: print (1 + "3a") ``` Rust parle *traits*, sa façon de parler surcharge, avec au passage quelques histoires de macros pour faire peur aux enfants. Et il nous dit qu’on peut avoir plus de détails en lui posant des questions au sujet d’E0277 (qui vaut le détour, ceci dit : un peu la même idée que _perldiag_, mais dans un style pédagogique). ``` $ cat main.rs fn main() { println!("{}", 1 + "3a"); } $ rustc main.rs main.rs:2:20: 2:28 error: the trait bound `_: std::ops::Add<&str>` is not satisfied [E0277] main.rs:2 println!("{}", 1 + "3a"); ^~~~~~~~ :2:25: 2:56 note: in this expansion of format_args! :3:1: 3:54 note: in this expansion of print! (defined in ) main.rs:2:5: 2:30 note: in this expansion of println! (defined in ) main.rs:2:20: 2:28 help: run `rustc --explain E0277` to see a detailed explanation main.rs:2:20: 2:28 help: the following implementations were found: main.rs:2:20: 2:28 help: main.rs:2:20: 2:28 help: <&'a f64 as std::ops::Add> main.rs:2:20: 2:28 help: > main.rs:2:20: 2:28 help: <&'b f64 as std::ops::Add<&'a f64>> main.rs:2:20: 2:28 help: and 58 others error: aborting due to previous error ``` Voilà, c’est tout. P.-S. : Pour ceux qui recherchent des choses à lire plus dans l’esprit du jour, il y a [_cet article_](https://www.tuxfamily.org/fr/news/2017040100) de chez _TuxFamily_ que j’ai trouvé pas mal.

AltStyle によって変換されたページ (->オリジナル) /